How to read managed function parameter values from call stack when they read in WinDBG?

This week I was debugging a managed code Application with WinDBG and PSSCOR2 extension.

I had to take a look at the managed call stack including it’s function parameter using !CLRStack –p

The output looked similar to this one (the problem is the <no data> tag for the argument “args”)

    1: 0034f260 003d018d ConsoleApplication5.Program.Main(System.String[]) [C:\Users\me\Documents\Visual Studio 2010\Projects\ConsoleApplication5\ConsoleApplication5\Program.cs @ 28]
    2:      PARAMETERS:
    3:          args (0x0034f290) = <no data>

After quite some time of research I gave up and later on met a colleague who was able to give me the answer.

The assemblies I was debugging were release assemblies and the Just In Time Compiler (JIT) does lots of performance optimizations so that the debugging extensions are not able to extract the parameter values.

The solution to this problem is to tell the JIT compiler to avoid optimization during while debugging. Unfortunately this means that there is no easy way to fix the issue when only looking at post mortem memory dumps.

The following MSDN Article demonstrates how to ease image debugging: https://msdn.microsoft.com/en-us/library/9dd8z24x(v=VS.100).aspx

If your create a text file “application.ini” next to your application.ini and make sure it contains the following lines before starting the program:

    1: [.NET Framework Debugging Control]
    2: GenerateTrackingInfo=1
    3: AllowOptimize=0

For debug builds you usually do not have to do this as optimizations are disabled anyway.

When generating native images with NGEN.EXE this settings are also considered so that you can take control over NI optimizations, too!

After applying these changes the !CLRStack –p output looked as follows:

    1: 0034f260 003d018d ConsoleApplication5.Program.Main(System.String[]) [C:\Users\me\Documents\Visual Studio 2010\Projects\ConsoleApplication5\ConsoleApplication5\Program.cs @ 28]
    2:     PARAMETERS:
    3:         args (0x0034f290) = 0x0242bf80

Now you can look at the args value using !DumpObject 0x0242bf80 or !DumpArray 0x0242bf80:

    1: 0:000> !do 0x0242bf80
    2: Name:        System.Object[]
    3: MethodTable: 6e826ba8
    4: EEClass:     6e5a9688
    5: Size:        16(0x10) bytes
    6: Array:       Rank 1, Number of elements 0, Type CLASS
    7: Element Type:System.String
    8: Fields:
    9: None
   10: 0:000> !dump array
   11: No export dump found
   12: 0:000> !dumparray 0x0242bf80
   13: Name:        System.String[]
   14: MethodTable: 6e826ba8
   15: EEClass:     6e5a9688
   16: Size:        16(0x10) bytes
   17: Array:       Rank 1, Number of elements 0, Type CLASS
   18: Element Methodtable: 6e86f92c