diff mbox

Create a displaced_step_closure class hierarchy

Message ID 1507905290-9405-1-git-send-email-simon.marchi@ericsson.com
State New
Headers show

Commit Message

Simon Marchi Oct. 13, 2017, 2:34 p.m. UTC
From: Simon Marchi <simon.marchi@polymtl.ca>

displaced_step_closure is a type defined in multiple -tdep.c files.
Trying to xfree it from the common code (infrun.c) is a problem when we
try to poison xfree for non-POD types.  Because there can be multiple of
these types in the same build, this patch makes a hierarchy of classes
with a virtual destructor.  When the common code deletes the object
through a displaced_step_closure pointer, it will invoke the right
destructor.

The amd64 used a last-member array with a variable size.  That doesn't
work with new, so I changed it for an std::vector.  Other architectures
which used a simple byte buffer as a closure now use a shared
buf_displaced_step_closure, a closure type that only contains a
gdb::byte_vector.

Reg-tested on the buildbot.

gdb/ChangeLog:

	* infrun.h: Include common/byte-vector.h.
	(struct displaced_step_closure): New struct.
	(struct buf_displaced_step_closure): New struct.
	* infrun.c (displaced_step_closure::~displaced_step_closure):
	Provide default implementation.
	(displaced_step_clear): Deallocate step closure with delete.
	* aarch64-tdep.c (displaced_step_closure): Rename to ...
	(aarch64_displaced_step_closure): ... this, extend
	displaced_step_closure.
	(aarch64_displaced_step_data) <dsc>: Change type to
	aarch64_displaced_step_closure.
	(aarch64_displaced_step_copy_insn): Adjust to type change, use
	unique_ptr.
	(aarch64_displaced_step_fixup): Add cast for displaced step
	closure.
	* amd64-tdep.c (displaced_step_closure): Rename to ...
	(amd64_displaced_step_closure): ... this, extend
	displaced_step_closure.
	<insn_buf>: Change type to std::vector<gdb_byte>.
	<max_len>: Remove.
	(fixup_riprel): Change type of DSC parameter, adjust to type
	change of insn_buf.
	(fixup_displaced_copy): Change type of DSC parameter.
	(amd64_displaced_step_copy_insn): Instantiate
	amd64_displaced_step_closure.
	(amd64_displaced_step_fixup): Add cast for closure type, adjust
	to type change of insn_buf.
	* arm-linux-tdep.c (arm_linux_cleanup_svc): Change type of
	parameter DSC.
	(arm_linux_copy_svc): Likewise.
	(cleanup_kernel_helper_return): Likewise.
	(arm_catch_kernel_helper_return): Likewise.
	(arm_linux_displaced_step_copy_insn): Instantiate
	arm_displaced_step_closure.
	* arm-tdep.c (arm_pc_is_thumb): Add cast for closure.
	(displaced_read_reg): Change type of parameter DSC.
	(branch_write_pc): Likewise.
	(load_write_pc): Likewise.
	(alu_write_pc): Likewise.
	(displaced_write_reg): Likewise.
	(arm_copy_unmodified): Likewise.
	(thumb_copy_unmodified_32bit): Likewise.
	(thumb_copy_unmodified_16bit): Likewise.
	(cleanup_preload): Likewise.
	(install_preload): Likewise.
	(arm_copy_preload): Likewise.
	(thumb2_copy_preload): Likewise.
	(install_preload_reg): Likewise.
	(arm_copy_preload_reg): Likewise.
	(cleanup_copro_load_store): Likewise.
	(install_copro_load_store): Likewise.
	(arm_copy_copro_load_store) Likewise.
	(thumb2_copy_copro_load_store): Likewise.
	(cleanup_branch): Likewise.
	(install_b_bl_blx): Likewise.
	(arm_copy_b_bl_blx): Likewise.
	(thumb2_copy_b_bl_blx): Likewise.
	(thumb_copy_b): Likewise.
	(install_bx_blx_reg): Likewise.
	(arm_copy_bx_blx_reg): Likewise.
	(thumb_copy_bx_blx_reg): Likewise.
	(cleanup_alu_imm): Likewise.
	(arm_copy_alu_imm): Likewise.
	(thumb2_copy_alu_imm): Likewise.
	(cleanup_alu_reg): Likewise.
	(install_alu_reg): Likewise.
	(arm_copy_alu_reg): Likewise.
	(thumb_copy_alu_reg): Likewise.
	(cleanup_alu_shifted_reg): Likewise.
	(install_alu_shifted_reg): Likewise.
	(arm_copy_alu_shifted_reg): Likewise.
	(cleanup_load): Likewise.
	(cleanup_store): Likewise.
	(arm_copy_extra_ld_st): Likewise.
	(install_load_store): Likewise.
	(thumb2_copy_load_literal): Likewise.
	(thumb2_copy_load_reg_imm): Likewise.
	(arm_copy_ldr_str_ldrb_strb): Likewise.
	(cleanup_block_load_all): Likewise.
	(cleanup_block_store_pc): Likewise.
	(cleanup_block_load_pc): Likewise.
	(arm_copy_block_xfer): Likewise.
	(thumb2_copy_block_xfer): Likewise.
	(cleanup_svc): Likewise.
	(install_svc): Likewise.
	(arm_copy_svc): Likewise.
	(thumb_copy_svc): Likewise.
	(arm_copy_undef): Likewise.
	(thumb_32bit_copy_undef): Likewise.
	(arm_copy_unpred): Likewise.
	(arm_decode_misc_memhint_neon): Likewise.
	(arm_decode_unconditional): Likewise.
	(arm_decode_miscellaneous): Likewise.
	(arm_decode_dp_misc): Likewise.
	(arm_decode_ld_st_word_ubyte): Likewise.
	(arm_decode_media): Likewise.
	(arm_decode_b_bl_ldmstm): Likewise.
	(arm_decode_ext_reg_ld_st): Likewise.
	(thumb2_decode_dp_shift_reg): Likewise.
	(thumb2_decode_ext_reg_ld_st): Likewise.
	(arm_decode_svc_copro): Likewise.
	(thumb2_decode_svc_copro): Likewise.
	(install_pc_relative): Likewise.
	(thumb_copy_pc_relative_16bit): Likewise.
	(thumb_decode_pc_relative_16bit): Likewise.
	(thumb_copy_pc_relative_32bit): Likewise.
	(thumb_copy_16bit_ldr_literal): Likewise.
	(thumb_copy_cbnz_cbz): Likewise.
	(thumb2_copy_table_branch): Likewise.
	(cleanup_pop_pc_16bit_all): Likewise.
	(thumb_copy_pop_pc_16bit): Likewise.
	(thumb_process_displaced_16bit_insn): Likewise.
	(decode_thumb_32bit_ld_mem_hints): Likewise.
	(thumb_process_displaced_32bit_insn): Likewise.
	(thumb_process_displaced_insn): Likewise.
	(arm_process_displaced_insn): Likewise.
	(arm_displaced_init_closure): Likewise.
	(arm_displaced_step_fixup): Add cast for closure.
	* arm-tdep.h: Include infrun.h.
	(displaced_step_closure): Rename to ...
	(arm_displaced_step_closure): ... this, extend
	displaced_step_closure.
	<u::svc::copy_svc_os>: Change type of parameter DSC.
	<cleanup>: Likewise.
	(arm_process_displaced_insn): Likewise.
	(arm_displaced_init_closure): Likewise.
	(displaced_read_reg): Likewise.
	(displaced_write_reg): Likewise.
	* i386-linux-tdep.c (i386_linux_displaced_step_copy_insn):
	Adjust.
	* i386-tdep.h: Include infrun.h.
	(i386_displaced_step_closure): New typedef.
	* i386-tdep.c (i386_displaced_step_copy_insn): Use
	i386_displaced_step_closure.
	(i386_displaced_step_fixup): Adjust.
	* rs6000-tdep.c (ppc_displaced_step_closure): New typedef.
	(ppc_displaced_step_copy_insn): Use ppc_displaced_step_closure
	and unique_ptr.
	(ppc_displaced_step_fixup): Adjust.
	* s390-linux-tdep.c (s390_displaced_step_closure): New typedef.
	(s390_displaced_step_copy_insn): Use s390_displaced_step_closure
	and unique_ptr.
	(s390_displaced_step_fixup): Adjust.
---
 gdb/aarch64-tdep.c    |  21 +++---
 gdb/amd64-tdep.c      |  38 ++++++-----
 gdb/arm-linux-tdep.c  |  10 +--
 gdb/arm-tdep.c        | 173 +++++++++++++++++++++++++-------------------------
 gdb/arm-tdep.h        |  15 +++--
 gdb/i386-linux-tdep.c |  14 ++--
 gdb/i386-tdep.c       |  12 ++--
 gdb/i386-tdep.h       |   4 ++
 gdb/infrun.c          |   8 ++-
 gdb/infrun.h          |  19 ++++++
 gdb/rs6000-tdep.c     |  19 +++---
 gdb/s390-linux-tdep.c |  18 ++++--
 12 files changed, 194 insertions(+), 157 deletions(-)

