Sample Windbg extension to recurse, filter and pipe commands
I didn't post to this blog during many months, mainly because I moved from my Escalation Engineer position to an Application Development Consultant position (aka Technical Account Manager Dev).
I missed some free time for that kind of leisure, and as many other interesting blogs now spread over the web, I felt unuseful to post things that may not really help someone.
That's why I come back today, to post a debugger extension I wrote some months ago to help me to automate my debugging sessions.
I always felt a lack in windbg to easily filter other debugger extensions outputs and automate recursing commands with previous results.
Others like Doug & Tess are able to use both !foreach, .shell - -ci or even logparser to filter outputs, but I'm too bad/lazy for that and preferred having my own debugger syntax :)
After having shown this extension to some debugging class I held in France, I decided to share it publicly.
The binary version I'm posting here is the initial version of this extension, that I wanted to improve before posting, but as I never had time I'm posting it here as-is..
It contains in this version only 1 debugger command called !sosexec, with this awful syntax:
!sosexec /c “command1|filter1”->”command2 [tokenID1]|filter2”->”command3 [tokenID2]”->....
The parameter [tokenID1] is the column index for the token you’re looking for, starting from 0.
For example in the bellow output, 0 is the ‘MT’ token, 1 is the ‘Field’ token, and thus 6 is the tokenID for ‘Value’. Note those indexes are changing depending on sos version so take care to check them first.
0:021> !do 0acca994
Name: System.Web.HttpContext
MethodTable: 663a2750
EEClass: 663a26e0
Size: 168(0xa8) bytes
(C:\WINDOWS\assembly\GAC_32\System.Web\2.0.0.0__b03f5f7f11d50a3a\System.Web.dll)
Fields:
MT Field Offset Type VT Attr Value Name
663ad210 4000fc7 4 ...IHttpAsyncHandler 0 instance 08a308d0 _asyncAppHandler
663a206c 4000fc8 8 ...b.HttpApplication 0 instance 08a308d0 _appInstance
663a3a9c 4000fc9 c ....Web.IHttpHandler 0 instance 0accb490 _handler
663a2ba0 4000fca 10 ...m.Web.HttpRequest 0 instance 0accaa3c _request
A real world example for ASP.NET 2.0 application could be the one bellow to list the current ASPX pages easily (note1 663a2750 was my methodtable for HttpContext) (note2 that’s just a sample, Tess debugging script makes it lots better)
0:021> !sosexec /c "!dumpheap -mt 663a2750 -short"->"!do [0]|_request"->"!do [6]|_path"->"!do [6]|String:"
Executing !do 06c35cb0
Executing !do 06c35d58
Executing !do 06c34538
String: E:\Applications.Net\CRM Cog Integration Web\coghierarchy.aspx
Executing !do 0acca994
Executing !do 0acc91e4
String: E:\Applications.Net\CRM Cog Integration Web\cogcompanyinformation.aspx
Executing !do 0ca32e98
Executing !do 0ca32f40
Executing !do 0ca31310
String: E:\Applications.Net\CRM Cog Integration Web\cogcompanyinformation.aspx
Executing !do 0caa95fc
Executing !do 0caa96a4
Executing !do 0caa7e4c
String: E:\Applications.Net\CRM Cog Integration Web\cogcompanyinformation.aspx
This command will:
1. Execute !dumpheap -mt 663a2750 -short (I got MT from an earlier !dumpheap –stat)
3. Execute !do with the 1th token (ID 0) for each output lines of step 1
4. Filter this output for lines containing string “_request”
5. Execute !do again with the 7th token (ID 6) of each filtered line of step 4 (the ‘Value’ token)
6. Filter output with lines containing the string ‘_path’
7. Execute !do with again the 7th token (ID 6) of each filtered line of step 6
8. Filter output from step 7. to only show the string content, that starts with “String:”
Another example bellow will list SQL commands executed by current threads:
!sosexec /c "~*e !dso|System.Data.SqlClient.SqlCommand"->"!do [1]|cmdText"->"!do [5]"
Executing !do 0x2645ab0c
Executing !do 0x143f9908
String: sql_PrestataireLoadPatente
Executing !do 0x111bbc18
Executing !do 0x1c442bdc
String: sql_FactureLoad
Executing !do 0x14efddc0
Executing !do 0x143f5f44
String: sql_Vue_facture_impayee
The nice thing is that it works for both user (native & managed) and kernel debugging (live or postmortem).
Another example will dump all ASP templates compiled in an IIS process using the iisinfo.dll debugger extension brought by DebugDiag.
.logopen c:\temp\aspcode.txt
!sosexec /c "!iisinfo.templates -v|C:\"->"!templatecode [1]"
.logclose
You can also simply use it to filter your debugger output, for example listing all DLLs named ora* (don’t ask me why :-p)
0:029> !sosexec /c "lmnt|ora"
03f70000 041c7000 orageneric9 orageneric9.dll Mon May 06 02:23:24 2002 (3CD5CCFC)
60500000 60590000 oracommon9 oracommon9.dll Mon Apr 29 01:12:14 2002 (3CCC81CE)
60800000 60806000 oravsn9 oravsn9.dll Mon Apr 29 01:13:48 2002 (3CCC822C)
60810000 60816000 orawtc9 orawtc9.dll Mon Apr 29 01:13:50 2002 (3CCC822E)
61400000 6142c000 oranl9 oranl9.dll Sat Apr 27 04:30:17 2002 (3CCA0D39)
61480000 61534000 oran9 oran9.dll Sat Apr 27 04:31:08 2002 (3CCA0D6C)
I highly recommend to write and test those commands step by step, as a simple mistake can make this version of the extension loop infinitely executing wrong commands and thus looking for unknown symbols… J
When I'll have a better version, I'll post it with source to codeplex to also let other people improve it, as it exposes lightweight framework of C++ objects to allow to be reused in other debugger extensions, such as my only !sosexec command is only made of:
HRESULT CALLBACK
sosexec(PDEBUG_CLIENT4 Client, PCSTR args)
{
INIT_API();
// Read arguments command line
CArgs* oArgs = new CArgs(args);
vector<string> sCommands = oArgs->getCommands();
// Split args into commands/filters/tokens
vector<string> sFilters = oArgs->getFilters();
vector<int> iTokens = oArgs->getTokens();
// Recursively execute commands
CExecutor *oExec1 = new CExecutor(Client, sCommands,sFilters,iTokens);
oExec1->RecurseExec();
free(oExec1);
EXIT_API();
return S_OK;
}
On the feature list there is currently some more switches like /unique, /silent, ability to use multiple filters, and skip headers or footer lines.
As I’ll try to improve it and post source code for good, feel free to share ideas, feedbacks or sample commands that you find useful to share.
Enjoy!
Comments
Anonymous
December 18, 2008
Web 10 Ways to Cut Down Web Development Time JavaScript Inheritance via Prototypes and Closures How toAnonymous
July 04, 2010
The comment has been removedAnonymous
August 21, 2010
Thanks Vandana for your comment. I left Microsoft since that time, but I'm happy to see it still helped some people :)Anonymous
September 19, 2011
Hi, I was about to cry when I saw that someone, somewhere finally wrote such an extension, but alas! I have a 64-bit dump and the extension is 32-bit! Please publish it somewhere, I'd be happy to see how these things are written, to improve it and to build a 64-bit version!Anonymous
January 10, 2014
Yes, please compile a 64 bit version or provide the source code.Anonymous
October 13, 2015
Hello, After all those years I finally recompiled an x86 and an x64 version, they are both available on ndietrich.fr/.../sosexec.zip Hope this might be useful for someone Nicolas