aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2007-09-10 18:49:26 +0000
committerUlrich Weigand <uweigand@de.ibm.com>2007-09-10 18:49:26 +0000
commit6a6b96b9c2552b97902d8ef1fbbce207328eef16 (patch)
tree7293363a7d8e9395abf2407b89014b05e5b45919 /gdb
parent548061812a687d9cd46a774c81d3ce82b26043a0 (diff)
downloadgdb-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')
-rw-r--r--gdb/ChangeLog18
-rw-r--r--gdb/gdbthread.h3
-rw-r--r--gdb/infrun.c84
-rw-r--r--gdb/thread.c3
4 files changed, 79 insertions, 29 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e3c9a81..5ea94cc 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,21 @@
+2007-09-10 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * 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 <muller@ics.u-strasbg.fr>
* p-valprint.c: Fix 7 ARI reported problems.
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index d378033..aeb4a40 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 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. */
diff --git a/gdb/thread.c b/gdb/thread.c
index 8853e91..563d18a 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))