1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| #define __STDC_FORMAT_MACROS #include <inttypes.h>
#define UNW_LOCAL_ONLY #include <libunwind.h>
#include <cxxabi.h> #include <signal.h> #include <stdio.h> #include <stdlib.h>
static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), int flags) { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = handler; sa.sa_flags = SA_SIGINFO | flags; sigemptyset(&sa.sa_mask); if (sigaction(sig, &sa, 0)) err(1, "sigaction"); }
void backtrace() { unw_cursor_t cursor; unw_context_t context;
unw_getcontext(&context); unw_init_local(&cursor, &context);
int n=0; while ( unw_step(&cursor) ) { unw_word_t ip, sp, off;
unw_get_reg(&cursor, UNW_REG_IP, &ip); unw_get_reg(&cursor, UNW_REG_SP, &sp);
char symbol[256] = {"<unknown>"}; char *name = symbol;
if ( !unw_get_proc_name(&cursor, symbol, sizeof(symbol), &off) ) { int status; if ( (name = abi::__cxa_demangle(symbol, NULL, NULL, &status)) == 0 ) name = symbol; }
printf("#%-2d 0x%016" PRIxPTR " sp=0x%016" PRIxPTR " %s + 0x%" PRIxPTR "\n", ++n, static_cast<uintptr_t>(ip), static_cast<uintptr_t>(sp), name, static_cast<uintptr_t>(off));
if ( name != symbol ) free(name); } }
static void sigusr1(int sig, siginfo_t *info, void *ctx_void) { long ip = 0; ucontext_t *uc = (ucontext_t *)ctx_void; ip = uc->uc_mcontext.arm_pc; printf("In signal handler. Trying to unwind.\n"); dprintf(2, "signal:%d address:0x%lx ip:0x%lx\n", sig,
(long)info->si_addr, ip); backtrace(); exit(0); }
int fac(int n) { if ( n == 0 ) { printf("Unwind from signal handler\n"); sethandler(SIGSEGV, sigusr1, 0); char *p = NULL; *p = 11; return 1; } else { return n*fac(n-1); } }
int main() { fac(10); return 0; }
|