#include "gdb_assert.h"
#include "mi/mi-common.h"
#include "event-top.h"
+#include "record.h"
/* Prototypes for local functions */
return (((can_use_displaced_stepping == can_use_displaced_stepping_auto
&& non_stop)
|| can_use_displaced_stepping == can_use_displaced_stepping_on)
- && gdbarch_displaced_step_copy_insn_p (gdbarch));
+ && gdbarch_displaced_step_copy_insn_p (gdbarch)
+ && !RECORD_IS_USED);
}
/* Clean out any stray displaced stepping state. */
context_switch (ptid);
- actual_pc = read_pc ();
+ actual_pc = regcache_read_pc (get_thread_regcache (ptid));
if (breakpoint_here_p (actual_pc))
{
}
}
+/* Try to setup for software single stepping over the specified location.
+ Return 1 if target_resume() should use hardware single step.
+
+ GDBARCH the current gdbarch.
+ PC the location to step over. */
+
+static int
+maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+ int hw_step = 1;
+
+ if (gdbarch_software_single_step_p (gdbarch)
+ && gdbarch_software_single_step (gdbarch, get_current_frame ()))
+ {
+ hw_step = 0;
+ /* Do not pull these breakpoints until after a `wait' in
+ `wait_for_inferior' */
+ singlestep_breakpoints_inserted_p = 1;
+ singlestep_ptid = inferior_ptid;
+ singlestep_pc = pc;
+ }
+ return hw_step;
+}
/* Resume the inferior, but allow a QUIT. This is useful if the user
wants to interrupt some lengthy single-stepping operation
}
}
- if (step && gdbarch_software_single_step_p (gdbarch))
- {
- /* Do it the hard way, w/temp breakpoints */
- if (gdbarch_software_single_step (gdbarch, get_current_frame ()))
- {
- /* ...and don't ask hardware to do it. */
- step = 0;
- /* and do not pull these breakpoints until after a `wait' in
- `wait_for_inferior' */
- singlestep_breakpoints_inserted_p = 1;
- singlestep_ptid = inferior_ptid;
- singlestep_pc = pc;
- }
- }
+ /* Do we need to do it the hard way, w/temp breakpoints? */
+ if (step)
+ step = maybe_software_singlestep (gdbarch, pc);
/* If there were any forks/vforks/execs that were caught and are
now to be followed, then do so. */
}
stop_after_trap = 0;
- breakpoint_proceeded = 1; /* We're about to proceed... */
+
+ observer_notify_about_to_proceed ();
if (stop_registers)
{
iterate_over_threads (infrun_thread_stop_requested_callback, &ptid);
}
+void nullify_last_target_wait_ptid (void);
+
+static void
+infrun_thread_thread_exit (struct thread_info *tp, int silent)
+{
+ if (ptid_equal (target_last_wait_ptid, tp->ptid))
+ nullify_last_target_wait_ptid ();
+}
+
/* Callback for iterate_over_threads. */
static int
if (software_breakpoint_inserted_here_p (breakpoint_pc)
|| (non_stop && moribund_breakpoint_here_p (breakpoint_pc)))
{
+ struct cleanup *old_cleanups = NULL;
+ if (RECORD_IS_USED)
+ old_cleanups = record_gdb_operation_disable_set ();
+
/* 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
|| !currently_stepping (ecs->event_thread)
|| ecs->event_thread->prev_pc == breakpoint_pc)
regcache_write_pc (regcache, breakpoint_pc);
+
+ if (RECORD_IS_USED)
+ do_cleanups (old_cleanups);
}
}
reinit_frame_cache ();
}
- stop_pc = read_pc ();
+ stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
ecs->event_thread->stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
reinit_frame_cache ();
}
- stop_pc = read_pc ();
+ stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
/* This causes the eventpoints and symbol table to be reset.
Must do this now, before trying to determine whether to
case TARGET_WAITKIND_NO_HISTORY:
/* Reverse execution: target ran out of history info. */
- stop_pc = read_pc ();
+ stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
print_stop_reason (NO_HISTORY, 0);
stop_stepping (ecs);
return;
{
fprintf_unfiltered (gdb_stdlog, "infrun: stop_pc = 0x%s\n",
paddr_nz (stop_pc));
- if (STOPPED_BY_WATCHPOINT (&ecs->ws))
+ if (target_stopped_by_watchpoint ())
{
CORE_ADDR addr;
fprintf_unfiltered (gdb_stdlog, "infrun: stopped by watchpoint\n");
/* If necessary, step over this watchpoint. We'll be back to display
it in a moment. */
if (stopped_by_watchpoint
- && (HAVE_STEPPABLE_WATCHPOINT
+ && (target_have_steppable_watchpoint
|| gdbarch_have_nonsteppable_watchpoint (current_gdbarch)))
{
/* At this point, we are stopped at an instruction which has
the inferior over it. If we have non-steppable watchpoints,
we must disable the current watchpoint; it's simplest to
disable all watchpoints and breakpoints. */
-
- if (!HAVE_STEPPABLE_WATCHPOINT)
+ int hw_step = 1;
+
+ if (!target_have_steppable_watchpoint)
remove_breakpoints ();
+ /* Single step */
+ hw_step = maybe_software_singlestep (current_gdbarch, stop_pc);
+ target_resume (ecs->ptid, hw_step, TARGET_SIGNAL_0);
registers_changed ();
- target_resume (ecs->ptid, 1, TARGET_SIGNAL_0); /* Single step */
waiton_ptid = ecs->ptid;
- if (HAVE_STEPPABLE_WATCHPOINT)
+ if (target_have_steppable_watchpoint)
infwait_state = infwait_step_watch_state;
else
infwait_state = infwait_nonstep_watch_state;
if (signal_program[ecs->event_thread->stop_signal] == 0)
ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
- if (ecs->event_thread->prev_pc == read_pc ()
+ if (ecs->event_thread->prev_pc == stop_pc
&& ecs->event_thread->trap_expected
&& ecs->event_thread->step_resume_breakpoint == NULL)
{
keep_going (struct execution_control_state *ecs)
{
/* Save the pc before execution, to compare with pc after stop. */
- ecs->event_thread->prev_pc = read_pc (); /* Might have been DECR_AFTER_BREAK */
+ ecs->event_thread->prev_pc
+ = regcache_read_pc (get_thread_regcache (ecs->ptid));
/* If we did not do break;, it means we should keep running the
inferior and not return to debugger. */
/* Set the current source location. This will also happen if we
display the frame below, but the current SAL will be incorrect
during a user hook-stop function. */
- if (target_has_stack && !stop_stack_dummy)
+ if (has_stack_frames () && !stop_stack_dummy)
set_current_sal_from_frame (get_current_frame (), 1);
/* Let the user/frontend see the threads as stopped. */
catch_errors (hook_stop_stub, stop_command,
"Error while running hook_stop:\n", RETURN_MASK_ALL);
- if (!target_has_stack)
+ if (!has_stack_frames ())
goto done;
if (last.kind == TARGET_WAITKIND_SIGNALLED
|| last.kind == TARGET_WAITKIND_EXITED
|| (!inferior_thread ()->step_multi
&& !(inferior_thread ()->stop_bpstat
- && inferior_thread ()->proceed_to_finish)))
+ && inferior_thread ()->proceed_to_finish)
+ && !inferior_thread ()->in_infcall))
{
if (!ptid_equal (inferior_ptid, null_ptid))
observer_notify_normal_stop (inferior_thread ()->stop_bpstat,
/* ID if the selected frame when the inferior function call was made. */
struct frame_id selected_frame_id;
- int breakpoint_proceeded;
int proceed_to_finish;
+ int in_infcall;
};
/* Save all of the information associated with the inferior<==>gdb
called. */
inf_status->stop_bpstat = tp->stop_bpstat;
tp->stop_bpstat = bpstat_copy (tp->stop_bpstat);
- inf_status->breakpoint_proceeded = breakpoint_proceeded;
inf_status->proceed_to_finish = tp->proceed_to_finish;
+ inf_status->in_infcall = tp->in_infcall;
inf_status->selected_frame_id = get_frame_id (get_selected_frame (NULL));
bpstat_clear (&tp->stop_bpstat);
tp->stop_bpstat = inf_status->stop_bpstat;
inf_status->stop_bpstat = NULL;
- breakpoint_proceeded = inf_status->breakpoint_proceeded;
tp->proceed_to_finish = inf_status->proceed_to_finish;
+ tp->in_infcall = inf_status->in_infcall;
if (target_has_stack)
{
observer_attach_thread_ptid_changed (infrun_thread_ptid_changed);
observer_attach_thread_stop_requested (infrun_thread_stop_requested);
+ observer_attach_thread_exit (infrun_thread_thread_exit);
/* Explicitly create without lookup, since that tries to create a
value with a void typed value, and when we get here, gdbarch