From 9f976b41d7cc6d186b6ceda2658feee5016d3348 Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Mon, 16 Feb 2004 20:49:51 +0000 Subject: [PATCH] * Makefile.in (infrun.o): Add $(gdb_assert_h). * infrun.c: Include "gdb_assert.h". (singlestep_ptid, saved_singlestep_ptid) (stepping_past_singlestep_breakpoint): New variables. (resume): Set singlestep_ptid. Check for singlestep thread hop. (init_wait_for_inferior): Clear stepping_past_singlestep_breakpoint. (handle_inferior_event): Handle singlestep thread hop. --- gdb/ChangeLog | 11 +++++++++ gdb/Makefile.in | 2 +- gdb/infrun.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 86 insertions(+), 3 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c7d69d9..e3479dc 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2004-02-16 Daniel Jacobowitz + + * Makefile.in (infrun.o): Add $(gdb_assert_h). + * infrun.c: Include "gdb_assert.h". + (singlestep_ptid, saved_singlestep_ptid) + (stepping_past_singlestep_breakpoint): New variables. + (resume): Set singlestep_ptid. Check for singlestep thread + hop. + (init_wait_for_inferior): Clear stepping_past_singlestep_breakpoint. + (handle_inferior_event): Handle singlestep thread hop. + 2004-02-16 Andrew Cagney * dwarf2-frame.c (dwarf2_frame_ops): New function. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index c658895..f6d33ca 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1851,7 +1851,7 @@ infrun.o: infrun.c $(defs_h) $(gdb_string_h) $(symtab_h) $(frame_h) \ $(inferior_h) $(breakpoint_h) $(gdb_wait_h) $(gdbcore_h) $(gdbcmd_h) \ $(cli_script_h) $(target_h) $(gdbthread_h) $(annotate_h) \ $(symfile_h) $(top_h) $(inf_loop_h) $(regcache_h) $(value_h) \ - $(observer_h) $(language_h) + $(observer_h) $(language_h) $(gdb_assert_h) inftarg.o: inftarg.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) \ $(gdbcore_h) $(command_h) $(gdb_stat_h) $(gdb_wait_h) $(inflow_h) infttrace.o: infttrace.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) \ diff --git a/gdb/infrun.c b/gdb/infrun.c index 3d41f42..6bbee5e 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -44,6 +44,7 @@ #include "value.h" #include "observer.h" #include "language.h" +#include "gdb_assert.h" /* Prototypes for local functions */ @@ -474,6 +475,14 @@ follow_exec (int pid, char *execd_pathname) because we cannot remove the breakpoints in the inferior process until after the `wait' in `wait_for_inferior'. */ static int singlestep_breakpoints_inserted_p = 0; + +/* The thread we inserted single-step breakpoints for. */ +static ptid_t singlestep_ptid; + +/* If another thread hit the singlestep breakpoint, we save the original + thread here so that we can resume single-stepping it later. */ +static ptid_t saved_singlestep_ptid; +static int stepping_past_singlestep_breakpoint; /* Things to clean up if we QUIT out of resume (). */ @@ -560,6 +569,7 @@ resume (int step, enum target_signal sig) /* and do not pull these breakpoints until after a `wait' in `wait_for_inferior' */ singlestep_breakpoints_inserted_p = 1; + singlestep_ptid = inferior_ptid; } /* Handle any optimized stores to the inferior NOW... */ @@ -597,7 +607,8 @@ resume (int step, enum target_signal sig) resume_ptid = RESUME_ALL; /* Default */ if ((step || singlestep_breakpoints_inserted_p) && - !breakpoints_inserted && breakpoint_here_p (read_pc ())) + (stepping_past_singlestep_breakpoint + || (!breakpoints_inserted && breakpoint_here_p (read_pc ())))) { /* Stepping past a breakpoint without inserting breakpoints. Make sure only the current thread gets to step, so that @@ -896,6 +907,8 @@ init_wait_for_inferior (void) number_of_threads_in_syscalls = 0; clear_proceed_status (); + + stepping_past_singlestep_breakpoint = 0; } static void @@ -1739,12 +1752,46 @@ handle_inferior_event (struct execution_control_state *ecs) stop_pc = read_pc_pid (ecs->ptid); + if (stepping_past_singlestep_breakpoint) + { + gdb_assert (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p); + gdb_assert (ptid_equal (singlestep_ptid, ecs->ptid)); + gdb_assert (!ptid_equal (singlestep_ptid, saved_singlestep_ptid)); + + stepping_past_singlestep_breakpoint = 0; + + /* We've either finished single-stepping past the single-step + breakpoint, or stopped for some other reason. It would be nice if + we could tell, but we can't reliably. */ + if (stop_signal == TARGET_SIGNAL_TRAP) + { + /* Pull the single step breakpoints out of the target. */ + SOFTWARE_SINGLE_STEP (0, 0); + singlestep_breakpoints_inserted_p = 0; + + ecs->random_signal = 0; + + ecs->ptid = saved_singlestep_ptid; + context_switch (ecs); + if (context_hook) + context_hook (pid_to_thread_id (ecs->ptid)); + + resume (1, TARGET_SIGNAL_0); + prepare_to_wait (ecs); + return; + } + } + + stepping_past_singlestep_breakpoint = 0; + /* 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. */ if (stop_signal == TARGET_SIGNAL_TRAP) { + int thread_hop_needed = 0; + /* Check if a regular breakpoint has been hit before checking for a potential single step breakpoint. Otherwise, GDB will not see this breakpoint hit when stepping onto breakpoints. */ @@ -1752,12 +1799,38 @@ handle_inferior_event (struct execution_control_state *ecs) { ecs->random_signal = 0; if (!breakpoint_thread_match (stop_pc, ecs->ptid)) + thread_hop_needed = 1; + } + else if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p) + { + ecs->random_signal = 0; + /* The call to in_thread_list is necessary because PTIDs sometimes + change when we go from single-threaded to multi-threaded. If + the singlestep_ptid is still in the list, assume that it is + really different from ecs->ptid. */ + if (!ptid_equal (singlestep_ptid, ecs->ptid) + && in_thread_list (singlestep_ptid)) + { + thread_hop_needed = 1; + stepping_past_singlestep_breakpoint = 1; + saved_singlestep_ptid = singlestep_ptid; + } + } + + if (thread_hop_needed) { int remove_status; /* Saw a breakpoint, but it was hit by the wrong thread. Just continue. */ + if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p) + { + /* Pull the single step breakpoints out of the target. */ + SOFTWARE_SINGLE_STEP (0, 0); + singlestep_breakpoints_inserted_p = 0; + } + remove_status = remove_breakpoints (); /* Did we fail to remove breakpoints? If so, try to set the PC past the bp. (There's at least @@ -1799,7 +1872,6 @@ handle_inferior_event (struct execution_control_state *ecs) registers_changed (); return; } - } } else if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p) { -- 2.7.4