diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 83f9df63a0b..3de085afcf0 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2015-04-10 Pedro Alves + + * infrun.c (displaced_step_in_progress): New function. + (do_target_resume): Advise target to report all signals if + displaced stepping. + 2015-04-10 Pedro Alves PR gdb/18216 diff --git a/gdb/infrun.c b/gdb/infrun.c index 3fcc55f6af7..c7567c6b4c0 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -1465,6 +1465,20 @@ get_displaced_stepping_state (int pid) return NULL; } +/* Return true if process PID has a thread doing a displaced step. */ + +static int +displaced_step_in_progress (int pid) +{ + struct displaced_step_inferior_state *displaced; + + displaced = get_displaced_stepping_state (pid); + if (displaced != NULL && !ptid_equal (displaced->step_ptid, null_ptid)) + return 1; + + return 0; +} + /* Add a new displaced stepping state for process PID to the displaced stepping state list, or return a pointer to an already existing entry, if it already exists. Never returns NULL. */ @@ -2047,11 +2061,27 @@ do_target_resume (ptid_t resume_ptid, int step, enum gdb_signal sig) happens to apply to another thread. */ tp->suspend.stop_signal = GDB_SIGNAL_0; - /* Advise target which signals may be handled silently. If we have - removed breakpoints because we are stepping over one (in any - thread), we need to receive all signals to avoid accidentally - skipping a breakpoint during execution of a signal handler. */ - if (step_over_info_valid_p ()) + /* Advise target which signals may be handled silently. + + If we have removed breakpoints because we are stepping over one + in-line (in any thread), we need to receive all signals to avoid + accidentally skipping a breakpoint during execution of a signal + handler. + + Likewise if we're displaced stepping, otherwise a trap for a + breakpoint in a signal handler might be confused with the + displaced step finishing. We don't make the displaced_step_fixup + step distinguish the cases instead, because: + + - a backtrace while stopped in the signal handler would show the + scratch pad as frame older than the signal handler, instead of + the real mainline code. + + - when the thread is later resumed, the signal handler would + return to the scratch pad area, which would no longer be + valid. */ + if (step_over_info_valid_p () + || displaced_step_in_progress (ptid_get_pid (tp->ptid))) target_pass_signals (0, NULL); else target_pass_signals ((int) GDB_SIGNAL_LAST, signal_pass); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index c47c6ac100b..af6104a845b 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2015-04-10 Pedro Alves + + * gdb.base/sigstep.exp (breakpoint_to_handler) + (breakpoint_to_handler_entry): New parameter 'displaced'. Use it. + Test "backtrace" in handler. + (breakpoint_over_handler): New parameter 'displaced'. Use it. + (top level): Add new "displaced" test axis to + breakpoint_to_handler, breakpoint_to_handler_entry and + breakpoint_over_handler. + 2015-04-10 Pedro Alves PR gdb/18216 diff --git a/gdb/testsuite/gdb.base/sigstep.exp b/gdb/testsuite/gdb.base/sigstep.exp index c4f7e914174..3c9454c788a 100644 --- a/gdb/testsuite/gdb.base/sigstep.exp +++ b/gdb/testsuite/gdb.base/sigstep.exp @@ -409,13 +409,19 @@ foreach cmd {"stepi" "nexti" "step" "next" "continue"} { # Try stepping when there's a signal pending, a pre-existing # breakpoint at the current instruction, and a breakpoint in the -# handler. Should advance to the signal handler. +# handler. Should advance to the signal handler. DISPLACED indicates +# whether to try with or without displaced stepping (to exercise the +# different techniques of stepping over the breakpoint at the current +# instruction). -proc breakpoint_to_handler { cmd } { +proc breakpoint_to_handler { displaced cmd } { global infinite_loop - with_test_prefix "$cmd on breakpoint, to handler" { + with_test_prefix "displaced=$displaced: $cmd on breakpoint, to handler" { restart + + gdb_test_no_output "set displaced-stepping $displaced" + # Use the real-time itimer, as otherwize the process never gets # enough time to expire the timer. gdb_test_no_output "set itimer = itimer_real" @@ -430,11 +436,21 @@ proc breakpoint_to_handler { cmd } { sleep 1 gdb_test "$cmd" " handler .*" "performing $cmd" + + # Make sure we the displaced stepping scratch pad isn't in the + # backtrace. + gdb_test_sequence "bt" "backtrace" { + "\[\r\n\]+.0 \[^\r\n\]* handler " + "\[\r\n\]+.1 .signal handler called." + "\[\r\n\]+.2 \[^\r\n\]* main " + } } } -foreach cmd {"step" "next" "continue"} { - breakpoint_to_handler $cmd +foreach displaced {"off" "on"} { + foreach cmd {"step" "next" "continue"} { + breakpoint_to_handler $displaced $cmd + } } # Try stepping when there's a signal pending, and a breakpoint at the @@ -449,11 +465,17 @@ foreach cmd {"step" "next" "continue"} { # have been called by the trampoline code. This test checks that it # is possible to stop the inferior, even at that first instruction. -proc breakpoint_to_handler_entry { cmd } { +# DISPLACED indicates whether to try with or without displaced +# stepping (to exercise the different techniques of stepping over the +# breakpoint at the current instruction). +proc breakpoint_to_handler_entry { displaced cmd } { global infinite_loop - with_test_prefix "$cmd on breakpoint, to handler entry" { + with_test_prefix "displaced=$displaced: $cmd on breakpoint, to handler entry" { restart + + gdb_test_no_output "set displaced-stepping $displaced" + # Use the real-time itimer, as otherwize the process never gets # enough time to expire the timer. gdb_test_no_output "set itimer = itimer_real" @@ -468,24 +490,37 @@ proc breakpoint_to_handler_entry { cmd } { sleep 1 gdb_test "$cmd" " handler .*" "performing $cmd" + + # Make sure we the displaced stepping scratch pad isn't in the + # backtrace. + gdb_test_sequence "bt" "backtrace" { + "\[\r\n\]+.0 \[^\r\n\]* handler " + "\[\r\n\]+.1 .signal handler called." + "\[\r\n\]+.2 \[^\r\n\]* main " + } } } -foreach cmd {"step" "next" "continue"} { - breakpoint_to_handler_entry $cmd +foreach displaced {"off" "on"} { + foreach cmd {"step" "next" "continue"} { + breakpoint_to_handler_entry $displaced $cmd + } } # Try stepping when there's a signal pending, and a pre-existing # breakpoint at the current instruction, and no breakpoint in the -# handler. Should advance to the next line/instruction. If SW_WATCH -# is true, set a software watchpoint, which exercises stepping the -# breakpoint instruction while delivering a signal at the same time. -# If NO_HANDLER, arrange for the signal's handler be SIG_IGN, thus -# when the software watchpoint is also set, testing stepping a -# breakpoint instruction and immediately triggering the breakpoint -# (exercises adjust_pc_after_break logic). +# handler. Should advance to the next line/instruction. DISPLACED +# indicates whether to try with or without displaced stepping (to +# exercise the different techniques of stepping over the breakpoint at +# the current instruction). If SW_WATCH is true, set a software +# watchpoint, which exercises stepping the breakpoint instruction +# while delivering a signal at the same time. If NO_HANDLER, arrange +# for the signal's handler be SIG_IGN, thus when the software +# watchpoint is also set, testing stepping a breakpoint instruction +# and immediately triggering the breakpoint (exercises +# adjust_pc_after_break logic). -proc breakpoint_over_handler { cmd with_sw_watch no_handler } { +proc breakpoint_over_handler { displaced cmd with_sw_watch no_handler } { global infinite_loop global clear_done @@ -497,8 +532,11 @@ proc breakpoint_over_handler { cmd with_sw_watch no_handler } { append prefix ", no handler" } - with_test_prefix "$prefix" { + with_test_prefix "displaced=$displaced: $prefix" { restart + + gdb_test_no_output "set displaced-stepping $displaced" + # Use the real-time itimer, as otherwize the process never gets # enough time to expire the timer. gdb_test_no_output "set itimer = itimer_real" @@ -534,10 +572,12 @@ proc breakpoint_over_handler { cmd with_sw_watch no_handler } { } } -foreach cmd {"stepi" "nexti" "step" "next" "continue"} { - foreach with_sw_watch {0 1} { - foreach no_handler {0 1} { - breakpoint_over_handler $cmd $with_sw_watch $no_handler +foreach displaced {"off" "on"} { + foreach cmd {"stepi" "nexti" "step" "next" "continue"} { + foreach with_sw_watch {0 1} { + foreach no_handler {0 1} { + breakpoint_over_handler $displaced $cmd $with_sw_watch $no_handler + } } } }