X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/66b0686fe441796325c3b5738b1b880d15ce1ea6..1f27be8ecd303fa9f686a2ca2ad1987cc4658180:/src/xbt/backtrace_linux.c diff --git a/src/xbt/backtrace_linux.c b/src/xbt/backtrace_linux.c index e57e486018..4fc1ebc6f4 100644 --- a/src/xbt/backtrace_linux.c +++ b/src/xbt/backtrace_linux.c @@ -25,13 +25,64 @@ void xbt_backtrace_postexit(void) { } +#include +struct trace_arg { + void **array; + int cnt, size; +}; + +static _Unwind_Reason_Code +backtrace_helper (struct _Unwind_Context *ctx, void *a) +{ + struct trace_arg *arg = a; + + /* We are first called with address in the __backtrace function. + Skip it. */ + if (arg->cnt != -1) + { + arg->array[arg->cnt] = (void *) _Unwind_GetIP(ctx); + + /* Check whether we make any progress. */ + if (arg->cnt > 0 && arg->array[arg->cnt - 1] == arg->array[arg->cnt]) + return _URC_END_OF_STACK; + } + if (++arg->cnt == arg->size) + return _URC_END_OF_STACK; + return _URC_NO_REASON; +} + +/** @brief reimplementation of glibc backtrace based directly on gcc library, without implicit malloc + * + * See http://webloria.loria.fr/~quinson/blog/2012/0208/system_programming_fun_in_SimGrid/ + * for the motivation behind this function + * */ + +int xbt_backtrace_no_malloc(void **array, int size) { + struct trace_arg arg = { .array = array, .size = size, .cnt = -1 }; + + if (size >= 1) + _Unwind_Backtrace(backtrace_helper, &arg); + + /* _Unwind_Backtrace on IA-64 seems to put NULL address above + _start. Fix it up here. */ + if (arg.cnt > 1 && arg.array[arg.cnt - 1] == NULL) + --arg.cnt; + return arg.cnt != -1 ? arg.cnt : 0; +} + void xbt_backtrace_current(xbt_ex_t * e) { e->used = backtrace((void **) e->bt, XBT_BACKTRACE_SIZE); + if (e->used == 0) { + fprintf(stderr, "The backtrace() function failed, which probably means that the memory is exhausted. Here is a crude dump of the exception that I was trying to build:"); + fprintf(stderr, "%s:%s(%d) [%s:%d] %s", e->host,e->procname,e->pid, e->file,e->line,e->msg); + fprintf(stderr, "Bailing out now since there is nothing I can do without a decent amount of memory. Please go fix the memleaks\n"); + exit(1); + } } -void xbt_ex_setup_backtrace(xbt_ex_t * e) +void xbt_ex_setup_backtrace(xbt_ex_t * e) //FIXME: This code could be greatly improved/simplifyied with http://cairo.sourcearchive.com/documentation/1.9.4/backtrace-symbols_8c-source.html { int i; @@ -56,23 +107,21 @@ void xbt_ex_setup_backtrace(xbt_ex_t * e) struct stat stat_buf; char *binary_name = NULL; - xbt_assert(e - && e->used, - "Backtrace not setup yet, cannot set it up for display"); + xbt_assert(e, "Backtrace not setup yet, cannot set it up for display"); + + e->bt_strings = NULL; if (!xbt_binary_name) /* no binary name, nothing to do */ return; - backtrace_syms = backtrace_symbols(e->bt, e->used); - /* ignore first one, which is this xbt_backtrace_current() */ - e->used--; - memmove(backtrace_syms, backtrace_syms + 1, sizeof(char *) * e->used); + if (e->used <= 1) + return; - e->bt_strings = NULL; + /* ignore first one, which is xbt_backtrace_current() */ + e->used--; + memmove(e->bt, e->bt + 1, (sizeof *e->bt) * e->used); - /* Some arches only have stubs of backtrace, no implementation (hppa comes to mind) */ - if (!e->used) - return; + backtrace_syms = backtrace_symbols(e->bt, e->used); /* build the commandline */ if (stat(xbt_binary_name, &stat_buf)) { @@ -86,8 +135,7 @@ void xbt_ex_setup_backtrace(xbt_ex_t * e) char *data; xbt_dynar_foreach(path, cpt, data) { - if (binary_name) - free(binary_name); + free(binary_name); binary_name = bprintf("%s/%s", data, xbt_binary_name); if (!stat(binary_name, &stat_buf)) { /* Found. */