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