mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-23 16:07:52 -05:00
display messages of unhandled c++ exceptions
This commit is contained in:
parent
27ed63e710
commit
fdd78aca3f
2 changed files with 96 additions and 13 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
46
loader/src/platform/windows/ehdata_structs.hpp
Normal file
46
loader/src/platform/windows/ehdata_structs.hpp
Normal 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;
|
Loading…
Reference in a new issue