From 52117cb7a06d14c1634df9eabd00920d2dcc20cf Mon Sep 17 00:00:00 2001 From: rei-2 <174158077+rei-2@users.noreply.github.com> Date: Sat, 26 Oct 2024 07:55:26 -0400 Subject: [PATCH] crash logging --- Amalgam/Amalgam.vcxproj | 4 +- Amalgam/Amalgam.vcxproj.filters | 4 +- Amalgam/src/DllMain.cpp | 10 +- Amalgam/src/SDK/Vars.h | 14 +-- Amalgam/src/Utils/CrashLog/CrashLog.cpp | 142 ++++++++++++++++++++++++ Amalgam/src/Utils/CrashLog/CrashLog.h | 7 ++ Amalgam/src/Utils/Minidump/Minidump.cpp | 77 ------------- Amalgam/src/Utils/Minidump/Minidump.h | 8 -- 8 files changed, 161 insertions(+), 105 deletions(-) create mode 100644 Amalgam/src/Utils/CrashLog/CrashLog.cpp create mode 100644 Amalgam/src/Utils/CrashLog/CrashLog.h delete mode 100644 Amalgam/src/Utils/Minidump/Minidump.cpp delete mode 100644 Amalgam/src/Utils/Minidump/Minidump.h diff --git a/Amalgam/Amalgam.vcxproj b/Amalgam/Amalgam.vcxproj index ff72cc5c..88878c2d 100644 --- a/Amalgam/Amalgam.vcxproj +++ b/Amalgam/Amalgam.vcxproj @@ -564,11 +564,11 @@ + - @@ -826,6 +826,7 @@ + @@ -833,7 +834,6 @@ - diff --git a/Amalgam/Amalgam.vcxproj.filters b/Amalgam/Amalgam.vcxproj.filters index e2686880..594ff40c 100644 --- a/Amalgam/Amalgam.vcxproj.filters +++ b/Amalgam/Amalgam.vcxproj.filters @@ -22,7 +22,6 @@ - @@ -172,6 +171,7 @@ + @@ -301,7 +301,6 @@ - @@ -438,6 +437,7 @@ + diff --git a/Amalgam/src/DllMain.cpp b/Amalgam/src/DllMain.cpp index 2807db9c..beac23c0 100644 --- a/Amalgam/src/DllMain.cpp +++ b/Amalgam/src/DllMain.cpp @@ -1,6 +1,6 @@ #include #include "Core/Core.h" -#include "Utils/Minidump/Minidump.h" +#include "Utils/CrashLog/CrashLog.h" DWORD WINAPI MainThread(LPVOID lpParam) { @@ -8,10 +8,6 @@ DWORD WINAPI MainThread(LPVOID lpParam) U::Core.Loop(); U::Core.Unload(); -#ifndef _DEBUG - SetUnhandledExceptionFilter(nullptr); -#endif - FreeLibraryAndExitThread(static_cast(lpParam), EXIT_SUCCESS); } @@ -20,9 +16,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { if (fdwReason == DLL_PROCESS_ATTACH) { -#ifndef _DEBUG - SetUnhandledExceptionFilter(Minidump::ExceptionFilter); -#endif + AddVectoredExceptionHandler(1, CrashLog::ExceptionFilter); if (const auto hMainThread = CreateThread(nullptr, 0, MainThread, hinstDLL, 0, nullptr)) CloseHandle(hMainThread); diff --git a/Amalgam/src/SDK/Vars.h b/Amalgam/src/SDK/Vars.h index 34492d70..1d06e3d2 100644 --- a/Amalgam/src/SDK/Vars.h +++ b/Amalgam/src/SDK/Vars.h @@ -108,8 +108,6 @@ namespace Vars SUBNAMESPACE_BEGIN(Theme) CVar(Accent, Color_t(255, 101, 101, 255), VISUAL) CVar(Background, Color_t(23, 23, 23, 250), VISUAL) - CVar(Foreground, Color_t(11, 11, 11, 250), VISUAL) - CVar(Foremost, Color_t(23, 23, 23, 250), VISUAL) CVar(Inactive, Color_t(150, 150, 150, 255), VISUAL) CVar(Active, Color_t(255, 255, 255, 255), VISUAL) SUBNAMESPACE_END(Theme) @@ -156,17 +154,17 @@ namespace Vars CVar(SplashRadius, 90.f) CVar(AutoRelease, 0.f) - CVar(GroundSamples, 66, NOSAVE) // debug + CVar(GroundSamples, 33, NOSAVE) // debug CVar(GroundStraightFuzzyValue, 100.f, NOSAVE) // debug - CVar(GroundLowMinimumSamples, 5, NOSAVE) // debug - CVar(GroundHighMinimumSamples, 15, NOSAVE) // debug + CVar(GroundLowMinimumSamples, 8, NOSAVE) // debug + CVar(GroundHighMinimumSamples, 16, NOSAVE) // debug CVar(GroundLowMinimumDistance, 0.f, NOSAVE) // debug CVar(GroundHighMinimumDistance, 2500.f, NOSAVE) // debug - CVar(AirSamples, 66, NOSAVE) // debug + CVar(AirSamples, 33, NOSAVE) // debug CVar(AirStraightFuzzyValue, 10.f, NOSAVE) // debug - CVar(AirLowMinimumSamples, 5, NOSAVE) // debug - CVar(AirHighMinimumSamples, 5, NOSAVE) // debug + CVar(AirLowMinimumSamples, 3, NOSAVE) // debug + CVar(AirHighMinimumSamples, 3, NOSAVE) // debug CVar(AirLowMinimumDistance, 100000.f, NOSAVE) // debug CVar(AirHighMinimumDistance, 100000.f, NOSAVE) // debug diff --git a/Amalgam/src/Utils/CrashLog/CrashLog.cpp b/Amalgam/src/Utils/CrashLog/CrashLog.cpp new file mode 100644 index 00000000..aaed317d --- /dev/null +++ b/Amalgam/src/Utils/CrashLog/CrashLog.cpp @@ -0,0 +1,142 @@ +#include "CrashLog.h" + +#include "../../Features/Configs/Configs.h" + +#include +#include +#include +#include +#include +#pragma comment(lib, "imagehlp.lib") + +struct Frame +{ + std::string m_sModule = ""; + uintptr_t m_pAddress = 0; + std::string m_sFile = ""; + unsigned int m_uLine = 0; + std::string m_sName = ""; +}; + +static std::deque StackTrace(PCONTEXT context) +{ + HANDLE hProcess = GetCurrentProcess(); + HANDLE hThread = GetCurrentThread(); + + OutputDebugStringA("StackTrace\n"); + if (!SymInitialize(hProcess, nullptr, TRUE)) + return {}; + + OutputDebugStringA("Frame\n"); + SymSetOptions(SYMOPT_LOAD_LINES); + + STACKFRAME64 frame = {}; + frame.AddrPC.Offset = context->Rip; + frame.AddrFrame.Offset = context->Rbp; + frame.AddrStack.Offset = context->Rsp; + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrFrame.Mode = AddrModeFlat; + frame.AddrStack.Mode = AddrModeFlat; + + std::deque vTrace = {}; + while (StackWalk64(IMAGE_FILE_MACHINE_AMD64, hProcess, hThread, &frame, context, nullptr, SymFunctionTableAccess64, SymGetModuleBase64, nullptr)) + { + OutputDebugStringA("StackWalk\n"); + Frame tFrame = {}; + + tFrame.m_pAddress = frame.AddrPC.Offset; + + { + auto base = HINSTANCE(SymGetModuleBase64(hProcess, frame.AddrPC.Offset)); + char buf[MAX_PATH]; + if (base && GetModuleFileNameA(base, buf, MAX_PATH)) + { + tFrame.m_sModule = std::format("{}, {:#x}", buf, uintptr_t(base)); + auto find = tFrame.m_sModule.rfind("\\"); + if (find != std::string::npos) + tFrame.m_sModule.replace(0, find + 1, ""); + } + } + + { + DWORD offset = 0; + IMAGEHLP_LINE64 line = {}; + line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + if (SymGetLineFromAddr64(hProcess, frame.AddrPC.Offset, &offset, &line)) + { + tFrame.m_sFile = line.FileName; + tFrame.m_uLine = line.LineNumber; + auto find = tFrame.m_sFile.rfind("\\"); + if (find != std::string::npos) + tFrame.m_sFile.replace(0, find + 1, ""); + } + } + + { + uintptr_t offset = 0; + char buf[sizeof(IMAGEHLP_SYMBOL64) + 255]; + auto symbol = PIMAGEHLP_SYMBOL64(buf); + symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64) + 255; + symbol->MaxNameLength = 254; + if (SymGetSymFromAddr64(hProcess, frame.AddrPC.Offset, &offset, symbol)) + tFrame.m_sName = symbol->Name; + } + + vTrace.push_back(tFrame); + } + //if (!vTrace.empty()) + // vTrace.pop_front(); + + SymCleanup(hProcess); + + return vTrace; +} + +LONG APIENTRY CrashLog::ExceptionFilter(PEXCEPTION_POINTERS Info) +{ + if (Info->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) + return EXCEPTION_EXECUTE_HANDLER; + + std::stringstream error; + error << std::format("Error: {:#X}\n", Info->ExceptionRecord->ExceptionCode); + error << std::format("Address: {:#X}\n\n", uintptr_t(Info->ExceptionRecord->ExceptionAddress)); + error << std::format("RIP: {:#x}\n", Info->ContextRecord->Rip); + error << std::format("EFLAGS: {:#x}\n", Info->ContextRecord->EFlags); + error << std::format("RAX: {:#x}\n", Info->ContextRecord->Rax); + error << std::format("RCX: {:#x}\n", Info->ContextRecord->Rcx); + error << std::format("RDX: {:#x}\n", Info->ContextRecord->Rdx); + error << std::format("RBX: {:#x}\n", Info->ContextRecord->Rbx); + error << std::format("RSP: {:#x}\n", Info->ContextRecord->Rsp); + error << std::format("RBP: {:#x}\n", Info->ContextRecord->Rbp); + error << std::format("RSI: {:#x}\n", Info->ContextRecord->Rsi); + error << std::format("RDI: {:#x}\n\n", Info->ContextRecord->Rdi); + + auto vTrace = StackTrace(Info->ContextRecord); + if (!vTrace.empty()) + { + for (auto& tFrame : vTrace) + { + error << std::format("{:#x}", tFrame.m_pAddress); + if (!tFrame.m_sModule.empty()) + error << std::format(" ({})", tFrame.m_sModule); + if (!tFrame.m_sFile.empty()) + error << std::format(" ({} L{})", tFrame.m_sFile, tFrame.m_uLine); + if (!tFrame.m_sName.empty()) + error << std::format(" ({})", tFrame.m_sName); + error << "\n"; + } + error << "\n"; + } + + error << "Ctrl + C to copy. Logged to Amalgam\\crash_log.txt. "; + + MessageBox(nullptr, error.str().c_str(), "Unhandled exception", MB_OK | MB_ICONERROR); + + error << "\n\n\n\n"; + std::ofstream file; + file.open(F::Configs.sConfigPath + "\\crash_log.txt", std::ios_base::app); + file << error.str(); + file.close(); + + return EXCEPTION_EXECUTE_HANDLER; +} \ No newline at end of file diff --git a/Amalgam/src/Utils/CrashLog/CrashLog.h b/Amalgam/src/Utils/CrashLog/CrashLog.h new file mode 100644 index 00000000..2d993214 --- /dev/null +++ b/Amalgam/src/Utils/CrashLog/CrashLog.h @@ -0,0 +1,7 @@ +#pragma once +#include + +namespace CrashLog +{ + LONG APIENTRY ExceptionFilter(PEXCEPTION_POINTERS Info); +} \ No newline at end of file diff --git a/Amalgam/src/Utils/Minidump/Minidump.cpp b/Amalgam/src/Utils/Minidump/Minidump.cpp deleted file mode 100644 index 2f7bbe90..00000000 --- a/Amalgam/src/Utils/Minidump/Minidump.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "Minidump.h" - -#include -#include -#include -#include - -[[noreturn]] void ExitWithMessage(const TCHAR* msg) -{ - MessageBox( - nullptr, - msg, - _T("Unhandled exception"), - MB_OK | MB_ICONERROR - ); - - ExitProcess(0); -} - -LONG __stdcall Minidump::ExceptionFilter(PEXCEPTION_POINTERS exPtr) -{ - const HMODULE hLib = LoadLibrary(_T("dbghelp")); - if (!hLib) - { - ExitWithMessage(_T("Could not load dbghelp!")); - } - - const auto pMiniDumpWriteDump = reinterpret_cast(GetProcAddress(hLib, "MiniDumpWriteDump")); - - // Get the MiniDumpWriteDump function - if (!pMiniDumpWriteDump) - { - ExitWithMessage(_T("Could not load MiniDumpWriteDump!")); - } - - // Get the dump folde (Desktop) - TCHAR buf[512]; - const auto gfpResult = SHGetFolderPath(nullptr, CSIDL_DESKTOP, nullptr, SHGFP_TYPE_CURRENT, buf); - if (FAILED(gfpResult)) - { - ExitWithMessage(_T("Failed to get folder path!")); - } - - // Create a file handle - TCHAR fileName[MAX_PATH]; - const int curTime = static_cast(time(nullptr) % 100000); - wsprintf(fileName, _T("%s\\Crash_Amalgam_%x.dmp"), buf, curTime); - const HANDLE hFile = CreateFile(fileName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - - if (hFile == INVALID_HANDLE_VALUE) - { - wsprintf(buf, _T("Could not create minidump file!\n\n- Error: %ul\n- File: %s"), GetLastError(), fileName); - ExitWithMessage(buf); - } - - // Write the minidump - MINIDUMP_EXCEPTION_INFORMATION mdei = { - GetCurrentThreadId(), - exPtr, - FALSE - }; - - if (pMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &mdei, nullptr, nullptr)) - { - wsprintf(buf, _T("Minidump created.\n\n- Build: " __TIMESTAMP__ "\n- File: %s"), fileName); - } - else - { - wsprintf(buf, _T("Could not create minidump!\n- Error: %ul\n- File: %s"), GetLastError(), fileName); - } - - // Cleanup - FreeLibrary(hLib); - CloseHandle(hFile); - - ExitWithMessage(buf); -} \ No newline at end of file diff --git a/Amalgam/src/Utils/Minidump/Minidump.h b/Amalgam/src/Utils/Minidump/Minidump.h deleted file mode 100644 index 4a215c54..00000000 --- a/Amalgam/src/Utils/Minidump/Minidump.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include "../Feature/Feature.h" -#include - -namespace Minidump -{ - LONG WINAPI ExceptionFilter(PEXCEPTION_POINTERS exPtr); -} \ No newline at end of file