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

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