From 6f9ac54bd6f3253c117a6aa9dd48df49c38a4e0d Mon Sep 17 00:00:00 2001 From: Ayrton Munoz Date: Mon, 4 Nov 2024 21:07:32 -0500 Subject: [PATCH] libia2: Replace libc backtrace with libunwind backtrace(3) doesn't support unwinding through PLT stubs so this commit replaces it with libunwind. Since we want backtraces on by default I'm not sure if this is exactly what we want but it's good enough for now. --- runtime/libia2/CMakeLists.txt | 5 +++++ runtime/libia2/ia2.c | 24 +++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/runtime/libia2/CMakeLists.txt b/runtime/libia2/CMakeLists.txt index 8c9c3f259..5bc1c03ec 100644 --- a/runtime/libia2/CMakeLists.txt +++ b/runtime/libia2/CMakeLists.txt @@ -19,6 +19,7 @@ endif() target_link_options(libia2 INTERFACE + "-lunwind" "-pthread" "-Wl,--wrap=pthread_create" "-Wl,--wrap=main" @@ -29,6 +30,10 @@ target_link_options(libia2 "-Wl,-z,relro" ) +if (LIBIA2_X86_64) + target_link_options(libia2 INTERFACE "-lunwind-x86_64") +endif() + target_link_libraries(libia2 PRIVATE dl) target_include_directories(libia2 PUBLIC include) diff --git a/runtime/libia2/ia2.c b/runtime/libia2/ia2.c index bed6a3f88..9f1e822d7 100644 --- a/runtime/libia2/ia2.c +++ b/runtime/libia2/ia2.c @@ -1,7 +1,7 @@ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif -#include +#include #include #include #include @@ -511,15 +511,21 @@ int protect_pages(struct dl_phdr_info *info, size_t size, void *data) { #if IA2_DEBUG void ia2_print_backtrace(void) { -#define IA2_BT_SZ 10 - void *ra_buf[IA2_BT_SZ]; - int num_ra = backtrace(ra_buf, IA2_BT_SZ); - char **fn_names = backtrace_symbols(ra_buf, num_ra); - for (size_t i = 0; i < num_ra; i++) { - if (fn_names) { - fprintf(stderr, "#%d %p in %s ()\n", i, ra_buf[i], fn_names[i]); + unw_cursor_t cursor; + unw_context_t uc; + unw_word_t pc; + + unw_getcontext(&uc); + unw_init_local(&cursor, &uc); + int i = 0; + while (unw_step(&cursor) > 0) { + unw_get_reg(&cursor, UNW_REG_IP, &pc); + Dl_info dlinf = {0}; + bool found = dladdr((void *)pc, &dlinf) != 0; + if (found) { + fprintf(stderr, "#%d %p in %s ()\n", i++, (void *)pc, dlinf.dli_sname); } else { - fprintf(stderr, "#%d %p ()\n", i, ra_buf[i]); + fprintf(stderr, "#%d %p ()\n", i++, (void *)pc); } } fflush(stderr);