static int stop_on_solib_events;
#endif
-#ifdef HP_OS_BUG
-/* Nonzero if the next time we try to continue the inferior, it will
- step one instruction and generate a spurious trace trap.
- This is used to compensate for a bug in HP-UX. */
-
-static int trap_expected_after_continue;
-#endif
-
/* Nonzero means expecting a trace trap
and should stop the inferior and return silently when it happens. */
if (prepare_to_proceed () && breakpoint_here_p (read_pc ()))
oneproc = 1;
-#ifdef HP_OS_BUG
- if (trap_expected_after_continue)
- {
- /* If (step == 0), a trap will be automatically generated after
- the first instruction is executed. Force step one
- instruction to clear this condition. This should not occur
- if step is nonzero, but it is harmless in that case. */
- oneproc = 1;
- trap_expected_after_continue = 0;
- }
-#endif /* HP_OS_BUG */
-
if (oneproc)
/* We will get a trace trap after one instruction.
Continue it automatically and insert breakpoints then. */
/* These are meaningless until the first time through wait_for_inferior. */
prev_pc = 0;
-#ifdef HP_OS_BUG
- trap_expected_after_continue = 0;
-#endif
breakpoints_inserted = 0;
breakpoint_init_inferior (inf_starting);
int handling_longjmp; /* FIXME */
ptid_t ptid;
ptid_t saved_inferior_ptid;
- int update_step_sp;
int stepping_through_solib_after_catch;
bpstat stepping_through_solib_catchpoints;
int enable_hw_watchpoints_after_wait;
void init_execution_control_state (struct execution_control_state *ecs);
-static void handle_step_into_function (struct execution_control_state *ecs);
void handle_inferior_event (struct execution_control_state *ecs);
static void step_into_function (struct execution_control_state *ecs);
ecs->random_signal = 0;
ecs->remove_breakpoints_on_following_step = 0;
ecs->handling_longjmp = 0; /* FIXME */
- ecs->update_step_sp = 0;
ecs->stepping_through_solib_after_catch = 0;
ecs->stepping_through_solib_catchpoints = NULL;
ecs->enable_hw_watchpoints_after_wait = 0;
ecs->stepping_through_solib_after_catch,
ecs->stepping_through_solib_catchpoints,
ecs->stepping_through_sigtramp,
- ecs->current_line, ecs->current_symtab, step_sp);
+ ecs->current_line, ecs->current_symtab);
/* Load infrun state for the new thread. */
load_infrun_state (ecs->ptid, &prev_pc,
&ecs->stepping_through_solib_after_catch,
&ecs->stepping_through_solib_catchpoints,
&ecs->stepping_through_sigtramp,
- &ecs->current_line, &ecs->current_symtab, &step_sp);
+ &ecs->current_line, &ecs->current_symtab);
}
inferior_ptid = ecs->ptid;
}
-/* Handle the inferior event in the cases when we just stepped
- into a function. */
-
-static void
-handle_step_into_function (struct execution_control_state *ecs)
-{
- CORE_ADDR real_stop_pc;
-
- if ((step_over_calls == STEP_OVER_NONE)
- || ((step_range_end == 1)
- && in_prologue (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
- ("stepi"). Just stop. */
- /* Also, maybe we just did a "nexti" inside a prolog,
- so we thought it was a subroutine call but it was not.
- Stop as well. FENN */
- stop_step = 1;
- print_stop_reason (END_STEPPING_RANGE, 0);
- stop_stepping (ecs);
- return;
- }
-
- if (step_over_calls == STEP_OVER_ALL || IGNORE_HELPER_CALL (stop_pc))
- {
- /* We're doing a "next", set a breakpoint at callee's return
- address (the address at which the caller will resume). */
- insert_step_resume_breakpoint (get_prev_frame (get_current_frame ()),
- ecs);
- keep_going (ecs);
- return;
- }
-
- /* If we are in a function call trampoline (a stub between
- the calling routine and the real function), locate the real
- function. That's what tells us (a) whether we want to step
- into it at all, and (b) what prologue we want to run to
- the end of, if we do step into it. */
- real_stop_pc = skip_language_trampoline (stop_pc);
- if (real_stop_pc == 0)
- real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
- if (real_stop_pc != 0)
- ecs->stop_func_start = real_stop_pc;
-
- /* If we have line number information for the function we
- are thinking of stepping into, step into it.
-
- If there are several symtabs at that PC (e.g. with include
- files), just want to know whether *any* of them have line
- numbers. find_pc_line handles this. */
- {
- struct symtab_and_line tmp_sal;
-
- tmp_sal = find_pc_line (ecs->stop_func_start, 0);
- if (tmp_sal.line != 0)
- {
- step_into_function (ecs);
- return;
- }
- }
-
- /* If we have no line number and the step-stop-if-no-debug
- is set, we stop the step so that the user has a chance to
- switch in assembly mode. */
- if (step_over_calls == STEP_OVER_UNDEBUGGABLE && step_stop_if_no_debug)
- {
- stop_step = 1;
- print_stop_reason (END_STEPPING_RANGE, 0);
- stop_stepping (ecs);
- return;
- }
-
- /* Set a breakpoint at callee's return address (the address at which
- the caller will resume). */
- insert_step_resume_breakpoint (get_prev_frame (get_current_frame ()), ecs);
- keep_going (ecs);
- return;
-}
-
static void
adjust_pc_after_break (struct execution_control_state *ecs)
{
- CORE_ADDR stop_pc;
+ CORE_ADDR breakpoint_pc;
/* If this target does not decrement the PC after breakpoints, then
we have nothing to do. */
if (ecs->ws.value.sig != TARGET_SIGNAL_TRAP)
return;
- /* Find the location where (if we've hit a breakpoint) the breakpoint would
- be. */
- stop_pc = read_pc_pid (ecs->ptid) - DECR_PC_AFTER_BREAK;
-
- /* If we're software-single-stepping, then assume this is a breakpoint.
- NOTE drow/2004-01-17: This doesn't check that the PC matches, or that
- we're even in the right thread. The software-single-step code needs
- some modernization.
-
- If we're not software-single-stepping, then we first check that there
- is an enabled software breakpoint at this address. If there is, and
- we weren't using hardware-single-step, then we've hit the breakpoint.
-
- If we were using hardware-single-step, we check prev_pc; if we just
- stepped over an inserted software breakpoint, then we should decrement
- the PC and eventually report hitting the breakpoint. The prev_pc check
- prevents us from decrementing the PC if we just stepped over a jump
- instruction and landed on the instruction after a breakpoint.
-
- The last bit checks that we didn't hit a breakpoint in a signal handler
- without an intervening stop in sigtramp, which is detected by a new
- stack pointer value below any usual function calling stack adjustments.
-
- NOTE drow/2004-01-17: I'm not sure that this is necessary. The check
- predates checking for software single step at the same time. Also,
- if we've moved into a signal handler we should have seen the
- signal. */
-
- if ((SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
- || (software_breakpoint_inserted_here_p (stop_pc)
- && !(currently_stepping (ecs)
- && prev_pc != stop_pc
- && !(step_range_end && INNER_THAN (read_sp (), (step_sp - 16))))))
- write_pc_pid (stop_pc, ecs->ptid);
+ /* Find the location where (if we've hit a breakpoint) the
+ breakpoint would be. */
+ breakpoint_pc = read_pc_pid (ecs->ptid) - DECR_PC_AFTER_BREAK;
+
+ if (SOFTWARE_SINGLE_STEP_P ())
+ {
+ /* When using software single-step, a SIGTRAP can only indicate
+ an inserted breakpoint. This actually makes things
+ easier. */
+ if (singlestep_breakpoints_inserted_p)
+ /* When software single stepping, the instruction at [prev_pc]
+ is never a breakpoint, but the instruction following
+ [prev_pc] (in program execution order) always is. Assume
+ that following instruction was reached and hence a software
+ breakpoint was hit. */
+ write_pc_pid (breakpoint_pc, ecs->ptid);
+ else if (software_breakpoint_inserted_here_p (breakpoint_pc))
+ /* The inferior was free running (i.e., no single-step
+ breakpoints inserted) and it hit a software breakpoint. */
+ write_pc_pid (breakpoint_pc, ecs->ptid);
+ }
+ else
+ {
+ /* When using hardware single-step, a SIGTRAP is reported for
+ both a completed single-step and a software breakpoint. Need
+ to differentiate between the two as the latter needs
+ adjusting but the former does not. */
+ if (currently_stepping (ecs))
+ {
+ if (prev_pc == breakpoint_pc
+ && software_breakpoint_inserted_here_p (breakpoint_pc))
+ /* Hardware single-stepped a software breakpoint (as
+ occures when the inferior is resumed with PC pointing
+ at not-yet-hit software breakpoint). Since the
+ breakpoint really is executed, the inferior needs to be
+ backed up to the breakpoint address. */
+ write_pc_pid (breakpoint_pc, ecs->ptid);
+ }
+ else
+ {
+ if (software_breakpoint_inserted_here_p (breakpoint_pc))
+ /* The inferior was free running (i.e., no hardware
+ single-step and no possibility of a false SIGTRAP) and
+ hit a software breakpoint. */
+ write_pc_pid (breakpoint_pc, ecs->ptid);
+ }
+ }
}
/* Given an execution control state that has been freshly filled in
defined in the file "config/pa/nm-hppah.h", accesses the variable
indirectly. Mutter something rude about the HP merge. */
int sw_single_step_trap_p = 0;
+ int stopped_by_watchpoint = 0;
/* Cache the last pid/waitstatus. */
target_last_wait_ptid = ecs->ptid;
/* If it's a new process, add it to the thread database */
ecs->new_thread_event = (!ptid_equal (ecs->ptid, inferior_ptid)
+ && !ptid_equal (ecs->ptid, minus_one_ptid)
&& !in_thread_list (ecs->ptid));
if (ecs->ws.kind != TARGET_WAITKIND_EXITED
stop_pc = read_pc ();
- stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
+ stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid, 0);
ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
ecs->saved_inferior_ptid = inferior_ptid;
inferior_ptid = ecs->ptid;
- stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
+ stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid, 0);
ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
inferior_ptid = ecs->saved_inferior_ptid;
/* It may be possible to simply continue after a watchpoint. */
if (HAVE_CONTINUABLE_WATCHPOINT)
- STOPPED_BY_WATCHPOINT (ecs->ws);
+ stopped_by_watchpoint = STOPPED_BY_WATCHPOINT (ecs->ws);
ecs->stop_func_start = 0;
ecs->stop_func_end = 0;
will both be 0 if it doesn't work. */
find_pc_partial_function (stop_pc, &ecs->stop_func_name,
&ecs->stop_func_start, &ecs->stop_func_end);
- ecs->stop_func_start += FUNCTION_START_OFFSET;
+ ecs->stop_func_start += DEPRECATED_FUNCTION_START_OFFSET;
ecs->another_trap = 0;
bpstat_clear (&stop_bpstat);
stop_step = 0;
else
{
/* See if there is a breakpoint at the current PC. */
- stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
+ stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid,
+ stopped_by_watchpoint);
/* Following in case break condition called a
function. */
if (what.call_dummy)
{
stop_stack_dummy = 1;
-#ifdef HP_OS_BUG
- trap_expected_after_continue = 1;
-#endif
}
switch (what.main_action)
return;
}
- if (step_over_calls == STEP_OVER_UNDEBUGGABLE
- && ecs->stop_func_name == NULL)
- {
- /* There is no symbol, not even a minimal symbol, corresponding
- to the address where we just stopped. So we just stepped
- inside undebuggable code. Since we want to step over this
- kind of code, we keep going until the inferior returns from
- the current function. */
- handle_step_into_function (ecs);
- return;
- }
-
- /* We can't update step_sp every time through the loop, because
- reading the stack pointer would slow down stepping too much.
- But we can update it every time we leave the step range. */
- ecs->update_step_sp = 1;
-
if (step_range_end != 1
&& (step_over_calls == STEP_OVER_UNDEBUGGABLE
|| step_over_calls == STEP_OVER_ALL)
return;
}
- if (frame_id_eq (get_frame_id (get_prev_frame (get_current_frame ())),
+ if (frame_id_eq (frame_unwind_id (get_current_frame ()),
step_frame_id))
{
/* It's a subroutine call. */
- handle_step_into_function (ecs);
- return;
- }
+ CORE_ADDR real_stop_pc;
+
+ if ((step_over_calls == STEP_OVER_NONE)
+ || ((step_range_end == 1)
+ && in_prologue (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
+ ("stepi"). Just stop. */
+ /* Also, maybe we just did a "nexti" inside a prolog, so we
+ thought it was a subroutine call but it was not. Stop as
+ well. FENN */
+ stop_step = 1;
+ print_stop_reason (END_STEPPING_RANGE, 0);
+ stop_stepping (ecs);
+ return;
+ }
+
+ if (step_over_calls == STEP_OVER_ALL || IGNORE_HELPER_CALL (stop_pc))
+ {
+ /* We're doing a "next", set a breakpoint at callee's return
+ address (the address at which the caller will
+ resume). */
+ insert_step_resume_breakpoint (get_prev_frame (get_current_frame ()),
+ ecs);
+ keep_going (ecs);
+ return;
+ }
+
+ /* If we are in a function call trampoline (a stub between the
+ calling routine and the real function), locate the real
+ function. That's what tells us (a) whether we want to step
+ into it at all, and (b) what prologue we want to run to the
+ end of, if we do step into it. */
+ real_stop_pc = skip_language_trampoline (stop_pc);
+ if (real_stop_pc == 0)
+ real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
+ if (real_stop_pc != 0)
+ ecs->stop_func_start = real_stop_pc;
+
+ if (IN_SOLIB_DYNSYM_RESOLVE_CODE (ecs->stop_func_start))
+ {
+ struct symtab_and_line sr_sal;
+ init_sal (&sr_sal);
+ sr_sal.pc = ecs->stop_func_start;
- /* We've wandered out of the step range. */
+ check_for_old_step_resume_breakpoint ();
+ step_resume_breakpoint =
+ set_momentary_breakpoint (sr_sal, null_frame_id, bp_step_resume);
+ if (breakpoints_inserted)
+ insert_breakpoints ();
- ecs->sal = find_pc_line (stop_pc, 0);
+ keep_going (ecs);
+ return;
+ }
- if (step_range_end == 1)
- {
- /* It is stepi or nexti. We always want to stop stepping after
- one instruction. */
- stop_step = 1;
- print_stop_reason (END_STEPPING_RANGE, 0);
- stop_stepping (ecs);
+ /* If we have line number information for the function we are
+ thinking of stepping into, step into it.
+
+ If there are several symtabs at that PC (e.g. with include
+ files), just want to know whether *any* of them have line
+ numbers. find_pc_line handles this. */
+ {
+ struct symtab_and_line tmp_sal;
+
+ tmp_sal = find_pc_line (ecs->stop_func_start, 0);
+ if (tmp_sal.line != 0)
+ {
+ step_into_function (ecs);
+ return;
+ }
+ }
+
+ /* If we have no line number and the step-stop-if-no-debug is
+ set, we stop the step so that the user has a chance to switch
+ in assembly mode. */
+ if (step_over_calls == STEP_OVER_UNDEBUGGABLE && step_stop_if_no_debug)
+ {
+ stop_step = 1;
+ print_stop_reason (END_STEPPING_RANGE, 0);
+ stop_stepping (ecs);
+ return;
+ }
+
+ /* Set a breakpoint at callee's return address (the address at
+ which the caller will resume). */
+ insert_step_resume_breakpoint (get_prev_frame (get_current_frame ()), ecs);
+ keep_going (ecs);
return;
}
}
}
+ /* NOTE: tausq/2004-05-24: This if block used to be done before all
+ the trampoline processing logic, however, there are some trampolines
+ that have no names, so we should do trampoline handling first. */
+ if (step_over_calls == STEP_OVER_UNDEBUGGABLE
+ && ecs->stop_func_name == NULL)
+ {
+ /* The inferior just stepped into, or returned to, an
+ undebuggable function (where there is no symbol, not even a
+ minimal symbol, corresponding to the address where the
+ inferior stopped). Since we want to skip this kind of code,
+ we keep going until the inferior returns from this
+ function. */
+ if (step_stop_if_no_debug)
+ {
+ /* If we have no line number and the step-stop-if-no-debug
+ is set, we stop the step so that the user has a chance to
+ switch in assembly mode. */
+ stop_step = 1;
+ print_stop_reason (END_STEPPING_RANGE, 0);
+ stop_stepping (ecs);
+ return;
+ }
+ else
+ {
+ /* Set a breakpoint at callee's return address (the address
+ at which the caller will resume). */
+ insert_step_resume_breakpoint (get_prev_frame (get_current_frame ()),
+ ecs);
+ keep_going (ecs);
+ return;
+ }
+ }
+
+ if (step_range_end == 1)
+ {
+ /* It is stepi or nexti. We always want to stop stepping after
+ one instruction. */
+ stop_step = 1;
+ print_stop_reason (END_STEPPING_RANGE, 0);
+ stop_stepping (ecs);
+ return;
+ }
+
+ ecs->sal = find_pc_line (stop_pc, 0);
+
if (ecs->sal.line == 0)
{
/* We have no line number information. That means to stop
/* Save the pc before execution, to compare with pc after stop. */
prev_pc = read_pc (); /* Might have been DECR_AFTER_BREAK */
- if (ecs->update_step_sp)
- step_sp = read_sp ();
- ecs->update_step_sp = 0;
-
/* If we did not do break;, it means we should keep running the
inferior and not return to debugger. */