// stacktrace.h (c) 2008, Timo Bingmann from http://idlebox.net/ // published under the WTFPL v2.0 #ifndef _STACKTRACE_H_ #define _STACKTRACE_H_ #include #include #include #include /** Print a demangled stack backtrace of the caller function to FILE* out. */ inline static void print_stacktrace( FILE* out = stdout, unsigned int max_frames = 3) { fprintf(out, "stack trace:\n"); // storage array for stack trace address data void* addrlist[max_frames + 1]; // retrieve current stack addresses int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*)); if (addrlen == 0) { fprintf(out, " \n"); return; } // 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 = 256; 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 char line[256]; sprintf(line, " %s : %s+%s\n", symbollist[i], funcname, begin_offset); int y = 0; } else { // demangling failed. Output function name as a C function with // no arguments. char line[256]; sprintf(line, " %s : %s()+%s\n", symbollist[i], begin_name, begin_offset); int x = 0; } } else { // couldn't parse the line? print the whole line. char line[256]; sprintf(line, " %s\n", symbollist[i]); int x = 0; } } free(funcname); free(symbollist); } #endif // _STACKTRACE_H_