#endif
/* For SVR4 shared libraries, each call goes through a small piece of
- trampoline code in the ".init" section. IN_SOLIB_TRAMPOLINE evaluates
+ trampoline code in the ".plt" section. IN_SOLIB_TRAMPOLINE evaluates
to nonzero if we are current stopped in one of these. */
#ifndef IN_SOLIB_TRAMPOLINE
#define IN_SOLIB_TRAMPOLINE(pc,name) 0
if (breakpoint_here_p (read_pc ()))
oneproc = 1;
+
+#ifdef STEP_SKIPS_DELAY
+ /* Check breakpoint_here_p first, because breakpoint_here_p is fast
+ (it just checks internal GDB data structures) and STEP_SKIPS_DELAY
+ is slow (it needs to read memory from the target). */
+ if (breakpoint_here_p (read_pc () + 4)
+ && STEP_SKIPS_DELAY (read_pc ()))
+ oneproc = 1;
+#endif /* STEP_SKIPS_DELAY */
}
else
write_pc (addr);
static CORE_ADDR prev_sp;
static CORE_ADDR prev_func_start;
static char *prev_func_name;
+static CORE_ADDR prev_frame_address;
\f
/* Start remote-debugging of a machine over a serial link. */
prev_sp = 0;
prev_func_start = 0;
prev_func_name = NULL;
+ prev_frame_address = 0;
trap_expected_after_continue = 0;
breakpoints_inserted = 0;
struct symtab *current_symtab;
int handling_longjmp = 0; /* FIXME */
struct breakpoint *step_resume_breakpoint = NULL;
+ struct breakpoint *through_sigtramp_breakpoint = NULL;
int pid;
old_cleanups = make_cleanup (delete_breakpoint_current_contents,
&step_resume_breakpoint);
+ make_cleanup (delete_breakpoint_current_contents,
+ &through_sigtramp_breakpoint);
sal = find_pc_line(prev_pc, 0);
current_line = sal.line;
current_symtab = sal.symtab;
/* Are we stepping? */
-#define CURRENTLY_STEPPING() ((step_resume_breakpoint == NULL \
- && !handling_longjmp \
- && (step_range_end \
- || trap_expected)) \
- || bpstat_should_step ())
+#define CURRENTLY_STEPPING() \
+ ((through_sigtramp_breakpoint == NULL \
+ && !handling_longjmp \
+ && ((step_range_end && step_resume_breakpoint == NULL) \
+ || trap_expected)) \
+ || bpstat_should_step ())
while (1)
{
delete_breakpoint (step_resume_breakpoint);
step_resume_breakpoint = NULL;
}
+
+ /* Not sure whether we need to blow this away too,
+ but probably it is like the step-resume
+ breakpoint. */
+ if (through_sigtramp_breakpoint)
+ {
+ delete_breakpoint (through_sigtramp_breakpoint);
+ through_sigtramp_breakpoint = NULL;
+ }
prev_pc = 0;
prev_sp = 0;
prev_func_name = NULL;
single_step (0); /* This actually cleans up the ss */
#endif /* NO_SINGLE_STEP */
-/* If PC is pointing at a nullified instruction, then step beyond it so that
- the user won't be confused when GDB appears to be ready to execute it. */
+ /* If PC is pointing at a nullified instruction, then step beyond
+ it so that the user won't be confused when GDB appears to be ready
+ to execute it. */
if (INSTRUCTION_NULLIFIED)
{
continue;
}
- set_current_frame ( create_new_frame (read_fp (), stop_pc));
+ set_current_frame (create_new_frame (read_fp (), stop_pc));
+ select_frame (get_current_frame (), 0);
+
+#ifdef HAVE_STEPPABLE_WATCHPOINT
+ /* It may not be necessary to disable the watchpoint to stop over
+ it. For example, the PA can (with some kernel cooperation)
+ single step over a watchpoint without disabling the watchpoint. */
+ if (STOPPED_BY_WATCHPOINT (w))
+ {
+ resume (1, 0);
+ continue;
+ }
+#endif
+
+#ifdef HAVE_NONSTEPPABLE_WATCHPOINT
+ /* It is far more common to need to disable a watchpoint
+ to step the inferior over it. FIXME. What else might
+ a debug register or page protection watchpoint scheme need
+ here? */
+ if (STOPPED_BY_WATCHPOINT (w))
+ {
+ remove_breakpoints ();
+ resume (1, 0);
+ insert_breakpoints ();
+ continue;
+ }
+#endif
stop_frame_address = FRAME_FP (get_current_frame ());
stop_sp = read_sp ();
if just proceeded over a breakpoint.
However, if we are trying to proceed over a breakpoint
- and end up in sigtramp, then step_resume_breakpoint
+ and end up in sigtramp, then through_sigtramp_breakpoint
will be set and we should check whether we've hit the
step breakpoint. */
if (stop_signal == TARGET_SIGNAL_TRAP && trap_expected
- && step_resume_breakpoint == NULL)
+ && through_sigtramp_breakpoint == NULL)
bpstat_clear (&stop_bpstat);
else
{
{
delete_breakpoint (step_resume_breakpoint);
step_resume_breakpoint = NULL;
- what.step_resume = 0;
+ }
+ /* Not sure whether we need to blow this away too, but probably
+ it is like the step-resume breakpoint. */
+ if (through_sigtramp_breakpoint != NULL)
+ {
+ delete_breakpoint (through_sigtramp_breakpoint);
+ through_sigtramp_breakpoint = NULL;
}
#if 0
case BPSTAT_WHAT_STOP_NOISY:
stop_print_frame = 1;
- /* We are about to nuke the step_resume_breakpoint via the
- cleanup chain, so no need to worry about it here. */
+
+ /* We are about to nuke the step_resume_breakpoint and
+ through_sigtramp_breakpoint via the cleanup chain, so
+ no need to worry about it here. */
+
goto stop_stepping;
case BPSTAT_WHAT_STOP_SILENT:
stop_print_frame = 0;
- /* We are about to nuke the step_resume_breakpoint via the
- cleanup chain, so no need to worry about it here. */
- goto stop_stepping;
- case BPSTAT_WHAT_LAST:
- /* Not a real code, but listed here to shut up gcc -Wall. */
+ /* We are about to nuke the step_resume_breakpoint and
+ through_sigtramp_breakpoint via the cleanup chain, so
+ no need to worry about it here. */
- case BPSTAT_WHAT_KEEP_CHECKING:
- break;
- }
+ goto stop_stepping;
- if (what.step_resume)
- {
+ case BPSTAT_WHAT_STEP_RESUME:
delete_breakpoint (step_resume_breakpoint);
step_resume_breakpoint = NULL;
+ break;
+
+ case BPSTAT_WHAT_THROUGH_SIGTRAMP:
+ delete_breakpoint (through_sigtramp_breakpoint);
+ through_sigtramp_breakpoint = NULL;
/* If were waiting for a trap, hitting the step_resume_break
doesn't count as getting it. */
if (trap_expected)
another_trap = 1;
+ break;
+
+ case BPSTAT_WHAT_LAST:
+ /* Not a real code, but listed here to shut up gcc -Wall. */
+
+ case BPSTAT_WHAT_KEEP_CHECKING:
+ break;
}
}
/* Having a step-resume breakpoint overrides anything
else having to do with stepping commands until
that breakpoint is reached. */
- /* I suspect this could/should be keep_going, because if the
- check_sigtramp2 check succeeds, then it will put in another
- step_resume_breakpoint, and we aren't (yet) prepared to nest
- them. */
+ /* I'm not sure whether this needs to be check_sigtramp2 or
+ whether it could/should be keep_going. */
goto check_sigtramp2;
if (step_range_end == 0)
if (IN_SIGTRAMP (stop_pc, stop_func_name)
&& !IN_SIGTRAMP (prev_pc, prev_func_name))
{
+ /* We've just taken a signal; go until we are back to
+ the point where we took it and one more. */
+
/* This code is needed at least in the following case:
The user types "next" and then a signal arrives (before
the "next" is done). */
- /* We've just taken a signal; go until we are back to
- the point where we took it and one more. */
+
+ /* Note that if we are stopped at a breakpoint, then we need
+ the step_resume breakpoint to override any breakpoints at
+ the same location, so that we will still step over the
+ breakpoint even though the signal happened. */
+
{
struct symtab_and_line sr_sal;
sr_sal.pc = prev_pc;
sr_sal.symtab = NULL;
sr_sal.line = 0;
+ /* We could probably be setting the frame to
+ prev_frame_address; the reason we don't is that it didn't used
+ to exist. */
step_resume_breakpoint =
- set_momentary_breakpoint (sr_sal, get_current_frame (),
- bp_step_resume);
+ set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
if (breakpoints_inserted)
insert_breakpoints ();
}
step_resume_breakpoint =
set_momentary_breakpoint (sr_sal, get_current_frame (),
bp_step_resume);
+ step_resume_breakpoint->frame = prev_frame_address;
if (breakpoints_inserted)
insert_breakpoints ();
}
sr_sal.pc = prev_pc;
sr_sal.symtab = NULL;
sr_sal.line = 0;
- step_resume_breakpoint =
- set_momentary_breakpoint (sr_sal, get_current_frame (),
- bp_step_resume);
+ /* We perhaps could set the frame if we kept track of what
+ the frame corresponding to prev_pc was. But we don't,
+ so don't. */
+ through_sigtramp_breakpoint =
+ set_momentary_breakpoint (sr_sal, NULL, bp_through_sigtramp);
if (breakpoints_inserted)
insert_breakpoints ();
function. */
prev_func_name = stop_func_name;
prev_sp = stop_sp;
+ prev_frame_address = stop_frame_address;
/* If we did not do break;, it means we should keep
running the inferior and not return to debugger. */
to one-proceed past a breakpoint. */
/* If we've just finished a special step resume and we don't
want to hit a breakpoint, pull em out. */
- if (step_resume_breakpoint == NULL &&
- remove_breakpoints_on_following_step)
+ if (step_resume_breakpoint == NULL
+ && through_sigtramp_breakpoint == NULL
+ && remove_breakpoints_on_following_step)
{
remove_breakpoints_on_following_step = 0;
remove_breakpoints ();
breakpoints_inserted = 0;
}
else if (!breakpoints_inserted &&
- (step_resume_breakpoint != NULL || !another_trap))
+ (through_sigtramp_breakpoint != NULL || !another_trap))
{
breakpoints_failed = insert_breakpoints ();
if (breakpoints_failed)
prev_func_start = stop_func_start;
prev_func_name = stop_func_name;
prev_sp = stop_sp;
+ prev_frame_address = stop_frame_address;
}
do_cleanups (old_cleanups);
}
if we have one. */
if (!stop_stack_dummy)
{
- select_frame (get_current_frame (), 0);
-
if (stop_print_frame)
{
int source_only;
POP_FRAME ends with a setting of the current frame, so we
can use that next. */
POP_FRAME;
+ /* Set stop_pc to what it was before we called the function. Can't rely
+ on restore_inferior_status because that only gets called if we don't
+ stop in the called function. */
+ stop_pc = read_pc();
select_frame (get_current_frame (), 0);
}
}
}
printf_filtered ("\n");
- for (oursig = 0; oursig < TARGET_SIGNAL_LAST; ++oursig)
+ /* These ugly casts brought to you by the native VAX compiler. */
+ for (oursig = TARGET_SIGNAL_FIRST;
+ (int)oursig < (int)TARGET_SIGNAL_LAST;
+ oursig = (enum target_signal)((int)oursig + 1))
{
QUIT;