From: Brian Norris Date: Mon, 8 Oct 2012 06:25:48 +0000 (-0700) Subject: Merge branch 'norris' X-Git-Url: http://plrg.eecs.uci.edu/git/?p=c11tester.git;a=commitdiff_plain;h=8f379cb70822bfd5498da9997ad4f7c3b37a18ed;hp=9b894e117ad1090ad6f54753cde7fd9b6ea60ab7 Merge branch 'norris' --- diff --git a/common.cc b/common.cc index e05e094e..b274989f 100644 --- a/common.cc +++ b/common.cc @@ -4,12 +4,17 @@ #include "common.h" #include "model.h" +#include "stacktrace.h" #define MAX_TRACE_LEN 100 +#define CONFIG_STACKTRACE /** Print a backtrace of the current program state. */ void print_trace(void) { +#ifdef CONFIG_STACKTRACE + print_stacktrace(stdout); +#else void *array[MAX_TRACE_LEN]; char **strings; int size, i; @@ -23,6 +28,7 @@ void print_trace(void) printf("\t%s\n", strings[i]); free(strings); +#endif /* CONFIG_STACKTRACE */ } void model_print_summary(void) diff --git a/stacktrace.h b/stacktrace.h new file mode 100644 index 00000000..01d31d2f --- /dev/null +++ b/stacktrace.h @@ -0,0 +1,86 @@ +// 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. */ +static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames = 63) +{ + 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 + fprintf(out, " %s : %s+%s\n", + symbollist[i], funcname, begin_offset); + } else { + // demangling failed. Output function name as a C function with + // no arguments. + fprintf(out, " %s : %s()+%s\n", + symbollist[i], begin_name, begin_offset); + } + } else { + // couldn't parse the line? print the whole line. + fprintf(out, " %s\n", symbollist[i]); + } + } + + free(funcname); + free(symbollist); +} + +#endif // __STACKTRACE_H__