Refactor svr4_create_solib_event_breakpoints
[external/binutils.git] / gdb / arm-tdep.c
index 2ba77e2..5dcc443 100644 (file)
 #include "coff/internal.h"
 #include "elf/arm.h"
 
-#include "common/vec.h"
+#include "gdbsupport/vec.h"
 
 #include "record.h"
 #include "record-full.h"
 #include <algorithm>
 
-#include "features/arm/arm-with-m.c"
-#include "features/arm/arm-with-m-fpa-layout.c"
-#include "features/arm/arm-with-m-vfp-d16.c"
-#include "features/arm/arm-with-iwmmxt.c"
-#include "features/arm/arm-with-vfpv2.c"
-#include "features/arm/arm-with-vfpv3.c"
-#include "features/arm/arm-with-neon.c"
-
 #if GDB_SELF_TEST
-#include "common/selftest.h"
+#include "gdbsupport/selftest.h"
 #endif
 
 static int arm_debug;
@@ -88,9 +80,6 @@ static int arm_debug;
 #define MSYMBOL_IS_SPECIAL(msym)                               \
        MSYMBOL_TARGET_FLAG_1 (msym)
 
-/* Per-objfile data used for mapping symbols.  */
-static const struct objfile_data *arm_objfile_data_key;
-
 struct arm_mapping_symbol
 {
   bfd_vma value;
@@ -126,6 +115,9 @@ struct arm_per_objfile
   std::unique_ptr<bool[]> section_maps_sorted;
 };
 
+/* Per-objfile data used for mapping symbols.  */
+static objfile_key<arm_per_objfile> arm_objfile_data_key;
+
 /* The list of available "set arm ..." and "show arm ..." commands.  */
 static struct cmd_list_element *setarmcmdlist = NULL;
 static struct cmd_list_element *showarmcmdlist = NULL;
@@ -240,6 +232,10 @@ static const char **valid_disassembly_styles;
 /* Disassembly style to use. Default to "std" register names.  */
 static const char *disassembly_style;
 
+/* All possible arm target descriptors.  */
+static struct target_desc *tdesc_arm_list[ARM_FP_TYPE_INVALID];
+static struct target_desc *tdesc_arm_mprofile_list[ARM_M_TYPE_INVALID];
+
 /* This is used to keep the bfd arch_info in sync with the disassembly
    style.  */
 static void set_disassembly_style_sfunc (const char *, int,
@@ -356,9 +352,7 @@ arm_find_mapping_symbol (CORE_ADDR memaddr, CORE_ADDR *start)
   sec = find_pc_section (memaddr);
   if (sec != NULL)
     {
-      arm_per_objfile *data
-       = (struct arm_per_objfile *) objfile_data (sec->objfile,
-                                                  arm_objfile_data_key);
+      arm_per_objfile *data = arm_objfile_data_key.get (sec->objfile);
       if (data != NULL)
        {
          unsigned int section_idx = sec->the_bfd_section->index;
@@ -1991,37 +1985,23 @@ struct frame_unwind arm_prologue_unwind = {
    personality routines; the cache will contain only the frame unwinding
    instructions associated with the entry (not the descriptors).  */
 
-static const struct objfile_data *arm_exidx_data_key;
-
 struct arm_exidx_entry
 {
   bfd_vma addr;
   gdb_byte *entry;
+
+  bool operator< (const arm_exidx_entry &other) const
+  {
+    return addr < other.addr;
+  }
 };
-typedef struct arm_exidx_entry arm_exidx_entry_s;
-DEF_VEC_O(arm_exidx_entry_s);
 
 struct arm_exidx_data
 {
-  VEC(arm_exidx_entry_s) **section_maps;
+  std::vector<std::vector<arm_exidx_entry>> section_maps;
 };
 
-static void
-arm_exidx_data_free (struct objfile *objfile, void *arg)
-{
-  struct arm_exidx_data *data = (struct arm_exidx_data *) arg;
-  unsigned int i;
-
-  for (i = 0; i < objfile->obfd->section_count; i++)
-    VEC_free (arm_exidx_entry_s, data->section_maps[i]);
-}
-
-static inline int
-arm_compare_exidx_entries (const struct arm_exidx_entry *lhs,
-                          const struct arm_exidx_entry *rhs)
-{
-  return lhs->addr < rhs->addr;
-}
+static const struct objfile_key<arm_exidx_data> arm_exidx_data_key;
 
 static struct obj_section *
 arm_obj_section_from_vma (struct objfile *objfile, bfd_vma vma)
@@ -2066,7 +2046,7 @@ arm_exidx_new_objfile (struct objfile *objfile)
   LONGEST i;
 
   /* If we've already touched this file, do nothing.  */
-  if (!objfile || objfile_data (objfile, arm_exidx_data_key) != NULL)
+  if (!objfile || arm_exidx_data_key.get (objfile) != NULL)
     return;
 
   /* Read contents of exception table and index.  */
@@ -2097,11 +2077,8 @@ arm_exidx_new_objfile (struct objfile *objfile)
     }
 
   /* Allocate exception table data structure.  */
-  data = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct arm_exidx_data);
-  set_objfile_data (objfile, arm_exidx_data_key, data);
-  data->section_maps = OBSTACK_CALLOC (&objfile->objfile_obstack,
-                                      objfile->obfd->section_count,
-                                      VEC(arm_exidx_entry_s) *);
+  data = arm_exidx_data_key.emplace (objfile);
+  data->section_maps.resize (objfile->obfd->section_count);
 
   /* Fill in exception table.  */
   for (i = 0; i < exidx_data.size () / 8; i++)
@@ -2252,9 +2229,8 @@ arm_exidx_new_objfile (struct objfile *objfile)
         appear in order of increasing addresses.  */
       new_exidx_entry.addr = idx;
       new_exidx_entry.entry = entry;
-      VEC_safe_push (arm_exidx_entry_s,
-                    data->section_maps[sec->the_bfd_section->index],
-                    &new_exidx_entry);
+      data->section_maps[sec->the_bfd_section->index].push_back
+       (new_exidx_entry);
     }
 }
 
