From ae8a12fa27643fc227b4fcd0e0da035c3ecc1073 Mon Sep 17 00:00:00 2001 From: Zephyr Lykos Date: Sun, 10 Aug 2025 01:46:01 +0800 Subject: [PATCH] impr: Show external frames when using std::stacktrace backend (#2302) ### Problem description `std::stacktrace` backend in `hex::trace` does not show frames for external libraries. ### Implementation description If `dlfcn.h` is available, use `dladdr` to retrieve external symbol information. ### Screenshots Before: ``` [02:33:46] [FATAL] [main | Main] Printing stacktrace using implementation 'std::stacktrace' [02:33:46] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/lib/trace/source/stacktrace.cpp:34) | hex::trace::getStackTrace() [02:33:46] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/main/gui/source/crash_handlers.cpp:75) | printStackTrace [02:33:46] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/main/gui/source/crash_handlers.cpp:125) | hex::crash::handleCrash(std::__cxx11::basic_string, std::allocator > const&) [02:33:46] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/main/gui/source/crash_handlers.cpp:211) | operator() [02:33:46] [FATAL] [main | Main] () | ?? [02:33:46] [FATAL] [main | Main] () | ?? [02:33:46] [FATAL] [main | Main] () | ?? [02:33:46] [FATAL] [main | Main] () | ?? [02:33:46] [FATAL] [main | Main] () | ?? [02:33:46] [FATAL] [main | Main] () | ?? [02:33:46] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/lib/third_party/imgui/backend/source/imgui_impl_glfw.cpp:844) | ImGui_ImplGlfw_UpdateMouseData [02:33:46] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/main/gui/source/window/window.cpp:353) | hex::Window::frameBegin() [02:33:46] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/main/gui/source/window/window.cpp:241) | hex::Window::fullFrame() [02:33:46] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/main/gui/source/window/window.cpp:297) | hex::Window::loop() [02:33:46] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/main/gui/source/init/run/native.cpp:43) | hex::init::runImHex() [02:33:46] [FATAL] [main | Main] () | ?? [02:33:46] [FATAL] [main | Main] () | ?? [02:33:47] [FATAL] [main | Main] () | ?? [02:33:47] [FATAL] [main | Main] () | ?? ``` After: ``` [02:30:19] [FATAL] [main | Main] Printing stacktrace using implementation 'std::stacktrace' [02:30:19] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/lib/trace/source/stacktrace.cpp:41) | hex::trace::getStackTrace() [02:30:19] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/main/gui/source/crash_handlers.cpp:75) | printStackTrace [02:30:19] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/main/gui/source/crash_handlers.cpp:125) | hex::crash::handleCrash(std::__cxx11::basic_string, std::allocator > const&) [02:30:19] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/main/gui/source/crash_handlers.cpp:211) | operator() [02:30:19] [FATAL] [main | Main] (/lib64/libc.so.6) | libc.so.6+0x00019bef [02:30:19] [FATAL] [main | Main] (/lib64/libc.so.6) | libc.so.6+0x00073c2c [02:30:19] [FATAL] [main | Main] (/lib64/libc.so.6) | gsignal+0x1d [02:30:19] [FATAL] [main | Main] (/lib64/libc.so.6) | abort+0x25 [02:30:19] [FATAL] [main | Main] (/lib64/libc.so.6) | libc.so.6+0x00001638 [02:30:19] [FATAL] [main | Main] (/lib64/libglfw.so.3) | libglfw.so.3+0x00002275 [02:30:19] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/lib/third_party/imgui/backend/source/imgui_impl_glfw.cpp:844) | ImGui_ImplGlfw_UpdateMouseData [02:30:19] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/main/gui/source/window/window.cpp:353) | hex::Window::frameBegin() [02:30:19] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/main/gui/source/window/window.cpp:241) | hex::Window::fullFrame() [02:30:19] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/main/gui/source/window/window.cpp:297) | hex::Window::loop() [02:30:19] [FATAL] [main | Main] (/home/mochaa/ghq/github.com/WerWolv/ImHex/main/gui/source/init/run/native.cpp:43) | hex::init::runImHex() [02:30:19] [FATAL] [main | Main] (/lib64/libc.so.6) | libc.so.6+0x000035b4 [02:30:19] [FATAL] [main | Main] (/lib64/libc.so.6) | __libc_start_main+0x87 [02:30:19] [FATAL] [main | Main] (./build/imhex) | imhex+0x0000cd94 [02:30:19] [FATAL] [main | Main] (??) | +0xffffffffffffffff ``` ### Additional things None --- lib/trace/source/stacktrace.cpp | 38 ++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/lib/trace/source/stacktrace.cpp b/lib/trace/source/stacktrace.cpp index aff6e4340..3286f969f 100644 --- a/lib/trace/source/stacktrace.cpp +++ b/lib/trace/source/stacktrace.cpp @@ -23,6 +23,13 @@ namespace hex::trace { #if defined(HEX_HAS_STD_STACKTRACE) && __has_include() #include + + #if __has_include() + + #include + #include + + #endif namespace hex::trace { @@ -36,10 +43,35 @@ namespace hex::trace { auto stackTrace = std::stacktrace::current(); for (const auto &entry : stackTrace) { - if (entry.source_line() == 0 && entry.source_file().empty()) + if (entry.source_line() == 0 && entry.source_file().empty()) { + #if __has_include() + Dl_info info = {}; + dladdr(reinterpret_cast(entry.native_handle()), &info); + + std::string description; + + auto path = info.dli_fname != nullptr ? std::optional{info.dli_fname} : std::nullopt; + auto filePath = path ? path->string() : "??"; + auto fileName = path ? path->filename().string() : ""; + + if (info.dli_sname != nullptr) { + description = tryDemangle(info.dli_sname); + if (info.dli_saddr != reinterpret_cast(entry.native_handle())) { + auto symOffset = entry.native_handle() - reinterpret_cast(info.dli_saddr); + description += std::format("+0x{:x}", symOffset); + } + } else { + auto rvaOffset = entry.native_handle() - reinterpret_cast(info.dli_fbase); + description = std::format("{}+0x{:08x}", fileName, rvaOffset); + } + + result.emplace_back(filePath, description, 0); + #else result.emplace_back("", "??", 0); - else + #endif + } else { result.emplace_back(entry.source_file(), entry.description(), entry.source_line()); + } } return { result, "std::stacktrace" }; @@ -251,4 +283,4 @@ namespace hex::trace { } } -#endif \ No newline at end of file +#endif