void print_ucontext(ucontext_t *a_uc, int fd) { unw_cursor_t cursor; unw_context_t *uc=(unw_context_t *)(a_uc); unw_word_t ip, sp; static char symname[10000]; static char cxx_name[102400]; static char outbuf[102400]; #define uc_out(x, ...) \ do {\ int len = snprintf(outbuf, sizeof(outbuf)-1, x "\n", ##__VA_ARGS__);\ if (len > (int) sizeof(outbuf)) len = sizeof(outbuf); \ write(fd, outbuf, len);\ } while(0) \ for(int i = 0; i < (int) NGREG; ++i) { uc_out("reg[%02d:%s]=\t0x" REGFORMAT, i, g_regs_name[i], uc->uc_mcontext.gregs[i]); } uc_out("Stack trace:"); int ret = unw_init_local(&cursor, uc); do { if (ret) break; ret = unw_get_reg(&cursor, UNW_REG_IP, &ip); ret = unw_get_reg(&cursor, UNW_REG_SP, &sp); ret = unw_get_proc_name(&cursor, symname, sizeof(symname), NULL); size_t name_len = sizeof(cxx_name); int status = 0; __cxa_demangle(symname, cxx_name, &name_len, &status); char *pname = symname; if (status == 0) pname = cxx_name; uc_out("%s: ip: %lx, sp: %lx", pname, (long) ip, (long) sp); } while (unw_step(&cursor) > 0); uc_out("End of stack trace."); }
static void signal_segv(int signum, siginfo_t* info, void*ptr) { //if(info->si_signo == SIGSEGV) // _exit (-1); static const char *si_codes[3] = {"", "SEGV_MAPERR", "SEGV_ACCERR"}; int i, f = 0; ucontext_t *ucontext = (ucontext_t*)ptr; Dl_info dlinfo; void **bp = 0; void *ip = 0; /* sigsegv_outp("Segmentation Fault!"); sigsegv_outp("info.si_signo = %d", signum); sigsegv_outp("info.si_errno = %d", info->si_errno); sigsegv_outp("info.si_code = %d (%s)", info->si_code, si_codes[info->si_code]); sigsegv_outp("info.si_addr = %p", info->si_addr); for(i = 0; i < NGREG; i++) sigsegv_outp("reg[%02d] = 0x" REGFORMAT, i, ucontext->uc_mcontext.gregs[i]); */ #ifndef SIGSEGV_NOSTACK ip = (void*)ucontext->uc_mcontext.gregs[REG_EIP]; bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP]; sigsegv_outp("Stack trace:"); i = 10; while(bp && ip && i) { i--; if(!dladdr(ip, &dlinfo)) break; const char *symname = dlinfo.dli_sname; #ifndef NO_CPP_DEMANGLE int status; char * tmp = __cxa_demangle(symname, NULL, 0, &status); if (status == 0 && tmp) symname = tmp; #endif sigsegv_outp("% 2d: %p <%s+%lu> (%s)", ++f, ip, symname, (unsigned long)ip - (unsigned long)dlinfo.dli_saddr, dlinfo.dli_fname); #ifndef NO_CPP_DEMANGLE if (tmp) free(tmp); #endif if(dlinfo.dli_sname && !strcmp(dlinfo.dli_sname, "main")) break; ip = bp[1]; bp = (void**)bp[0]; } sigsegv_outp("End of stack trace."); #else sigsegv_outp("Not printing stack strace."); #endif if(info->si_signo == SIGSEGV) _exit (-1); }