Reading minidump files, part 4 of 4: Putting it all together

All code is available on my CodePlex project.

This is the last in a 4 part series on how to use MiniDumpReadDumpStream to read data streams contained within minidump files. The first article discussed how to access memory mapped files from c#, the second how to call MiniDumpReadDumpStream and the third how to interpret the data returned (using ModuleListStream as an example). This post wraps everything up and introduces the Minidump Explorer Windows Form application. The posts that follow this one will discuss each data stream as I work towards creating an application (Minidump Explorer is just a stepping stone) that will let you analyze and visualize minidumps of processes that were running the CLR.

Analyzing the information contained in minidumps is still going to take some time; that requires using an entirely different API and a lot more work. For now we’ll just look at the raw data contained in a minidump file and create an application that can view that data. We’ll use that as a stepping stone to something bigger. Given that, let me introduce the Minidump Explorer Windows Form application! Remember those Firefox crash dumps I found lying around in my first post? Well here’s our first look at the contents of those files:

Display of a module list

Minidump Explorer displaying a module list stream.

You can see that I’m using the module stream information I spoke about in the previous article to display a list of modules that were loaded at the time of the crash. Some of this module information (e.g. the base address, timestamp, size & module name) is going to be vital to us in the future when we start trying to interpret the minidump i.e. trying to look at threads and calls stacks, or heaps and objects. That’s still a ways off, but I want to take a moment to explain the difference between looking at the raw minidump stream data and looking at what’s happening inside the application that crashed.

What is a minidump and how do we interpret them?

You’ll notice that I always mention analyzing minidumps of processes “running the CLR”. I’ve been very careful to deliberately word it that way. Minidumps are crash dumps of a process from an operating system point of view. By that I mean that from the operating system point of view, it was running a process; that process stopped working and a crash dump was created. The operating system doesn’t know what that process was, or what it was doing. It’s knows it had resources allocated to it, there were one or more threads and it had a list of instructions that it was executing. But it doesn’t know whether it was running a Python interpreter, a Java VM, the CLR or just a regular native application. From the operating system point of view everything is a native process. Think about it this way: the operating system is running the CLR, and the CLR is running your code.

When we look at a minidump we’re seeing what the operating system see’s i.e. the CLR. It has no knowledge of the data structures or workings of the CLR; it just does what it’s told to do.

For example: the operating system doesn’t know about CLR threads. It knows about threads that the CLR asks it to create, but it doesn’t know about threads created internally by the CLR. Did you know that CLR threads don’t necessarily match one-to-one with operating system threads? Just because you create a System.Threading.Thread object in your .Net code doesn’t mean the CLR will create a matching thread in the operating system. This is because the CLR sits on top of the operating system and manages itself and its own resources; just like the Java VM does.

What does this all mean? Well we don’t want to see what the operating was doing when the application crashed. If we looked from that point of view we’d see that the operating system was running the CLR. We want to know what was happening in our .Net code when it crashed, or rather what the CLR was doing. This means we need something that knows how the CLR works and can translate between what the operating system saw and what the CLR was doing, like this:

Operating system running CLR code

Operating system running CLR code

Hopefully that helps to illustrate where we’re heading towards. It’s a bit more technical than that, but it should help you understand.

Viewing module information

Back to Minidump Explorer! As I was saying: I’ve used the module stream to display the list of modules. You can also double click each module to get more detailed information:

General module properties

General module properties

Module fixed info

By the way: I’m not picking on Firefox! It just happens to be one of the few applications that will create a minidump when something does go wrong. I’m sure the problem was probably Flash related 😉

Creating minidumps

I’ve also included the ability to capture crash dumps. I discussed that here. It’s a simple wizard that lets you select a process, choose what information you want captured and create the crash dump. The process will be unaffected once the dump has been created.

CodePlex

I’ve created a project on codeplex and uploaded all of the code I’ve done so far, you’ll find it at https://minidumps.codeplex.com. Have a look around, download the application and give some comments/suggestions, feedback is very welcome.

Moving forward

Now that the basics are done we should be able to add the other data streams fairly quickly. Next up: thread, memory/memory 64 and handle streams.

Posted in Crash Dumps | Tagged , , | 3 Comments

Converting from time_t to System.DateTime

I was busy reviewing my minidump source code before publishing it to codeplex and I noticed that there was one field in the MINIDUMP_MODULE structure that I didn’t mention previously: MINIDUMP_MODULE.TimeDateStamp.

The documentation for MINIDUMP_MODULE says this field is stored as a time_t, which turns out to be a C/C++ type. Trying to find out how to convert that into a System.DateTime in .Net has been a painful experience. The amount of different date/time formats in the Windows API is quite scary. You can find a list of some of them here.

So to save you the time and effort of trying to figure out how to deal with time_t’s here the code to convert them to a System.DateTime:

public static DateTime TimeTToDateTime(UInt32 time_t)
{
    // 10 000 000 * january 1st 1970
    long win32FileTime = 10000000 * (long)time_t + 116444736000000000;

    // FromFileTimeUtc is the UCT time, FromFileTime adjusts for the local timezone
    return DateTime.FromFileTime(win32FileTime); 
}

And here’s why it works.

Another route that (should) work is to first convert the time_t to a system time using FileTimeToSystemTime.

Posted in Crash Dumps | Tagged | Leave a comment

Reading minidump files, part 3 of 4: Reading stream data (ModuleListStream) returned from MiniDumpReadDumpStream

All code is available on my CodePlex project.

This is part 3 of a 4 part series on using MiniDumpReadDumpStream. Part 1 discussed how to access memory mapped files from C#. Part 2 showed how to invoke MiniDumpReadDumpStream. This article follows on from part 2 and discusses how to read the data returned from MiniDumpReadDumpStream.

I ended the previous article with the C# signature we’ll be using to invoke MiniDumpReadDumpStream:

[DllImport("dbghelp.dll", SetLastError = true)]
public static extern bool MiniDumpReadDumpStream(IntPtr BaseOfDump,
        uint StreamNumber,
        ref MINIDUMP_DIRECTORY Dir,
        ref IntPtr StreamPointer,
        ref uint StreamSize);

This article will discuss how to read the data that is returned in StreamPointer.

I’m going to use MINIDUMP_STREAM_TYPE.ModuleListStream as an example as it is fairly simple to read and also covers most of the code we’ll need to use when reading other streams.

