Blame SOURCES/gdb-rhbz1542149-spawn-default-signal-handlers-regression.patch

15e4b0
commit e379cee61f3890e535e995828e8846b020ef2a32
15e4b0
Author: Pedro Alves <palves@redhat.com>
15e4b0
Date:   Fri Jan 5 18:26:18 2018 +0000
15e4b0
15e4b0
    Fix regression: cannot start with LD_PRELOAD=libSegFault.so (PR gdb/18653#c7)
15e4b0
    
15e4b0
    At https://sourceware.org/bugzilla/show_bug.cgi?id=18653#c7, Andrew
15e4b0
    reports that the fix for PR gdb/18653 made GDB useless if you preload
15e4b0
    libSegFault.so, because GDB internal-errors on startup:
15e4b0
    
15e4b0
     $ LD_PRELOAD=libSegFault.so gdb
15e4b0
     src/gdb/common/signals-state-save-restore.c:64: internal-error: unexpected signal handler
15e4b0
     A problem internal to GDB has been detected,
15e4b0
     further debugging may prove unreliable.
15e4b0
     Aborted (core dumped)
15e4b0
     $
15e4b0
    
15e4b0
    The internal error comes from the code saving the signal dispositions
15e4b0
    inherited from gdb's parent:
15e4b0
    
15e4b0
     (top-gdb) bt
15e4b0
     #0  0x000000000056b001 in internal_error(char const*, int, char const*, ...) (file=0xaf5f38 "src/gdb/common/signals-state-save-restore.c", line=64, fmt=0xaf5f18 "unexpected signal handler") at src/gdb/common/errors.c:54
15e4b0
     #1  0x00000000005752c9 in save_original_signals_state() () at src/gdb/common/signals-state-save-restore.c:64
15e4b0
     #2  0x00000000007425de in captured_main_1(captured_main_args*) (context=0x7fffffffd860)
15e4b0
         at src/gdb/main.c:509
15e4b0
     #3  0x0000000000743622 in captured_main(void*) (data=0x7fffffffd860) at src/gdb/main.c:1145
15e4b0
     During symbol reading, cannot get low and high bounds for subprogram DIE at 24065.
15e4b0
     #4  0x00000000007436f9 in gdb_main(captured_main_args*) (args=0x7fffffffd860) at src/gdb/main.c:1171
15e4b0
     #5  0x0000000000413acd in main(int, char**) (argc=1, argv=0x7fffffffd968) at src/gdb/gdb.c:32
15e4b0
    
15e4b0
    This commit downgrades the internal error to a warning.  You'll get
15e4b0
    instead:
15e4b0
    
15e4b0
    ~~~
15e4b0
     $ LD_PRELOAD=libSegFault.so gdb
15e4b0
     warning: Found custom handler for signal 11 (Segmentation fault) preinstalled.
15e4b0
     Some signal dispositions inherited from the environment (SIG_DFL/SIG_IGN)
15e4b0
     won't be propagated to spawned programs.
15e4b0
     GNU gdb (GDB) 8.0.50.20171213-git
15e4b0
     Copyright (C) 2017 Free Software Foundation, Inc.
15e4b0
     License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
15e4b0
     This is free software: you are free to change and redistribute it.
15e4b0
     There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
15e4b0
     and "show warranty" for details.
15e4b0
     This GDB was configured as "x86_64-pc-linux-gnu".
15e4b0
     Type "show configuration" for configuration details.
15e4b0
     For bug reporting instructions, please see:
15e4b0
     <http://www.gnu.org/software/gdb/bugs/>.
15e4b0
     Find the GDB manual and other documentation resources online at:
15e4b0
     <http://www.gnu.org/software/gdb/documentation/>.
15e4b0
     For help, type "help".
15e4b0
     Type "apropos word" to search for commands related to "word"...
15e4b0
     (gdb)
15e4b0
    ~~~
15e4b0
    
15e4b0
    This also moves the location where save_original_signals_state is
15e4b0
    called a bit further below (to after option processing), so that "-q"
15e4b0
    disables the warning:
15e4b0
    
15e4b0
    ~~~
15e4b0
     $ LD_PRELOAD=libSegFault.so gdb -q
15e4b0
     (gdb)
15e4b0
    ~~~
15e4b0
    
15e4b0
    New testcase included.
15e4b0
    
15e4b0
    gdb/ChangeLog:
15e4b0
    2018-01-05  Pedro Alves  <palves@redhat.com>
15e4b0
    
15e4b0
            PR gdb/18653
15e4b0
            * common/signals-state-save-restore.c
15e4b0
            (save_original_signals_state): New parameter 'quiet'.  Warn if we
15e4b0
            find a custom handler preinstalled, instead of internal erroring.
15e4b0
            But only warn if !quiet.
15e4b0
            * common/signals-state-save-restore.h
15e4b0
            (save_original_signals_state): New parameter 'quiet'.
15e4b0
            * main.c (captured_main_1): Move save_original_signals_state call
15e4b0
            after option handling, and pass QUIET.
15e4b0
    
15e4b0
    gdb/gdbserver/ChangeLog:
15e4b0
    2018-01-05  Pedro Alves  <palves@redhat.com>
15e4b0
    
15e4b0
            PR gdb/18653
15e4b0
            * server.c (captured_main): Pass quiet=false to
15e4b0
            save_original_signals_state.
15e4b0
    
15e4b0
    gdb/testsuite/ChangeLog:
15e4b0
    2018-01-05  Pedro Alves  <palves@redhat.com>
15e4b0
    
15e4b0
            PR gdb/18653
15e4b0
            * gdb.base/libsegfault.exp: New.
15e4b0
15e4b0
### a/gdb/ChangeLog
15e4b0
### b/gdb/ChangeLog
15e4b0
## -1,3 +1,15 @@
15e4b0
+2018-01-05  Pedro Alves  <palves@redhat.com>
15e4b0
+
15e4b0
+	PR gdb/18653
15e4b0
+	* common/signals-state-save-restore.c
15e4b0
+	(save_original_signals_state): New parameter 'quiet'.  Warn if we
15e4b0
+	find a custom handler preinstalled, instead of internal erroring.
15e4b0
+	But only warn if !quiet.
15e4b0
+	* common/signals-state-save-restore.h
15e4b0
+	(save_original_signals_state): New parameter 'quiet'.
15e4b0
+	* main.c (captured_main_1): Move save_original_signals_state call
15e4b0
+	after option handling, and pass QUIET.
15e4b0
+
15e4b0
 2018-01-05  Pedro Alves  <palves@redhat.com>
15e4b0
 
15e4b0
 	* spu-tdep.c (spu_catch_start): Pass
15e4b0
--- a/gdb/common/signals-state-save-restore.c
15e4b0
+++ b/gdb/common/signals-state-save-restore.c
15e4b0
@@ -35,7 +35,7 @@ static sigset_t original_signal_mask;
15e4b0
 /* See signals-state-save-restore.h.   */
15e4b0
 
15e4b0
 void
15e4b0
-save_original_signals_state (void)
15e4b0
+save_original_signals_state (bool quiet)
15e4b0
 {
15e4b0
 #ifdef HAVE_SIGACTION
15e4b0
   int i;
15e4b0
@@ -45,6 +45,8 @@ save_original_signals_state (void)
15e4b0
   if (res == -1)
15e4b0
     perror_with_name (("sigprocmask"));
15e4b0
 
15e4b0
+  bool found_preinstalled = false;
15e4b0
+
15e4b0
   for (i = 1; i < NSIG; i++)
15e4b0
     {
15e4b0
       struct sigaction *oldact = &original_signal_actions[i];
15e4b0
@@ -59,9 +61,31 @@ save_original_signals_state (void)
15e4b0
 	perror_with_name (("sigaction"));
15e4b0
 
15e4b0
       /* If we find a custom signal handler already installed, then
15e4b0
-	 this function was called too late.  */
15e4b0
-      if (oldact->sa_handler != SIG_DFL && oldact->sa_handler != SIG_IGN)
15e4b0
-	internal_error (__FILE__, __LINE__, _("unexpected signal handler"));
15e4b0
+	 this function was called too late.  This is a warning instead
15e4b0
+	 of an internal error because this can also happen if you
15e4b0
+	 LD_PRELOAD a library that installs a signal handler early via
15e4b0
+	 __attribute__((constructor)), like libSegFault.so.  */
15e4b0
+      if (!quiet
15e4b0
+	  && oldact->sa_handler != SIG_DFL
15e4b0
+	  && oldact->sa_handler != SIG_IGN)
15e4b0
+	{
15e4b0
+	  found_preinstalled = true;
15e4b0
+
15e4b0
+	  /* Use raw fprintf here because we're being called in early
15e4b0
+	     startup, because GDB's filtered streams are are
15e4b0
+	     created.  */
15e4b0
+	  fprintf (stderr,
15e4b0
+		   _("warning: Found custom handler for signal "
15e4b0
+		     "%d (%s) preinstalled.\n"), i,
15e4b0
+		   strsignal (i));
15e4b0
+	}
15e4b0
+    }
15e4b0
+
15e4b0
+  if (found_preinstalled)
15e4b0
+    {
15e4b0
+      fprintf (stderr, _("\
15e4b0
+Some signal dispositions inherited from the environment (SIG_DFL/SIG_IGN)\n\
15e4b0
+won't be propagated to spawned programs.\n"));
15e4b0
     }
15e4b0
 #endif
15e4b0
 }
15e4b0
--- a/gdb/common/signals-state-save-restore.h
15e4b0
+++ b/gdb/common/signals-state-save-restore.h
15e4b0
@@ -28,9 +28,10 @@
15e4b0
    back to what was originally inherited from gdb/gdbserver's parent,
15e4b0
    just before execing the target program to debug.  */
15e4b0
 
15e4b0
-/* Save the signal state of all signals.  */
15e4b0
+/* Save the signal state of all signals.  If !QUIET, warn if we detect
15e4b0
+   a custom signal handler preinstalled.  */
15e4b0
 
15e4b0
-extern void save_original_signals_state (void);
15e4b0
+extern void save_original_signals_state (bool quiet);
15e4b0
 
15e4b0
 /* Restore the signal state of all signals.  */
15e4b0
 
15e4b0
### a/gdb/gdbserver/ChangeLog
15e4b0
### b/gdb/gdbserver/ChangeLog
15e4b0
## -1,3 +1,9 @@
15e4b0
+2018-01-05  Pedro Alves  <palves@redhat.com>
15e4b0
+
15e4b0
+	PR gdb/18653
15e4b0
+	* server.c (captured_main): Pass quiet=false to
15e4b0
+	save_original_signals_state.
15e4b0
+
15e4b0
 2018-01-01  Joel Brobecker  <brobecker@adacore.com>
15e4b0
 
15e4b0
 	* gdbreplay.c (gdbreplay_version): Update copyright year in
15e4b0
--- a/gdb/gdbserver/server.c
15e4b0
+++ b/gdb/gdbserver/server.c
15e4b0
@@ -3712,7 +3712,7 @@ captured_main (int argc, char *argv[])
15e4b0
      opened by remote_prepare.  */
15e4b0
   notice_open_fds ();
15e4b0
 
15e4b0
-  save_original_signals_state ();
15e4b0
+  save_original_signals_state (false);
15e4b0
 
15e4b0
   /* We need to know whether the remote connection is stdio before
15e4b0
      starting the inferior.  Inferiors created in this scenario have
15e4b0
--- a/gdb/main.c
15e4b0
+++ b/gdb/main.c
15e4b0
@@ -506,7 +506,6 @@ captured_main_1 (struct captured_main_args *context)
15e4b0
 
15e4b0
   bfd_init ();
15e4b0
   notice_open_fds ();
15e4b0
-  save_original_signals_state ();
15e4b0
 
15e4b0
   saved_command_line = (char *) xstrdup ("");
15e4b0
 
15e4b0
@@ -849,6 +848,8 @@ captured_main_1 (struct captured_main_args *context)
15e4b0
       quiet = 1;
15e4b0
   }
15e4b0
 
15e4b0
+  save_original_signals_state (quiet);
15e4b0
+
15e4b0
   /* Try to set up an alternate signal stack for SIGSEGV handlers.  */
15e4b0
   setup_alternate_signal_stack ();
15e4b0
 
15e4b0
### a/gdb/testsuite/ChangeLog
15e4b0
### b/gdb/testsuite/ChangeLog
15e4b0
## -1,3 +1,8 @@
15e4b0
+2018-01-05  Pedro Alves  <palves@redhat.com>
15e4b0
+
15e4b0
+	PR gdb/18653
15e4b0
+	* gdb.base/libsegfault.exp: New.
15e4b0
+
15e4b0
 2018-01-05  Joel Brobecker  <brobecker@adacore.com>
15e4b0
 
15e4b0
 	PR gdb/22670
15e4b0
--- /dev/null
15e4b0
+++ b/gdb/testsuite/gdb.base/libsegfault.exp
15e4b0
@@ -0,0 +1,84 @@
15e4b0
+# Copyright 2017-2018 Free Software Foundation, Inc.
15e4b0
+
15e4b0
+# This program is free software; you can redistribute it and/or modify
15e4b0
+# it under the terms of the GNU General Public License as published by
15e4b0
+# the Free Software Foundation; either version 3 of the License, or
15e4b0
+# (at your option) any later version.
15e4b0
+#
15e4b0
+# This program is distributed in the hope that it will be useful,
15e4b0
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
15e4b0
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15e4b0
+# GNU General Public License for more details.
15e4b0
+#
15e4b0
+# You should have received a copy of the GNU General Public License
15e4b0
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
15e4b0
+
15e4b0
+# This file is part of the gdb testsuite.
15e4b0
+
15e4b0
+# Test that GDB tolerates being started with libSegFault.so preloaded
15e4b0
+# with LD_PRELOAD, and that GDB warns about a custom SIGSEGV custom
15e4b0
+# handler.  See PR gdb/18653
15e4b0
+# <https://sourceware.org/bugzilla/show_bug.cgi?id=18653#c7>.
15e4b0
+
15e4b0
+# We cannot expect remote hosts to see environment variables set on
15e4b0
+# the local machine.
15e4b0
+if { [is_remote host] } {
15e4b0
+    unsupported "can't set environment variables on remote host"
15e4b0
+    return -1
15e4b0
+}
15e4b0
+
15e4b0
+# Spawn GDB with LIB preloaded with LD_PRELOAD.  CMDLINE_OPTS are
15e4b0
+# command line options passed to GDB.
15e4b0
+
15e4b0
+proc gdb_spawn_with_ld_preload {lib cmdline_opts} {
15e4b0
+    global env
15e4b0
+
15e4b0
+    save_vars { env(LD_PRELOAD) } {
15e4b0
+	if { ![info exists env(LD_PRELOAD) ]
15e4b0
+	     || $env(LD_PRELOAD) == "" } {
15e4b0
+	    set env(LD_PRELOAD) "$lib"
15e4b0
+	} else {
15e4b0
+	    append env(LD_PRELOAD) ":$lib"
15e4b0
+	}
15e4b0
+
15e4b0
+	gdb_spawn_with_cmdline_opts $cmdline_opts
15e4b0
+    }
15e4b0
+}
15e4b0
+
15e4b0
+proc test_libsegfault {} {
15e4b0
+    global gdb_prompt
15e4b0
+
15e4b0
+    set libsegfault "libSegFault.so"
15e4b0
+
15e4b0
+    # When started normally, if libSegFault.so is preloaded, GDB
15e4b0
+    # should warn about not being able to propagate the signal
15e4b0
+    # disposition of SIGSEGV.
15e4b0
+    gdb_exit
15e4b0
+    gdb_spawn_with_ld_preload $libsegfault ""
15e4b0
+
15e4b0
+    set test "gdb emits custom handler warning"
15e4b0
+    gdb_test_multiple "" $test {
15e4b0
+	-re "cannot be preloaded.*\r\n$gdb_prompt $" {
15e4b0
+	    # Glibc 2.22 outputs:
15e4b0
+	    # ERROR: ld.so: object 'libSegFault.so' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
15e4b0
+	    untested "cannot preload libSegFault.so"
15e4b0
+	    return
15e4b0
+	}
15e4b0
+	-re "Found custom handler.*won't be propagated.*\r\n$gdb_prompt $" {
15e4b0
+	    pass $test
15e4b0
+	}
15e4b0
+    }
15e4b0
+
15e4b0
+    # "-q" should disable the warning, though.
15e4b0
+    gdb_exit
15e4b0
+    gdb_spawn_with_ld_preload $libsegfault "-q"
15e4b0
+
15e4b0
+    set test "quiet suppresses custom handler warning"
15e4b0
+    gdb_test_multiple "" $test {
15e4b0
+	-re "^$gdb_prompt $" {
15e4b0
+	    pass $test
15e4b0
+	}
15e4b0
+    }
15e4b0
+}
15e4b0
+
15e4b0
+test_libsegfault