Minidump Explorer v0.3 released

I’ve released a new version of Minidump Explorer on CodePlex. You can find the download here.

Included in this release:

Write-ups on each stream will follow soon.

Posted in Crash Dumps | Tagged | Leave a comment

Minidump Explorer v0.2: Reading minidump ThreadListStream

Version 0.2 of Minidump Explorer included 4 new data streams: MemoryListStream, Memory64ListStream, HandleDataStream and ThreadListStream. These are all fairly simple streams to read and use but 3 of them are going to be vitally important when we start hooking into CorDebug: MemoryListStream, Memory64ListStream and ThreadListStream. I spoke about the 2 memory list streams last time. This time I’ll talk about the ThreadListStream.

ThreadListStream

First up lets have a look at the structures we’ll be using when reading MemoryListStream:

typedef struct _MINIDUMP_THREAD_LIST {
  ULONG32         NumberOfThreads;
  MINIDUMP_THREAD Threads[];
} MINIDUMP_THREAD_LIST, *PMINIDUMP_THREAD_LIST;

typedef struct _MINIDUMP_THREAD {
  ULONG32                      ThreadId;
  ULONG32                      SuspendCount;
  ULONG32                      PriorityClass;
  ULONG32                      Priority;
  ULONG64                      Teb;
  MINIDUMP_MEMORY_DESCRIPTOR   Stack;
  MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
} MINIDUMP_THREAD, *PMINIDUMP_THREAD;

There’s no need to discuss MINIDUMP_THREAD_LIST as it’s quite self explanatory and we’ve seen it previously when reading the ModuleListStream and memory streams. Our interest is in the MINIDUMP_THREAD structure.

I haven’t really needed to use most of the fields provided by MINIDUMP_THREAD, so I won’t be going into too much detail about most of them for now. I will provide references to extra information just in case they’re of interest to you.

The first 4 fields provide fairly basic thread info: it’s id, how many times it has been suspended and it’s priority class and priority. The Id is self-explanatory. This one is obviously quite important. I haven’t needed to use the suspend count and priority fields yet. You can find more information about the suspend count by looking at the documentation for SuspendThread and ResumeThread. Simply put: it’s a count of how many times the thread has been suspended. If the count is greater than 0 then the thread has been suspended and will not run. Each call to SuspendThread and ResumeThread increases and decreases the count respectively. Once the count reaches 0 the thread is allowed to run again.

There’s a detailed write up on the priority fields here. The documentation is clear enough (mostly), but I looked at a sample crash dump and I couldn’t tie the priorty/priority class I saw back to the documentation.

The last 3 fields are where things start to get interesting.

Teb. This is the “thread environment block”. This contains very low level information about a thread and as you can see from the documentation it can change between different versions of Windows.

Stack. I mentioned in a previous post that the minidump API (or rather the DbgHelp API) only provides methods to read the raw data contained in a minidump. Well here’s a good example of that. The Stack field tells us where the data for the stack of the thread is located, and how big it is, but it doesn’t provide a way to decode the information contained there. If you want to make sense of the data you have to go through the stack frames one by one and piece the information together yourself. That’s quite a daunting task. This where the CorDebug API comes in: it’ll reconstruct the stack for us. It does still leave some work for us to do, but it’s a lot better that piecing it together ourselves. Suffice it to say that I haven’t found a reason to use this field yet.

Context. This field points to the location in the crash dump where the context information of the thread can be found. This is also very low level thread information e.g. the value of the cpu registers, etc. The explanation about the Stack field applies here also: you can access the raw context data, but decoding it is up to you. Luckily I haven’t needed to get into the details of the context structure; all CorDebug needs is the raw data, it’ll figure the rest out itself.

Show me the code

I won’t go through the all of the field types individually as they’re all types I have covered previously. The definitions for MINIDUMP_MEMORY_DESCRIPTOR and MINIDUMP_LOCATION_DESCRIPTOR were covered when I discussed reading the two memory streams.