@@ -2271,43 +2247,37 @@ arm_find_exidx_entry (CORE_ADDR memaddr, CORE_ADDR *start)
   if (sec != NULL)
     {
       struct arm_exidx_data *data;
-      VEC(arm_exidx_entry_s) *map;
       struct arm_exidx_entry map_key = { memaddr - obj_section_addr (sec), 0 };
-      unsigned int idx;
 
-      data = ((struct arm_exidx_data *)
-             objfile_data (sec->objfile, arm_exidx_data_key));
+      data = arm_exidx_data_key.get (sec->objfile);
       if (data != NULL)
        {
-         map = data->section_maps[sec->the_bfd_section->index];
-         if (!VEC_empty (arm_exidx_entry_s, map))
+         std::vector<arm_exidx_entry> &map
+           = data->section_maps[sec->the_bfd_section->index];
+         if (!map.empty ())
            {
-             struct arm_exidx_entry *map_sym;
-
-             idx = VEC_lower_bound (arm_exidx_entry_s, map, &map_key,
-                                    arm_compare_exidx_entries);
+             auto idx = std::lower_bound (map.begin (), map.end (), map_key);
 
-             /* VEC_lower_bound finds the earliest ordered insertion
+             /* std::lower_bound finds the earliest ordered insertion
                 point.  If the following symbol starts at this exact
                 address, we use that; otherwise, the preceding
                 exception table entry covers this address.  */
-             if (idx < VEC_length (arm_exidx_entry_s, map))
+             if (idx < map.end ())
                {
-                 map_sym = VEC_index (arm_exidx_entry_s, map, idx);
-                 if (map_sym->addr == map_key.addr)
+                 if (idx->addr == map_key.addr)
                    {
                      if (start)
-                       *start = map_sym->addr + obj_section_addr (sec);
-                     return map_sym->entry;
+                       *start = idx->addr + obj_section_addr (sec);
+                     return idx->entry;
                    }
                }
 
-             if (idx > 0)
+             if (idx > map.begin ())
                {
-                 map_sym = VEC_index (arm_exidx_entry_s, map, idx - 1);
+                 idx = idx - 1;
                  if (start)
-                   *start = map_sym->addr + obj_section_addr (sec);
-                 return map_sym->entry;
+                   *start = idx->addr + obj_section_addr (sec);
+                 return idx->entry;
                }
            }
        }
@@ -3696,18 +3666,19 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
       align = type_align (arg_type);
       /* Round alignment up to a whole number of words.  */
-      align = (align + INT_REGISTER_SIZE - 1) & ~(INT_REGISTER_SIZE - 1);
+      align = (align + ARM_INT_REGISTER_SIZE - 1)
+               & ~(ARM_INT_REGISTER_SIZE - 1);
       /* Different ABIs have different maximum alignments.  */
       if (gdbarch_tdep (gdbarch)->arm_abi == ARM_ABI_APCS)
        {
          /* The APCS ABI only requires word alignment.  */
-         align = INT_REGISTER_SIZE;
+         align = ARM_INT_REGISTER_SIZE;
        }
       else
        {
          /* The AAPCS requires at most doubleword alignment.  */
-         if (align > INT_REGISTER_SIZE * 2)
-           align = INT_REGISTER_SIZE * 2;
+         if (align > ARM_INT_REGISTER_SIZE * 2)
+           align = ARM_INT_REGISTER_SIZE * 2;
        }
 
       if (use_vfp_abi
@@ -3772,14 +3743,14 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
       /* Push stack padding for dowubleword alignment.  */
       if (nstack & (align - 1))
        {
-         si = push_stack_item (si, val, INT_REGISTER_SIZE);
-         nstack += INT_REGISTER_SIZE;
+         si = push_stack_item (si, val, ARM_INT_REGISTER_SIZE);
+         nstack += ARM_INT_REGISTER_SIZE;
        }
       
       /* Doubleword aligned quantities must go in even register pairs.  */
       if (may_use_core_reg
          && argreg <= ARM_LAST_ARG_REGNUM
-         && align > INT_REGISTER_SIZE
+         && align > ARM_INT_REGISTER_SIZE
          && argreg & 1)
        argreg++;
 
@@ -3805,7 +3776,8 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
         registers and stack.  */
       while (len > 0)
        {
-         int partial_len = len < INT_REGISTER_SIZE ? len : INT_REGISTER_SIZE;
+         int partial_len = len < ARM_INT_REGISTER_SIZE
+                           ? len : ARM_INT_REGISTER_SIZE;
          CORE_ADDR regval
            = extract_unsigned_integer (val, partial_len, byte_order);
 
@@ -3814,19 +3786,19 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              /* The argument is being passed in a general purpose
                 register.  */
              if (byte_order == BFD_ENDIAN_BIG)
-               regval <<= (INT_REGISTER_SIZE - partial_len) * 8;
+               regval <<= (ARM_INT_REGISTER_SIZE - partial_len) * 8;
              if (arm_debug)
                fprintf_unfiltered (gdb_stdlog, "arg %d in %s = 0x%s\n",
                                    argnum,
                                    gdbarch_register_name
                                      (gdbarch, argreg),
-                                   phex (regval, INT_REGISTER_SIZE));
+                                   phex (regval, ARM_INT_REGISTER_SIZE));
              regcache_cooked_write_unsigned (regcache, argreg, regval);
              argreg++;
            }
          else
            {
-             gdb_byte buf[INT_REGISTER_SIZE];
+             gdb_byte buf[ARM_INT_REGISTER_SIZE];
 
              memset (buf, 0, sizeof (buf));
              store_unsigned_integer (buf, partial_len, byte_order, regval);
@@ -3835,8 +3807,8 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              if (arm_debug)
                fprintf_unfiltered (gdb_stdlog, "arg %d @ sp + %d\n",
                                    argnum, nstack);
-             si = push_stack_item (si, buf, INT_REGISTER_SIZE);
-             nstack += INT_REGISTER_SIZE;
+             si = push_stack_item (si, buf, ARM_INT_REGISTER_SIZE);
+             nstack += ARM_INT_REGISTER_SIZE;
            }
              
          len -= partial_len;
@@ -7842,7 +7814,7 @@ arm_extract_return_value (struct type *type, struct regcache *regs,
            /* The value is in register F0 in internal format.  We need to
               extract the raw value and then convert it to the desired
               internal type.  */
-           bfd_byte tmpbuf[FP_REGISTER_SIZE];
+           bfd_byte tmpbuf[ARM_FP_REGISTER_SIZE];
 
            regs->cooked_read (ARM_F0_REGNUM, tmpbuf);
            target_float_convert (tmpbuf, arm_ext_type (gdbarch),
@@ -7857,7 +7829,8 @@ arm_extract_return_value (struct type *type, struct regcache *regs,
        case ARM_FLOAT_VFP:
          regs->cooked_read (ARM_A1_REGNUM, valbuf);
          if (TYPE_LENGTH (type) > 4)
-           regs->cooked_read (ARM_A1_REGNUM + 1, valbuf + INT_REGISTER_SIZE);
+           regs->cooked_read (ARM_A1_REGNUM + 1,
+                              valbuf + ARM_INT_REGISTER_SIZE);
          break;
 
        default:
@@ -7887,11 +7860,11 @@ arm_extract_return_value (struct type *type, struct regcache *regs,
             anything special for small big-endian values.  */
          regcache_cooked_read_unsigned (regs, regno++, &tmp);
          store_unsigned_integer (valbuf, 
-                                 (len > INT_REGISTER_SIZE
-                                  ? INT_REGISTER_SIZE : len),
+                                 (len > ARM_INT_REGISTER_SIZE
+                                  ? ARM_INT_REGISTER_SIZE : len),
                                  byte_order, tmp);
-         len -= INT_REGISTER_SIZE;
-         valbuf += INT_REGISTER_SIZE;
+         len -= ARM_INT_REGISTER_SIZE;
+         valbuf += ARM_INT_REGISTER_SIZE;
        }
     }
   else
@@ -7901,15 +7874,15 @@ arm_extract_return_value (struct type *type, struct regcache *regs,
          registers with 32-bit load instruction(s).  */
       int len = TYPE_LENGTH (type);
       int regno = ARM_A1_REGNUM;
-      bfd_byte tmpbuf[INT_REGISTER_SIZE];
+      bfd_byte tmpbuf[ARM_INT_REGISTER_SIZE];
 
       while (len > 0)
        {
          regs->cooked_read (regno++, tmpbuf);
          memcpy (valbuf, tmpbuf,
-                 len > INT_REGISTER_SIZE ? INT_REGISTER_SIZE : len);
-         len -= INT_REGISTER_SIZE;
-         valbuf += INT_REGISTER_SIZE;
+                 len > ARM_INT_REGISTER_SIZE ? ARM_INT_REGISTER_SIZE : len);
+         len -= ARM_INT_REGISTER_SIZE;
+         valbuf += ARM_INT_REGISTER_SIZE;
        }
     }
 }
@@ -7944,7 +7917,7 @@ arm_return_in_memory (struct gdbarch *gdbarch, struct type *type)
     {
       /* The AAPCS says all aggregates not larger than a word are returned
         in a register.  */
-      if (TYPE_LENGTH (type) <= INT_REGISTER_SIZE)
+      if (TYPE_LENGTH (type) <= ARM_INT_REGISTER_SIZE)
        return 0;
 
       return 1;
@@ -7955,12 +7928,12 @@ arm_return_in_memory (struct gdbarch *gdbarch, struct type *type)
 
       /* All aggregate types that won't fit in a register must be returned
         in memory.  */
-      if (TYPE_LENGTH (type) > INT_REGISTER_SIZE)
+      if (TYPE_LENGTH (type) > ARM_INT_REGISTER_SIZE)
        return 1;
 
       /* In the ARM ABI, "integer" like aggregate types are returned in
         registers.  For an aggregate type to be integer like, its size
-        must be less than or equal to INT_REGISTER_SIZE and the
+        must be less than or equal to ARM_INT_REGISTER_SIZE and the
         offset of each addressable subfield must be zero.  Note that bit
         fields are not addressable, and all addressable subfields of
         unions always start at offset zero.
@@ -7984,7 +7957,7 @@ arm_return_in_memory (struct gdbarch *gdbarch, struct type *type)
          int i;
          /* Need to check if this struct/union is "integer" like.  For
             this to be true, its size must be less than or equal to
-            INT_REGISTER_SIZE and the offset of each addressable
+            ARM_INT_REGISTER_SIZE and the offset of each addressable
             subfield must be zero.  Note that bit fields are not
             addressable, and unions always start at offset zero.  If any
             of the subfields is a floating point type, the struct/union
@@ -8043,7 +8016,7 @@ arm_store_return_value (struct type *type, struct regcache *regs,
 
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
     {
-      gdb_byte buf[FP_REGISTER_SIZE];
+      gdb_byte buf[ARM_FP_REGISTER_SIZE];
 
       switch (gdbarch_tdep (gdbarch)->fp_model)
        {
@@ -8060,7 +8033,8 @@ arm_store_return_value (struct type *type, struct regcache *regs,
        case ARM_FLOAT_VFP:
          regs->cooked_write (ARM_A1_REGNUM, valbuf);
          if (TYPE_LENGTH (type) > 4)
-           regs->cooked_write (ARM_A1_REGNUM + 1, valbuf + INT_REGISTER_SIZE);
+           regs->cooked_write (ARM_A1_REGNUM + 1,
+                               valbuf + ARM_INT_REGISTER_SIZE);
          break;
 
        default:
@@ -8081,10 +8055,10 @@ arm_store_return_value (struct type *type, struct regcache *regs,
        {
          /* Values of one word or less are zero/sign-extended and
             returned in r0.  */
-         bfd_byte tmpbuf[INT_REGISTER_SIZE];
+         bfd_byte tmpbuf[ARM_INT_REGISTER_SIZE];
          LONGEST val = unpack_long (type, valbuf);
 
-         store_signed_integer (tmpbuf, INT_REGISTER_SIZE, byte_order, val);
+         store_signed_integer (tmpbuf, ARM_INT_REGISTER_SIZE, byte_order, val);
          regs->cooked_write (ARM_A1_REGNUM, tmpbuf);
        }
       else
@@ -8098,8 +8072,8 @@ arm_store_return_value (struct type *type, struct regcache *regs,
          while (len > 0)
            {
              regs->cooked_write (regno++, valbuf);
-             len -= INT_REGISTER_SIZE;
-             valbuf += INT_REGISTER_SIZE;
+             len -= ARM_INT_REGISTER_SIZE;
+             valbuf += ARM_INT_REGISTER_SIZE;
            }
        }
     }