Before I go into the details I’ll give a quick summary of what we’re going to be doing:

  • First we’ll invoke MiniDumpReadDumpStream() and ask it to read the MINIDUMP_STREAM_TYPE.ModuleListStream. This minidump stream contains a list of modules.
  • The call will return a pointer (StreamPointer) to a MINIDUMP_MODULE_LIST structure as well as the size of the structure (StreamSize).
  • MINIDUMP_MODULE_LIST has 2 fields: one telling us how many modules there are (NumberOfModules) and the second containing an array of the modules (Modules[]).
  • First we’ll read the MINIDUMP_MODULE_LIST and then we’ll read each of the MINIDUMP_MODULE’s (with a few tricks along the way).

First up we need to call MiniDumpReadDumpStream to read the ModuleListStream.

  • BaseOfDump is the pointer to the memory mapped view that we created previously.
  • StreamNumber is the stream we want to read. We’ll be using MINIDUMP_STREAM_TYPE.ModuleListStream (which happens to be “4”).
  • Dir, StreamPointer and StreamSize are all returned from the call, so we’ll create local variables for them.

The Dir parameter is of type MINIDUMP_DIRECTORY. This is declared in dbghelp.h. We won’t be using this, so I’ll just list the C# translation without going into details:

internal struct MINIDUMP_LOCATION_DESCRIPTOR
{
    public UInt32 DataSize;
    public uint Rva;
}

internal struct MINIDUMP_DIRECTORY
{
    public UInt32 StreamType;
    public MINIDUMP_LOCATION_DESCRIPTOR Location;
}

Now that we know the types for all of the parameters we can invoke the method:

MINIDUMP_DIRECTORY directory = new MINIDUMP_DIRECTORY();
streamPointer = IntPtr.Zero;
streamSize = 0;

// baseOfView is the IntPtr we got when we created the memory mapped file
if (!NativeMethods.MiniDumpReadDumpStream(baseOfView, MINIDUMP_STREAM_TYPE.ModuleListStream, ref directory, ref streamPointer, ref streamSize))
{
    throw new Win32Exception(Marshal.GetLastWin32Error());
}

Using Marshal.PtrToStructure() to marhsal unmanaged to managed memory

So if reading the ModuleListStream is supposed to return a MINIDUMP_MODULE_LIST structure how do we get to it from the IntPtr returned in streamPointer? streamPointer is a pointer to a MINIDUMP_MODULE_LIST structure held in unmanaged memory. In order to make use of it we need to marshal the structure from unmanaged into managed memory. Luckily the .Net Framework does all of the heavy lifting for us, all we need to do is call Marshal.PtrToStructure and it’ll do the marshaling for us, like this:

MINIDUMP_MODULE_LIST moduleList = 
    (MINIDUMP_MODULE_LIST) Marshal.PtrToStructure(streamPointer, typeof(MINIDUMP_MODULE_LIST));

With MINIDUMP_MODULE_LIST defined as:

