• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * sigcatcher.c --- print a backtrace on a SIGSEGV, et. al
3  *
4  * Copyright (C) 2011 Theodore Ts'o.
5  *
6  * %Begin-Header%
7  * This file may be redistributed under the terms of the GNU Public
8  * License.
9  * %End-Header%
10  */
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <signal.h>
15 #include <string.h>
16 #ifdef HAVE_EXECINFO_H
17 #include <execinfo.h>
18 #endif
19 
20 #include "e2fsck.h"
21 
22 struct str_table {
23 	int	num;
24 	const char	*name;
25 };
26 
27 #define DEFINE_ENTRY(SYM)	{ SYM, #SYM },
28 #define END_TABLE		{ 0, 0 }
29 
30 static struct str_table sig_table[] = {
31 #ifdef SIGHUP
32 	DEFINE_ENTRY(SIGHUP)
33 #endif
34 #ifdef SIGINT
35 	DEFINE_ENTRY(SIGINT)
36 #endif
37 #ifdef SIGQUIT
38 	DEFINE_ENTRY(SIGQUIT)
39 #endif
40 #ifdef SIGILL
41 	DEFINE_ENTRY(SIGILL)
42 #endif
43 #ifdef SIGTRAP
44 	DEFINE_ENTRY(SIGTRAP)
45 #endif
46 #ifdef SIGABRT
47 	DEFINE_ENTRY(SIGABRT)
48 #endif
49 #ifdef SIGIOT
50 	DEFINE_ENTRY(SIGIOT)
51 #endif
52 #ifdef SIGBUS
53 	DEFINE_ENTRY(SIGBUS)
54 #endif
55 #ifdef SIGFPE
56 	DEFINE_ENTRY(SIGFPE)
57 #endif
58 #ifdef SIGKILL
59 	DEFINE_ENTRY(SIGKILL)
60 #endif
61 #ifdef SIGUSR1
62 	DEFINE_ENTRY(SIGUSR1)
63 #endif
64 #ifdef SIGSEGV
65 	DEFINE_ENTRY(SIGSEGV)
66 #endif
67 #ifdef SIGUSR2
68 	DEFINE_ENTRY(SIGUSR2)
69 #endif
70 #ifdef SIGPIPE
71 	DEFINE_ENTRY(SIGPIPE)
72 #endif
73 #ifdef SIGALRM
74 	DEFINE_ENTRY(SIGALRM)
75 #endif
76 #ifdef SIGTERM
77 	DEFINE_ENTRY(SIGTERM)
78 #endif
79 #ifdef SIGSTKFLT
80 	DEFINE_ENTRY(SIGSTKFLT)
81 #endif
82 #ifdef SIGCHLD
83 	DEFINE_ENTRY(SIGCHLD)
84 #endif
85 #ifdef SIGCONT
86 	DEFINE_ENTRY(SIGCONT)
87 #endif
88 #ifdef SIGSTOP
89 	DEFINE_ENTRY(SIGSTOP)
90 #endif
91 #ifdef SIGTSTP
92 	DEFINE_ENTRY(SIGTSTP)
93 #endif
94 #ifdef SIGTTIN
95 	DEFINE_ENTRY(SIGTTIN)
96 #endif
97 #ifdef SIGTTOU
98 	DEFINE_ENTRY(SIGTTOU)
99 #endif
100 #ifdef SIGURG
101 	DEFINE_ENTRY(SIGURG)
102 #endif
103 #ifdef SIGXCPU
104 	DEFINE_ENTRY(SIGXCPU)
105 #endif
106 #ifdef SIGXFSZ
107 	DEFINE_ENTRY(SIGXFSZ)
108 #endif
109 #ifdef SIGVTALRM
110 	DEFINE_ENTRY(SIGVTALRM)
111 #endif
112 #ifdef SIGPROF
113 	DEFINE_ENTRY(SIGPROF)
114 #endif
115 #ifdef SIGWINCH
116 	DEFINE_ENTRY(SIGWINCH)
117 #endif
118 #ifdef SIGIO
119 	DEFINE_ENTRY(SIGIO)
120 #endif
121 #ifdef SIGPOLL
122 	DEFINE_ENTRY(SIGPOLL)
123 #endif
124 #ifdef SIGPWR
125 	DEFINE_ENTRY(SIGPWR)
126 #endif
127 #ifdef SIGSYS
128 	DEFINE_ENTRY(SIGSYS)
129 #endif
130 	END_TABLE
131 };
132 
133 static struct str_table generic_code_table[] = {
134 #ifdef SI_ASYNCNL
135 	DEFINE_ENTRY(SI_ASYNCNL)
136 #endif
137 #ifdef SI_TKILL
138 	DEFINE_ENTRY(SI_TKILL)
139 #endif
140 #ifdef SI_SIGIO
141 	DEFINE_ENTRY(SI_SIGIO)
142 #endif
143 #ifdef SI_ASYNCIO
144 	DEFINE_ENTRY(SI_ASYNCIO)
145 #endif
146 #ifdef SI_MESGQ
147 	DEFINE_ENTRY(SI_MESGQ)
148 #endif
149 #ifdef SI_TIMER
150 	DEFINE_ENTRY(SI_TIMER)
151 #endif
152 #ifdef SI_QUEUE
153 	DEFINE_ENTRY(SI_QUEUE)
154 #endif
155 #ifdef SI_USER
156 	DEFINE_ENTRY(SI_USER)
157 #endif
158 #ifdef SI_KERNEL
159 	DEFINE_ENTRY(SI_KERNEL)
160 #endif
161 	END_TABLE
162 };
163 
164 static struct str_table sigill_code_table[] = {
165 #ifdef ILL_ILLOPC
166 	DEFINE_ENTRY(ILL_ILLOPC)
167 #endif
168 #ifdef ILL_ILLOPN
169 	DEFINE_ENTRY(ILL_ILLOPN)
170 #endif
171 #ifdef ILL_ILLADR
172 	DEFINE_ENTRY(ILL_ILLADR)
173 #endif
174 #ifdef ILL_ILLTRP
175 	DEFINE_ENTRY(ILL_ILLTRP)
176 #endif
177 #ifdef ILL_PRVOPC
178 	DEFINE_ENTRY(ILL_PRVOPC)
179 #endif
180 #ifdef ILL_PRVREG
181 	DEFINE_ENTRY(ILL_PRVREG)
182 #endif
183 #ifdef ILL_COPROC
184 	DEFINE_ENTRY(ILL_COPROC)
185 #endif
186 #ifdef ILL_BADSTK
187 	DEFINE_ENTRY(ILL_BADSTK)
188 #endif
189 #ifdef BUS_ADRALN
190 	DEFINE_ENTRY(BUS_ADRALN)
191 #endif
192 #ifdef BUS_ADRERR
193 	DEFINE_ENTRY(BUS_ADRERR)
194 #endif
195 #ifdef BUS_OBJERR
196 	DEFINE_ENTRY(BUS_OBJERR)
197 #endif
198 	END_TABLE
199 };
200 
201 static struct str_table sigfpe_code_table[] = {
202 #ifdef FPE_INTDIV
203 	DEFINE_ENTRY(FPE_INTDIV)
204 #endif
205 #ifdef FPE_INTOVF
206 	DEFINE_ENTRY(FPE_INTOVF)
207 #endif
208 #ifdef FPE_FLTDIV
209 	DEFINE_ENTRY(FPE_FLTDIV)
210 #endif
211 #ifdef FPE_FLTOVF
212 	DEFINE_ENTRY(FPE_FLTOVF)
213 #endif
214 #ifdef FPE_FLTUND
215 	DEFINE_ENTRY(FPE_FLTUND)
216 #endif
217 #ifdef FPE_FLTRES
218 	DEFINE_ENTRY(FPE_FLTRES)
219 #endif
220 #ifdef FPE_FLTINV
221 	DEFINE_ENTRY(FPE_FLTINV)
222 #endif
223 #ifdef FPE_FLTSUB
224 	DEFINE_ENTRY(FPE_FLTSUB)
225 #endif
226 	END_TABLE
227 };
228 
229 static struct str_table sigsegv_code_table[] = {
230 #ifdef SEGV_MAPERR
231 	DEFINE_ENTRY(SEGV_MAPERR)
232 #endif
233 #ifdef SEGV_ACCERR
234 	DEFINE_ENTRY(SEGV_ACCERR)
235 #endif
236 	END_TABLE
237 };
238 
239 
240 static struct str_table sigbus_code_table[] = {
241 #ifdef BUS_ADRALN
242 	DEFINE_ENTRY(BUS_ADRALN)
243 #endif
244 #ifdef BUS_ADRERR
245 	DEFINE_ENTRY(BUS_ADRERR)
246 #endif
247 #ifdef BUS_OBJERR
248 	DEFINE_ENTRY(BUS_OBJERR)
249 #endif
250 	END_TABLE
251 };
252 
253 #if 0 /* should this be hooked in somewhere? */
254 static struct str_table sigstrap_code_table[] = {
255 #ifdef TRAP_BRKPT
256 	DEFINE_ENTRY(TRAP_BRKPT)
257 #endif
258 #ifdef TRAP_TRACE
259 	DEFINE_ENTRY(TRAP_TRACE)
260 #endif
261 	END_TABLE
262 };
263 #endif
264 
265 static struct str_table sigcld_code_table[] = {
266 #ifdef CLD_EXITED
267 	DEFINE_ENTRY(CLD_EXITED)
268 #endif
269 #ifdef CLD_KILLED
270 	DEFINE_ENTRY(CLD_KILLED)
271 #endif
272 #ifdef CLD_DUMPED
273 	DEFINE_ENTRY(CLD_DUMPED)
274 #endif
275 #ifdef CLD_TRAPPED
276 	DEFINE_ENTRY(CLD_TRAPPED)
277 #endif
278 #ifdef CLD_STOPPED
279 	DEFINE_ENTRY(CLD_STOPPED)
280 #endif
281 #ifdef CLD_CONTINUED
282 	DEFINE_ENTRY(CLD_CONTINUED)
283 #endif
284 	END_TABLE
285 };
286 
287 #if 0 /* should this be hooked in somewhere? */
288 static struct str_table sigpoll_code_table[] = {
289 #ifdef POLL_IN
290 	DEFINE_ENTRY(POLL_IN)
291 #endif
292 #ifdef POLL_OUT
293 	DEFINE_ENTRY(POLL_OUT)
294 #endif
295 #ifdef POLL_MSG
296 	DEFINE_ENTRY(POLL_MSG)
297 #endif
298 #ifdef POLL_ERR
299 	DEFINE_ENTRY(POLL_ERR)
300 #endif
301 #ifdef POLL_PRI
302 	DEFINE_ENTRY(POLL_PRI)
303 #endif
304 #ifdef POLL_HUP
305 	DEFINE_ENTRY(POLL_HUP)
306 #endif
307 	END_TABLE
308 };
309 #endif
310 
lookup_table(int num,struct str_table * table)311 static const char *lookup_table(int num, struct str_table *table)
312 {
313 	struct str_table *p;
314 
315 	for (p=table; p->name; p++)
316 		if (num == p->num)
317 			return(p->name);
318 	return NULL;
319 }
320 
lookup_table_fallback(int num,struct str_table * table)321 static const char *lookup_table_fallback(int num, struct str_table *table)
322 {
323 	static char buf[32];
324 	const char *ret = lookup_table(num, table);
325 
326 	if (ret)
327 		return ret;
328 	snprintf(buf, sizeof(buf), "%d", num);
329 	buf[sizeof(buf)-1] = 0;
330 	return buf;
331 }
332 
die_signal_handler(int signum,siginfo_t * siginfo,void * context EXT2FS_ATTR ((unused)))333 static void die_signal_handler(int signum, siginfo_t *siginfo,
334 			       void *context EXT2FS_ATTR((unused)))
335 {
336        void *stack_syms[32];
337        int frames;
338        const char *cp;
339 
340        fprintf(stderr, "Signal (%d) %s ", signum,
341 	       lookup_table_fallback(signum, sig_table));
342        if (siginfo->si_code == SI_USER)
343 	       fprintf(stderr, "(sent from pid %u) ", siginfo->si_pid);
344        cp = lookup_table(siginfo->si_code, generic_code_table);
345        if (cp)
346 	       fprintf(stderr, "si_code=%s ", cp);
347        else if (signum == SIGILL)
348 	       fprintf(stderr, "si_code=%s ",
349 		       lookup_table_fallback(siginfo->si_code,
350 					     sigill_code_table));
351        else if (signum == SIGFPE)
352 	       fprintf(stderr, "si_code=%s ",
353 		       lookup_table_fallback(siginfo->si_code,
354 					     sigfpe_code_table));
355        else if (signum == SIGSEGV)
356 	       fprintf(stderr, "si_code=%s ",
357 		       lookup_table_fallback(siginfo->si_code,
358 					     sigsegv_code_table));
359        else if (signum == SIGBUS)
360 	       fprintf(stderr, "si_code=%s ",
361 		       lookup_table_fallback(siginfo->si_code,
362 					     sigbus_code_table));
363        else if (signum == SIGCHLD)
364 	       fprintf(stderr, "si_code=%s ",
365 		       lookup_table_fallback(siginfo->si_code,
366 					     sigcld_code_table));
367        else
368 	       fprintf(stderr, "si code=%d ", siginfo->si_code);
369        if ((siginfo->si_code != SI_USER) &&
370 	   (signum == SIGILL || signum == SIGFPE ||
371 	    signum == SIGSEGV || signum == SIGBUS))
372 	       fprintf(stderr, "fault addr=%p", siginfo->si_addr);
373        fprintf(stderr, "\n");
374 
375 #if defined(HAVE_BACKTRACE) && !defined(DISABLE_BACKTRACE)
376        frames = backtrace(stack_syms, 32);
377        backtrace_symbols_fd(stack_syms, frames, 2);
378 #endif
379        exit(FSCK_ERROR);
380 }
381 
sigcatcher_setup(void)382 void sigcatcher_setup(void)
383 {
384 	struct sigaction	sa;
385 
386 	memset(&sa, 0, sizeof(struct sigaction));
387 	sa.sa_sigaction = die_signal_handler;
388 	sa.sa_flags = SA_SIGINFO;
389 
390 	sigaction(SIGFPE, &sa, 0);
391 	sigaction(SIGILL, &sa, 0);
392 	sigaction(SIGBUS, &sa, 0);
393 	sigaction(SIGSEGV, &sa, 0);
394 }
395 
396 
397 #ifdef DEBUG
398 #include <getopt.h>
399 
usage(void)400 void usage(void)
401 {
402 	fprintf(stderr, "tst_sigcatcher: [-akfn]\n");
403 	exit(1);
404 }
405 
main(int argc,char ** argv)406 int main(int argc, char** argv)
407 {
408 	struct sigaction	sa;
409 	char			*p = 0;
410 	int 			i, c;
411 	volatile		x=0;
412 
413 	memset(&sa, 0, sizeof(struct sigaction));
414 	sa.sa_sigaction = die_signal_handler;
415 	sa.sa_flags = SA_SIGINFO;
416 	for (i=1; i < 31; i++)
417 		sigaction(i, &sa, 0);
418 
419 	while ((c = getopt (argc, argv, "afkn")) != EOF)
420 		switch (c) {
421 		case 'a':
422 			abort();
423 			break;
424 		case 'f':
425 			printf("%d\n", 42/x);
426 		case 'k':
427 			kill(getpid(), SIGTERM);
428 			break;
429 		case 'n':
430 			*p = 42;
431 		default:
432 			usage ();
433 		}
434 
435 	printf("Sleeping for 10 seconds, send kill signal to pid %u...\n",
436 	       getpid());
437 	fflush(stdout);
438 	sleep(10);
439 	exit(0);
440 }
441 #endif
442