packaging: Add python3-base dependency
[platform/upstream/gdb.git] / gdb / arch-utils.c
index 5da6f0c..a6d0035 100644 (file)
@@ -1,6 +1,6 @@
 /* Dynamic architecture support for GDB, the GNU debugger.
 
-   Copyright (C) 1998-2017 Free Software Foundation, Inc.
+   Copyright (C) 1998-2023 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -20,7 +20,6 @@
 #include "defs.h"
 
 #include "arch-utils.h"
-#include "buildsym.h"
 #include "gdbcmd.h"
 #include "inferior.h"          /* enum CALL_DUMMY_LOCATION et al.  */
 #include "infrun.h"
 #include "objfiles.h"
 #include "language.h"
 #include "symtab.h"
+#include "dummy-frame.h"
+#include "frame-unwind.h"
+#include "reggroups.h"
+#include "auxv.h"
+#include "observable.h"
+#include "solib-target.h"
 
-#include "version.h"
+#include "gdbsupport/version.h"
 
 #include "floatformat.h"
 
+#include "dis-asm.h"
 
-struct displaced_step_closure *
-simple_displaced_step_copy_insn (struct gdbarch *gdbarch,
-                                 CORE_ADDR from, CORE_ADDR to,
-                                 struct regcache *regs)
-{
-  size_t len = gdbarch_max_insn_length (gdbarch);
-  gdb_byte *buf = (gdb_byte *) xmalloc (len);
-
-  read_memory (from, buf, len);
-  write_memory (to, buf, len);
-
-  if (debug_displaced)
-    {
-      fprintf_unfiltered (gdb_stdlog, "displaced: copy %s->%s: ",
-                          paddress (gdbarch, from), paddress (gdbarch, to));
-      displaced_step_dump_bytes (gdb_stdlog, buf, len);
-    }
-
-  return (struct displaced_step_closure *) buf;
-}
-
-
-void
-simple_displaced_step_free_closure (struct gdbarch *gdbarch,
-                                    struct displaced_step_closure *closure)
-{
-  xfree (closure);
-}
-
-int
-default_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
-                                     struct displaced_step_closure *closure)
+bool
+default_displaced_step_hw_singlestep (struct gdbarch *gdbarch)
 {
   return !gdbarch_software_single_step_p (gdbarch);
 }
@@ -98,17 +74,73 @@ legacy_register_sim_regno (struct gdbarch *gdbarch, int regnum)
   gdb_assert (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch));
   /* NOTE: cagney/2002-05-13: The old code did it this way and it is
      suspected that some GDB/SIM combinations may rely on this
-     behavour.  The default should be one2one_register_sim_regno
+     behaviour.  The default should be one2one_register_sim_regno
      (below).  */
-  if (gdbarch_register_name (gdbarch, regnum) != NULL
-      && gdbarch_register_name (gdbarch, regnum)[0] != '\0')
+  if (gdbarch_register_name (gdbarch, regnum)[0] != '\0')
     return regnum;
   else
     return LEGACY_SIM_REGNO_IGNORE;
 }
 
+/* See arch-utils.h */
+
 CORE_ADDR
-generic_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
+default_remove_non_address_bits (struct gdbarch *gdbarch, CORE_ADDR pointer)
+{
+  /* By default, just return the pointer value.  */
+  return pointer;
+}
+
+/* See arch-utils.h */
+
+std::string
+default_memtag_to_string (struct gdbarch *gdbarch, struct value *tag)
+{
+  error (_("This architecture has no method to convert a memory tag to"
+          " a string."));
+}
+
+/* See arch-utils.h */
+
+bool
+default_tagged_address_p (struct gdbarch *gdbarch, struct value *address)
+{
+  /* By default, assume the address is untagged.  */
+  return false;
+}
+
+/* See arch-utils.h */
+
+bool
+default_memtag_matches_p (struct gdbarch *gdbarch, struct value *address)
+{
+  /* By default, assume the tags match.  */
+  return true;
+}
+
+/* See arch-utils.h */
+
+bool
+default_set_memtags (struct gdbarch *gdbarch, struct value *address,
+                    size_t length, const gdb::byte_vector &tags,
+                    memtag_type tag_type)
+{
+  /* By default, return true (successful);  */
+  return true;
+}
+
+/* See arch-utils.h */
+
+struct value *
+default_get_memtag (struct gdbarch *gdbarch, struct value *address,
+                   memtag_type tag_type)
+{
+  /* By default, return no tag.  */
+  return nullptr;
+}
+
+CORE_ADDR
+generic_skip_trampoline_code (frame_info_ptr frame, CORE_ADDR pc)
 {
   return 0;
 }
@@ -134,7 +166,7 @@ generic_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 
 int
 default_code_of_frame_writable (struct gdbarch *gdbarch,
-                               struct frame_info *frame)
+                               frame_info_ptr frame)
 {
   return 1;
 }
@@ -204,6 +236,15 @@ default_adjust_dwarf2_line (CORE_ADDR addr, int rel)
   return addr;
 }
 
