views:

3960

answers:

19

I have come to realize that Windbg is a very powerful debugger for the Windows platform & I learn something new about it once in a while. Can fellow Windbg users share some of their mad skills?

ps: I am not looking for a nifty command, those can be found in the documentation. How about sharing tips on doing something that one couldn't otherwise imagine could be done with windbg? e.g. Some way to generate statistics about memory allocations when a process is run under windbg.

+9  A: 
bk1e
Without a doubt the best book to learn how to use WinDBG.
Sacha
+15  A: 

My favorite tip is to follow Tess Ferrandez' blogging about Windows and .NET debugging. Start with http://blogs.msdn.com/tess/archive/2007/04/19/windbg-scripts-and-tools.aspx

bzlm
+14  A: 
Kris Kumler
+1  A: 

I've just read this blog post on a very handy command called ".cmdtree". This one doesn't quite fit your question but I thought it's very cool and should mention it.

Daisuke Shimamoto
Oh damn just got beaten......
Daisuke Shimamoto
+6  A: 

Following command:

dpp esp Range

comes very handy when looking on stack for C++ objects with vtables, especially when working with release builds when quite a few things get optimized away.
Being able to load an arbitrary PE file as dump is neat:

windbg -z mylib.dll

Query GetLastError() with:

!gle
!error error_number

helps to decode common error codes.

dpp - good one, thanks.
+3  A: 
Kapil Kapre
Wow. kM is pretty fabulous!
Aaron
+2  A: 

My favorite is Getting an exception call stack from the catch block by Slava Oks (Microsoft C++ specific).

Constantin
+1  A: 

Do not use Windbg .heap -stat command, it will sometimes give you incorrect output.
Instead use DebugDiags memory reporting.
Having the currect numbers you can then use windbg's .heap -flt ... command.

Tal
+2  A: 

I really really like PowerDbg, a powershell library which makes windbg scripting easy, er, no, easier, well, make that "less tear wrenching".

There are some example scripts written for it, my favorite being one that display the most cpu-hogging threads or the worst GC handles leakers.

wow, thats what I've been looking for, thanks!
+1  A: 

I like to use advanced breakpoint commands, such as using breakpoints to create new one-shot breakpoints.

Brian
+3  A: 

The "tip" I use most often is one that will save you from having to touch that pesky mouse so often: Alt-1

Alt-1 will place focus into the command window so that you can actually type a command and so that up-arrow actually scrolls through command history. However, it doesn't work if your focus is already in the scrollable command history.

Peeve: why the heck are key presses ignored while the focus is in a source window? It's not like you can edit the source code from inside windbg. Alt-1 to the rescue.

JeffJ
+7  A: 

To investigate a memory leak in a crash dump (since I prefer by far UMDH for live processes).
The strategy is that objects are all allocated with the same size.

  • Feed the !heap -h 0 command to WinDbg command line version cdb.exe (for greater speed) to get all heap allocations:
"C:\Program Files\Debugging Tools for Windows\cdb.exe" -c "!heap -h 0;q" -z [DumpPath] > DumpHeapEntries.log
  • Use cygwin to grep the list of allocations, grouping them by size:
grep "busy ([[:alnum:]]\+)" DumpHeapEntries.log \  
| gawk '{ str = $8; gsub(/\(|\)/, "", str); print "0x" str " 0x" $4 }' \
| sort \  
| uniq -c \  
| gawk '{ printf "%10.2f %10d %10d ( %s = %d )\n", $1*strtonum($3)/1024, $1, strtonum($3), $2, strtonum($2) }' \  
| sort > DumpHeapEntriesStats.log
  • You get a table that look like this
   8489.52        707      12296 ( 0x3000 = 12288 )  
  11894.28       5924       2056 ( 0x800 = 2048 )  
  13222.66     846250         16 ( 0x2 = 2 )  
  14120.41     602471         24 ( 0x2 = 2 )  
  31539.30    2018515         16 ( 0x1 = 1 )  
  38902.01    1659819         24 ( 0x1 = 1 )  
  40856.38        817      51208 ( 0xc800 = 51200 )  
1196684.53   25529270         48 ( 0x24 = 36 )
  • Then if your objects have vtables, just use the dds command to seek some of the heap allocations in DumpHeapEntriesStats.log to know the type of the objects that are taking all the memory.
