00001
00014 #ifndef __cplusplus
00015 #define NO_CPP_DEMANGLE
00016 #endif
00017
00018 #define _GNU_SOURCE
00019 #include <memory.h>
00020 #include <stdlib.h>
00021 #include <stdio.h>
00022 #include <signal.h>
00023 #include <ucontext.h>
00024 #include <dlfcn.h>
00025 #include <execinfo.h>
00026 #ifndef NO_CPP_DEMANGLE
00027 #include <cxxabi.h>
00028 #endif
00029
00030 #if defined(REG_RIP)
00031 # define SIGSEGV_STACK_IA64
00032 # define REGFORMAT "%016lx"
00033 #elif defined(REG_EIP)
00034 # define SIGSEGV_STACK_X86
00035 # define REGFORMAT "%08x"
00036 #else
00037 # define SIGSEGV_STACK_GENERIC
00038 # define REGFORMAT "%x"
00039 #endif
00040
00041 static void signal_segv(int signum, siginfo_t* info, void*ptr) {
00042 static const char *si_codes[3] = {"", "SEGV_MAPERR", "SEGV_ACCERR"};
00043 #if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64)
00044 # ifdef SIGSEGV_REGS
00045 size_t i;
00046 # endif
00047 ucontext_t *ucontext = (ucontext_t*)ptr;
00048 int f = 0;
00049 Dl_info dlinfo;
00050 void **bp = 0;
00051 void *ip = 0;
00052 #else
00053 size_t i;
00054 void *bt[20];
00055 char **strings;
00056 size_t sz;
00057 #endif
00058
00059 fprintf(stderr, "Segmentation Fault!\n");
00060 fprintf(stderr, "info.si_signo = %d\n", signum);
00061 fprintf(stderr, "info.si_errno = %d\n", info->si_errno);
00062 fprintf(stderr, "info.si_code = %d (%s)\n", info->si_code, si_codes[info->si_code]);
00063 fprintf(stderr, "info.si_addr = %p\n", info->si_addr);
00064
00065 #ifdef SIGSEGV_REGS
00066 for(i = 0; i < NGREG; i++)
00067 fprintf(stderr, "reg[%02d] = 0x" REGFORMAT "\n", i, ucontext->uc_mcontext.gregs[i]);
00068 #endif
00069
00070 #if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64)
00071 # if defined(SIGSEGV_STACK_IA64)
00072 ip = (void*)ucontext->uc_mcontext.gregs[REG_RIP];
00073 bp = (void**)ucontext->uc_mcontext.gregs[REG_RBP];
00074 # elif defined(SIGSEGV_STACK_X86)
00075 ip = (void*)ucontext->uc_mcontext.gregs[REG_EIP];
00076 bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP];
00077 # endif
00078
00079 fprintf(stderr, "Stack trace:\n");
00080 while(bp && ip) {
00081 if(!dladdr(ip, &dlinfo))
00082 break;
00083
00084 const char *symname = dlinfo.dli_sname;
00085 # ifndef NO_CPP_DEMANGLE
00086 int status;
00087 char *tmp = __cxa_demangle(symname, NULL, 0, &status);
00088
00089 if(status == 0 && tmp)
00090 symname = tmp;
00091 # endif
00092
00093 fprintf(stderr, "% 2d: %p <%s+%u> (%s)\n",
00094 ++f,
00095 ip,
00096 symname,
00097 (unsigned)(ip - dlinfo.dli_saddr),
00098 dlinfo.dli_fname);
00099
00100 # ifndef NO_CPP_DEMANGLE
00101 if(tmp)
00102 free(tmp);
00103 # endif
00104
00105 if(dlinfo.dli_sname && !strcmp(dlinfo.dli_sname, "main"))
00106 break;
00107
00108 ip = bp[1];
00109 bp = (void**)bp[0];
00110 }
00111 #else // !SIGSEGV_STACK_X86 && !SIGSEGV_STACK_IA64
00112 fprintf(stderr, "Stack trace (non-dedicated):\n");
00113 sz = backtrace(bt, 20);
00114 strings = backtrace_symbols(bt, sz);
00115
00116 for(i = 0; i < sz; ++i)
00117 fprintf(stderr, "%s\n", strings[i]);
00118 #endif
00119 fprintf(stderr, "End of stack trace\n");
00120 exit (-1);
00121 }
00122
00123 int setup_sigsegv() {
00124 struct sigaction action;
00125 memset(&action, 0, sizeof(action));
00126 action.sa_sigaction = signal_segv;
00127 action.sa_flags = SA_SIGINFO;
00128 if(sigaction(SIGSEGV, &action, NULL) < 0) {
00129 perror("sigaction");
00130 return 0;
00131 }
00132
00133 return 1;
00134 }
00135
00136 #ifdef SIGSEGV_AUTO_INIT
00137 static void __attribute((constructor)) init(void) {
00138 setup_sigsegv();
00139 }
00140 #endif