diff options
| author | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2021-12-20 08:41:55 -0300 |
|---|---|---|
| committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2022-01-06 07:59:49 -0300 |
| commit | 65ccd641bacea33be23d51da737c2de7543d0f5e (patch) | |
| tree | a3dbd16426b4a51dcb8450ede9d47c5a90e58a66 | |
| parent | c1fc366ec9e78e17ad3e2ecdb4c4cc662decc32b (diff) | |
| download | glibc-65ccd641bacea33be23d51da737c2de7543d0f5e.tar.xz glibc-65ccd641bacea33be23d51da737c2de7543d0f5e.zip | |
debug: Remove catchsegv and libSegfault (BZ #14913)
Trapping SIGSEGV within the process is error-prone, adds security
issues, and modern analysis design tends to happen out of the
process (either by attaching a debugger or by post-mortem analysis).
The libSegfault also has some design problems, it uses non
async-signal-safe function (backtrace) on signal handler.
There are multiple alternatives if users do want to use similar
functionality, such as sigsegv gnulib module or libsegfault.
22 files changed, 6 insertions, 3438 deletions
@@ -135,6 +135,10 @@ Deprecated and removed features, and other changes affecting compatibility: configuration script now automatically detects static-pie support in the toolchain and architecture and enables it if available. +* The catchsegv script and associated libSegFault.so shared object have + been removed. There are widely-deployed out-of-process alternatives for + catching coredumps and backtraces. + Changes to build and runtime requirements: [Add changes to build and runtime requirements here] diff --git a/debug/Makefile b/debug/Makefile index 9c2ce61a86..5818d751c9 100644 --- a/debug/Makefile +++ b/debug/Makefile @@ -167,12 +167,9 @@ tests-unsupported = tst-chk4 tst-chk5 tst-chk6 tst-chk8 \ tst-lfschk4 tst-lfschk5 tst-lfschk6 endif -extra-libs = libSegFault libpcprofile +extra-libs = libpcprofile extra-libs-others = $(extra-libs) -libSegFault-routines = segfault -libSegFault-inhibit-o = $(filter-out .os,$(object-suffixes)) - libpcprofile-routines = pcprofile libpcprofile-inhibit-o = $(filter-out .os,$(object-suffixes)) @@ -180,10 +177,7 @@ others = pcprofiledump install-bin = pcprofiledump install-bin-script = xtrace -ifeq ($(build-shared),yes) -install-bin-script += catchsegv -endif -generated += catchsegv xtrace +generated += xtrace include ../Rules @@ -209,15 +203,6 @@ endif sLIBdir := $(shell echo $(slibdir) | sed 's,lib\(\|64\)$$,\\\\$$LIB,') -$(objpfx)catchsegv: catchsegv.sh $(common-objpfx)soversions.mk \ - $(common-objpfx)config.make - slibpfx=`echo $(slibdir)|sed 's/lib\(64\|\)$$/\\\\\\\\$$LIB/'`; \ - sed -e 's|@VERSION@|$(version)|' -e "s|@SLIB@|$$slibpfx|" \ - -e 's|@PKGVERSION@|$(PKGVERSION)|' \ - -e 's|@REPORT_BUGS_TO@|$(REPORT_BUGS_TO)|' $< > $@.new - chmod 555 $@.new - mv -f $@.new $@ - $(objpfx)pcprofiledump: $(objpfx)pcprofiledump.o $(objpfx)xtrace: xtrace.sh diff --git a/debug/catchsegv.sh b/debug/catchsegv.sh deleted file mode 100755 index f8328eee69..0000000000 --- a/debug/catchsegv.sh +++ /dev/null @@ -1,106 +0,0 @@ -#!/bin/sh -# Copyright (C) 1998-2022 Free Software Foundation, Inc. -# This file is part of the GNU C Library. - -# The GNU C Library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. - -# The GNU C Library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. - -# You should have received a copy of the GNU Lesser General Public -# License along with the GNU C Library; if not, see -# <https://www.gnu.org/licenses/>. - -if test $# -eq 0; then - echo "$0: missing program name" >&2 - echo "Try \`$0 --help' for more information." >&2 - exit 1 -fi - -prog="$1" -shift - -if test $# -eq 0; then - case "$prog" in - --h | --he | --hel | --help) - echo 'Usage: catchsegv PROGRAM ARGS...' - echo ' --help print this help, then exit' - echo ' --version print version number, then exit' - echo 'For bug reporting instructions, please see:' - cat <<\EOF -@REPORT_BUGS_TO@. -EOF - exit 0 - ;; - --v | --ve | --ver | --vers | --versi | --versio | --version) - echo 'catchsegv @PKGVERSION@@VERSION@' - echo 'Copyright (C) 2022 Free Software Foundation, Inc. -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -Written by Ulrich Drepper.' - exit 0 - ;; - *) - ;; - esac -fi - -segv_output=`mktemp ${TMPDIR:-/tmp}/segv_output.XXXXXX` || exit - -# Redirect stderr to avoid termination message from shell. -(exec 3>&2 2>/dev/null -LD_PRELOAD=${LD_PRELOAD:+${LD_PRELOAD}:}@SLIB@/libSegFault.so \ -SEGFAULT_USE_ALTSTACK=1 \ -SEGFAULT_OUTPUT_NAME=$segv_output \ -"$prog" ${1+"$@"} 2>&3 3>&-) -exval=$? - -# Check for output. Even if the program terminated correctly it might -# be that a minor process (clone) failed. Therefore we do not check the -# exit code. -if test -s "$segv_output"; then - # The program caught a signal. The output is in the file with the - # name we have in SEGFAULT_OUTPUT_NAME. In the output the names of - # functions in shared objects are available, but names in the static - # part of the program are not. We use addr2line to get this information. - case $prog in - */*) ;; - *) - old_IFS=$IFS - IFS=: - for p in $PATH; do - test -n "$p" || p=. - if test -f "$p/$prog"; then - prog=$p/$prog - break - fi - done - IFS=$old_IFS - ;; - esac - sed '/Backtrace/q' "$segv_output" - sed '1,/Backtrace/d' "$segv_output" | - (while read line; do - line=`echo $line | sed "s@^$prog\\(\\[.*\\)@\1@"` - case "$line" in - \[*) addr=`echo "$line" | sed 's/^\[\(.*\)\]$/\1/'` - complete=`addr2line -f -e "$prog" $addr 2>/dev/null` - if test $? -eq 0; then - echo "`echo "$complete"|sed 'N;s/\(.*\)\n\(.*\)/\2(\1)/;'`$line" - else - echo "$line" - fi - ;; - *) echo "$line" - ;; - esac - done) -fi -rm -f "$segv_output" - -exit $exval diff --git a/debug/segfault.c b/debug/segfault.c deleted file mode 100644 index 55801d1944..0000000000 --- a/debug/segfault.c +++ /dev/null @@ -1,215 +0,0 @@ -/* Catch segmentation faults and print backtrace. - Copyright (C) 1998-2022 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <https://www.gnu.org/licenses/>. */ - -#include <alloca.h> -#include <ctype.h> -#include <errno.h> -#include <execinfo.h> -#include <fcntl.h> -#include <signal.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <_itoa.h> -#include <ldsodefs.h> - -/* This file defines macros to access the content of the sigcontext element - passed up by the signal handler. */ -#include <sigcontextinfo.h> - -#ifdef SA_SIGINFO -# define SIGCONTEXT siginfo_t *info, void * -#endif - -/* Get code to possibly dump the content of all registers. */ -#include <register-dump.h> - -/* We'll use this a lot. */ -#define WRITE_STRING(s) write (fd, s, strlen (s)) - -/* Name of the output file. */ -static const char *fname; - - -/* Print the signal number SIGNAL. Either strerror or strsignal might - call local internal functions and these in turn call far too many - other functions and might even allocate memory which might fail. */ -static void -write_strsignal (int fd, int signal) -{ - char buf[30]; - char *ptr = _itoa_word (signal, &buf[sizeof (buf)], 10, 0); - WRITE_STRING ("signal "); - write (fd, ptr, &buf[sizeof (buf)] - ptr); -} - - -/* This function is called when a segmentation fault is caught. The system - is in an unstable state now. This means especially that malloc() might - not work anymore. */ -static void -catch_segfault (int signal, SIGCONTEXT ctx) -{ - int fd, cnt, i; - void **arr; - struct sigaction sa; - uintptr_t pc; - - /* This is the name of the file we are writing to. If none is given - or we cannot write to this file write to stderr. */ - fd = 2; - if (fname != NULL) - { - fd = open (fname, O_TRUNC | O_WRONLY | O_CREAT, 0666); - if (fd == -1) - fd = 2; - } - - WRITE_STRING ("*** "); - write_strsignal (fd, signal); - WRITE_STRING ("\n"); - -#ifdef REGISTER_DUMP - REGISTER_DUMP; -#endif - - WRITE_STRING ("\nBacktrace:\n"); - - /* Get the backtrace. */ - arr = alloca (256 * sizeof (void *)); - cnt = backtrace (arr, 256); - - /* Now try to locate the PC from signal context in the backtrace. - Normally it will be found at arr[2], but it might appear later - if there were some signal handler wrappers. Allow a few bytes - difference to cope with as many arches as possible. */ - pc = sigcontext_get_pc (ctx); - for (i = 0; i < cnt; ++i) - if ((uintptr_t) arr[i] >= pc - 16 && (uintptr_t) arr[i] <= pc + 16) - break; - - /* If we haven't found it, better dump full backtrace even including - the signal handler frames instead of not dumping anything. */ - if (i == cnt) - i = 0; - - /* Now generate nicely formatted output. */ - __backtrace_symbols_fd (arr + i, cnt - i, fd); - -#ifdef HAVE_PROC_SELF - /* Now the link map. */ - int mapfd = open ("/proc/self/maps", O_RDONLY); - if (mapfd != -1) - { - write (fd, "\nMemory map:\n\n", 14); - - char buf[256]; - ssize_t n; - - while ((n = TEMP_FAILURE_RETRY (read (mapfd, buf, sizeof (buf)))) > 0) - TEMP_FAILURE_RETRY (write (fd, buf, n)); - - close (mapfd); - } -#endif - - /* Pass on the signal (so that a core file is produced). */ - sa.sa_handler = SIG_DFL; - sigemptyset (&sa.sa_mask); - sa.sa_flags = 0; - sigaction (signal, &sa, NULL); - raise (signal); -} - - -static void -__attribute__ ((constructor)) -install_handler (void) -{ - struct sigaction sa; - const char *sigs = getenv ("SEGFAULT_SIGNALS"); - const char *name; - -#ifdef SA_SIGINFO - sa.sa_sigaction = catch_segfault; - sa.sa_flags = SA_SIGINFO; -#else - sa.sa_handler = (void*) catch_segfault; - sa.sa_flags = 0; -#endif - sigemptyset (&sa.sa_mask); - sa.sa_flags |= SA_RESTART; - - /* Maybe we are expected to use an alternative stack. */ - if (getenv ("SEGFAULT_USE_ALTSTACK") != 0) - { - void *stack_mem = malloc (2 * SIGSTKSZ); - stack_t ss; - - if (stack_mem != NULL) - { - ss.ss_sp = stack_mem; - ss.ss_flags = 0; - ss.ss_size = 2 * SIGSTKSZ; - - if (sigaltstack (&ss, NULL) == 0) - sa.sa_flags |= SA_ONSTACK; - } - } - - if (sigs == NULL) - sigaction (SIGSEGV, &sa, NULL); - else if (sigs[0] == '\0') - /* Do not do anything. */ - return; - else - { - const char *where; - int all = __strcasecmp (sigs, "all") == 0; - -#define INSTALL_FOR_SIG(sig, name) \ - where = __strcasestr (sigs, name); \ - if (all || (where != NULL \ - && (where == sigs || !isalnum (where[-1])) \ - && !isalnum (where[sizeof (name) - 1]))) \ - sigaction (sig, &sa, NULL); - - INSTALL_FOR_SIG (SIGSEGV, "segv"); - INSTALL_FOR_SIG (SIGILL, "ill"); -#ifdef SIGBUS - INSTALL_FOR_SIG (SIGBUS, "bus"); -#endif -#ifdef SIGSTKFLT - INSTALL_FOR_SIG (SIGSTKFLT, "stkflt"); -#endif - INSTALL_FOR_SIG (SIGABRT, "abrt"); - INSTALL_FOR_SIG (SIGFPE, "fpe"); - } - - /* Preserve the output file name if there is any given. */ - name = getenv ("SEGFAULT_OUTPUT_NAME"); - if (name != NULL && name[0] != '\0') - { - int ret = access (name, R_OK | W_OK); - - if (ret == 0 || (ret == -1 && errno == ENOENT)) - fname = __strdup (name); - } -} diff --git a/sysdeps/generic/register-dump.h b/sysdeps/generic/register-dump.h deleted file mode 100644 index 9d6b2a3b0b..0000000000 --- a/sysdeps/generic/register-dump.h +++ /dev/null @@ -1,19 +0,0 @@ -/* Dump registers. - Copyright (C) 1998-2022 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <https://www.gnu.org/licenses/>. */ - -/* In general we cannot do anything. */ diff --git a/sysdeps/powerpc/powerpc32/register-dump.h b/sysdeps/powerpc/powerpc32/register-dump.h deleted file mode 100644 index ea1335fd02..0000000000 --- a/sysdeps/powerpc/powerpc32/register-dump.h +++ /dev/null @@ -1,120 +0,0 @@ -/* Dump registers. - Copyright (C) 1998-2022 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <https://www.gnu.org/licenses/>. */ - -#include <sys/uio.h> -#include <_itoa.h> - -/* This prints out the information in the following form: */ -static const char dumpform[] = "\ -Register dump:\n\ -fp0-3: 0000030%0000031% 0000032%0000033% 0000034%0000035% 0000036%0000037%\n\ -fp4-7: 0000038%0000039% 000003a%000003b% 000003c%000003d% 000003e%000003f%\n\ -fp8-11: 0000040%0000041% 0000042%0000043% 0000044%0000045% 0000046%0000047%\n\ -fp12-15: 0000048%0000049% 000004a%000004b% 000004c%000004d% 000004e%000004f%\n\ -fp16-19: 0000050%0000051% 0000052%0000053% 0000054%0000055% 0000056%0000057%\n\ -fp20-23: 0000058%0000059% 000005a%000005b% 000005c%000005d% 000005e%000005f%\n\ -fp24-27: 0000060%0000061% 0000062%0000063% 0000064%0000065% 0000066%0000067%\n\ -fp28-31: 0000068%0000069% 000006a%000006b% 000006c%000006d% 000006e%000006f%\n\ -r0 =0000000% sp =0000001% r2 =0000002% r3 =0000003% trap=0000028%\n\ -r4 =0000004% r5 =0000005% r6 =0000006% r7 =0000007% sr0=0000020% sr1=0000021%\n\ -r8 =0000008% r9 =0000009% r10=000000a% r11=000000b% dar=0000029% dsi=000002a%\n\ -r12=000000c% r13=000000d% r14=000000e% r15=000000f% r3*=0000022%\n\ -r16=0000010% r17=0000011% r18=0000012% r19=0000013%\n\ -r20=0000014% r21=0000015% r22=0000016% r23=0000017% lr=0000024% xer=0000025%\n\ -r24=0000018% r25=0000019% r26=000001a% r27=000001b% mq=0000027% ctr=0000023%\n\ -r28=000001c% r29=000001d% r30=000001e% r31=000001f% fscr=0000071% ccr=0000026%\n\ -"; - -/* Most of the fields are self-explanatory. 'sr0' is the next - instruction to execute, from SRR0, which may have some relationship - with the instruction that caused the exception. 'r3*' is the value - that will be returned in register 3 when the current system call - returns. 'sr1' is SRR1, bits 16-31 of which are copied from the MSR: - - 16 - External interrupt enable - 17 - Privilege level (1=user, 0=supervisor) - 18 - FP available - 19 - Machine check enable (if clear, processor locks up on machine check) - 20 - FP exception mode bit 0 (FP exceptions recoverable) - 21 - Single-step trace enable - 22 - Branch trace enable - 23 - FP exception mode bit 1 - 25 - exception prefix (if set, exceptions are taken from 0xFFFnnnnn, - otherwise from 0x000nnnnn). - 26 - Instruction address translation enabled. - 27 - Data address translation enabled. - 30 - Exception is recoverable (otherwise, don't try to return). - 31 - Little-endian mode enable. - - 'Trap' is the address of the exception: - - 00200 - Machine check exception (memory parity error, for instance) - 00300 - Data access exception (memory not mapped, see dsisr for why) - 00400 - Instruction access exception (memory not mapped) - 00500 - External interrupt - 00600 - Alignment exception (see dsisr for more information) - 00700 - Program exception (illegal/trap instruction, FP exception) - 00800 - FP unavailable (should not be seen by user code) - 00900 - Decrementer exception (for instance, SIGALRM) - 00A00 - I/O controller interface exception - 00C00 - System call exception (for instance, kill(3)). - 00E00 - FP assist exception (optional FP instructions, etc.) - - 'dar' is the memory location, for traps 00300, 00400, 00600, 00A00. - 'dsisr' has the following bits under trap 00300: - 0 - direct-store error exception - 1 - no page table entry for page - 4 - memory access not permitted - 5 - trying to access I/O controller space or using lwarx/stwcx on - non-write-cached memory - 6 - access was store - 9 - data access breakpoint hit - 10 - segment table search failed to find translation (64-bit ppcs only) - 11 - I/O controller instruction not permitted - For trap 00400, the same bits are set in SRR1 instead. - For trap 00600, bits 12-31 of the DSISR set to allow emulation of - the instruction without actually having to read it from memory. -*/ - -#define xtoi(x) (x >= 'a' ? x + 10 - 'a' : x - '0') - -static void |