@@ -8110,15 +8084,15 @@ arm_store_return_value (struct type *type, struct regcache *regs,
          registers with 32-bit load instruction(s).  */
       int len = TYPE_LENGTH (type);
       int regno = ARM_A1_REGNUM;
-      bfd_byte tmpbuf[INT_REGISTER_SIZE];
+      bfd_byte tmpbuf[ARM_INT_REGISTER_SIZE];
 
       while (len > 0)
        {
          memcpy (tmpbuf, valbuf,
-                 len > INT_REGISTER_SIZE ? INT_REGISTER_SIZE : len);
+                 len > ARM_INT_REGISTER_SIZE ? ARM_INT_REGISTER_SIZE : len);
          regs->cooked_write (regno++, tmpbuf);
-         len -= INT_REGISTER_SIZE;
-         valbuf += INT_REGISTER_SIZE;
+         len -= ARM_INT_REGISTER_SIZE;
+         valbuf += ARM_INT_REGISTER_SIZE;
        }
     }
 }
@@ -8202,17 +8176,67 @@ arm_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR jb_addr;
-  gdb_byte buf[INT_REGISTER_SIZE];
+  gdb_byte buf[ARM_INT_REGISTER_SIZE];
   
   jb_addr = get_frame_register_unsigned (frame, ARM_A1_REGNUM);
 
   if (target_read_memory (jb_addr + tdep->jb_pc * tdep->jb_elt_size, buf,
-                         INT_REGISTER_SIZE))
+                         ARM_INT_REGISTER_SIZE))
     return 0;
 