0:075> dds 3be7f7e8  
3be7f7e8  00020006  
3be7f7ec  090c01e7  
3be7f7f0  0b40fe94 SomeDll!TSomeType::`vftable'  
3be7f7f4  00000000  
3be7f7f8  00000000

Thats cheezy but it works :)

total
This is epic man, thanks a ton for posting it.
pj4533
I've been trying to implement this myself, but I am confused. How do you get the '3be7f7e8' address to give dds? Is that just the first column in the !heap output? Meaning you search your original log for the allocation of that size, get the address, then do a dds on it?
pj4533
Exactly, in the log you get a line that looks like this for every memory allocation: "3be7f7e8: 00038 . 00040 [107] - busy (24)".24 is the value we search for here, got from the table above telling us that most of the memory is used by 0x24 bytes allocations.I then use cygwin's less to search DumpHeapEntriesStats.log for these lines using the command "/(24)", pick some of the matched addresses and dds them in cdb/WinDBG.
total
+3  A: 

One word (well, ok, three) : DML, i.e. Debugger Markup Language.

This is a fairly recent addition to Windbg and it's not documented in the help file. There is however some documentation in "dml.doc" in the installation directory for the Debugging Tools for Windows.

Basically, this is an html like syntax you can add to your debugger scripts for formatting and, more importantly, linking. You can use links to call other scripts, or even the same script.

My day-to-day work involves maintenance on a meta-modeler that provides generic objects and relationship between objects for a large piece of C++ software. At first, to ease debugging, I had written a simple dump script that extracts relevant information from these objects.

Now, with DML, I've been able to add links to the output, allowing the same script to be called again on related objects. This allows for much faster exploration of a model.

Here's a simplified example. Assume the object under introspection has a relationship called "reference" to another object. r @$t0 = $arg1 $$ arg1 is the adress of an object to examine

$$ dump some info from $t0

$$ allow the user to examine our reference
aS /x myref @@(&((<C++ type of the reference>*)@$t0)->reference )
.block { .printf /D "<link cmd=\"$$>a< <full path to this script> ${myref}\">dump Ref</link> " }

Obviously this a pretty canned example but this stuff is really invaluable for me. Instead of hunting around in very complex objects for the right data members (which usually took up to a minute and various casting and dereferencing trickery), everything is automated in one click !

Bethor
+1  A: 

Someone above mentioned the command window and "Alt+1" to focus on the command input window. Anyone finds it's difficult to scroll the command output window without using mouse?

Well, I have recently used AutoHotKey to scroll the command output window using keyboard and without leaving the command input window.

; WM_VSCROLL = 0x115 (277)
ScrollUp(control="")
{
    SendMessage, 277, 0, 0, %control%, A
}

ScrollDown(control="")
{
    SendMessage, 277, 1, 0, %control%, A
}

ScrollPageUp(control="")
{
    SendMessage, 277, 2, 0, %control%, A
}

ScrollPageDown(control="")
{
    SendMessage, 277, 3, 0, %control%, A
}

ScrollToTop(control="")
{
    SendMessage, 277, 6, 0, %control%, A
}

ScrollToBottom(control="")
{   
    SendMessage, 277, 7, 0, %control%, A
}

#IfWinActive, ahk_class WinDbgFrameClass
    ; for windbg, when the child window is attached to the main window
    !UP::ScrollUp("RichEdit50W1")
    ^k::ScrollUp("RichEdit50W1")
    !DOWN::ScrollDown("RichEdit50W1")
    ^j::ScrollDown("RichEdit50W1")
    !PGDN::ScrollPageDown("RichEdit50W1")
    !PGUP::ScrollPageUp("RichEdit50W1")
    !HOME::ScrollToTop("RichEdit50W1")
    !END::ScrollToBottom("RichEdit50W1")
#IfWinActive, ahk_class WinBaseClass
    ; also for windbg, when the child window is a separate window
    !UP::ScrollUp("RichEdit50W1")
    !DOWN::ScrollDown("RichEdit50W1")
    !PGDN::ScrollPageDown("RichEdit50W1")
    !PGUP::ScrollPageUp("RichEdit50W1")
    !HOME::ScrollToTop("RichEdit50W1")
    !END::ScrollToBottom("RichEdit50W1")

After this script is run, you can use Alt+up/down to scroll one line of the command output window, Alt+Pgdn/Pgup to scroll one screen.

Note: it seems different versions of windbg will have different class names for the window and controls, so you might want to use window spy tool provided by AutoHotkey to find the actual class names first.

wangzq
+1  A: 

.prefer_dml 1

This modifies many of the built in commands (i.e. lm) to display DML output which allows you to click links instead of running commands. Pretty handy...

  • Jason
JasonE
+1  A: 

For command & straightforward (static or automatable) routines where debugger is used, it is very cool to be able to put all the debugger commands to run through in a text command file and run that as input through kd.exe or cdb.exe, callable via a batch script, etc.

Run that whenever you need to do this same old routine, w/o having to fire up WinDbg and do things manually. Too bad this doesn't work when you aren't sure what you are looking for, or some command parameters need manual analysis to find/get.

David
+1  A: 

Script to load sos based on the .NET framework version (v2.0 / v4.0)

!for_each_module .if(($sicmp( "@#ModuleName" , "mscorwks") = 0) ) 
{.loadby sos mscorwks} .elsif ($sicmp( "@#ModuleName" , "clr") = 0) 
{.loadby sos clr}
Naveen
A: 

http://kdar.codeplex.com/

Alexander
Why exactly it is your favorite windbg tip/trick?
Constantin