1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22: #include <alloca.h>
23: #include <ctype.h>
24: #include <errno.h>
25: #include <execinfo.h>
26: #include <fcntl.h>
27: #include <signal.h>
28: #include <stdint.h>
29: #include <stdio.h>
30: #include <stdlib.h>
31: #include <string.h>
32: #include <unistd.h>
33: #include <stdio-common/_itoa.h>
34: #include <ldsodefs.h>
35:
36: #include <bp-checks.h>
37:
38:
39:
40: #include <sigcontextinfo.h>
41:
42:
43: #include <register-dump.h>
44:
45:
46: #define WRITE_STRING(s) write (fd, s, strlen (s))
47:
48:
49: static const char *fname;
50:
51:
52:
53:
54: static void
55: write_strsignal (int fd, int signal)
56: {
57: if (signal < 0 || signal >= _NSIG || _sys_siglist[signal] == NULL)
58: {
59: char buf[30];
60: char *ptr = _itoa_word (signal, &buf[sizeof (buf)], 10, 0);
61: WRITE_STRING ("signal ");
62: write (fd, buf, &buf[sizeof (buf)] - ptr);
63: }
64: else
65: WRITE_STRING (_sys_siglist[signal]);
66: }
67:
68:
69:
70:
71:
72: static void
73: catch_segfault (int signal, SIGCONTEXT ctx)
74: {
75: int fd, cnt, i;
76: void **arr;
77: struct sigaction sa;
78: uintptr_t pc;
79:
80:
81:
82: fd = 2;
83: if (fname != NULL)
84: {
85: fd = open (fname, O_TRUNC | O_WRONLY | O_CREAT, 0666);
86: if (fd == -1)
87: fd = 2;
88: }
89:
90: WRITE_STRING ("*** ");
91: write_strsignal (fd, signal);
92: WRITE_STRING ("\n");
93:
94: #ifdef REGISTER_DUMP
95: REGISTER_DUMP;
96: #endif
97:
98: WRITE_STRING ("\nBacktrace:\n");
99:
100:
101: arr = alloca (256 * sizeof (void *));
102: cnt = backtrace (arr, 256);
103:
104:
105:
106:
107:
108: pc = (uintptr_t) GET_PC (ctx);
109: for (i = 0; i < cnt; ++i)
110: if ((uintptr_t) arr[i] >= pc - 16 && (uintptr_t) arr[i] <= pc + 16)
111: break;
112:
113:
114:
115: if (i == cnt)
116: i = 0;
117:
118:
119: __backtrace_symbols_fd (arr + i, cnt - i, fd);
120:
121: #ifdef HAVE_PROC_SELF
122:
123: int mapfd = open ("/proc/self/maps", O_RDONLY);
124: if (mapfd != -1)
125: {
126: write (fd, "\nMemory map:\n\n", 14);
127:
128: char buf[256];
129: ssize_t n;
130:
131: while ((n = TEMP_FAILURE_RETRY (read (mapfd, buf, sizeof (buf)))) > 0)
132: TEMP_FAILURE_RETRY (write (fd, buf, n));
133:
134: close (mapfd);
135: }
136: #endif
137:
138:
139: sa.sa_handler = SIG_DFL;
140: sigemptyset (&sa.sa_mask);
141: sa.sa_flags = 0;
142: sigaction (signal, &sa, NULL);
143: raise (signal);
144: }
145:
146:
147: static void
148: __attribute__ ((constructor))
149: install_handler (void)
150: {
151: struct sigaction sa;
152: const char *sigs = getenv ("SEGFAULT_SIGNALS");
153: const char *name;
154:
155: sa.sa_handler = (void *) catch_segfault;
156: sigemptyset (&sa.sa_mask);
157: sa.sa_flags = SA_RESTART;
158:
159:
160: if (getenv ("SEGFAULT_USE_ALTSTACK") != 0)
161: {
162: void *stack_mem = malloc (2 * SIGSTKSZ);
163: struct sigaltstack ss;
164:
165: if (stack_mem != NULL)
166: {
167: ss.ss_sp = stack_mem;
168: ss.ss_flags = 0;
169: ss.ss_size = 2 * SIGSTKSZ;
170:
171: if (sigaltstack (&ss, NULL) == 0)
172: sa.sa_flags |= SA_ONSTACK;
173: }
174: }
175:
176: if (sigs == NULL)
177: sigaction (SIGSEGV, &sa, NULL);
178: else if (sigs[0] == '\0')
179:
180: return;
181: else
182: {
183: const char *where;
184: int all = __strcasecmp (sigs, "all") == 0;
185:
186: #define INSTALL_FOR_SIG(sig, name) \
187: where = __strcasestr (sigs, name); \
188: if (all || (where != NULL \
189: && (where == sigs || !isalnum (where[-1])) \
190: && !isalnum (where[sizeof (name) - 1]))) \
191: sigaction (sig, &sa, NULL);
192:
193: INSTALL_FOR_SIG (SIGSEGV, "segv");
194: INSTALL_FOR_SIG (SIGILL, "ill");
195: #ifdef SIGBUS
196: INSTALL_FOR_SIG (SIGBUS, "bus");
197: #endif
198: #ifdef SIGSTKFLT
199: INSTALL_FOR_SIG (SIGSTKFLT, "stkflt");
200: #endif
201: INSTALL_FOR_SIG (SIGABRT, "abrt");
202: INSTALL_FOR_SIG (SIGFPE, "fpe");
203: }
204:
205:
206: name = getenv ("SEGFAULT_OUTPUT_NAME");
207: if (name != NULL && name[0] != '\0')
208: {
209: int ret = access (name, R_OK | W_OK);
210:
211: if (ret == 0 || (ret == -1 && errno == ENOENT))
212: fname = __strdup (name);
213: }
214: }