While we are getting some nice tools from Microsoft for analyzing our memory, there’s still a lot of gaps where you have to resort to WinDBG and SOS. A perfect example that I’ve run into is looking at variables/types that are in different app domains because the Visual Studio debugging environment has essentially zero support for app domains. That’s normally not a problem for most people, but there’s a lot of things that you just need WinDBG and SOS to figure out. In this article I wanted to show a little trick I use with the WinDBG command language.

If you’re not familiar with WinDBG or SOS, you can watch my Introduction to WinDBG and SOS Commands and Minidump videos on WintellectNOW. Use the code JOHNR-2013 to get two free weeks of viewing pleasure.

The WinDBG command language allows you to write looping and logic statements using commands like .if, .while, .foreach, .printf, etc. You can use the command language with conditional breakpoints or write complicated analysis scripts in it. Like anything else in WinDBG, it’s barely documented and has no debugger, but a little trial and error take you a long way.

A very common situation when looking at a minidump is that you want to look at all of the objects of a particular type. In the usual case you have to copy and paste each address you find with !dumpheap –type <type>. That’s kind of tedious so here’s a quick way to dump out all the objects with the SOSEX !mdt command.

  1. .foreach (addr {!dumpheap -type Namespace.Class -short}) { !mdt addr; .echo }

It’s probably easiest to understand this from the inside out. The !dumpheap –type Namespace.Class –short, returns just the object addresses for Namespace.Class. Those address are assigned to the addr variable. The .foreach enumerates over each line of text in the addr variable and calls !mdt on each individual address. The final .echo places a blank line in the output. Below is an example where I’ll display the FontFamily types in a process.

  1. 0:013> .foreach (addr {!dumpheap -type FontFamily -short}) { !mdt addr; .echo }
  2. 000000b45faff460 (System.Drawing.FontFamily)
  3.     __identity:NULL (System.Object)
  4.     nativeFamily:000000b6aaad8f40 (System.IntPtr)
  5.     createDefaultOnFail:false (System.Boolean)
  7. 000000b45faff630 (System.Drawing.FontFamily)
  8.     __identity:NULL (System.Object)
  9.     nativeFamily:000000b6aaad8f40 (System.IntPtr)
  10.     createDefaultOnFail:false (System.Boolean)

If you run the above command, substituting your own type of course, you’ll see that the WinDBG command language is not the quickest language around. If you dump out a type with a lot of instances, you will see a lot of the BUSY in the command line. The good news is that running the command is far faster than you copy and pasting each address in yourself.

As this is a useful command, here’s a small script you can save to DumpType.txt. Note that $$ are comment characters.

  1. $$ If there's no first argument, there's nothing to do.
  2. .if(0 != ${/d:$arg1})
  3. {
  4.     $$ Get each address of the type into the addr variable.
  5.     .foreach (addr {!dumpheap -type ${$arg1} -short})
  6.     {
  7.         $$ Dump out this address using SOSEX.
  8.         !mdt addr;
  9.         $$ Put a line between each item dumped.
  10.         .echo
  11.     }   
  12. }
  13. .else
  14. {
  15.     .printf "\nUsage: $$>>a<\DumpType.txt type\n"
  16. }

To run the script use the WinDBG $$>a< command to read it in and pass the parameter of the type you’d like to dump.

  1. 0:013> $$>a<c:\junk\DumpType.txt
  2. Usage: $$>>a<DumpType.txt type
  4. 0:013> $$>a<c:\junk\DumpType.txt FontFamily
  5. 000000b45faff460 (System.Drawing.FontFamily)
  6.     __identity:NULL (System.Object)
  7.     nativeFamily:000000b6aaad8f40 (System.IntPtr)
  8.     createDefaultOnFail:false (System.Boolean)
  10. 000000b45faff630 (System.Drawing.FontFamily)
  11.     __identity:NULL (System.Object)
  12.     nativeFamily:000000b6aaad8f40 (System.IntPtr)
  13.     createDefaultOnFail:false (System.Boolean)