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

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