-  *pc = extract_unsigned_integer (buf, INT_REGISTER_SIZE, byte_order);
+  *pc = extract_unsigned_integer (buf, ARM_INT_REGISTER_SIZE, byte_order);
   return 1;
 }
+/* A call to cmse secure entry function "foo" at "a" is modified by
+     GNU ld as "b".
+     a) bl xxxx <foo>
+
+     <foo>
+     xxxx:
+
+     b) bl yyyy <__acle_se_foo>
+
+     section .gnu.sgstubs:
+     <foo>
+     yyyy: sg   // secure gateway
+          b.w xxxx <__acle_se_foo>  // original_branch_dest
+
+     <__acle_se_foo>
+     xxxx:
+
+  When the control at "b", the pc contains "yyyy" (sg address) which is a
+  trampoline and does not exist in source code.  This function returns the
+  target pc "xxxx".  For more details please refer to section 5.4
+  (Entry functions) and section 3.4.4 (C level development flow of secure code)
+  of "armv8-m-security-extensions-requirements-on-development-tools-engineering-specification"
+  document on www.developer.arm.com.  */
+
+static CORE_ADDR
+arm_skip_cmse_entry (CORE_ADDR pc, const char *name, struct objfile *objfile)
+{
+  int target_len = strlen (name) + strlen ("__acle_se_") + 1;
+  char *target_name = (char *) alloca (target_len);
+  xsnprintf (target_name, target_len, "%s%s", "__acle_se_", name);
+
+  struct bound_minimal_symbol minsym
+   = lookup_minimal_symbol (target_name, NULL, objfile);
+
+  if (minsym.minsym != nullptr)
+    return BMSYMBOL_VALUE_ADDRESS (minsym);
+
+  return 0;
+}
+
+/* Return true when SEC points to ".gnu.sgstubs" section.  */
+
+static bool
+arm_is_sgstubs_section (struct obj_section *sec)
+{
+  return (sec != nullptr
+         && sec->the_bfd_section != nullptr
+         && sec->the_bfd_section->name != nullptr
+         && streq (sec->the_bfd_section->name, ".gnu.sgstubs"));
+}
 
 /* Recognize GCC and GNU ld's trampolines.  If we are in a trampoline,
    return the target PC.  Otherwise return 0.  */
