.NET Crash Dump and live process analysis via clrmd

Application debugging and analysis can be a daunting task, even more when source code neither symbols are not available. Visual Studio provides developers with powerful debugging capabilities, but the problem many times faced by developers is that Visual Studio is not installed on the target computer Sad smile which is fair enough if it is a production environment.

There are a few tools available, being WinDbg the most powerful and one of my favorite ones. WinDbg allows developers to debug native (in kernel and user mode) and managed code through SOS (Debugging Extension). The options available are more powerful than the ones provided by Visual Studio debugger, however it might not be very user friendly, for the following reasons:

  • Load SOS via CLR or mscorwks (depending on the version of the framework)
  • Type in commands in WinDbg to perform our analysis. These commands are powerful if the developer knows them besides having a good understanding of how the CLR works, the only thing is that many of these commands’ names are very user friendly, as shown below
.load C:WINDOWSMicrosoft.NETFrameworkv2.0.50727sos.dll


!dumpheap -type MyBusinessObject

PDB symbol for mscorwks.dll not loaded

 Address       MT     Size

027437e4 01d6683c       12

02743830 01d6683c       12

0274387c 01d6683c       12

...

02747d6c 01d6683c       12

02747db8 01d6683c       12

02747e04 01d6683c       12

02747e50 01d6683c       12

02747e9c 01d6683c       12

02747ee8 01d6683c       12

total 30 objects

Statistics:

      MT    Count    TotalSize Class Name

01d6683c       30          360 FinalizerProblem.MyBusinessObject

Total 30 objects


!gcroot 02747d6c

Note: Roots found on stacks may be false positives. Run "!help gcroot" for

more info.

Error during command: warning! Extension is using a feature which Visual Studio does not implement.


Scan Thread 7092 OSTHread 1bb4

Scan Thread 6864 OSTHread 1ad0

Finalizer queue:Root:02747d6c(FinalizerProblem.MyBusinessObject)


!finalizequeue

SyncBlocks to be cleaned up: 0

MTA Interfaces to be released: 0

STA Interfaces to be released: 0

----------------------------------

generation 0 has 0 finalizable objects (002906d0->002906d0)

generation 1 has 36 finalizable objects (00290640->002906d0)

generation 2 has 0 finalizable objects (00290640->00290640)

Ready for finalization 69 objects (002906d0->002907e4)

Statistics:

      MT    Count    TotalSize Class Name

7b47f8f8        1           20 System.Windows.Forms.ApplicationContext

...

7910b694       10          160 System.WeakReference

7b47ff4c        4          224 System.Windows.Forms.Control+ControlNativeWindow

01d6683c       22          264 FinalizerProblem.MyBusinessObject

01d65a54        1          332 FinalizerProblem.Form1

7b4827e8        2          336 System.Windows.Forms.Button

7ae78e7c        8          352 System.Drawing.BufferedGraphics

...

Total 105 objects

There is a great article on MSDN on this subject – Debugging Managed Code using the Windows Debugger.

So, WinDbg is very powerful but some developers might not find it user friendly, what options do we have then? Well, good news is that Microsoft has produced and released a library to diagnose and analyze CLR applications, it is called CLrMD (CLR Memory Diagnostics). It is currently in beta and available to download from nuget.

image

Image 1 – Install nuget package

Therefore, I have just built an utility to showcase some of the features in the library. The utility is a WPF C# application which implements the ClrMD library as well as the MVVM pattern. The whole idea is to make developers life easier, by providing an easy to use UI and encapsulate some of the commands in SOS as operations that can be selected on the user interface.

image

Image 2 – Options available in the utility

The utility as of now, provides 3 operations only which are:

  • Dump Heap
  • Heap Stats
  • Threads and StackTrace

These options can be expanded by making changes to the DebuggerOption ViewModel to add a new option, and by implementing the required code in CorDbg.Operations class (Depicted below code for collecting information threads and stack trace information of the attached process.

public ObservableCollection<Thread> GeThreadsAndStackTrace() {

            var retval = new ObservableCollection<Thread>();


            if (Session != null) {

                Session.Runtime.Threads.ToList().ForEach(x => {

                    var newItem = new Thread() {

                        ThreadId = string.Format("{0:X}", x.OSThreadId).Trim(),

                        ThreadExecutionBlock = string.Format("{0:X}", x.Teb).Trim()

                    };


                    x.StackTrace.ToList().ForEach(z => newItem.StackTrace.Add(new StackTrace() {

                        InstructionPtr = string.Format("{0,12:X}", z.InstructionPointer),

                        StackPtr = string.Format("{0,12:X}", z.StackPointer),

                        Method =  (z.Method != null ?  z.Method.GetFullSignature() : string.Empty)

                    }));


                    retval.Add(newItem);

                });

            }


            return retval;


        }

The operation workflow is as follows:

  • Refresh process list – if required (This is if the target application was launched after the utility was running)
  • Select the mode to attach to the target process.
  • Select operation and click on the Go button… That simple!

In this example, the target application was another instance of Visual Studio.

image

Image 3 – Managed Heap Stats

image

Image 4 – Running threads and their stack traces

I hope you’ll find this utility useful, please feel free to download it and extend it.
[office src=”https://onedrive.live.com/embed?cid=2FE1291768841ACE&resid=2FE1291768841ACE!5826&authkey=!ADRH2VtXOaWWuRU” width=”98″ height=”120″”]

Leave a Reply

Your email address will not be published. Required fields are marked *