+/* See arch-utils.h.  */
+
+bool
+default_execute_dwarf_cfa_vendor_op (struct gdbarch *gdbarch, gdb_byte op,
+                                    struct dwarf2_frame_state *fs)
+{
+  return false;
+}
+
 int
 cannot_register_not (struct gdbarch *gdbarch, int regnum)
 {
@@ -231,16 +272,49 @@ legacy_virtual_frame_pointer (struct gdbarch *gdbarch,
     *frame_regnum = gdbarch_deprecated_fp_regnum (gdbarch);
   else if (gdbarch_sp_regnum (gdbarch) >= 0
           && gdbarch_sp_regnum (gdbarch)
-               < gdbarch_num_regs (gdbarch))
+               < gdbarch_num_regs (gdbarch))
     *frame_regnum = gdbarch_sp_regnum (gdbarch);
   else
     /* Should this be an internal error?  I guess so, it is reflecting
        an architectural limitation in the current design.  */
-    internal_error (__FILE__, __LINE__, 
-                   _("No virtual frame pointer available"));
+    internal_error (_("No virtual frame pointer available"));
   *frame_offset = 0;
 }
 
+/* Return a floating-point format for a floating-point variable of
+   length LEN in bits.  If non-NULL, NAME is the name of its type.
+   If no suitable type is found, return NULL.  */
+
+const struct floatformat **
+default_floatformat_for_type (struct gdbarch *gdbarch,
+                             const char *name, int len)
+{
+  const struct floatformat **format = NULL;
+
+  /* Check if this is a bfloat16 type.  It has the same size as the
+     IEEE half float type, so we use the base type name to tell them
+     apart.  */
+  if (name != nullptr && strcmp (name, "__bf16") == 0
+      && len == gdbarch_bfloat16_bit (gdbarch))
+    format = gdbarch_bfloat16_format (gdbarch);
+  else if (len == gdbarch_half_bit (gdbarch))
+    format = gdbarch_half_format (gdbarch);
+  else if (len == gdbarch_float_bit (gdbarch))
+    format = gdbarch_float_format (gdbarch);
+  else if (len == gdbarch_double_bit (gdbarch))
+    format = gdbarch_double_format (gdbarch);
+  else if (len == gdbarch_long_double_bit (gdbarch))
+    format = gdbarch_long_double_format (gdbarch);
+  /* On i386 the 'long double' type takes 96 bits,
+     while the real number of used bits is only 80,
+     both in processor and in memory.
+     The code below accepts the real bit size.  */
+  else if (gdbarch_long_double_format (gdbarch) != NULL
+          && len == gdbarch_long_double_format (gdbarch)[0]->totalsize)
+    format = gdbarch_long_double_format (gdbarch);
+
+  return format;
+}
 \f
 int
 generic_convert_register_p (struct gdbarch *gdbarch, int regnum,
@@ -292,7 +366,7 @@ static const char *const endian_enum[] =
   endian_auto,
   NULL,
 };
-static const char *set_endian_string;
+static const char *set_endian_string = endian_auto;
 
 enum bfd_endian
 selected_byte_order (void)