@@ -8292,6 +8316,12 @@ arm_skip_stub (struct frame_info *frame, CORE_ADDR pc)
        return 0;
     }
 
+  struct obj_section *section = find_pc_section (pc);
+
+  /* Check whether SECTION points to the ".gnu.sgstubs" section.  */
+  if (arm_is_sgstubs_section (section))
+    return arm_skip_cmse_entry (pc, name, section->objfile);
+
   return 0;                    /* not a stub */
 }
 
@@ -8529,14 +8559,6 @@ arm_coff_make_msymbol_special(int val, struct minimal_symbol *msym)
 }
 
 static void
-arm_objfile_data_free (struct objfile *objfile, void *arg)
-{
-  struct arm_per_objfile *data = (struct arm_per_objfile *) arg;
-
-  delete data;
-}
-
-static void
 arm_record_special_symbol (struct gdbarch *gdbarch, struct objfile *objfile,
                           asymbol *sym)
 {
@@ -8548,13 +8570,10 @@ arm_record_special_symbol (struct gdbarch *gdbarch, struct objfile *objfile,
   if (name[1] != 'a' && name[1] != 't' && name[1] != 'd')
     return;
 
-  data = (struct arm_per_objfile *) objfile_data (objfile,
-                                                 arm_objfile_data_key);
+  data = arm_objfile_data_key.get (objfile);
   if (data == NULL)
-    {
-      data = new arm_per_objfile (objfile->obfd->section_count);
-      set_objfile_data (objfile, arm_objfile_data_key, data);
-    }
+    data = arm_objfile_data_key.emplace (objfile,
+                                        objfile->obfd->section_count);
   arm_mapping_symbol_vec &map
     = data->section_maps[bfd_get_section (sym)->index];
 
@@ -8772,7 +8791,6 @@ arm_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
     return default_register_reggroup_p (gdbarch, regnum, group);
 }
 
-\f
 /* For backward-compatibility we allow two 'g' packet lengths with
    the remote protocol depending on whether FPA registers are
    supplied.  M-profile targets do not have FPA registers, but some
@@ -8786,30 +8804,26 @@ arm_register_g_packet_guesses (struct gdbarch *gdbarch)
 {
   if (gdbarch_tdep (gdbarch)->is_m)
     {
+      const target_desc *tdesc;
+
       /* If we know from the executable this is an M-profile target,
         cater for remote targets whose register set layout is the
         same as the FPA layout.  */
+      tdesc = arm_read_mprofile_description (ARM_M_TYPE_WITH_FPA);
       register_remote_g_packet_guess (gdbarch,
-                                     /* r0-r12,sp,lr,pc; f0-f7; fps,xpsr */
-                                     (16 * INT_REGISTER_SIZE)
-                                     + (8 * FP_REGISTER_SIZE)
-                                     + (2 * INT_REGISTER_SIZE),
-                                     tdesc_arm_with_m_fpa_layout);
+                                     ARM_CORE_REGS_SIZE + ARM_FP_REGS_SIZE,
+                                     tdesc);
 
       /* The regular M-profile layout.  */
