#include <ehdata.h>
EXTERN_C
_CRTIMP
PSTR
__CRTDECL
__unDNameEx(
_Out_ PSTR buffer,
_In_ PCSTR mangled,
_In_ DWORD cb,
_In_ void* (__cdecl* memget)(DWORD),
_In_ void (__cdecl* memfree)(void*),
_In_ PCSTR (__cdecl* GetParameter)(long i),
_In_ DWORD flags
);
static PCSTR __cdecl GetParameter(long /*i*/)
{
return "";
}
static void* __cdecl fAlloc(ULONG cb)
{
return LocalAlloc(LMEM_FIXED, (ULONG)cb);
}
static void __cdecl fFree(void* pv)
{
LocalFree(pv);
}
void PrintName(PCSTR Name)
{
if ('.' == *Name++)
{
PSTR buf = 0, name = 0;
int len = 0;
while (0 < (len = _snprintf(name, len, "?_@@YAX%s@Z", Name)))
{
if (name)
{
len += 0x20;
len <<= 1;
if (buf == __unDNameEx(buf = (PSTR)alloca(len), name, len, fAlloc, fFree, GetParameter, UNDNAME_DEFAULT))
{
if (buf = strchr(buf, '('))
{
buf++;
name = buf + strlen(buf)-1;
if (')' == *name)
{
*name = 0;
DbgPrint("\tcatch (%hs ) { /***/ }\n", buf);
return ;
}
}
}
break;
}
name = (PSTR)alloca(++len);
}
}
DbgPrint("\tcatch (%hs ) { ... }\n", Name - 1);
}
EXTERN_C
_CRTIMP
void
__CRTDECL
__DestructExceptionObject(PEXCEPTION_RECORD ExceptionRecord, BOOLEAN bDestruct);
NTSTATUS seh(PEXCEPTION_RECORD ExceptionRecord)
{
DbgPrint("%x [%x] at %p\n", ExceptionRecord->ExceptionCode,
ExceptionRecord->ExceptionFlags, ExceptionRecord->ExceptionAddress);
if (ULONG NumberParameters = ExceptionRecord->NumberParameters)
{
DbgPrint("%u params: [ ", NumberParameters);
PULONG_PTR ExceptionInformation = ExceptionRecord->ExceptionInformation;
do
{
DbgPrint("%p, ", *ExceptionInformation++);
} while (--NumberParameters);
DbgPrint("]\n");
}
switch (ExceptionRecord->ExceptionCode)
{
case EH_EXCEPTION_NUMBER:
if (!(EXCEPTION_SOFTWARE_ORIGINATE & ExceptionRecord->ExceptionFlags))
{
__debugbreak();
}
if (EH_EXCEPTION_PARAMETERS <= ExceptionRecord->NumberParameters)
{
void **pExceptionObject = reinterpret_cast<void **>(ExceptionRecord->ExceptionInformation[1]);
ThrowInfo *pTI = reinterpret_cast<ThrowInfo *>(ExceptionRecord->ExceptionInformation[2]);
ULONG_PTR ImageBase = ExceptionRecord->ExceptionInformation[3];
DbgPrint("c++[%x]: pExceptionObject=%p\n", ExceptionRecord->ExceptionInformation[0], *pExceptionObject);
switch (ExceptionRecord->ExceptionInformation[0])
{
case EH_MAGIC_NUMBER1:
case EH_MAGIC_NUMBER2:
case EH_MAGIC_NUMBER3:
CatchableTypeArray* p = THROW_CTARRAY_IB(*pTI,ImageBase);
if (ULONG nCatchableTypes = p->nCatchableTypes)
{
const int* arrayOfCatchableTypes = p->arrayOfCatchableTypes;
do
{
CatchableType* pt = (CatchableType*)RtlOffsetToPointer(ImageBase, *arrayOfCatchableTypes++);
TypeDescriptor* pType = (TypeDescriptor*)RtlOffsetToPointer(ImageBase, pt->pType);
PrintName(pType->name);
} while (--nCatchableTypes);
}
break;
}
// exported by ucrtbase but included to public ucrt.lib
// __DestructExceptionObject(ExceptionRecord, TRUE);// optional call
if (PMFN pmfnUnwind = pTI->pmfnUnwind)
{
reinterpret_cast<void (__cdecl * )(void*)>(RtlOffsetToPointer(ImageBase, pmfnUnwind))(*pExceptionObject);
}
}
return EXCEPTION_EXECUTE_HANDLER;
}
return EXCEPTION_CONTINUE_SEARCH;
}
void Handler_CPP()
{
try
{
foo();
}
catch (const std::exception& exc)
{
std::cout << exc.what();
}
catch (long e)
{
std::cout << e;
}
}
void Handler_C()
{
__try {
Handler_CPP();
} __except(seh(GetExceptionInformation()->ExceptionRecord)){
__nop();
}
}
(this code is designed for x64, where _EH_RELATIVE_TYPEINFO is true, however possible here use macros from ehdata.h, like THROW_CTARRAY_IB
catch(...)clause, the program will crash and stderr will show something liketerminate called after throwing and instance of 'blah'but yeah, relying of a crash to get some information is not what I would call a solution...