/******************************************************************* Print a backtrace of the stack to the debug log. ********************************************************************/ #include "debug.h" #include "config.h" #include "util.h" #include #include #include #include // HAVE_LIBUNWIND passed in from Makefile #ifdef HAVE_LIBUNWIND #define UNW_LOCAL_ONLY #include #endif #ifdef HAVE_LIBUNWIND void log_stack_trace(char * program_name) { unw_cursor_t cursor; unw_context_t uc; unw_word_t ip, sp, off; int status; unsigned i = 0; char procname[256]; procname[sizeof(procname) - 1] = '\0'; if (unw_getcontext(&uc) != 0) { INFO("unable to produce a stack trace with libunwind; unw_getcontext failure\n"); return; } if (unw_init_local(&cursor, &uc) != 0) { INFO("unable to produce a stack trace with libunwind; unw_init_local failure\n"); return; } INFO("%s: BACKTRACE:\n", program_name); while(1) { status = unw_step(&cursor); if(status == 0) { // INFO("unw_step: returned %d\n", status); break; } if(status < 0) { INFO("unw_step error: %d\n", status); break; } // we got a valid stack frame to display ip = sp = 0; unw_get_reg(&cursor, UNW_REG_IP, &ip); unw_get_reg(&cursor, UNW_REG_SP, &sp); switch (unw_get_proc_name(&cursor, procname, sizeof(procname) - 1, &off)) { case 0: /* Name found. */ case -UNW_ENOMEM: /* Name truncated. */ INFO(" #%u %s + %#lx [ip=%#lx] [sp=%#lx]\n", i, procname, (unsigned long)off, (unsigned long)ip, (unsigned long) sp); break; default: /* case -UNW_ENOINFO: */ /* case -UNW_EUNSPEC: */ /* No symbol name found. */ INFO(" #%u %s [ip=%#lx] [sp=%#lx]\n", i, "", (unsigned long)ip, (unsigned long) sp); } i++; } return; } #else // If we don't have libunwind, then we can't do a stack backtrace void log_stack_trace(char * program_name) { INFO("%s: unable to produce a stack trace on this platform; Need libunwind\n", program_name); } #endif