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.

Advertisements
This entry was posted in Crash Dumps and tagged , , . Bookmark the permalink.

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s