@@ -308,39 +382,37 @@ show_endian (struct ui_file *file, int from_tty, struct cmd_list_element *c,
 {
   if (target_byte_order_user == BFD_ENDIAN_UNKNOWN)
     if (gdbarch_byte_order (get_current_arch ()) == BFD_ENDIAN_BIG)
-      fprintf_unfiltered (file, _("The target endianness is set automatically "
-                                 "(currently big endian)\n"));
+      gdb_printf (file, _("The target endianness is set automatically "
+                         "(currently big endian).\n"));
     else
-      fprintf_unfiltered (file, _("The target endianness is set automatically "
-                                 "(currently little endian)\n"));
+      gdb_printf (file, _("The target endianness is set automatically "
+                         "(currently little endian).\n"));
   else
     if (target_byte_order_user == BFD_ENDIAN_BIG)
-      fprintf_unfiltered (file,
-                         _("The target is assumed to be big endian\n"));
+      gdb_printf (file,
+                 _("The target is set to big endian.\n"));
     else
-      fprintf_unfiltered (file,
-                         _("The target is assumed to be little endian\n"));
+      gdb_printf (file,
+                 _("The target is set to little endian.\n"));
 }
 
 static void
-set_endian (char *ignore_args, int from_tty, struct cmd_list_element *c)
+set_endian (const char *ignore_args, int from_tty, struct cmd_list_element *c)
 {
   struct gdbarch_info info;
 
-  gdbarch_info_init (&info);
-
   if (set_endian_string == endian_auto)
     {
       target_byte_order_user = BFD_ENDIAN_UNKNOWN;
       if (! gdbarch_update_p (info))
-       internal_error (__FILE__, __LINE__,
-                       _("set_endian: architecture update failed"));
+       internal_error (_("set_endian: architecture update failed"));
     }
   else if (set_endian_string == endian_little)
     {
       info.byte_order = BFD_ENDIAN_LITTLE;
       if (! gdbarch_update_p (info))
-       printf_unfiltered (_("Little endian target not supported by GDB\n"));
+       gdb_printf (gdb_stderr,
+                   _("Little endian target not supported by GDB\n"));
       else
        target_byte_order_user = BFD_ENDIAN_LITTLE;
     }
@@ -348,13 +420,13 @@ set_endian (char *ignore_args, int from_tty, struct cmd_list_element *c)
     {
       info.byte_order = BFD_ENDIAN_BIG;
       if (! gdbarch_update_p (info))
-       printf_unfiltered (_("Big endian target not supported by GDB\n"));
+       gdb_printf (gdb_stderr,
+                   _("Big endian target not supported by GDB\n"));
       else
        target_byte_order_user = BFD_ENDIAN_BIG;
     }
   else
-    internal_error (__FILE__, __LINE__,
-                   _("set_endian: bad value"));
+    internal_error (_("set_endian: bad value"));
 
   show_endian (gdb_stdout, from_tty, NULL, NULL);
 }
@@ -365,7 +437,7 @@ set_endian (char *ignore_args, int from_tty, struct cmd_list_element *c)
 
    SELECTED may be NULL, in which case we return the architecture
    associated with TARGET_DESC.  If SELECTED specifies a variant
-   of the architecture associtated with TARGET_DESC, return the
+   of the architecture associated with TARGET_DESC, return the
    more specific of the two.
 
    If SELECTED is a different architecture, but it is accepted as
@@ -468,12 +540,12 @@ show_architecture (struct ui_file *file, int from_tty,
                   struct cmd_list_element *c, const char *value)
 {
   if (target_architecture_user == NULL)
-    fprintf_filtered (file, _("The target architecture is set "
-                             "automatically (currently %s)\n"),
-                     gdbarch_bfd_arch_info (get_current_arch ())->printable_name);
+    gdb_printf (file, _("The target architecture is set to "
+                       "\"auto\" (currently \"%s\").\n"),
+               gdbarch_bfd_arch_info (get_current_arch ())->printable_name);
   else
-    fprintf_filtered (file, _("The target architecture is assumed to be %s\n"),
-                     set_architecture_string);
+    gdb_printf (file, _("The target architecture is set to \"%s\".\n"),
+               set_architecture_string);
 }
 
 
@@ -481,30 +553,28 @@ show_architecture (struct ui_file *file, int from_tty,
    argument.  */
 
 static void
-set_architecture (char *ignore_args, int from_tty, struct cmd_list_element *c)
+set_architecture (const char *ignore_args,
+                 int from_tty, struct cmd_list_element *c)
 {
   struct gdbarch_info info;
 
-  gdbarch_info_init (&info);
-
   if (strcmp (set_architecture_string, "auto") == 0)
     {
       target_architecture_user = NULL;
       if (!gdbarch_update_p (info))
-       internal_error (__FILE__, __LINE__,
-                       _("could not select an architecture automatically"));
+       internal_error (_("could not select an architecture automatically"));
     }
   else
     {
       info.bfd_arch_info = bfd_scan_arch (set_architecture_string);
       if (info.bfd_arch_info == NULL)
-       internal_error (__FILE__, __LINE__,
-                       _("set_architecture: bfd_scan_arch failed"));
+       internal_error (_("set_architecture: bfd_scan_arch failed"));
       if (gdbarch_update_p (info))
        target_architecture_user = info.bfd_arch_info;
       else
-       printf_unfiltered (_("Architecture `%s' not recognized.\n"),
-                          set_architecture_string);
+       gdb_printf (gdb_stderr,
+                   _("Architecture `%s' not recognized.\n"),
+                   set_architecture_string);
     }
   show_architecture (gdb_stdout, from_tty, NULL, NULL);
 }
@@ -518,7 +588,7 @@ gdbarch_update_p (struct gdbarch_info info)
 
   /* Check for the current file.  */
   if (info.abfd == NULL)
-    info.abfd = exec_bfd;
+    info.abfd = current_program_space->exec_bfd ();
   if (info.abfd == NULL)
     info.abfd = core_bfd;
 
@@ -532,8 +602,8 @@ gdbarch_update_p (struct gdbarch_info info)
   if (new_gdbarch == NULL)
     {
       if (gdbarch_debug)
-       fprintf_unfiltered (gdb_stdlog, "gdbarch_update_p: "
-                           "Architecture not found\n");
+       gdb_printf (gdb_stdlog, "gdbarch_update_p: "
+                   "Architecture not found\n");
       return 0;
     }
 
@@ -542,19 +612,19 @@ gdbarch_update_p (struct gdbarch_info info)
   if (new_gdbarch == target_gdbarch ())
     {
       if (gdbarch_debug)
-       fprintf_unfiltered (gdb_stdlog, "gdbarch_update_p: "
-                           "Architecture %s (%s) unchanged\n",
-                           host_address_to_string (new_gdbarch),
-                           gdbarch_bfd_arch_info (new_gdbarch)->printable_name);
+       gdb_printf (gdb_stdlog, "gdbarch_update_p: "
+                   "Architecture %s (%s) unchanged\n",
+                   host_address_to_string (new_gdbarch),
+                   gdbarch_bfd_arch_info (new_gdbarch)->printable_name);
       return 1;
     }
 
   /* It's a new architecture, swap it in.  */
   if (gdbarch_debug)
-    fprintf_unfiltered (gdb_stdlog, "gdbarch_update_p: "
-                       "New architecture %s (%s) selected\n",
-                       host_address_to_string (new_gdbarch),
-                       gdbarch_bfd_arch_info (new_gdbarch)->printable_name);
+    gdb_printf (gdb_stdlog, "gdbarch_update_p: "
+               "New architecture %s (%s) selected\n",
+               host_address_to_string (new_gdbarch),
+               gdbarch_bfd_arch_info (new_gdbarch)->printable_name);
   set_target_gdbarch (new_gdbarch);
 
   return 1;
@@ -567,7 +637,6 @@ struct gdbarch *
 gdbarch_from_bfd (bfd *abfd)
 {
   struct gdbarch_info info;
-  gdbarch_info_init (&info);
 
   info.abfd = abfd;
   return gdbarch_find_by_info (info);
@@ -582,7 +651,6 @@ set_gdbarch_from_file (bfd *abfd)
   struct gdbarch_info info;
   struct gdbarch *gdbarch;
 
-  gdbarch_info_init (&info);
   info.abfd = abfd;
   info.target_desc = target_current_description ();
   gdbarch = gdbarch_find_by_info (info);
@@ -612,14 +680,14 @@ static const bfd_target *default_bfd_vec;
 
 static enum bfd_endian default_byte_order = BFD_ENDIAN_UNKNOWN;
 
+/* Printable names of architectures.  Used as the enum list of the
+   "set arch" command.  */
+static std::vector<const char *> arches;
+
 void
 initialize_current_architecture (void)
 {
-  const char **arches = gdbarch_printable_names ();
-  struct gdbarch_info info;
-
-  /* determine a default architecture and byte order.  */
-  gdbarch_info_init (&info);
+  arches = gdbarch_printable_names ();
   
   /* Find a default architecture.  */
   if (default_bfd_arch == NULL)
@@ -627,21 +695,22 @@ initialize_current_architecture (void)
       /* Choose the architecture by taking the first one
         alphabetically.  */
       const char *chosen = arches[0];
-      const char **arch;
-      for (arch = arches; *arch != NULL; arch++)
+
+      for (const char *arch : arches)
        {
-         if (strcmp (*arch, chosen) < 0)
-           chosen = *arch;
+         if (strcmp (arch, chosen) < 0)
+           chosen = arch;
        }
+
       if (chosen == NULL)
-       internal_error (__FILE__, __LINE__,
-                       _("initialize_current_architecture: No arch"));
+       internal_error (_("initialize_current_architecture: No arch"));
+
       default_bfd_arch = bfd_scan_arch (chosen);
       if (default_bfd_arch == NULL)
-       internal_error (__FILE__, __LINE__,
-                       _("initialize_current_architecture: Arch not found"));
+       internal_error (_("initialize_current_architecture: Arch not found"));
     }
 
+  gdbarch_info info;
   info.bfd_arch_info = default_bfd_arch;
 
   /* Take several guesses at a byte order.  */
@@ -681,45 +750,28 @@ initialize_current_architecture (void)
   info.byte_order_for_code = info.byte_order;
 
   if (! gdbarch_update_p (info))
-    internal_error (__FILE__, __LINE__,
-                   _("initialize_current_architecture: Selection of "
+    internal_error (_("initialize_current_architecture: Selection of "
                      "initial architecture failed"));
 
   /* Create the ``set architecture'' command appending ``auto'' to the
      list of architectures.  */
   {
     /* Append ``auto''.  */
-    int nr;
-    for (nr = 0; arches[nr] != NULL; nr++);
-    arches = XRESIZEVEC (const char *, arches, nr + 2);
-    arches[nr + 0] = "auto";
-    arches[nr + 1] = NULL;
-    add_setshow_enum_cmd ("architecture", class_support,
-                         arches, &set_architecture_string, 
-                         _("Set architecture of target."),
-                         _("Show architecture of target."), NULL,
-                         set_architecture, show_architecture,
-                         &setlist, &showlist);
-    add_alias_cmd ("processor", "architecture", class_support, 1, &setlist);
+    set_architecture_string = "auto";
+    arches.push_back (set_architecture_string);
+    arches.push_back (nullptr);
+    set_show_commands architecture_cmds
+      = add_setshow_enum_cmd ("architecture", class_support,
+                             arches.data (), &set_architecture_string,
+                             _("Set architecture of target."),
+                             _("Show architecture of target."), NULL,
+                             set_architecture, show_architecture,
+                             &setlist, &showlist);
+    add_alias_cmd ("processor", architecture_cmds.set, class_support, 1,
+                  &setlist);
   }
 }
 
-
-/* Initialize a gdbarch info to values that will be automatically
-   overridden.  Note: Originally, this ``struct info'' was initialized
-   using memset(0).  Unfortunately, that ran into problems, namely
-   BFD_ENDIAN_BIG is zero.  An explicit initialization function that
-   can explicitly set each field to a well defined value is used.  */
-
-void
-gdbarch_info_init (struct gdbarch_info *info)
-{
-  memset (info, 0, sizeof (struct gdbarch_info));
-  info->byte_order = BFD_ENDIAN_UNKNOWN;
-  info->byte_order_for_code = info->byte_order;
-  info->osabi = GDB_OSABI_UNINITIALIZED;
-}
-
 /* Similar to init, but this time fill in the blanks.  Information is
    obtained from the global "set ..." options and explicitly
    initialized INFO fields.  */
@@ -759,12 +811,15 @@ gdbarch_info_fill (struct gdbarch_info *info)
   if (info->byte_order == BFD_ENDIAN_UNKNOWN)
     info->byte_order = default_byte_order;
   info->byte_order_for_code = info->byte_order;
+  /* Wire the default to the last selected byte order.  */
+  default_byte_order = info->byte_order;
 
   /* "(gdb) set osabi ...".  Handled by gdbarch_lookup_osabi.  */
   /* From the manual override, or from file.  */
-  if (info->osabi == GDB_OSABI_UNINITIALIZED)
+  if (info->osabi == GDB_OSABI_UNKNOWN)
     info->osabi = gdbarch_lookup_osabi (info->abfd);
   /* From the target.  */
+
   if (info->osabi == GDB_OSABI_UNKNOWN && info->target_desc != NULL)
     info->osabi = tdesc_osabi (info->target_desc);
   /* From the configured default.  */
@@ -772,6 +827,9 @@ gdbarch_info_fill (struct gdbarch_info *info)
   if (info->osabi == GDB_OSABI_UNKNOWN)
     info->osabi = GDB_OSABI_DEFAULT;
 #endif
+  /* If we still don't know which osabi to pick, pick none.  */
+  if (info->osabi == GDB_OSABI_UNKNOWN)
+    info->osabi = GDB_OSABI_NONE;
 
   /* Must have at least filled in the architecture.  */
   gdb_assert (info->bfd_arch_info != NULL);
@@ -803,22 +861,32 @@ default_has_shared_address_space (struct gdbarch *gdbarch)
 
 int
 default_fast_tracepoint_valid_at (struct gdbarch *gdbarch, CORE_ADDR addr,
-                                 char **msg)
+                                 std::string *msg)
 {
   /* We don't know if maybe the target has some way to do fast
      tracepoints that doesn't need gdbarch, so always say yes.  */
   if (msg)
-    *msg = NULL;
+    msg->clear ();
   return 1;
 }
 
-void
-default_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
-                                  int *kindptr)
+const gdb_byte *
+default_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
+                           int *lenptr)
+{
+  int kind = gdbarch_breakpoint_kind_from_pc (gdbarch, pcptr);
+
+  return gdbarch_sw_breakpoint_from_kind (gdbarch, kind, lenptr);
+}
+int
+default_breakpoint_kind_from_current_state (struct gdbarch *gdbarch,
+                                           struct regcache *regcache,
+                                           CORE_ADDR *pcptr)
 {
-  gdbarch_breakpoint_from_pc (gdbarch, pcptr, kindptr);
+  return gdbarch_breakpoint_kind_from_pc (gdbarch, pcptr);
 }
 
+
 void
 default_gen_return_address (struct gdbarch *gdbarch,
                            struct agent_expr *ax, struct axs_value *value,
@@ -834,7 +902,7 @@ default_return_in_first_hidden_param_p (struct gdbarch *gdbarch,
   /* Usually, the return value's address is stored the in the "first hidden"
      parameter if the return value should be passed by reference, as
      specified in ABI.  */
-  return language_pass_by_reference (type);
+  return !(language_pass_by_reference (type).trivially_copyable);
 }
 
 int default_insn_is_call (struct gdbarch *gdbarch, CORE_ADDR addr)
@@ -852,10 +920,42 @@ int default_insn_is_jump (struct gdbarch *gdbarch, CORE_ADDR addr)
   return 0;
 }
 
+/*  See arch-utils.h.  */
+
+bool
+default_program_breakpoint_here_p (struct gdbarch *gdbarch,
+                                  CORE_ADDR address)
+{
+  int len;
+  const gdb_byte *bpoint = gdbarch_breakpoint_from_pc (gdbarch, &address, &len);
+
+  /* Software breakpoints unsupported?  */
+  if (bpoint == nullptr)
+    return false;
+
+  gdb_byte *target_mem = (gdb_byte *) alloca (len);
+
+  /* Enable the automatic memory restoration from breakpoints while
+     we read the memory.  Otherwise we may find temporary breakpoints, ones
+     inserted by GDB, and flag them as permanent breakpoints.  */
+  scoped_restore restore_memory
+    = make_scoped_restore_show_memory_breakpoints (0);
+
+  if (target_read_memory (address, target_mem, len) == 0)
+    {
+      /* Check if this is a breakpoint instruction for this architecture,
+        including ones used by GDB.  */
+      if (memcmp (target_mem, bpoint, len) == 0)
+       return true;
+    }
+
+  return false;
+}
+
 void
 default_skip_permanent_breakpoint (struct regcache *regcache)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   CORE_ADDR current_pc = regcache_read_pc (regcache);
   int bp_len;
 
@@ -879,11 +979,12 @@ default_infcall_munmap (CORE_ADDR addr, CORE_ADDR size)
 /* -mcmodel=large is used so that no GOT (Global Offset Table) is needed to be
    created in inferior memory by GDB (normally it is set by ld.so).  */
 
-char *
+std::string
 default_gcc_target_options (struct gdbarch *gdbarch)
 {
-  return xstrprintf ("-m%d%s", gdbarch_ptr_bit (gdbarch),
-                    gdbarch_ptr_bit (gdbarch) == 64 ? " -mcmodel=large" : "");
+  return string_printf ("-m%d%s", gdbarch_ptr_bit (gdbarch),
+                       (gdbarch_ptr_bit (gdbarch) == 64
+                        ? " -mcmodel=large" : ""));
 }
 
 /* gdbarch gnu_triplet_regexp method.  */
@@ -894,13 +995,15 @@ default_gnu_triplet_regexp (struct gdbarch *gdbarch)
   return gdbarch_bfd_arch_info (gdbarch)->arch_name;
 }
 
