#include #include #include #include #include #include #define MAX_BACKTRACE 32 static size_t obtain_backtrace(void ** dest, size_t destsize, void * context) { unw_cursor_t cursor; unw_context_t uc; unw_context_t * ctx; size_t i = 0; int ret; if (!destsize) return 0; if (context) { ctx = context; } else { if (unw_getcontext(&uc) < 0) return 0; ctx = &uc; } if (unw_init_local(&cursor, ctx) < 0) return 0; do { unw_word_t ip; unw_word_t sp; unw_get_reg(&cursor, UNW_REG_IP, &ip); unw_get_reg(&cursor, UNW_REG_SP, &sp); /* This shouldn't really happen, since unw_step() is * supposed to return 0 in this case, but it's been * known to happen anyway, so we take our precautions. */ if (!ip) break; dest[i++] = (void*) ip; } while ((ret = unw_step(&cursor)) > 0 && i < destsize); return i; } static void dump_backtrace(void ** trace, size_t trace_size) { char ** strings; size_t i; assert(trace_size > 0 && trace); if (!(strings = backtrace_symbols(trace, trace_size))) return; fputs("Backtrace:\n", stderr); for (i = 0; i < trace_size; ++i) fprintf(stderr, "%s\n", strings[i]); fputs("End of backtrace:\n", stderr); free(strings); } static void dump_backtrace_current_task(void) { void *trace[MAX_BACKTRACE]; size_t trace_size; trace_size = obtain_backtrace(trace, sizeof trace / sizeof trace[0], NULL); dump_backtrace(trace, trace_size); } static int foo(int a) { fprintf(stderr, "foo(%d)\n", a); dump_backtrace_current_task(); return a + 2; } static int bar(int a) { fprintf(stderr, "bar(%d)\n", a); return foo(a + 1); } int main(void) { //register_signal_handlers(NULL); fprintf(stderr, "Signal handlers done\n"); bar(0); return 0; }