[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct MINIDUMP_THREAD_LIST
{
    public UInt32 NumberOfThreads;
    public IntPtr Threads; // MINIDUMP_THREAD[] 
}

[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct MINIDUMP_THREAD
{
    public UInt32 ThreadId;
    public UInt32 SuspendCount;
    public UInt32 PriorityClass;
    public UInt32 Priority;
    public UInt64 Teb;
    public MINIDUMP_MEMORY_DESCRIPTOR Stack;
    public MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
}

As far as reading the stream: you’ll follow the same steps as we did when reading the ModuleListStream. You can find the full source code on my CodePlex project (I’ve made a few small updates since the original article).

That’s it for the ThreadListStream. Other than the Id and Context fields there’s not much I’ll be using from this stream. Those 2 fields are vital though!

Next time: the HandleDataStream.

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

Minidump Explorer v0.2: Reading minidump MemoryListStream and Memory64ListStream

Version 0.2 of Minidump Explorer included 4 new data streams: MemoryListStream, Memory64ListStream, HandleDataStream and ThreadListStream. These are all fairly simple streams to read and use but 3 of them are going to be vitally important when we start hooking into CorDebug: MemoryListStream, Memory64ListStream and ThreadListStream. The 2 memory list streams will naturally give us access to some, or all, of the memory of the crashed process, while the thread list stream, amongst other things, give us access to the thread’s Context information. The handle data is interesting, but not essential at this point in time.

MemoryListStream and Memory64ListStream

MemoryListStream and Memory64ListStream provide you with a list of memory regions that are contained in the crash dump. The difference between the two is that Memory64ListStream is used for full-memory dumps, while MemoryListStream is used when only partial memory is available. You can see the difference when you look at the declaration of the structures they return:

MemoryListStream (C++)

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

typedef struct _MINIDUMP_MEMORY_DESCRIPTOR {
  ULONG64                      StartOfMemoryRange;
  MINIDUMP_LOCATION_DESCRIPTOR Memory;
} MINIDUMP_MEMORY_DESCRIPTOR, *PMINIDUMP_MEMORY_DESCRIPTOR;

typedef struct _MINIDUMP_MEMORY_LIST {
  ULONG32                    NumberOfMemoryRanges;
  MINIDUMP_MEMORY_DESCRIPTOR MemoryRanges[];
} MINIDUMP_MEMORY_LIST, *PMINIDUMP_MEMORY_LIST;

If you look at MINIDUMP_MEMORY_LIST you’ll notice that it contains an array of MINIDUMP_MEMORY_DESCRIPTOR’s (MemoryRanges). Each MINIDUMP_MEMORY_DESCRIPTOR represents a region of memory included with the minidump. It contains the starting address of the region of memory represented (StartOfMemoryRange) and a MINIDUMP_LOCATION_DESCRIPTOR (Memory) indicating how big the region is and where in the minidump file to find it. What’s important to note here, is that each region of memory could be in a different physical location inside the minidump file. Because of this each MINIDUMP_LOCATION_DESCRIPTOR has an Rva field which you need to use to find the correct location in the minidump to read from. Full memory dumps are different: the memory is all stored in one sequential block at the end of the dump. As a result you don’t need individual RVA’s for each region. You can see the difference here:

Memory64ListStream (C++)

typedef struct _MINIDUMP_MEMORY_DESCRIPTOR64 {
    ULONG64 StartOfMemoryRange;
    ULONG64 DataSize;
} MINIDUMP_MEMORY_DESCRIPTOR64, *PMINIDUMP_MEMORY_DESCRIPTOR64;

typedef struct _MINIDUMP_MEMORY64_LIST {
    ULONG64 NumberOfMemoryRanges;
    RVA64 BaseRva;
    MINIDUMP_MEMORY_DESCRIPTOR64 MemoryRanges [0];
} MINIDUMP_MEMORY64_LIST, *PMINIDUMP_MEMORY64_LIST;

You’ll notice that MINIDUMP_MEMORY64_LIST also has an array of descriptors (MINIDUMP_MEMORY_DESCRIPTOR64). The difference here is that MINIDUMP_MEMORY_DESCRIPTOR64 doesn’t include a location descriptor as MINIDUMP_MEMORY_DESCRIPTOR did. This is as a result of all of the memory being in one block at the end of the minidump: you don’t need individual RVA’s for each block since they all follow each other starting from MINIDUMP_MEMORY64_LIST.BaseRva.

Reading memory data from a minidump

So how do you go about reading from a location in memory?

If you have a crash dump containing partial memory (MINIDUMP_MEMORY_LIST) you would loop through each MINIDUMP_MEMORY_DESCRIPTOR and check for a region containing the address you were looking for: (myReadAddress >= StartOfMemoryRange) && (myReadAddress < (StartOfMemoryRange + Memory.DataSize)). If you find a matching MINIDUMP_MEMORY_DESCRIPTOR you would then add it’s Memory.Rva field (from MINIDUMP_LOCATION_DESCRIPTOR) to the address of the minidump file mapping in order to get the physical location to read from.

Reading from MINIDUMP_MEMORY64_LIST is a bit different. You would still loop through each MINIDUMP_MEMORY_DESCRIPTOR64 looking for the region that holds the address you want to read from, but the difference is in how you read the data once you’ve found the correct region. Since a full-memory dump has all of the memory stored sequentially at the end of the dump file there is only one RVA and that RVA points to the beginning of the memory data inside the minidump. In order to read the actual memory you need to keep a running total of the DataSize of each MINIDUMP_MEMORY_DESCRIPTOR64 that precedes the one that you need and add that to the BaseRva. Then add that to the address of the memory mapped file of the crash dump. So the end result logic would look similar to this:

// addressOfBlockToReadFrom is the address in the minidump file of 
// the start of the block you want to read from.
long addressOfBlockToReadFrom = memoryMappedFileAddress + memory64List.BaseRva + allPreceedingDataSizes;

// offsetToReadFrom is the offset from the beginning of the 
// block that you want to read from.
// e.g. if you want to read from 0x23 and the block starts 
// at 0x20 then the offset is 0x3.
long offsetToReadFrom = addressIWantToReadFrom - blockToReadFrom.StartOfMemoryRange;

// addressToReadFrom is the physical address in the minidump file
// where you should start reading from.
long addressToReadFrom = addressOfBlockToReadFrom + offsetToReadFrom;

Show me the code

I won’t go through the all of the field types individually as they’re all types I have covered previously. The only new one is RVA64 which is a ULONG64 and translates to a UInt64 in c#.

MemoryListStream (C#)

[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct MINIDUMP_LOCATION_DESCRIPTOR
{
    public UInt32 DataSize;
    public uint Rva;
}

[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct MINIDUMP_MEMORY_DESCRIPTOR
{
    public UInt64 StartOfMemoryRange;
    public MINIDUMP_LOCATION_DESCRIPTOR Memory;
}

[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct MINIDUMP_MEMORY_LIST
{
    public UInt32 NumberOfMemoryRanges;
    public IntPtr MemoryRanges; // MINIDUMP_MEMORY_DESCRIPTOR[]
}

Memory64ListStream

[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct MINIDUMP_MEMORY_DESCRIPTOR64
{
    public UInt64 StartOfMemoryRange;
    public UInt64 DataSize;
}

[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct MINIDUMP_MEMORY64_LIST
{
    public UInt64 NumberOfMemoryRanges;
    public UInt64 BaseRva;
    public IntPtr MemoryRanges; // MINIDUMP_MEMORY_DESCRIPTOR64[]
}

As far as reading the streams: you’ll follow the same steps as we did when reading the ModuleListStream. You can find the full source code on my CodePlex project (I’ve made a few small updates since the original article).

That’s it for the memory streams, next time I’ll cover the ThreadListStream.

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

Minidump Explorer v0.2 released

I’ve released a new version of Minidump Explorer on CodePlex. You can find the download here.

Included in this release:

Write-ups on each stream will follow soon :)

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

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 , , , | Leave a comment