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!

soshelp.dll

Comments (6)

  1. Web 10 Ways to Cut Down Web Development Time JavaScript Inheritance via Prototypes and Closures How to

  2. Hi,

    Thanks a lot for your extension. Really helped me out a lot in analysing a prod issue.

  3. Nicolas Dietrich says:

    Thanks Vandana for your comment. I left Microsoft since that time, but I'm happy to see it still helped some people 🙂

  4. Eugene Kirpichov says:

    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!

  5. Thomas W. says:

    Yes, please compile a 64 bit version or provide the source code.

  6. nicd_msft says:

    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

Skip to main content