What is your favourite Windbg tip/trick? [closed]

天大地大妈咪最大 提交于 2019-12-04 07:18:03

问题


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.


回答1:


My favorite is the command .cmdtree <file> (undocumented, but referenced in previous release notes). This can assist in bringing up another window (that can be docked) to display helpful or commonly used commands. This can help make the user much more productive using the tool.

Initially talked about here, with an example for the <file> parameter: http://blogs.msdn.com/debuggingtoolbox/archive/2008/09/17/special-command-execute-commands-from-a-customized-user-interface-with-cmdtree.aspx

Example: alt text http://blogs.msdn.com/photos/debuggingtoolbox/images/8954736/original.aspx




回答2:


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

  • Feed the !heap -h 0 command to WinDbg's 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 looks like this, for example, telling us that 25529270 allocations of 0x24 bytes take nearly 1.2 GB of memory.
   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 dps command to seek some of the 0x24 bytes heap allocations in DumpHeapEntries.log to know the type of the objects that are taking all the memory.
0:075> dps 3be7f7e8
3be7f7e8  00020006
3be7f7ec  090c01e7
3be7f7f0  0b40fe94 SomeDll!SomeType::`vftable'
3be7f7f4  00000000
3be7f7f8  00000000

It's cheesy but it works :)




回答3:


The following command comes very handy when looking on the stack for C++ objects with vtables, especially when working with release builds when quite a few things get optimized away.

dpp esp Range


Being able to load an arbitrary PE file as dump is neat:

windbg -z mylib.dll


Query GetLastError() with:

!gle


This helps to decode common error codes:

!error error_number



回答4:


Almost 60% of the commands I use everyday..

dv /i /t
?? this
kM (kinda undocumented) generates links to frames
.frame x
!analyze -v
!lmi
~

Explanation

  1. dv /i /t [doc]
    1. dv - display names and values of local variables in the current scope
    2. /i - specify the kind of variable: local, global, parameter, function, or unknown
    3. /t - display data type of variables
  2. ?? this [doc]
    1. ?? - evaluate C++ expression
    2. this - C++ this pointer
  3. kM [doc]
    1. k - display stack back trace
    2. M - DML mode. Frame numbers are hyperlinks to the particular frame. For more info about kM refer to http://windbg.info/doc/1-common-cmds.html
  4. .frame x [doc]
    1. Switch to frame number x. 0 being the frame at top of stack, 1 being frame 1 below the 0th frame, and so on.
    2. To display local variables from another frame on the stack, first switch to that frame - .frame x, then use dv /i /t. By default d will show info from top frame.
  5. !analyze -v [doc1] [doc2 - Using the !analyze Extension]
    1. !analyze - analyze extension. Display information about the current exception or bug check. Note that to run an extension we prefix !.
    2. -v - verbose output
  6. !lmi [doc]
    1. !lmi - lmi extension. Display detailed information about a module.
  7. ~ [doc]
    1. ~ - Displays status for the specified thread or for all threads in the current process.



回答5:


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.




回答6:


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 address of an object to examine

$$ dump some information 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!




回答7:


  • .prefer_dml 1

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

  • .reload /f /o file.dll (the /o will overwrite the current copy of the symbol you have)

  • .enable_unicode 1 //Switches the debugger to default to Unicode for strings since all the Windows components use Unicode internally, this is pretty handy.

  • .ignore_missing_pages 1 //If you do a lot of kernel dump analysis, you will see a lot of errors regarding memory being paged out. This command will tell the debugger to stop throwing this warning.

alias alias alias...

Save yourself some time in the debugger. Here are some of mine:

aS !p !process;
aS !t !thread;
aS .f .frame;
aS .p .process /p /r
aS .t .thread /p /r
aS dv dv /V /i /t //make dv do your favorite options by default
aS f !process 0 0 //f for find, e.g. f explorer.exe



回答8:


Another answer mentioned the command window and Alt + 1 to focus on the command input window. Does anyone find it difficult to scroll the command output window without using the 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 the window spy tool provided by AutoHotkey to find the actual class names first.




回答9:


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}



回答10:


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




回答11:


Do not use WinDbg's .heap -stat command. It will sometimes give you incorrect output. Instead, use DebugDiags memory reporting.

Having the correct numbers, you can then use WinDbg's .heap -flt ... command.




回答12:


For command & straightforward (static or automatable) routines where the 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, without 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.




回答13:


Platform-independent dump string for managed code which will work for x86/x64:

j $ptrsize = 8 'aS !ds .printf "%mu \n", c+';'aS !ds .printf "%mu \n", 10+'

Here is a sample usage:

0:000> !ds 00000000023620b8

MaxConcurrentInstances


来源:https://stackoverflow.com/questions/127564/what-is-your-favourite-windbg-tip-trick

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!