/* See LICENSE file for copyright and license details. */ #include #include #include #include #include #define UNW_LOCAL_ONLY #include #include static const int full_paths = 0; static void dump_stack(ucontext_t *ucontext) { int saved_errno = errno, lineno; unw_word_t rip; unw_cursor_t cursor; char *debuginfo_path = NULL; Dwarf_Addr ip; Dwfl_Callbacks callbacks; Dwfl *dwfl = NULL; Dwfl_Line *line = NULL; Dwfl_Module *module = NULL; const char *filename = NULL, *p; const char *funcname = NULL; int first = 1; if (unw_init_local2(&cursor, ucontext, UNW_INIT_SIGNAL_FRAME)) goto out; memset(&callbacks, 0, sizeof(callbacks)); callbacks.find_elf = dwfl_linux_proc_find_elf; callbacks.find_debuginfo = dwfl_standard_find_debuginfo; callbacks.debuginfo_path = &debuginfo_path; dwfl = dwfl_begin(&callbacks); if (dwfl) { if (dwfl_linux_proc_report(dwfl, getpid()) || dwfl_report_end(dwfl, NULL, NULL)) { dwfl_end(dwfl); dwfl = NULL; } } do { if (unw_get_reg(&cursor, UNW_REG_IP, &rip)) break; ip = (Dwarf_Addr)rip; if (dwfl) { module = dwfl_addrmodule(dwfl, ip); funcname = module ? dwfl_module_addrname(module, ip) : NULL; line = dwfl_getsrc(dwfl, ip); if (line) { filename = dwfl_lineinfo(line, &(Dwarf_Addr){0}, &lineno, NULL, NULL, NULL); if (!full_paths && (p = strrchr(filename, '/'))) filename = &p[1]; } } fprintf(stderr, "%s 0x%016"PRIxPTR": %s", first ? "crashed at" : " by", (uintptr_t)ip, funcname ? funcname : "???"); first = 0; if (line) fprintf(stderr, " (%s:%i)\n", filename, lineno); else fprintf(stderr, "\n"); } while (unw_step(&cursor) > 0); if (dwfl) dwfl_end(dwfl); out: errno = saved_errno; } static void stack_dumper(int sig, siginfo_t *info, void *ucontext) { (void) sig; (void) info; dump_stack(ucontext); } int main(void) { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = &stack_dumper; sa.sa_flags = (int)(SA_RESETHAND | SA_SIGINFO); #if 1 { static volatile int *null = NULL; sigaction(SIGSEGV, &sa, NULL); return *null; } #else sigaction(SIGABRT, &sa, NULL); abort(); return 0; #endif }