display messages of unhandled c++ exceptions

This commit is contained in:
dank_meme01 2023-10-23 23:19:15 +02:00
parent 27ed63e710
commit fdd78aca3f
2 changed files with 96 additions and 13 deletions

View file

@ -20,6 +20,7 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <fmt/core.h> #include <fmt/core.h>
#include "ehdata_structs.hpp"
using namespace geode::prelude; using namespace geode::prelude;
@ -199,6 +200,41 @@ static std::string getRegisters(PCONTEXT context) {
static std::string getInfo(LPEXCEPTION_POINTERS info, Mod* faultyMod) { static std::string getInfo(LPEXCEPTION_POINTERS info, Mod* faultyMod) {
std::stringstream stream; std::stringstream stream;
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<std::exception*>(exceptionObject);
// stream << "C++ Exception Type: " << typeid(excObject).name() << "\n"; // always const std::exception *
stream << "C++ Exception: " << excObject->what() << "\n";
} else {
stream << "C++ Exception: <Unknown type>\n";
}
stream << "Faulty Mod: " << (faultyMod ? faultyMod->getID() : "<Unknown>") << "\n";
} else {
stream << "Faulty Module: " stream << "Faulty Module: "
<< getModuleName(handleFromAddress(info->ExceptionRecord->ExceptionAddress), true) << getModuleName(handleFromAddress(info->ExceptionRecord->ExceptionAddress), true)
<< "\n" << "\n"
@ -212,6 +248,7 @@ static std::string getInfo(LPEXCEPTION_POINTERS info, Mod* faultyMod) {
stream << ")" stream << ")"
<< "\n" << "\n"
<< "Number Parameters: " << info->ExceptionRecord->NumberParameters << "\n"; << "Number Parameters: " << info->ExceptionRecord->NumberParameters << "\n";
}
return stream.str(); return stream.str();
} }

View file

@ -0,0 +1,46 @@
#pragma once
// All of those are defined in <ehdata.h> 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;