-/* Default method for gdbarch_addressable_memory_unit_size.  By default, a memory byte has
-   a size of 1 octet.  */
+/* Default method for gdbarch_addressable_memory_unit_size.  The default is
+   based on the bits_per_byte defined in the bfd library for the current
+   architecture, this is usually 8-bits, and so this function will usually
+   return 1 indicating 1 byte is 1 octet.  */
 
 int
 default_addressable_memory_unit_size (struct gdbarch *gdbarch)
 {
-  return 1;
+  return gdbarch_bfd_arch_info (gdbarch)->bits_per_byte / 8;
 }
 
 void
@@ -923,14 +1026,438 @@ default_guess_tracepoint_registers (struct gdbarch *gdbarch,
   regs = (gdb_byte *) alloca (register_size (gdbarch, pc_regno));
   store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
                          gdbarch_byte_order (gdbarch), addr);
-  regcache_raw_supply (regcache, pc_regno, regs);
+  regcache->raw_supply (pc_regno, regs);
+}
+
+int
+default_print_insn (bfd_vma memaddr, disassemble_info *info)
+{
+  disassembler_ftype disassemble_fn;
+
+  disassemble_fn = disassembler (info->arch, info->endian == BFD_ENDIAN_BIG,
+                                info->mach, current_program_space->exec_bfd ());
+
+  gdb_assert (disassemble_fn != NULL);
+  return (*disassemble_fn) (memaddr, info);
+}
+
+/* See arch-utils.h.  */
+
+CORE_ADDR
+gdbarch_skip_prologue_noexcept (gdbarch *gdbarch, CORE_ADDR pc) noexcept
+{
+  CORE_ADDR new_pc = pc;
+
+  try
+    {
+      new_pc = gdbarch_skip_prologue (gdbarch, pc);
+    }
+  catch (const gdb_exception &ex)
+    {}
+
+  return new_pc;
+}
+
+/* See arch-utils.h.  */
+
+bool
+default_in_indirect_branch_thunk (gdbarch *gdbarch, CORE_ADDR pc)
+{
+  return false;
+}
+
+/* See arch-utils.h.  */
+
+ULONGEST
+default_type_align (struct gdbarch *gdbarch, struct type *type)
+{
+  return 0;
+}
+
+/* See arch-utils.h.  */
+
+std::string
+default_get_pc_address_flags (frame_info_ptr frame, CORE_ADDR pc)
+{
+  return "";
+}
+
+/* See arch-utils.h.  */
+void
+default_read_core_file_mappings
+  (struct gdbarch *gdbarch,
+   struct bfd *cbfd,
+   read_core_file_mappings_pre_loop_ftype pre_loop_cb,
+   read_core_file_mappings_loop_ftype loop_cb)
+{
+}
+
+CORE_ADDR
+default_get_return_buf_addr (struct type *val_type, frame_info_ptr cur_frame)
+{
+  return 0;
 }
 
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_gdbarch_utils;
+/* Non-zero if we want to trace architecture code.  */
+
+#ifndef GDBARCH_DEBUG
+#define GDBARCH_DEBUG 0
+#endif
+unsigned int gdbarch_debug = GDBARCH_DEBUG;
+static void
+show_gdbarch_debug (struct ui_file *file, int from_tty,
+                   struct cmd_list_element *c, const char *value)
+{
+  gdb_printf (file, _("Architecture debugging is %s.\n"), value);
+}
+
+static const char *
+pformat (struct gdbarch *gdbarch, const struct floatformat **format)
+{
+  if (format == NULL)
+    return "(null)";
+
+  int format_index = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE ? 1 : 0;
+  return format[format_index]->name;
+}
+
+static const char *
+pstring (const char *string)
+{
+  if (string == NULL)
+    return "(null)";
+  return string;
+}
+
+static const char *
+pstring_ptr (char **string)
+{
+  if (string == NULL || *string == NULL)
+    return "(null)";
+  return *string;
+}
+
+/* Helper function to print a list of strings, represented as "const
+   char *const *".  The list is printed comma-separated.  */
+
+static const char *
+pstring_list (const char *const *list)
+{
+  static char ret[100];
+  const char *const *p;
+  size_t offset = 0;
+
+  if (list == NULL)
+    return "(null)";
+
+  ret[0] = '\0';
+  for (p = list; *p != NULL && offset < sizeof (ret); ++p)
+    {
+      size_t s = xsnprintf (ret + offset, sizeof (ret) - offset, "%s, ", *p);
+      offset += 2 + s;
+    }
+
+  if (offset > 0)
+    {
+      gdb_assert (offset - 2 < sizeof (ret));
+      ret[offset - 2] = '\0';
+    }
+
+  return ret;
+}
+
+#include "gdbarch.c"
+
+obstack *gdbarch_obstack (gdbarch *arch)
+{
+  return &arch->obstack;
+}
+
+/* See gdbarch.h.  */
+
+char *
+gdbarch_obstack_strdup (struct gdbarch *arch, const char *string)
+{
+  return obstack_strdup (&arch->obstack, string);
+}
+
+
+/* Free a gdbarch struct.  This should never happen in normal
+   operation --- once you've created a gdbarch, you keep it around.
+   However, if an architecture's init function encounters an error
+   building the structure, it may need to clean up a partially
+   constructed gdbarch.  */
+
+void
+gdbarch_free (struct gdbarch *arch)
+{
+  gdb_assert (arch != NULL);
+  gdb_assert (!arch->initialized_p);
+  delete arch;
+}
+
+/* See gdbarch.h.  */
+
+struct gdbarch_tdep_base *
+gdbarch_tdep_1 (struct gdbarch *gdbarch)
+{
+  if (gdbarch_debug >= 2)
+    gdb_printf (gdb_stdlog, "gdbarch_tdep_1 called\n");
+  return gdbarch->tdep;
+}
+
+registry<gdbarch> *
+registry_accessor<gdbarch>::get (gdbarch *arch)
+{
+  return &arch->registry_fields;
+}
+
+/* Keep a registry of the architectures known by GDB.  */
+
+struct gdbarch_registration
+{
+  enum bfd_architecture bfd_architecture;
+  gdbarch_init_ftype *init;
+  gdbarch_dump_tdep_ftype *dump_tdep;
+  struct gdbarch_list *arches;
+  struct gdbarch_registration *next;
+};
+
+static struct gdbarch_registration *gdbarch_registry = NULL;
+
+std::vector<const char *>
+gdbarch_printable_names ()
+{
+  /* Accumulate a list of names based on the registed list of
+     architectures.  */
+  std::vector<const char *> arches;
+
+  for (gdbarch_registration *rego = gdbarch_registry;
+       rego != nullptr;
+       rego = rego->next)
+    {
+      const struct bfd_arch_info *ap
+       = bfd_lookup_arch (rego->bfd_architecture, 0);
+      if (ap == nullptr)
+       internal_error (_("gdbarch_architecture_names: multi-arch unknown"));
+      do
+       {
+         arches.push_back (ap->printable_name);
+         ap = ap->next;
+       }
+      while (ap != NULL);
+    }
+
+  return arches;
+}
+
+
+void
+gdbarch_register (enum bfd_architecture bfd_architecture,
+                 gdbarch_init_ftype *init,
+                 gdbarch_dump_tdep_ftype *dump_tdep)
+{
+  struct gdbarch_registration **curr;
+  const struct bfd_arch_info *bfd_arch_info;
+
+  /* Check that BFD recognizes this architecture */
+  bfd_arch_info = bfd_lookup_arch (bfd_architecture, 0);
+  if (bfd_arch_info == NULL)
+    {
+      internal_error (_("gdbarch: Attempt to register "
+                       "unknown architecture (%d)"),
+                     bfd_architecture);
+    }
+  /* Check that we haven't seen this architecture before.  */
+  for (curr = &gdbarch_registry;
+       (*curr) != NULL;
+       curr = &(*curr)->next)
+    {
+      if (bfd_architecture == (*curr)->bfd_architecture)
+       internal_error (_("gdbarch: Duplicate registration "
+                         "of architecture (%s)"),
+                       bfd_arch_info->printable_name);
+    }
+  /* log it */
+  if (gdbarch_debug)
+    gdb_printf (gdb_stdlog, "gdbarch_register (%s, %s)\n",
+               bfd_arch_info->printable_name,
+               host_address_to_string (init));
+  /* Append it */
+  (*curr) = XNEW (struct gdbarch_registration);
+  (*curr)->bfd_architecture = bfd_architecture;
+  (*curr)->init = init;
+  (*curr)->dump_tdep = dump_tdep;
+  (*curr)->arches = NULL;
+  (*curr)->next = NULL;
+}
+
+/* Look for an architecture using gdbarch_info.  */
+
+struct gdbarch_list *
+gdbarch_list_lookup_by_info (struct gdbarch_list *arches,
+                            const struct gdbarch_info *info)
+{
+  for (; arches != NULL; arches = arches->next)
+    {
+      if (info->bfd_arch_info != arches->gdbarch->bfd_arch_info)
+       continue;
+      if (info->byte_order != arches->gdbarch->byte_order)
+       continue;
+      if (info->osabi != arches->gdbarch->osabi)
+       continue;
+      if (info->target_desc != arches->gdbarch->target_desc)
+       continue;
+      return arches;
+    }
+  return NULL;
+}
+
+
+/* Find an architecture that matches the specified INFO.  Create a new
+   architecture if needed.  Return that new architecture.  */
+
+struct gdbarch *
+gdbarch_find_by_info (struct gdbarch_info info)
+{
+  struct gdbarch *new_gdbarch;
+  struct gdbarch_registration *rego;
+
+  /* Fill in missing parts of the INFO struct using a number of
+     sources: "set ..."; INFOabfd supplied; and the global
+     defaults.  */
+  gdbarch_info_fill (&info);
+
+  /* Must have found some sort of architecture.  */
+  gdb_assert (info.bfd_arch_info != nullptr);
+
+  if (gdbarch_debug)
+    {
+      gdb_printf (gdb_stdlog,
+                 "gdbarch_find_by_info: info.bfd_arch_info %s\n",
+                 (info.bfd_arch_info != nullptr
+                  ? info.bfd_arch_info->printable_name
+                  : "(null)"));
+      gdb_printf (gdb_stdlog,
+                 "gdbarch_find_by_info: info.byte_order %d (%s)\n",
+                 info.byte_order,
+                 (info.byte_order == BFD_ENDIAN_BIG ? "big"
+                  : info.byte_order == BFD_ENDIAN_LITTLE ? "little"
+                  : "default"));
+      gdb_printf (gdb_stdlog,
+                 "gdbarch_find_by_info: info.osabi %d (%s)\n",
+                 info.osabi, gdbarch_osabi_name (info.osabi));
+      gdb_printf (gdb_stdlog,
+                 "gdbarch_find_by_info: info.abfd %s\n",
+                 host_address_to_string (info.abfd));
+    }
+
+  /* Find the tdep code that knows about this architecture.  */
+  for (rego = gdbarch_registry;
+       rego != nullptr;
+       rego = rego->next)
+    if (rego->bfd_architecture == info.bfd_arch_info->arch)
+      break;
+  if (rego == nullptr)
+    {
+      if (gdbarch_debug)
+       gdb_printf (gdb_stdlog, "gdbarch_find_by_info: "
+                   "No matching architecture\n");
+      return nullptr;
+    }
+
+  /* Ask the tdep code for an architecture that matches "info".  */
+  new_gdbarch = rego->init (info, rego->arches);
+
+  /* Did the tdep code like it?  No.  Reject the change and revert to
+     the old architecture.  */
+  if (new_gdbarch == nullptr)
+    {
+      if (gdbarch_debug)
+       gdb_printf (gdb_stdlog, "gdbarch_find_by_info: "
+                   "Target rejected architecture\n");
+      return nullptr;
+    }
+
+  /* Is this a pre-existing architecture (as determined by already
+     being initialized)?  Move it to the front of the architecture
+     list (keeping the list sorted Most Recently Used).  */
+  if (new_gdbarch->initialized_p)
+    {
+      struct gdbarch_list **list;
+      struct gdbarch_list *self;
+      if (gdbarch_debug)
+       gdb_printf (gdb_stdlog, "gdbarch_find_by_info: "
+                   "Previous architecture %s (%s) selected\n",
+                   host_address_to_string (new_gdbarch),
+                   new_gdbarch->bfd_arch_info->printable_name);
+      /* Find the existing arch in the list.  */
+      for (list = &rego->arches;
+          (*list) != nullptr && (*list)->gdbarch != new_gdbarch;
+          list = &(*list)->next);
+      /* It had better be in the list of architectures.  */
+      gdb_assert ((*list) != nullptr && (*list)->gdbarch == new_gdbarch);
+      /* Unlink SELF.  */
+      self = (*list);
+      (*list) = self->next;
+      /* Insert SELF at the front.  */
+      self->next = rego->arches;
+      rego->arches = self;
+      /* Return it.  */
+      return new_gdbarch;
+    }
+
+  /* It's a new architecture.  */
+  if (gdbarch_debug)
+    gdb_printf (gdb_stdlog, "gdbarch_find_by_info: "
+               "New architecture %s (%s) selected\n",
+               host_address_to_string (new_gdbarch),
+               new_gdbarch->bfd_arch_info->printable_name);
+
+  /* Insert the new architecture into the front of the architecture
+     list (keep the list sorted Most Recently Used).  */
+  {
+    struct gdbarch_list *self = XNEW (struct gdbarch_list);
+    self->next = rego->arches;
+    self->gdbarch = new_gdbarch;
+    rego->arches = self;
+  }
+
+  /* Check that the newly installed architecture is valid.  Plug in
+     any post init values.  */
+  new_gdbarch->dump_tdep = rego->dump_tdep;
+  verify_gdbarch (new_gdbarch);
+  new_gdbarch->initialized_p = true;
+
+  if (gdbarch_debug)
+    gdbarch_dump (new_gdbarch, gdb_stdlog);
+
+  return new_gdbarch;
+}
+
+/* Make the specified architecture current.  */
+
+void
+set_target_gdbarch (struct gdbarch *new_gdbarch)
+{
+  gdb_assert (new_gdbarch != NULL);
+  gdb_assert (new_gdbarch->initialized_p);
+  current_inferior ()->gdbarch = new_gdbarch;
+  gdb::observers::architecture_changed.notify (new_gdbarch);
+  registers_changed ();
+}
+
+/* Return the current inferior's arch.  */
+
+struct gdbarch *
+target_gdbarch (void)
+{
+  return current_inferior ()->gdbarch;
+}
 
+void _initialize_gdbarch_utils ();
 void
-_initialize_gdbarch_utils (void)
+_initialize_gdbarch_utils ()
 {
   add_setshow_enum_cmd ("endian", class_support,
                        endian_enum, &set_endian_string, 
@@ -938,4 +1465,11 @@ _initialize_gdbarch_utils (void)
                        _("Show endianness of target."),
                        NULL, set_endian, show_endian,
                        &setlist, &showlist);
+  add_setshow_zuinteger_cmd ("arch", class_maintenance, &gdbarch_debug, _("\
+Set architecture debugging."), _("\
+Show architecture debugging."), _("\
+When non-zero, architecture debugging is enabled."),
+                           NULL,
+                           show_gdbarch_debug,
+                           &setdebuglist, &showdebuglist);
 }