Comments

Simon Marchi Oct. 21, 2017, 3:51 p.m. UTC | #1
On 2017-10-13 10:34 AM, Simon Marchi wrote:
> From: Simon Marchi <simon.marchi@polymtl.ca>
> 
> displaced_step_closure is a type defined in multiple -tdep.c files.
> Trying to xfree it from the common code (infrun.c) is a problem when we
> try to poison xfree for non-POD types.  Because there can be multiple of
> these types in the same build, this patch makes a hierarchy of classes
> with a virtual destructor.  When the common code deletes the object
> through a displaced_step_closure pointer, it will invoke the right
> destructor.
> 
> The amd64 used a last-member array with a variable size.  That doesn't
> work with new, so I changed it for an std::vector.  Other architectures
> which used a simple byte buffer as a closure now use a shared
> buf_displaced_step_closure, a closure type that only contains a
> gdb::byte_vector.
> 
> Reg-tested on the buildbot.

I pushed this in.

Simon
diff mbox

Patch

diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index a40dc69..cbab1a5 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -2488,14 +2488,14 @@  aarch64_software_single_step (struct regcache *regcache)
   return next_pcs;
 }
 
-struct displaced_step_closure
+struct aarch64_displaced_step_closure : public displaced_step_closure
 {
   /* It is true when condition instruction, such as B.CON, TBZ, etc,
      is being displaced stepping.  */
-  int cond;
+  int cond = 0;
 
   /* PC adjustment offset after displaced stepping.  */
-  int32_t pc_adjust;
+  int32_t pc_adjust = 0;
 };
 
 /* Data when visiting instructions for displaced stepping.  */
@@ -2513,7 +2513,7 @@  struct aarch64_displaced_step_data
   /* Registers when doing displaced stepping.  */
   struct regcache *regs;
 
-  struct displaced_step_closure *dsc;
+  aarch64_displaced_step_closure *dsc;
 };
 
 /* Implementation of aarch64_insn_visitor method "b".  */