-      register_remote_g_packet_guess (gdbarch,
-                                     /* r0-r12,sp,lr,pc; xpsr */
-                                     (16 * INT_REGISTER_SIZE)
-                                     + INT_REGISTER_SIZE,
-                                     tdesc_arm_with_m);
+      tdesc = arm_read_mprofile_description (ARM_M_TYPE_M_PROFILE);
+      register_remote_g_packet_guess (gdbarch, ARM_CORE_REGS_SIZE,
+                                     tdesc);
 
       /* M-profile plus M4F VFP.  */
+      tdesc = arm_read_mprofile_description (ARM_M_TYPE_VFP_D16);
       register_remote_g_packet_guess (gdbarch,
-                                     /* r0-r12,sp,lr,pc; d0-d15; fpscr,xpsr */
-                                     (16 * INT_REGISTER_SIZE)
-                                     + (16 * VFP_REGISTER_SIZE)
-                                     + (2 * INT_REGISTER_SIZE),
-                                     tdesc_arm_with_m_vfp_d16);
+                                     ARM_CORE_REGS_SIZE + ARM_VFP2_REGS_SIZE,
+                                     tdesc);
     }
 
   /* Otherwise we don't have a useful guess.  */
@@ -8831,7 +8845,17 @@ arm_code_of_frame_writable (struct gdbarch *gdbarch, struct frame_info *frame)
     return 1;
 }
 
