From 5aea27d56d6b82b1e73fbb9a33ecdb25a0043af8 Mon Sep 17 00:00:00 2001 From: Reece Date: Thu, 16 Jun 2022 01:27:00 +0100 Subject: [PATCH] [*] "Improve" win32 AuDebug --- Include/Aurora/Runtime.hpp | 25 ++++++- Source/Debug/ExceptionWatcher.NT.cpp | 20 ++++-- Source/Debug/ExceptionWatcher.Win32.cpp | 88 +++++++++++++++++-------- Source/Debug/Panic.cpp | 44 ++++++------- Source/Debug/Panic.hpp | 4 ++ 5 files changed, 120 insertions(+), 61 deletions(-) diff --git a/Include/Aurora/Runtime.hpp b/Include/Aurora/Runtime.hpp index 6f93f74a..b4c01e2e 100644 --- a/Include/Aurora/Runtime.hpp +++ b/Include/Aurora/Runtime.hpp @@ -258,14 +258,37 @@ namespace Aurora struct FIOConfig { /// You can bypass branding by assigning an empty string to 'defaultBrand' - AuString defaultBrand = "Aurora"; + AuString defaultBrand = "Aurora SDK Sample"; }; struct DebugConfig { + /** + * @brief Precache/initialize symbols for printable stack traces under binaries not intended for shipping to consumers + */ bool nonshipPrecachesSymbols {true}; + + /** + * @brief Activates the internal AddVectoredExceptionHandler handler. Might conflict with DRM and other debugging utilities + */ bool enableWin32RootExceptionHandler {true}; + + /** + * @brief + */ bool enableInjectedExceptionHandler {true}; + + /** + * @brief Causes a SysPanic + */ + bool isMemoryErrorFatal {false}; + + /** + * @brief + */ + bool isExceptionThrowFatal {false}; + + bool printExceptionStackTracesOut {true}; }; struct RuntimeStartInfo diff --git a/Source/Debug/ExceptionWatcher.NT.cpp b/Source/Debug/ExceptionWatcher.NT.cpp index 61dde367..125ceedf 100644 --- a/Source/Debug/ExceptionWatcher.NT.cpp +++ b/Source/Debug/ExceptionWatcher.NT.cpp @@ -237,14 +237,22 @@ extern "C" AUKN_SYM void __stdcall _ReportMSVCSEH(void *exception, const void *t try { - auto trace = AuDebug::GetStackTrace(); - AuDebug::ReportSEH(handle, exception, throwInfo, {}, trace, - [&](const AuString &str) + + if (gRuntimeConfig.debug.printExceptionStackTracesOut) { - AuLogWarn("Local MSVC Exception: 0x{:x}, {}", exception, str.c_str()); - AuLogWarn("{}", StringifyStackTrace(trace)); - }); + AuDebug::ReportSEH(handle, exception, throwInfo, {}, trace, + [&](const AuString &str) + { + AuLogWarn("Local MSVC Exception: 0x{:x}, {}", exception, str.c_str()); + AuLogWarn("{}", StringifyStackTrace(trace)); + }); + } + else + { + AuDebug::ReportSEH(handle, exception, throwInfo, {}, trace, + [&](const AuString &str) {}); + } } catch (...) { diff --git a/Source/Debug/ExceptionWatcher.Win32.cpp b/Source/Debug/ExceptionWatcher.Win32.cpp index 5f90040b..1d210813 100644 --- a/Source/Debug/ExceptionWatcher.Win32.cpp +++ b/Source/Debug/ExceptionWatcher.Win32.cpp @@ -106,26 +106,53 @@ namespace Aurora::Debug return (info.Protect & (PAGE_READONLY | PAGE_READWRITE)) != 0; } + bool InPanic(); + static LONG CALLBACK HandleVectorException(_EXCEPTION_POINTERS *ExceptionInfo) { if (ExceptionInfo->ExceptionRecord->ExceptionCode == DBG_CONTROL_C) { Exit::PostLevel(AuThreads::GetThread(), Exit::ETriggerLevel::eSigTerminate); - return Exit::gHasCanceled ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH; + return AuExchange(Exit::gHasCanceled, false) ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH; } + // https://www.youtube.com/embed/w6P03sTzSqM?start=2&autoplay=1 if (ExceptionInfo->ExceptionRecord->ExceptionCode < STATUS_GUARD_PAGE_VIOLATION) { return EXCEPTION_CONTINUE_SEARCH; } + #if defined(AU_CFG_ID_SHIP) + + // you what? + if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT) + { + SysPanic(""); + return EXCEPTION_CONTINUE_EXECUTION; + } + + #else + + // debugger go brrr if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT) { return EXCEPTION_CONTINUE_SEARCH; } - auto minimal = gDebugLocked++; + #endif + // debug builds can go do something stupid + // QA builds, staging, rel in any form should just give up trying if we're under a panic + #if !defined(AU_CFG_ID_DEBUG) + if (InPanic()) + { + return EXCEPTION_CONTINUE_SEARCH; + } + #endif + + // something dumb like this mess w hat i had before. + // gave up trying + auto minimal = gDebugLocked++; if (minimal >= 5) { SysPanic("Nested Exception"); @@ -177,7 +204,6 @@ namespace Aurora::Debug StackTrace backtrace; ParseStack(ExceptionInfo->ContextRecord, backtrace); - #if defined(_AU_USE_EXTENDED_FWD_FACING_DEBUGGING) bool isInternal = true; #else @@ -191,26 +217,29 @@ namespace Aurora::Debug // Pre-submit callback -> its showtime if ((isCritical || isInternal) && (minimal == 0)) { - AuLogWarn("NT Exception: 0x{:x}, {}", ExceptionInfo->ExceptionRecord->ExceptionCode, str); - AuLogWarn("{}", StringifyStackTrace(backtrace)); + if (gRuntimeConfig.debug.printExceptionStackTracesOut) + { + AuLogWarn("NT Exception: 0x{:x}, {}", ExceptionInfo->ExceptionRecord->ExceptionCode, str); + AuLogWarn("{}", StringifyStackTrace(backtrace)); + } } }); } try { + Grug::Arrow empty; + Grug::HurlRaiseProblematicEvent(&empty); + if (isCritical) { Telemetry::Mayday(); } - if (isCritical) + if (isCritical || gRuntimeConfig.debug.isExceptionThrowFatal) // exception = literally anything { PlatformHandleFatal(true); } - - Grug::Arrow empty; - Grug::HurlRaiseProblematicEvent(&empty); } catch (...) { @@ -314,15 +343,13 @@ namespace Aurora::Debug { AuString path; HANDLE hFile; - std::wstring wpath; AuString utf8Path; MINIDUMP_EXCEPTION_INFORMATION info; - auto ok = AuIOFS::GetProfileDomain(path); + auto ok = AuIOFS::GetProfileDomain(path); // < could throw inside if (!ok) { - AuLogWarn("Couldn't find minidump directory"); - goto miniMiniDumpOut; + path = ".\\"; } info.ClientPointers = true; @@ -336,22 +363,22 @@ namespace Aurora::Debug MiniDumpWithThreadInfo; - while (wpath.empty()) - { - try - { - utf8Path = path + "Crashes/" + GetDumpName(); - wpath = Locale::ConvertFromUTF8(utf8Path); - } - catch (...) - { + static std::wstring pathStorage(8192, L' '); - } - } + int index {}; - AuIOFS::CreateDirectories(utf8Path, true); + index += MultiByteToWideChar(CP_UTF8, 0, path.c_str(), path.length(), pathStorage.data() + index, pathStorage.size() - index); + static const std::string crashesSlash = "Crashes\\"; + index += MultiByteToWideChar(CP_UTF8, 0, crashesSlash.c_str(), crashesSlash.length(), pathStorage.data() + index, pathStorage.size() - index); - hFile = CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + auto dumpName = GetDumpName();; + index += MultiByteToWideChar(CP_UTF8, 0, dumpName.c_str(), dumpName.length(), pathStorage.data() + index, pathStorage.size() - index); + + pathStorage.resize(index); + + AuIOFS::CreateDirectories(utf8Path, true); // potentially unsafe / could throw inside + + hFile = CreateFileW(pathStorage.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (hFile != INVALID_HANDLE_VALUE) { AuLogWarn("[1] Couldn't open minidump file. Has a debugger locked the .dmp file?"); @@ -370,7 +397,7 @@ namespace Aurora::Debug miniMiniDumpOut: Telemetry::NewBlackBoxEntryMinidump report {}; report.includesRx = false; - report.resource.path = path; + report.resource.path = dumpName; //