OSDN Git Service

Merge "lib/uuid: make a static library also"
[android-x86/external-e2fsprogs.git] / e2fsck / sigcatcher.c
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
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
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
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
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
400 void usage(void)
401 {
402         fprintf(stderr, "tst_sigcatcher: [-akfn]\n");
403         exit(1);
404 }
405
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