Viewing types, part 3: Exceptions

Last time a way was shown to use internal RTTI mechanics to view C++ type names without direct debugger aid. There is one place in particular where such type names carry substantial information, and that is c++ exceptions. These can also require some additional treatment.

Native SEH exceptions are characterized – and can be caught – by a code. In contrast, C++ exceptions are characterized and caught by a type. So if you are debugging already within a catch-block (which is after some hefty compiler and runtime machinery already kicked in), you already have a direct view of the caught type, and need no extra trickery.

Where things get delicate is when a C++ exception goes uncaught in any C++ catch block, and is either caught in an SEH __except clause or goes completely uncaught and (hopefully) included in a core dump for you to analyze.  C++ exceptions, which are implemented on top of SEH ones, all utilize the code E06D7363 (standing for Exception, ‘M’ ‘V’ ‘C’ in ascii) and so cannot be distinguished by code. Some low-level trickery is in order.

The Old New Recipe

Sometime in 2010 Raymond Chen posted a recipe on how to view types of such exceptions (i.e.: originating in VC++, viewed in a context of SEH). Briefly, once you obtained an EXCEPTION_RECORD, do as follows:

Take Parameter 2 [of the exception record, O.S.] and go to the fourth DWORD and treat it as a pointer. (On 64-bit systems, you have to add this value to the HINSTANCE passed as Parameter 3 to convert it to a pointer.)

Next, go to the second DWORD and treat it as a pointer. (Again, on 64-bit systems, it’s really an offset from the HINSTANCE.)

Next, go to the second DWORD and treat it as a pointer. (64-bit systems: you know the drill.)

Finally, skip over the first two void*s and the rest is the class name.

And here’s a shameless cut & paste of his diagram:

EXCEPTION_RECORD
+----------+
| E06D7363 |
+----------+
|  ~~~     |
+----------+
|* ~~~     |
+----------+
|* ~~~     |
+----------+
| 3 or 4   |
+----------+
|* ~~~     |
+----------+
|*Object   |
+----------+     +---+
|*       ------> |~~~|
+----------+     +---+
|*HINSTANCE|     |~~~|
+----------+     +---+
                 |~~~|
                 +---+    +---+
                 | -----> |~~~|
                 +---+    +---+    +---+
                          | -----> |~~~|
                          +---+    +---+    +----------+
                                   | -----> |*   ~~~   |
                                   +---+    +----------+
                                            |*   ~~~   |
                                            +----------+
                                            |Class name|
                                            +----------+

Decorate with type names

If you’re thinking there’s gotta be a better way, you’d be right. Dumping VC++ intrinsic compiler types by compiling an empty file with /d1reportAllClassLayout – as done for type analysis – reveals a few types that directly relate to exception handling:

class _s__CatchableType    size(28):
+---
0    | properties
4    | pType
8    | _PMD thisDisplacement
20    | sizeOrOffset
24    | copyFunction
+---
class _s__CatchableTypeArray    size(4):
+---
0    | nCatchableTypes
4    | arrayOfCatchableTypes
+---
class _s__ThrowInfo    size(16):
+---
0    | attributes
4    | pmfnUnwind
8    | pForwardCompat
12    | pCatchableTypeArray
+---

Fitting these into Raymond’s diagram gives –

EXCEPTION_RECORD
+----------+
| E06D7363 |
+----------+
|  ~~~     |
+----------+
|* ~~~     |
+----------+
|* ~~~     |
+----------+
| 3 or 4   |
+----------+
|* ~~~     |
+----------+
|*Object   |  _s__ThrowInfo 
+----------+     +---+
|*       ------> |~~~|
+----------+     +---+
                 |~~~|
                 +---+
                 |~~~|  _s__CatchableTypeArray
                 +---+    +---+
                 | -----> |~~~|    _s__CatchableType
                 +---+    +---+    +---+
                          | -----> |~~~|   _TypeDescriptor
                          +---+    +---+    +----------+
                                   | -----> |*   ~~~   |
                                   +---+    +----------+
                                     .      |*   ~~~   |
                                     .      +----------+
                                     .      |Class name|
                                            +----------+

Into the debugger

Now for a toy – but real – example in VC. Take this code:

__try
{
throw std::runtime_error("adsf"); // throw a C++ exception
}
__except (EXCEPTION_EXECUTE_HANDLER ) // catch as a native exception
{
__debugbreak(); // can we identify the C++ type of the thrown exception?
}

Here’s an initial inspection of the exception record in the watch window:

image

NumberParameters being 3 indicates that this is an x86 system. The interesting parts are the contents of ExceptionInformation. Forget about parameter 1 for a minute, and let’s inspect parameter 2 – which by the analysis above should be of type _s__ThrowInfo:

image

There seem to already exist multiple indications of the thrown C++ type name, as circled in red, with no need to go further down Raymond’s recipe. However this is only due to the fact that our toy code throws a standard type for which symbols are available. If such is the kind exception you’re facing – you can happily stop here. If you’re facing a custom type – follow this game a bit further.   For some reason VS properly recognizes the type of arrayOfCatchableTypes but does not expand it, so let’s do it ourselves:

image

And the name is available as part of the TypeDescriptor, as for a regular C++ type (bottom red rect). Undname.exe it – if the decorated name isn’t obvious enough – and view the type name as appeared in the source code.

Bonus: An Alternate (Arguably Better) Recipe

As Raymond notes, parameter 1 of the ExceptionInformation (red rect ‘1’ above) is usually a pointer to the C++ object being thrown. It might contain much more information that it’s type name (well, at least if it’s not a custom type it should be accessible to you), and as seen in the previous post – an object contains its own route to the TypeDescriptor and hence the type name.  Here’s how it looks in the watch window:

image

Raymond notes that parameter 1 usually points to the thrown object, but –

…sometimes there is some junk in front that you have to skip over. Once you figure out what it is, you can dump it. (I haven’t bothered trying to figure out exactly how much; I just dump bytes and figure out the correct start of the object by inspection.)

You can easily do that from within VS too: if the expression in the example

  (_s__RTTICompleteObjectLocator**)(*(int*)0x003bf75c-4)

(containing the direct parameter 1, 0x003bf75c) expands to rubbish, start increasing the pointer until you arrive at meaningful struct contents. This seems a faster way to get to the information of interest since you get to the thrown object and its type name in a single search.

Advertisements
This entry was posted in Debugging, VC++. 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