+displaced_step_prepare_status
+linux_displaced_step_prepare (gdbarch *arch, thread_info *thread,
+ CORE_ADDR &displaced_pc)
+{
+ linux_info *per_inferior = get_linux_inferior_data (thread->inf);
+
+ if (!per_inferior->disp_step_bufs.has_value ())
+ {
+ /* Figure out the location of the buffers. They are contiguous, starting
+ at DISP_STEP_BUF_ADDR. They are all of size BUF_LEN. */
+ CORE_ADDR disp_step_buf_addr
+ = linux_displaced_step_location (thread->inf->gdbarch);
+ int buf_len = gdbarch_max_insn_length (arch);
+
+ linux_gdbarch_data *gdbarch_data = get_linux_gdbarch_data (arch);
+ gdb_assert (gdbarch_data->num_disp_step_buffers > 0);
+
+ std::vector<CORE_ADDR> buffers;
+ for (int i = 0; i < gdbarch_data->num_disp_step_buffers; i++)
+ buffers.push_back (disp_step_buf_addr + i * buf_len);
+
+ per_inferior->disp_step_bufs.emplace (buffers);
+ }
+
+ return per_inferior->disp_step_bufs->prepare (thread, displaced_pc);
+}
+
+/* See linux-tdep.h. */
+
+displaced_step_finish_status
+linux_displaced_step_finish (gdbarch *arch, thread_info *thread, gdb_signal sig)
+{
+ linux_info *per_inferior = get_linux_inferior_data (thread->inf);
+
+ gdb_assert (per_inferior->disp_step_bufs.has_value ());
+
+ return per_inferior->disp_step_bufs->finish (arch, thread, sig);
+}
+
+/* See linux-tdep.h. */
+
+const displaced_step_copy_insn_closure *
+linux_displaced_step_copy_insn_closure_by_addr (inferior *inf, CORE_ADDR addr)
+{
+ linux_info *per_inferior = linux_inferior_data.get (inf);
+
+ if (per_inferior == nullptr
+ || !per_inferior->disp_step_bufs.has_value ())
+ return nullptr;
+
+ return per_inferior->disp_step_bufs->copy_insn_closure_by_addr (addr);
+}
+
+/* See linux-tdep.h. */
+
+void
+linux_displaced_step_restore_all_in_ptid (inferior *parent_inf, ptid_t ptid)
+{
+ linux_info *per_inferior = linux_inferior_data.get (parent_inf);
+
+ if (per_inferior == nullptr
+ || !per_inferior->disp_step_bufs.has_value ())
+ return;
+
+ per_inferior->disp_step_bufs->restore_in_ptid (ptid);
+}
+
+/* See linux-tdep.h. */
+