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