From dfd23f7e8f23562cc8da1db49b89c4d93dc0640c Mon Sep 17 00:00:00 2001 From: Alexandre Bique Date: Sat, 14 Feb 2009 13:28:20 +0000 Subject: [PATCH] demangled backtrace --- src/core/assert.cc | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/core/assert.hh | 32 +++-------------------- 2 files changed, 81 insertions(+), 28 deletions(-) diff --git a/src/core/assert.cc b/src/core/assert.cc index 2c81462..fe34a62 100644 --- a/src/core/assert.cc +++ b/src/core/assert.cc @@ -1,7 +1,84 @@ +#include +#include +#include + #include namespace core { + void assert_print_stack_trace(void) + { + void * addrlist[64]; + int addrlen; + + // get the address + addrlen = backtrace(addrlist, sizeof (addrlist) / sizeof (addrlist[0])); + + // resolve addresses into strings containing "filename(function+address)", + // this array must be free()-ed + char ** symbollist = backtrace_symbols(addrlist, addrlen); + + // allocate string which will be filled with the demangled function name + size_t funcnamesize = 1024; + char * funcname = (char*)malloc(funcnamesize); + + // iterate over the returned symbol lines. skip the first, it is the + // address of this function. + for (int i = 1; i < addrlen; i++) + { + char *begin_name = 0, *begin_offset = 0, *end_offset = 0; + + // find parentheses and +address offset surrounding the mangled name: + // ./module(function+0x15c) [0x8048a6d] + for (char *p = symbollist[i]; *p; ++p) + { + if (*p == '(') + begin_name = p; + else if (*p == '+') + begin_offset = p; + else if (*p == ')' && begin_offset) { + end_offset = p; + break; + } + } + + if (begin_name && begin_offset && end_offset + && begin_name < begin_offset) + { + *begin_name++ = '\0'; + *begin_offset++ = '\0'; + *end_offset = '\0'; + + // mangled name is now in [begin_name, begin_offset) and caller + // offset in [begin_offset, end_offset). now apply + // __cxa_demangle(): + + int status; + char* ret = abi::__cxa_demangle(begin_name, + funcname, &funcnamesize, &status); + if (status == 0) { + funcname = ret; // use possibly realloc()-ed string + fprintf(stderr, "%s: %s+%s\n", + symbollist[i], funcname, begin_offset); + } + else { + // demangling failed. Output function name as a C function with + // no arguments. + fprintf(stderr, "%s: %s()+%s\n", + symbollist[i], begin_name, begin_offset); + } + } + else + { + // couldn't parse the line? print the whole line. + fprintf(stderr, "%s\n", symbollist[i]); + } + } + + free(funcname); + free(symbollist); + } + void assert_trap(void) { } diff --git a/src/core/assert.hh b/src/core/assert.hh index 1ca0af5..e5867ed 100644 --- a/src/core/assert.hh +++ b/src/core/assert.hh @@ -5,14 +5,14 @@ namespace core { /** @brief This function is a trap on which you can put a breakpoint. */ void assert_trap(void); + /** @brief print the stack trace, and demangle it */ + void assert_print_stack_trace(void); } # ifndef NDEBUG -# include # include # include -# include # ifdef assert # undef assert @@ -23,14 +23,6 @@ namespace core do { \ if (!(Cond)) \ { \ - void *__array[50]; \ - int __size; \ - char **__strings; \ - int __assert_i; \ - \ - __size = backtrace(__array, 50); \ - __strings = backtrace_symbols(__array, __size); \ - \ fprintf(stderr, \ "\e[1;31m" \ "======== ASSERT FAILED (\e[0;33m%s\e[1;31m) ========\n" \ @@ -38,11 +30,7 @@ namespace core "location:\t\e[0;34m%s\e[1;31m:\e[0;35m%d\e[1;31m\n" \ "======== BACKTRACE ========\n\e[0;36m", \ #Cond, __PRETTY_FUNCTION__, __FILE__, __LINE__); \ - for (__assert_i = 0; __assert_i < __size; __assert_i++) \ - fprintf(stderr, "%s\n", __strings[__assert_i]); \ - fprintf(stderr, "\e[m"); \ - free(__strings); \ - \ + ::core::assert_print_stack_trace(); \ ::core::assert_trap(); \ abort(); \ } \ @@ -53,14 +41,6 @@ namespace core do { \ if (!(Cond)) \ { \ - void *__array[50]; \ - int __size; \ - char **__strings; \ - int __assert_i; \ - \ - __size = backtrace(__array, 50); \ - __strings = backtrace_symbols(__array, __size); \ - \ fprintf(stderr, \ "\e[1;31m" \ "======== ASSERT FAILED (\e[0;33m%s\e[1;31m) ========\n" \ @@ -69,11 +49,7 @@ namespace core "message:\t\e[0;34m%s\e[1;31m\n" \ "======== BACKTRACE ========\n\e[0;36m", \ #Cond, __PRETTY_FUNCTION__, __FILE__, __LINE__, (Msg)); \ - for (__assert_i = 0; __assert_i < __size; __assert_i++) \ - fprintf(stderr, "%s\n", __strings[__assert_i]); \ - fprintf(stderr, "\e[m"); \ - free(__strings); \ - \ + ::core::assert_print_stack_trace(); \ ::core::assert_trap(); \ abort(); \ } \ -- 2.11.4.GIT