1 /***************************************************************************
2 Try to display interesting crash dump
3
4 copyright : (C) 2007 by mean, (C) 2007 Gruntster
5 email : fixounet@free.fr
6 ***************************************************************************/
7
8 /***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <stdarg.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include <cxxabi.h>
23 #include <signal.h>
24 #if defined(__sun__)
25 #include <dlfcn.h>
26 #include <strings.h>
27 #include <ucontext.h>
28 #include <sys/stack.h>
29 #ifdef _LP64
30 #define _ELF64
31 #endif
32 #include <sys/machelf.h>
33 #else
34 #include <execinfo.h>
35 #endif
36
37 #include "ADM_default.h"
38
39 // Our callback to give UI formatted informations....
40 static ADM_saveFunction *mysaveFunction=NULL;
41 static ADM_fatalFunction *myFatalFunction=NULL;
42 static ADM_sigIntFunction *mySigIntFunction=NULL;
43 static sig_t oldSignalHandlerSigInt;
44 static sig_t oldSignalHandlerSigSev;
45 void sig_segfault_handler(int signo);
46 void sig_sigint_handler(int signo);
47
48 /**
49 \fn ADM_setCrashHook
50 \brief install crash handlers (save + display)
51 */
ADM_setCrashHook(ADM_saveFunction * save,ADM_fatalFunction * fatal,ADM_sigIntFunction * sigint)52 void ADM_setCrashHook(ADM_saveFunction *save, ADM_fatalFunction *fatal,ADM_sigIntFunction *sigint)
53 {
54 mysaveFunction=save;
55 myFatalFunction=fatal;
56 mySigIntFunction=sigint;
57 }
58 /**
59 \fn installSigHandler
60 */
installSigHandler(void)61 void installSigHandler(void)
62 {
63 oldSignalHandlerSigSev=signal(SIGSEGV, sig_segfault_handler); // show stacktrace on default
64 oldSignalHandlerSigInt=signal(SIGINT, sig_sigint_handler); // show stacktrace on default
65 }
uninstallSigHandler(void)66 void uninstallSigHandler(void)
67 {
68 ADM_info("Removing signal handler\n");
69 signal(SIGINT, SIG_DFL);
70 signal(SIGSEGV, SIG_DFL);
71 }
72
73 /**
74 \fn sig_segfault_handler
75 \brief our segfault handler
76 */
sig_segfault_handler(int signo)77 void sig_segfault_handler(int signo)
78 {
79 static int running=0;
80 if(running)
81 {
82 signo=0;
83 exit(1);
84 }
85 running=0;
86 ADM_backTrack("Segfault",0,"??");
87 }
88 /**
89 *
90 * @param signo
91 */
sig_sigint_handler(int signo)92 void sig_sigint_handler(int signo)
93 {
94 ADM_info("Sigint..\n");
95 if(mySigIntFunction) mySigIntFunction();
96 exit(-1);
97 }
98 #if defined(__sun__)
99 static const int maxSize = 2048;
100
addr2sym(void * pc,char * buffer,int size)101 static void addr2sym(void* pc, char* buffer, int size)
102 {
103 Dl_info info;
104 Sym* sym = (Sym*)0;
105 static size_t dsize = maxSize - 1;
106 static char demangled[maxSize];
107 int dstatus = 0;
108
109 if (dladdr1(pc, &info, (void**)&sym, RTLD_DL_SYMENT) == 0)
110 {
111 snprintf(buffer, size, "[0x%p]", pc);
112 }
113
114 if ((info.dli_fname != NULL && info.dli_sname != NULL) &&
115 (((uintptr_t)pc - (uintptr_t)info.dli_saddr) < sym->st_size))
116 {
117 __cxxabiv1::__cxa_demangle(info.dli_sname,demangled,&dsize,&dstatus);
118 snprintf(buffer, size, "%s'%s+0x%x [0x%p]",
119 info.dli_fname,
120 demangled,
121 (unsigned long)pc - (unsigned long)info.dli_saddr,
122 pc);
123 }
124 else
125 {
126 snprintf(buffer, size, "%s'0x%p [0x%p]",
127 info.dli_fname,
128 (unsigned long)pc - (unsigned long)info.dli_fbase,
129 pc);
130 }
131
132 return;
133 }
134
printFrame(int fd,const char * format,...)135 static void printFrame(int fd, const char* format, ...)
136 {
137 va_list ap;
138 static char buffer[maxSize];
139
140 va_start(ap, format);
141 (void)vsnprintf(buffer, sizeof (buffer), format, ap);
142 va_end(ap);
143
144 (void)write(fd, buffer, strlen(buffer));
145 }
146
printStack(uintptr_t pc,int signo,void * arg)147 static int printStack(uintptr_t pc, int signo, void *arg)
148 {
149
150 static char buffer[maxSize];
151 char sigbuf[SIG2STR_MAX];
152
153
154 int filenum = (intptr_t)arg;
155
156 addr2sym((void *)pc, buffer, sizeof (buffer));
157
158 if (signo) {
159 sigbuf[0] = '?';
160 sigbuf[1] = 0;
161
162 (void) sig2str(signo, sigbuf);
163
164 printFrame(filenum, "%s [Signal %d (%s)]\n",
165 buffer, (ulong_t)signo, sigbuf);
166 } else
167 printFrame(filenum, "%s\n", buffer);
168
169 return (0);
170 }
171
backtrace(int fd)172 static int backtrace(int fd)
173 {
174 int rc = -1;
175 ucontext_t u;
176
177 if (getcontext(&u) >= 0)
178 {
179 rc = walkcontext(&u, printStack, (void*)(intptr_t)fd);
180 }
181 return(rc);
182 }
183 #endif /* : defined(__sun__) */
184
ADM_backTrack(const char * info,int lineno,const char * file)185 void ADM_backTrack(const char *info,int lineno,const char *file)
186 {
187 if(mysaveFunction)
188 mysaveFunction();
189 #define MAX_BACKTRACK 30
190 #if !defined(__HAIKU__) && !defined(__sun__)
191 char wholeStuff[2048];
192 char buffer[4096];
193 char in[2048];
194 void *stack[MAX_BACKTRACK+1];
195 char **functions;
196 int count, i;
197 wholeStuff[0]=0;
198
199 printf("\n*********** BACKTRACK **************\n");
200
201 count = backtrace(stack, MAX_BACKTRACK);
202 functions = backtrace_symbols(stack, count);
203 sprintf(wholeStuff,"%s\n at line %d, file %s\n",info,lineno,file);
204 int status;
205 size_t size=2047;
206 // it looks like that xxxx (functionName+0x***) XXXX
207 for (i=0; i < count; i++)
208 {
209 char *s=strstr(functions[i],"(");
210 buffer[0]=0;
211 if(s && strstr(s+1,"+"))
212 {
213 strcpy(in,s+1);
214 char *e=strstr(in,"+");
215 *e=0;
216 __cxxabiv1::__cxa_demangle(in,buffer,&size,&status);
217 if(status)
218 strcpy(buffer,in);
219 }else
220 strcpy(buffer,functions[i]);
221 printf("%s:%d:<%s>:%d\n",functions[i],i,buffer,status);
222 strcat(wholeStuff,buffer);
223 strcat(wholeStuff,"\n");
224 }
225 printf("*********** BACKTRACK **************\n");
226
227 if(myFatalFunction)
228 myFatalFunction("Crash", wholeStuff); // FIXME
229 printf("*********** Exiting **************\n");
230 exit(-1); // _exit(1) ???
231 #endif
232 }
233 //EOF
234