diff options
-rw-r--r-- | gdb/ChangeLog | 17 | ||||
-rw-r--r-- | gdb/Makefile.in | 9 | ||||
-rw-r--r-- | gdb/common/common.m4 | 2 | ||||
-rw-r--r-- | gdb/common/signals-state-save-restore.c | 94 | ||||
-rw-r--r-- | gdb/common/signals-state-save-restore.h | 39 | ||||
-rwxr-xr-x | gdb/configure | 2 | ||||
-rw-r--r-- | gdb/fork-child.c | 4 | ||||
-rw-r--r-- | gdb/gdbserver/ChangeLog | 13 | ||||
-rw-r--r-- | gdb/gdbserver/Makefile.in | 4 | ||||
-rw-r--r-- | gdb/gdbserver/config.in | 3 | ||||
-rwxr-xr-x | gdb/gdbserver/configure | 2 | ||||
-rw-r--r-- | gdb/gdbserver/linux-low.c | 4 | ||||
-rw-r--r-- | gdb/gdbserver/server.c | 4 | ||||
-rw-r--r-- | gdb/main.c | 2 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/signals-state-child.c | 101 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/signals-state-child.exp | 82 | ||||
-rw-r--r-- | gdb/testsuite/gdb.gdb/selftest.exp | 4 |
18 files changed, 386 insertions, 7 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index dd87420..bfa131f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,22 @@ 2016-08-09 Pedro Alves <palves@redhat.com> + PR gdb/18653 + * Makefile.in (SFILES): Add + common/signals-state-save-restore.c. + (HFILES_NO_SRCDIR): Add common/signals-state-save-restore.h. + (COMMON_OBS): Add signals-state-save-restore.o. + (signals-state-save-restore.o): New rule. + * configure: Regenerate. + * fork-child.c: Include "signals-state-save-restore.h". + (fork_inferior): Call restore_original_signals_state. + * main.c: Include "signals-state-save-restore.h". + (captured_main): Call save_original_signals_state. + * common/common.m4: Add sigaction to AC_CHECK_FUNCS checks. + * common/signals-state-save-restore.c: New file. + * common/signals-state-save-restore.h: New file. + +2016-08-09 Pedro Alves <palves@redhat.com> + * value.c (unpack_value_bitfield): Skip unpacking if the parent has no contents buffer to begin with. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 5af6103..7b2df86 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -897,6 +897,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ target/waitstatus.c common/print-utils.c common/rsp-low.c \ common/errors.c common/common-debug.c common/common-exceptions.c \ common/btrace-common.c common/fileio.c common/common-regcache.c \ + common/signals-state-save-restore.c \ $(SUBDIR_GCC_COMPILE_SRCS) LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c @@ -989,7 +990,8 @@ common/common-exceptions.h target/target.h common/symbol.h \ common/common-regcache.h fbsd-tdep.h nat/linux-personality.h \ common/fileio.h nat/x86-linux.h nat/x86-linux-dregs.h nat/amd64-linux-siginfo.h\ nat/linux-namespaces.h arch/arm.h common/gdb_sys_time.h arch/aarch64-insn.h \ -tid-parse.h ser-event.h +tid-parse.h ser-event.h \ +common/signals-state-save-restore.h # Header files that already have srcdir in them, or which are in objdir. @@ -1049,6 +1051,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ build-id.o buildsym.o \ findcmd.o \ std-regs.o \ + signals-state-save-restore.o \ signals.o \ exec.o reverse.o \ bcache.o objfiles.o observer.o minsyms.o maint.o demangle.o \ @@ -2286,6 +2289,10 @@ common-regcache.o: ${srcdir}/common/common-regcache.c $(COMPILE) $(srcdir)/common/common-regcache.c $(POSTCOMPILE) +signals-state-save-restore.o: $(srcdir)/common/signals-state-save-restore.c + $(COMPILE) $(srcdir)/common/signals-state-save-restore.c + $(POSTCOMPILE) + # # gdb/target/ dependencies # diff --git a/gdb/common/common.m4 b/gdb/common/common.m4 index 1342503..68afc65 100644 --- a/gdb/common/common.m4 +++ b/gdb/common/common.m4 @@ -30,7 +30,7 @@ AC_DEFUN([GDB_AC_COMMON], [ sys/un.h sys/wait.h dnl thread_db.h wait.h) - AC_CHECK_FUNCS([fdwalk getrlimit pipe pipe2 socketpair]) + AC_CHECK_FUNCS([fdwalk getrlimit pipe pipe2 socketpair sigaction]) AC_CHECK_DECLS([strerror, strstr]) diff --git a/gdb/common/signals-state-save-restore.c b/gdb/common/signals-state-save-restore.c new file mode 100644 index 0000000..1c00cdd --- /dev/null +++ b/gdb/common/signals-state-save-restore.c @@ -0,0 +1,94 @@ +/* Copyright (C) 2016 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "common-defs.h" +#include "signals-state-save-restore.h" + +#include <signal.h> + +/* The original signal actions and mask. */ + +#ifdef HAVE_SIGACTION +static struct sigaction original_signal_actions[NSIG]; + +/* Note that we use sigprocmask without worrying about threads because + the save/restore functions are called either from main, or after a + fork. In both cases, we know the calling process is single + threaded. */ +static sigset_t original_signal_mask; +#endif + +/* See signals-state-save-restore.h. */ + +void +save_original_signals_state (void) +{ +#ifdef HAVE_SIGACTION + int i; + int res; + + res = sigprocmask (0, NULL, &original_signal_mask); + if (res == -1) + perror_with_name ("sigprocmask"); + + for (i = 1; i < NSIG; i++) + { + struct sigaction *oldact = &original_signal_actions[i]; + + res = sigaction (i, NULL, oldact); + if (res == -1 && errno == EINVAL) + { + /* Some signal numbers in the range are invalid. */ + continue; + } + else if (res == -1) + perror_with_name ("sigaction"); + + /* If we find a custom signal handler already installed, then + this function was called too late. */ + if (oldact->sa_handler != SIG_DFL && oldact->sa_handler != SIG_IGN) + internal_error (__FILE__, __LINE__, _("unexpected signal handler")); + } +#endif +} + +/* See signals-state-save-restore.h. */ + +void +restore_original_signals_state (void) +{ +#ifdef HAVE_SIGACTION + int i; + int res; + + for (i = 1; i < NSIG; i++) + { + res = sigaction (i, &original_signal_actions[i], NULL); + if (res == -1 && errno == EINVAL) + { + /* Some signal numbers in the range are invalid. */ + continue; + } + else if (res == -1) + perror_with_name ("sigaction"); + } + + res = sigprocmask (SIG_SETMASK, &original_signal_mask, NULL); + if (res == -1) + perror_with_name ("sigprocmask"); +#endif +} diff --git a/gdb/common/signals-state-save-restore.h b/gdb/common/signals-state-save-restore.h new file mode 100644 index 0000000..bed77fe --- /dev/null +++ b/gdb/common/signals-state-save-restore.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2016 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef COMMON_SIGNALS_STATE_SAVE_RESTORE_H +#define COMMON_SIGNALS_STATE_SAVE_RESTORE_H + +/* Save/restore the signal actions of all signals, and the signal + mask. + + Since the exec family of functions does not reset the signal + disposition of signals set to SIG_IGN, nor does it reset the signal + mask, in order to be transparent, when spawning new child processes + to debug (with "run", etc.), we must reset signal actions and mask + back to what was originally inherited from gdb/gdbserver's parent, + just before execing the target program to debug. */ + +/* Save the signal state of all signals. */ + +extern void save_original_signals_state (void); + +/* Restore the signal state of all signals. */ + +extern void restore_original_signals_state (void); + +#endif /* COMMON_SIGNALS_STATE_SAVE_RESTORE_H */ diff --git a/gdb/configure b/gdb/configure index 8f92ed9..7577ba4 100755 --- a/gdb/configure +++ b/gdb/configure @@ -12244,7 +12244,7 @@ fi done - for ac_func in fdwalk getrlimit pipe pipe2 socketpair + for ac_func in fdwalk getrlimit pipe pipe2 socketpair sigaction do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/gdb/fork-child.c b/gdb/fork-child.c index 8ac3bef..6856cf6 100644 --- a/gdb/fork-child.c +++ b/gdb/fork-child.c @@ -32,7 +32,7 @@ #include "solib.h" #include "filestuff.h" #include "top.h" - +#include "signals-state-save-restore.h" #include <signal.h> /* This just gets used as a default if we can't find SHELL. */ @@ -366,6 +366,8 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env, saying "not parent". Sorry; you'll have to use print statements! */ + restore_original_signals_state (); + /* There is no execlpe call, so we have to set the environment for our child in the global variable. If we've vforked, this clobbers the parent, but environ is restored a few lines down diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index e88b001..6986714 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,16 @@ +2016-08-09 Pedro Alves <palves@redhat.com> + + PR gdb/18653 + * Makefile.in (OBS): Add signals-state-save-restore.o. + (signals-state-save-restore.o): New rule. + * config.in: Regenerate. + * configure: Regenerate. + * linux-low.c: Include "signals-state-save-restore.h". + (linux_create_inferior): Call + restore_original_signals_state. + * server.c: Include "dispositions-save-restore.h". + (captured_main): Call save_original_signals_state. + 2016-08-05 Pedro Alves <palves@redhat.com> * configure: Regenerate. diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index 2be61ef..bed2b1e 100644 --- a/gdb/gdbserver/Makefile.in +++ b/gdb/gdbserver/Makefile.in @@ -200,6 +200,7 @@ OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o \ common-utils.o ptid.o buffer.o format.o filestuff.o dll.o notif.o \ tdesc.o print-utils.o rsp-low.o errors.o common-debug.o cleanups.o \ common-exceptions.o symbol.o btrace-common.o fileio.o common-regcache.o \ + signals-state-save-restore.o \ $(XML_BUILTIN) $(DEPFILES) $(LIBOBJS) GDBREPLAY_OBS = gdbreplay.o version.o GDBSERVER_LIBS = @GDBSERVER_LIBS@ @@ -715,6 +716,9 @@ fileio.o: ../common/fileio.c common-regcache.o: ../common/common-regcache.c $(COMPILE) $< $(POSTCOMPILE) +signals-state-save-restore.o: ../common/signals-state-save-restore.c + $(COMPILE) $< + $(POSTCOMPILE) # Arch object files rules form ../arch diff --git a/gdb/gdbserver/config.in b/gdb/gdbserver/config.in index 2c3a69a..04072cf 100644 --- a/gdb/gdbserver/config.in +++ b/gdb/gdbserver/config.in @@ -202,6 +202,9 @@ /* Define to 1 if you have the <sgtty.h> header file. */ #undef HAVE_SGTTY_H +/* Define to 1 if you have the `sigaction' function. */ +#undef HAVE_SIGACTION + /* Define to 1 if you have the <signal.h> header file. */ #undef HAVE_SIGNAL_H diff --git a/gdb/gdbserver/configure b/gdb/gdbserver/configure index 80fa1f3..889e35b 100755 --- a/gdb/gdbserver/configure +++ b/gdb/gdbserver/configure @@ -5913,7 +5913,7 @@ fi done - for ac_func in fdwalk getrlimit pipe pipe2 socketpair + for ac_func in fdwalk getrlimit pipe pipe2 socketpair sigaction do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 1839f99..45061ac 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -22,7 +22,7 @@ #include "agent.h" #include "tdesc.h" #include "rsp-low.h" - +#include "signals-state-save-restore.h" #include "nat/linux-nat.h" #include "nat/linux-waitpid.h" #include "gdb_wait.h" @@ -975,6 +975,8 @@ linux_create_inferior (char *program, char **allargs) } } + restore_original_signals_state (); + execv (program, allargs); if (errno == ENOENT) execvp (program, allargs); diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 6d6cb09..6fbd61d 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -22,7 +22,7 @@ #include "notif.h" #include "tdesc.h" #include "rsp-low.h" - +#include "signals-state-save-restore.h" #include <ctype.h> #include <unistd.h> #if HAVE_SIGNAL_H @@ -3611,6 +3611,8 @@ captured_main (int argc, char *argv[]) opened by remote_prepare. */ notice_open_fds (); + save_original_signals_state (); + /* We need to know whether the remote connection is stdio before starting the inferior. Inferiors created in this scenario have stdin,stdout redirected. So do this here before we call @@ -44,6 +44,7 @@ #include <signal.h> #include "event-top.h" #include "infrun.h" +#include "signals-state-save-restore.h" /* The selected interpreter. This will be used as a set command variable, so it should always be malloc'ed - since @@ -505,6 +506,7 @@ captured_main (void *data) bfd_init (); notice_open_fds (); + save_original_signals_state (); make_cleanup (VEC_cleanup (cmdarg_s), &cmdarg_vec); dirsize = 1; diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 4b70059..6581556 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,12 @@ 2016-08-09 Pedro Alves <palves@redhat.com> + PR gdb/18653 + * gdb.base/signals-state-child.c: New file. + * gdb.base/signals-state-child.exp: New file. + * gdb.gdb/selftest.exp (do_steps_and_nexts): Add new pattern. + +2016-08-09 Pedro Alves <palves@redhat.com> + * gdb.dwarf2/bitfield-parent-optimized-out.exp: New file. 2016-08-03 Tom Tromey <tom@tromey.com> diff --git a/gdb/testsuite/gdb.base/signals-state-child.c b/gdb/testsuite/gdb.base/signals-state-child.c new file mode 100644 index 0000000..e11fa93 --- /dev/null +++ b/gdb/testsuite/gdb.base/signals-state-child.c @@ -0,0 +1,101 @@ +/* Copyright 2016 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <stdlib.h> +#include <stdio.h> +#include <signal.h> +#include <assert.h> +#include <errno.h> + +#ifndef OUTPUT_TXT +# define OUTPUT_TXT "output.txt" +#endif + +static void +perror_and_exit (const char *s) +{ + perror (s); + exit (1); +} + +int +main (int argc, char **argv) +{ + int i; + FILE *out; + sigset_t sigset; + int res; + + res = sigprocmask (0, NULL, &sigset); + if (res != 0) + perror_and_exit ("sigprocmask"); + + if (argc > 1) + out = stdout; + else + { + out = fopen (OUTPUT_TXT, "w"); + if (out == NULL) + perror_and_exit ("fopen"); + } + + for (i = 1; i < NSIG; i++) + { + struct sigaction oldact; + + fprintf (out, "signal %d: ", i); + + res = sigaction (i, NULL, &oldact); + if (res == -1 && errno == EINVAL) + { + /* Some signal numbers in the range are invalid. E.g., + signals 32 and 33 on GNU/Linux. */ + fprintf (out, "invalid"); + } + else if (res == -1) + { + perror_and_exit ("sigaction"); + } + else + { + int m; + + fprintf (out, "sigaction={sa_handler=", i); + + if (oldact.sa_handler == SIG_DFL) + fprintf (out, "SIG_DFL"); + else if (oldact.sa_handler == SIG_IGN) + fprintf (out, "SIG_IGN"); + else + abort (); + + fprintf (out, ", sa_mask="); + for (m = 1; m < NSIG; m++) + fprintf (out, "%c", sigismember (&oldact.sa_mask, m) ? '1' : '0'); + + fprintf (out, ", sa_flags=%d", oldact.sa_flags); + + fprintf (out, "}, masked=%d", sigismember (&sigset, i)); + } + fprintf (out, "\n"); + } + + if (out != stdout) + fclose (out); + + return 0; +} diff --git a/gdb/testsuite/gdb.base/signals-state-child.exp b/gdb/testsuite/gdb.base/signals-state-child.exp new file mode 100644 index 0000000..f5fdcb2 --- /dev/null +++ b/gdb/testsuite/gdb.base/signals-state-child.exp @@ -0,0 +1,82 @@ +# Copyright 2016 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Test that gdb's (or gdbserver's) own signal handling does not +# interfere with the signal actions (dispositions, etc.) and mask +# their spawned children inherit. +# +# - If gdb inherits some signal set to SIG_IGN, so should the +# inferior, even if gdb itself chooses not to ignore the signal. +# +# - If gdb inherits some signal set to SIG_DFL, so should the inferior +# even if gdb itself ignores that signal. +# +# This requires special support in gdb/gdbserver because the exec +# family of functions does not reset the signal disposition of signals +# that are set to SIG_IGN, nor signal masks and flags. + +standard_testfile + +set gdb_txt [standard_output_file gdb.txt] +set standalone_txt [standard_output_file standalone.txt] +remote_exec host "rm -f $gdb_txt" +remote_exec host "rm -f $standalone_txt" + +set options [list debug "additional_flags=-DOUTPUT_TXT=\"$gdb_txt\""] +if {[build_executable $testfile.exp $testfile $srcfile $options]} { + untested $testfile.exp + return -1 +} + +set options [list debug "additional_flags=-DOUTPUT_TXT=\"$standalone_txt\""] +if {[build_executable $testfile.exp $testfile-standalone $srcfile $options]} { + untested $testfile.exp + return -1 +} + +# Run the program directly, and dump its initial signal actions and +# mask in "standalone.txt". + +# Use remote_spawn instead of remote_exec, like how we spawn gdb. +# This is in order to take the same code code paths in dejagnu +# compared to when running the program through gdb. E.g., because +# local_exec uses -ignore SIGHUP, while remote_spawn does not, if we +# used remote_exec, the test program would start with SIGHUP ignored +# when run standalone, but not when run through gdb. +set res [remote_spawn host "$binfile-standalone"] +if { $res < 0 || $res == "" } { + untested "spawning $binfile-standalone failed" + return 1 +} else { + pass "collect standalone signals state" +} +remote_close host + +# Now run the program through gdb, and dump its initial signal actions +# and mask in "gdb.txt". + +clean_restart $binfile + +if { ! [ runto_main ] } then { + untested $testfile.exp + return -1 +} + +gdb_continue_to_end "collect signals state under gdb" + +# Diff the .txt files. They should be identical. +gdb_test "shell diff -s $standalone_txt $gdb_txt" \ + "Files .* are identical.*" \ + "signals states are identical" diff --git a/gdb/testsuite/gdb.gdb/selftest.exp b/gdb/testsuite/gdb.gdb/selftest.exp index 2fdd9e3..28d5493 100644 --- a/gdb/testsuite/gdb.gdb/selftest.exp +++ b/gdb/testsuite/gdb.gdb/selftest.exp @@ -162,6 +162,10 @@ proc do_steps_and_nexts {} { set description "next over notice_open_fds" set command "next" } + -re ".*save_original_signals_state ..;.*$gdb_prompt $" { + set description "next over save_original_signals_state" + set command "next" + } -re ".*VEC_cleanup .cmdarg_s.*$gdb_prompt $" { set description "next over cmdarg_s VEC_cleanup" set command "next" |