From: Ulrich Weigand Date: Mon, 10 Sep 2007 18:49:26 +0000 (+0000) Subject: * infrun.c (stepping_past_breakpoint): New global variable. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6a6b96b9c2552b97902d8ef1fbbce207328eef16;p=binutils-gdb.git * 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e3c9a81d9b5..5ea94cc5a07 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,21 @@ +2007-09-10 Ulrich Weigand + + * 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. + 2007-09-07 2007-09-07 Pierre Muller * p-valprint.c: Fix 7 ARI reported problems. diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h index d37803368a8..aeb4a408ff2 100644 --- a/gdb/gdbthread.h +++ b/gdb/gdbthread.h @@ -135,6 +135,9 @@ extern void load_infrun_state (ptid_t ptid, int *current_line, struct symtab **current_symtab); +/* Switch from one thread to another. */ +extern void switch_to_thread (ptid_t ptid); + /* Commands with a prefix of `thread'. */ extern struct cmd_list_element *thread_cmd_list; diff --git a/gdb/infrun.c b/gdb/infrun.c index 7026d08cf43..a8297c95ebf 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. */ diff --git a/gdb/thread.c b/gdb/thread.c index 8853e9105b1..563d18a8afa 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -59,7 +59,6 @@ static int thread_alive (struct thread_info *); static void info_threads_command (char *, int); static void thread_apply_command (char *, int); static void restore_current_thread (ptid_t); -static void switch_to_thread (ptid_t ptid); static void prune_threads (void); static struct cleanup *make_cleanup_restore_current_thread (ptid_t, struct frame_id); @@ -452,7 +451,7 @@ info_threads_command (char *arg, int from_tty) /* Switch from one thread to another. */ -static void +void switch_to_thread (ptid_t ptid) { if (ptid_equal (ptid, inferior_ptid))