displaced_step_prepare_status
multiple_displaced_buffer_manager::prepare (thread_info *thread)
{
+ gdb_assert (thread != nullptr);
+
+ gdbarch *arch = thread->arch ();
+
+ /* This class requires that the arch implements both copy_insn and fixup. */
+ gdb_assert (gdbarch_displaced_step_copy_insn_p (arch));
+ gdb_assert (gdbarch_displaced_step_fixup_p (arch));
+
+ /* It's invalid to `prepare` a thread that already has a displaced step in
+ progress. */
gdb_assert (!thread->displaced_step_state.in_progress ());
- displaced_step_buffer_state *buffer = nullptr;
- /* Sanity check. */
+ /* Sanity check: no buffer is currently assigned to this thread. */
for (displaced_step_buffer_state &buf : m_buffers)
gdb_assert (buf.m_current_thread != thread);
/* Search for an unused buffer. */
+ displaced_step_buffer_state *buffer = nullptr;
+
for (displaced_step_buffer_state &candidate : m_buffers)
{
if (candidate.m_current_thread == nullptr)
if (buffer == nullptr)
return DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE;
- gdbarch *arch = thread->arch ();
if (debug_displaced)
fprintf_unfiltered (gdb_stdlog, "displaced: selected buffer at %s\n",
gdbarch->skip_permanent_breakpoint = default_skip_permanent_breakpoint;
gdbarch->displaced_step_hw_singlestep = default_displaced_step_hw_singlestep;
gdbarch->displaced_step_fixup = NULL;
- gdbarch->displaced_step_prepare = NULL;
gdbarch->displaced_step_finish = NULL;
gdbarch->relocate_instruction = NULL;
gdbarch->has_shared_address_space = default_has_shared_address_space;
/* Skip verify of displaced_step_copy_insn, has predicate. */
/* Skip verify of displaced_step_hw_singlestep, invalid_p == 0 */
/* Skip verify of displaced_step_fixup, has predicate. */
- if ((! gdbarch->displaced_step_prepare) != (! gdbarch->displaced_step_copy_insn))
- log.puts ("\n\tdisplaced_step_prepare");
- if ((! gdbarch->displaced_step_finish) != (! gdbarch->displaced_step_copy_insn))
+ /* Skip verify of displaced_step_prepare, has predicate. */
+ if ((! gdbarch->displaced_step_finish) != (! gdbarch->displaced_step_prepare))
log.puts ("\n\tdisplaced_step_finish");
/* Skip verify of relocate_instruction, has predicate. */
/* Skip verify of overlay_update, has predicate. */
fprintf_unfiltered (file,
"gdbarch_dump: displaced_step_hw_singlestep = <%s>\n",
host_address_to_string (gdbarch->displaced_step_hw_singlestep));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: gdbarch_displaced_step_prepare_p() = %d\n",
+ gdbarch_displaced_step_prepare_p (gdbarch));
fprintf_unfiltered (file,
"gdbarch_dump: displaced_step_prepare = <%s>\n",
host_address_to_string (gdbarch->displaced_step_prepare));
gdbarch->displaced_step_fixup = displaced_step_fixup;
}
+int
+gdbarch_displaced_step_prepare_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->displaced_step_prepare != NULL;
+}
+
displaced_step_prepare_status
gdbarch_displaced_step_prepare (struct gdbarch *gdbarch, thread_info *thread)
{
m;CORE_ADDR;displaced_step_location;thread_info *;thread;;NULL;;(! gdbarch->displaced_step_location) != (! gdbarch->displaced_step_copy_insn)
m;CORE_ADDR;displaced_step_release_location;CORE_ADDR;addr;;NULL;;(! gdbarch->displaced_step_location) != (! gdbarch->displaced_step_copy_insn) */
+extern int gdbarch_displaced_step_prepare_p (struct gdbarch *gdbarch);
+
typedef displaced_step_prepare_status (gdbarch_displaced_step_prepare_ftype) (struct gdbarch *gdbarch, thread_info *thread);
extern displaced_step_prepare_status gdbarch_displaced_step_prepare (struct gdbarch *gdbarch, thread_info *thread);
extern void set_gdbarch_displaced_step_prepare (struct gdbarch *gdbarch, gdbarch_displaced_step_prepare_ftype *displaced_step_prepare);
# see the comments in infrun.c.
#m;CORE_ADDR;displaced_step_location;thread_info *;thread;;NULL;;(! gdbarch->displaced_step_location) != (! gdbarch->displaced_step_copy_insn)
#m;CORE_ADDR;displaced_step_release_location;CORE_ADDR;addr;;NULL;;(! gdbarch->displaced_step_location) != (! gdbarch->displaced_step_copy_insn)
-m;displaced_step_prepare_status;displaced_step_prepare;thread_info *thread;thread;;NULL;;(! gdbarch->displaced_step_prepare) != (! gdbarch->displaced_step_copy_insn)
-m;displaced_step_finish_status;displaced_step_finish;thread_info *thread, gdb_signal sig;thread, sig;;NULL;;(! gdbarch->displaced_step_finish) != (! gdbarch->displaced_step_copy_insn)
+M;displaced_step_prepare_status;displaced_step_prepare;thread_info *thread;thread
+m;displaced_step_finish_status;displaced_step_finish;thread_info *thread, gdb_signal sig;thread, sig;;NULL;;(! gdbarch->displaced_step_finish) != (! gdbarch->displaced_step_prepare)
# Relocate an instruction to execute at a different address. OLDLOC
# is the address in the inferior memory where the instruction to
static bool
gdbarch_supports_displaced_stepping (gdbarch *arch)
{
- /* Only check for the presence of copy_insn. Other required methods
- are checked by the gdbarch validation to be provided if copy_insn is
- provided. */
- return gdbarch_displaced_step_copy_insn_p (arch);
+ /* Only check for the presence of `prepare`. `finish` is required by the
+ gdbarch verification to be provided if `prepare` is provided. */
+ return gdbarch_displaced_step_prepare_p (arch);
}
/* Return non-zero if displaced stepping can/should be used to step