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. */
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);
# 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"
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
# 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"
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).
-
-proc breakpoint_over_handler { cmd with_sw_watch no_handler } {
+# 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 { displaced cmd with_sw_watch no_handler } {
global infinite_loop
global clear_done
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"
}
}
-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
+ }
}
}
}