Remove context switching in favour of accessing thread_info fields
directly. * infrun.c (stepping_over_breakpoint, step_resume_breakpoint): Delete. (struct thread_stepping_state): Delete. (gtss, tss): Delete. (follow_inferior_reset_breakpoints, follow_exec) (resume, clear_proceed_status): Adjust. (prev_pc): Delete. (proceed, start_remote, init_wait_for_inferior): Adjust. (struct execution_control_state): Add event_thread member. (delete_step_resume_breakpoint_callback) (delete_step_thread_step_resume_breakpoint) (delete_step_thread_step_resume_breakpoint_cleanup) (delete_step_thread_step_resume_breakpoint): New. (wait_for_inferior, init_execution_control_state): Use delete_step_thread_step_resume_breakpoint_cleanup. (wait_for_inferior): Set the event_thread. (fetch_inferior_event): Ditto. Delete the step-resume breakpoint with delete_step_thread_step_resume_breakpoint. (init_thread_stepping_state): Change parameter type to thread_info. Adjust. (context_switch): Don't context switch prev_pc, stepping_over_breakpoint, step_resume_breakpoint, step_range_start, step_range_end, step_frame_id, tss->stepping_over_breakpoint, tss->stepping_through_solib_after_catch, tss->stepping_through_solib_catchpoints, tss->current_line, or tss->current_symtab. (adjust_pc_after_break, handle_inferior_event) (currently_stepping, step_into_function) (insert_step_resume_breakpoint_at_sal) (insert_longjmp_resume_breakpoint, keep_going): Adjust. (clear_stepping_state): New. (normal_stop): Adjust. (save_inferior_status, restore_inferior_status): Adjust. * gdbthread.h (struct thread_info): Comments describing the members moved here. Add step_after_step_resume_breakpoint. (delete_step_resume_breakpoint): Add thread_info argument. (save_infrun_state, load_infrun_state): Remove prev_pc, trap_expected, step_resume_breakpoint, step_range_start, step_range_end, step_frame_id, another_trap, stepping_through_solib_after_catch, stepping_through_solib_catchpoints, current_line and current_symtab function arguments. (inferior_thread): Declare. * thread.c (inferior_thread): New. (delete_step_resume_breakpoint): Add a thread_info parameter and rewrite. (load_infrun_state, save_infrun_state): Remove prev_pc, trap_expected, step_resume_breakpoint, step_range_start, step_range_end, step_frame_id, stepping_over_breakpoint, stepping_through_solib_after_catch, stepping_through_solib_catchpoints, current_line and current_symtab args. Remove code referencing them. * infcmd.c (step_range_start, step_range_end, step_frame_id): Delete. (step_1, step_once, until_next_command): Adjust. * inferior.h (step_range_start, step_range_end, step_frame_id): Delete. * linux-nat.c (linux_child_follow_fork): If following the child, move the step state to it. Adjust. * inf-ptrace.c (inf_ptrace_follow_fork): Ditto. * inf-ttrace.c (inf_ttrace_follow_fork): Ditto.
This commit is contained in:
parent
757f359dd1
commit
4e1c45eac7
9 changed files with 438 additions and 344 deletions
|
@ -1,3 +1,76 @@
|
|||
2008-09-08 Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
Remove context switching in favour of accessing thread_info fields
|
||||
directly.
|
||||
|
||||
* infrun.c (stepping_over_breakpoint, step_resume_breakpoint):
|
||||
Delete.
|
||||
(struct thread_stepping_state): Delete.
|
||||
(gtss, tss): Delete.
|
||||
(follow_inferior_reset_breakpoints, follow_exec)
|
||||
(resume, clear_proceed_status): Adjust.
|
||||
(prev_pc): Delete.
|
||||
(proceed, start_remote, init_wait_for_inferior): Adjust.
|
||||
(struct execution_control_state): Add event_thread member.
|
||||
(delete_step_resume_breakpoint_callback)
|
||||
(delete_step_thread_step_resume_breakpoint)
|
||||
(delete_step_thread_step_resume_breakpoint_cleanup)
|
||||
(delete_step_thread_step_resume_breakpoint): New.
|
||||
(wait_for_inferior, init_execution_control_state): Use
|
||||
delete_step_thread_step_resume_breakpoint_cleanup.
|
||||
(wait_for_inferior): Set the event_thread.
|
||||
(fetch_inferior_event): Ditto. Delete the step-resume breakpoint
|
||||
with delete_step_thread_step_resume_breakpoint.
|
||||
(init_thread_stepping_state): Change parameter type to
|
||||
thread_info. Adjust.
|
||||
(context_switch): Don't context switch prev_pc,
|
||||
stepping_over_breakpoint, step_resume_breakpoint,
|
||||
step_range_start, step_range_end, step_frame_id,
|
||||
tss->stepping_over_breakpoint,
|
||||
tss->stepping_through_solib_after_catch,
|
||||
tss->stepping_through_solib_catchpoints, tss->current_line, or
|
||||
tss->current_symtab.
|
||||
(adjust_pc_after_break, handle_inferior_event)
|
||||
(currently_stepping, step_into_function)
|
||||
(insert_step_resume_breakpoint_at_sal)
|
||||
(insert_longjmp_resume_breakpoint, keep_going): Adjust.
|
||||
(clear_stepping_state): New.
|
||||
(normal_stop): Adjust.
|
||||
(save_inferior_status, restore_inferior_status): Adjust.
|
||||
|
||||
* gdbthread.h (struct thread_info): Comments describing the
|
||||
members moved here. Add step_after_step_resume_breakpoint.
|
||||
(delete_step_resume_breakpoint): Add thread_info argument.
|
||||
(save_infrun_state, load_infrun_state): Remove prev_pc,
|
||||
trap_expected, step_resume_breakpoint, step_range_start,
|
||||
step_range_end, step_frame_id, another_trap,
|
||||
stepping_through_solib_after_catch,
|
||||
stepping_through_solib_catchpoints, current_line and
|
||||
current_symtab function arguments.
|
||||
(inferior_thread): Declare.
|
||||
|
||||
* thread.c (inferior_thread): New.
|
||||
(delete_step_resume_breakpoint): Add a thread_info parameter and
|
||||
rewrite.
|
||||
(load_infrun_state, save_infrun_state): Remove prev_pc,
|
||||
trap_expected, step_resume_breakpoint, step_range_start,
|
||||
step_range_end, step_frame_id, stepping_over_breakpoint,
|
||||
stepping_through_solib_after_catch,
|
||||
stepping_through_solib_catchpoints, current_line and
|
||||
current_symtab args. Remove code referencing them.
|
||||
|
||||
* infcmd.c (step_range_start, step_range_end, step_frame_id):
|
||||
Delete.
|
||||
(step_1, step_once, until_next_command): Adjust.
|
||||
|
||||
* inferior.h (step_range_start, step_range_end, step_frame_id):
|
||||
Delete.
|
||||
|
||||
* linux-nat.c (linux_child_follow_fork): If following the child,
|
||||
move the step state to it. Adjust.
|
||||
* inf-ptrace.c (inf_ptrace_follow_fork): Ditto.
|
||||
* inf-ttrace.c (inf_ttrace_follow_fork): Ditto.
|
||||
|
||||
2008-09-08 Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
* bsd-uthread.c (bsd_uthread_find_new_threads): Claim the main
|
||||
|
|
|
@ -61,17 +61,70 @@ struct thread_info
|
|||
if we detect it exiting. */
|
||||
int refcount;
|
||||
|
||||
/* State from wait_for_inferior */
|
||||
CORE_ADDR prev_pc;
|
||||
/* User/external stepping state. */
|
||||
|
||||
/* Step-resume or longjmp-resume breakpoint. */
|
||||
struct breakpoint *step_resume_breakpoint;
|
||||
CORE_ADDR step_range_start;
|
||||
CORE_ADDR step_range_end;
|
||||
|
||||
/* Range to single step within.
|
||||
|
||||
If this is nonzero, respond to a single-step signal by continuing
|
||||
to step if the pc is in this range.
|
||||
|
||||
If step_range_start and step_range_end are both 1, it means to
|
||||
step for a single instruction (FIXME: it might clean up
|
||||
wait_for_inferior in a minor way if this were changed to the
|
||||
address of the instruction and that address plus one. But maybe
|
||||
not.). */
|
||||
CORE_ADDR step_range_start; /* Inclusive */
|
||||
CORE_ADDR step_range_end; /* Exclusive */
|
||||
|
||||
/* Stack frame address as of when stepping command was issued.
|
||||
This is how we know when we step into a subroutine call, and how
|
||||
to set the frame for the breakpoint used to step out. */
|
||||
struct frame_id step_frame_id;
|
||||
int current_line;
|
||||
struct symtab *current_symtab;
|
||||
|
||||
/* Internal stepping state. */
|
||||
|
||||
/* Record the pc of the thread the last time it stopped. This is
|
||||
maintained by proceed and keep_going, and used in
|
||||
adjust_pc_after_break to distinguish a hardware single-step
|
||||
SIGTRAP from a breakpoint SIGTRAP. */
|
||||
CORE_ADDR prev_pc;
|
||||
|
||||
/* Nonzero if we are presently stepping over a breakpoint.
|
||||
|
||||
If we hit a breakpoint or watchpoint, and then continue, we need
|
||||
to single step the current thread with breakpoints disabled, to
|
||||
avoid hitting the same breakpoint or watchpoint again. And we
|
||||
should step just a single thread and keep other threads stopped,
|
||||
so that other threads don't miss breakpoints while they are
|
||||
removed.
|
||||
|
||||
So, this variable simultaneously means that we need to single
|
||||
step the current thread, keep other threads stopped, and that
|
||||
breakpoints should be removed while we step.
|
||||
|
||||
This variable is set either:
|
||||
- in proceed, when we resume inferior on user's explicit request
|
||||
- in keep_going, if handle_inferior_event decides we need to
|
||||
step over breakpoint.
|
||||
|
||||
The variable is cleared in normal_stop. The proceed calls
|
||||
wait_for_inferior, which calls handle_inferior_event in a loop,
|
||||
and until wait_for_inferior exits, this variable is changed only
|
||||
by keep_going. */
|
||||
int trap_expected;
|
||||
|
||||
/* Should we step over breakpoint next time keep_going is called? */
|
||||
int stepping_over_breakpoint;
|
||||
|
||||
/* Set to TRUE if we should finish single-stepping over a breakpoint
|
||||
after hitting the current step-resume breakpoint. */
|
||||
int step_after_step_resume_breakpoint;
|
||||
|
||||
/* This is set TRUE when a catchpoint of a shared library event
|
||||
triggers. Since we don't wish to leave the inferior in the
|
||||
solib hook when we report the event, we step the inferior
|
||||
|
@ -127,7 +180,7 @@ extern void delete_thread (ptid_t);
|
|||
extern void delete_thread_silent (ptid_t);
|
||||
|
||||
/* Delete a step_resume_breakpoint from the thread database. */
|
||||
extern void delete_step_resume_breakpoint (void *);
|
||||
extern void delete_step_resume_breakpoint (struct thread_info *);
|
||||
|
||||
/* Translate the integer thread id (GDB's homegrown id, not the system's)
|
||||
into a "pid" (which may be overloaded with extra thread information). */
|
||||
|
@ -163,17 +216,6 @@ extern int thread_count (void);
|
|||
|
||||
/* infrun context switch: save the debugger state for the given thread. */
|
||||
extern void save_infrun_state (ptid_t ptid,
|
||||
CORE_ADDR prev_pc,
|
||||
int trap_expected,
|
||||
struct breakpoint *step_resume_breakpoint,
|
||||
CORE_ADDR step_range_start,
|
||||
CORE_ADDR step_range_end,
|
||||
const struct frame_id *step_frame_id,
|
||||
int another_trap,
|
||||
int stepping_through_solib_after_catch,
|
||||
bpstat stepping_through_solib_catchpoints,
|
||||
int current_line,
|
||||
struct symtab *current_symtab,
|
||||
struct continuation *continuations,
|
||||
struct continuation *intermediate_continuations,
|
||||
int proceed_to_finish,
|
||||
|
@ -186,17 +228,6 @@ extern void save_infrun_state (ptid_t ptid,
|
|||
/* infrun context switch: load the debugger state previously saved
|
||||
for the given thread. */
|
||||
extern void load_infrun_state (ptid_t ptid,
|
||||
CORE_ADDR *prev_pc,
|
||||
int *trap_expected,
|
||||
struct breakpoint **step_resume_breakpoint,
|
||||
CORE_ADDR *step_range_start,
|
||||
CORE_ADDR *step_range_end,
|
||||
struct frame_id *step_frame_id,
|
||||
int *another_trap,
|
||||
int *stepping_through_solib_after_catch,
|
||||
bpstat *stepping_through_solib_catchpoints,
|
||||
int *current_line,
|
||||
struct symtab **current_symtab,
|
||||
struct continuation **continuations,
|
||||
struct continuation **intermediate_continuations,
|
||||
int *proceed_to_finish,
|
||||
|
@ -263,5 +294,8 @@ extern void print_thread_info (struct ui_out *uiout, int thread);
|
|||
|
||||
extern struct cleanup *make_cleanup_restore_current_thread (void);
|
||||
|
||||
/* Returns a pointer into the thread_info corresponding to
|
||||
INFERIOR_PTID. INFERIOR_PTID *must* be in the thread list. */
|
||||
extern struct thread_info* inferior_thread (void);
|
||||
|
||||
#endif /* GDBTHREAD_H */
|
||||
|
|
|
@ -46,6 +46,7 @@ inf_ptrace_follow_fork (struct target_ops *ops, int follow_child)
|
|||
{
|
||||
pid_t pid, fpid;
|
||||
ptrace_state_t pe;
|
||||
struct thread_info *last_tp = NULL;
|
||||
|
||||
/* FIXME: kettenis/20050720: This stuff should really be passed as
|
||||
an argument by our caller. */
|
||||
|
@ -57,6 +58,7 @@ inf_ptrace_follow_fork (struct target_ops *ops, int follow_child)
|
|||
gdb_assert (status.kind == TARGET_WAITKIND_FORKED);
|
||||
|
||||
pid = ptid_get_pid (ptid);
|
||||
last_tp = find_thread_pid (ptid);
|
||||
}
|
||||
|
||||
if (ptrace (PT_GET_PROCESS_STATE, pid,
|
||||
|
@ -68,14 +70,39 @@ inf_ptrace_follow_fork (struct target_ops *ops, int follow_child)
|
|||
|
||||
if (follow_child)
|
||||
{
|
||||
inferior_ptid = pid_to_ptid (fpid);
|
||||
detach_breakpoints (pid);
|
||||
/* Copy user stepping state to the new inferior thread. */
|
||||
struct breakpoint *step_resume_breakpoint = last_tp->step_resume_breakpoint;
|
||||
CORE_ADDR step_range_start = last_tp->step_range_start;
|
||||
CORE_ADDR step_range_end = last_tp->step_range_end;
|
||||
struct frame_id step_frame_id = last_tp->step_frame_id;
|
||||
|
||||
/* Reset breakpoints in the child as appropriate. */
|
||||
follow_inferior_reset_breakpoints ();
|
||||
struct thread_info *tp;
|
||||
|
||||
/* Otherwise, deleting the parent would get rid of this
|
||||
breakpoint. */
|
||||
last_tp->step_resume_breakpoint = NULL;
|
||||
|
||||
/* Before detaching from the parent, remove all breakpoints from
|
||||
it. */
|
||||
detach_breakpoints (pid);
|
||||
|
||||
if (ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, 0) == -1)
|
||||
perror_with_name (("ptrace"));
|
||||
|
||||
/* Delete the parent. */
|
||||
delete_thread_silent (last_tp->ptid);
|
||||
|
||||
/* Add the child. */
|
||||
inferior_ptid = pid_to_ptid (fpid);
|
||||
tp = add_thread_silent (inferior_ptid);
|
||||
|
||||
tp->step_resume_breakpoint = step_resume_breakpoint;
|
||||
tp->step_range_start = step_range_start;
|
||||
tp->step_range_end = step_range_end;
|
||||
tp->step_frame_id = step_frame_id;
|
||||
|
||||
/* Reset breakpoints in the child as appropriate. */
|
||||
follow_inferior_reset_breakpoints ();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -412,6 +412,7 @@ inf_ttrace_follow_fork (struct target_ops *ops, int follow_child)
|
|||
pid_t pid, fpid;
|
||||
lwpid_t lwpid, flwpid;
|
||||
ttstate_t tts;
|
||||
struct thread_info *last_tp = NULL;
|
||||
|
||||
/* FIXME: kettenis/20050720: This stuff should really be passed as
|
||||
an argument by our caller. */
|
||||
|
@ -425,6 +426,7 @@ inf_ttrace_follow_fork (struct target_ops *ops, int follow_child)
|
|||
|
||||
pid = ptid_get_pid (ptid);
|
||||
lwpid = ptid_get_lwp (ptid);
|
||||
last_tp = find_thread_pid (ptid);
|
||||
}
|
||||
|
||||
/* Get all important details that core GDB doesn't (and shouldn't)
|
||||
|
@ -452,6 +454,18 @@ inf_ttrace_follow_fork (struct target_ops *ops, int follow_child)
|
|||
|
||||
if (follow_child)
|
||||
{
|
||||
/* Copy user stepping state to the new inferior thread. */
|
||||
struct breakpoint *step_resume_breakpoint = last_tp->step_resume_breakpoint;
|
||||
CORE_ADDR step_range_start = last_tp->step_range_start;
|
||||
CORE_ADDR step_range_end = last_tp->step_range_end;
|
||||
struct frame_id step_frame_id = last_tp->step_frame_id;
|
||||
|
||||
struct thread_info *tp;
|
||||
|
||||
/* Otherwise, deleting the parent would get rid of this
|
||||
breakpoint. */
|
||||
last_tp->step_resume_breakpoint = NULL;
|
||||
|
||||
inferior_ptid = ptid_build (fpid, flwpid, 0);
|
||||
detach_breakpoints (pid);
|
||||
|
||||
|
@ -530,6 +544,11 @@ Detaching after fork from child process %ld.\n"), (long)fpid);
|
|||
memset (ti->private, 0,
|
||||
sizeof (struct inf_ttrace_private_thread_info));
|
||||
|
||||
ti->step_resume_breakpoint = step_resume_breakpoint;
|
||||
ti->step_range_start = step_range_start;
|
||||
ti->step_range_end = step_range_end;
|
||||
ti->step_frame_id = step_frame_id;
|
||||
|
||||
/* Reset breakpoints in the child as appropriate. */
|
||||
follow_inferior_reset_breakpoints ();
|
||||
}
|
||||
|
|
64
gdb/infcmd.c
64
gdb/infcmd.c
|
@ -177,19 +177,6 @@ int stop_stack_dummy;
|
|||
|
||||
int stopped_by_random_signal;
|
||||
|
||||
/* Range to single step within.
|
||||
If this is nonzero, respond to a single-step signal
|
||||
by continuing to step if the pc is in this range. */
|
||||
|
||||
CORE_ADDR step_range_start; /* Inclusive */
|
||||
CORE_ADDR step_range_end; /* Exclusive */
|
||||
|
||||
/* Stack frame address as of when stepping command was issued.
|
||||
This is how we know when we step into a subroutine call,
|
||||
and how to set the frame for the breakpoint used to step out. */
|
||||
|
||||
struct frame_id step_frame_id;
|
||||
|
||||
enum step_over_calls_kind step_over_calls;
|
||||
|
||||
/* If stepping, nonzero means step count is > 1
|
||||
|
@ -800,21 +787,22 @@ step_1 (int skip_subroutines, int single_inst, char *count_string)
|
|||
{
|
||||
for (; count > 0; count--)
|
||||
{
|
||||
struct thread_info *tp = inferior_thread ();
|
||||
clear_proceed_status ();
|
||||
|
||||
frame = get_current_frame ();
|
||||
if (!frame) /* Avoid coredump here. Why tho? */
|
||||
error (_("No current frame"));
|
||||
step_frame_id = get_frame_id (frame);
|
||||
tp->step_frame_id = get_frame_id (frame);
|
||||
|
||||
if (!single_inst)
|
||||
{
|
||||
find_pc_line_pc_range (stop_pc, &step_range_start, &step_range_end);
|
||||
if (step_range_end == 0)
|
||||
find_pc_line_pc_range (stop_pc,
|
||||
&tp->step_range_start, &tp->step_range_end);
|
||||
if (tp->step_range_end == 0)
|
||||
{
|
||||
char *name;
|
||||
if (find_pc_partial_function (stop_pc, &name, &step_range_start,
|
||||
&step_range_end) == 0)
|
||||
if (find_pc_partial_function (stop_pc, &name,
|
||||
&tp->step_range_start,
|
||||
&tp->step_range_end) == 0)
|
||||
error (_("Cannot find bounds of current function"));
|
||||
|
||||
target_terminal_ours ();
|
||||
|
@ -826,7 +814,7 @@ which has no line number information.\n"), name);
|
|||
else
|
||||
{
|
||||
/* Say we are stepping, but stop after one insn whatever it does. */
|
||||
step_range_start = step_range_end = 1;
|
||||
tp->step_range_start = tp->step_range_end = 1;
|
||||
if (!skip_subroutines)
|
||||
/* It is stepi.
|
||||
Don't step over function calls, not even to functions lacking
|
||||
|
@ -905,27 +893,34 @@ step_once (int skip_subroutines, int single_inst, int count, int thread)
|
|||
|
||||
if (count > 0)
|
||||
{
|
||||
/* Don't assume THREAD is a valid thread id. It is set to -1 if
|
||||
the longjmp breakpoint was not required. Use the
|
||||
INFERIOR_PTID thread instead, which is the same thread when
|
||||
THREAD is set. */
|
||||
struct thread_info *tp = inferior_thread ();
|
||||
clear_proceed_status ();
|
||||
|
||||
frame = get_current_frame ();
|
||||
if (!frame) /* Avoid coredump here. Why tho? */
|
||||
error (_("No current frame"));
|
||||
step_frame_id = get_frame_id (frame);
|
||||
tp->step_frame_id = get_frame_id (frame);
|
||||
|
||||
if (!single_inst)
|
||||
{
|
||||
find_pc_line_pc_range (stop_pc, &step_range_start, &step_range_end);
|
||||
find_pc_line_pc_range (stop_pc,
|
||||
&tp->step_range_start, &tp->step_range_end);
|
||||
|
||||
/* If we have no line info, switch to stepi mode. */
|
||||
if (step_range_end == 0 && step_stop_if_no_debug)
|
||||
if (tp->step_range_end == 0 && step_stop_if_no_debug)
|
||||
{
|
||||
step_range_start = step_range_end = 1;
|
||||
tp->step_range_start = tp->step_range_end = 1;
|
||||
}
|
||||
else if (step_range_end == 0)
|
||||
else if (tp->step_range_end == 0)
|
||||
{
|
||||
char *name;
|
||||
if (find_pc_partial_function (stop_pc, &name, &step_range_start,
|
||||
&step_range_end) == 0)
|
||||
if (find_pc_partial_function (stop_pc, &name,
|
||||
&tp->step_range_start,
|
||||
&tp->step_range_end) == 0)
|
||||
error (_("Cannot find bounds of current function"));
|
||||
|
||||
target_terminal_ours ();
|
||||
|
@ -937,7 +932,7 @@ which has no line number information.\n"), name);
|
|||
else
|
||||
{
|
||||
/* Say we are stepping, but stop after one insn whatever it does. */
|
||||
step_range_start = step_range_end = 1;
|
||||
tp->step_range_start = tp->step_range_end = 1;
|
||||
if (!skip_subroutines)
|
||||
/* It is stepi.
|
||||
Don't step over function calls, not even to functions lacking
|
||||
|
@ -1145,6 +1140,7 @@ until_next_command (int from_tty)
|
|||
CORE_ADDR pc;
|
||||
struct symbol *func;
|
||||
struct symtab_and_line sal;
|
||||
struct thread_info *tp = inferior_thread ();
|
||||
|
||||
clear_proceed_status ();
|
||||
|
||||
|
@ -1164,19 +1160,19 @@ until_next_command (int from_tty)
|
|||
if (msymbol == NULL)
|
||||
error (_("Execution is not within a known function."));
|
||||
|
||||
step_range_start = SYMBOL_VALUE_ADDRESS (msymbol);
|
||||
step_range_end = pc;
|
||||
tp->step_range_start = SYMBOL_VALUE_ADDRESS (msymbol);
|
||||
tp->step_range_end = pc;
|
||||
}
|
||||
else
|
||||
{
|
||||
sal = find_pc_line (pc, 0);
|
||||
|
||||
step_range_start = BLOCK_START (SYMBOL_BLOCK_VALUE (func));
|
||||
step_range_end = sal.end;
|
||||
tp->step_range_start = BLOCK_START (SYMBOL_BLOCK_VALUE (func));
|
||||
tp->step_range_end = sal.end;
|
||||
}
|
||||
|
||||
step_over_calls = STEP_OVER_ALL;
|
||||
step_frame_id = get_frame_id (frame);
|
||||
tp->step_frame_id = get_frame_id (frame);
|
||||
|
||||
step_multi = 0; /* Only one call to proceed */
|
||||
|
||||
|
|
|
@ -309,24 +309,6 @@ extern int stop_stack_dummy;
|
|||
|
||||
extern int stopped_by_random_signal;
|
||||
|
||||
/* Range to single step within.
|
||||
If this is nonzero, respond to a single-step signal
|
||||
by continuing to step if the pc is in this range.
|
||||
|
||||
If step_range_start and step_range_end are both 1, it means to step for
|
||||
a single instruction (FIXME: it might clean up wait_for_inferior in a
|
||||
minor way if this were changed to the address of the instruction and
|
||||
that address plus one. But maybe not.). */
|
||||
|
||||
extern CORE_ADDR step_range_start; /* Inclusive */
|
||||
extern CORE_ADDR step_range_end; /* Exclusive */
|
||||
|
||||
/* Stack frame address as of when stepping command was issued.
|
||||
This is how we know when we step into a subroutine call,
|
||||
and how to set the frame for the breakpoint used to step out. */
|
||||
|
||||
extern struct frame_id step_frame_id;
|
||||
|
||||
/* 1 means step over all subroutine calls.
|
||||
-1 means step over calls to undebuggable functions. */
|
||||
|
||||
|
|
396
gdb/infrun.c
396
gdb/infrun.c
|
@ -73,9 +73,7 @@ static int follow_fork (void);
|
|||
static void set_schedlock_func (char *args, int from_tty,
|
||||
struct cmd_list_element *c);
|
||||
|
||||
struct thread_stepping_state;
|
||||
|
||||
static int currently_stepping (struct thread_stepping_state *tss);
|
||||
static int currently_stepping (struct thread_info *tp);
|
||||
|
||||
static void xdb_handle_command (char *args, int from_tty);
|
||||
|
||||
|
@ -216,31 +214,6 @@ static struct cmd_list_element *stop_command;
|
|||
|
||||
static struct symbol *step_start_function;
|
||||
|
||||
/* Nonzero if we are presently stepping over a breakpoint.
|
||||
|
||||
If we hit a breakpoint or watchpoint, and then continue,
|
||||
we need to single step the current thread with breakpoints
|
||||
disabled, to avoid hitting the same breakpoint or
|
||||
watchpoint again. And we should step just a single
|
||||
thread and keep other threads stopped, so that
|
||||
other threads don't miss breakpoints while they are removed.
|
||||
|
||||
So, this variable simultaneously means that we need to single
|
||||
step the current thread, keep other threads stopped, and that
|
||||
breakpoints should be removed while we step.
|
||||
|
||||
This variable is set either:
|
||||
- in proceed, when we resume inferior on user's explicit request
|
||||
- in keep_going, if handle_inferior_event decides we need to
|
||||
step over breakpoint.
|
||||
|
||||
The variable is cleared in clear_proceed_status, called every
|
||||
time before we call proceed. The proceed calls wait_for_inferior,
|
||||
which calls handle_inferior_event in a loop, and until
|
||||
wait_for_inferior exits, this variable is changed only by keep_going. */
|
||||
|
||||
static int stepping_over_breakpoint;
|
||||
|
||||
/* Nonzero if we want to give control to the user when we're notified
|
||||
of shared library events by the dynamic linker. */
|
||||
static int stop_on_solib_events;
|
||||
|
@ -280,34 +253,15 @@ struct regcache *stop_registers;
|
|||
|
||||
static int stop_print_frame;
|
||||
|
||||
/* Step-resume or longjmp-resume breakpoint. */
|
||||
static struct breakpoint *step_resume_breakpoint = NULL;
|
||||
|
||||
/* This is a cached copy of the pid/waitstatus of the last event
|
||||
returned by target_wait()/deprecated_target_wait_hook(). This
|
||||
information is returned by get_last_target_status(). */
|
||||
static ptid_t target_last_wait_ptid;
|
||||
static struct target_waitstatus target_last_waitstatus;
|
||||
|
||||
/* Context-switchable data. */
|
||||
struct thread_stepping_state
|
||||
{
|
||||
/* Should we step over breakpoint next time keep_going
|
||||
is called? */
|
||||
int stepping_over_breakpoint;
|
||||
int current_line;
|
||||
struct symtab *current_symtab;
|
||||
int step_after_step_resume_breakpoint;
|
||||
int stepping_through_solib_after_catch;
|
||||
bpstat stepping_through_solib_catchpoints;
|
||||
};
|
||||
|
||||
struct thread_stepping_state gtss;
|
||||
struct thread_stepping_state *tss = >ss;
|
||||
|
||||
static void context_switch (ptid_t ptid);
|
||||
|
||||
void init_thread_stepping_state (struct thread_stepping_state *tss);
|
||||
void init_thread_stepping_state (struct thread_info *tss);
|
||||
|
||||
void init_infwait_state (void);
|
||||
|
||||
|
@ -359,6 +313,8 @@ follow_fork (void)
|
|||
void
|
||||
follow_inferior_reset_breakpoints (void)
|
||||
{
|
||||
struct thread_info *tp = inferior_thread ();
|
||||
|
||||
/* Was there a step_resume breakpoint? (There was if the user
|
||||
did a "next" at the fork() call.) If so, explicitly reset its
|
||||
thread number.
|
||||
|
@ -370,8 +326,8 @@ follow_inferior_reset_breakpoints (void)
|
|||
"threads". We must update the bp's notion of which thread
|
||||
it is for, or it'll be ignored when it triggers. */
|
||||
|
||||
if (step_resume_breakpoint)
|
||||
breakpoint_re_set_thread (step_resume_breakpoint);
|
||||
if (tp->step_resume_breakpoint)
|
||||
breakpoint_re_set_thread (tp->step_resume_breakpoint);
|
||||
|
||||
/* Reinsert all breakpoints in the child. The user may have set
|
||||
breakpoints after catching the fork, in which case those
|
||||
|
@ -389,6 +345,7 @@ follow_exec (ptid_t pid, char *execd_pathname)
|
|||
{
|
||||
ptid_t saved_pid = pid;
|
||||
struct target_ops *tgt;
|
||||
struct thread_info *th = inferior_thread ();
|
||||
|
||||
/* This is an exec event that we actually wish to pay attention to.
|
||||
Refresh our symbol table to the newly exec'd program, remove any
|
||||
|
@ -414,9 +371,9 @@ follow_exec (ptid_t pid, char *execd_pathname)
|
|||
|
||||
/* If there was one, it's gone now. We cannot truly step-to-next
|
||||
statement through an exec(). */
|
||||
step_resume_breakpoint = NULL;
|
||||
step_range_start = 0;
|
||||
step_range_end = 0;
|
||||
th->step_resume_breakpoint = NULL;
|
||||
th->step_range_start = 0;
|
||||
th->step_range_end = 0;
|
||||
|
||||
/* What is this a.out's name? */
|
||||
printf_unfiltered (_("Executing new program: %s\n"), execd_pathname);
|
||||
|
@ -944,14 +901,15 @@ resume (int step, enum target_signal sig)
|
|||
struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
|
||||
struct regcache *regcache = get_current_regcache ();
|
||||
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||
struct thread_info *tp = inferior_thread ();
|
||||
CORE_ADDR pc = regcache_read_pc (regcache);
|
||||
QUIT;
|
||||
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"infrun: resume (step=%d, signal=%d), "
|
||||
"stepping_over_breakpoint=%d\n",
|
||||
step, sig, stepping_over_breakpoint);
|
||||
"trap_expected=%d\n",
|
||||
step, sig, tp->trap_expected);
|
||||
|
||||
/* Some targets (e.g. Solaris x86) have a kernel bug when stepping
|
||||
over an instruction that causes a page fault without triggering
|
||||
|
@ -988,7 +946,7 @@ a command like `return' or `jump' to continue execution."));
|
|||
comments in the handle_inferior event for dealing with 'random
|
||||
signals' explain what we do instead. */
|
||||
if (use_displaced_stepping (gdbarch)
|
||||
&& stepping_over_breakpoint
|
||||
&& tp->trap_expected
|
||||
&& sig == TARGET_SIGNAL_0)
|
||||
{
|
||||
if (!displaced_step_prepare (inferior_ptid))
|
||||
|
@ -1072,7 +1030,7 @@ a command like `return' or `jump' to continue execution."));
|
|||
}
|
||||
|
||||
if ((step || singlestep_breakpoints_inserted_p)
|
||||
&& stepping_over_breakpoint)
|
||||
&& tp->trap_expected)
|
||||
{
|
||||
/* We're allowing a thread to run past a breakpoint it has
|
||||
hit, by single-stepping the thread with the breakpoint
|
||||
|
@ -1112,7 +1070,7 @@ a command like `return' or `jump' to continue execution."));
|
|||
|
||||
if (debug_displaced
|
||||
&& use_displaced_stepping (gdbarch)
|
||||
&& stepping_over_breakpoint)
|
||||
&& tp->trap_expected)
|
||||
{
|
||||
struct regcache *resume_regcache = get_thread_regcache (resume_ptid);
|
||||
CORE_ADDR actual_pc = regcache_read_pc (resume_regcache);
|
||||
|
@ -1138,10 +1096,16 @@ a command like `return' or `jump' to continue execution."));
|
|||
void
|
||||
clear_proceed_status (void)
|
||||
{
|
||||
stepping_over_breakpoint = 0;
|
||||
step_range_start = 0;
|
||||
step_range_end = 0;
|
||||
step_frame_id = null_frame_id;
|
||||
if (!ptid_equal (inferior_ptid, null_ptid))
|
||||
{
|
||||
struct thread_info *tp = inferior_thread ();
|
||||
|
||||
tp->trap_expected = 0;
|
||||
tp->step_range_start = 0;
|
||||
tp->step_range_end = 0;
|
||||
tp->step_frame_id = null_frame_id;
|
||||
}
|
||||
|
||||
step_over_calls = STEP_OVER_UNDEBUGGABLE;
|
||||
stop_after_trap = 0;
|
||||
stop_soon = NO_STOP_QUIETLY;
|
||||
|
@ -1201,11 +1165,6 @@ prepare_to_proceed (int step)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Record the pc of the program the last time it stopped. This is
|
||||
just used internally by wait_for_inferior, but need to be preserved
|
||||
over calls to it and cleared when the inferior is started. */
|
||||
static CORE_ADDR prev_pc;
|
||||
|
||||
/* Basic routine for continuing the program in various fashions.
|
||||
|
||||
ADDR is the address to resume at, or -1 for resume where stopped.
|
||||
|
@ -1223,6 +1182,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
|
|||
{
|
||||
struct regcache *regcache = get_current_regcache ();
|
||||
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||
struct thread_info *tp;
|
||||
CORE_ADDR pc = regcache_read_pc (regcache);
|
||||
int oneproc = 0;
|
||||
|
||||
|
@ -1278,9 +1238,12 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
|
|||
oneproc = 1;
|
||||
}
|
||||
|
||||
/* prepare_to_proceed may change the current thread. */
|
||||
tp = inferior_thread ();
|
||||
|
||||
if (oneproc)
|
||||
{
|
||||
stepping_over_breakpoint = 1;
|
||||
tp->trap_expected = 1;
|
||||
/* If displaced stepping is enabled, we can step over the
|
||||
breakpoint without hitting it, so leave all breakpoints
|
||||
inserted. Otherwise we need to disable all breakpoints, step
|
||||
|
@ -1293,7 +1256,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
|
|||
/* We can insert breakpoints if we're not trying to step over one,
|
||||
or if we are stepping over one but we're using displaced stepping
|
||||
to do so. */
|
||||
if (! stepping_over_breakpoint || use_displaced_stepping (gdbarch))
|
||||
if (! tp->trap_expected || use_displaced_stepping (gdbarch))
|
||||
insert_breakpoints ();
|
||||
|
||||
if (siggnal != TARGET_SIGNAL_DEFAULT)
|
||||
|
@ -1331,10 +1294,10 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
|
|||
are not guaranteed the inferior is stopped and so the regcache_read_pc ()
|
||||
call can fail. Setting the prev_pc value here ensures the value is
|
||||
updated correctly when the inferior is stopped. */
|
||||
prev_pc = regcache_read_pc (get_current_regcache ());
|
||||
tp->prev_pc = regcache_read_pc (get_current_regcache ());
|
||||
|
||||
/* Fill in with reasonable starting values. */
|
||||
init_thread_stepping_state (tss);
|
||||
init_thread_stepping_state (tp);
|
||||
|
||||
/* Reset to normal state. */
|
||||
init_infwait_state ();
|
||||
|
@ -1361,7 +1324,6 @@ start_remote (int from_tty)
|
|||
{
|
||||
init_wait_for_inferior ();
|
||||
stop_soon = STOP_QUIETLY_REMOTE;
|
||||
stepping_over_breakpoint = 0;
|
||||
|
||||
/* Always go on waiting for the target, regardless of the mode. */
|
||||
/* FIXME: cagney/1999-09-23: At present it isn't possible to
|
||||
|
@ -1393,7 +1355,6 @@ void
|
|||
init_wait_for_inferior (void)
|
||||
{
|
||||
/* These are meaningless until the first time through wait_for_inferior. */
|
||||
prev_pc = 0;
|
||||
|
||||
breakpoint_init_inferior (inf_starting);
|
||||
|
||||
|
@ -1410,7 +1371,6 @@ init_wait_for_inferior (void)
|
|||
|
||||
target_last_wait_ptid = minus_one_ptid;
|
||||
|
||||
init_thread_stepping_state (tss);
|
||||
previous_inferior_ptid = null_ptid;
|
||||
init_infwait_state ();
|
||||
|
||||
|
@ -1455,6 +1415,10 @@ enum infwait_states infwait_state;
|
|||
struct execution_control_state
|
||||
{
|
||||
ptid_t ptid;
|
||||
/* The thread that got the event, if this was a thread event; NULL
|
||||
otherwise. */
|
||||
struct thread_info *event_thread;
|
||||
|
||||
struct target_waitstatus ws;
|
||||
int random_signal;
|
||||
CORE_ADDR stop_func_start;
|
||||
|
@ -1481,6 +1445,53 @@ static void keep_going (struct execution_control_state *ecs);
|
|||
static void print_stop_reason (enum inferior_stop_reason stop_reason,
|
||||
int stop_info);
|
||||
|
||||
/* Callback for iterate_over_threads. */
|
||||
|
||||
static int
|
||||
delete_step_resume_breakpoint_callback (struct thread_info *info, void *data)
|
||||
{
|
||||
if (is_exited (info->ptid))
|
||||
return 0;
|
||||
|
||||
delete_step_resume_breakpoint (info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* In all-stop, delete the step resume breakpoint of any thread that
|
||||
had one. In non-stop, delete the step resume breakpoint of the
|
||||
thread that just stopped. */
|
||||
|
||||
static void
|
||||
delete_step_thread_step_resume_breakpoint (void)
|
||||
{
|
||||
if (!target_has_execution
|
||||
|| ptid_equal (inferior_ptid, null_ptid))
|
||||
/* If the inferior has exited, we have already deleted the step
|
||||
resume breakpoints out of GDB's lists. */
|
||||
return;
|
||||
|
||||
if (non_stop)
|
||||
{
|
||||
/* If in non-stop mode, only delete the step-resume or
|
||||
longjmp-resume breakpoint of the thread that just stopped
|
||||
stepping. */
|
||||
struct thread_info *tp = inferior_thread ();
|
||||
delete_step_resume_breakpoint (tp);
|
||||
}
|
||||
else
|
||||
/* In all-stop mode, delete all step-resume and longjmp-resume
|
||||
breakpoints of any thread that had them. */
|
||||
iterate_over_threads (delete_step_resume_breakpoint_callback, NULL);
|
||||
}
|
||||
|
||||
/* A cleanup wrapper. */
|
||||
|
||||
static void
|
||||
delete_step_thread_step_resume_breakpoint_cleanup (void *arg)
|
||||
{
|
||||
delete_step_thread_step_resume_breakpoint ();
|
||||
}
|
||||
|
||||
/* Wait for control to return from inferior to debugger.
|
||||
|
||||
If TREAT_EXEC_AS_SIGTRAP is non-zero, then handle EXEC signals
|
||||
|
@ -1505,8 +1516,8 @@ wait_for_inferior (int treat_exec_as_sigtrap)
|
|||
(gdb_stdlog, "infrun: wait_for_inferior (treat_exec_as_sigtrap=%d)\n",
|
||||
treat_exec_as_sigtrap);
|
||||
|
||||
old_cleanups = make_cleanup (delete_step_resume_breakpoint,
|
||||
&step_resume_breakpoint);
|
||||
old_cleanups =
|
||||
make_cleanup (delete_step_thread_step_resume_breakpoint_cleanup, NULL);
|
||||
|
||||
ecs = &ecss;
|
||||
memset (ecs, 0, sizeof (*ecs));
|
||||
|
@ -1531,6 +1542,8 @@ wait_for_inferior (int treat_exec_as_sigtrap)
|
|||
else
|
||||
ecs->ptid = target_wait (waiton_ptid, &ecs->ws);
|
||||
|
||||
ecs->event_thread = find_thread_pid (ecs->ptid);
|
||||
|
||||
if (treat_exec_as_sigtrap && ecs->ws.kind == TARGET_WAITKIND_EXECD)
|
||||
{
|
||||
xfree (ecs->ws.value.execd_pathname);
|
||||
|
@ -1544,6 +1557,7 @@ wait_for_inferior (int treat_exec_as_sigtrap)
|
|||
if (!ecs->wait_some_more)
|
||||
break;
|
||||
}
|
||||
|
||||
do_cleanups (old_cleanups);
|
||||
}
|
||||
|
||||
|
@ -1605,12 +1619,14 @@ fetch_inferior_event (void *client_data)
|
|||
thread. */
|
||||
context_switch (ecs->ptid);
|
||||
|
||||
ecs->event_thread = find_thread_pid (ecs->ptid);
|
||||
|
||||
/* Now figure out what to do with the result of the result. */
|
||||
handle_inferior_event (ecs);
|
||||
|
||||
if (!ecs->wait_some_more)
|
||||
{
|
||||
delete_step_resume_breakpoint (&step_resume_breakpoint);
|
||||
delete_step_thread_step_resume_breakpoint ();
|
||||
|
||||
if (stop_soon == NO_STOP_QUIETLY)
|
||||
normal_stop ();
|
||||
|
@ -1642,7 +1658,7 @@ init_execution_control_state (struct execution_control_state *ecs)
|
|||
/* Clear context switchable stepping state. */
|
||||
|
||||
void
|
||||
init_thread_stepping_state (struct thread_stepping_state *tss)
|
||||
init_thread_stepping_state (struct thread_info *tss)
|
||||
{
|
||||
struct symtab_and_line sal;
|
||||
|
||||
|
@ -1651,7 +1667,7 @@ init_thread_stepping_state (struct thread_stepping_state *tss)
|
|||
tss->stepping_through_solib_after_catch = 0;
|
||||
tss->stepping_through_solib_catchpoints = NULL;
|
||||
|
||||
sal = find_pc_line (prev_pc, 0);
|
||||
sal = find_pc_line (tss->prev_pc, 0);
|
||||
tss->current_line = sal.line;
|
||||
tss->current_symtab = sal.symtab;
|
||||
}
|
||||
|
@ -1696,14 +1712,7 @@ context_switch (ptid_t ptid)
|
|||
if (in_thread_list (inferior_ptid) && in_thread_list (ptid))
|
||||
{ /* Perform infrun state context switch: */
|
||||
/* Save infrun state for the old thread. */
|
||||
save_infrun_state (inferior_ptid, prev_pc,
|
||||
stepping_over_breakpoint, step_resume_breakpoint,
|
||||
step_range_start,
|
||||
step_range_end, &step_frame_id,
|
||||
tss->stepping_over_breakpoint,
|
||||
tss->stepping_through_solib_after_catch,
|
||||
tss->stepping_through_solib_catchpoints,
|
||||
tss->current_line, tss->current_symtab,
|
||||
save_infrun_state (inferior_ptid,
|
||||
cmd_continuation, intermediate_continuation,
|
||||
proceed_to_finish,
|
||||
step_over_calls,
|
||||
|
@ -1713,14 +1722,7 @@ context_switch (ptid_t ptid)
|
|||
stop_bpstat);
|
||||
|
||||
/* Load infrun state for the new thread. */
|
||||
load_infrun_state (ptid, &prev_pc,
|
||||
&stepping_over_breakpoint, &step_resume_breakpoint,
|
||||
&step_range_start,
|
||||
&step_range_end, &step_frame_id,
|
||||
&tss->stepping_over_breakpoint,
|
||||
&tss->stepping_through_solib_after_catch,
|
||||
&tss->stepping_through_solib_catchpoints,
|
||||
&tss->current_line, &tss->current_symtab,
|
||||
load_infrun_state (ptid,
|
||||
&cmd_continuation, &intermediate_continuation,
|
||||
&proceed_to_finish,
|
||||
&step_over_calls,
|
||||
|
@ -1817,8 +1819,8 @@ adjust_pc_after_break (struct execution_control_state *ecs)
|
|||
|
||||
if (singlestep_breakpoints_inserted_p
|
||||
|| !ptid_equal (ecs->ptid, inferior_ptid)
|
||||
|| !currently_stepping (tss)
|
||||
|| prev_pc == breakpoint_pc)
|
||||
|| !currently_stepping (ecs->event_thread)
|
||||
|| ecs->event_thread->prev_pc == breakpoint_pc)
|
||||
regcache_write_pc (regcache, breakpoint_pc);
|
||||
}
|
||||
}
|
||||
|
@ -2254,6 +2256,8 @@ targets should add new threads to the thread list themselves in non-stop mode.")
|
|||
the fact that we were supposed to switch back. */
|
||||
if (stop_signal == TARGET_SIGNAL_TRAP)
|
||||
{
|
||||
struct thread_info *tp;
|
||||
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"infrun: handling deferred step\n");
|
||||
|
@ -2347,6 +2351,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
|
|||
the context we want to use. Just fudge our
|
||||
state and continue. */
|
||||
ecs->ptid = singlestep_ptid;
|
||||
ecs->event_thread = find_thread_pid (ecs->ptid);
|
||||
stop_pc = new_singlestep_pc;
|
||||
}
|
||||
else
|
||||
|
@ -2406,7 +2411,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
|
|||
infwait_state = infwait_thread_hop_state;
|
||||
}
|
||||
|
||||
tss->stepping_over_breakpoint = 1;
|
||||
ecs->event_thread->stepping_over_breakpoint = 1;
|
||||
keep_going (ecs);
|
||||
registers_changed ();
|
||||
return;
|
||||
|
@ -2495,7 +2500,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
|
|||
&ecs->stop_func_start, &ecs->stop_func_end);
|
||||
ecs->stop_func_start
|
||||
+= gdbarch_deprecated_function_start_offset (current_gdbarch);
|
||||
tss->stepping_over_breakpoint = 0;
|
||||
ecs->event_thread->stepping_over_breakpoint = 0;
|
||||
bpstat_clear (&stop_bpstat);
|
||||
stop_step = 0;
|
||||
stop_print_frame = 1;
|
||||
|
@ -2503,9 +2508,9 @@ targets should add new threads to the thread list themselves in non-stop mode.")
|
|||
stopped_by_random_signal = 0;
|
||||
|
||||
if (stop_signal == TARGET_SIGNAL_TRAP
|
||||
&& stepping_over_breakpoint
|
||||
&& ecs->event_thread->trap_expected
|
||||
&& gdbarch_single_step_through_delay_p (current_gdbarch)
|
||||
&& currently_stepping (tss))
|
||||
&& currently_stepping (ecs->event_thread))
|
||||
{
|
||||
/* We're trying to step off a breakpoint. Turns out that we're
|
||||
also on an instruction that needs to be stepped multiple
|
||||
|
@ -2517,11 +2522,11 @@ targets should add new threads to the thread list themselves in non-stop mode.")
|
|||
get_current_frame ());
|
||||
if (debug_infrun && step_through_delay)
|
||||
fprintf_unfiltered (gdb_stdlog, "infrun: step through delay\n");
|
||||
if (step_range_end == 0 && step_through_delay)
|
||||
if (ecs->event_thread->step_range_end == 0 && step_through_delay)
|
||||
{
|
||||
/* The user issued a continue when stopped at a breakpoint.
|
||||
Set up for another trap and get out of here. */
|
||||
tss->stepping_over_breakpoint = 1;
|
||||
ecs->event_thread->stepping_over_breakpoint = 1;
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
|
@ -2533,7 +2538,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
|
|||
case, don't decide that here, just set
|
||||
ecs->stepping_over_breakpoint, making sure we
|
||||
single-step again before breakpoints are re-inserted. */
|
||||
tss->stepping_over_breakpoint = 1;
|
||||
ecs->event_thread->stepping_over_breakpoint = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2541,7 +2546,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
|
|||
The alternatives are:
|
||||
1) stop_stepping and return; to really stop and return to the debugger,
|
||||
2) keep_going and return to start up again
|
||||
(set tss->stepping_over_breakpoint to 1 to single step once)
|
||||
(set ecs->event_thread->stepping_over_breakpoint to 1 to single step once)
|
||||
3) set ecs->random_signal to 1, and the decision between 1 and 2
|
||||
will be made according to the signal handling tables. */
|
||||
|
||||
|
@ -2560,7 +2565,7 @@ targets should add new threads to the thread list themselves in non-stop mode.")
|
|||
breakpoint is always inserted at the original instruction;
|
||||
non-standard signals can't be explained by the breakpoint. */
|
||||
if (stop_signal == TARGET_SIGNAL_TRAP
|
||||
|| (! stepping_over_breakpoint
|
||||
|| (! ecs->event_thread->trap_expected
|
||||
&& breakpoint_inserted_here_p (stop_pc)
|
||||
&& (stop_signal == TARGET_SIGNAL_ILL
|
||||
|| stop_signal == TARGET_SIGNAL_SEGV
|
||||
|
@ -2638,8 +2643,9 @@ targets should add new threads to the thread list themselves in non-stop mode.")
|
|||
if (stop_signal == TARGET_SIGNAL_TRAP)
|
||||
ecs->random_signal
|
||||
= !(bpstat_explains_signal (stop_bpstat)
|
||||
|| stepping_over_breakpoint
|
||||
|| (step_range_end && step_resume_breakpoint == NULL));
|
||||
|| ecs->event_thread->trap_expected
|
||||
|| (ecs->event_thread->step_range_end
|
||||
&& ecs->event_thread->step_resume_breakpoint == NULL));
|
||||
else
|
||||
{
|
||||
ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
|
||||
|
@ -2689,9 +2695,9 @@ process_event_stop_test:
|
|||
if (signal_program[stop_signal] == 0)
|
||||
stop_signal = TARGET_SIGNAL_0;
|
||||
|
||||
if (prev_pc == read_pc ()
|
||||
&& stepping_over_breakpoint
|
||||
&& step_resume_breakpoint == NULL)
|
||||
if (ecs->event_thread->prev_pc == read_pc ()
|
||||
&& ecs->event_thread->trap_expected
|
||||
&& ecs->event_thread->step_resume_breakpoint == NULL)
|
||||
{
|
||||
/* We were just starting a new sequence, attempting to
|
||||
single-step off of a breakpoint and expecting a SIGTRAP.
|
||||
|
@ -2709,17 +2715,18 @@ process_event_stop_test:
|
|||
"breakpoint\n");
|
||||
|
||||
insert_step_resume_breakpoint_at_frame (get_current_frame ());
|
||||
tss->step_after_step_resume_breakpoint = 1;
|
||||
ecs->event_thread->step_after_step_resume_breakpoint = 1;
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (step_range_end != 0
|
||||
if (ecs->event_thread->step_range_end != 0
|
||||
&& stop_signal != TARGET_SIGNAL_0
|
||||
&& stop_pc >= step_range_start && stop_pc < step_range_end
|
||||
&& (ecs->event_thread->step_range_start <= stop_pc
|
||||
&& stop_pc < ecs->event_thread->step_range_end)
|
||||
&& frame_id_eq (get_frame_id (get_current_frame ()),
|
||||
step_frame_id)
|
||||
&& step_resume_breakpoint == NULL)
|
||||
ecs->event_thread->step_frame_id)
|
||||
&& ecs->event_thread->step_resume_breakpoint == NULL)
|
||||
{
|
||||
/* The inferior is about to take a signal that will take it
|
||||
out of the single step range. Set a breakpoint at the
|
||||
|
@ -2773,7 +2780,7 @@ process_event_stop_test:
|
|||
fprintf_unfiltered (gdb_stdlog,
|
||||
"infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME\n");
|
||||
|
||||
tss->stepping_over_breakpoint = 1;
|
||||
ecs->event_thread->stepping_over_breakpoint = 1;
|
||||
|
||||
if (!gdbarch_get_longjmp_target_p (current_gdbarch)
|
||||
|| !gdbarch_get_longjmp_target (current_gdbarch,
|
||||
|
@ -2788,8 +2795,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
|
||||
/* We're going to replace the current step-resume breakpoint
|
||||
with a longjmp-resume breakpoint. */
|
||||
if (step_resume_breakpoint != NULL)
|
||||
delete_step_resume_breakpoint (&step_resume_breakpoint);
|
||||
delete_step_resume_breakpoint (ecs->event_thread);
|
||||
|
||||
/* Insert a breakpoint at resume address. */
|
||||
insert_longjmp_resume_breakpoint (jmp_buf_pc);
|
||||
|
@ -2802,8 +2808,8 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
fprintf_unfiltered (gdb_stdlog,
|
||||
"infrun: BPSTAT_WHAT_CLEAR_LONGJMP_RESUME\n");
|
||||
|
||||
gdb_assert (step_resume_breakpoint != NULL);
|
||||
delete_step_resume_breakpoint (&step_resume_breakpoint);
|
||||
gdb_assert (ecs->event_thread->step_resume_breakpoint != NULL);
|
||||
delete_step_resume_breakpoint (ecs->event_thread);
|
||||
|
||||
stop_step = 1;
|
||||
print_stop_reason (END_STEPPING_RANGE, 0);
|
||||
|
@ -2813,7 +2819,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
case BPSTAT_WHAT_SINGLE:
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_SINGLE\n");
|
||||
tss->stepping_over_breakpoint = 1;
|
||||
ecs->event_thread->stepping_over_breakpoint = 1;
|
||||
/* Still need to check other stuff, at least the case
|
||||
where we are stepping and step out of the right range. */
|
||||
break;
|
||||
|
@ -2841,39 +2847,17 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
return;
|
||||
|
||||
case BPSTAT_WHAT_STEP_RESUME:
|
||||
/* This proably demands a more elegant solution, but, yeah
|
||||
right...
|
||||
|
||||
This function's use of the simple variable
|
||||
step_resume_breakpoint doesn't seem to accomodate
|
||||
simultaneously active step-resume bp's, although the
|
||||
breakpoint list certainly can.
|
||||
|
||||
If we reach here and step_resume_breakpoint is already
|
||||
NULL, then apparently we have multiple active
|
||||
step-resume bp's. We'll just delete the breakpoint we
|
||||
stopped at, and carry on.
|
||||
|
||||
Correction: what the code currently does is delete a
|
||||
step-resume bp, but it makes no effort to ensure that
|
||||
the one deleted is the one currently stopped at. MVS */
|
||||
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STEP_RESUME\n");
|
||||
|
||||
if (step_resume_breakpoint == NULL)
|
||||
{
|
||||
step_resume_breakpoint =
|
||||
bpstat_find_step_resume_breakpoint (stop_bpstat);
|
||||
}
|
||||
delete_step_resume_breakpoint (&step_resume_breakpoint);
|
||||
if (tss->step_after_step_resume_breakpoint)
|
||||
delete_step_resume_breakpoint (ecs->event_thread);
|
||||
if (ecs->event_thread->step_after_step_resume_breakpoint)
|
||||
{
|
||||
/* Back when the step-resume breakpoint was inserted, we
|
||||
were trying to single-step off a breakpoint. Go back
|
||||
to doing that. */
|
||||
tss->step_after_step_resume_breakpoint = 0;
|
||||
tss->stepping_over_breakpoint = 1;
|
||||
ecs->event_thread->step_after_step_resume_breakpoint = 0;
|
||||
ecs->event_thread->stepping_over_breakpoint = 1;
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
|
@ -2948,19 +2932,20 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
friends) until we reach non-dld code. At that point,
|
||||
we can stop stepping. */
|
||||
bpstat_get_triggered_catchpoints (stop_bpstat,
|
||||
&tss->
|
||||
&ecs->
|
||||
event_thread->
|
||||
stepping_through_solib_catchpoints);
|
||||
tss->stepping_through_solib_after_catch = 1;
|
||||
ecs->event_thread->stepping_through_solib_after_catch = 1;
|
||||
|
||||
/* Be sure to lift all breakpoints, so the inferior does
|
||||
actually step past this point... */
|
||||
tss->stepping_over_breakpoint = 1;
|
||||
ecs->event_thread->stepping_over_breakpoint = 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We want to step over this breakpoint, then keep going. */
|
||||
tss->stepping_over_breakpoint = 1;
|
||||
ecs->event_thread->stepping_over_breakpoint = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2983,7 +2968,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
/* Are we stepping to get the inferior out of the dynamic linker's
|
||||
hook (and possibly the dld itself) after catching a shlib
|
||||
event? */
|
||||
if (tss->stepping_through_solib_after_catch)
|
||||
if (ecs->event_thread->stepping_through_solib_after_catch)
|
||||
{
|
||||
#if defined(SOLIB_ADD)
|
||||
/* Have we reached our destination? If not, keep going. */
|
||||
|
@ -2991,7 +2976,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
{
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog, "infrun: stepping in dynamic linker\n");
|
||||
tss->stepping_over_breakpoint = 1;
|
||||
ecs->event_thread->stepping_over_breakpoint = 1;
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
|
@ -3000,16 +2985,16 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
fprintf_unfiltered (gdb_stdlog, "infrun: step past dynamic linker\n");
|
||||
/* Else, stop and report the catchpoint(s) whose triggering
|
||||
caused us to begin stepping. */
|
||||
tss->stepping_through_solib_after_catch = 0;
|
||||
ecs->event_thread->stepping_through_solib_after_catch = 0;
|
||||
bpstat_clear (&stop_bpstat);
|
||||
stop_bpstat = bpstat_copy (tss->stepping_through_solib_catchpoints);
|
||||
bpstat_clear (&tss->stepping_through_solib_catchpoints);
|
||||
stop_bpstat = bpstat_copy (ecs->event_thread->stepping_through_solib_catchpoints);
|
||||
bpstat_clear (&ecs->event_thread->stepping_through_solib_catchpoints);
|
||||
stop_print_frame = 1;
|
||||
stop_stepping (ecs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (step_resume_breakpoint)
|
||||
if (ecs->event_thread->step_resume_breakpoint)
|
||||
{
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
|
@ -3022,7 +3007,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
return;
|
||||
}
|
||||
|
||||
if (step_range_end == 0)
|
||||
if (ecs->event_thread->step_range_end == 0)
|
||||
{
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog, "infrun: no stepping, continue\n");
|
||||
|
@ -3036,12 +3021,13 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
Note that step_range_end is the address of the first instruction
|
||||
beyond the step range, and NOT the address of the last instruction
|
||||
within it! */
|
||||
if (stop_pc >= step_range_start && stop_pc < step_range_end)
|
||||
if (stop_pc >= ecs->event_thread->step_range_start
|
||||
&& stop_pc < ecs->event_thread->step_range_end)
|
||||
{
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog, "infrun: stepping inside range [0x%s-0x%s]\n",
|
||||
paddr_nz (step_range_start),
|
||||
paddr_nz (step_range_end));
|
||||
paddr_nz (ecs->event_thread->step_range_start),
|
||||
paddr_nz (ecs->event_thread->step_range_end));
|
||||
keep_going (ecs);
|
||||
return;
|
||||
}
|
||||
|
@ -3076,7 +3062,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
return;
|
||||
}
|
||||
|
||||
if (step_range_end != 1
|
||||
if (ecs->event_thread->step_range_end != 1
|
||||
&& (step_over_calls == STEP_OVER_UNDEBUGGABLE
|
||||
|| step_over_calls == STEP_OVER_ALL)
|
||||
&& get_frame_type (get_current_frame ()) == SIGTRAMP_FRAME)
|
||||
|
@ -3100,8 +3086,10 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
NOTE: frame_id_eq will never report two invalid frame IDs as
|
||||
being equal, so to get into this block, both the current and
|
||||
previous frame must have valid frame IDs. */
|
||||
if (!frame_id_eq (get_frame_id (get_current_frame ()), step_frame_id)
|
||||
&& frame_id_eq (frame_unwind_id (get_current_frame ()), step_frame_id))
|
||||
if (!frame_id_eq (get_frame_id (get_current_frame ()),
|
||||
ecs->event_thread->step_frame_id)
|
||||
&& frame_id_eq (frame_unwind_id (get_current_frame ()),
|
||||
ecs->event_thread->step_frame_id))
|
||||
{
|
||||
CORE_ADDR real_stop_pc;
|
||||
|
||||
|
@ -3109,8 +3097,9 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
fprintf_unfiltered (gdb_stdlog, "infrun: stepped into subroutine\n");
|
||||
|
||||
if ((step_over_calls == STEP_OVER_NONE)
|
||||
|| ((step_range_end == 1)
|
||||
&& in_prologue (prev_pc, ecs->stop_func_start)))
|
||||
|| ((ecs->event_thread->step_range_end == 1)
|
||||
&& in_prologue (ecs->event_thread->prev_pc,
|
||||
ecs->stop_func_start)))
|
||||
{
|
||||
/* I presume that step_over_calls is only 0 when we're
|
||||
supposed to be stepping at the assembly language level
|
||||
|
@ -3268,7 +3257,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
}
|
||||
}
|
||||
|
||||
if (step_range_end == 1)
|
||||
if (ecs->event_thread->step_range_end == 1)
|
||||
{
|
||||
/* It is stepi or nexti. We always want to stop stepping after
|
||||
one instruction. */
|
||||
|
@ -3295,8 +3284,8 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
}
|
||||
|
||||
if ((stop_pc == stop_pc_sal.pc)
|
||||
&& (tss->current_line != stop_pc_sal.line
|
||||
|| tss->current_symtab != stop_pc_sal.symtab))
|
||||
&& (ecs->event_thread->current_line != stop_pc_sal.line
|
||||
|| ecs->event_thread->current_symtab != stop_pc_sal.symtab))
|
||||
{
|
||||
/* We are at the start of a different line. So stop. Note that
|
||||
we don't stop if we step into the middle of a different line.
|
||||
|
@ -3317,11 +3306,11 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
new line in mid-statement, we continue stepping. This makes
|
||||
things like for(;;) statements work better.) */
|
||||
|
||||
step_range_start = stop_pc_sal.pc;
|
||||
step_range_end = stop_pc_sal.end;
|
||||
step_frame_id = get_frame_id (get_current_frame ());
|
||||
tss->current_line = stop_pc_sal.line;
|
||||
tss->current_symtab = stop_pc_sal.symtab;
|
||||
ecs->event_thread->step_range_start = stop_pc_sal.pc;
|
||||
ecs->event_thread->step_range_end = stop_pc_sal.end;
|
||||
ecs->event_thread->step_frame_id = get_frame_id (get_current_frame ());
|
||||
ecs->event_thread->current_line = stop_pc_sal.line;
|
||||
ecs->event_thread->current_symtab = stop_pc_sal.symtab;
|
||||
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog, "infrun: keep going\n");
|
||||
|
@ -3331,11 +3320,11 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
|
|||
/* Are we in the middle of stepping? */
|
||||
|
||||
static int
|
||||
currently_stepping (struct thread_stepping_state *tss)
|
||||
currently_stepping (struct thread_info *tp)
|
||||
{
|
||||
return (((step_range_end && step_resume_breakpoint == NULL)
|
||||
|| stepping_over_breakpoint)
|
||||
|| tss->stepping_through_solib_after_catch
|
||||
return (((tp->step_range_end && tp->step_resume_breakpoint == NULL)
|
||||
|| tp->trap_expected)
|
||||
|| tp->stepping_through_solib_after_catch
|
||||
|| bpstat_should_step ());
|
||||
}
|
||||
|
||||
|
@ -3409,7 +3398,7 @@ step_into_function (struct execution_control_state *ecs)
|
|||
insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id);
|
||||
|
||||
/* And make sure stepping stops right away then. */
|
||||
step_range_end = step_range_start;
|
||||
ecs->event_thread->step_range_end = ecs->event_thread->step_range_start;
|
||||
}
|
||||
keep_going (ecs);
|
||||
}
|
||||
|
@ -3424,15 +3413,15 @@ insert_step_resume_breakpoint_at_sal (struct symtab_and_line sr_sal,
|
|||
/* There should never be more than one step-resume or longjmp-resume
|
||||
breakpoint per thread, so we should never be setting a new
|
||||
step_resume_breakpoint when one is already active. */
|
||||
gdb_assert (step_resume_breakpoint == NULL);
|
||||
gdb_assert (inferior_thread ()->step_resume_breakpoint == NULL);
|
||||
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"infrun: inserting step-resume breakpoint at 0x%s\n",
|
||||
paddr_nz (sr_sal.pc));
|
||||
|
||||
step_resume_breakpoint = set_momentary_breakpoint (sr_sal, sr_id,
|
||||
bp_step_resume);
|
||||
inferior_thread ()->step_resume_breakpoint
|
||||
= set_momentary_breakpoint (sr_sal, sr_id, bp_step_resume);
|
||||
}
|
||||
|
||||
/* Insert a "step-resume breakpoint" at RETURN_FRAME.pc. This is used
|
||||
|
@ -3501,14 +3490,14 @@ insert_longjmp_resume_breakpoint (CORE_ADDR pc)
|
|||
/* There should never be more than one step-resume or longjmp-resume
|
||||
breakpoint per thread, so we should never be setting a new
|
||||
longjmp_resume_breakpoint when one is already active. */
|
||||
gdb_assert (step_resume_breakpoint == NULL);
|
||||
gdb_assert (inferior_thread ()->step_resume_breakpoint == NULL);
|
||||
|
||||
if (debug_infrun)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"infrun: inserting longjmp-resume breakpoint at 0x%s\n",
|
||||
paddr_nz (pc));
|
||||
|
||||
step_resume_breakpoint =
|
||||
inferior_thread ()->step_resume_breakpoint =
|
||||
set_momentary_breakpoint_at_pc (pc, bp_longjmp_resume);
|
||||
}
|
||||
|
||||
|
@ -3530,17 +3519,17 @@ static void
|
|||
keep_going (struct execution_control_state *ecs)
|
||||
{
|
||||
/* Save the pc before execution, to compare with pc after stop. */
|
||||
prev_pc = read_pc (); /* Might have been DECR_AFTER_BREAK */
|
||||
ecs->event_thread->prev_pc = read_pc (); /* Might have been DECR_AFTER_BREAK */
|
||||
|
||||
/* If we did not do break;, it means we should keep running the
|
||||
inferior and not return to debugger. */
|
||||
|
||||
if (stepping_over_breakpoint && stop_signal != TARGET_SIGNAL_TRAP)
|
||||
if (ecs->event_thread->trap_expected && stop_signal != TARGET_SIGNAL_TRAP)
|
||||
{
|
||||
/* We took a signal (which we are supposed to pass through to
|
||||
the inferior, else we'd have done a break above) and we
|
||||
haven't yet gotten our trap. Simply continue. */
|
||||
resume (currently_stepping (tss), stop_signal);
|
||||
the inferior, else we'd not get here) and we haven't yet
|
||||
gotten our trap. Simply continue. */
|
||||
resume (currently_stepping (ecs->event_thread), stop_signal);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3557,7 +3546,7 @@ keep_going (struct execution_control_state *ecs)
|
|||
already inserted breakpoints. Therefore, we don't
|
||||
care if breakpoints were already inserted, or not. */
|
||||
|
||||
if (tss->stepping_over_breakpoint)
|
||||
if (ecs->event_thread->stepping_over_breakpoint)
|
||||
{
|
||||
if (! use_displaced_stepping (current_gdbarch))
|
||||
/* Since we can't do a displaced step, we have to remove
|
||||
|
@ -3581,7 +3570,7 @@ keep_going (struct execution_control_state *ecs)
|
|||
}
|
||||
}
|
||||
|
||||
stepping_over_breakpoint = tss->stepping_over_breakpoint;
|
||||
ecs->event_thread->trap_expected = ecs->event_thread->stepping_over_breakpoint;
|
||||
|
||||
/* Do not deliver SIGNAL_TRAP (except when the user explicitly
|
||||
specifies that such a signal should be delivered to the
|
||||
|
@ -3599,7 +3588,7 @@ keep_going (struct execution_control_state *ecs)
|
|||
stop_signal = TARGET_SIGNAL_0;
|
||||
|
||||
|
||||
resume (currently_stepping (tss), stop_signal);
|
||||
resume (currently_stepping (ecs->event_thread), stop_signal);
|
||||
}
|
||||
|
||||
prepare_to_wait (ecs);
|
||||
|
@ -3864,7 +3853,7 @@ Further execution is probably impossible.\n"));
|
|||
(or should) carry around the function and does (or
|
||||
should) use that when doing a frame comparison. */
|
||||
if (stop_step
|
||||
&& frame_id_eq (step_frame_id,
|
||||
&& frame_id_eq (inferior_thread ()->step_frame_id,
|
||||
get_frame_id (get_current_frame ()))
|
||||
&& step_start_function == find_pc_function (stop_pc))
|
||||
source_flag = SRC_LINE; /* finished step, just print source line */
|
||||
|
@ -4372,16 +4361,17 @@ struct inferior_status *
|
|||
save_inferior_status (int restore_stack_info)
|
||||
{
|
||||
struct inferior_status *inf_status = XMALLOC (struct inferior_status);
|
||||
struct thread_info *tp = inferior_thread ();
|
||||
|
||||
inf_status->stop_signal = stop_signal;
|
||||
inf_status->stop_pc = stop_pc;
|
||||
inf_status->stop_step = stop_step;
|
||||
inf_status->stop_stack_dummy = stop_stack_dummy;
|
||||
inf_status->stopped_by_random_signal = stopped_by_random_signal;
|
||||
inf_status->stepping_over_breakpoint = stepping_over_breakpoint;
|
||||
inf_status->step_range_start = step_range_start;
|
||||
inf_status->step_range_end = step_range_end;
|
||||
inf_status->step_frame_id = step_frame_id;
|
||||
inf_status->stepping_over_breakpoint = tp->trap_expected;
|
||||
inf_status->step_range_start = tp->step_range_start;
|
||||
inf_status->step_range_end = tp->step_range_end;
|
||||
inf_status->step_frame_id = tp->step_frame_id;
|
||||
inf_status->step_over_calls = step_over_calls;
|
||||
inf_status->stop_after_trap = stop_after_trap;
|
||||
inf_status->stop_soon = stop_soon;
|
||||
|
@ -4425,15 +4415,17 @@ restore_selected_frame (void *args)
|
|||
void
|
||||
restore_inferior_status (struct inferior_status *inf_status)
|
||||
{
|
||||
struct thread_info *tp = inferior_thread ();
|
||||
|
||||
stop_signal = inf_status->stop_signal;
|
||||
stop_pc = inf_status->stop_pc;
|
||||
stop_step = inf_status->stop_step;
|
||||
stop_stack_dummy = inf_status->stop_stack_dummy;
|
||||
stopped_by_random_signal = inf_status->stopped_by_random_signal;
|
||||
stepping_over_breakpoint = inf_status->stepping_over_breakpoint;
|
||||
step_range_start = inf_status->step_range_start;
|
||||
step_range_end = inf_status->step_range_end;
|
||||
step_frame_id = inf_status->step_frame_id;
|
||||
tp->trap_expected = inf_status->stepping_over_breakpoint;
|
||||
tp->step_range_start = inf_status->step_range_start;
|
||||
tp->step_range_end = inf_status->step_range_end;
|
||||
tp->step_frame_id = inf_status->step_frame_id;
|
||||
step_over_calls = inf_status->step_over_calls;
|
||||
stop_after_trap = inf_status->stop_after_trap;
|
||||
stop_soon = inf_status->stop_soon;
|
||||
|
|
|
@ -774,8 +774,20 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child)
|
|||
}
|
||||
else
|
||||
{
|
||||
struct thread_info *last_tp = find_thread_pid (last_ptid);
|
||||
struct thread_info *tp;
|
||||
char child_pid_spelling[40];
|
||||
|
||||
/* Copy user stepping state to the new inferior thread. */
|
||||
struct breakpoint *step_resume_breakpoint = last_tp->step_resume_breakpoint;
|
||||
CORE_ADDR step_range_start = last_tp->step_range_start;
|
||||
CORE_ADDR step_range_end = last_tp->step_range_end;
|
||||
struct frame_id step_frame_id = last_tp->step_frame_id;
|
||||
|
||||
/* Otherwise, deleting the parent would get rid of this
|
||||
breakpoint. */
|
||||
last_tp->step_resume_breakpoint = NULL;
|
||||
|
||||
/* Needed to keep the breakpoint lists in sync. */
|
||||
if (! has_vforked)
|
||||
detach_breakpoints (child_pid);
|
||||
|
@ -832,6 +844,12 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child)
|
|||
linux_nat_switch_fork (inferior_ptid);
|
||||
check_for_thread_db ();
|
||||
|
||||
tp = inferior_thread ();
|
||||
tp->step_resume_breakpoint = step_resume_breakpoint;
|
||||
tp->step_range_start = step_range_start;
|
||||
tp->step_range_end = step_range_end;
|
||||
tp->step_frame_id = step_frame_id;
|
||||
|
||||
/* Reset breakpoints in the child as appropriate. */
|
||||
follow_inferior_reset_breakpoints ();
|
||||
}
|
||||
|
|
71
gdb/thread.c
71
gdb/thread.c
|
@ -74,20 +74,21 @@ enum thread_state
|
|||
static enum thread_state main_thread_state = THREAD_STOPPED;
|
||||
static int main_thread_executing = 0;
|
||||
|
||||
void
|
||||
delete_step_resume_breakpoint (void *arg)
|
||||
extern struct thread_info*
|
||||
inferior_thread (void)
|
||||
{
|
||||
struct breakpoint **breakpointp = (struct breakpoint **) arg;
|
||||
struct thread_info *tp;
|
||||
struct thread_info *tp = find_thread_pid (inferior_ptid);
|
||||
gdb_assert (tp);
|
||||
return tp;
|
||||
}
|
||||
|
||||
if (*breakpointp != NULL)
|
||||
void
|
||||
delete_step_resume_breakpoint (struct thread_info *tp)
|
||||
{
|
||||
if (tp && tp->step_resume_breakpoint)
|
||||
{
|
||||
delete_breakpoint (*breakpointp);
|
||||
for (tp = thread_list; tp; tp = tp->next)
|
||||
if (tp->step_resume_breakpoint == *breakpointp)
|
||||
tp->step_resume_breakpoint = NULL;
|
||||
|
||||
*breakpointp = NULL;
|
||||
delete_breakpoint (tp->step_resume_breakpoint);
|
||||
tp->step_resume_breakpoint = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -442,17 +443,6 @@ gdb_list_thread_ids (struct ui_out *uiout, char **error_message)
|
|||
|
||||
void
|
||||
load_infrun_state (ptid_t ptid,
|
||||
CORE_ADDR *prev_pc,
|
||||
int *trap_expected,
|
||||
struct breakpoint **step_resume_breakpoint,
|
||||
CORE_ADDR *step_range_start,
|
||||
CORE_ADDR *step_range_end,
|
||||
struct frame_id *step_frame_id,
|
||||
int *stepping_over_breakpoint,
|
||||
int *stepping_through_solib_after_catch,
|
||||
bpstat *stepping_through_solib_catchpoints,
|
||||
int *current_line,
|
||||
struct symtab **current_symtab,
|
||||
struct continuation **continuations,
|
||||
struct continuation **intermediate_continuations,
|
||||
int *proceed_to_finish,
|
||||
|
@ -470,20 +460,6 @@ load_infrun_state (ptid_t ptid,
|
|||
if (tp == NULL)
|
||||
return;
|
||||
|
||||
*prev_pc = tp->prev_pc;
|
||||
*trap_expected = tp->trap_expected;
|
||||
*step_resume_breakpoint = tp->step_resume_breakpoint;
|
||||
*step_range_start = tp->step_range_start;
|
||||
*step_range_end = tp->step_range_end;
|
||||
*step_frame_id = tp->step_frame_id;
|
||||
*stepping_over_breakpoint = tp->stepping_over_breakpoint;
|
||||
*stepping_through_solib_after_catch =
|
||||
tp->stepping_through_solib_after_catch;
|
||||
*stepping_through_solib_catchpoints =
|
||||
tp->stepping_through_solib_catchpoints;
|
||||
*current_line = tp->current_line;
|
||||
*current_symtab = tp->current_symtab;
|
||||
|
||||
/* In all-stop mode, these are global state, while in non-stop mode,
|
||||
they are per thread. */
|
||||
if (non_stop)
|
||||
|
@ -509,17 +485,6 @@ load_infrun_state (ptid_t ptid,
|
|||
|
||||
void
|
||||
save_infrun_state (ptid_t ptid,
|
||||
CORE_ADDR prev_pc,
|
||||
int trap_expected,
|
||||
struct breakpoint *step_resume_breakpoint,
|
||||
CORE_ADDR step_range_start,
|
||||
CORE_ADDR step_range_end,
|
||||
const struct frame_id *step_frame_id,
|
||||
int stepping_over_breakpoint,
|
||||
int stepping_through_solib_after_catch,
|
||||
bpstat stepping_through_solib_catchpoints,
|
||||
int current_line,
|
||||
struct symtab *current_symtab,
|
||||
struct continuation *continuations,
|
||||
struct continuation *intermediate_continuations,
|
||||
int proceed_to_finish,
|
||||
|
@ -537,18 +502,6 @@ save_infrun_state (ptid_t ptid,
|
|||
if (tp == NULL)
|
||||
return;
|
||||
|
||||
tp->prev_pc = prev_pc;
|
||||
tp->trap_expected = trap_expected;
|
||||
tp->step_resume_breakpoint = step_resume_breakpoint;
|
||||
tp->step_range_start = step_range_start;
|
||||
tp->step_range_end = step_range_end;
|
||||
tp->step_frame_id = (*step_frame_id);
|
||||
tp->stepping_over_breakpoint = stepping_over_breakpoint;
|
||||
tp->stepping_through_solib_after_catch = stepping_through_solib_after_catch;
|
||||
tp->stepping_through_solib_catchpoints = stepping_through_solib_catchpoints;
|
||||
tp->current_line = current_line;
|
||||
tp->current_symtab = current_symtab;
|
||||
|
||||
/* In all-stop mode, these are global state, while in non-stop mode,
|
||||
they are per thread. */
|
||||
if (non_stop)
|
||||
|
|
Loading…
Reference in a new issue