How can I view the local variables on the evaluation stack when debugging a .NET CLR application?

Mike Dinescu picture Mike Dinescu · Feb 6, 2009 · Viewed 8.9k times · Source

I'm using Windbg (with the sos extention) and trying to debug a crashed application. I was able to dump the IL of the call that threw the exception and by examining the code, it seems like I could obtain the information that I need if I could dump the contents of the evaluation stack. Is it possible to do what with WinDbg & sos ?

Here's what I did:

  1. Started WinDbg
  2. Attached to the crashed process
  3. loadby sos mscorwks (to load the sos extension)
  4. !token2ee theModuleName 0600009a (where theModuleName is the name of the app(and assembly) t hat I'm debuging and 9a is the method offset of the method that crashed as reported by the Windows Error Reporting tool. I got this output:

    Module: 000e2c3c (theApplicationName.exe)
    Token: 0x0600009a
    MethodDesc: 000e67c8
    Name: MyNamespace.MyClassName.theCulpritFn(MyOtherClass)
    JITTED Code Address: 0081b1d0

  5. !dumpil 00e67c8 (which dumped the IL for the method in question). This is the output:

    
    // ..
    // .. the previous code omitted for brevity
    .catch
    {
     IL_0071: stloc.0
     IL_0072: nop
     IL_0073: ldstr "Can't set CurrentServer property for: "
     IL_0078: ldarg.0
     IL_0079: ldfld MyNamespace.MyClassName::_currentServer
     IL_007e: brtrue.s IL_0087
     IL_0080: ldstr ""
     IL_0085: br.s IL_0092
     IL_0087: ldarg.0
     IL_0088: ldfld MyNamespace.MyClassName::_currentServer
     IL_008d: callvirt MyNamespace.MyOtherClass::get_Name
     IL_0092: call System.String::Concat
     IL_0097: ldloc.0
     IL_0098: newobj MyNamespace.MySpecialExceptionType::ctor
     IL_009d: throw
    } 
    

    The question is: is there a way for me to see what was pushed on the stack before the exception was thrown. If I'm not mistaken, the argument passed into the exception constructor should be the local variable at index 0 on the evaluation stack.

    P.S. When I tried to call !clrstack -a I got a message saying: Unable to walk the managed stack. The current thread is likely not a managed thread. You can run !threads to get a list of managed threads in the process.

Thanks!

Answer

Brian Rasmussen picture Brian Rasmussen · Feb 7, 2009

You need to identify and select the right thread. The id of the current thread is displayed in the WinDbg prompt.

!threads will display all managed threads in your application. Once identified you can switch threads using ~Xs where X is the WinDbg id for the thread.

!clrstack will show you the stack trace. If you want locals and/or parameters use -l / -p (or -a for both).

You can go through all the threads and list their call stack with ~*e!clrstack.

If local/parameters doesn't give you what you need, use !dso to display objects pushed onto the stack.