* 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:
parent
f090b9b105
commit
9f976b41d7
|
@ -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.
|
||||||
|
|
|
@ -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) \
|
||||||
|
|
76
gdb/infrun.c
76
gdb/infrun.c
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue