Last week, Microsoft released the new CLR Memory Diagnostics (ClrMD) library, which is a set of APIs for programmatically inspecting a crash dump of a .NET program.
To start playing with it, you first need to add the Microsoft.Diagnostics.Runtime package from NuGet (be sure to select Include Prerelease, because it is a prerelease version):
You can use ClrMD to analyze a crash dump from disk, or to attach to a live process. In both scenarios, you will need to use one of the static factory methods declared in the DataTarget class. To analyze a crash dump file from disk, start with the following code:
To attach to a live process, you need the process’s id:
By default, invasive attachment is used. You can state otherwise by using another overload of the AttachToProcess method that accepts an AttachFlag parameter.
Once attached, the DataTarget object will contain information on the process such as its architecture, loaded CLR versions and loaded modules, but for the really interesting stuff, you will need to create an instance of the ClrRuntime class:
You should pay attention to a few things here:
- Multiple CLR versions can be loaded side by side in the same process. DataTarget will contain all of them.
- In order to create a ClrRuntime instance, the path to the mscordacwks.dll should be provided.
- The TryGetDacLocation method returns the full path to mscordacwks.dll in case that you have it on your machine.
- In case that you are analyzing a crash dump, it is possible that you won’t have the matching mscordacwks.dll on your machine. In that case, you will need to get it from Microsoft’s symbol server (See ClrInfo.DacInfo.FileName). In the rare cases when it’s not there, use the method described here.
Once the runtime is created, you can use it for various tasks such as:
- Inspect the managed heap (all objects, blocking objects, finalizable objects, roots and so on).
- Inspect the thread pool.
- Inspect GC Handles.
- Inspect managed threads (call stack, objects on which the thread is blocked waiting on, current exception, and more).
It’s great to have this API as another tool in my debugging tool belt. I’m sure that it will prove itself as valuable in many situations.