* 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.
This commit is contained in:
Daniel Jacobowitz 2004-02-16 20:49:51 +00:00
parent f090b9b105
commit 9f976b41d7
3 changed files with 86 additions and 3 deletions

View File

@ -1,3 +1,14 @@
2004-02-16 Daniel Jacobowitz <drow@mvista.com>
* 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 <cagney@redhat.com> 2004-02-16 Andrew Cagney <cagney@redhat.com>
* dwarf2-frame.c (dwarf2_frame_ops): New function. * dwarf2-frame.c (dwarf2_frame_ops): New function.

View File

@ -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) \ $(inferior_h) $(breakpoint_h) $(gdb_wait_h) $(gdbcore_h) $(gdbcmd_h) \
$(cli_script_h) $(target_h) $(gdbthread_h) $(annotate_h) \ $(cli_script_h) $(target_h) $(gdbthread_h) $(annotate_h) \
$(symfile_h) $(top_h) $(inf_loop_h) $(regcache_h) $(value_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) \ inftarg.o: inftarg.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) \
$(gdbcore_h) $(command_h) $(gdb_stat_h) $(gdb_wait_h) $(inflow_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) \ infttrace.o: infttrace.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) \

View File

@ -44,6 +44,7 @@
#include "value.h" #include "value.h"
#include "observer.h" #include "observer.h"
#include "language.h" #include "language.h"
#include "gdb_assert.h"
/* Prototypes for local functions */ /* 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 because we cannot remove the breakpoints in the inferior process
until after the `wait' in `wait_for_inferior'. */ until after the `wait' in `wait_for_inferior'. */
static int singlestep_breakpoints_inserted_p = 0; 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 (). */ /* 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 /* and do not pull these breakpoints until after a `wait' in
`wait_for_inferior' */ `wait_for_inferior' */
singlestep_breakpoints_inserted_p = 1; singlestep_breakpoints_inserted_p = 1;
singlestep_ptid = inferior_ptid;
} }
/* Handle any optimized stores to the inferior NOW... */ /* Handle any optimized stores to the inferior NOW... */
@ -597,7 +607,8 @@ resume (int step, enum target_signal sig)
resume_ptid = RESUME_ALL; /* Default */ resume_ptid = RESUME_ALL; /* Default */
if ((step || singlestep_breakpoints_inserted_p) && 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. /* Stepping past a breakpoint without inserting breakpoints.
Make sure only the current thread gets to step, so that 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; number_of_threads_in_syscalls = 0;
clear_proceed_status (); clear_proceed_status ();
stepping_past_singlestep_breakpoint = 0;
} }
static void static void
@ -1739,12 +1752,46 @@ handle_inferior_event (struct execution_control_state *ecs)
stop_pc = read_pc_pid (ecs->ptid); 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 /* See if a thread hit a thread-specific breakpoint that was meant for
another thread. If so, then step that thread past the breakpoint, another thread. If so, then step that thread past the breakpoint,
and continue it. */ and continue it. */
if (stop_signal == TARGET_SIGNAL_TRAP) if (stop_signal == TARGET_SIGNAL_TRAP)
{ {
int thread_hop_needed = 0;
/* Check if a regular breakpoint has been hit before checking /* Check if a regular breakpoint has been hit before checking
for a potential single step breakpoint. Otherwise, GDB will for a potential single step breakpoint. Otherwise, GDB will
not see this breakpoint hit when stepping onto breakpoints. */ 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; ecs->random_signal = 0;
if (!breakpoint_thread_match (stop_pc, ecs->ptid)) 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; int remove_status;
/* Saw a breakpoint, but it was hit by the wrong thread. /* Saw a breakpoint, but it was hit by the wrong thread.
Just continue. */ 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 (); remove_status = remove_breakpoints ();
/* Did we fail to remove breakpoints? If so, try /* Did we fail to remove breakpoints? If so, try
to set the PC past the bp. (There's at least 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 (); registers_changed ();
return; return;
} }
}
} }
else if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p) else if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
{ {