aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog12
-rw-r--r--gdb/common/signals-state-save-restore.c32
-rw-r--r--gdb/common/signals-state-save-restore.h5
-rw-r--r--gdb/gdbserver/ChangeLog6
-rw-r--r--gdb/gdbserver/server.c2
-rw-r--r--gdb/main.c3
-rw-r--r--gdb/testsuite/ChangeLog5
-rw-r--r--gdb/testsuite/gdb.base/libsegfault.exp84
8 files changed, 141 insertions, 8 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 0eeff94..24ccfe6 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,17 @@
2018-01-05 Pedro Alves <palves@redhat.com>
+ PR gdb/18653
+ * common/signals-state-save-restore.c
+ (save_original_signals_state): New parameter 'quiet'. Warn if we
+ find a custom handler preinstalled, instead of internal erroring.
+ But only warn if !quiet.
+ * common/signals-state-save-restore.h
+ (save_original_signals_state): New parameter 'quiet'.
+ * main.c (captured_main_1): Move save_original_signals_state call
+ after option handling, and pass QUIET.
+
+2018-01-05 Pedro Alves <palves@redhat.com>
+
* spu-tdep.c (spu_catch_start): Pass
symbol_name_match_type::SEARCH_NAME to block_lookup_symbol.
diff --git a/gdb/common/signals-state-save-restore.c b/gdb/common/signals-state-save-restore.c
index 7c7afd3..eb281dd 100644
--- a/gdb/common/signals-state-save-restore.c
+++ b/gdb/common/signals-state-save-restore.c
@@ -35,7 +35,7 @@ static sigset_t original_signal_mask;
/* See signals-state-save-restore.h. */
void
-save_original_signals_state (void)
+save_original_signals_state (bool quiet)
{
#ifdef HAVE_SIGACTION
int i;
@@ -45,6 +45,8 @@ save_original_signals_state (void)
if (res == -1)
perror_with_name (("sigprocmask"));
+ bool found_preinstalled = false;
+
for (i = 1; i < NSIG; i++)
{
struct sigaction *oldact = &original_signal_actions[i];
@@ -59,9 +61,31 @@ save_original_signals_state (void)
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"));
+ this function was called too late. This is a warning instead
+ of an internal error because this can also happen if you
+ LD_PRELOAD a library that installs a signal handler early via
+ __attribute__((constructor)), like libSegFault.so. */
+ if (!quiet
+ && oldact->sa_handler != SIG_DFL
+ && oldact->sa_handler != SIG_IGN)
+ {
+ found_preinstalled = true;
+
+ /* Use raw fprintf here because we're being called in early
+ startup, because GDB's filtered streams are are
+ created. */
+ fprintf (stderr,
+ _("warning: Found custom handler for signal "
+ "%d (%s) preinstalled.\n"), i,
+ strsignal (i));
+ }
+ }
+
+ if (found_preinstalled)
+ {
+ fprintf (stderr, _("\
+Some signal dispositions inherited from the environment (SIG_DFL/SIG_IGN)\n\
+won't be propagated to spawned programs.\n"));
}
#endif
}
diff --git a/gdb/common/signals-state-save-restore.h b/gdb/common/signals-state-save-restore.h
index 71ec08e..276ddc4 100644
--- a/gdb/common/signals-state-save-restore.h
+++ b/gdb/common/signals-state-save-restore.h
@@ -28,9 +28,10 @@
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. */
+/* Save the signal state of all signals. If !QUIET, warn if we detect
+ a custom signal handler preinstalled. */
-extern void save_original_signals_state (void);
+extern void save_original_signals_state (bool quiet);
/* Restore the signal state of all signals. */
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 1170a06..2299c8e 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,9 @@
+2018-01-05 Pedro Alves <palves@redhat.com>
+
+ PR gdb/18653
+ * server.c (captured_main): Pass quiet=false to
+ save_original_signals_state.
+
2018-01-01 Joel Brobecker <brobecker@adacore.com>
* gdbreplay.c (gdbreplay_version): Update copyright year in
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 3367555..1a72123 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -3712,7 +3712,7 @@ captured_main (int argc, char *argv[])
opened by remote_prepare. */
notice_open_fds ();
- save_original_signals_state ();
+ save_original_signals_state (false);
/* We need to know whether the remote connection is stdio before
starting the inferior. Inferiors created in this scenario have
diff --git a/gdb/main.c b/gdb/main.c
index 77d2bf7..3c98787 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -506,7 +506,6 @@ captured_main_1 (struct captured_main_args *context)
bfd_init ();
notice_open_fds ();
- save_original_signals_state ();
saved_command_line = (char *) xstrdup ("");
@@ -849,6 +848,8 @@ captured_main_1 (struct captured_main_args *context)
quiet = 1;
}
+ save_original_signals_state (quiet);
+
/* Try to set up an alternate signal stack for SIGSEGV handlers. */
setup_alternate_signal_stack ();
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 18ad740..e87099b 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2018-01-05 Pedro Alves <palves@redhat.com>
+
+ PR gdb/18653
+ * gdb.base/libsegfault.exp: New.
+
2018-01-05 Joel Brobecker <brobecker@adacore.com>
PR gdb/22670
diff --git a/gdb/testsuite/gdb.base/libsegfault.exp b/gdb/testsuite/gdb.base/libsegfault.exp
new file mode 100644
index 0000000..e1de253
--- /dev/null
+++ b/gdb/testsuite/gdb.base/libsegfault.exp
@@ -0,0 +1,84 @@
+# Copyright 2017-2018 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/>.
+
+# This file is part of the gdb testsuite.
+
+# Test that GDB tolerates being started with libSegFault.so preloaded
+# with LD_PRELOAD, and that GDB warns about a custom SIGSEGV custom
+# handler. See PR gdb/18653
+# <https://sourceware.org/bugzilla/show_bug.cgi?id=18653#c7>.
+
+# We cannot expect remote hosts to see environment variables set on
+# the local machine.
+if { [is_remote host] } {
+ unsupported "can't set environment variables on remote host"
+ return -1
+}
+
+# Spawn GDB with LIB preloaded with LD_PRELOAD. CMDLINE_OPTS are
+# command line options passed to GDB.
+
+proc gdb_spawn_with_ld_preload {lib cmdline_opts} {
+ global env
+
+ save_vars { env(LD_PRELOAD) } {
+ if { ![info exists env(LD_PRELOAD) ]
+ || $env(LD_PRELOAD) == "" } {
+ set env(LD_PRELOAD) "$lib"
+ } else {
+ append env(LD_PRELOAD) ":$lib"
+ }
+
+ gdb_spawn_with_cmdline_opts $cmdline_opts
+ }
+}
+
+proc test_libsegfault {} {
+ global gdb_prompt
+
+ set libsegfault "libSegFault.so"
+
+ # When started normally, if libSegFault.so is preloaded, GDB
+ # should warn about not being able to propagate the signal
+ # disposition of SIGSEGV.
+ gdb_exit
+ gdb_spawn_with_ld_preload $libsegfault ""
+
+ set test "gdb emits custom handler warning"
+ gdb_test_multiple "" $test {
+ -re "cannot be preloaded.*\r\n$gdb_prompt $" {
+ # Glibc 2.22 outputs:
+ # ERROR: ld.so: object 'libSegFault.so' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
+ untested "cannot preload libSegFault.so"
+ return
+ }
+ -re "Found custom handler.*won't be propagated.*\r\n$gdb_prompt $" {
+ pass $test
+ }
+ }
+
+ # "-q" should disable the warning, though.
+ gdb_exit
+ gdb_spawn_with_ld_preload $libsegfault "-q"
+
+ set test "quiet suppresses custom handler warning"
+ gdb_test_multiple "" $test {
+ -re "^$gdb_prompt $" {
+ pass $test
+ }
+ }
+}
+
+test_libsegfault