From a1437658af941b62a54b78cda83c19643198d6d9 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Fri, 15 Mar 2024 17:53:12 +0100 Subject: [PATCH] impr: Generate more useful stack traces on Linux --- cmake/build_helpers.cmake | 20 ++-- main/gui/source/crash_handlers.cpp | 2 +- main/gui/source/stacktrace.cpp | 160 +++++++++++++++-------------- 3 files changed, 93 insertions(+), 89 deletions(-) diff --git a/cmake/build_helpers.cmake b/cmake/build_helpers.cmake index 20146a513..e28e43a86 100644 --- a/cmake/build_helpers.cmake +++ b/cmake/build_helpers.cmake @@ -655,20 +655,20 @@ macro(addBundledLibraries) if (${Backtrace_FOUND}) message(STATUS "Backtrace enabled! Header: ${Backtrace_HEADER}") - if (Backtrace_HEADER STREQUAL "execinfo.h") + if (Backtrace_HEADER STREQUAL "backtrace.h") set(LIBBACKTRACE_LIBRARIES ${Backtrace_LIBRARY}) set(LIBBACKTRACE_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR}) - add_compile_definitions(BACKTRACE_HEADER=\"${Backtrace_HEADER}\") - add_compile_definitions(HEX_HAS_EXECINFO) - elseif (Backtrace_HEADER STREQUAL "backtrace.h") - set(LIBBACKTRACE_LIBRARIES ${Backtrace_LIBRARY}) - set(LIBBACKTRACE_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR}) - add_compile_definitions(BACKTRACE_HEADER=\"${Backtrace_HEADER}\") + add_compile_definitions(BACKTRACE_HEADER=<${Backtrace_HEADER}>) add_compile_definitions(HEX_HAS_BACKTRACE) - endif () + elseif (Backtrace_HEADER STREQUAL "execinfo.h") + set(LIBBACKTRACE_LIBRARIES ${Backtrace_LIBRARY}) + set(LIBBACKTRACE_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR}) + add_compile_definitions(BACKTRACE_HEADER=<${Backtrace_HEADER}>) + add_compile_definitions(HEX_HAS_EXECINFO) + endif() endif() - endif () - endif () + endif() + endif() endmacro() function(enableUnityBuild TARGET) diff --git a/main/gui/source/crash_handlers.cpp b/main/gui/source/crash_handlers.cpp index 4b013d9e4..2657c50d3 100644 --- a/main/gui/source/crash_handlers.cpp +++ b/main/gui/source/crash_handlers.cpp @@ -65,7 +65,7 @@ namespace hex::crash { static void printStackTrace() { for (const auto &stackFrame : stacktrace::getStackTrace()) { if (stackFrame.line == 0) - log::fatal(" {}", stackFrame.function); + log::fatal(" ({}) | {}", stackFrame.file, stackFrame.function); else log::fatal(" ({}:{}) | {}", stackFrame.file, stackFrame.line, stackFrame.function); } diff --git a/main/gui/source/stacktrace.cpp b/main/gui/source/stacktrace.cpp index 84e340217..0ebb9a1e3 100644 --- a/main/gui/source/stacktrace.cpp +++ b/main/gui/source/stacktrace.cpp @@ -2,12 +2,26 @@ #include #include +#include + +namespace { + + std::string tryDemangle(const std::string &symbolName) { + if (auto variant1 = llvm::demangle(symbolName); variant1 != symbolName) + return variant1; + + if (auto variant2 = llvm::demangle(std::string("_") + symbolName); variant2 != std::string("_") + symbolName) + return variant2; + + return symbolName; + } + +} #if defined(OS_WINDOWS) #include #include - #include namespace hex::stacktrace { @@ -80,14 +94,7 @@ fileName = "??"; } - std::string demangledName; - if (auto variant1 = llvm::demangle(symbolName); variant1 != symbolName) - demangledName = variant1; - else if (auto variant2 = llvm::demangle(std::string("_") + symbolName); variant2 != std::string("_") + symbolName) - demangledName = variant2; - else - demangledName = symbolName; - + auto demangledName = tryDemangle(symbolName); stackTrace.push_back(StackFrame { fileName, demangledName, lineNumber }); } @@ -100,80 +107,77 @@ #elif defined(HEX_HAS_EXECINFO) - #if __has_include(BACKTRACE_HEADER) + #include BACKTRACE_HEADER + #include + #include - #include BACKTRACE_HEADER - #include - #include - #include + namespace hex::stacktrace { - namespace hex::stacktrace { - - void initialize() { - - } - - std::vector getStackTrace() { - static std::vector result; - - std::array addresses; - size_t count = backtrace(addresses.data(), addresses.size()); - auto functions = backtrace_symbols(addresses.data(), count); - - for (size_t i = 0; i < count; i++) - result.push_back(StackFrame { "", functions[i], 0 }); - - return result; - } - - } - #endif - -#elif defined(HEX_HAS_BACKTRACE) - - #if __has_include(BACKTRACE_HEADER) - - #include BACKTRACE_HEADER - #include - #include - #include - - namespace hex::stacktrace { - - static struct backtrace_state *s_backtraceState; - - - void initialize() { - if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value()) { - static std::string path = executablePath->string(); - s_backtraceState = backtrace_create_state(path.c_str(), 1, [](void *, const char *msg, int) { log::error("{}", msg); }, nullptr); - } - } - - std::vector getStackTrace() { - static std::vector result; - - result.clear(); - if (s_backtraceState != nullptr) { - backtrace_full(s_backtraceState, 0, [](void *, uintptr_t, const char *fileName, int lineNumber, const char *function) -> int { - if (fileName == nullptr) - fileName = "??"; - if (function == nullptr) - function = "??"; - - result.push_back(StackFrame { std::fs::path(fileName).filename().string(), llvm::demangle(function), u32(lineNumber) }); - - return 0; - }, nullptr, nullptr); - - } - - return result; - } + void initialize() { } - #endif + std::vector getStackTrace() { + static std::vector result; + + std::array addresses = {}; + const size_t count = backtrace(addresses.data(), addresses.size()); + + Dl_info info; + for (size_t i = 0; i < count; i += 1) { + dladdr(addresses[i], &info); + + auto fileName = info.dli_fname != nullptr ? std::fs::path(info.dli_fname).filename().string() : "??"; + auto demangledName = info.dli_sname != nullptr ? tryDemangle(info.dli_sname) : "??"; + + result.push_back(StackFrame { std::move(fileName), std::move(demangledName), 0 }); + } + + return result; + } + + } + +#elif defined(HEX_HAS_BACKTRACE) && __has_include(BACKTRACE_HEADER) + + #include BACKTRACE_HEADER + #include + #include + + namespace hex::stacktrace { + + static struct backtrace_state *s_backtraceState; + + + void initialize() { + if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value()) { + static std::string path = executablePath->string(); + s_backtraceState = backtrace_create_state(path.c_str(), 1, [](void *, const char *msg, int) { log::error("{}", msg); }, nullptr); + } + } + + std::vector getStackTrace() { + static std::vector result; + + result.clear(); + if (s_backtraceState != nullptr) { + backtrace_full(s_backtraceState, 0, [](void *, uintptr_t, const char *fileName, int lineNumber, const char *function) -> int { + if (fileName == nullptr) + fileName = "??"; + if (function == nullptr) + function = "??"; + + result.push_back(StackFrame { std::fs::path(fileName).filename().string(), tryDemangle(function), u32(lineNumber) }); + + return 0; + }, nullptr, nullptr); + + } + + return result; + } + + } #else