diff options
author | Ulrich Weigand <uweigand@de.ibm.com> | 2007-09-10 18:49:26 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@de.ibm.com> | 2007-09-10 18:49:26 +0000 |
commit | 6a6b96b9c2552b97902d8ef1fbbce207328eef16 (patch) | |
tree | 7293363a7d8e9395abf2407b89014b05e5b45919 /gdb/infrun.c | |
parent | 548061812a687d9cd46a774c81d3ce82b26043a0 (diff) | |
download | gdb-6a6b96b9c2552b97902d8ef1fbbce207328eef16.zip gdb-6a6b96b9c2552b97902d8ef1fbbce207328eef16.tar.gz gdb-6a6b96b9c2552b97902d8ef1fbbce207328eef16.tar.bz2 |
* infrun.c (stepping_past_breakpoint): New global variable.
(stepping_past_breakpoint_ptid): Likewise.
(prepare_to_proceed): Add STEP parameter. Do not check for Ctrl-C.
Only switch threads if we need to single-step over a breakpoint hit
in the previously selected thread. If stepping, remember previous
thread to switch back to in STEPPING_PAST_BREAKPOINT[_PTID]. Call
switch_to_thread instead of copying its contents.
(proceed): Pass STEP to prepare_to_proceed. Always set ONEPROC if
prepare_to_proceed returns true.
(init_wait_for_inferior): Reset STEPPING_PAST_BREAKPOINT.
(context_switch): Call switch_to_thread.
(handle_inferior_event): Switch back to previous thread if requested
in STEPPING_PAST_BREAKPOINT[_PTID] by prepare_to_proceed.
* gdbthread.h (switch_to_thread): Add prototype.
* thread.c (switch_to_thread): Make global.
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r-- | gdb/infrun.c | 84 |
1 files changed, 57 insertions, 27 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c index 7026d08..a8297c9 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -78,7 +78,7 @@ static int currently_stepping (struct execution_control_state *ecs); static void xdb_handle_command (char *args, int from_tty); -static int prepare_to_proceed (void); +static int prepare_to_proceed (int); void _initialize_infrun (void); @@ -445,6 +445,11 @@ static CORE_ADDR singlestep_pc; thread here so that we can resume single-stepping it later. */ 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; /* Things to clean up if we QUIT out of resume (). */ @@ -642,7 +647,7 @@ clear_proceed_status (void) /* This should be suitable for any targets that support threads. */ static int -prepare_to_proceed (void) +prepare_to_proceed (int step) { ptid_t wait_ptid; struct target_waitstatus wait_status; @@ -650,42 +655,35 @@ prepare_to_proceed (void) /* Get the last target status returned by target_wait(). */ get_last_target_status (&wait_ptid, &wait_status); - /* Make sure we were stopped either at a breakpoint, or because - of a Ctrl-C. */ + /* Make sure we were stopped at a breakpoint. */ if (wait_status.kind != TARGET_WAITKIND_STOPPED - || (wait_status.value.sig != TARGET_SIGNAL_TRAP - && wait_status.value.sig != TARGET_SIGNAL_INT)) + || wait_status.value.sig != TARGET_SIGNAL_TRAP) { return 0; } + /* Switched over from WAIT_PID. */ if (!ptid_equal (wait_ptid, minus_one_ptid) - && !ptid_equal (inferior_ptid, wait_ptid)) + && !ptid_equal (inferior_ptid, wait_ptid) + && breakpoint_here_p (read_pc_pid (wait_ptid))) { - /* Switched over from WAIT_PID. */ - CORE_ADDR wait_pc = read_pc_pid (wait_ptid); - - if (wait_pc != read_pc ()) + /* If stepping, remember current thread to switch back to. */ + if (step) { - /* Switch back to WAIT_PID thread. */ - inferior_ptid = wait_ptid; - - /* FIXME: This stuff came from switch_to_thread() in - thread.c (which should probably be a public function). */ - reinit_frame_cache (); - registers_changed (); - stop_pc = wait_pc; + stepping_past_breakpoint = 1; + stepping_past_breakpoint_ptid = inferior_ptid; } + /* Switch back to WAIT_PID thread. */ + switch_to_thread (wait_ptid); + /* We return 1 to indicate that there is a breakpoint here, - so we need to step over it before continuing to avoid - hitting it straight away. */ - if (breakpoint_here_p (wait_pc)) - return 1; + so we need to step over it before continuing to avoid + hitting it straight away. */ + return 1; } return 0; - } /* Record the pc of the program the last time it stopped. This is @@ -751,7 +749,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step) prepare_to_proceed checks the current thread against the thread that reported the most recent event. If a step-over is required it returns TRUE and sets the current thread to the old thread. */ - if (prepare_to_proceed () && breakpoint_here_p (read_pc ())) + if (prepare_to_proceed (step)) oneproc = 1; if (oneproc) @@ -872,6 +870,7 @@ init_wait_for_inferior (void) clear_proceed_status (); stepping_past_singlestep_breakpoint = 0; + stepping_past_breakpoint = 0; } /* This enum encodes possible reasons for doing a target_wait, so that @@ -1141,8 +1140,8 @@ context_switch (struct execution_control_state *ecs) &ecs->stepping_through_solib_catchpoints, &ecs->current_line, &ecs->current_symtab); } - inferior_ptid = ecs->ptid; - reinit_frame_cache (); + + switch_to_thread (ecs->ptid); } static void @@ -1604,6 +1603,37 @@ handle_inferior_event (struct execution_control_state *ecs) stepping_past_singlestep_breakpoint = 0; + if (stepping_past_breakpoint) + { + 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"); + + /* Pull the single step breakpoints out of the target. */ + if (singlestep_breakpoints_inserted_p) + { + remove_single_step_breakpoints (); + singlestep_breakpoints_inserted_p = 0; + } + + /* 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); + /* Suppress spurious "Switching to ..." message. */ + previous_inferior_ptid = inferior_ptid; + + resume (1, TARGET_SIGNAL_0); + prepare_to_wait (ecs); + return; + } + } + /* See if a thread hit a thread-specific breakpoint that was meant for another thread. If so, then step that thread past the breakpoint, and continue it. */ |