From 2ce8ea0c3f9969b737b626265d896304d6306636 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Thu, 13 Mar 2025 04:23:38 -0400 Subject: [PATCH] In system::getStackTrace(), use dladdr() instead of backtrace_symbols() on Linux and Mac. --- src/system.cpp | 75 ++++++++++++++++---------------------------------- 1 file changed, 24 insertions(+), 51 deletions(-) diff --git a/src/system.cpp b/src/system.cpp index d4130b18..190b6da3 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -17,6 +17,7 @@ #include // for backtrace and backtrace_symbols #include // for execl #include + #include // for dladdr #endif #if defined ARCH_MAC @@ -671,67 +672,39 @@ std::string getStackTrace() { #if defined ARCH_LIN || defined ARCH_MAC stackLen = backtrace(stack, stackLen); - char** strings = backtrace_symbols(stack, stackLen); - if (!strings) - return ""; // Skip the first line because it's this function. for (int i = 1; i < stackLen; i++) { - s += string::f("%d: ", stackLen - i - 1); - std::string line = strings[i]; -#if ARCH_LIN - // Parse line, e.g. - // ./main(__mangled_symbol+0x100) [0x12345678] - std::regex r(R"((.+?)\((.*?)\+(.+?)\) (.+?))"); - std::smatch match; - if (std::regex_match(line, match, r)) { - s += match[1].str(); - s += "("; - std::string symbol = match[2].str(); - // Demangle symbol - char* symbolD = abi::__cxa_demangle(symbol.c_str(), NULL, NULL, NULL); - if (symbolD) { - symbol = symbolD; - free(symbolD); - } - s += symbol; - s += "+"; - s += match[3].str(); - s += ")"; - } - else { - // If regex fails, just use the raw line - s += line; + // Get symbol info from stack address + Dl_info info = {}; + if (dladdr(stack[i], &info)) { + // Ignore error } -#elif defined ARCH_MAC - // Parse line, e.g. - // 1 Rack 0x0000000002ddc3eb _mangled_symbol + 27 - std::regex r(R"((\d+)\s+(.+?)\s+(.+?) (.*?) \+ (.+?))"); - std::smatch match; - if (std::regex_match(line, match, r)) { - s += match[2].str(); - s += "("; - std::string symbol = match[4].str(); - // Demangle symbol - char* symbolD = abi::__cxa_demangle(symbol.c_str(), NULL, NULL, NULL); - if (symbolD) { - symbol = symbolD; - free(symbolD); + + // Binary/library filename + s += info.dli_fname ? info.dli_fname : "??"; + s += ": "; + + // Attempt to demangle C++ symbol name + if (info.dli_sname) { + char* demangled = abi::__cxa_demangle(info.dli_sname, NULL, NULL, NULL); + if (demangled) { + s += demangled; + free(demangled); + } + else { + s += info.dli_sname; } - s += symbol; - s += "+"; - s += match[5].str(); - s += ")"; } else { - // If regex fails, just use the raw line - s += line; + s += "??"; } -#endif + + s += " +"; + ptrdiff_t offset = (char*) stack[i] - (char*) info.dli_saddr; + s += string::f("0x%x", offset); s += "\n"; } - free(strings); - #elif defined ARCH_WIN HANDLE process = GetCurrentProcess(); SymInitialize(process, NULL, true);