]>
git.ipfire.org Git - thirdparty/glibc.git/blob - debug/segfault.c
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.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <https://www.gnu.org/licenses/>. */
34 /* This file defines macros to access the content of the sigcontext element
35 passed up by the signal handler. */
36 #include <sigcontextinfo.h>
39 # define SIGCONTEXT siginfo_t *info, void *
42 /* Get code to possibly dump the content of all registers. */
43 #include <register-dump.h>
45 /* We'll use this a lot. */
46 #define WRITE_STRING(s) write (fd, s, strlen (s))
48 /* Name of the output file. */
49 static const char *fname
;
52 /* Print the signal number SIGNAL. Either strerror or strsignal might
53 call local internal functions and these in turn call far too many
54 other functions and might even allocate memory which might fail. */
56 write_strsignal (int fd
, int signal
)
59 char *ptr
= _itoa_word (signal
, &buf
[sizeof (buf
)], 10, 0);
60 WRITE_STRING ("signal ");
61 write (fd
, ptr
, &buf
[sizeof (buf
)] - ptr
);
65 /* This function is called when a segmentation fault is caught. The system
66 is in an unstable state now. This means especially that malloc() might
69 catch_segfault (int signal
, SIGCONTEXT ctx
)
76 /* This is the name of the file we are writing to. If none is given
77 or we cannot write to this file write to stderr. */
81 fd
= open (fname
, O_TRUNC
| O_WRONLY
| O_CREAT
, 0666);
86 WRITE_STRING ("*** ");
87 write_strsignal (fd
, signal
);
94 WRITE_STRING ("\nBacktrace:\n");
96 /* Get the backtrace. */
97 arr
= alloca (256 * sizeof (void *));
98 cnt
= backtrace (arr
, 256);
100 /* Now try to locate the PC from signal context in the backtrace.
101 Normally it will be found at arr[2], but it might appear later
102 if there were some signal handler wrappers. Allow a few bytes
103 difference to cope with as many arches as possible. */
104 pc
= sigcontext_get_pc (ctx
);
105 for (i
= 0; i
< cnt
; ++i
)
106 if ((uintptr_t) arr
[i
] >= pc
- 16 && (uintptr_t) arr
[i
] <= pc
+ 16)
109 /* If we haven't found it, better dump full backtrace even including
110 the signal handler frames instead of not dumping anything. */
114 /* Now generate nicely formatted output. */
115 __backtrace_symbols_fd (arr
+ i
, cnt
- i
, fd
);
117 #ifdef HAVE_PROC_SELF
118 /* Now the link map. */
119 int mapfd
= open ("/proc/self/maps", O_RDONLY
);
122 write (fd
, "\nMemory map:\n\n", 14);
127 while ((n
= TEMP_FAILURE_RETRY (read (mapfd
, buf
, sizeof (buf
)))) > 0)
128 TEMP_FAILURE_RETRY (write (fd
, buf
, n
));
134 /* Pass on the signal (so that a core file is produced). */
135 sa
.sa_handler
= SIG_DFL
;
136 sigemptyset (&sa
.sa_mask
);
138 sigaction (signal
, &sa
, NULL
);
144 __attribute__ ((constructor
))
145 install_handler (void)
148 const char *sigs
= getenv ("SEGFAULT_SIGNALS");
152 sa
.sa_sigaction
= catch_segfault
;
153 sa
.sa_flags
= SA_SIGINFO
;
155 sa
.sa_handler
= (void*) catch_segfault
;
158 sigemptyset (&sa
.sa_mask
);
159 sa
.sa_flags
|= SA_RESTART
;
161 /* Maybe we are expected to use an alternative stack. */
162 if (getenv ("SEGFAULT_USE_ALTSTACK") != 0)
164 void *stack_mem
= malloc (2 * SIGSTKSZ
);
167 if (stack_mem
!= NULL
)
169 ss
.ss_sp
= stack_mem
;
171 ss
.ss_size
= 2 * SIGSTKSZ
;
173 if (sigaltstack (&ss
, NULL
) == 0)
174 sa
.sa_flags
|= SA_ONSTACK
;
179 sigaction (SIGSEGV
, &sa
, NULL
);
180 else if (sigs
[0] == '\0')
181 /* Do not do anything. */
186 int all
= __strcasecmp (sigs
, "all") == 0;
188 #define INSTALL_FOR_SIG(sig, name) \
189 where = __strcasestr (sigs, name); \
190 if (all || (where != NULL \
191 && (where == sigs || !isalnum (where[-1])) \
192 && !isalnum (where[sizeof (name) - 1]))) \
193 sigaction (sig, &sa, NULL);
195 INSTALL_FOR_SIG (SIGSEGV
, "segv");
196 INSTALL_FOR_SIG (SIGILL
, "ill");
198 INSTALL_FOR_SIG (SIGBUS
, "bus");
201 INSTALL_FOR_SIG (SIGSTKFLT
, "stkflt");
203 INSTALL_FOR_SIG (SIGABRT
, "abrt");
204 INSTALL_FOR_SIG (SIGFPE
, "fpe");
207 /* Preserve the output file name if there is any given. */
208 name
= getenv ("SEGFAULT_OUTPUT_NAME");
209 if (name
!= NULL
&& name
[0] != '\0')
211 int ret
= access (name
, R_OK
| W_OK
);
213 if (ret
== 0 || (ret
== -1 && errno
== ENOENT
))
214 fname
= __strdup (name
);