gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / target-descriptions.c
index 2782ffaab9355e5a74da45e326ad468ff6bed796..20a3a640f4f8f0016ee57415c8c32289ecce1614 100644 (file)
@@ -1,6 +1,6 @@
 /* Target description support for GDB.
 
-   Copyright (C) 2006-2018 Free Software Foundation, Inc.
+   Copyright (C) 2006-2020 Free Software Foundation, Inc.
 
    Contributed by CodeSourcery.
 
@@ -26,7 +26,6 @@
 #include "reggroups.h"
 #include "target.h"
 #include "target-descriptions.h"
-#include "vec.h"
 #include "xml-support.h"
 #include "xml-tdesc.h"
 #include "osabi.h"
@@ -119,6 +118,11 @@ make_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *ttype)
 
       switch (e->kind)
        {
+       case TDESC_TYPE_IEEE_HALF:
+         m_type = arch_float_type (m_gdbarch, -1, "builtin_type_ieee_half",
+                                   floatformats_ieee_half);
+         return;
+
        case TDESC_TYPE_IEEE_SINGLE:
          m_type = arch_float_type (m_gdbarch, -1, "builtin_type_ieee_single",
                                    floatformats_ieee_single);
@@ -152,7 +156,7 @@ make_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *ttype)
 
       type *element_gdb_type = make_gdb_type (m_gdbarch, e->element_type);
       m_type = init_vector_type (element_gdb_type, e->count);
-      TYPE_NAME (m_type) = xstrdup (e->name.c_str ());
+      m_type->set_name (xstrdup (e->name.c_str ()));
       return;
     }
 
@@ -188,8 +192,7 @@ make_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *ttype)
     void make_gdb_type_struct (const tdesc_type_with_fields *e)
     {
       m_type = arch_composite_type (m_gdbarch, NULL, TYPE_CODE_STRUCT);
-      TYPE_NAME (m_type) = xstrdup (e->name.c_str ());
-      TYPE_TAG_NAME (m_type) = TYPE_NAME (m_type);
+      m_type->set_name (xstrdup (e->name.c_str ()));
 
       for (const tdesc_type_field &f : e->fields)
        {
@@ -221,7 +224,7 @@ make_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *ttype)
                 the total size of the structure.  */
              bitsize = f.end - f.start + 1;
              total_size = e->size * TARGET_CHAR_BIT;
-             if (gdbarch_bits_big_endian (m_gdbarch))
+             if (gdbarch_byte_order (m_gdbarch) == BFD_ENDIAN_BIG)
                SET_FIELD_BITPOS (fld[0], total_size - f.start - bitsize);
              else
                SET_FIELD_BITPOS (fld[0], f.start);
