impr: Generate more useful stack traces on Linux

This commit is contained in:
WerWolv
2024-03-15 17:53:12 +01:00
parent f4ec69021d
commit a1437658af
3 changed files with 93 additions and 89 deletions

View File

@@ -2,12 +2,26 @@
#include <hex/helpers/fmt.hpp>
#include <array>
#include <llvm/Demangle/Demangle.h>
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 <windows.h>
#include <dbghelp.h>
#include <llvm/Demangle/Demangle.h>
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 <hex/helpers/utils.hpp>
#include <dlfcn.h>
#include BACKTRACE_HEADER
#include <llvm/Demangle/Demangle.h>
#include <hex/helpers/logger.hpp>
#include <hex/helpers/utils.hpp>
namespace hex::stacktrace {
namespace hex::stacktrace {
void initialize() {
}
std::vector<StackFrame> getStackTrace() {
static std::vector<StackFrame> result;
std::array<void*, 128> 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 <llvm/Demangle/Demangle.h>
#include <hex/helpers/logger.hpp>
#include <hex/helpers/utils.hpp>
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<StackFrame> getStackTrace() {
static std::vector<StackFrame> 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<StackFrame> getStackTrace() {
static std::vector<StackFrame> result;
std::array<void*, 128> 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 <hex/helpers/logger.hpp>
#include <hex/helpers/utils.hpp>
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<StackFrame> getStackTrace() {
static std::vector<StackFrame> 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