Decoding the parameters of a thrown C++ exception (0xE06D7363)

old question and a very late answer (question popped up in active list so replying)

the gist of raymond chen and valdos answer in a consice script

0:000> dt _s_throwinfo pCatchableTypeArray[0]->arrayOfCatchableTypes->pType->name  @@c++(( (ntdll!_EXCEPTION_RECORD *) @@masm(@esp+4) )->ExceptionInformation[2])
cppexept!_s_ThrowInfo
   +0x00c pCatchableTypeArray                                        : [0] 
      +0x004 arrayOfCatchableTypes                                      : [0] 
         +0x004 pType                                                      : 
            +0x008 name                                                       : [0]  ".PAD"

There're many technical details involved. I can give you the direction.

The 2nd exception parameter (0052ccd8) is a pointer to a _s__ThrowInfo structure, which describes the thrown type. The 3rd parameter (564099d8) is a pointer to the thrown object.

First let's discuss the thrown object type. The _s__ThrowInfo points to a constant structure (generated at the compile-time), which resides within your executable (EXE or DLL), which is mapped into the process address space.

If the global memory is included in your crash dump - then you can find it there. Otherwise you may deduce it from the executable. Subtract the "base" address from your executable (assuming it was loaded at its preferred address), and you'll get the offset of this structure within your executable.

Decoding the actual type from this structure is kind tricky. It includes the information about types it may be cast to (C++ polymorphism), plus the d'tor (destructor) in case it's a non-trivial type (with non-trivial d'tor) and it was thrown by-value. The table of types it may be cast to contain pointers to the appropriate structures describing those types. Among other things there are textual "encodings" of those types.

Information about layout of those structures may be found here:

Next, the thrown object. Its address usually belongs to the stack memory (strictly speaking this is not mandatory, one may throw either global or dynamically-allocated(on-heap) object. But this is usually not the case). If you have the stack included in your crash dump - you'll see the object layout. Coupled with the type you'll (hopefully) realize what it means.

If you don't have the stack memory included in your crash dump - you'll not be able to recover the object.

In addition your object may contain members that are pointer to other things (like strings or other objects) which may not necessarily be allocated on the stack. Most probably you'll fail to realize those members, unless you have the full-memory dump.