1 // src/segv_backtrace.cc
2 // This file is part of libpbe; see http://svn.chezphil.org/libpbe/trunk
3 // (C) 2008 Philip Endecott
4 
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 
19 #include "segv_backtrace.hh"
20 
21 // This is available on glibc on Linux; I'm not sure about other platforms.
22 #ifdef __linux__
23 
24 #include <execinfo.h>
25 #include <signal.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <string.h>
29 
30 #include "compiler_magic.hh"
31 
32 #define max_backtrace_size 200
33 
print_backtrace(int signum)34 static void print_backtrace(int signum)
35 {
36   signal(SIGSEGV,SIG_DFL);
37   signal(SIGBUS,SIG_DFL);
38   signal(SIGILL,SIG_DFL);
39   signal(SIGFPE,SIG_DFL);
40   const char* signame;
41   switch(signum) {
42     case SIGSEGV: signame="Segmentation fault";  break;
43     case SIGBUS:  signame="Bus error";           break;
44     case SIGILL:  signame="Illegal instruction"; break;
45     case SIGFPE:  signame="FP exception";        break;
46     default:      signame="unexpected signal";   break;
47   }
48   ::write(2,signame,::strlen(signame));
49   const char* msg=" detected; Backtrace:\n";
50   ::write(2,msg,::strlen(msg));
51   void* return_addrs[max_backtrace_size];
52   size_t n_return_addrs = ::backtrace(return_addrs,max_backtrace_size);
53   ::backtrace_symbols_fd(return_addrs,n_return_addrs,2);
54   raise(signum);
55 }
56 
57 
get_backtrace_on_segv()58 void get_backtrace_on_segv()
59 {
60   struct sigaction s;
61   s.sa_handler = &print_backtrace;
62   sigfillset(&s.sa_mask);
63   s.sa_flags=0;
64   sigaction(SIGSEGV,&s,NULL);
65   sigaction(SIGBUS,&s,NULL);
66   sigaction(SIGILL,&s,NULL);
67   sigaction(SIGFPE,&s,NULL);
68 }
69 
70 #else
71 // Platform doesn't have these functions, so no-op.
72 
get_backtrace_on_segv()73 void get_backtrace_on_segv()
74 {
75 }
76 
77 #endif
78 
79