Skip to content

Automate Memory Dump analysis with Windbg commands in C#

AutoDebug : A simple Automated Debugger to run Windbg Commands and also query .NET CLR Runtime data in C#. Microsoft.Diagnostics.Runtime (ClrMD) is a set of APIs for introspecting processes and dumps. AutoDebug project make use of ClrMD v2 API’s to build the underlying debugger.

Why AutoDebug?

Quite often when you have large memory dumps, you need to run multiple debugger commands first to start looking deeper into the issues. This project would provide an easy way to automate running a set of commands on the memory dumps at hand.

What is Windbg?

Windbg or Debugging Tools for Windows is a multipurpose debugger for the Microsoft Windows operating system, distributed by Microsoft. Debugging is the process of finding and resolving errors in a system ; in computing it also includes exploring the internal operation of software as a help to development.

What are the core components of Windbg?

Windbg package contains a lot of functionality but at its core are few DLL’s listed below

  • dbgeng.dll (core debugger interfaces)
  • dbghelp.dll (helper functions)
  • symsrv.dll (symbol loading)
  • srcsrv.dll (source loading)

How do the above files get utilized?

When you write an application using dbgeng, by default the above dll’s are loaded from Windows system folder. But these files are not updated often and that becomes a challenge if you are planning to write an application using dbgeng as debugger engine.

How to get updated debugger components?

The updated component dll’s mentioned above are available as part of ‘Debugging Tools for Windows’ packages. In order to use the updated components, copy the above 4 dll’s to your local application/executable folder.

Keep in mind, debugger components are NOT architecture agnostic. So make sure the files match the process (or system) architecture you are debugging.

Can I re-distribute these components as part of my application?

The answer is YES. Here is the legal documentation for it from Microsoft.

First look at usage

Let us see a simple use case first.

> We create a debugger instance passing memory dump file name.
> Then calling Execute method by passing a Windbg command
> The Execute method returns the command results.
> We are just printing the returned string on console.

Usage

// Create Debugger instance and call Execute for any Windbg Command
using (DbgEngine dbg = new DbgEngine(DumpFileName))
{
	Console.WriteLine(dbg.Execute(".time"));
	Console.WriteLine(dbg.Execute("~"));
	Console.WriteLine(dbg.Execute(".sympath"));
}

Output

Sample output of the above code

Debug session time: Fri Jun 12 23:46:40.000 2020(UTC + 5:30)
System Uptime: 1 days 20:32:03.277
Process Uptime: 0 days 0:06:13.000
	Kernel time: 0 days 0:00:01.000
	User time: 0 days 0:00:05.000

.0  Id: 13ac.1350 Suspend: 0 Teb: 00000081`b83dc000 Unfrozen
 1  Id: 13ac.380 Suspend: 0 Teb: 00000081`b83de000 Unfrozen
 2  Id: 13ac.1bc4 Suspend: 0 Teb: 00000081`b83e0000 Unfrozen
 3  Id: 13ac.1088 Suspend: 0 Teb: 00000081`b83e6000 Unfrozen
 4  Id: 13ac.dc8 Suspend: 0 Teb: 00000081`b83e8000 Unfrozen
 5  Id: 13ac.462c Suspend: 0 Teb: 00000081`b83ec000 Unfrozen
 6  Id: 13ac.5788 Suspend: 0 Teb: 00000081`b83ee000 Unfrozen
 7  Id: 13ac.1adc Suspend: 0 Teb: 00000081`b83f0000 Unfrozen
 8  Id: 13ac.3b6c Suspend: 0 Teb: 00000081`b83f2000 Unfrozen
 9  Id: 13ac.4450 Suspend: 0 Teb: 00000081`b83f4000 Unfrozen
10  Id: 13ac.41d8 Suspend: 0 Teb: 00000081`b83f6000 Unfrozen
11  Id: 13ac.4c3c Suspend: 0 Teb: 00000081`b83f8000 Unfrozen
12  Id: 13ac.566c Suspend: 0 Teb: 00000081`b83fa000 Unfrozen
13  Id: 13ac.1df8 Suspend: 0 Teb: 00000081`b83fc000 Unfrozen

Symbol search path is: srv*
Expanded Symbol search path is: cache *; SRV* https://msdl.microsoft.com/download/symbols

Using Command List file

There is an easier way to automate the list of native windbg commands executed using a Command list file.

Command list file

Create a text file in the application local folder > commandlist.txt

Sample file content below, one command per line

.time
.sympath
~
~*kb 100
.dumpdebug

Advanced Usage

Let us try some advanced use case scenarios.
You need extra files in the local application folder for these windbg commands to work.

Usage

// Create Debugger instance and call Execute for any Windbg Command
using (DbgEngine dbg = new DbgEngine(DumpFileName))
{
 Console.WriteLine(dbg.Execute(".time"));
 Console.WriteLine(dbg.Execute(".sympath"));
 Console.WriteLine(dbg.Execute(@".extpath+ [c:\path-to-windbg-extensions]"));
 Console.WriteLine(dbg.Execute(".load [extension-name]"));
 Console.WriteLine(dbg.Execute("![extension-command]"));
}

Practical usage of AutoDebug would be to redirect output to a text file

C:\AutoDebug>autodebug [memory-dump-file-name] > result.txt

Query CLR Runtime using ClrMD API

DbgEngine class exposes a propery called DataTargetInstance which is of type DataTarget from ClrMD v2.
You can use this property to access ClrMD API hierarchy.

I have also added few functions which demonstrates how to use ClrMD v2 API.
Check the source in ClrDebugger.cs file and have also included the sample output of each function there.

/// Create Debugger instance and call Execute any Windbg Command
using (DbgEngine dbg = new DbgEngine(DumpFileName))
{
    /// Sample ClrMD v2 snippets to mimic SOS Windbg extension commands
    /// Check the sample code in ClrDebugger.cs file
    dbg.ClrDacInfo();
    dbg.DumpHeap(StatsOnly : false);
    dbg.DumpModules();
}

Code for ClrDacInfo function
Code for Dumpheap function
Code for DumpModules function

Have fun. If you have any suggestions or ideas, feel free to comment here or on github (project link below).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: