diff --git a/loader/src/platform/windows/crashlog.cpp b/loader/src/platform/windows/crashlog.cpp index 19784522..a2fb66c9 100644 --- a/loader/src/platform/windows/crashlog.cpp +++ b/loader/src/platform/windows/crashlog.cpp @@ -20,6 +20,7 @@ #include #include #include +#include "ehdata_structs.hpp" using namespace geode::prelude; @@ -199,19 +200,55 @@ static std::string getRegisters(PCONTEXT context) { static std::string getInfo(LPEXCEPTION_POINTERS info, Mod* faultyMod) { std::stringstream stream; - stream << "Faulty Module: " - << getModuleName(handleFromAddress(info->ExceptionRecord->ExceptionAddress), true) - << "\n" - << "Faulty Mod: " << (faultyMod ? faultyMod->getID() : "") << "\n" - << "Exception Code: " << std::hex << info->ExceptionRecord->ExceptionCode << " (" - << getExceptionCodeString(info->ExceptionRecord->ExceptionCode) << ")" << std::dec - << "\n" - << "Exception Flags: " << info->ExceptionRecord->ExceptionFlags << "\n" - << "Exception Address: " << info->ExceptionRecord->ExceptionAddress << " ("; - printAddr(stream, info->ExceptionRecord->ExceptionAddress, false); - stream << ")" - << "\n" - << "Number Parameters: " << info->ExceptionRecord->NumberParameters << "\n"; + + if (info->ExceptionRecord->ExceptionCode == EH_EXCEPTION_NUMBER) { + // This executes when a C++ exception was thrown and not handled. + // https://devblogs.microsoft.com/oldnewthing/20100730-00/?p=13273 + + bool isStdException = false; + + auto exceptionRecord = info->ExceptionRecord; + auto exceptionObject = exceptionRecord->ExceptionInformation[1]; + + auto throwInfo = reinterpret_cast<_ThrowInfo*>(exceptionRecord->ExceptionInformation[2]); + auto catchableTypeArray = reinterpret_cast<_CatchableTypeArray*>(throwInfo->pCatchableTypeArray); + auto ctaSize = catchableTypeArray->nCatchableTypes; + + for (int i = 0; i < ctaSize; i++) { + auto catchableType = reinterpret_cast<_CatchableType*>(catchableTypeArray->arrayOfCatchableTypes[i]); + auto ctDescriptor = reinterpret_cast<_TypeDescriptor*>(catchableType->pType); + auto classname = ctDescriptor->name; + + if (strcmp(classname, ".?AVexception@std@@") == 0) { + isStdException = true; + break; + } + } + + if (isStdException) { + auto excObject = reinterpret_cast(exceptionObject); + // stream << "C++ Exception Type: " << typeid(excObject).name() << "\n"; // always const std::exception * + stream << "C++ Exception: " << excObject->what() << "\n"; + } else { + stream << "C++ Exception: \n"; + } + + stream << "Faulty Mod: " << (faultyMod ? faultyMod->getID() : "") << "\n"; + } else { + stream << "Faulty Module: " + << getModuleName(handleFromAddress(info->ExceptionRecord->ExceptionAddress), true) + << "\n" + << "Faulty Mod: " << (faultyMod ? faultyMod->getID() : "") << "\n" + << "Exception Code: " << std::hex << info->ExceptionRecord->ExceptionCode << " (" + << getExceptionCodeString(info->ExceptionRecord->ExceptionCode) << ")" << std::dec + << "\n" + << "Exception Flags: " << info->ExceptionRecord->ExceptionFlags << "\n" + << "Exception Address: " << info->ExceptionRecord->ExceptionAddress << " ("; + printAddr(stream, info->ExceptionRecord->ExceptionAddress, false); + stream << ")" + << "\n" + << "Number Parameters: " << info->ExceptionRecord->NumberParameters << "\n"; + } return stream.str(); } diff --git a/loader/src/platform/windows/ehdata_structs.hpp b/loader/src/platform/windows/ehdata_structs.hpp new file mode 100644 index 00000000..14d0b94a --- /dev/null +++ b/loader/src/platform/windows/ehdata_structs.hpp @@ -0,0 +1,46 @@ +#pragma once +// All of those are defined in but the header fails to compile for some reason. + +#define EH_EXCEPTION_NUMBER ('msc' | 0xE0000000) + +typedef struct _PMD +{ + int mdisp; + int pdisp; + int vdisp; +} _PMD; + +typedef void (*_PMFN) (void); + +#pragma warning (disable:4200) +#pragma pack (push, _TypeDescriptor, 8) +typedef struct _TypeDescriptor +{ + const void *pVFTable; + void *spare; + char name []; +} _TypeDescriptor; +#pragma pack (pop, _TypeDescriptor) +#pragma warning (default:4200) + +typedef const struct _s__CatchableType { + unsigned int properties; + _TypeDescriptor *pType; + _PMD thisDisplacement; + int sizeOrOffset; + _PMFN copyFunction; +} _CatchableType; + +#pragma warning (disable:4200) +typedef const struct _s__CatchableTypeArray { + int nCatchableTypes; + _CatchableType *arrayOfCatchableTypes []; +} _CatchableTypeArray; +#pragma warning (default:4200) + +typedef const struct _s__ThrowInfo { + unsigned int attributes; + _PMFN pmfnUnwind; + int (__cdecl *pForwardCompat) (...); + _CatchableTypeArray *pCatchableTypeArray; +} _ThrowInfo; \ No newline at end of file