@@ -244,7 +247,7 @@ make_gdb_type (struct gdbarch *gdbarch, struct tdesc_type *ttype)
     void make_gdb_type_union (const tdesc_type_with_fields *e)
     {
       m_type = arch_composite_type (m_gdbarch, NULL, TYPE_CODE_UNION);
-      TYPE_NAME (m_type) = xstrdup (e->name.c_str ());
+      m_type->set_name (xstrdup (e->name.c_str ()));
 
       for (const tdesc_type_field &f : e->fields)
        {
@@ -333,6 +336,9 @@ struct target_desc : tdesc_element
   /* The features associated with this target.  */
   std::vector<tdesc_feature_up> features;
 
+  /* Used to cache the generated xml version of the target description.  */
+  mutable char *xmltarget = nullptr;
+
   void accept (tdesc_element_visitor &v) const override
   {
     v.visit_pre (this);
@@ -518,11 +524,11 @@ target_find_description (void)
   /* Next try to read the description from the current target using
      target objects.  */
   if (current_target_desc == NULL)
-    current_target_desc = target_read_description_xml (&current_target);
+    current_target_desc = target_read_description_xml (current_top_target ());
 
   /* If that failed try a target-specific hook.  */
   if (current_target_desc == NULL)
-    current_target_desc = target_read_description (&current_target);
+    current_target_desc = target_read_description (current_top_target ());
 
   /* If a non-NULL description was returned, then update the current
      architecture.  */
@@ -628,6 +634,14 @@ tdesc_architecture (const struct target_desc *target_desc)
   return target_desc->arch;
 }
 
+/* See gdbsupport/tdesc.h.  */
+
+const char *
+tdesc_architecture_name (const struct target_desc *target_desc)
+{
+  return target_desc->arch->printable_name;
+}
+
 /* Return the OSABI associated with this target description, or
    GDB_OSABI_UNKNOWN if no osabi was specified.  */
 
@@ -637,7 +651,16 @@ tdesc_osabi (const struct target_desc *target_desc)
   return target_desc->osabi;
 }
 
-\f
+/* See gdbsupport/tdesc.h.  */
+
+const char *
+tdesc_osabi_name (const struct target_desc *target_desc)
+{
+  enum gdb_osabi osabi = tdesc_osabi (target_desc);
+  if (osabi > GDB_OSABI_UNKNOWN && osabi < GDB_OSABI_INVALID)
+    return gdbarch_osabi_name (osabi);
+  return nullptr;
+}
 
 /* Return 1 if this target description includes any registers.  */
 
@@ -703,12 +726,7 @@ tdesc_find_type (struct gdbarch *gdbarch, const char *id)
 static void *
 tdesc_data_init (struct obstack *obstack)
 {
-  struct tdesc_arch_data *data;
-
-  data = OBSTACK_ZALLOC (obstack, struct tdesc_arch_data);
-  new (data) tdesc_arch_data ();
-
-  return data;
+  return obstack_new<tdesc_arch_data> (obstack);
 }
 
 /* Similar, but for the temporary copy used during architecture
@@ -802,8 +820,7 @@ tdesc_numbered_register_choices (const struct tdesc_feature *feature,
    bits.  The register must exist.  */
 
 int
-tdesc_register_size (const struct tdesc_feature *feature,
-                    const char *name)
+tdesc_register_bitsize (const struct tdesc_feature *feature, const char *name)
 {
   struct tdesc_reg *reg = tdesc_find_register_early (feature, name);
 
@@ -841,12 +858,11 @@ tdesc_register_name (struct gdbarch *gdbarch, int regno)
 {
   struct tdesc_reg *reg = tdesc_find_register (gdbarch, regno);
   int num_regs = gdbarch_num_regs (gdbarch);
-  int num_pseudo_regs = gdbarch_num_pseudo_regs (gdbarch);
 
   if (reg != NULL)
     return reg->name.c_str ();
 
-  if (regno >= num_regs && regno < num_regs + num_pseudo_regs)
+  if (regno >= num_regs && regno < gdbarch_num_cooked_regs (gdbarch))
     {
       struct tdesc_arch_data *data
        = (struct tdesc_arch_data *) gdbarch_data (gdbarch, tdesc_data);
@@ -1108,11 +1124,10 @@ tdesc_use_registers (struct gdbarch *gdbarch,
   set_gdbarch_register_reggroup_p (gdbarch, tdesc_register_reggroup_p);
 }
 
-/* See common/tdesc.h.  */
+/* See gdbsupport/tdesc.h.  */
 
 struct tdesc_feature *
-tdesc_create_feature (struct target_desc *tdesc, const char *name,
-                     const char *xml)
+tdesc_create_feature (struct target_desc *tdesc, const char *name)
 {
   struct tdesc_feature *new_feature = new tdesc_feature (name);
 
@@ -1127,20 +1142,12 @@ allocate_target_description (void)
   return new target_desc ();
 }
 
-static void
-free_target_description (void *arg)
+void
+target_desc_deleter::operator() (struct target_desc *target_desc) const
 {
-  struct target_desc *target_desc = (struct target_desc *) arg;
-
   delete target_desc;
 }
 
-struct cleanup *
-make_cleanup_free_target_description (struct target_desc *target_desc)
-{
-  return make_cleanup (free_target_description, target_desc);
-}
-
 void
 tdesc_add_compatible (struct target_desc *target_desc,
                      const struct bfd_arch_info *compatible)
@@ -1174,7 +1181,7 @@ set_tdesc_property (struct target_desc *target_desc,
   target_desc->properties.emplace_back (key, value);
 }
 
-/* See common/tdesc.h.  */
+/* See gdbsupport/tdesc.h.  */
 
 void
 set_tdesc_architecture (struct target_desc *target_desc,
@@ -1190,7 +1197,7 @@ set_tdesc_architecture (struct target_desc *target_desc,
   target_desc->arch = arch;
 }
 
-/* See common/tdesc.h.  */
+/* See gdbsupport/tdesc.h.  */
 
 void
 set_tdesc_osabi (struct target_desc *target_desc, const char *name)
@@ -1210,24 +1217,6 @@ static struct cmd_list_element *tdesc_unset_cmdlist;
 
 /* Helper functions for the CLI commands.  */
 
-static void
-set_tdesc_cmd (const char *args, int from_tty)
-{
-  help_list (tdesc_set_cmdlist, "set tdesc ", all_commands, gdb_stdout);
-}
-
-static void
-show_tdesc_cmd (const char *args, int from_tty)
-{
-  cmd_show_list (tdesc_show_cmdlist, from_tty, "");
-}
-
-static void
-unset_tdesc_cmd (const char *args, int from_tty)
-{
-  help_list (tdesc_unset_cmdlist, "unset tdesc ", all_commands, gdb_stdout);
-}
-
 static void
 set_tdesc_filename_cmd (const char *args, int from_tty,
                        struct cmd_list_element *c)
@@ -1555,7 +1544,7 @@ public:
     printf_unfiltered ("  Original: %s */\n\n",
                       lbasename (m_filename_after_features.c_str ()));
 
-    printf_unfiltered ("#include \"common/tdesc.h\"\n");
+    printf_unfiltered ("#include \"gdbsupport/tdesc.h\"\n");
     printf_unfiltered ("\n");
   }
 
@@ -1580,8 +1569,8 @@ public:
     printf_unfiltered ("  struct tdesc_feature *feature;\n");
 
     printf_unfiltered
-      ("\n  feature = tdesc_create_feature (result, \"%s\", \"%s\");\n",
-       e->name.c_str (), lbasename (m_filename_after_features.c_str ()));
+      ("\n  feature = tdesc_create_feature (result, \"%s\");\n",
+       e->name.c_str ());
   }
 
   void visit_post (const tdesc_feature *e) override
@@ -1650,6 +1639,21 @@ private:
   int m_next_regnum = 0;
 };
 
+/* See gdbsupport/tdesc.h.  */
+
+const char *
+tdesc_get_features_xml (const target_desc *tdesc)
+{
+  if (tdesc->xmltarget == nullptr)
+    {
+      std::string buffer ("@");
+      print_xml_feature v (&buffer);
+      tdesc->accept (v);
+      tdesc->xmltarget = xstrdup (buffer.c_str ());
+    }
+  return tdesc->xmltarget;
+}
+
 static void
 maint_print_c_tdesc_cmd (const char *args, int from_tty)
 {
@@ -1690,8 +1694,11 @@ maint_print_c_tdesc_cmd (const char *args, int from_tty)
   if (startswith (filename_after_features.c_str (), "i386/32bit-")
       || startswith (filename_after_features.c_str (), "i386/64bit-")
       || startswith (filename_after_features.c_str (), "i386/x32-core.xml")
+      || startswith (filename_after_features.c_str (), "riscv/")
       || startswith (filename_after_features.c_str (), "tic6x-")
-      || startswith (filename_after_features.c_str (), "aarch64"))
+      || startswith (filename_after_features.c_str (), "aarch64")
+      || startswith (filename_after_features.c_str (), "arm/")
+      || startswith (filename_after_features.c_str (), "arc/"))
     {
       print_c_feature v (filename_after_features);
 
@@ -1707,21 +1714,66 @@ maint_print_c_tdesc_cmd (const char *args, int from_tty)
 
 namespace selftests {
 
-static std::vector<std::pair<const char*, const target_desc *>> xml_tdesc;
+/* A reference target description, used for testing (see record_xml_tdesc).  */
+
+struct xml_test_tdesc
+{
+  xml_test_tdesc (const char *name, std::unique_ptr<const target_desc> &&tdesc)
+    : name (name), tdesc (std::move (tdesc))
+  {}
+
+  const char *name;
+  std::unique_ptr<const target_desc> tdesc;
+};
+
+static std::vector<xml_test_tdesc> xml_tdesc;
 
 #if GDB_SELF_TEST
 
-/* See target-descritpions.h.  */
+/* See target-descriptions.h.  */
 
 void
 record_xml_tdesc (const char *xml_file, const struct target_desc *tdesc)
 {
-  xml_tdesc.emplace_back (xml_file, tdesc);
+  xml_tdesc.emplace_back (xml_file, std::unique_ptr<const target_desc> (tdesc));
 }
 #endif
 
 }
 
+/* Test the conversion process of a target description to/from xml: Take a target
+   description TDESC, convert to xml, back to a description, and confirm the new
+   tdesc is identical to the original.  */
+static bool
+maintenance_check_tdesc_xml_convert (const target_desc *tdesc, const char *name)
+{
+  const char *xml = tdesc_get_features_xml (tdesc);
+
+  if (xml == nullptr || *xml != '@')
+    {
+      printf_filtered (_("Could not convert description for %s to xml.\n"),
+                      name);
+      return false;
+    }
+
+  const target_desc *tdesc_trans = string_read_description_xml (xml + 1);
+
+  if (tdesc_trans == nullptr)
+    {
+      printf_filtered (_("Could not convert description for %s from xml.\n"),
+                      name);
+      return false;
+    }
+  else if (*tdesc != *tdesc_trans)
+    {
+      printf_filtered (_("Converted description for %s does not match.\n"),
+                      name);
+      return false;
+    }
+  return true;
+}
+
+
 /* Check that the target descriptions created dynamically by
    architecture-specific code equal the descriptions created from XML files
    found in the specified directory DIR.  */
@@ -1738,40 +1790,47 @@ maintenance_check_xml_descriptions (const char *dir, int from_tty)
 
   for (auto const &e : selftests::xml_tdesc)
     {
-      std::string tdesc_xml = (feature_dir + SLASH_STRING + e.first);
+      std::string tdesc_xml = (feature_dir + SLASH_STRING + e.name);
       const target_desc *tdesc
        = file_read_description_xml (tdesc_xml.data ());
 
-      if (tdesc == NULL || *tdesc != *e.second)
+      if (tdesc == NULL || *tdesc != *e.tdesc)
+       {
+         printf_filtered ( _("Descriptions for %s do not match.\n"), e.name);
+         failed++;
+       }
+      else if (!maintenance_check_tdesc_xml_convert (tdesc, e.name)
+              || !maintenance_check_tdesc_xml_convert (e.tdesc.get (), e.name))
        failed++;
     }
   printf_filtered (_("Tested %lu XML files, %d failed\n"),
                   (long) selftests::xml_tdesc.size (), failed);
 }
 
+void _initialize_target_descriptions ();
 void
-_initialize_target_descriptions (void)
+_initialize_target_descriptions ()
 {
   tdesc_data = gdbarch_data_register_pre_init (tdesc_data_init);
 
-  add_prefix_cmd ("tdesc", class_maintenance, set_tdesc_cmd, _("\
+  add_basic_prefix_cmd ("tdesc", class_maintenance, _("\
 Set target description specific variables."),
-                 &tdesc_set_cmdlist, "set tdesc ",
-                 0 /* allow-unknown */, &setlist);
-  add_prefix_cmd ("tdesc", class_maintenance, show_tdesc_cmd, _("\
+                       &tdesc_set_cmdlist, "set tdesc ",
+                       0 /* allow-unknown */, &setlist);
+  add_show_prefix_cmd ("tdesc", class_maintenance, _("\
 Show target description specific variables."),
-                 &tdesc_show_cmdlist, "show tdesc ",
-                 0 /* allow-unknown */, &showlist);
-  add_prefix_cmd ("tdesc", class_maintenance, unset_tdesc_cmd, _("\
+                      &tdesc_show_cmdlist, "show tdesc ",
+                      0 /* allow-unknown */, &showlist);
+  add_basic_prefix_cmd ("tdesc", class_maintenance, _("\
 Unset target description specific variables."),
-                 &tdesc_unset_cmdlist, "unset tdesc ",
-                 0 /* allow-unknown */, &unsetlist);
+                       &tdesc_unset_cmdlist, "unset tdesc ",
+                       0 /* allow-unknown */, &unsetlist);
 
   add_setshow_filename_cmd ("filename", class_obscure,
                            &tdesc_filename_cmd_string,
                            _("\
-Set the file to read for an XML target description"), _("\
-Show the file to read for an XML target description"), _("\
+Set the file to read for an XML target description."), _("\
+Show the file to read for an XML target description."), _("\
 When set, GDB will read the target description from a local\n\
 file instead of querying the remote target."),
                            set_tdesc_filename_cmd,
@@ -1779,8 +1838,8 @@ file instead of querying the remote target."),
                            &tdesc_set_cmdlist, &tdesc_show_cmdlist);
 
   add_cmd ("filename", class_obscure, unset_tdesc_filename_cmd, _("\
-Unset the file to read for an XML target description.  When unset,\n\
-GDB will read the description from the target."),
+Unset the file to read for an XML target description.\n\
+When unset, GDB will read the description from the target."),
           &tdesc_unset_cmdlist);
 
   add_cmd ("c-tdesc", class_maintenance, maint_print_c_tdesc_cmd, _("\
@@ -1791,6 +1850,7 @@ Print the current target description as a C source file."),
 
   cmd = add_cmd ("xml-descriptions", class_maintenance,
                 maintenance_check_xml_descriptions, _("\
+Check equality of GDB target descriptions and XML created descriptions.\n\
 Check the target descriptions created in GDB equal the descriptions\n\
 created from XML files in the directory.\n\
 The parameter is the directory name."),
This page took 0.035131 seconds and 4 git commands to generate.