From a3ba48adecb7cde429beddfea3b1ceca6a722f95 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 4 Jun 2025 00:06:11 +1200 Subject: [PATCH] 'Generic Commit' --- Dockerfile.dropshell-build | 4 ++- ipdemo/src/assert.hpp | 61 ++++++++++++++++++++++++++++++++++---- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/Dockerfile.dropshell-build b/Dockerfile.dropshell-build index b0c978e..402f100 100644 --- a/Dockerfile.dropshell-build +++ b/Dockerfile.dropshell-build @@ -32,7 +32,9 @@ RUN apk add --no-cache \ libdwarf-dev \ elfutils \ elfutils-dev \ - elfutils-libelf + elfutils-libelf \ + binutils \ + binutils-dev #RUN apk add --no-cache --update --repository=https://dl-cdn.alpinelinux.org/alpine/v3.16/main/ libexecinfo-dev diff --git a/ipdemo/src/assert.hpp b/ipdemo/src/assert.hpp index 24bb2b8..20c7025 100644 --- a/ipdemo/src/assert.hpp +++ b/ipdemo/src/assert.hpp @@ -8,6 +8,11 @@ #include #include #include +#include +#include +#include +#include +#include // Simple RAII wrapper for file descriptor class FileDescriptor { @@ -20,6 +25,27 @@ public: FileDescriptor& operator=(const FileDescriptor&) = delete; }; +std::string get_addr2line_info(const char* executable, void* addr) { + char cmd[512]; + snprintf(cmd, sizeof(cmd), "addr2line -f -p -e %s %p 2>/dev/null", executable, addr); + + FILE* pipe = popen(cmd, "r"); + if (!pipe) return ""; + + char buffer[1024]; + std::string result; + while (fgets(buffer, sizeof(buffer), pipe) != nullptr) { + result += buffer; + } + pclose(pipe); + + // Remove trailing newline if present + if (!result.empty() && result.back() == '\n') { + result.pop_back(); + } + return result; +} + void print_stacktrace() { unw_cursor_t cursor; unw_context_t context; @@ -28,6 +54,15 @@ void print_stacktrace() { char *name = sym; int status; int frame_num = 0; + char exe_path[1024] = {0}; + + // Get the path to the current executable + ssize_t count = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1); + if (count == -1) { + strcpy(exe_path, "[unknown]"); + } else { + exe_path[count] = '\0'; + } // Initialize cursor to current frame unw_getcontext(&context); @@ -43,7 +78,7 @@ void print_stacktrace() { } std::cerr << "#" << frame_num++ << " "; - + // Get symbol name if (unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0) { // Demangle the C++ name @@ -51,21 +86,37 @@ void print_stacktrace() { size_t length = sizeof(sym); name = abi::__cxa_demangle(sym, nullptr, &length, &status); + // Get line info using addr2line + std::string line_info = get_addr2line_info(exe_path, (void*)pc); + Dl_info info; if (dladdr(reinterpret_cast(pc), &info) && info.dli_fname) { - std::cerr << "in " << info.dli_fname << ": "; + const char* base = strrchr(info.dli_fname, '/'); + std::cerr << (base ? base + 1 : info.dli_fname) << ": "; } if (name) { - std::cerr << name << " + 0x" << std::hex << offset; + std::cerr << name; free(name); } else { - std::cerr << sym << " + 0x" << std::hex << offset; + std::cerr << sym; + } + + std::cerr << " + 0x" << std::hex << offset; + + if (!line_info.empty()) { + std::cerr << " at " << line_info; } std::cerr << " [0x" << std::hex << pc << "]\n"; } else { - std::cerr << "[unknown] [0x" << std::hex << pc << "]\n"; + std::cerr << "[unknown] [0x" << std::hex << pc << "]"; + // Try to get at least some info with addr2line even for unknown symbols + std::string line_info = get_addr2line_info(exe_path, (void*)pc); + if (!line_info.empty()) { + std::cerr << " at " << line_info; + } + std::cerr << "\n"; } } }