[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct MINIDUMP_MODULE_LIST
{
    public UInt32 NumberOfModules;
    public IntPtr Modules; // Why not "MINIDUMP_MODULE[] Modules"? Keep on reading...
}

Simple hey? Too simple? Unfortunately for us, this time it is too simple.

While the marshaler does an excellent job of letting us call into unmanaged code and transfering data between the two, it’s not always perfect. You’ll remember I said that MINIDUMP_MODULE_LIST contains a Modules field that is an array of MINIDUMP_MODULE’s. So why have I declared Modules as an IntPtr? It’s because the marshaler doesn’t seem to be able to marshal an array of structures (by value) contained within a structure. At least I haven’t been able to find a way to do it. So we’re going to have to do this in 2 parts: we’ll get the MINIDUMP_MODULE_LIST structure like we already have, and then we’ll read the array seperately (we’re actually not even going to use the Modules field directly). Stick with me here, this part needs some concentration.

Lets look at MINIDUMP_MODULE_LIST again: we have NumberOfModules which is 4 bytes (32 bits) followed by an array MINIDUMP_MODULES, each of which is 108 bytes (I’ll show you the C# version soon). When I read my sample minidump I get streamPointer = 0x0f84054c and streamSize = 0x000011bc (4540 bytes). So if NumberOfModules is 4 bytes then I should have 4536 bytes (4540 – 4 = 4536) allocated to the Modules field. If each MINIDUMP_MODULE is 108 bytes then I should have 42 modules (4536 / 108 = 42). The important thing to note here is that all the data we need is contained in one, sequential, block of memory: NumberOfModules is followed by 42 allocations of MINIDUMP_MODULE’s.

After calling Marshal.PtrToStructure() to marshal my streamPointer into a MINIDUMP_MODULE_LIST structure I can see that NumberOfModules is “42”, as expected. So we have all of the data we need, we just need to get it into a format that we can use.

Since Modules is an array of strucutres, and Marshal.PtrToStructure() can marshal pointers into structures, we can use it and some basic pointer arithmetic to do the work for us.

We know the data for the stream beings at 0x0f84054c (that’s my value for the streamPointer). And we know that the first field (NumberOfModules) is 4 bytes. So if we add 4 to the value of streamPointer we’ll get the address of the first MINIDUMP_MODULE structure (the first strucutre in Modules). So we could do something like this:

streamPointer += Marshal.SizeOf(typeof(MINIDUMP_MODULE_LIST.NumberOfModules)); // Advance the pointer past the "NumberOfModules" field

MINIDUMP_MODULE theFirstModule = 
    (MINIDUMP_MODULE) Marshal.PtrToStructure(streamPointer, typeof(MINIDUMP_MODULE)); // read the first MINIDUMP_MODULE

Put that in a for…loop and we’ve read the whole structure successfully.

There is actually an easier way to do this. I’ve been experimenting with using SafeMemoryMappedViewHandle as the return value to MapViewOfFile instead of IntPtr. Either will work, but SafeMemoryMappedViewHandle includes a ReadArray() method, which makes our code easier to read as there is no need to read each MINIDUMP_MODULE individually.

SafeMemoryMappedViewHandle does make other things a bit more tedious though. You have to call AcquirePointer() & ReleasePointer() everytime you want to get at the memory address it references. I’ll probably stick with it though as it does make reading arrays easier. It also handles bounds checking and cleanup for us.

Now that we can successfully read a stream it makes sense to put this all into a method and use some generics:

protected unsafe T ReadStream(IntPtr baseOfView, MINIDUMP_STREAM_TYPE streamToRead)
{
    MINIDUMP_DIRECTORY directory = new MINIDUMP_DIRECTORY();
    IntPtr streamPointer = IntPtr.Zero;
    uint streamSize = 0;

    if (!NativeMethods.MiniDumpReadDumpStream(baseOfView, streamToRead, ref directory, ref streamPointer, ref streamSize))
    {
        throw new Win32Exception(Marshal.GetLastWin32Error());
    }

    return (T)Marshal.PtrToStructure(streamPointer, typeof(T));
}

Now that we can successfully read MINIDUMP_MODULE_LIST it’s time to talk about MINIDUMP_MODULE a bit. The definition for MINIDUMP_MODULE in the MSDN is:

typedef struct _MINIDUMP_MODULE {
  ULONG64                      BaseOfImage;
  ULONG32                      SizeOfImage;
  ULONG32                      CheckSum;
  ULONG32                      TimeDateStamp;
  RVA                          ModuleNameRva;
  VS_FIXEDFILEINFO             VersionInfo;
  MINIDUMP_LOCATION_DESCRIPTOR CvRecord;
  MINIDUMP_LOCATION_DESCRIPTOR MiscRecord;
  ULONG64                      Reserved0;
  ULONG64                      Reserved1;
} MINIDUMP_MODULE, *PMINIDUMP_MODULE;

There are a few new types we need to map here.

ULONG64 is defined as a 64-bit unsigned integer. We’ll use UInt64 in C#.

We’ve discussed ULONG32 before, it’s a UInt32 in C#.

ModuleNameRva is an RVA. This is an interesting one. Physically it’s defined as a DWORD in DbhHelp.h, so we’ll use a uint. That part is easy. What it means is a bit more complicated. An RVA is a “Relative Virtual Address”: it contains the offset from the beginning of the memory mapped view where reading should start. So if the memory mapped view starts at 0x00000010 and the RVA is 4, then you should reading from 0x00000014 (0x00000010 + 4).

Reading MINIDUMP_STRING’s

The documentation for MINIDUMP_MODULE says that ModuleNameRva is “An RVA to a MINIDUMP_STRING structure that specifies the name of the module”. So if we add ModuleNameRva to the memory mapped view pointer we’ll find a MINIDUMP_STRING structure:

typedef struct _MINIDUMP_STRING {
  ULONG32 Length;
  WCHAR   Buffer[];
} MINIDUMP_STRING, *PMINIDUMP_STRING;

I haven’t got the marshaler to read this structure successfully in it’s entirety, so we’ll use the marshaler to read the pieces seperately:

We have the pointer to the memory mapped view and we have the RVA offset to the MINIDUMP_STRING, so if we add them together we’ll get the address of the Length field:

IntPtr positionToReadFrom = new IntPtr(baseOfView + rva);

Length is 32bits, so we’ll ask the marshaler to read that for us:

int numberOfCharacters = Marshal.ReadInt32(positionToReadFrom) / 2;

You’ll see I’ve read the 32 bits for the Length field and then divided it by 2. This is because we’re going to call Marshal.PtrToStringUni() to read Buffer for us. It needs to know the number of characters to read, not the number of bytes to read. Buffer is an array of wide chars (WCHAR), so each character in the string is 2 bytes (this is to cater for unicode characters). Length contains the size of the Buffer in bytes, not the number of characters, so we have to divide it by 2 to get the number of characters. As an example: Length could indicate 20, which means Buffer is 20 bytes big, but contains 10 (20 / 2) characters, each of which is 2 bytes.

To read the string we call Marshal.PtrToStringUni():

// "advance" the pointer 4 bytes (to jump over the "Length" field);
positionToReadFrom += 4; 

// Read and marshal the string
return Marshal.PtrToStringUni(positionToReadFrom, numberOfCharacters);

The full method looks like this (I’ve used SafeMemoryMappedViewHandle in this case instead of IntPtr for the memory mapped view. You can see the extra code this adds):

protected internal unsafe string ReadString(uint rva)
{
    try
    {
        byte* baseOfView = null;

        // _mappedFileView is a SafeMemoryMappedViewHandle 
        _mappedFileView.AcquirePointer(ref baseOfView);

        IntPtr positionToReadFrom = new IntPtr(baseOfView + rva);

        // First 32bits is the length field, which is the number of bytes, not number of chars. Divide it by 2 to get number of chars (WCHAR is 2 bytes - unicode)
        int len = Marshal.ReadInt32(positionToReadFrom) / 2;

        // "advance" the pointer 4 bytes (to jump over the "Length" field);
        positionToReadFrom += 4; 

        // Read and marshal the string
        return Marshal.PtrToStringUni(positionToReadFrom, len);
    }
    finally
    {
        _mappedFileView.ReleasePointer();
    }
}

That takes care of reading ModuleNameRva. Next up is VersionInfo. This is of type VS_FIXEDFILEINFO. I won’t go into the detail of each field; the documentation describes them well enough. The C# version is below.

CvRecord and MiscRecord are both MINIDUMP_LOCATION_DESCRIPTOR which I’ve already mentioned. The final versions of VS_FIXEDFILEINFO and MINIDUMP_MODULE are:

[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct VS_FIXEDFILEINFO
{
    public UInt32 dwSignature;
    public UInt32 dwStrucVersion;
    public UInt32 dwFileVersionMS;
    public UInt32 dwFileVersionLS;
    public UInt32 dwProductVersionMS;
    public UInt32 dwProductVersionLS;
    public UInt32 dwFileFlagsMask;
    public UInt32 dwFileFlags;
    public UInt32 dwFileOS;
    public UInt32 dwFileType;
    public UInt32 dwFileSubtype;
    public UInt32 dwFileDateMS;
    public UInt32 dwFileDateLS;
};

[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct MINIDUMP_MODULE
{
    public UInt64 BaseOfImage;
    public UInt32 SizeOfImage;
    public UInt32 CheckSum;
    public UInt32 TimeDateStamp;
    public uint ModuleNameRva;
    public VS_FIXEDFILEINFO VersionInfo;
    public MINIDUMP_LOCATION_DESCRIPTOR CvRecord;
    public MINIDUMP_LOCATION_DESCRIPTOR MiscRecord;
    public UInt64 Reserved0;
    public UInt64 Reserved1;
}

And the final version of our read methods are:

public MiniDumpModule[] ReadModuleList()
{
    MINIDUMP_MODULE_LIST moduleList;
    IntPtr streamPointer;
    uint streamSize;

    moduleList = this.ReadStream(MINIDUMP_STREAM_TYPE.ModuleListStream, out streamPointer, out streamSize);
    //4 == skip the NumberOfModules field (4 bytes)
    MINIDUMP_MODULE[] modules = ReadArray(streamPointer + 4, (int) moduleList.NumberOfModules);

    List returnList = new List(modules.Select(x => new MiniDumpModule(x, this)));

    return returnList.ToArray();
}

protected unsafe T ReadStream(IntPtr baseOfView, MINIDUMP_STREAM_TYPE streamToRead)
{
    MINIDUMP_DIRECTORY directory = new MINIDUMP_DIRECTORY();
    IntPtr streamPointer = IntPtr.Zero;
    uint streamSize = 0;

    if (!NativeMethods.MiniDumpReadDumpStream(baseOfView, streamToRead, ref directory, ref streamPointer, ref streamSize))
    {
        throw new Win32Exception(Marshal.GetLastWin32Error());
    }

    return (T)Marshal.PtrToStructure(streamPointer, typeof(T));
}

protected internal unsafe string ReadString(uint rva)
{
    try
    {
        byte* baseOfView = null;

        // _mappedFileView is a SafeMemoryMappedViewHandle 
        _mappedFileView.AcquirePointer(ref baseOfView);

        IntPtr positionToReadFrom = new IntPtr(baseOfView + rva);

        // First 32bits is the length field, which is the number of bytes, not number of chars. Divide it by 2 to get number of chars (WCHAR is 2 bytes - unicode)
        int len = Marshal.ReadInt32(positionToReadFrom) / 2;

        // "advance" the pointer 4 bytes (to jump over the "Length" field);
        positionToReadFrom += 4; 

        // Read and marshal the string
        return Marshal.PtrToStringUni(positionToReadFrom, len);
    }
    finally
    {
        _mappedFileView.ReleasePointer();
    }
}

And that’s it. We can now successfully create a memory dump and read module information from it. Next time I’ll put it all together in an application and publish that code.

Posted in Crash Dumps | Tagged , , , | 3 Comments

Reading minidump files, part 2 of 4: Using MiniDumpReadDumpStream

All code is available on my CodePlex project.

In the first post in this series I discussed memory mapped files and how to access them in C#. Now that we have those sorted we can move on to calling MiniDumpReadDumpStream() to read information out of a minidump file.

Here’s a reminder from the last post on what the method signature of

MiniDumpReadDumpStream

looks like (from MSDN):

BOOL WINAPI MiniDumpReadDumpStream(
    _In_ PVOID BaseOfDump,
    _In_ ULONG StreamNumber,
    _Out_ PMINIDUMP_DIRECTORY *Dir,
    _Out_ PVOID *StreamPointer,
    _Out_ ULONG *StreamSize
);
BaseOfDump [in] A pointer to the base of the mapped minidump file. The file should have been mapped into memory using the MapViewOfFile function.
StreamNumber [in] The type of data to be read from the minidump file. This member can be one of the values in the MINIDUMP_STREAM_TYPE enumeration.
Dir [out] A pointer to a MINIDUMP_DIRECTORY structure.
StreamPointer [out] A pointer to the beginning of the minidump stream. The format of this stream depends on the value of StreamNumber. For more information, see MINIDUMP_STREAM_TYPE.
StreamSize [out] The size of the stream pointed to by StreamPointer, in bytes.

To call

MiniDumpReadDumpStream()

we’ll tell it where to read from (BaseOfDump), what we want it to read (StreamNumber) and where we want the read information saved (StreamPointer and StreamSize). Don’t worry about “Dir” for now, we won’t be using it.

I covered BaseOfDump in the previous post so you can read up on it there. For the purposes of this article all we need to know is that PVOID maps to IntPtr in C# (don’t forget I’ve put a page up here with all of the C++/C# type mappings).

We use the second parameter, StreamNumber, to tell MiniDumpReadDumpStream() which stream of information we want to read.

Minidump files contain “streams” of information, similar to tables in a database. We can access the different streams by passing in different values to StreamNumber using the MINIDUMP_STREAM_TYPE enumeration. You’ll recall that when I spoke about MiniDumpWriteDump we had to specify what information to save using the DumpType parameter. Your choice of flags for DumpType will control what streams were saved in the minidump file and thus which ones you can read using StreamNumber. As an example: you can’t read the MINIDUMP_STREAM_TYPE.ThreadInfoListStream stream if you didn’t include MINIDUMP_TYPE.MiniDumpWithThreadInfo in your DumpType parameter.

From an interop point of view StreamNumber is a ULONG which is defined as a “32-bit unsigned integer”. Looking at our C# data types we see uint is also “Unsigned 32-bit integer”, so we’ll use it.

The values you can pass in are defined in the MINIDUMP_STREAM_TYPE enumeration. Here’s my mapped C# version:

public enum MINIDUMP_STREAM_TYPE : uint
{
    UnusedStream = 0,
    ReservedStream0 = 1,
    ReservedStream1 = 2,
    ThreadListStream = 3,
    ModuleListStream = 4,
    MemoryListStream = 5,
    ExceptionStream = 6,
    SystemInfoStream = 7,
    ThreadExListStream = 8,
    Memory64ListStream = 9,
    CommentStreamA = 10,
    CommentStreamW = 11,
    HandleDataStream = 12,
    FunctionTableStream = 13,
    UnloadedModuleListStream = 14,
    MiscInfoStream = 15,
    MemoryInfoListStream = 16,
    ThreadInfoListStream = 17,
    HandleOperationListStream = 18,
    LastReservedStream = 0xffff
}

Before I talk about the next 3 parameters (Dir, StreamPointer and StreamSize) there’s one very important thing to note about all of them: they’re all [Out] pointer parameters. Up until now all of the functions we’ve called have had [In] parameters – they only read values from us. If they returned anything it was a return value. None of them have returned information in their parameters. This time around these parameters will be returning information to us. Well that’s the simple version. I’m not going to go into the differences between out and ref now, if anyone wants details you’re welecome to ask and I’ll try and explain it. For now, suffice to say we need to pass each of the 3 using the ref keyword.

Dir is of type MINIDUMP_DIRECTORY and is a custom DbgHelp structure. It also contains a field of type MINIDUMP_LOCATION_DESCRIPTOR. Here are both of their definitions.

typedef struct _MINIDUMP_LOCATION_DESCRIPTOR {
  ULONG32 DataSize;
  RVA     Rva;
} MINIDUMP_LOCATION_DESCRIPTOR;

typedef struct _MINIDUMP_DIRECTORY {
  ULONG32                      StreamType;
  MINIDUMP_LOCATION_DESCRIPTOR Location;
} MINIDUMP_DIRECTORY, *PMINIDUMP_DIRECTORY;

I’m not going to explain either of them yet, as they’re not important for the moment. As far as mapping the types go: ULONG32 is an unsigned 32 integer (we’ll use UInt32) and RVA (defined in DbhHelp.h line 3697) is a DWORD, so uint for us.

The C# versions are as follows:

public struct MINIDUMP_LOCATION_DESCRIPTOR
{
    public UInt32 DataSize;
    public uint Rva;
}

public struct MINIDUMP_DIRECTORY
{
    public UInt32 StreamType;
    public MINIDUMP_LOCATION_DESCRIPTOR Location;
}

The last 2 parameters, StreamPointer and StreamSize tell us where the information was saved and how many bytes were saved. I’ll explain StreamPointer in more detail next time when I discuss how to interpret the information we get back. For now we just need to know that PVOID maps to IntPtr and ULONG maps to uint.

Here is the final version of our PInvoke mapping for MiniDumpReadDumpStream():

[DllImport("dbghelp.dll", SetLastError = true)]
public static extern bool MiniDumpReadDumpStream(IntPtr BaseOfDump,
        uint StreamNumber,
        ref MINIDUMP_DIRECTORY Dir,
        ref IntPtr StreamPointer,
        ref uint StreamSize);

Next time we’ll invoke the function and read one of the information streams (MINIDUMP_STREAM_TYPE.ModuleListStream)!

Posted in Crash Dumps | Tagged , , , | 9 Comments

Reading minidump files, part 1 of 4: Accessing memory mapped files from C#

UPDATE: I’m looking into using SafeMemoryMappedViewHandle as the return value for MapViewOfFile() instead of IntPtr. Either will work, but since Microsoft provides a class to specifically wrap memory mapped view handles I thought I’d have a look at using it. I’ll report later on what my preference ends up being.

All code is available on my CodePlex project.

In my previous post I explained how to use PInvoke to call MiniDumpWriteDump in order to create minidump files. Now it’s time to start reading data out of them. I’m going to break this topic into a few posts as this is the first time we’re going to be reading data and there is quite a bit to cover. I’ll start with the mechanics of opening the file and creating a memory mapped view of it. Following that I’ll talk about the actual read function. Next I’ll talk about how to interpret the data you read and finally I’ll put it all together in an application. Once we’ve successfully completed our first read the rest will follow easily and with much less effort.

In my previous post I mentioned the DumpType parameter of the MiniDumpWriteDump function and how we would use that parameter to determine which information was saved into our minidump. Using MiniDumpReadDumpStream we can now choose which of those pieces of information we want to read out of the minidump.

The method signature of MiniDumpReadDumpStream is as follows (from MSDN):

BOOL WINAPI MiniDumpReadDumpStream(
    _In_ PVOID BaseOfDump,
    _In_ ULONG StreamNumber,
    _Out_ PMINIDUMP_DIRECTORY *Dir,
    _Out_ PVOID *StreamPointer,
    _Out_ ULONG *StreamSize
);
BaseOfDump [in] A pointer to the base of the mapped minidump file. The file should have been mapped into memory using the MapViewOfFile function.
StreamNumber [in] The type of data to be read from the minidump file. This member can be one of the values in the MINIDUMP_STREAM_TYPE enumeration.
Dir [out] A pointer to a MINIDUMP_DIRECTORY structure.
StreamPointer [out] A pointer to the beginning of the minidump stream. The format of this stream depends on the value of StreamNumber. For more information, see MINIDUMP_STREAM_TYPE.
StreamSize [out] The size of the stream pointed to by StreamPointer, in bytes.

Simply put: we tell the function where to read from (BaseOfDump), what we want it to read (StreamNumber) and where we want the read information put (StreamPointer and StreamSize). Don’t worry about “Dir” for now, we won’t be using it.

For the rest of this post I’m going to talk about the BaseOfDump parameter as this is the whole reason we need to talk about mapped file views in the first place.

You’ll see from the MSDN description of the BaseOfDump parameter that it’s a pointer to the memory mapped view of the file. What does a memory mapped file do? It lets us read a portion (or all) of a file as if it were a block of memory in our address space. So our code will read the file as if it were a piece of memory and not a file on the disk. Another way to about it is that we’ll using memory functions to read data, not file I/O functions.

To create a memory mapped file we’ll: open a file, create a mapping using CreateFileMapping() and then put a view onto the mapping using MapViewOfFile().

The .Net Framework actually provides a wrapper around the CreateFileMapping() and MapViewOfFile() calls. You can use MemoryMappedFile.CreateFromFile() to create a MemoryMappedFile and then use MemoryMappedFile.CreateViewAccessor() to get a MemoryMappedViewAccessor.

Using these classes would make life a lot easier for us as all of the PInvoke hard work has already been done. The only problem is that neither provides us with access to the address the file was mapped to. The MemoryMappedViewAccessor only provides Read() and Write() methods to access the view and since we’re not the ones doing the reading (MiniDumpReadDumpStream() is) that doesn’t really help us. MemoryMappedFile does however provide a handle to the file mapping that it created so we’ll use that and call the unmanaged MapViewOfFile() ourselves; at least we save a bit of work.

Given that let’s figure out how to call MapViewOfFile() from C#. Here’s the method signature from MSDN:

LPVOID WINAPI MapViewOfFile(
  _In_  HANDLE hFileMappingObject,
  _In_  DWORD dwDesiredAccess,
  _In_  DWORD dwFileOffsetHigh,
  _In_  DWORD dwFileOffsetLow,
  _In_  SIZE_T dwNumberOfBytesToMap
);

Before I continue: I’ve create a page that I’ll use to keep track of all of the C++/C# type mappings for future use. You can access it here.

First up is the LPVOID return type. This is a pointer type so we use IntPtr in C#.

The first parameter is hFileMappingObject. This is a HANDLE which we know from last time is an IntPtr (or SafeHandle if possible). We’ll be using MemoryMappedFile.SafeMemoryMappedFileHandle to get access to the handle of the file mapping, so we’ll use SafeHandle.

Next up is dwDesiredAccess. This is a DWORD which we also used last time; the equivalent in C# is uint. That part was easy; figuring out what value to pass in is a bit more challenging. You’ll notice from the MSDN entry that they tell you exactly what the possible options are e.g. FILE_MAP_ALL_ACCESS, FILE_MAP_COPY etc. The only problem is that they don’t say what the value of any of the options are, only what they are called .This is because these are all defined in the C++ header files. If you were calling this function from C++ you wouldn’t care what the value is, you only need to know what it’s called. We’re doing all of this in C# though, which means we don’t have access to those header files from our code, so we’ll need to find the definition in the header file and redefine it in our C# code.

If you need to find something in a C++ header file, you can either search through the files in the header files folder (“C:\Program Files (x86)\Windows Kits\8.0\Include\um” on my machine) or keep a “spare” C++ console app project on the side and just use the Visual Studio “Go to definition” command to find it. I started out just searching through the header files on disk, but I’ve switched to using the “Go to definition” command now as its much quicker and easier.

Looking at the options for dwDesiredAccess we can see that the option we need is FILE_MAP_READ. This is defined in “memoryapi.h” (line 49) as “SECTION_MAP_READ”. SECTION_MAP_READ in turn is defined in “winnt.h” (line 11500) as “0x0004” (you can see the value of “Go to definition” now – most types/defines end up as alias’s to other ones).

Here is the end result of the mapping:

public const uint STANDARD_RIGHTS_REQUIRED = 0x000F0000;
public const uint SECTION_QUERY = 0x0001;
public const uint SECTION_MAP_WRITE = 0x0002;
public const uint SECTION_MAP_READ = 0x0004;
public const uint SECTION_MAP_EXECUTE = 0x0008;
public const uint SECTION_EXTEND_SIZE = 0x0010;
public const uint SECTION_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | 
    SECTION_QUERY |
    SECTION_MAP_WRITE |
    SECTION_MAP_READ |
    SECTION_MAP_EXECUTE |
    SECTION_EXTEND_SIZE);

public const uint FILE_MAP_COPY = SECTION_QUERY;
public const uint FILE_MAP_WRITE = SECTION_MAP_WRITE;
public const uint FILE_MAP_READ = SECTION_MAP_READ;
public const uint FILE_MAP_EXECUTE = SECTION_MAP_EXECUTE;
public const uint FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS;

Following dwDesiredAccess we have dwFileOffsetHigh and dwFileOffsetLow. Both are DWORD’s so in C# they’re both uint’s. Our view starts at the beginning of the file, so there is no offset and we set both of these to 0.

Finally we have dwNumberOfBytesToMap which is a SIZE_T. SIZE_T is defined here as a ULONG_PTR which is in turn defined as a __int3264. As you can see from the documentation __int3264 varies depending on the platform you’re using: 32-bits if you’re executing in 32bit mode, 64-bits otherwise. We’ll use IntPtr for our C# call as it is also platform specific i.e. either 32 bits or 64 bits.

Our parameters now look like this:

Parameter Type Parameter Name Description C# Type
LPVOID return type pointer IntPtr
HANDLE hFileMappingObject void* IntPtr or SafeHandle
DWORD dwDesiredAccess unsigned 32-bit integer UInt
DWORD dwFileOffsetHigh unsigned 32-bit integer UInt
DWORD dwFileOffsetLow unsigned 32-bit integer UInt
SIZE_T dwNumberOfBytesToMap 32-bit or 64-bit integer depending on execution environemtn IntPtr

Our method signature now looks like this:

IntPtr MapViewOfFile(SafeHandle hFileMappingObject, 
    uint dwDesiredAccess, 
    uint dwFileOffsetHigh, 
    uint dwFileOffsetLow, 
    IntPtr dwNumberOfBytesToMap)

Adding our DllImport attribute we end up with the final method:

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr MapViewOfFile(
	SafeHandle hFileMappingObject,
	uint dwDesiredAccess,
	uint dwFileOffsetHigh,
	uint dwFileOffsetLow,
	IntPtr dwNumberOfBytesToMap);

There’s one very important thing to take note of before going on: cleaning up after ourselves! I mentioned previously that there is no magic .Net garbage collection in the unmanaged world and this is a perfect example of that. We called the unmanaged function MapViewOfFile to map a view for us. This call allocated resources and it’s up to us to free those resources when we’re done using them. So once we’re done using the view we need to close it using UnmapViewOfFile:

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool UnmapViewOfFile(IntPtr lpBaseAddress);

With that done we now have access to a memory mapped view of our minidump file. In the next part I’ll talk about invoking MiniDumpReadDumpStream to read some data.

Posted in Crash Dumps | Tagged , , , | 4 Comments

Getting started with PInvoke: calling MiniDumpWriteDump to create minidumps

In my last post I briefly touched on what information is contained inside a minidump and the use of MiniDumpWriteDump to create your own dumps. In this post I’m going to elaborate on both of those and provide some code on how to call MiniDumpWriteDump.

The functions needed to interact with minidumps (and other debug data e.g. symbol files) are contained in the Debug Help Library (DbgHelp.dll). If you’re using C++ you can access these functions by simply including “DbgHelp.h”. Since I want to do this all in C# we’ll need to use PInvoke to access the DbgHelp functions (as DbgHelp.dll is unmanaged code i.e. a native library, not .Net).

When accessing unmanaged code there are 2 main pieces of information you need to know: the signature of the method you want to call and the file/dll that implements the function. This information is all available from the MSDN library.

If you look at the MSDN entry for MiniDumpWriteDump, you’ll see the method signature is defined as follows (just to state the obvious this is C++):

BOOL WINAPI MiniDumpWriteDump(
_In_ HANDLE hProcess,
_In_ DWORD ProcessId,
_In_ HANDLE hFile,
_In_ MINIDUMP_TYPE DumpType,
_In_ PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
_In_ PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
_In_ PMINIDUMP_CALLBACK_INFORMATION CallbackParam
);

Towards the bottom of the page you’ll see the header file it’s declared in as well as the dll that implements it.

A quick side note – if you ever need to call any unmanaged code a good starting point is to search for the C# method signature at www.pinvoke.net. The library there is quite extensive, but it doesn’t contain everything you’ll look for. The DbhHelp functions are quite niche, so you’ll have mixed luck finding them. It turns out that MiniDumpWriteDump is actually on PInvoke (http://www.pinvoke.net/default.aspx/dbghelp/MiniDumpWriteDump.html), but I’ll take you through the steps of creating the signature so that you’ll be able to do it for yourself in future.

In order to use MiniDumpWriteDump from C# we’ll need to define a C# method that matches the method signature I mentioned above; so we need to match C# data types with the C/C++ data types. We also have to take into account whether the parameters are [In], [Out] or [In, Out]. For now all of the parameters are [In], so I’ll save that topic for another day. Once we’ve mapped the data types we then tell the .Net runtime that we won’t be defining the body of the method, it’ll be defined somewhere other than our code. After that you can try calling the function and see if you mapped everything correctly. Be prepared for a few crashes 😉

Mapping types between C++ and C# can be… challenging at times, but plenty of people have done it already so if you ever get stuck it’ll just take a bit of googling to fix your problem.

The first thing you need to know is what the definition of the C++ types are, you can find that here. Here’s a matching page for C# types.

First up on our list is the return type: “BOOL”. This one is easy: C++ BOOL maps to C# bool.

Next up is “hProcess” which is a HANDLE. This type is a core type in the Win32 API and is used throughout Win32 programming. The easiest way to describe it, is that it’s a reference to some kind of resource. It could reference a file, printer, bitmap, device context, font etc… it’s a long list. The important thing to note is that it’s a “reference to a resource”. That resource has memory associated with it and it’s up to you to make sure that you release that memory/handle when/if needed – there’s no magic .Net garbage collection in the unmanaged world. You can see from the link that HANDLE is actually a “void*” (in C++ you can declare typedefs, where one type is essentially an alias to another). So HANDLE is actually a pointer to a void. Previously we would use the C# type IntPtr to map to a HANDLE, but we now also have the option of using the SafeHandle class when possible (I’ll talk about the “when possible” part later).

Following “hProcess” is “ProcessId” which is a “DWORD”. The definition for DWORD says: “A DWORD is a 32-bit unsigned integer (range: 0 through 4294967295 decimal)”. We need to look for a matching C# type in our reference. DWORD is an integer type, so go to the “Integral Types Table”. Looking through that table we see that “uint” is an unsigned 32-bit integer, so that’s our match for a DWORD in C++.

I’m going to skip “hFile” since we’ve already covered handles.

After “hFile” we have “DumpType” which is of type “MINIDUMP_TYPE”. You won’t find MINIDUMP_TYPE in our list of Windows Data Types as it’s not a Windows Data Type, it’s a custom type specific to DbgHelp. If we look it up in MSDN we see that it’s actually an enum. Converting enums between C++ and C# is easy, they’re pretty much exactly the same. From the MSDN entry for MINIDUMP_TYPE we see it’s declared as follows:

typedef enum _MINIDUMP_TYPE {
MiniDumpNormal = 0x00000000,
MiniDumpWithDataSegs = 0x00000001,
//...
} MINIDUMP_TYPE;

In C# we have:

public enum MINIDUMP_TYPE
{
MiniDumpNormal = 0x00000000,
MiniDumpWithDataSegs = 0x00000001,
//...
}

As I said: almost exactly the same.

I’m not going to talk about the next 3 parameters as I don’t think many people will actually use them. Technically we should use ExceptionParam, but for now I’m going to leave it out. The quick version is: they’re structures, which means they’ll marshal as pointers, so we’ll just use IntPtr as a substitute for them. One thing to note here: it is absolutely vital that your C# data types are the same size as the C++ data types e.g. DWORD is 32-bits (4 bytes) so whatever C# type you use it has to, at the very least, be 32-bits (4 bytes) also. We used UInt as it is 32-bits. Technically we could have used Int32 also, since it’s also 32 bits. But Int32 is signed whereas UInt isn’t, so while they’re the same size, they have different meanings.

Given all that, here’s where what our parameter mapping looks like:

Parameter Type Parameter Name Description C# Type
BOOL return type Boolean bool
HANDLE hProcess void* IntPtr or SafeHandle
DWORD unsigned 32-bit integer UInt
MINIDUMP_TYPE DumpType enum enum
PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam custom structure IntPtr
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam custom structure IntPtr
PMINIDUMP_CALLBACK_INFORMATION CallbackParam custom structure IntPtr

And this is what our C# function currently looks like:

bool MiniDumpWriteDump(IntPtr hProcess, UInt ProcessId, SafeHandle hFile, MINIDUMP_TYPE DumpType, IntPtr ExceptionParam, IntPtr UserStreamParam, IntPtr CallbackParam);

Now that we know what the C# method signature looks like we have to tell the C# compiler that this function is not implemented in our code. In C++ this is called a forward declaration: you’re telling the compiler that the function will exist somewhere, just not necessarily in our code and not at compile time. It should just carry on as if the function were there and the actual implementation will be resolved later. We do this in C# using 2 things: the extern keyword and the DllImport attribute.

The extern keyword tells the compiler that the function is implemented externally i.e. it’s not part of our code, we’re merely calling it from somewhere else. Your method has to be “static” when using “extern”.

The DllImport attribute lets us specify some details about where the function is implemented and some options to use when calling it. There is one very important property that you need to know about: SetLastError.

SetLastError defaults to false. If the function you are going to call will call the Win32 SetLastError() function, you need to set SetLastError=true. If you look at the “Return Value” section in the MSDN documentation for MiniDumpWriteDump you’ll notice they say that if the function returns FALSE then you should call GetLastError() to get the error code. This means we need to set SetLastError=true so that we can retrieve the error code from our C# code. I’ll show you how later.

While I’m mentioning SetLastError, have a look at PreserveSig also. We don’t need to worry about it now, but it’s important to understand for future use.

For now we just need to specify the name of the dll where the function can be found i.e. “dbghelp.dll” and SetLastError=true.

Our method now looks like this:

[DllImport(“dbghelp.dll”, SetLastError=true)]
static extern bool MiniDumpWriteDump(SafeHandle hProcess, UInt ProcessId, SafeHandle hFile, MINIDUMP_TYPE DumpType, IntPtr ExceptionParam, IntPtr UserStreamParam, IntPtr CallbackParam);

And that’s it, we’re good to go! Let’s try calling it now.

In order to call it we need to provide values for the following parameters:

Parameter Name Description
hProcess A handle to the process for which the information is to be generated.
ProcessId The identifier of the process for which the information is to be generated.
hFile A handle to the file in which the information is to be written.
DumpType The type of information to be generated. This parameter can be one or more of the values from the MINIDUMP_TYPE enumeration.

I decided to display a list of processes and let the user pick which one they wanted to create a minidump for. At first I was going to use the Win32 EnumProcesses to get a list of running processes, but then I remembered that .Net already has a Process class, which in turn has a method called GetProcesses() that you can use to list all processes on the local system. You can then use the Handle and Id properties which take care of the hProcess and ProcessId parameters respectively.

The last 2 parameters we need are hFile and DumpType. Both of those are up to us. hFile is a handle to a file we opened/created to save the dump to, and DumpType is the information you want saved.

You can use File.Create() to create a FileStream and then use it’s SafeFileHandle property for hFile.

DumpType is up to you; just use one or any combination of options from the enum.

With that done you’re good to go. I won’t release full code for the example this time as I’ve already worked ahead on starting to read the contents of minidumps. But here’s a quick peak at what it looks like:

[DllImport("DbgHelp.dll", SetLastError=true)]
public extern static bool MiniDumpWriteDump(
    IntPtr hProcess,
    UInt32 ProcessId,
    SafeHandle hFile,
    MINIDUMP_TYPE DumpType,
    IntPtr ExceptionParam,
    IntPtr UserStreamParam,
    IntPtr CallbackParam);

public enum MINIDUMP_TYPE
{
    MiniDumpNormal = 0x00000000,
    MiniDumpWithDataSegs = 0x00000001,
    //...
    MiniDumpWithFullAuxiliaryState = 0x00008000
}

using (FileStream crashDumpFileStream = File.Create(captureArguments.FilePath))
{
    bool success = NativeMethods.MiniDumpWriteDump(
        captureArguments.ProcessHandle,
        (uint)captureArguments.ProcessId,
        crashDumpFileStream.SafeFileHandle,
        captureArguments.MiniDumpType,
        IntPtr.Zero,
        IntPtr.Zero,
        IntPtr.Zero);

    if (!success)
    {
        int lastError = Marshal.GetLastWin32Error();

        // Neat way to avoid the pain of calling FormatMessage.
        // You can create a new instance of Win32Exception without calling GetLast*Error first,
        // but I prefer this way as it's more obvious what's happening
        Win32Exception lastErrorException = new Win32Exception(lastError);

        MessageBox.Show(lastErrorException.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}


Next time I’ll start talking about how to read the contents of minidumps.

Posted in Crash Dumps | Tagged , , | 1 Comment

What is a minidump and what can I do with it?

I thought that before I talk about how to analyze minidumps I should probably spend some time talking about what they are, how you get them and what can you do with them. I’m going to keep this fairly simple and high level, so those of you who already have a good understanding of crash dumps might want to skim this post. If anyone is interested in more detail they can post a comment and I’ll elaborate where I can.

The easiest way to describe a minidump is that it is a snapshot of the state of an application at a given point in time. They can be capture automatically or manually and depending on the problem you are trying to solve they can be captured at different points in time. If an application is crashing unexpectedly then the minidump will probably (or rather hopefully!) be captured automatically when the crash occurs. Crashing applications can also create their own crash dumps e.g. the Firefox crash reporter. If an application is making excessive use of the cpu then you would normally capture one manually while the excessive usage is occurring. The same strategy would work if you’re trying to solve a problem with excessive memory usage. Solving memory leaks can sometimes be a bit more complicated: you can either wait for the leak to consume enough memory and then capture a minidump, or you’ll have to create a few crash dumps at regular intervals and then look for differences within them.

I found the easiest way to capture minidumps manually was to use WinDbg (part of the Debugging Tools for Windows). The Debugging Tools also include command line applications, but I never looked at them. Once you’ve got the tools installed simply open WinDbg, attach to the offending process (selecting the “Non Invasive” option) and running the dump command e.g. “.dump /map c:\Minidump1.hdmp” (I’ll talk about the “/map” option later). Some things to note here:

  • Once you attach WinDbg to your process, the process will be paused. So if you’re doing this in a production environment it’s best to be as quick as possible 😉 Even so, it’s still a pretty quick process (mine used to take around half a minute to create a 600MB crash dump) and is well worth it if it means you can solve a critical problem.
  • The tools need to be installed on the machine where the minidump is going to be captured. The installation doesn’t “mess” with your system, but depending on how open minded your sys admin is you might have problems here.
  • Using the “/map” option will result in a pretty big file on disk (mine used to be around 600MB). More on this later though

Don’t forget to “Detach” afterwards! That’s “Detach” not “Stop Debugging”!

So WinDbg is a nice and easy way to capture a crash dump manually (and a very powerful tool to analyze it!). But what happens when your process crashes unexpectedly? There are actually a few options here, some dependent on what version of Windows you’re running.

Besides WinDbg (and a few other tools), the Debugging Tools for Windows also includes a script you can use to automatically collect crash dumps when your application crashes. It’s called ADPlus. I’ve never used it, so I can’t say much about it, but I have heard about it quite often. Having read that link I see it’s actually been rewritten recently. I’ll have to find out more about that, could prove interesting.

I relied on Dr Watson (we were using Windows 2003 – old school!) to capture crash dumps when our process crashed. Those crash dumps used to be saved somewhere in the “c:\Windows\PCHEALTH” folder (inside .CAB files if I remember correctly, go have a look at yours, you might be surprised to see what’s there).

In the more recent versions of Windows Dr Watson has been replaced with Windows Error Reporting (WER). I haven’t used this much yet, but it seems like saving crash dumps is actually disabled by default. If you want to change this, then read this article on MSDN.

These days you can even create a crash dump right from the Task Manager: just right click a process and select “Create dump file”. You don’t get to select what information to include in the file though.

Before I talk about what’s inside minidumps here’s a quick exercise for you. Open a command prompt and browse to “%appdata%”, then run “dir *.dmp /s”. I get 14 results, mostly from Firefox crash reports. Those are crash dumps! If you have ones from Firefox do you notice how small they are? I don’t have any that even reach 500KB. Now try running that same “dir *.dmp /s” command in your windows folder. I find a 500MB file called “memory.dmp” in my “c:\Windows” folder. You can try using “dir *.hdmp /s” also, you might get some hits there.

You can see from the samples I found on my local drive that the size of crash dumps can vary dramatically: anything from 500KB to 500MB in my case. This is because minidumps can store various different sets of information. The more information you store the bigger they get. The Firefox ones are quite small, so they probably just store enough information to reconstruct a call stack of running threads. The “memory.dmp” one probably contains the full user space memory of the process, loaded modules, thread information, etc. I’m just guessing here, but in the next few posts I’ll be releasing some code that will allow us to look inside those crash dumps and see what information they contain (as well as some code to capture your own).

When I mention using WinDbg earlier to manually capture a crash dump I said to run the “.dump” command with “/map” as its options, this is what those options mean (from the “Debugging Help” file):

  • m – Create a minidump
  • a – Creates a minidump with all optional additions. The /ma option is equivalent to /mfFhut — it adds full memory data, handle data, unloaded module information, basic memory information, and thread time information to the minidump. Any failure to read inaccessable memory results in termination of the minidump generation.
  • p – Adds process environment block (PEB) and thread environment block (TEB) data to the minidump. This can be useful if you need access to Windows system information regarding the application’s processes and threads.

So I’m basically saying: create a crash dump of everything, or at least very close to everything 🙂

I’m not going to go into the detail of what all of the options are: if you want to know what they are you can open the “Debugging Help” file that gets installed with the Debugging Tools and browse to Windows Debugging\Debugger Reference\Debugger Commands\Meta-Commands in the contents. There is a lot of useful information in that help file.

What I do want to point out though is the description of the “a” option and just how many different pieces of information can be stored in a minidump file, and that’s not even the full list.

In the next post I’ll start talking about how we can use MiniDumpWriteDump to create our own crash dumps with whatever information we want (with some actual code!) and then how we can start reading them (with even more code!)

Posted in Crash Dumps | Tagged , , | Leave a comment