-\f
+/* Implement gdbarch_gnu_triplet_regexp.  If the arch name is arm then allow it
+   to be postfixed by a version (eg armv7hl).  */
+
+static const char *
+arm_gnu_triplet_regexp (struct gdbarch *gdbarch)
+{
+  if (strcmp (gdbarch_bfd_arch_info (gdbarch)->arch_name, "arm") == 0)
+    return "arm(v[^- ]*)?";
+  return gdbarch_bfd_arch_info (gdbarch)->arch_name;
+}
+
 /* Initialize the current architecture based on INFO.  If possible,
    re-use an architecture from ARCHES, which is a list of
    architectures already created during this debugging session.
@@ -9271,7 +9295,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Note: for displaced stepping, this includes the breakpoint, and one word
      of additional scratch space.  This setting isn't used for anything beside
      displaced stepping at present.  */
-  set_gdbarch_max_insn_length (gdbarch, 4 * DISPLACED_MODIFIED_INSNS);
+  set_gdbarch_max_insn_length (gdbarch, 4 * ARM_DISPLACED_MODIFIED_INSNS);
 
   /* This should be low enough for everything.  */
   tdep->lowest_pc = 0x20;
@@ -9433,6 +9457,8 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_disassembler_options (gdbarch, &arm_disassembler_options);
   set_gdbarch_valid_disassembler_options (gdbarch, disassembler_options_arm ());
 
