From ac88aa934de9a7e5731a0af81c9a8fa134c1b965 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Wed, 7 Sep 2016 20:13:49 -1000 Subject: [PATCH] Add backtrace print to fatal logvisor errors --- include/logvisor/logvisor.hpp | 11 ++++- lib/logvisor.cpp | 92 ++++++++++++++++++++++++++++++++++- 2 files changed, 99 insertions(+), 4 deletions(-) diff --git a/include/logvisor/logvisor.hpp b/include/logvisor/logvisor.hpp index dca373e..d8fed01 100644 --- a/include/logvisor/logvisor.hpp +++ b/include/logvisor/logvisor.hpp @@ -15,6 +15,8 @@ extern "C" void logvisorBp(); namespace logvisor { +void logvisorAbort(); + #if _WIN32 && UNICODE #define LOG_UCS2 1 #endif @@ -114,6 +116,11 @@ void RegisterConsoleLogger(); */ void RegisterFileLogger(const char* filepath); +/** + * @brief Register signal handlers with system for common client exceptions + */ +void RegisterStandardExceptions(); + #if _WIN32 /** * @brief Spawn an application-owned cmd.exe window for displaying console output @@ -170,7 +177,7 @@ public: if (severity == Error || severity == Fatal) logvisorBp(); if (severity == Fatal) - abort(); + logvisorAbort(); else if (severity == Error) ++ErrorCount; } @@ -204,7 +211,7 @@ public: } if (severity == Fatal) - abort(); + logvisorAbort(); else if (severity == Error) ++ErrorCount; } diff --git a/lib/logvisor.cpp b/lib/logvisor.cpp index a4699e2..bdf863f 100644 --- a/lib/logvisor.cpp +++ b/lib/logvisor.cpp @@ -7,19 +7,19 @@ #endif #include #include -#include #else #include -#include #include #endif +#include #include #include #include #include #include #include +#include #include "logvisor/logvisor.hpp" /* ANSI sequences */ @@ -39,6 +39,7 @@ void logvisorBp() {} namespace logvisor { +static Module Log("logvisor"); static std::unordered_map ThreadMap; void RegisterThreadName(const char* name) @@ -66,6 +67,86 @@ void RegisterThreadName(const char* name) #endif } +#if _WIN32 +#include +#pragma comment(lib, "Dbghelp.lib") + +static void logvisorAbort() +{ + unsigned int i; + void* stack[100]; + unsigned short frames; + SYMBOL_INFO* symbol; + HANDLE process; + + process = GetCurrentProcess(); + SymInitialize(process, NULL, TRUE); + frames = CaptureStackBackTrace(0, 100, stack, NULL); + symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); + symbol->MaxNameLen = 255; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + + for (i = 0; i < frames; i++) + { + SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); + + printf("%i: %s - 0x%0llX", frames - i - 1, symbol->Name, symbol->Address); + + DWORD dwDisplacement; + IMAGEHLP_LINE64 line; + SymSetOptions(SYMOPT_LOAD_LINES); + + line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + if (SymGetLineFromAddr64(process, (DWORD64)(stack[i]), &dwDisplacement, &line)) + { + // SymGetLineFromAddr64 returned success + printf(" LINE %d\n", line.LineNumber); + } + else + { + printf("\n"); + } + } + + free(symbol); + + // If you caught one of the above signals, it is likely you just + // want to quit your program right now. + abort(); +} +#else + +#include +void logvisorAbort() +{ + void* array[128]; + size_t size = backtrace(array, 128); + char** strings = backtrace_symbols(array, size); + + for (size_t i = 0; i < size; i++) + printf("%s\n", strings[i]); + + free(strings); + abort(); +} + +#endif + +static void AbortHandler(int signum) +{ + switch (signum) + { + case SIGSEGV: + Log.report(logvisor::Fatal, "Segmentation Fault"); + case SIGILL: + Log.report(logvisor::Fatal, "Bad Execution"); + case SIGFPE: + Log.report(logvisor::Fatal, "Floating Point Exception"); + default: + Log.report(logvisor::Fatal, "unknown signal %d", signum); + } +} + std::vector> MainLoggers; std::atomic_size_t ErrorCount(0); static std::chrono::steady_clock MonoClock; @@ -314,6 +395,13 @@ void CreateWin32Console() } #endif +void RegisterStandardExceptions() +{ + signal(SIGSEGV, AbortHandler); + signal(SIGILL, AbortHandler); + signal(SIGFPE, AbortHandler); +} + struct FileLogger : public ILogger { FILE* fp;