diff --git a/gdb/infrun.c b/gdb/infrun.c index 043d8f1..77623b6 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -463,10 +463,14 @@ static CORE_ADDR singlestep_pc; static ptid_t saved_singlestep_ptid; static int stepping_past_singlestep_breakpoint; -/* Similarly, if we are stepping another thread past a breakpoint, - save the original thread here so that we can resume stepping it later. */ -static ptid_t stepping_past_breakpoint_ptid; -static int stepping_past_breakpoint; +/* If not equal to null_ptid, means that after stepping over breakpoint + is finished, we need to switch to deferred_step_ptid, and step it. + + The use case is when a breakpoint in one thread, and then the user + has switched to another thread and issued 'step'. We need to step over + breakpoint in the thread which hit breakpoint, but then continue + stepping the thread user has selected. */ +static ptid_t deferred_step_ptid; /* Things to clean up if we QUIT out of resume (). */ @@ -714,8 +718,7 @@ prepare_to_proceed (int step) /* If stepping, remember current thread to switch back to. */ if (step) { - stepping_past_breakpoint = 1; - stepping_past_breakpoint_ptid = inferior_ptid; + deferred_step_ptid = inferior_ptid; } /* Switch back to WAIT_PID thread. */ @@ -908,7 +911,7 @@ init_wait_for_inferior (void) clear_proceed_status (); stepping_past_singlestep_breakpoint = 0; - stepping_past_breakpoint = 0; + deferred_step_ptid = null_ptid; } /* This enum encodes possible reasons for doing a target_wait, so that @@ -1643,17 +1646,15 @@ handle_inferior_event (struct execution_control_state *ecs) stepping_past_singlestep_breakpoint = 0; - if (stepping_past_breakpoint) + if (!ptid_equal (deferred_step_ptid, null_ptid)) { - stepping_past_breakpoint = 0; - /* If we stopped for some other reason than single-stepping, ignore the fact that we were supposed to switch back. */ if (stop_signal == TARGET_SIGNAL_TRAP) { if (debug_infrun) fprintf_unfiltered (gdb_stdlog, - "infrun: stepping_past_breakpoint\n"); + "infrun: handling deferred step\n"); /* Pull the single step breakpoints out of the target. */ if (singlestep_breakpoints_inserted_p) @@ -1664,7 +1665,8 @@ handle_inferior_event (struct execution_control_state *ecs) /* Note: We do not call context_switch at this point, as the context is already set up for stepping the original thread. */ - switch_to_thread (stepping_past_breakpoint_ptid); + switch_to_thread (deferred_step_ptid); + deferred_step_ptid = null_ptid; /* Suppress spurious "Switching to ..." message. */ previous_inferior_ptid = inferior_ptid; @@ -1672,6 +1674,8 @@ handle_inferior_event (struct execution_control_state *ecs) prepare_to_wait (ecs); return; } + + deferred_step_ptid = null_ptid; } /* See if a thread hit a thread-specific breakpoint that was meant for