locale: Fix localedata/sort-test undefined behavior
[glibc.git] / debug / segfault.c
blobb6c0facd595556a16653dfe5478f45c685374182
1 /* Catch segmentation faults and print backtrace.
2 Copyright (C) 1998-2021 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <alloca.h>
20 #include <ctype.h>
21 #include <errno.h>
22 #include <execinfo.h>
23 #include <fcntl.h>
24 #include <signal.h>
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <_itoa.h>
31 #include <ldsodefs.h>
33 /* This file defines macros to access the content of the sigcontext element
34 passed up by the signal handler. */
35 #include <sigcontextinfo.h>
37 #ifdef SA_SIGINFO
38 # define SIGCONTEXT siginfo_t *info, void *
39 #endif
41 /* Get code to possibly dump the content of all registers. */
42 #include <register-dump.h>
44 /* We'll use this a lot. */
45 #define WRITE_STRING(s) write (fd, s, strlen (s))
47 /* Name of the output file. */
48 static const char *fname;
51 /* Print the signal number SIGNAL. Either strerror or strsignal might
52 call local internal functions and these in turn call far too many
53 other functions and might even allocate memory which might fail. */
54 static void
55 write_strsignal (int fd, int signal)
57 char buf[30];
58 char *ptr = _itoa_word (signal, &buf[sizeof (buf)], 10, 0);
59 WRITE_STRING ("signal ");
60 write (fd, ptr, &buf[sizeof (buf)] - ptr);
64 /* This function is called when a segmentation fault is caught. The system
65 is in an unstable state now. This means especially that malloc() might
66 not work anymore. */
67 static void
68 catch_segfault (int signal, SIGCONTEXT ctx)
70 int fd, cnt, i;
71 void **arr;
72 struct sigaction sa;
73 uintptr_t pc;
75 /* This is the name of the file we are writing to. If none is given
76 or we cannot write to this file write to stderr. */
77 fd = 2;
78 if (fname != NULL)
80 fd = open (fname, O_TRUNC | O_WRONLY | O_CREAT, 0666);
81 if (fd == -1)
82 fd = 2;
85 WRITE_STRING ("*** ");
86 write_strsignal (fd, signal);
87 WRITE_STRING ("\n");
89 #ifdef REGISTER_DUMP
90 REGISTER_DUMP;
91 #endif
93 WRITE_STRING ("\nBacktrace:\n");
95 /* Get the backtrace. */
96 arr = alloca (256 * sizeof (void *));
97 cnt = backtrace (arr, 256);
99 /* Now try to locate the PC from signal context in the backtrace.
100 Normally it will be found at arr[2], but it might appear later
101 if there were some signal handler wrappers. Allow a few bytes
102 difference to cope with as many arches as possible. */
103 pc = sigcontext_get_pc (ctx);
104 for (i = 0; i < cnt; ++i)
105 if ((uintptr_t) arr[i] >= pc - 16 && (uintptr_t) arr[i] <= pc + 16)
106 break;
108 /* If we haven't found it, better dump full backtrace even including
109 the signal handler frames instead of not dumping anything. */
110 if (i == cnt)
111 i = 0;
113 /* Now generate nicely formatted output. */
114 __backtrace_symbols_fd (arr + i, cnt - i, fd);
116 #ifdef HAVE_PROC_SELF
117 /* Now the link map. */
118 int mapfd = open ("/proc/self/maps", O_RDONLY);
119 if (mapfd != -1)
121 write (fd, "\nMemory map:\n\n", 14);
123 char buf[256];
124 ssize_t n;
126 while ((n = TEMP_FAILURE_RETRY (read (mapfd, buf, sizeof (buf)))) > 0)
127 TEMP_FAILURE_RETRY (write (fd, buf, n));
129 close (mapfd);
131 #endif
133 /* Pass on the signal (so that a core file is produced). */
134 sa.sa_handler = SIG_DFL;
135 sigemptyset (&sa.sa_mask);
136 sa.sa_flags = 0;
137 sigaction (signal, &sa, NULL);
138 raise (signal);
142 static void
143 __attribute__ ((constructor))
144 install_handler (void)
146 struct sigaction sa;
147 const char *sigs = getenv ("SEGFAULT_SIGNALS");
148 const char *name;
150 #ifdef SA_SIGINFO
151 sa.sa_sigaction = catch_segfault;
152 sa.sa_flags = SA_SIGINFO;
153 #else
154 sa.sa_handler = (void*) catch_segfault;
155 sa.sa_flags = 0;
156 #endif
157 sigemptyset (&sa.sa_mask);
158 sa.sa_flags |= SA_RESTART;
160 /* Maybe we are expected to use an alternative stack. */
161 if (getenv ("SEGFAULT_USE_ALTSTACK") != 0)
163 void *stack_mem = malloc (2 * SIGSTKSZ);
164 stack_t ss;
166 if (stack_mem != NULL)
168 ss.ss_sp = stack_mem;
169 ss.ss_flags = 0;
170 ss.ss_size = 2 * SIGSTKSZ;
172 if (sigaltstack (&ss, NULL) == 0)
173 sa.sa_flags |= SA_ONSTACK;
177 if (sigs == NULL)
178 sigaction (SIGSEGV, &sa, NULL);
179 else if (sigs[0] == '\0')
180 /* Do not do anything. */
181 return;
182 else
184 const char *where;
185 int all = __strcasecmp (sigs, "all") == 0;
187 #define INSTALL_FOR_SIG(sig, name) \
188 where = __strcasestr (sigs, name); \
189 if (all || (where != NULL \
190 && (where == sigs || !isalnum (where[-1])) \
191 && !isalnum (where[sizeof (name) - 1]))) \
192 sigaction (sig, &sa, NULL);
194 INSTALL_FOR_SIG (SIGSEGV, "segv");
195 INSTALL_FOR_SIG (SIGILL, "ill");
196 #ifdef SIGBUS
197 INSTALL_FOR_SIG (SIGBUS, "bus");
198 #endif
199 #ifdef SIGSTKFLT
200 INSTALL_FOR_SIG (SIGSTKFLT, "stkflt");
201 #endif
202 INSTALL_FOR_SIG (SIGABRT, "abrt");
203 INSTALL_FOR_SIG (SIGFPE, "fpe");
206 /* Preserve the output file name if there is any given. */
207 name = getenv ("SEGFAULT_OUTPUT_NAME");
208 if (name != NULL && name[0] != '\0')
210 int ret = access (name, R_OK | W_OK);
212 if (ret == 0 || (ret == -1 && errno == ENOENT))
213 fname = __strdup (name);