Mike Taulty's Weblog Ones & Zeros I read ... Blog Roll (Opml) MicrosoftMS UK Post Events Site NewsBBC News The Guardian The Observer A word for WinDbg Before I came to work at Microsoft I worked as a professional developer on the Microsoft platform and I used to work with the Visual Studio (6 latterly) debugger which I thought was a pretty cool debugger. When I joined Microsoft I found that a lot of people worked with WinDbg as their primary debugger and, for a while, I just did not get it as it seemed like an unnecessarily grungy tool for achieving things that Visual Studio could already do. However, over a period of time I came to see the light and I'm now of the view that WinDbg is about the best debugger I '
ve ever used (including those ones I used to work with on Unix platforms). WinDbg is just the most powerful debugger out there for user-mode debugging and I do not do any other kind of debugging J So, there is a lot of information out there already on WinDbg but I just wanted to try and highlight it here and provide a single-pager on it as it seems to be grossly overlooked as a debugger for managed code and, yet, it's capable of a whole tonne of stuff that no single other debugger can do for you right now. People are often put off WinDbg because of its interface and the vast array of commands so in this little series of postings I'll try and demystify a little bit and show how you can debug a Few Common Scenarios in Managed Code with It, Let's Just Get To The Point Where We can use window That you can do. Installation So, First Things First, Get Hold of A Copy Of Windbg Fr . Om here and install it If you want to follow along with this post then you can go and download it right now -. The install takes about 2 minutes once you've got the 10MB download down from the site The first thing you'll realise is how lightweight an installation WinDbg is and that (sometimes) means that you can install it into places that you'd never install a copy of Visual Studio or the Visual Studio remote debug set up. Indeed, often if you raise a support call With microsoft you'll get coured to install windbg and it's automated helper (the "autodumper"
) In order to get a crash dump of your application to send back to Microsoft. Before we get into debugging something I need to have a quick word or two about Symbols and Commands.Symbols The first issue that we need to address in order to progress is that of symbols. If you want to get decent stack traces and dumps of variable values and so on out of the debugger then you need symbols for the modules that you're debugging whether those modules are yours or someone else's and whether those modules are managed or unmanaged (although there's quite a lot more that you can do with managed code without symbols). Symbols are typically either private symbols (include variable information), retail symbols (function information but not variable information) or export symbols (generally not so useful for debugging purposes). If you're debugging with "export" symbols it's not usually enough to actually work out what's going on. for your own code you're responsible for building the symbol files (us ually .PDB program databases) by setting the right flags on the compiler or choosing the right configuration in a project (this is true for VC , VB6 and all the .NET languages). This will give you full private symbols. When the debugger ( and lots of other tools) want to find symbols they typically check the contents of an environment variable named _NT_SYMBOL_PATH which is used (just like PATH -. ie a list of folder separated by semi-colons) to find symbol files You can set _NT_SYMBOL_PATH prior TO Running Windbg or You Can Use The Debugger's OWN Symbol Path Settings To Find Symbol Files. Thase settings are controlled via the file->
Symbol File Path menu option or using the .sympath command. For other people's code you need to get symbols from them. For Microsoft code you're in luck because the symbols are available from a public symbol server on the internet. In order to make use of the symbol server you should set your symbol path to be something like; SRV * C: / MyLocalSymbols * http: //msdl.microsoft.com/download/symbols What this says is that the debugger should first check a local cache named C: / MyLocalSymbols and if symbols are not found there then go out to the Microsoft symbol server for symbols and, if found, download them and cache them in that folder Note that symbols are downloaded based upon name, version and checksum information from the. modules being debugged so the debugger usually knows if the symbols match the code properly If you wanted to combine this with a local location for your own code then you'd use something like; C:. / MyCodesSymbols; SRV * C: / MyLocalSymbols * http://msdl.microsoft.co m / download / symbols so that the debugger would check your folder first and would then proceed to look in the cache and finally to the symbol server for symbols. Commands A core set of commands would be as below. I rarely venture beyond these as I 'm not an advanced user of window gets me by. .hh. .hh - bring up the help file :-) the help file is fantastic so don't skip on it - everything's docutented in there .g - "Go ! "................................... ..
bp KERNEL32 CreateFileA (remember that most Windows functions have an ASCII and a Unicode variant so we have KERNEL32 CreateFileA and KERNEL32 CreateFileW!!) bl -!.. list all breakpoints Each breakpoint listed has a number in the list which you need for .. , BC (Number), BD (Number) - The Commists Beginning with Kd (Number), BD (Number), BD (Number), BD (Number) - The Stack for the Thread That The Stack for the Thread That The THE STAS Debugger is looking at. There a few variants so check out the help for those. The Simplest Variant That I use IS; KB 200 (200 is The maximum depth of stack trace That I'm looking for) DW, DB, DS, etc. The commands beginning with "d" show the contents of memory. One of the most common is "dt" which shows you the contents of memory laid out according to the specification of a type as long as the debugger can see the definition of A Type. SXE, SXD, SXI, SXN. THE Commands Beginning with "SET" SET the behaviour for what the debugger limited when an exception occurs A good example here would be; sxe 0xc0000005 which is saying "I want to break into the debugger if there's an access violation" lm - lists the modules loaded by the program and what kind of symbols are loaded for the.. modules. Note that export symbols are not really symbols at all but are really the debugger guessing which function you're in based upon the export table of the DLL. For COM servers in particular (which have only 4 exported functions or so) you ' LL OFTEN FIND YOURSELF APPEARING in DllRegisterServer if you only "). Good examples here where would be;
lm v (verbose mode) lm v mUSER * (verbose mode, matc any modules that begin with USER *) x -. Examine symbols This is very, very useful as it shows you the set of symbols loaded for particular modules A good example. ! here would be; x USER32 * (show me all the symbols loaded from the USER32 module) x USER32 Create * (show me all the symbols loaded from the USER32 module that begin with "Create") .cls - clear the screen!. You'll be needing this one .reload - this causes the symbol information to be reloaded for a particular module The most common form of this would be to do something like;!. .reload / f user32.dll Where the / f overrides the debugger's naturally lazy mode of working whereby it would not actually do the reload right there and then Normally, this is a useful parameter to use ~ -.. this is the tilde character and it lists all the threads in the process and shows their status ................... .. The single most common one is probably to combine it with a "stack" command to do something like;. ~ * Kb 200 which will show you the stack frames for all the threads in the process ~ N s - this changes the debugger's focus to aNother thread. for example;
~ 7 s Will switch the debugger so that it's focused on thread 7. Note that 7 here is the debugger's thread number rather than the real thread ID and it comes from the list given by the ~ command. Along with the core set of commands, .. WinDbg is capable of loading up debugger extensions to extend the core functionality of the debugger These are "bang commands" in that they begin with an exclamation mark You can manipulate the extensions that the debugger has loaded using the following commands; .chain - this shows the extensions that the debugger has loaded.load - this loads an extension DLL (eg .load SOS.DLL) .unload - unloads an extension DLL.unloadall.setdll -. this sets the "default" extension DLL A quick word about . .setdll and how command processing works here If you have an extension named UEXT.DLL which contains a command named help (and most extensions will have a help command) then you can run that command using;! UEXT.help and that works fine IF you find yourself Using Uext more than any other extension then you can use; .setdll UEXT.DLL To make UEXT.DLL the default extension and then you can just use;! help And that will now default to mean UEXT.help because of the default extension setting!. A First Debugging Session So, let's finish up this post with a quick debugging session and next time around I'll talk about debugging managed code rather than just any old process. Run up WinDbg and also run up a copy of NotePad. Within WinDbg attach To the notepad process this you just ran by each each each each either using the file->
Attach to Process menu or the F6 shortcut. This will give you a dialog where you can select a process. Note that the "Non Invasive" option would allow you to detach from the debugged process without killing it (if you're on Windows XP or 2003) but it limits the commands that you can use so leave it unchecked. Do not worry about the workspace information, let it go. The debugger should present some diagnostics as it loads information and will then stop with the command prompt. The debuggee (notePad) is now halted. Let's take a look around. Firstly, let's look at the modules that are loaded by notepad. Execute a "lm v" to list all the modules and follow it up with a simple "lm". On My System I get this; 0: 001>
lmstart end module name01000000 01014000 notepad (no symbols) 4ce00000 4cf02000 COMCTL32 (export symbols) C: /WINDOWS/WinSxS/x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.2149_x-ww_a84b1f06/COMCTL32.dll5ad70000 5ada7000 uxtheme (export symbols) C: / WINDOWS / system32 / uxtheme.dll605d0000 605d9000 mslbui (export symbols) C: /WINDOWS/system32/mslbui.dll61220000 61232000 MSH_ZWF (export symbols) C: / Program Files / Microsoft Hardware / Mouse / MSH_ZWF.dll73000000 73026000 WINSPOOL (export symbols) C : /WINDOWS/system32/WINSPOOL.DRV74720000 7476b000 MSCTF (export symbols) C: /WINDOWS/system32/MSCTF.dll763b0000 763f9000 comdlg32 (export symbols) C: /WINDOWS/system32/comdlg32.dll77120000 771ac000 OLEAUT32 (export symbols) C: / Windows / System32 / Oleaut32.dll771b0000 779C4000 Shell32 (Export Symbols) C: /Windows/system32/Shell32.dll779d0000 77A46000 SHLWAPI (Export Symbo ls) C: /WINDOWS/system32/SHLWAPI.dll77a50000 77b8d000 ole32 (export symbols) C: /WINDOWS/system32/ole32.dll77c10000 77c68000 msvcrt (export symbols) C: /WINDOWS/system32/msvcrt.dll77cc0000 77d5b000 ADVAPI32 (export symbols) C: /WINDOWS/system32/ADVAPI32.dll77d60000 77df1000 USER32 (export symbols) C: /WINDOWS/system32/USER32.dll77e00000 77e93000 RPCRT4 (export symbols) C: /WINDOWS/system32/RPCRT4.dll77ea0000 77ee5000 GDI32 (export symbols) C: / Windows/system32/gdi32.dll7c800000 7C8F2000 Kernel32 (Export Symbols) c: /windows/system32/kernel32.dll7c900000 7C9AE000 NTDLL (Export Symbols) C:
/WINDOWS/system32/ntdll.dll Let's get some symbols because we can not really work with export symbols. Set up your symbol path (either through the File-> Symbol Path menu or through the .sympath command) so look something like this ; SRV * e: / LocalSymbolCache * http: //msdl.microsoft.com/download/symbols Reload symbols for the loaded modules by using the ".reload / f" command - this may well take a little time as the symbols for all those modules that NotePad loaded trickle down from the internet to your local cache. This gets better with time as you pull down common symbols from the net. After the reload completes do another lm and make sure you got some symbols. My session now gives me ; 0: 001>
lmstart end module name01000000 01014000 notepad (pdb symbols) e: /LocalSymbols/notepad.pdb/15800B8231AF4FDE85232D42B267D3E51/notepad.pdb4ce00000 4cf02000 COMCTL32 (pdb symbols) e: /LocalSymbols/MicrosoftWindowsCommon-Controls-6.0.2600.2149-comctl32.pdb/4133208CAF9A4B93982A1F873FBC79261/MicrosoftWindowsCommon -Controls-6.0.2600.2149-comctl32.pdb5ad70000 5ada7000 uxtheme (pdb symbols) e: /LocalSymbols/uxtheme.pdb/3A4D37B97BA34837AC589BDB15CC265D2/uxtheme.pdb605d0000 605d9000 mslbui (pdb symbols) e: /LocalSymbols/MSLBUI.pdb/ED5CCEFBD83C4F929AAB9A1029C54DDD1/MSLBUI.pdb61220000 61232000 MSH_ZWF (export symbols) C: / Program Files / Microsoft Hardware / Mouse / MSH_ZWF.dll73000000 73026000 WINSPOOL (pdb symbols) e: /LocalSymbols/winspool.pdb/20EE1501116B4C4180ABE40B209DEC962/winspool.pdb74720000 7476b000 MSCTF (pdb symbols) e: / localSymbols / msctf.pdb/f8f1c6e0e1cc4d1cb4936c12a6a6d4c92/msctf.pdb763b0000 763f9000 comdlg32 (pdb symbols) e: /LocalSymbols/comdlg32.pdb/2BC57F8BE63A429FB4B439EA2854387A2/comdlg32.pdb77120000 771ac000 OLEAUT32 (pdb symbols) e: /LocalSymbols/oleaut32.pdb/96D8A9A6CB704201A365F345B2A9F72D2/oleaut32.pdb771b0000 779c4000 SHELL32 (pdb symbols) e: / LocalSymbols /shell32.pdb/FE0DC899DD78422AB29561FE8255E1C92/shell32.pdb779d0000 77a46000 SHLWAPI (pdb symbols) e: /LocalSymbols/shlwapi.pdb/231AB6F0A19F4DBB9837440BCC167BEC2/shlwapi.pdb77a50000 77b8d000 ole32 (pdb symbols) e: /LocalSymbols/ole32.pdb/656B303C367B4E679CA249E32CE572D92/ole32.pdb77c10000 77C68000 MSVCRT (PDB Symbols) E:
/LocalSymbols/msvcrt.pdb/8E17C9B9A55C4118A7D35025C5BE51871/msvcrt.pdb77cc0000 77d5b000 ADVAPI32 (pdb symbols) e: /LocalSymbols/advapi32.pdb/57E2A801C610451AA66B7CD94F0910F72/advapi32.pdb77d60000 77df1000 USER32 (pdb symbols) e: /LocalSymbols/user32.pdb/35948255FAC04CA99F5CF61959B45DC42/user32 .pdb77e00000 77e93000 RPCRT4 (pdb symbols) e: /LocalSymbols/rpcrt4.pdb/79C7047CB77B435DB01EB365C3AF17152/rpcrt4.pdb77ea0000 77ee5000 GDI32 (pdb symbols) e: /LocalSymbols/gdi32.pdb/E7D5B033EFE5466E97DB048BE4C88FA62/gdi32.pdb7c800000 7c8f2000 kernel32 (pdb symbols) e: /LocalSymbols/kernel32.pdb/5091FA1742544F2EA3D425642634F78E2/kernel32.pdb7c900000 7c9ae000 ntdll (pdb symbols) e:. /LocalSymbols/ntdll.pdb/7B2A2EF0E63F4848A8D309E84E47322C2/ntdll.pdb So, that's modules and symbols Let's see if we can set some breakpoints Suppose that. I want to hit a Breakpoint Anytime That NotEpad Opens Up A File. Let's do this. Firstly, take a look at symbols in KERNEL32 to see if we can find the CreateFile function that NotePad uses. Issue a "x KERNEL32! CreateF *" and see what results we get back you should find the ASCII CreateFileA and the Unicode CreateFileW functions in there. Set a breakpoint on a function. Issue a "bp kernel32! CreateFileW" to set a breakpoint on that function. Issue a "GO" command "g" to continue the debuggee running. Note that when the debuggee is running you can always get back To the debugger by Issuing a Ctrl
BREAK to the debugger window when it will try and halt the debuggee for you and drop you back to the command prompt. Open a file with notepad. You'll spot NotePad loading some more modules in order to do this operation and get that dialog onto . the screen your breakpoint will more than likely hit before the file dialog comes up Check-out where you are with your breakpoint - ie what the stack frame looks like Issue a "kb 200" command you should get results as below...; 0:!!!! 000> kbChildEBP RetAddr Args to Child 0006be18 76671b2a 76671b74 00000020 00000003 kernel32 CreateFileW0006be94 766724e2 000a6b40 0006bf4c 00000000 cscui IsCSCEnabled 0x380006bea8 77a68b49 000a7084 77a51a60 0006bf44 cscui DllGetClassObject 0x720006bec4 77a80f5e 000a7084 77a51a60 0006bf44 ole32 CClassCache :: CDllPathEntry :: DllGetClassObject 0x2d0006bedc 77A80E9A 0006BEF0 77A51A60 0006BF44 OLE32! CCLASCACHE :: CDLFNPTRMONIKER :: Bindtoobjectnoswitch 0x1f0006bf08 77a81cc6 0006bf4c 00000000 0006C540 OLE32! CCLAS !!! SCache :: GetClassObject 0x380006bf84 77a806aa 77b76ca4 00000000 0006c540 ole32 CServerContextActivator :: CreateInstance 0x1060006bfc4 77a81e19 0006c540 00000000 0006ca8c ole32 ActivationPropertiesIn :: DelegateCreateInstance 0xf70006c018 77a81d90 77b76ca8 00000000 0006c540 ole32 CApartmentActivator :: CreateInstance 0x1100006c038 77a8101e 77b76ca8 00000001 00000000 ole32 CProcessActivator!: :! CCICallback 0x6d0006c058 77a80fd5 77b76ca0 0006c39c 00000000 ole32 CProcessActivator :: AttemptActivation 0x2c0006c090 77a81e7a 77b76ca0 0006c39c 00000000 ole32 CProcessActivator :: ActivateByContext 0x420006c0b8 77a806aa 77b76ca0 00000000 0006c540 ole32 CProcessActivator :: CreateInstance !!
0x490006c0f8 77a81bc4 0006c540 00000000 0006ca8c ole32! ActivationPropertiesIn :: DelegateCreateInstance 0xf70006c348 77a806aa 77b765d4 00000000 0006c540 ole32! CClientContextActivator :: CreateInstance 0x8f0006c388 77a805dc 0006c540 00000000 0006ca8c ole32! ActivationPropertiesIn :: DelegateCreateInstance 0xf70006cb38 77a64eb1 000a2f08 00000000 00000001 ole32! ICoCreateInstanceEx 0x3c90006cb60 77a64e80 000a2f08 00000000 00000001 ole32! CComActivator :: DoCreateInstance 0x280006cb84 77a65102 000a2f08 00000000 00000001 ole32! CoCreateInstanceEx 0x1e0006cbb4 779d69a5 000a2f08 00000000 00000001 ole32! CoCreateInstance 0x37 So, we can see the direct call-stack that led to our call to CreateFileW. If we had full symbols for these modules we could use a KP rather than a KB command and we'd get a list of parameters to the functions. As it is with what we have here we'd need to resort to disassembly to get the parameter information here and it's beyond This Posting. Continue the debuggee by Issuing a "g" COM mand and continue issuing "g" commands until NotePad finally puts its dialog on the screen - note how many times we hit this function here J If you're interested, issue a few KB's on some of these call chains and see what exactly it is That Notepad is doing. Break the debuggee by Hitting Ctrl Break on the window a "Command to Get A Picture of the Threads in the process. in My seference I get 3 as bellow; 0: 002>
~ 0 ID: 9BC.B58 SUSPEND: 1 TEB: 7FFDF000 UNFROZEN 1 ID: 9BC.8A4 SUSPEND: 1 TEB: 7FFDE000 Unfrozen. 2 ID: 9bc.d4 suspend: 1 TEB: 7FFDD000 Unfrozen Note That Display Indicates That the debugger is Focused On Thread "2" Which is real os thread 8A4 in Process 9bc (All Hex I'm Afraid). Check Out Where All The Threads Are By Issuing A "~ * KB 200". You might not get anything Too Exciting Here But it's illustrative of how to use the technique. Finally, close off this session by having a look at some extension commands. List the set of extensions that you've got by issuing the ".chain" command. Have a look at the commands available In There Extensions by Issuing:! EXTS.HELP,! UEXT.HELP,! NTDSEXTS.HELP,! EXT.HELP AND SEE What Commands Are Available To You. Try An Extension Command. for Example, "! Exts.cs" Will Display All the critical sections what the process has and their status as to whather the isy deficer not. this can be used nd the debugging session with a "q" command. That's it. I'll post again in the near future around how you can build on what I've just walked through here in order to debug managed code with WinDbg and take advantage of features Uttice Elsewhere. Posted on Tuesday, August 03, 2004 3:54 Ammike Taulty's Weblogposted @ 8/3/2004 5:28 AM
# Windbg Review Robert Hurlbut's .NET BlogPosted @ 8/3/2004 8:05 AM
# Windbg is your friend Jed's blogposted @ 8/3/2004 9:09 AM
# Re: a word for windbg hakan berg hbe@master.nuposted @ 10/11/2004 4:21 AMEXCETED ARTICLE. I Love Such Clear Step-by-Step How-to-Do INSTRUCTIONS. THIS WILL Really Help Me In My PROGAM Web.
Thank you!
# Re: a word for windbg davidposted @ 12/31/2004 1:14 Amit is Great! Thank you very much * _ * # Re: a word for windbg yiposted @ 1/14/2005 7:09 PMVERY Good Article! # Re: a Word for Windbg Deepuposted @ 2/21/2005 6:10 Ama Crisp Article, with a smart example. THANK you very much !! # a word for windbg smartwombat blogposted @ 2/22/2005 8 : 40 am
# John Robbins on .NET V2.0 and Sos.dll Mike Taulty's Weblogposted @ 3/1/2005 2:39 PM
# RE: A Word for Windbg Yujiposted @ 3/3/2005 3:43 Amthis Is Very Good Article. Thanks !! # Re: a Word for Windbg Rene PallyPosted @ 3/9/2005 3:11 PMI Have Some Problems Trying To 2003 specially configuring aedebug run Windbg on Windows Ok, the Windbg catch the crashed process but, when windbg starts with crashed process windbg console freezes Any Ideas happens on Windows 2003 SP1 # Excellent .NET debugging tool Blog:..? Martin ParryPosted @ 3 / 21/2005 3:34 AM
# A word for Windbg Smartwombat BlogPosted @ 3/28/2005 2:07 AM Introduction to windbg for both managed and unmanaged debugging A word for WinDbg - short introduction ... # Would it work with VB6 SamionPosted @ 4/4/2005 11 : 02 Amassuming I Have a symbols file for an application. # Re: a word for windbg mikeposted @ 4/4/2005 11:54 Amyou Can Debug VB6 Code with Windbg, The Sos Stuff Is Just For Managed (.NET) Code But Regular VB6 Code with Symbugs and with wels Optimizations Debugs OK in Windbg. # Re: a word for windbg jasonposted @ 4/10/2005 11:51 PMANY Ideas for the following output?
"POISONED_TB: NT! MMPOISONEDTB IS NON-ZERO"
2. "MRXSMB! BowSergetBackupListResponse 7A"
3. "The Machine Has Been Manipulated Using The Kernel Debugger."
Thanks Jason # Re: a Word for WINDBG ROBPOSTED @ 6/16/2005 5:48 Amgood Article.i AM INTERESTEDION THE DUMP Analysis. What do you do ife not a Microsoft File and does not a microsoft file and does not have An Associated Symbol File? Is IT Possible To Make Your Own Symbol File? # Re: a Word for Windbg Mikeposted @ 6/16/2005 5:55 Amhi,
I'm not quite sure what you're looking for here. If you've got code in a crashing process that's not from MS then you can still have symbols (usually .pdb files) for that code but those symbol files are part of the build process so you'd normally get them from the vendor of that software or as part of building the software yourself # re:. A word for WinDbg RobPosted @ 6/16/2005 12:25 PMI have gone through this page ten times Already. You Did A Great Job.
My problem deals with a Novell client file (SRVLOC.SYS) which causes my Terminal servers to randomly crash. When I run WinDbg to analyze the dump file, it can not find the proper symbol file for srvloc.sys, but it does indicate This is indeed the problem. The srvloc.pdb file is nowhere to be bound.
I am Going to Keep Running THROUGH YOUR NOTEPAD EXAMPLE ABOVE IN ATTEMPT To Better Learn Windbg. You Have Definitely Opened My Eyes To The Power Of Windbg. Thank you
# Re: a word for windbg timposted @ 3/3/2006 11:17 Ampersonally, i love logkd from system internals. Uses Windbg for Live Kernel Debugging.