diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5c5b75a72e..303bb96d00 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2015-02-19 Antoine Tremblay + + PR breakpoints/16812 + * linux-nat.c (linux_nat_filter_event): Report SIGTRAP,SIGILL,SIGSEGV. + * nat/linux-ptrace.c (linux_wstatus_maybe_breakpoint): Add. + * nat/linux-ptrace.h: Add linux_wstatus_maybe_breakpoint. + 2015-02-19 David Taylor * common/ax.def (setv): Fix consumed entry in setv DEFOP. diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 4badd9e796..06848e089c 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,10 @@ +2015-02-19 Antoine Tremblay + + PR breakpoints/16812 + * linux-low.c (wstatus_maybe_breakpoint): Remove. + (linux_low_filter_event): Update wstatus_maybe_breakpoint name. + (linux_wait_1): Report SIGTRAP,SIGILL,SIGSEGV. + 2015-02-10 Antoine Tremblay PR breakpoints/15956 diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index eff940de10..1869857d59 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -1738,19 +1738,6 @@ dequeue_one_deferred_signal (struct lwp_info *lwp, int *wstat) return 0; } -/* Return true if the event in LP may be caused by breakpoint. */ - -static int -wstatus_maybe_breakpoint (int wstatus) -{ - return (WIFSTOPPED (wstatus) - && (WSTOPSIG (wstatus) == SIGTRAP - /* SIGILL and SIGSEGV are also treated as traps in case a - breakpoint is inserted at the current PC. */ - || WSTOPSIG (wstatus) == SIGILL - || WSTOPSIG (wstatus) == SIGSEGV)); -} - /* Fetch the possibly triggered data watchpoint info and store it in CHILD. @@ -1898,7 +1885,7 @@ linux_low_filter_event (int lwpid, int wstat) if (WIFSTOPPED (wstat) && WSTOPSIG (wstat) == SIGTRAP && check_stopped_by_watchpoint (child)) ; - else if (WIFSTOPPED (wstat) && wstatus_maybe_breakpoint (wstat)) + else if (WIFSTOPPED (wstat) && linux_wstatus_maybe_breakpoint (wstat)) { if (check_stopped_by_breakpoint (child)) have_stop_pc = 1; @@ -2739,7 +2726,8 @@ linux_wait_1 (ptid_t ptid, any that GDB specifically requested we ignore. But never ignore SIGSTOP if we sent it ourselves, and do not ignore signals when stepping - they may require special handling to skip the signal - handler. */ + handler. Also never ignore signals that could be caused by a + breakpoint. */ /* FIXME drow/2002-06-09: Get signal numbers from the inferior's thread library? */ if (WIFSTOPPED (w) @@ -2753,7 +2741,8 @@ linux_wait_1 (ptid_t ptid, #endif (pass_signals[gdb_signal_from_host (WSTOPSIG (w))] && !(WSTOPSIG (w) == SIGSTOP - && current_thread->last_resume_kind == resume_stop)))) + && current_thread->last_resume_kind == resume_stop) + && !linux_wstatus_maybe_breakpoint (w)))) { siginfo_t info, *info_p; diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 169188ac54..ed007bde36 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -3070,9 +3070,11 @@ linux_nat_filter_event (int lwpid, int status) } /* When using hardware single-step, we need to report every signal. - Otherwise, signals in pass_mask may be short-circuited. */ + Otherwise, signals in pass_mask may be short-circuited + except signals that might be caused by a breakpoint. */ if (!lp->step - && WSTOPSIG (status) && sigismember (&pass_mask, WSTOPSIG (status))) + && WSTOPSIG (status) && sigismember (&pass_mask, WSTOPSIG (status)) + && !linux_wstatus_maybe_breakpoint (status)) { linux_resume_one_lwp (lp, lp->step, signo); if (debug_linux_nat) diff --git a/gdb/nat/linux-ptrace.c b/gdb/nat/linux-ptrace.c index 0ce258f369..1c67819574 100644 --- a/gdb/nat/linux-ptrace.c +++ b/gdb/nat/linux-ptrace.c @@ -621,3 +621,16 @@ linux_is_extended_waitstatus (int wstat) { return (linux_ptrace_get_extended_event (wstat) != 0); } + +/* Return true if the event in LP may be caused by breakpoint. */ + +int +linux_wstatus_maybe_breakpoint (int wstat) +{ + return (WIFSTOPPED (wstat) + && (WSTOPSIG (wstat) == SIGTRAP + /* SIGILL and SIGSEGV are also treated as traps in case a + breakpoint is inserted at the current PC. */ + || WSTOPSIG (wstat) == SIGILL + || WSTOPSIG (wstat) == SIGSEGV)); +} diff --git a/gdb/nat/linux-ptrace.h b/gdb/nat/linux-ptrace.h index 137b61a551..c5b0f14581 100644 --- a/gdb/nat/linux-ptrace.h +++ b/gdb/nat/linux-ptrace.h @@ -107,5 +107,6 @@ extern int linux_supports_tracesysgood (void); extern void linux_ptrace_set_additional_flags (int); extern int linux_ptrace_get_extended_event (int wstat); extern int linux_is_extended_waitstatus (int wstat); +extern int linux_wstatus_maybe_breakpoint (int wstat); #endif /* COMMON_LINUX_PTRACE_H */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 2fae0808b0..a7f876e675 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2015-02-19 Antoine Tremblay + + PR breakpoints/16812 + * gdb.base/catch-gdb-caused-signals.c: New file. + * gdb.base/catch-gdb-caused-signals.exp: New file. + 2015-02-18 Jose E. Marchesi * configure: Regenerated. diff --git a/gdb/testsuite/gdb.base/catch-gdb-caused-signals.c b/gdb/testsuite/gdb.base/catch-gdb-caused-signals.c new file mode 100644 index 0000000000..769858c81a --- /dev/null +++ b/gdb/testsuite/gdb.base/catch-gdb-caused-signals.c @@ -0,0 +1,36 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2015 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 . */ + +/* This program is intended to be a simple dummy program for gdb to read. */ + +#include +#include + +int +main (void) +{ + int i = 0; + + i++; /* set dprintf here */ + return 0; /* set breakpoint here */ +} + +int +return_one (void) +{ + return 1; +} diff --git a/gdb/testsuite/gdb.base/catch-gdb-caused-signals.exp b/gdb/testsuite/gdb.base/catch-gdb-caused-signals.exp new file mode 100644 index 0000000000..8ba3be5499 --- /dev/null +++ b/gdb/testsuite/gdb.base/catch-gdb-caused-signals.exp @@ -0,0 +1,63 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2015 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 . + +# Test that checks if we handle a SIGSEGV,SIGILL caused by gdb in the inferior +# even if we have noprint,nostop options set in handle SIGSEV,SIGILL +# See PR breakpoints/16812 + +standard_testfile + +# Some targets can't call functions, so don't even bother with this +# test. +if [target_info exists gdb,cannot_call_functions] { + unsupported "cannot call functions" + return +} + +set dp_location [gdb_get_line_number "set dprintf here"] +set bp_location [gdb_get_line_number "set breakpoint here"] + +if {[prepare_for_testing $testfile.exp $testfile $srcfile debug]} { + return -1 +} + +if ![runto_main] { + fail "Can't run to main to make the tests" + return -1 +} + +gdb_test "handle SIGSEGV nostop noprint" \ + "Signal\[ \t\]+Stop\[ \t\]+Print\[ \t\]+Pass to program\[ \t\]+Description\r\nSIGSEGV\[ \t\]+No\[ \t\]+No\[ \t\]+Yes\[ \t\].*" +gdb_test "handle SIGILL nostop noprint" \ + "Signal\[ \t\]+Stop\[ \t\]+Print\[ \t\]+Pass to program\[ \t\]+Description\r\nSIGILL\[ \t\]+No\[ \t\]+No\[ \t\]+Yes\[ \t\].*" + +gdb_test "print return_one()" " = 1" + +if ![target_info exists gdb,noinferiorio] { + + # Clean up the breakpoint state. + delete_breakpoints + + gdb_breakpoint $bp_location + + gdb_test_no_output "set dprintf-style call" + + # Also test with dprintf since the original bug was noticed using dprintf. + gdb_test "dprintf $dp_location,\"testdprintf\\n\"" "Dprintf .*" + + gdb_test "continue" "testdprintf.*" +}