+  set_gdbarch_gnu_triplet_regexp (gdbarch, arm_gnu_triplet_regexp);
+
   return gdbarch;
 }
 
@@ -9465,28 +9491,14 @@ _initialize_arm_tdep (void)
 
   gdbarch_register (bfd_arch_arm, arm_gdbarch_init, arm_dump_tdep);
 
-  arm_objfile_data_key
-    = register_objfile_data_with_cleanup (NULL, arm_objfile_data_free);
-
   /* Add ourselves to objfile event chain.  */
   gdb::observers::new_objfile.attach (arm_exidx_new_objfile);
-  arm_exidx_data_key
-    = register_objfile_data_with_cleanup (NULL, arm_exidx_data_free);
 
   /* Register an ELF OS ABI sniffer for ARM binaries.  */
   gdbarch_register_osabi_sniffer (bfd_arch_arm,
                                  bfd_target_elf_flavour,
                                  arm_elf_osabi_sniffer);
 
-  /* Initialize the standard target descriptions.  */
-  initialize_tdesc_arm_with_m ();
-  initialize_tdesc_arm_with_m_fpa_layout ();
-  initialize_tdesc_arm_with_m_vfp_d16 ();
-  initialize_tdesc_arm_with_iwmmxt ();
-  initialize_tdesc_arm_with_vfpv2 ();
-  initialize_tdesc_arm_with_vfpv3 ();
-  initialize_tdesc_arm_with_neon ();
-
   /* Add root prefix command for all "set arm"/"show arm" commands.  */
   add_prefix_cmd ("arm", no_class, set_arm_command,
                  _("Various ARM-specific commands."),
@@ -10980,7 +10992,7 @@ arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
          /* STMDA (STMED): Decrement after.  */
          case 0:
          record_buf_mem[1] = (uint32_t) u_regval
-                             - register_count * INT_REGISTER_SIZE + 4;
+                             - register_count * ARM_INT_REGISTER_SIZE + 4;
          break;
          /* STM (STMIA, STMEA): Increment after.  */
          case 1:
@@ -10989,18 +11001,18 @@ arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
          /* STMDB (STMFD): Decrement before.  */
          case 2:
          record_buf_mem[1] = (uint32_t) u_regval
-                             - register_count * INT_REGISTER_SIZE;
+                             - register_count * ARM_INT_REGISTER_SIZE;
          break;
          /* STMIB (STMFA): Increment before.  */
          case 3:
-         record_buf_mem[1] = (uint32_t) u_regval + INT_REGISTER_SIZE;
+         record_buf_mem[1] = (uint32_t) u_regval + ARM_INT_REGISTER_SIZE;
          break;
          default:
            gdb_assert_not_reached ("no decoding pattern found");
          break;
        }
 
-      record_buf_mem[0] = register_count * INT_REGISTER_SIZE;
+      record_buf_mem[0] = register_count * ARM_INT_REGISTER_SIZE;
       arm_insn_r->mem_rec_count = 1;
 
       /* If wback is true, also save the base register, which is going to be
@@ -13345,3 +13357,35 @@ arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
 
   return ret;
 }
+
+/* See arm-tdep.h.  */
+
+const target_desc *
+arm_read_description (arm_fp_type fp_type)
+{
+  struct target_desc *tdesc = tdesc_arm_list[fp_type];
+
+  if (tdesc == nullptr)
+    {
+      tdesc = arm_create_target_description (fp_type);
+      tdesc_arm_list[fp_type] = tdesc;
+    }
+
+  return tdesc;
+}
+
+/* See arm-tdep.h.  */
+
+const target_desc *
+arm_read_mprofile_description (arm_m_profile_type m_type)
+{
+  struct target_desc *tdesc = tdesc_arm_mprofile_list[m_type];
+
+  if (tdesc == nullptr)
+    {
+      tdesc = arm_create_mprofile_target_description (m_type);
+      tdesc_arm_mprofile_list[m_type] = tdesc;
+    }
+
+  return tdesc;
+}