Tuesday, May 19, 2009

Scripting WinDbg: .foreach command

The .foreach token parses the output of one or more debugger commands and uses each value in this output as the input to one or more additional commands.

.foreach [Options] ( Variable { InCommands } ) { OutCommands }

Can be any combination of the following options:
/pS InitialSkipNumber
Causes some initial tokens to be skipped. InitialSkipNumber specifies the number of output tokens that will not be passed to the specified OutCommands.
/ps SkipNumber
Causes tokens to be skipped repeatedly each time a command is processed. After each time a token is passed to the specified OutCommands, a number of tokens equal to the value of SkipNumber will be ignored.

Sample Usage
Consider a example where we need to dump all GCRoot references of System.Drawing.Icon objects. The MT for System.Drawing.Icon in our application is 7ae7613
To find all objects of MT 7ae76134, we will run the command !DumpHeap -mt 7ae76134
The output of the above command looks like

0:000> !DumpHeap -mt 7ae76134
Address MT Size
0989d6a4 7ae76134 40
09ab24b8 7ae76134 40
09b6a044 7ae76134 40
09b6cc70 7ae76134 40
09b6cdb4 7ae76134 40
09d444e4 7ae76134 40
0a0e480c 7ae76134 40
total 7 objects
MT Count TotalSize Class Name
7ae76134 7 280 System.Drawing.Icon
Total 7 objects

Now in normal scenario we have to run !GCRoot on each of the object address, that is seven times to get the desired result. .foreach comes to rescue here. We can run it for each object address for a specific command. As you have noted the above output have three columns with Address as the first which will be needed to passed on to the GCRoot command.

Executing !DumpHeap -mt 7ae76134 -short gives us the following, which only gives us the required object instance Address
0:000> !DumpHeap -mt 7ae76134 -short

We can now get the desired output (that is find all references to all System.Drawing.Icon objects) by .foreach using the following two variants

  1. .foreach ( ico {!DumpHeap -mt 7ae76134 -short}) {!GCRoot ico }
  2. .foreach /ps2 ( ico {!DumpHeap -mt 7ae76134 }) {!GCRoot ico }

Both of above commands prints the exact same output, but they differ in the way its parsed.

Example 1 uses the -short option that outputs only the address of the objects, which are directly passed on to the OutCommands
Example 2 is more versatile as it does not depend on the -short option. It uses the /ps option which causes the token to be skipped. In our case the first token (Which is Address) of the Output is read and passed to GCRoot, and next two subsequent tokens ( which are MT and Size are skipped for every line)

No comments:

Post a Comment