From 22506fa68992d32b9c4a462deb9f5066e8e03c56 Mon Sep 17 00:00:00 2001 From: Marvin D <41352111+IcePixelx@users.noreply.github.com> Date: Sat, 24 Dec 2022 16:40:04 +0100 Subject: [PATCH] Fix VEH. * Make sure IsMaterialInternal won't be inlined. * Fix recurssive VEH throwing. * Check if IsMaterialInternal caused exception and ignore it. --- r5dev/materialsystem/cmaterialsystem.cpp | 2 +- r5dev/materialsystem/cmaterialsystem.h | 2 +- r5dev/public/utility/crashhandler.cpp | 45 ++++++++++++++++++++---- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/r5dev/materialsystem/cmaterialsystem.cpp b/r5dev/materialsystem/cmaterialsystem.cpp index f997c8ee..d822951f 100644 --- a/r5dev/materialsystem/cmaterialsystem.cpp +++ b/r5dev/materialsystem/cmaterialsystem.cpp @@ -66,7 +66,7 @@ void* __fastcall DispatchDrawCall(int64_t a1, uint64_t a2, int a3, int a4, int64 // Input : **pCandidate - // Output : true if valid and material, false otherwise //----------------------------------------------------------------------------- -bool IsMaterialInternal(void** pCandidate) +__declspec(noinline) bool IsMaterialInternal(void** pCandidate) { // NOTE: this is a dirty fix, but for running technically broken BSP's, this is the only fix // besides going bare metal inline assembly (which on its own isn't directly the problem, but diff --git a/r5dev/materialsystem/cmaterialsystem.h b/r5dev/materialsystem/cmaterialsystem.h index 8f77eeeb..16a88a88 100644 --- a/r5dev/materialsystem/cmaterialsystem.h +++ b/r5dev/materialsystem/cmaterialsystem.h @@ -43,7 +43,7 @@ inline int* g_nUnfreeStreamingTextureMemory = nullptr; inline int* g_nUnusableStreamingTextureMemory = nullptr; #endif // !DEDICATED -bool IsMaterialInternal(void** pCandidate); +__declspec(noinline) bool IsMaterialInternal(void** pCandidate); void CMaterialSystem_Attach(); void CMaterialSystem_Detach(); /////////////////////////////////////////////////////////////////////////////// diff --git a/r5dev/public/utility/crashhandler.cpp b/r5dev/public/utility/crashhandler.cpp index 5ddad4bd..eae264dd 100644 --- a/r5dev/public/utility/crashhandler.cpp +++ b/r5dev/public/utility/crashhandler.cpp @@ -8,6 +8,14 @@ #ifndef _DEBUG +#include "tier1/cvar.h" +#include "vpc/keyvalues.h" +#include "rtech/rtech_utils.h" +#include "engine/cmodel_bsp.h" +#include "materialsystem/cmaterialglue.h" +#include "materialsystem/cmaterialsystem.h" +#include "bsplib/bsplib.h" + // Class is just for DLL init and DLL close, so we can actually define it here fine. class CCrashHandler { @@ -135,6 +143,34 @@ long __stdcall ExceptionFilter(EXCEPTION_POINTERS* exceptionInfo) if (g_ExceptionToString.find(exceptionInfo->ExceptionRecord->ExceptionCode) == g_ExceptionToString.end()) return EXCEPTION_CONTINUE_SEARCH; +#ifndef _DEBUG + // THIS WONT WORK ON DEBUG!!! + // THIS IS DUE TO A JMP TABLE CREATED BY MSVC!! + static void* imiRetAddr = nullptr; + static auto find_IMI_ref = CMemory(IsMaterialInternal).FindAllCallReferences(reinterpret_cast(BuildPropStaticFrustumCullMap), 1000); + if (!find_IMI_ref.empty()) + { + imiRetAddr = find_IMI_ref.at(0).Offset(0x5).RCast(); + } +#endif // _DEBUG + + // Now get the callstack.. + constexpr DWORD NUM_FRAMES_TO_CAPTURE = 60; + void* pStackTrace[NUM_FRAMES_TO_CAPTURE] = { 0 }; + WORD nCapturedFrames = RtlCaptureStackBackTrace(0, NUM_FRAMES_TO_CAPTURE, pStackTrace, NULL); + +#ifndef _DEBUG + // Check if we found IMI. + if (imiRetAddr) + { + for (WORD i = 0; i < 10; i++) + { + if (imiRetAddr == pStackTrace[i]) + return EXCEPTION_CONTINUE_SEARCH; + } + } +#endif // _DEBUG + CONTEXT* pExceptionContext = exceptionInfo->ContextRecord; // Setup message. @@ -157,11 +193,6 @@ long __stdcall ExceptionFilter(EXCEPTION_POINTERS* exceptionInfo) svMessage += "\r\nStacktrace:\r\n\r\n"; - // Now get the callstack.. - constexpr DWORD NUM_FRAMES_TO_CAPTURE = 60; - void* pStackTrace[NUM_FRAMES_TO_CAPTURE] = { 0 }; - WORD nCapturedFrames = RtlCaptureStackBackTrace(0, NUM_FRAMES_TO_CAPTURE, pStackTrace, NULL); - for (WORD i = 0; i < nCapturedFrames; i++) { svMessage += GetModuleCrashOffsetAndName(reinterpret_cast(pStackTrace[i])) + "\n"; @@ -177,6 +208,8 @@ long __stdcall ExceptionFilter(EXCEPTION_POINTERS* exceptionInfo) MessageBoxA(0, svMessage.c_str(), "R5R Crashed :/", MB_ICONERROR | MB_OK); + bLogged = true; + return EXCEPTION_EXECUTE_HANDLER; } @@ -192,6 +225,6 @@ CCrashHandler::~CCrashHandler() // Init on DLL init! // Needs fixing for frustum culling, it triggers the SEH handler there which also triggers this, add address to whitelist/whitelist whole code page. -//CCrashHandler* g_CrashHandler = new CCrashHandler(); +CCrashHandler* g_CrashHandler = new CCrashHandler(); #endif // _DEBUG \ No newline at end of file