aboutsummaryrefslogtreecommitdiff
path: root/gdb/rs6000-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/rs6000-tdep.c')
-rw-r--r--gdb/rs6000-tdep.c78
1 files changed, 76 insertions, 2 deletions
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 626b47e..1a7c7fc 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -153,6 +153,31 @@ static const char *const powerpc_vector_strings[] =
static enum powerpc_vector_abi powerpc_vector_abi_global = POWERPC_VEC_AUTO;
static const char *powerpc_vector_abi_string = "auto";
+/* PowerPC-related per-inferior data. */
+
+struct ppc_inferior_data
+{
+ /* This is an optional in case we add more fields to ppc_inferior_data, we
+ don't want it instantiated as soon as we get the ppc_inferior_data for an
+ inferior. */
+ gdb::optional<displaced_step_buffer> disp_step_buf;
+};
+
+static inferior_key<ppc_inferior_data> ppc_inferior_data_key;
+
+/* Get the per-inferior PowerPC data for INF. */
+
+static ppc_inferior_data *
+get_ppc_per_inferior (inferior *inf)
+{
+ ppc_inferior_data *per_inf = ppc_inferior_data_key.get (inf);
+
+ if (per_inf == nullptr)
+ per_inf = ppc_inferior_data_key.emplace (inf);
+
+ return per_inf;
+}
+
/* To be used by skip_prologue. */
struct rs6000_framedata
@@ -979,6 +1004,53 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch,
from + offset);
}
+/* Implementation of gdbarch_displaced_step_prepare. */
+
+static displaced_step_prepare_status
+ppc_displaced_step_prepare (gdbarch *arch, thread_info *thread,
+ CORE_ADDR &displaced_pc)
+{
+ ppc_inferior_data *per_inferior = get_ppc_per_inferior (thread->inf);
+
+ if (!per_inferior->disp_step_buf.has_value ())
+ {
+ /* Figure out where the displaced step buffer is. */
+ CORE_ADDR disp_step_buf_addr
+ = displaced_step_at_entry_point (thread->inf->gdbarch);
+
+ per_inferior->disp_step_buf.emplace (disp_step_buf_addr);
+ }
+
+ return per_inferior->disp_step_buf->prepare (thread, displaced_pc);
+}
+
+/* Implementation of gdbarch_displaced_step_finish. */
+
+static displaced_step_finish_status
+ppc_displaced_step_finish (gdbarch *arch, thread_info *thread,
+ gdb_signal sig)
+{
+ ppc_inferior_data *per_inferior = get_ppc_per_inferior (thread->inf);
+
+ gdb_assert (per_inferior->disp_step_buf.has_value ());
+
+ return per_inferior->disp_step_buf->finish (arch, thread, sig);
+}
+
+/* Implementation of gdbarch_displaced_step_restore_all_in_ptid. */
+
+static void
+ppc_displaced_step_restore_all_in_ptid (inferior *parent_inf, ptid_t ptid)
+{
+ ppc_inferior_data *per_inferior = ppc_inferior_data_key.get (parent_inf);
+
+ if (per_inferior == nullptr
+ || !per_inferior->disp_step_buf.has_value ())
+ return;
+
+ per_inferior->disp_step_buf->restore_in_ptid (ptid);
+}
+
/* Always use hardware single-stepping to execute the
displaced instruction. */
static bool
@@ -6990,8 +7062,10 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_displaced_step_hw_singlestep (gdbarch,
ppc_displaced_step_hw_singlestep);
set_gdbarch_displaced_step_fixup (gdbarch, ppc_displaced_step_fixup);
- set_gdbarch_displaced_step_location (gdbarch,
- displaced_step_at_entry_point);
+ set_gdbarch_displaced_step_prepare (gdbarch, ppc_displaced_step_prepare);
+ set_gdbarch_displaced_step_finish (gdbarch, ppc_displaced_step_finish);
+ set_gdbarch_displaced_step_restore_all_in_ptid
+ (gdbarch, ppc_displaced_step_restore_all_in_ptid);
set_gdbarch_max_insn_length (gdbarch, PPC_INSN_SIZE);