@@ -2727,7 +2727,6 @@  aarch64_displaced_step_copy_insn (struct gdbarch *gdbarch,
 				  CORE_ADDR from, CORE_ADDR to,
 				  struct regcache *regs)
 {
-  struct displaced_step_closure *dsc = NULL;
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
   uint32_t insn = read_memory_unsigned_integer (from, 4, byte_order_for_code);
   struct aarch64_displaced_step_data dsd;
@@ -2743,11 +2742,12 @@  aarch64_displaced_step_copy_insn (struct gdbarch *gdbarch,
       return NULL;
     }
 
-  dsc = XCNEW (struct displaced_step_closure);
+  std::unique_ptr<aarch64_displaced_step_closure> dsc
+    (new aarch64_displaced_step_closure);
   dsd.base.insn_addr = from;
   dsd.new_addr = to;
   dsd.regs = regs;
-  dsd.dsc = dsc;
+  dsd.dsc = dsc.get ();
   dsd.insn_count = 0;
   aarch64_relocate_instruction (insn, &visitor,
 				(struct aarch64_insn_data *) &dsd);
@@ -2773,21 +2773,22 @@  aarch64_displaced_step_copy_insn (struct gdbarch *gdbarch,
     }
   else
     {
-      xfree (dsc);
       dsc = NULL;
     }
 
-  return dsc;
+  return dsc.release ();
 }
 
 /* Implement the "displaced_step_fixup" gdbarch method.  */
 
 void
 aarch64_displaced_step_fixup (struct gdbarch *gdbarch,
-			      struct displaced_step_closure *dsc,
+			      struct displaced_step_closure *dsc_,
 			      CORE_ADDR from, CORE_ADDR to,
 			      struct regcache *regs)
 {
+  aarch64_displaced_step_closure *dsc = (aarch64_displaced_step_closure *) dsc_;
+
   if (dsc->cond)
     {
       ULONGEST pc;
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index e56c388..08a9cae 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -46,6 +46,7 @@ 
 #include "producer.h"
 #include "ax.h"
 #include "ax-gdb.h"
+#include "common/byte-vector.h"
 
 /* Note that the AMD64 architecture was previously known as x86-64.
    The latter is (forever) engraved into the canonical system name as
@@ -1047,22 +1048,22 @@  struct amd64_insn
   gdb_byte *raw_insn;
 };
 
-struct displaced_step_closure
+struct amd64_displaced_step_closure : public displaced_step_closure
 {
+  amd64_displaced_step_closure (int insn_buf_len)
+  : insn_buf (insn_buf_len, 0)
+  {}
+
   /* For rip-relative insns, saved copy of the reg we use instead of %rip.  */
-  int tmp_used;
+  int tmp_used = 0;
   int tmp_regno;
   ULONGEST tmp_save;
 
   /* Details of the instruction.  */
   struct amd64_insn insn_details;
 
-  /* Amount of space allocated to insn_buf.  */
-  int max_len;
-
-  /* The possibly modified insn.
-     This is a variable-length field.  */
-  gdb_byte insn_buf[1];
+  /* The possibly modified insn.  */
+  gdb::byte_vector insn_buf;
 };
 
 /* WARNING: Keep onebyte_has_modrm, twobyte_has_modrm in sync with
@@ -1303,7 +1304,7 @@  amd64_get_insn_details (gdb_byte *insn, struct amd64_insn *details)
    We set base = pc + insn_length so we can leave disp unchanged.  */
 
 static void
-fixup_riprel (struct gdbarch *gdbarch, struct displaced_step_closure *dsc,
+fixup_riprel (struct gdbarch *gdbarch, amd64_displaced_step_closure *dsc,
 	      CORE_ADDR from, CORE_ADDR to, struct regcache *regs)
 {
   const struct amd64_insn *insn_details = &dsc->insn_details;
@@ -1318,8 +1319,8 @@  fixup_riprel (struct gdbarch *gdbarch, struct displaced_step_closure *dsc,
   ++insn;
 
   /* Compute the rip-relative address.	*/
-  insn_length = gdb_buffered_insn_length (gdbarch, dsc->insn_buf,
-					  dsc->max_len, from);
+  insn_length = gdb_buffered_insn_length (gdbarch, dsc->insn_buf.data (),
+					  dsc->insn_buf.size (), from);
   rip_base = from + insn_length;
 
   /* We need a register to hold the address.
@@ -1353,7 +1354,7 @@  fixup_riprel (struct gdbarch *gdbarch, struct displaced_step_closure *dsc,
 
 static void
 fixup_displaced_copy (struct gdbarch *gdbarch,
-		      struct displaced_step_closure *dsc,
+		      amd64_displaced_step_closure *dsc,
 		      CORE_ADDR from, CORE_ADDR to, struct regcache *regs)
 {
   const struct amd64_insn *details = &dsc->insn_details;
@@ -1380,15 +1381,11 @@  amd64_displaced_step_copy_insn (struct gdbarch *gdbarch,
   /* Extra space for sentinels so fixup_{riprel,displaced_copy} don't have to
      continually watch for running off the end of the buffer.  */
   int fixup_sentinel_space = len;
-  struct displaced_step_closure *dsc
-    = ((struct displaced_step_closure *)
-       xmalloc (sizeof (*dsc) + len + fixup_sentinel_space));
+  amd64_displaced_step_closure *dsc
+    = new amd64_displaced_step_closure (len + fixup_sentinel_space);
   gdb_byte *buf = &dsc->insn_buf[0];
   struct amd64_insn *details = &dsc->insn_details;
 
-  dsc->tmp_used = 0;
-  dsc->max_len = len + fixup_sentinel_space;
-
   read_memory (from, buf, len);
 
   /* Set up the sentinel space so we don't have to worry about running
@@ -1583,14 +1580,15 @@  amd64_insn_is_jump (struct gdbarch *gdbarch, CORE_ADDR addr)
 
 void
 amd64_displaced_step_fixup (struct gdbarch *gdbarch,
-			    struct displaced_step_closure *dsc,
+			    struct displaced_step_closure *dsc_,
 			    CORE_ADDR from, CORE_ADDR to,
 			    struct regcache *regs)
 {
+  amd64_displaced_step_closure *dsc = (amd64_displaced_step_closure *) dsc_;
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   /* The offset we applied to the instruction's address.  */
   ULONGEST insn_offset = to - from;
-  gdb_byte *insn = dsc->insn_buf;
+  gdb_byte *insn = dsc->insn_buf.data ();
   const struct amd64_insn *insn_details = &dsc->insn_details;
 
   if (debug_displaced)
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index 056c1b9..4d1d890 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -950,7 +950,7 @@  arm_linux_software_single_step (struct regcache *regcache)
 static void
 arm_linux_cleanup_svc (struct gdbarch *gdbarch,
 		       struct regcache *regs,
-		       struct displaced_step_closure *dsc)
+		       arm_displaced_step_closure *dsc)
 {
   ULONGEST apparent_pc;
   int within_scratch;
@@ -978,7 +978,7 @@  arm_linux_cleanup_svc (struct gdbarch *gdbarch,
 
 static int
 arm_linux_copy_svc (struct gdbarch *gdbarch, struct regcache *regs,
-		    struct displaced_step_closure *dsc)
+		    arm_displaced_step_closure *dsc)
 {
   CORE_ADDR return_to = 0;
 
@@ -1069,7 +1069,7 @@  arm_linux_copy_svc (struct gdbarch *gdbarch, struct regcache *regs,
 static void
 cleanup_kernel_helper_return (struct gdbarch *gdbarch,
 			      struct regcache *regs,
-			      struct displaced_step_closure *dsc)
+			      arm_displaced_step_closure *dsc)
 {
   displaced_write_reg (regs, dsc, ARM_LR_REGNUM, dsc->tmp[0], CANNOT_WRITE_PC);
   displaced_write_reg (regs, dsc, ARM_PC_REGNUM, dsc->tmp[0], BRANCH_WRITE_PC);
@@ -1078,7 +1078,7 @@  cleanup_kernel_helper_return (struct gdbarch *gdbarch,
 static void
 arm_catch_kernel_helper_return (struct gdbarch *gdbarch, CORE_ADDR from,
 				CORE_ADDR to, struct regcache *regs,
-				struct displaced_step_closure *dsc)
+				arm_displaced_step_closure *dsc)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
@@ -1112,7 +1112,7 @@  arm_linux_displaced_step_copy_insn (struct gdbarch *gdbarch,
 				    CORE_ADDR from, CORE_ADDR to,
 				    struct regcache *regs)
 {
-  struct displaced_step_closure *dsc = XNEW (struct displaced_step_closure);
+  arm_displaced_step_closure *dsc = new arm_displaced_step_closure;
 
   /* Detect when we enter an (inaccessible by GDB) Linux kernel helper, and
      stop at the return location.  */
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 960696d..fc6197d 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -399,8 +399,9 @@  arm_pc_is_thumb (struct gdbarch *gdbarch, CORE_ADDR memaddr)
 {
   struct bound_minimal_symbol sym;
   char type;
-  struct displaced_step_closure* dsc
-    = get_displaced_step_closure_by_addr(memaddr);
+  arm_displaced_step_closure *dsc
+    = ((arm_displaced_step_closure * )
+	get_displaced_step_closure_by_addr (memaddr));
 
   /* If checking the mode of displaced instruction in copy area, the mode
      should be determined by instruction on the original address.  */
@@ -4413,7 +4414,7 @@  arm_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
    location.  */
 
 ULONGEST
-displaced_read_reg (struct regcache *regs, struct displaced_step_closure *dsc,
+displaced_read_reg (struct regcache *regs, arm_displaced_step_closure *dsc,
 		    int regno)
 {
   ULONGEST ret;
@@ -4461,7 +4462,7 @@  displaced_in_arm_mode (struct regcache *regs)
 /* Write to the PC as from a branch instruction.  */
 
 static void
-branch_write_pc (struct regcache *regs, struct displaced_step_closure *dsc,
+branch_write_pc (struct regcache *regs, arm_displaced_step_closure *dsc,
 		 ULONGEST val)
 {
   if (!dsc->is_thumb)
@@ -4507,7 +4508,7 @@  bx_write_pc (struct regcache *regs, ULONGEST val)
 /* Write to the PC as if from a load instruction.  */
 
 static void
-load_write_pc (struct regcache *regs, struct displaced_step_closure *dsc,
+load_write_pc (struct regcache *regs, arm_displaced_step_closure *dsc,
 	       ULONGEST val)
 {
   if (DISPLACED_STEPPING_ARCH_VERSION >= 5)
@@ -4519,7 +4520,7 @@  load_write_pc (struct regcache *regs, struct displaced_step_closure *dsc,
 /* Write to the PC as if from an ALU instruction.  */
 
 static void
-alu_write_pc (struct regcache *regs, struct displaced_step_closure *dsc,
+alu_write_pc (struct regcache *regs, arm_displaced_step_closure *dsc,
 	      ULONGEST val)
 {
   if (DISPLACED_STEPPING_ARCH_VERSION >= 7 && !dsc->is_thumb)
@@ -4533,7 +4534,7 @@  alu_write_pc (struct regcache *regs, struct displaced_step_closure *dsc,
    this is controlled by the WRITE_PC argument.  */
 
 void
-displaced_write_reg (struct regcache *regs, struct displaced_step_closure *dsc,
+displaced_write_reg (struct regcache *regs, arm_displaced_step_closure *dsc,
 		     int regno, ULONGEST val, enum pc_write_style write_pc)
 {
   if (regno == ARM_PC_REGNUM)
@@ -4617,7 +4618,7 @@  insn_references_pc (uint32_t insn, uint32_t bitmask)
 
 static int
 arm_copy_unmodified (struct gdbarch *gdbarch, uint32_t insn,
-		     const char *iname, struct displaced_step_closure *dsc)
+		     const char *iname, arm_displaced_step_closure *dsc)
 {
   if (debug_displaced)
     fprintf_unfiltered (gdb_stdlog, "displaced: copying insn %.8lx, "
@@ -4632,7 +4633,7 @@  arm_copy_unmodified (struct gdbarch *gdbarch, uint32_t insn,
 static int
 thumb_copy_unmodified_32bit (struct gdbarch *gdbarch, uint16_t insn1,
 			     uint16_t insn2, const char *iname,
-			     struct displaced_step_closure *dsc)
+			     arm_displaced_step_closure *dsc)
 {
   if (debug_displaced)
     fprintf_unfiltered (gdb_stdlog, "displaced: copying insn %.4x %.4x, "
@@ -4651,7 +4652,7 @@  thumb_copy_unmodified_32bit (struct gdbarch *gdbarch, uint16_t insn1,
 static int
 thumb_copy_unmodified_16bit (struct gdbarch *gdbarch, uint16_t insn,
 			     const char *iname,
-			     struct displaced_step_closure *dsc)
+			     arm_displaced_step_closure *dsc)
 {
   if (debug_displaced)
     fprintf_unfiltered (gdb_stdlog, "displaced: copying insn %.4x, "
@@ -4667,7 +4668,7 @@  thumb_copy_unmodified_16bit (struct gdbarch *gdbarch, uint16_t insn,
 
 static void
 cleanup_preload (struct gdbarch *gdbarch,
-		 struct regcache *regs, struct displaced_step_closure *dsc)
+		 struct regcache *regs, arm_displaced_step_closure *dsc)
 {
   displaced_write_reg (regs, dsc, 0, dsc->tmp[0], CANNOT_WRITE_PC);
   if (!dsc->u.preload.immed)
@@ -4676,7 +4677,7 @@  cleanup_preload (struct gdbarch *gdbarch,
 
 static void
 install_preload (struct gdbarch *gdbarch, struct regcache *regs,
-		 struct displaced_step_closure *dsc, unsigned int rn)
+		 arm_displaced_step_closure *dsc, unsigned int rn)
 {
   ULONGEST rn_val;
   /* Preload instructions:
@@ -4695,7 +4696,7 @@  install_preload (struct gdbarch *gdbarch, struct regcache *regs,
 
 static int
 arm_copy_preload (struct gdbarch *gdbarch, uint32_t insn, struct regcache *regs,
-		  struct displaced_step_closure *dsc)
+		  arm_displaced_step_closure *dsc)
 {
   unsigned int rn = bits (insn, 16, 19);
 
@@ -4715,7 +4716,7 @@  arm_copy_preload (struct gdbarch *gdbarch, uint32_t insn, struct regcache *regs,
 
 static int
 thumb2_copy_preload (struct gdbarch *gdbarch, uint16_t insn1, uint16_t insn2,
-		     struct regcache *regs, struct displaced_step_closure *dsc)
+		     struct regcache *regs, arm_displaced_step_closure *dsc)
 {
   unsigned int rn = bits (insn1, 0, 3);
   unsigned int u_bit = bit (insn1, 7);
@@ -4765,7 +4766,7 @@  thumb2_copy_preload (struct gdbarch *gdbarch, uint16_t insn1, uint16_t insn2,
 
 static void
 install_preload_reg(struct gdbarch *gdbarch, struct regcache *regs,
-		    struct displaced_step_closure *dsc, unsigned int rn,
+		    arm_displaced_step_closure *dsc, unsigned int rn,
 		    unsigned int rm)
 {
   ULONGEST rn_val, rm_val;
@@ -4790,7 +4791,7 @@  install_preload_reg(struct gdbarch *gdbarch, struct regcache *regs,
 static int
 arm_copy_preload_reg (struct gdbarch *gdbarch, uint32_t insn,
 		      struct regcache *regs,
-		      struct displaced_step_closure *dsc)
+		      arm_displaced_step_closure *dsc)
 {
   unsigned int rn = bits (insn, 16, 19);
   unsigned int rm = bits (insn, 0, 3);
@@ -4814,7 +4815,7 @@  arm_copy_preload_reg (struct gdbarch *gdbarch, uint32_t insn,
 static void
 cleanup_copro_load_store (struct gdbarch *gdbarch,
 			  struct regcache *regs,
-			  struct displaced_step_closure *dsc)
+			  arm_displaced_step_closure *dsc)
 {
   ULONGEST rn_val = displaced_read_reg (regs, dsc, 0);
 
@@ -4826,7 +4827,7 @@  cleanup_copro_load_store (struct gdbarch *gdbarch,
 
 static void
 install_copro_load_store (struct gdbarch *gdbarch, struct regcache *regs,
-			  struct displaced_step_closure *dsc,
+			  arm_displaced_step_closure *dsc,
 			  int writeback, unsigned int rn)
 {
   ULONGEST rn_val;
@@ -4854,7 +4855,7 @@  install_copro_load_store (struct gdbarch *gdbarch, struct regcache *regs,
 static int
 arm_copy_copro_load_store (struct gdbarch *gdbarch, uint32_t insn,
 			   struct regcache *regs,
-			   struct displaced_step_closure *dsc)
+			   arm_displaced_step_closure *dsc)
 {
   unsigned int rn = bits (insn, 16, 19);
 
@@ -4875,7 +4876,7 @@  arm_copy_copro_load_store (struct gdbarch *gdbarch, uint32_t insn,
 static int
 thumb2_copy_copro_load_store (struct gdbarch *gdbarch, uint16_t insn1,
 			      uint16_t insn2, struct regcache *regs,
-			      struct displaced_step_closure *dsc)
+			      arm_displaced_step_closure *dsc)
 {
   unsigned int rn = bits (insn1, 0, 3);
 
@@ -4903,7 +4904,7 @@  thumb2_copy_copro_load_store (struct gdbarch *gdbarch, uint16_t insn1,
 
 static void
 cleanup_branch (struct gdbarch *gdbarch, struct regcache *regs,
-		struct displaced_step_closure *dsc)
+		arm_displaced_step_closure *dsc)
 {
   uint32_t status = displaced_read_reg (regs, dsc, ARM_PS_REGNUM);
   int branch_taken = condition_true (dsc->u.branch.cond, status);
@@ -4934,7 +4935,7 @@  cleanup_branch (struct gdbarch *gdbarch, struct regcache *regs,
 
 static void
 install_b_bl_blx (struct gdbarch *gdbarch, struct regcache *regs,
-		  struct displaced_step_closure *dsc,
+		  arm_displaced_step_closure *dsc,
 		  unsigned int cond, int exchange, int link, long offset)
 {
   /* Implement "BL<cond> <label>" as:
@@ -4963,7 +4964,7 @@  install_b_bl_blx (struct gdbarch *gdbarch, struct regcache *regs,
 }
 static int
 arm_copy_b_bl_blx (struct gdbarch *gdbarch, uint32_t insn,
-		   struct regcache *regs, struct displaced_step_closure *dsc)
+		   struct regcache *regs, arm_displaced_step_closure *dsc)
 {
   unsigned int cond = bits (insn, 28, 31);
   int exchange = (cond == 0xf);
@@ -4993,7 +4994,7 @@  arm_copy_b_bl_blx (struct gdbarch *gdbarch, uint32_t insn,
 static int
 thumb2_copy_b_bl_blx (struct gdbarch *gdbarch, uint16_t insn1,
 		      uint16_t insn2, struct regcache *regs,
-		      struct displaced_step_closure *dsc)
+		      arm_displaced_step_closure *dsc)
 {
   int link = bit (insn2, 14);
   int exchange = link && !bit (insn2, 12);
@@ -5048,7 +5049,7 @@  thumb2_copy_b_bl_blx (struct gdbarch *gdbarch, uint16_t insn1,
 /* Copy B Thumb instructions.  */
 static int
 thumb_copy_b (struct gdbarch *gdbarch, uint16_t insn,
-	      struct displaced_step_closure *dsc)
+	      arm_displaced_step_closure *dsc)
 {
   unsigned int cond = 0;
   int offset = 0;
@@ -5088,7 +5089,7 @@  thumb_copy_b (struct gdbarch *gdbarch, uint16_t insn,
 
 static void
 install_bx_blx_reg (struct gdbarch *gdbarch, struct regcache *regs,
-		    struct displaced_step_closure *dsc, int link,
+		    arm_displaced_step_closure *dsc, int link,
 		    unsigned int cond, unsigned int rm)
 {
   /* Implement {BX,BLX}<cond> <reg>" as:
@@ -5111,7 +5112,7 @@  install_bx_blx_reg (struct gdbarch *gdbarch, struct regcache *regs,
 
 static int
 arm_copy_bx_blx_reg (struct gdbarch *gdbarch, uint32_t insn,
-		     struct regcache *regs, struct displaced_step_closure *dsc)
+		     struct regcache *regs, arm_displaced_step_closure *dsc)
 {
   unsigned int cond = bits (insn, 28, 31);
   /* BX:  x12xxx1x
@@ -5132,7 +5133,7 @@  arm_copy_bx_blx_reg (struct gdbarch *gdbarch, uint32_t insn,
 static int
 thumb_copy_bx_blx_reg (struct gdbarch *gdbarch, uint16_t insn,
 		       struct regcache *regs,
-		       struct displaced_step_closure *dsc)
+		       arm_displaced_step_closure *dsc)
 {
   int link = bit (insn, 7);
   unsigned int rm = bits (insn, 3, 6);
@@ -5153,7 +5154,7 @@  thumb_copy_bx_blx_reg (struct gdbarch *gdbarch, uint16_t insn,
 
 static void
 cleanup_alu_imm (struct gdbarch *gdbarch,
-		 struct regcache *regs, struct displaced_step_closure *dsc)
+		 struct regcache *regs, arm_displaced_step_closure *dsc)
 {
   ULONGEST rd_val = displaced_read_reg (regs, dsc, 0);
   displaced_write_reg (regs, dsc, 0, dsc->tmp[0], CANNOT_WRITE_PC);
@@ -5163,7 +5164,7 @@  cleanup_alu_imm (struct gdbarch *gdbarch,
 
 static int
 arm_copy_alu_imm (struct gdbarch *gdbarch, uint32_t insn, struct regcache *regs,
-		  struct displaced_step_closure *dsc)
+		  arm_displaced_step_closure *dsc)
 {
   unsigned int rn = bits (insn, 16, 19);
   unsigned int rd = bits (insn, 12, 15);
@@ -5212,7 +5213,7 @@  arm_copy_alu_imm (struct gdbarch *gdbarch, uint32_t insn, struct regcache *regs,
 static int
 thumb2_copy_alu_imm (struct gdbarch *gdbarch, uint16_t insn1,
 		     uint16_t insn2, struct regcache *regs,
-		     struct displaced_step_closure *dsc)
+		     arm_displaced_step_closure *dsc)
 {
   unsigned int op = bits (insn1, 5, 8);
   unsigned int rn, rm, rd;
@@ -5265,7 +5266,7 @@  thumb2_copy_alu_imm (struct gdbarch *gdbarch, uint16_t insn1,
 
 static void
 cleanup_alu_reg (struct gdbarch *gdbarch,
-		 struct regcache *regs, struct displaced_step_closure *dsc)
+		 struct regcache *regs, arm_displaced_step_closure *dsc)
 {
   ULONGEST rd_val;
   int i;
@@ -5280,7 +5281,7 @@  cleanup_alu_reg (struct gdbarch *gdbarch,
 
 static void
 install_alu_reg (struct gdbarch *gdbarch, struct regcache *regs,
-		 struct displaced_step_closure *dsc,
+		 arm_displaced_step_closure *dsc,
 		 unsigned int rd, unsigned int rn, unsigned int rm)
 {
   ULONGEST rd_val, rn_val, rm_val;
@@ -5313,7 +5314,7 @@  install_alu_reg (struct gdbarch *gdbarch, struct regcache *regs,
 
 static int
 arm_copy_alu_reg (struct gdbarch *gdbarch, uint32_t insn, struct regcache *regs,
-		  struct displaced_step_closure *dsc)
+		  arm_displaced_step_closure *dsc)
 {
   unsigned int op = bits (insn, 21, 24);
   int is_mov = (op == 0xd);
@@ -5338,7 +5339,7 @@  arm_copy_alu_reg (struct gdbarch *gdbarch, uint32_t insn, struct regcache *regs,
 static int
 thumb_copy_alu_reg (struct gdbarch *gdbarch, uint16_t insn,
 		    struct regcache *regs,
-		    struct displaced_step_closure *dsc)
+		    arm_displaced_step_closure *dsc)
 {
   unsigned rm, rd;
 
@@ -5364,7 +5365,7 @@  thumb_copy_alu_reg (struct gdbarch *gdbarch, uint16_t insn,
 static void
 cleanup_alu_shifted_reg (struct gdbarch *gdbarch,
 			 struct regcache *regs,
-			 struct displaced_step_closure *dsc)
+			 arm_displaced_step_closure *dsc)
 {
   ULONGEST rd_val = displaced_read_reg (regs, dsc, 0);
   int i;
@@ -5377,7 +5378,7 @@  cleanup_alu_shifted_reg (struct gdbarch *gdbarch,
 
 static void
 install_alu_shifted_reg (struct gdbarch *gdbarch, struct regcache *regs,
-			 struct displaced_step_closure *dsc,
+			 arm_displaced_step_closure *dsc,
 			 unsigned int rd, unsigned int rn, unsigned int rm,
 			 unsigned rs)
 {
@@ -5416,7 +5417,7 @@  install_alu_shifted_reg (struct gdbarch *gdbarch, struct regcache *regs,
 static int
 arm_copy_alu_shifted_reg (struct gdbarch *gdbarch, uint32_t insn,
 			  struct regcache *regs,
-			  struct displaced_step_closure *dsc)
+			  arm_displaced_step_closure *dsc)
 {
   unsigned int op = bits (insn, 21, 24);
   int is_mov = (op == 0xd);
@@ -5449,7 +5450,7 @@  arm_copy_alu_shifted_reg (struct gdbarch *gdbarch, uint32_t insn,
 
 static void
 cleanup_load (struct gdbarch *gdbarch, struct regcache *regs,
-	      struct displaced_step_closure *dsc)
+	      arm_displaced_step_closure *dsc)
 {
   ULONGEST rt_val, rt_val2 = 0, rn_val;
 
@@ -5478,7 +5479,7 @@  cleanup_load (struct gdbarch *gdbarch, struct regcache *regs,
 
 static void
 cleanup_store (struct gdbarch *gdbarch, struct regcache *regs,
-	       struct displaced_step_closure *dsc)
+	       arm_displaced_step_closure *dsc)
 {
   ULONGEST rn_val = displaced_read_reg (regs, dsc, 2);
 
@@ -5501,7 +5502,7 @@  cleanup_store (struct gdbarch *gdbarch, struct regcache *regs,
 
 static int
 arm_copy_extra_ld_st (struct gdbarch *gdbarch, uint32_t insn, int unprivileged,
-		      struct regcache *regs, struct displaced_step_closure *dsc)
+		      struct regcache *regs, arm_displaced_step_closure *dsc)
 {
   unsigned int op1 = bits (insn, 20, 24);
   unsigned int op2 = bits (insn, 5, 6);
@@ -5575,7 +5576,7 @@  arm_copy_extra_ld_st (struct gdbarch *gdbarch, uint32_t insn, int unprivileged,
 
 static void
 install_load_store (struct gdbarch *gdbarch, struct regcache *regs,
-		    struct displaced_step_closure *dsc, int load,
+		    arm_displaced_step_closure *dsc, int load,
 		    int immed, int writeback, int size, int usermode,
 		    int rt, int rm, int rn)
 {
@@ -5631,7 +5632,7 @@  install_load_store (struct gdbarch *gdbarch, struct regcache *regs,
 static int
 thumb2_copy_load_literal (struct gdbarch *gdbarch, uint16_t insn1,
 			  uint16_t insn2, struct regcache *regs,
-			  struct displaced_step_closure *dsc, int size)
+			  arm_displaced_step_closure *dsc, int size)
 {
   unsigned int u_bit = bit (insn1, 7);
   unsigned int rt = bits (insn2, 12, 15);
@@ -5687,7 +5688,7 @@  thumb2_copy_load_literal (struct gdbarch *gdbarch, uint16_t insn1,
 static int
 thumb2_copy_load_reg_imm (struct gdbarch *gdbarch, uint16_t insn1,
 			  uint16_t insn2, struct regcache *regs,
-			  struct displaced_step_closure *dsc,
+			  arm_displaced_step_closure *dsc,
 			  int writeback, int immed)
 {
   unsigned int rt = bits (insn2, 12, 15);
@@ -5736,7 +5737,7 @@  thumb2_copy_load_reg_imm (struct gdbarch *gdbarch, uint16_t insn1,
 static int
 arm_copy_ldr_str_ldrb_strb (struct gdbarch *gdbarch, uint32_t insn,
 			    struct regcache *regs,
-			    struct displaced_step_closure *dsc,
+			    arm_displaced_step_closure *dsc,
 			    int load, int size, int usermode)
 {
   int immed = !bit (insn, 25);
@@ -5820,7 +5821,7 @@  arm_copy_ldr_str_ldrb_strb (struct gdbarch *gdbarch, uint32_t insn,
 
 static void
 cleanup_block_load_all (struct gdbarch *gdbarch, struct regcache *regs,
-			struct displaced_step_closure *dsc)
+			arm_displaced_step_closure *dsc)
 {
   int inc = dsc->u.block.increment;
   int bump_before = dsc->u.block.before ? (inc ? 4 : -4) : 0;
@@ -5881,7 +5882,7 @@  cleanup_block_load_all (struct gdbarch *gdbarch, struct regcache *regs,
 
 static void
 cleanup_block_store_pc (struct gdbarch *gdbarch, struct regcache *regs,
-			struct displaced_step_closure *dsc)
+			arm_displaced_step_closure *dsc)
 {
   uint32_t status = displaced_read_reg (regs, dsc, ARM_PS_REGNUM);
   int store_executed = condition_true (dsc->u.block.cond, status);
@@ -5932,7 +5933,7 @@  cleanup_block_store_pc (struct gdbarch *gdbarch, struct regcache *regs,
 static void
 cleanup_block_load_pc (struct gdbarch *gdbarch,
 		       struct regcache *regs,
-		       struct displaced_step_closure *dsc)
+		       arm_displaced_step_closure *dsc)
 {
   uint32_t status = displaced_read_reg (regs, dsc, ARM_PS_REGNUM);
   int load_executed = condition_true (dsc->u.block.cond, status);
@@ -6012,7 +6013,7 @@  cleanup_block_load_pc (struct gdbarch *gdbarch,
 static int
 arm_copy_block_xfer (struct gdbarch *gdbarch, uint32_t insn,
 		     struct regcache *regs,
-		     struct displaced_step_closure *dsc)
+		     arm_displaced_step_closure *dsc)
 {
   int load = bit (insn, 20);
   int user = bit (insn, 22);
@@ -6126,7 +6127,7 @@  arm_copy_block_xfer (struct gdbarch *gdbarch, uint32_t insn,
 static int
 thumb2_copy_block_xfer (struct gdbarch *gdbarch, uint16_t insn1, uint16_t insn2,
 			struct regcache *regs,
-			struct displaced_step_closure *dsc)
+			arm_displaced_step_closure *dsc)
 {
   int rn = bits (insn1, 0, 3);
   int load = bit (insn1, 4);
@@ -6272,7 +6273,7 @@  arm_software_single_step (struct regcache *regcache)
 
 static void
 cleanup_svc (struct gdbarch *gdbarch, struct regcache *regs,
-	     struct displaced_step_closure *dsc)
+	     arm_displaced_step_closure *dsc)
 {
   CORE_ADDR resume_addr = dsc->insn_addr + dsc->insn_size;
 
@@ -6288,7 +6289,7 @@  cleanup_svc (struct gdbarch *gdbarch, struct regcache *regs,
 
 static int
 install_svc (struct gdbarch *gdbarch, struct regcache *regs,
-	     struct displaced_step_closure *dsc)
+	     arm_displaced_step_closure *dsc)
 {
   /* Preparation: none.
      Insn: unmodified svc.
@@ -6310,7 +6311,7 @@  install_svc (struct gdbarch *gdbarch, struct regcache *regs,
 
 static int
 arm_copy_svc (struct gdbarch *gdbarch, uint32_t insn,
-	      struct regcache *regs, struct displaced_step_closure *dsc)
+	      struct regcache *regs, arm_displaced_step_closure *dsc)
 {
 
   if (debug_displaced)
@@ -6324,7 +6325,7 @@  arm_copy_svc (struct gdbarch *gdbarch, uint32_t insn,
 
 static int
 thumb_copy_svc (struct gdbarch *gdbarch, uint16_t insn,
-		struct regcache *regs, struct displaced_step_closure *dsc)
+		struct regcache *regs, arm_displaced_step_closure *dsc)
 {
 
   if (debug_displaced)
@@ -6340,7 +6341,7 @@  thumb_copy_svc (struct gdbarch *gdbarch, uint16_t insn,
 
 static int
 arm_copy_undef (struct gdbarch *gdbarch, uint32_t insn,
-		struct displaced_step_closure *dsc)
+		arm_displaced_step_closure *dsc)
 {
   if (debug_displaced)
     fprintf_unfiltered (gdb_stdlog,
@@ -6354,7 +6355,7 @@  arm_copy_undef (struct gdbarch *gdbarch, uint32_t insn,
 
 static int
 thumb_32bit_copy_undef (struct gdbarch *gdbarch, uint16_t insn1, uint16_t insn2,
-                       struct displaced_step_closure *dsc)
+                       arm_displaced_step_closure *dsc)
 {
 
   if (debug_displaced)
@@ -6373,7 +6374,7 @@  thumb_32bit_copy_undef (struct gdbarch *gdbarch, uint16_t insn1, uint16_t insn2,
 
 static int
 arm_copy_unpred (struct gdbarch *gdbarch, uint32_t insn,
-		 struct displaced_step_closure *dsc)
+		 arm_displaced_step_closure *dsc)
 {
   if (debug_displaced)
     fprintf_unfiltered (gdb_stdlog, "displaced: copying unpredictable insn "
@@ -6390,7 +6391,7 @@  arm_copy_unpred (struct gdbarch *gdbarch, uint32_t insn,
 static int
 arm_decode_misc_memhint_neon (struct gdbarch *gdbarch, uint32_t insn,
 			      struct regcache *regs,
-			      struct displaced_step_closure *dsc)
+			      arm_displaced_step_closure *dsc)
 {
   unsigned int op1 = bits (insn, 20, 26), op2 = bits (insn, 4, 7);
   unsigned int rn = bits (insn, 16, 19);
@@ -6450,7 +6451,7 @@  arm_decode_misc_memhint_neon (struct gdbarch *gdbarch, uint32_t insn,
 static int
 arm_decode_unconditional (struct gdbarch *gdbarch, uint32_t insn,
 			  struct regcache *regs,
-			  struct displaced_step_closure *dsc)
+			  arm_displaced_step_closure *dsc)
 {
   if (bit (insn, 27) == 0)
     return arm_decode_misc_memhint_neon (gdbarch, insn, regs, dsc);
@@ -6535,7 +6536,7 @@  arm_decode_unconditional (struct gdbarch *gdbarch, uint32_t insn,
 static int
 arm_decode_miscellaneous (struct gdbarch *gdbarch, uint32_t insn,
 			  struct regcache *regs,
-			  struct displaced_step_closure *dsc)
+			  arm_displaced_step_closure *dsc)
 {
   unsigned int op2 = bits (insn, 4, 6);
   unsigned int op = bits (insn, 21, 22);
@@ -6585,7 +6586,7 @@  arm_decode_miscellaneous (struct gdbarch *gdbarch, uint32_t insn,
 static int
 arm_decode_dp_misc (struct gdbarch *gdbarch, uint32_t insn,
 		    struct regcache *regs,
-		    struct displaced_step_closure *dsc)
+		    arm_displaced_step_closure *dsc)
 {
   if (bit (insn, 25))
     switch (bits (insn, 20, 24))
@@ -6631,7 +6632,7 @@  arm_decode_dp_misc (struct gdbarch *gdbarch, uint32_t insn,
 static int
 arm_decode_ld_st_word_ubyte (struct gdbarch *gdbarch, uint32_t insn,
 			     struct regcache *regs,
-			     struct displaced_step_closure *dsc)
+			     arm_displaced_step_closure *dsc)
 {
   int a = bit (insn, 25), b = bit (insn, 4);
   uint32_t op1 = bits (insn, 20, 24);
@@ -6667,7 +6668,7 @@  arm_decode_ld_st_word_ubyte (struct gdbarch *gdbarch, uint32_t insn,
 
 static int
 arm_decode_media (struct gdbarch *gdbarch, uint32_t insn,
-		  struct displaced_step_closure *dsc)
+		  arm_displaced_step_closure *dsc)
 {
   switch (bits (insn, 20, 24))
     {
@@ -6724,7 +6725,7 @@  arm_decode_media (struct gdbarch *gdbarch, uint32_t insn,
 static int
 arm_decode_b_bl_ldmstm (struct gdbarch *gdbarch, uint32_t insn,
 			struct regcache *regs,
-			struct displaced_step_closure *dsc)
+			arm_displaced_step_closure *dsc)
 {
   if (bit (insn, 25))
     return arm_copy_b_bl_blx (gdbarch, insn, regs, dsc);
@@ -6735,7 +6736,7 @@  arm_decode_b_bl_ldmstm (struct gdbarch *gdbarch, uint32_t insn,
 static int
 arm_decode_ext_reg_ld_st (struct gdbarch *gdbarch, uint32_t insn,
 			  struct regcache *regs,
-			  struct displaced_step_closure *dsc)
+			  arm_displaced_step_closure *dsc)
 {
   unsigned int opcode = bits (insn, 20, 24);
 
@@ -6768,7 +6769,7 @@  arm_decode_ext_reg_ld_st (struct gdbarch *gdbarch, uint32_t insn,
 static int
 thumb2_decode_dp_shift_reg (struct gdbarch *gdbarch, uint16_t insn1,
 			    uint16_t insn2,  struct regcache *regs,
-			    struct displaced_step_closure *dsc)
+			    arm_displaced_step_closure *dsc)
 {
   /* PC is only allowed to be used in instruction MOV.  */
 
@@ -6789,7 +6790,7 @@  thumb2_decode_dp_shift_reg (struct gdbarch *gdbarch, uint16_t insn1,
 static int
 thumb2_decode_ext_reg_ld_st (struct gdbarch *gdbarch, uint16_t insn1,
 			     uint16_t insn2,  struct regcache *regs,
-			     struct displaced_step_closure *dsc)
+			     arm_displaced_step_closure *dsc)
 {
   unsigned int opcode = bits (insn1, 4, 8);
 
@@ -6824,7 +6825,7 @@  thumb2_decode_ext_reg_ld_st (struct gdbarch *gdbarch, uint16_t insn1,
 
 static int
 arm_decode_svc_copro (struct gdbarch *gdbarch, uint32_t insn,
-		      struct regcache *regs, struct displaced_step_closure *dsc)
+		      struct regcache *regs, arm_displaced_step_closure *dsc)
 {
   unsigned int op1 = bits (insn, 20, 25);
   int op = bit (insn, 4);
@@ -6870,7 +6871,7 @@  arm_decode_svc_copro (struct gdbarch *gdbarch, uint32_t insn,
 static int
 thumb2_decode_svc_copro (struct gdbarch *gdbarch, uint16_t insn1,
 			 uint16_t insn2, struct regcache *regs,
-			 struct displaced_step_closure *dsc)
+			 arm_displaced_step_closure *dsc)
 {
   unsigned int coproc = bits (insn2, 8, 11);
   unsigned int bit_5_8 = bits (insn1, 5, 8);
@@ -6910,7 +6911,7 @@  thumb2_decode_svc_copro (struct gdbarch *gdbarch, uint16_t insn1,
 
 static void
 install_pc_relative (struct gdbarch *gdbarch, struct regcache *regs,
-		     struct displaced_step_closure *dsc, int rd)
+		     arm_displaced_step_closure *dsc, int rd)
 {
   /* ADR Rd, #imm
 
@@ -6928,7 +6929,7 @@  install_pc_relative (struct gdbarch *gdbarch, struct regcache *regs,
 
 static int
 thumb_copy_pc_relative_16bit (struct gdbarch *gdbarch, struct regcache *regs,
-			      struct displaced_step_closure *dsc,
+			      arm_displaced_step_closure *dsc,
 			      int rd, unsigned int imm)
 {
 
@@ -6943,7 +6944,7 @@  thumb_copy_pc_relative_16bit (struct gdbarch *gdbarch, struct regcache *regs,
 static int
 thumb_decode_pc_relative_16bit (struct gdbarch *gdbarch, uint16_t insn,
 				struct regcache *regs,
-				struct displaced_step_closure *dsc)
+				arm_displaced_step_closure *dsc)
 {
   unsigned int rd = bits (insn, 8, 10);
   unsigned int imm8 = bits (insn, 0, 7);
@@ -6959,7 +6960,7 @@  thumb_decode_pc_relative_16bit (struct gdbarch *gdbarch, uint16_t insn,
 static int
 thumb_copy_pc_relative_32bit (struct gdbarch *gdbarch, uint16_t insn1,
 			      uint16_t insn2, struct regcache *regs,
-			      struct displaced_step_closure *dsc)
+			      arm_displaced_step_closure *dsc)
 {
   unsigned int rd = bits (insn2, 8, 11);
   /* Since immediate has the same encoding in ADR ADD and SUB, so we simply
@@ -6996,7 +6997,7 @@  thumb_copy_pc_relative_32bit (struct gdbarch *gdbarch, uint16_t insn1,
 static int
 thumb_copy_16bit_ldr_literal (struct gdbarch *gdbarch, uint16_t insn1,
 			      struct regcache *regs,
-			      struct displaced_step_closure *dsc)
+			      arm_displaced_step_closure *dsc)
 {
   unsigned int rt = bits (insn1, 8, 10);
   unsigned int pc;
@@ -7046,7 +7047,7 @@  thumb_copy_16bit_ldr_literal (struct gdbarch *gdbarch, uint16_t insn1,
 static int
 thumb_copy_cbnz_cbz (struct gdbarch *gdbarch, uint16_t insn1,
 		     struct regcache *regs,
-		     struct displaced_step_closure *dsc)
+		     arm_displaced_step_closure *dsc)
 {
   int non_zero = bit (insn1, 11);
   unsigned int imm5 = (bit (insn1, 9) << 6) | (bits (insn1, 3, 7) << 1);
@@ -7084,7 +7085,7 @@  thumb_copy_cbnz_cbz (struct gdbarch *gdbarch, uint16_t insn1,
 static int
 thumb2_copy_table_branch (struct gdbarch *gdbarch, uint16_t insn1,
 			  uint16_t insn2, struct regcache *regs,
-			  struct displaced_step_closure *dsc)
+			  arm_displaced_step_closure *dsc)
 {
   ULONGEST rn_val, rm_val;
   int is_tbh = bit (insn2, 4);
@@ -7127,7 +7128,7 @@  thumb2_copy_table_branch (struct gdbarch *gdbarch, uint16_t insn1,
 
 static void
 cleanup_pop_pc_16bit_all (struct gdbarch *gdbarch, struct regcache *regs,
-			  struct displaced_step_closure *dsc)
+			  arm_displaced_step_closure *dsc)
 {
   /* PC <- r7 */
   int val = displaced_read_reg (regs, dsc, 7);
@@ -7145,7 +7146,7 @@  cleanup_pop_pc_16bit_all (struct gdbarch *gdbarch, struct regcache *regs,
 static int
 thumb_copy_pop_pc_16bit (struct gdbarch *gdbarch, uint16_t insn1,
 			 struct regcache *regs,
-			 struct displaced_step_closure *dsc)
+			 arm_displaced_step_closure *dsc)
 {
   dsc->u.block.regmask = insn1 & 0x00ff;
 
@@ -7218,7 +7219,7 @@  thumb_copy_pop_pc_16bit (struct gdbarch *gdbarch, uint16_t insn1,
 static void
 thumb_process_displaced_16bit_insn (struct gdbarch *gdbarch, uint16_t insn1,
 				    struct regcache *regs,
-				    struct displaced_step_closure *dsc)
+				    arm_displaced_step_closure *dsc)
 {
   unsigned short op_bit_12_15 = bits (insn1, 12, 15);
   unsigned short op_bit_10_11 = bits (insn1, 10, 11);
@@ -7322,7 +7323,7 @@  static int
 decode_thumb_32bit_ld_mem_hints (struct gdbarch *gdbarch,
 				 uint16_t insn1, uint16_t insn2,
 				 struct regcache *regs,
-				 struct displaced_step_closure *dsc)
+				 arm_displaced_step_closure *dsc)
 {
   int rt = bits (insn2, 12, 15);
   int rn = bits (insn1, 0, 3);
@@ -7401,7 +7402,7 @@  decode_thumb_32bit_ld_mem_hints (struct gdbarch *gdbarch,
 static void
 thumb_process_displaced_32bit_insn (struct gdbarch *gdbarch, uint16_t insn1,
 				    uint16_t insn2, struct regcache *regs,
-				    struct displaced_step_closure *dsc)
+				    arm_displaced_step_closure *dsc)
 {
   int err = 0;
   unsigned short op = bit (insn2, 15);
@@ -7529,7 +7530,7 @@  thumb_process_displaced_32bit_insn (struct gdbarch *gdbarch, uint16_t insn1,
 static void
 thumb_process_displaced_insn (struct gdbarch *gdbarch, CORE_ADDR from,
 			      struct regcache *regs,
-			      struct displaced_step_closure *dsc)
+			      arm_displaced_step_closure *dsc)
 {
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
   uint16_t insn1
@@ -7554,7 +7555,7 @@  thumb_process_displaced_insn (struct gdbarch *gdbarch, CORE_ADDR from,
 void
 arm_process_displaced_insn (struct gdbarch *gdbarch, CORE_ADDR from,
 			    CORE_ADDR to, struct regcache *regs,
-			    struct displaced_step_closure *dsc)
+			    arm_displaced_step_closure *dsc)
 {
   int err = 0;
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
@@ -7613,7 +7614,7 @@  arm_process_displaced_insn (struct gdbarch *gdbarch, CORE_ADDR from,
 
 void
 arm_displaced_init_closure (struct gdbarch *gdbarch, CORE_ADDR from,
-			    CORE_ADDR to, struct displaced_step_closure *dsc)
+			    CORE_ADDR to, arm_displaced_step_closure *dsc)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   unsigned int i, len, offset;
@@ -7670,10 +7671,12 @@  arm_displaced_init_closure (struct gdbarch *gdbarch, CORE_ADDR from,
 
 void
 arm_displaced_step_fixup (struct gdbarch *gdbarch,
-			  struct displaced_step_closure *dsc,
+			  struct displaced_step_closure *dsc_,
 			  CORE_ADDR from, CORE_ADDR to,
 			  struct regcache *regs)
 {
+  arm_displaced_step_closure *dsc = (arm_displaced_step_closure *) dsc_;
+
   if (dsc->cleanup)
     dsc->cleanup (gdbarch, regs, dsc);
 
diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h
index 1329782..4bb24ff 100644
--- a/gdb/arm-tdep.h
+++ b/gdb/arm-tdep.h
@@ -28,6 +28,7 @@  struct arm_get_next_pcs;
 struct gdb_get_next_pcs;
 
 #include "arch/arm.h"
+#include "infrun.h"
 
 #include <vector>
 
@@ -153,7 +154,7 @@  struct gdbarch_tdep
    sequence) and any scratch words, etc.  */
 #define DISPLACED_MODIFIED_INSNS	8
 
-struct displaced_step_closure
+struct arm_displaced_step_closure : public displaced_step_closure
 {
   ULONGEST tmp[DISPLACED_TEMPS];
   int rd;
@@ -200,7 +201,7 @@  struct displaced_step_closure
       /* If non-NULL, override generic SVC handling (e.g. for a particular
          OS).  */
       int (*copy_svc_os) (struct gdbarch *gdbarch, struct regcache *regs,
-			  struct displaced_step_closure *dsc);
+			  arm_displaced_step_closure *dsc);
     } svc;
   } u;
 
@@ -219,7 +220,7 @@  struct displaced_step_closure
   CORE_ADDR insn_addr;
   CORE_ADDR scratch_base;
   void (*cleanup) (struct gdbarch *, struct regcache *,
-		   struct displaced_step_closure *);
+		   arm_displaced_step_closure *);
 };
 
 /* Values for the WRITE_PC argument to displaced_write_reg.  If the register
@@ -238,16 +239,16 @@  enum pc_write_style
 extern void
   arm_process_displaced_insn (struct gdbarch *gdbarch, CORE_ADDR from,
 			      CORE_ADDR to, struct regcache *regs,
-			      struct displaced_step_closure *dsc);
+			      arm_displaced_step_closure *dsc);
 extern void
   arm_displaced_init_closure (struct gdbarch *gdbarch, CORE_ADDR from,
-			      CORE_ADDR to, struct displaced_step_closure *dsc);
+			      CORE_ADDR to, arm_displaced_step_closure *dsc);
 extern ULONGEST
-  displaced_read_reg (struct regcache *regs, struct displaced_step_closure *dsc,
+  displaced_read_reg (struct regcache *regs, arm_displaced_step_closure *dsc,
 		      int regno);
 extern void
   displaced_write_reg (struct regcache *regs,
-		       struct displaced_step_closure *dsc, int regno,
+		       arm_displaced_step_closure *dsc, int regno,
 		       ULONGEST val, enum pc_write_style write_pc);
 
 CORE_ADDR arm_skip_stub (struct frame_info *, CORE_ADDR);
diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
index 8cec675..84d4435 100644
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -802,21 +802,21 @@  i386_linux_displaced_step_copy_insn (struct gdbarch *gdbarch,
 				     CORE_ADDR from, CORE_ADDR to,
 				     struct regcache *regs)
 {
-  struct displaced_step_closure *closure;
-
-  closure = i386_displaced_step_copy_insn (gdbarch, from, to, regs);
+  displaced_step_closure *closure_
+    =  i386_displaced_step_copy_insn (gdbarch, from, to, regs);
 
   if (i386_linux_get_syscall_number_from_regcache (regs) != -1)
     {
       /* The closure returned by i386_displaced_step_copy_insn is simply a
-         buffer with a copy of the instruction. */
-      gdb_byte *insn = (gdb_byte *) closure;
+	 buffer with a copy of the instruction. */
+      i386_displaced_step_closure *closure
+	= (i386_displaced_step_closure *) closure_;
 
       /* Fake nop.  */
-      insn[0] = 0x90;
+      closure->buf[0] = 0x90;
     }
 
-  return closure;
+  return closure_;
 }
 
 static void
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 46e5e32..26628ee 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -802,7 +802,8 @@  i386_displaced_step_copy_insn (struct gdbarch *gdbarch,
 			       struct regcache *regs)
 {
   size_t len = gdbarch_max_insn_length (gdbarch);
-  gdb_byte *buf = (gdb_byte *) xmalloc (len);
+  i386_displaced_step_closure *closure = new i386_displaced_step_closure (len);
+  gdb_byte *buf = closure->buf.data ();
 
   read_memory (from, buf, len);
 
@@ -827,7 +828,7 @@  i386_displaced_step_copy_insn (struct gdbarch *gdbarch,
       displaced_step_dump_bytes (gdb_stdlog, buf, len);
     }
 
-  return (struct displaced_step_closure *) buf;
+  return closure;
 }
 
 /* Fix up the state of registers and memory after having single-stepped
@@ -835,7 +836,7 @@  i386_displaced_step_copy_insn (struct gdbarch *gdbarch,
 
 void
 i386_displaced_step_fixup (struct gdbarch *gdbarch,
-                           struct displaced_step_closure *closure,
+                           struct displaced_step_closure *closure_,
                            CORE_ADDR from, CORE_ADDR to,
                            struct regcache *regs)
 {
@@ -847,8 +848,9 @@  i386_displaced_step_fixup (struct gdbarch *gdbarch,
      applying it.  */
   ULONGEST insn_offset = to - from;
 
-  /* Our closure is a copy of the instruction.  */
-  gdb_byte *insn = (gdb_byte *) closure;
+  i386_displaced_step_closure *closure
+    = (i386_displaced_step_closure *) closure_;
+  gdb_byte *insn = closure->buf.data ();
   /* The start of the insn, needed in case we see some prefixes.  */
   gdb_byte *insn_start = insn;
 
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 99b89e7..f190bb3 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -20,6 +20,8 @@ 
 #ifndef I386_TDEP_H
 #define I386_TDEP_H
 
+#include "infrun.h"
+
 struct frame_info;
 struct gdbarch;
 struct reggroup;
@@ -416,6 +418,8 @@  extern void
 				     void *cb_data,
 				     const struct regcache *regcache);
 
+typedef buf_displaced_step_closure i386_displaced_step_closure;
+
 extern struct displaced_step_closure *i386_displaced_step_copy_insn
   (struct gdbarch *gdbarch, CORE_ADDR from, CORE_ADDR to,
    struct regcache *regs);
diff --git a/gdb/infrun.c b/gdb/infrun.c
index d00c5f6..c58ceb6 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1445,8 +1445,6 @@  step_over_info_valid_p (void)
      same effect the instruction would have had if we had executed it
      at its original address.  We use this in step n3.
 
-   - gdbarch_displaced_step_free_closure provides cleanup.
-
    The gdbarch_displaced_step_copy_insn and
    gdbarch_displaced_step_fixup functions must be written so that
    copying an instruction with gdbarch_displaced_step_copy_insn,
@@ -1484,6 +1482,10 @@  step_over_info_valid_p (void)
    displaced step operation on it.  See displaced_step_prepare and
    displaced_step_fixup for details.  */
 
+/* Default destructor for displaced_step_closure.  */
+
+displaced_step_closure::~displaced_step_closure () = default;
+
 /* Per-inferior displaced stepping state.  */
 struct displaced_step_inferior_state
 {
@@ -1709,7 +1711,7 @@  displaced_step_clear (struct displaced_step_inferior_state *displaced)
   /* Indicate that there is no cleanup pending.  */
   displaced->step_ptid = null_ptid;
 
-  xfree (displaced->step_closure);
+  delete displaced->step_closure;
   displaced->step_closure = NULL;
 }
 
diff --git a/gdb/infrun.h b/gdb/infrun.h
index 2003637..08dfebf 100644
--- a/gdb/infrun.h
+++ b/gdb/infrun.h
@@ -19,6 +19,7 @@ 
 #define INFRUN_H 1
 
 #include "symtab.h"
+#include "common/byte-vector.h"
 
 struct target_waitstatus;
 struct frame_info;
@@ -243,4 +244,22 @@  extern void all_uis_check_sync_execution_done (void);
    started or re-started).  */
 extern void all_uis_on_sync_execution_starting (void);
 
+/* Base class for displaced stepping closures (the arch-specific data).  */
+
+struct displaced_step_closure
+{
+  virtual ~displaced_step_closure () = 0;
+};
+
+/* A simple displaced step closure that contains only a byte buffer.  */
+
+struct buf_displaced_step_closure : displaced_step_closure
+{
+  buf_displaced_step_closure (int buf_size)
+  : buf (buf_size)
+  {}
+
+  gdb::byte_vector buf;
+};
+
 #endif /* INFRUN_H */
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index df1a84d..e38f41b 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -1014,6 +1014,8 @@  typedef BP_MANIPULATION_ENDIAN (little_breakpoint, big_breakpoint)
 					 || (insn & STORE_CONDITIONAL_MASK) == STHCX_INSTRUCTION \
 					 || (insn & STORE_CONDITIONAL_MASK) == STQCX_INSTRUCTION)
 
+typedef buf_displaced_step_closure ppc_displaced_step_closure;
+
 /* We can't displaced step atomic sequences.  */
 
 static struct displaced_step_closure *
@@ -1022,8 +1024,9 @@  ppc_displaced_step_copy_insn (struct gdbarch *gdbarch,
 			      struct regcache *regs)
 {
   size_t len = gdbarch_max_insn_length (gdbarch);
-  gdb_byte *buf = (gdb_byte *) xmalloc (len);
-  struct cleanup *old_chain = make_cleanup (xfree, buf);
+  std::unique_ptr<ppc_displaced_step_closure> closure
+    (new ppc_displaced_step_closure (len));
+  gdb_byte *buf = closure->buf.data ();
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   int insn;
 
@@ -1041,7 +1044,7 @@  ppc_displaced_step_copy_insn (struct gdbarch *gdbarch,
 			      "atomic sequence at %s\n",
 			      paddress (gdbarch, from));
 	}
-      do_cleanups (old_chain);
+
       return NULL;
     }
 
@@ -1054,22 +1057,22 @@  ppc_displaced_step_copy_insn (struct gdbarch *gdbarch,
       displaced_step_dump_bytes (gdb_stdlog, buf, len);
     }
 
-  discard_cleanups (old_chain);
-  return (struct displaced_step_closure *) buf;
+  return closure.release ();
 }
 
 /* Fix up the state of registers and memory after having single-stepped
    a displaced instruction.  */
 static void
 ppc_displaced_step_fixup (struct gdbarch *gdbarch,
-			  struct displaced_step_closure *closure,
+			  struct displaced_step_closure *closure_,
 			  CORE_ADDR from, CORE_ADDR to,
 			  struct regcache *regs)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   /* Our closure is a copy of the instruction.  */
-  ULONGEST insn  = extract_unsigned_integer ((gdb_byte *) closure,
-					      PPC_INSN_SIZE, byte_order);
+  ppc_displaced_step_closure *closure = (ppc_displaced_step_closure *) closure_;
+  ULONGEST insn  = extract_unsigned_integer (closure->buf.data (),
+					     PPC_INSN_SIZE, byte_order);
   ULONGEST opcode = 0;
   /* Offset for non PC-relative instructions.  */
   LONGEST offset = PPC_INSN_SIZE;
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index d48364b..8847e8d 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -1861,6 +1861,8 @@  is_non_branch_ril (gdb_byte *insn)
   return 0;
 }
 
+typedef buf_displaced_step_closure s390_displaced_step_closure;
+
 /* Implementation of gdbarch_displaced_step_copy_insn.  */
 
 static struct displaced_step_closure *
@@ -1869,8 +1871,9 @@  s390_displaced_step_copy_insn (struct gdbarch *gdbarch,
 			       struct regcache *regs)
 {
   size_t len = gdbarch_max_insn_length (gdbarch);
-  gdb_byte *buf = (gdb_byte *) xmalloc (len);
-  struct cleanup *old_chain = make_cleanup (xfree, buf);
+  std::unique_ptr<s390_displaced_step_closure> closure
+    (new s390_displaced_step_closure (len));
+  gdb_byte *buf = closure->buf.data ();
 
   read_memory (from, buf, len);
 
@@ -1898,7 +1901,7 @@  s390_displaced_step_copy_insn (struct gdbarch *gdbarch,
 				  "RIL instruction: offset %s out of range\n",
 				  plongest (offset));
 	    }
-	  do_cleanups (old_chain);
+
 	  return NULL;
 	}
 
@@ -1914,20 +1917,21 @@  s390_displaced_step_copy_insn (struct gdbarch *gdbarch,
       displaced_step_dump_bytes (gdb_stdlog, buf, len);
     }
 
-  discard_cleanups (old_chain);
-  return (struct displaced_step_closure *) buf;
+  return closure.release ();
 }
 
 /* Fix up the state of registers and memory after having single-stepped
    a displaced instruction.  */
 static void
 s390_displaced_step_fixup (struct gdbarch *gdbarch,
-			   struct displaced_step_closure *closure,
+			   struct displaced_step_closure *closure_,
 			   CORE_ADDR from, CORE_ADDR to,
 			   struct regcache *regs)
 {
   /* Our closure is a copy of the instruction.  */
-  gdb_byte *insn = (gdb_byte *) closure;
+  s390_displaced_step_closure *closure
+    = (s390_displaced_step_closure *) closure_;
+  gdb_byte *insn = closure->buf.data ();
   static int s390_instrlen[] = { 2, 4, 4, 6 };
   int insnlen = s390_instrlen[insn[0] >> 6];