Skip to content

Commit 1ec6a11

Browse files
committed
Fix regression: cannot start with LD_PRELOAD=libSegFault.so (PR gdb/18653#c7)
At https://sourceware.org/bugzilla/show_bug.cgi?id=18653#c7, Andrew reports that the fix for PR gdb/18653 made GDB useless if you preload libSegFault.so, because GDB internal-errors on startup: $ LD_PRELOAD=libSegFault.so gdb src/gdb/common/signals-state-save-restore.c:64: internal-error: unexpected signal handler A problem internal to GDB has been detected, further debugging may prove unreliable. Aborted (core dumped) $ The internal error comes from the code saving the signal dispositions inherited from gdb's parent: (top-gdb) bt #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 #1 0x00000000005752c9 in save_original_signals_state() () at src/gdb/common/signals-state-save-restore.c:64 #2 0x00000000007425de in captured_main_1(captured_main_args*) (context=0x7fffffffd860) at src/gdb/main.c:509 #3 0x0000000000743622 in captured_main(void*) (data=0x7fffffffd860) at src/gdb/main.c:1145 During symbol reading, cannot get low and high bounds for subprogram DIE at 24065. #4 0x00000000007436f9 in gdb_main(captured_main_args*) (args=0x7fffffffd860) at src/gdb/main.c:1171 #5 0x0000000000413acd in main(int, char**) (argc=1, argv=0x7fffffffd968) at src/gdb/gdb.c:32 This commit downgrades the internal error to a warning. You'll get instead: ~~~ $ LD_PRELOAD=libSegFault.so gdb warning: Found custom handler for signal 11 (Segmentation fault) preinstalled. Some signal dispositions inherited from the environment (SIG_DFL/SIG_IGN) won't be propagated to spawned programs. GNU gdb (GDB) 8.0.50.20171213-git Copyright (C) 2017 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-pc-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... (gdb) ~~~ This also moves the location where save_original_signals_state is called a bit further below (to after option processing), so that "-q" disables the warning: ~~~ $ LD_PRELOAD=libSegFault.so gdb -q (gdb) ~~~ New testcase included. gdb/ChangeLog: 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. gdb/gdbserver/ChangeLog: 2018-01-05 Pedro Alves <palves@redhat.com> PR gdb/18653 * server.c (captured_main): Pass quiet=false to save_original_signals_state. gdb/testsuite/ChangeLog: 2018-01-05 Pedro Alves <palves@redhat.com> PR gdb/18653 * gdb.base/libsegfault.exp: New.
1 parent 1dc9069 commit 1ec6a11

File tree

8 files changed

+141
-8
lines changed

8 files changed

+141
-8
lines changed

gdb/ChangeLog

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
2018-01-05 Pedro Alves <palves@redhat.com>
2+
3+
PR gdb/18653
4+
* common/signals-state-save-restore.c
5+
(save_original_signals_state): New parameter 'quiet'. Warn if we
6+
find a custom handler preinstalled, instead of internal erroring.
7+
But only warn if !quiet.
8+
* common/signals-state-save-restore.h
9+
(save_original_signals_state): New parameter 'quiet'.
10+
* main.c (captured_main_1): Move save_original_signals_state call
11+
after option handling, and pass QUIET.
12+
113
2018-01-05 Pedro Alves <palves@redhat.com>
214

315
* spu-tdep.c (spu_catch_start): Pass

gdb/common/signals-state-save-restore.c

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ static sigset_t original_signal_mask;
3535
/* See signals-state-save-restore.h. */
3636

3737
void
38-
save_original_signals_state (void)
38+
save_original_signals_state (bool quiet)
3939
{
4040
#ifdef HAVE_SIGACTION
4141
int i;
@@ -45,6 +45,8 @@ save_original_signals_state (void)
4545
if (res == -1)
4646
perror_with_name (("sigprocmask"));
4747

48+
bool found_preinstalled = false;
49+
4850
for (i = 1; i < NSIG; i++)
4951
{
5052
struct sigaction *oldact = &original_signal_actions[i];
@@ -59,9 +61,31 @@ save_original_signals_state (void)
5961
perror_with_name (("sigaction"));
6062

6163
/* If we find a custom signal handler already installed, then
62-
this function was called too late. */
63-
if (oldact->sa_handler != SIG_DFL && oldact->sa_handler != SIG_IGN)
64-
internal_error (__FILE__, __LINE__, _("unexpected signal handler"));
64+
this function was called too late. This is a warning instead
65+
of an internal error because this can also happen if you
66+
LD_PRELOAD a library that installs a signal handler early via
67+
__attribute__((constructor)), like libSegFault.so. */
68+
if (!quiet
69+
&& oldact->sa_handler != SIG_DFL
70+
&& oldact->sa_handler != SIG_IGN)
71+
{
72+
found_preinstalled = true;
73+
74+
/* Use raw fprintf here because we're being called in early
75+
startup, because GDB's filtered streams are are
76+
created. */
77+
fprintf (stderr,
78+
_("warning: Found custom handler for signal "
79+
"%d (%s) preinstalled.\n"), i,
80+
strsignal (i));
81+
}
82+
}
83+
84+
if (found_preinstalled)
85+
{
86+
fprintf (stderr, _("\
87+
Some signal dispositions inherited from the environment (SIG_DFL/SIG_IGN)\n\
88+
won't be propagated to spawned programs.\n"));
6589
}
6690
#endif
6791
}

gdb/common/signals-state-save-restore.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@
2828
back to what was originally inherited from gdb/gdbserver's parent,
2929
just before execing the target program to debug. */
3030

31-
/* Save the signal state of all signals. */
31+
/* Save the signal state of all signals. If !QUIET, warn if we detect
32+
a custom signal handler preinstalled. */
3233

33-
extern void save_original_signals_state (void);
34+
extern void save_original_signals_state (bool quiet);
3435

3536
/* Restore the signal state of all signals. */
3637

gdb/gdbserver/ChangeLog

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
2018-01-05 Pedro Alves <palves@redhat.com>
2+
3+
PR gdb/18653
4+
* server.c (captured_main): Pass quiet=false to
5+
save_original_signals_state.
6+
17
2018-01-01 Joel Brobecker <brobecker@adacore.com>
28

39
* gdbreplay.c (gdbreplay_version): Update copyright year in

gdb/gdbserver/server.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3712,7 +3712,7 @@ captured_main (int argc, char *argv[])
37123712
opened by remote_prepare. */
37133713
notice_open_fds ();
37143714

3715-
save_original_signals_state ();
3715+
save_original_signals_state (false);
37163716

37173717
/* We need to know whether the remote connection is stdio before
37183718
starting the inferior. Inferiors created in this scenario have

gdb/main.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,6 @@ captured_main_1 (struct captured_main_args *context)
506506

507507
bfd_init ();
508508
notice_open_fds ();
509-
save_original_signals_state ();
510509

511510
saved_command_line = (char *) xstrdup ("");
512511

@@ -849,6 +848,8 @@ captured_main_1 (struct captured_main_args *context)
849848
quiet = 1;
850849
}
851850

851+
save_original_signals_state (quiet);
852+
852853
/* Try to set up an alternate signal stack for SIGSEGV handlers. */
853854
setup_alternate_signal_stack ();
854855

gdb/testsuite/ChangeLog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2018-01-05 Pedro Alves <palves@redhat.com>
2+
3+
PR gdb/18653
4+
* gdb.base/libsegfault.exp: New.
5+
16
2018-01-05 Joel Brobecker <brobecker@adacore.com>
27

38
PR gdb/22670
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Copyright 2017-2018 Free Software Foundation, Inc.
2+
3+
# This program is free software; you can redistribute it and/or modify
4+
# it under the terms of the GNU General Public License as published by
5+
# the Free Software Foundation; either version 3 of the License, or
6+
# (at your option) any later version.
7+
#
8+
# This program is distributed in the hope that it will be useful,
9+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
# GNU General Public License for more details.
12+
#
13+
# You should have received a copy of the GNU General Public License
14+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
16+
# This file is part of the gdb testsuite.
17+
18+
# Test that GDB tolerates being started with libSegFault.so preloaded
19+
# with LD_PRELOAD, and that GDB warns about a custom SIGSEGV custom
20+
# handler. See PR gdb/18653
21+
# <https://sourceware.org/bugzilla/show_bug.cgi?id=18653#c7>.
22+
23+
# We cannot expect remote hosts to see environment variables set on
24+
# the local machine.
25+
if { [is_remote host] } {
26+
unsupported "can't set environment variables on remote host"
27+
return -1
28+
}
29+
30+
# Spawn GDB with LIB preloaded with LD_PRELOAD. CMDLINE_OPTS are
31+
# command line options passed to GDB.
32+
33+
proc gdb_spawn_with_ld_preload {lib cmdline_opts} {
34+
global env
35+
36+
save_vars { env(LD_PRELOAD) } {
37+
if { ![info exists env(LD_PRELOAD) ]
38+
|| $env(LD_PRELOAD) == "" } {
39+
set env(LD_PRELOAD) "$lib"
40+
} else {
41+
append env(LD_PRELOAD) ":$lib"
42+
}
43+
44+
gdb_spawn_with_cmdline_opts $cmdline_opts
45+
}
46+
}
47+
48+
proc test_libsegfault {} {
49+
global gdb_prompt
50+
51+
set libsegfault "libSegFault.so"
52+
53+
# When started normally, if libSegFault.so is preloaded, GDB
54+
# should warn about not being able to propagate the signal
55+
# disposition of SIGSEGV.
56+
gdb_exit
57+
gdb_spawn_with_ld_preload $libsegfault ""
58+
59+
set test "gdb emits custom handler warning"
60+
gdb_test_multiple "" $test {
61+
-re "cannot be preloaded.*\r\n$gdb_prompt $" {
62+
# Glibc 2.22 outputs:
63+
# ERROR: ld.so: object 'libSegFault.so' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
64+
untested "cannot preload libSegFault.so"
65+
return
66+
}
67+
-re "Found custom handler.*won't be propagated.*\r\n$gdb_prompt $" {
68+
pass $test
69+
}
70+
}
71+
72+
# "-q" should disable the warning, though.
73+
gdb_exit
74+
gdb_spawn_with_ld_preload $libsegfault "-q"
75+
76+
set test "quiet suppresses custom handler warning"
77+
gdb_test_multiple "" $test {
78+
-re "^$gdb_prompt $" {
79+
pass $test
80+
}
81+
}
82+
}
83+
84+
test_libsegfault

0 commit comments

Comments
 (0)