Move DWARF index-related things to a separate file
[deliverable/binutils-gdb.git] / gdb / dwarf2read.c
index c15ae5b14384e0f95d9d50e62978a0c19800c058..dfa69d1dbbb8b2e459890a2119fc97d2863640fb 100644 (file)
@@ -29,6 +29,8 @@
    E.g., load_partial_dies, read_partial_die.  */
 
 #include "defs.h"
+#include "dwarf2read.h"
+#include "dwarf-index-common.h"
 #include "bfd.h"
 #include "elf-bfd.h"
 #include "symtab.h"
@@ -86,6 +88,8 @@
 #include <cmath>
 #include <set>
 #include <forward_list>
+#include "rust-lang.h"
+#include "common/pathstuff.h"
 
 /* When == 1, print basic high level tracing messages.
    When > 1, be more verbose.
@@ -113,99 +117,6 @@ static int dwarf2_loclist_index;
 static int dwarf2_locexpr_block_index;
 static int dwarf2_loclist_block_index;
 
-/* A descriptor for dwarf sections.
-
-   S.ASECTION, SIZE are typically initialized when the objfile is first
-   scanned.  BUFFER, READIN are filled in later when the section is read.
-   If the section contained compressed data then SIZE is updated to record
-   the uncompressed size of the section.
-
-   DWP file format V2 introduces a wrinkle that is easiest to handle by
-   creating the concept of virtual sections contained within a real section.
-   In DWP V2 the sections of the input DWO files are concatenated together
-   into one section, but section offsets are kept relative to the original
-   input section.
-   If this is a virtual dwp-v2 section, S.CONTAINING_SECTION is a backlink to
-   the real section this "virtual" section is contained in, and BUFFER,SIZE
-   describe the virtual section.  */
-
-struct dwarf2_section_info
-{
-  union
-  {
-    /* If this is a real section, the bfd section.  */
-    asection *section;
-    /* If this is a virtual section, pointer to the containing ("real")
-       section.  */
-    struct dwarf2_section_info *containing_section;
-  } s;
-  /* Pointer to section data, only valid if readin.  */
-  const gdb_byte *buffer;
-  /* The size of the section, real or virtual.  */
-  bfd_size_type size;
-  /* If this is a virtual section, the offset in the real section.
-     Only valid if is_virtual.  */
-  bfd_size_type virtual_offset;
-  /* True if we have tried to read this section.  */
-  char readin;
-  /* True if this is a virtual section, False otherwise.
-     This specifies which of s.section and s.containing_section to use.  */
-  char is_virtual;
-};
-
-typedef struct dwarf2_section_info dwarf2_section_info_def;
-DEF_VEC_O (dwarf2_section_info_def);
-
-/* All offsets in the index are of this type.  It must be
-   architecture-independent.  */
-typedef uint32_t offset_type;
-
-DEF_VEC_I (offset_type);
-
-/* Ensure only legit values are used.  */
-#define DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE(cu_index, value) \
-  do { \
-    gdb_assert ((unsigned int) (value) <= 1); \
-    GDB_INDEX_SYMBOL_STATIC_SET_VALUE((cu_index), (value)); \
-  } while (0)
-
-/* Ensure only legit values are used.  */
-#define DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE(cu_index, value) \
-  do { \
-    gdb_assert ((value) >= GDB_INDEX_SYMBOL_KIND_TYPE \
-                && (value) <= GDB_INDEX_SYMBOL_KIND_OTHER); \
-    GDB_INDEX_SYMBOL_KIND_SET_VALUE((cu_index), (value)); \
-  } while (0)
-
-/* Ensure we don't use more than the alloted nuber of bits for the CU.  */
-#define DW2_GDB_INDEX_CU_SET_VALUE(cu_index, value) \
-  do { \
-    gdb_assert (((value) & ~GDB_INDEX_CU_MASK) == 0); \
-    GDB_INDEX_CU_SET_VALUE((cu_index), (value)); \
-  } while (0)
-
-#if WORDS_BIGENDIAN
-
-/* Convert VALUE between big- and little-endian.  */
-
-static offset_type
-byte_swap (offset_type value)
-{
-  offset_type result;
-
-  result = (value & 0xff) << 24;
-  result |= (value & 0xff00) << 8;
-  result |= (value & 0xff0000) >> 8;
-  result |= (value & 0xff000000) >> 24;
-  return result;
-}
-
-#define MAYBE_SWAP(V)  byte_swap (V)
-
-#else
-#define MAYBE_SWAP(V) static_cast<offset_type> (V)
-#endif /* WORDS_BIGENDIAN */
-
 /* An index into a (C++) symbol name component in a symbol name as
    recorded in the mapped_index's symbol table.  For each C++ symbol
    in the symbol table, we record one entry for the start of each
@@ -365,160 +276,9 @@ struct mapped_debug_names final : public mapped_index_base
   { return this->name_count; }
 };
 
-typedef struct dwarf2_per_cu_data *dwarf2_per_cu_ptr;
-DEF_VEC_P (dwarf2_per_cu_ptr);
-
-struct tu_stats
-{
-  int nr_uniq_abbrev_tables;
-  int nr_symtabs;
-  int nr_symtab_sharers;
-  int nr_stmt_less_type_units;
-  int nr_all_type_units_reallocs;
-};
-
-/* Collection of data recorded per objfile.
-   This hangs off of dwarf2_objfile_data_key.  */
-
-struct dwarf2_per_objfile : public allocate_on_obstack
-{
-  /* Construct a dwarf2_per_objfile for OBJFILE.  NAMES points to the
-     dwarf2 section names, or is NULL if the standard ELF names are
-     used.  */
-  dwarf2_per_objfile (struct objfile *objfile,
-                     const dwarf2_debug_sections *names);
-
-  ~dwarf2_per_objfile ();
-
-  DISABLE_COPY_AND_ASSIGN (dwarf2_per_objfile);
-
-  /* Free all cached compilation units.  */
-  void free_cached_comp_units ();
-private:
-  /* This function is mapped across the sections and remembers the
-     offset and size of each of the debugging sections we are
-     interested in.  */
-  void locate_sections (bfd *abfd, asection *sectp,
-                       const dwarf2_debug_sections &names);
-
-public:
-  dwarf2_section_info info {};
-  dwarf2_section_info abbrev {};
-  dwarf2_section_info line {};
-  dwarf2_section_info loc {};
-  dwarf2_section_info loclists {};
-  dwarf2_section_info macinfo {};
-  dwarf2_section_info macro {};
-  dwarf2_section_info str {};
-  dwarf2_section_info line_str {};
-  dwarf2_section_info ranges {};
-  dwarf2_section_info rnglists {};
-  dwarf2_section_info addr {};
-  dwarf2_section_info frame {};
-  dwarf2_section_info eh_frame {};
-  dwarf2_section_info gdb_index {};
-  dwarf2_section_info debug_names {};
-  dwarf2_section_info debug_aranges {};
-
-  VEC (dwarf2_section_info_def) *types = NULL;
-
-  /* Back link.  */
-  struct objfile *objfile = NULL;
-
-  /* Table of all the compilation units.  This is used to locate
-     the target compilation unit of a particular reference.  */
-  struct dwarf2_per_cu_data **all_comp_units = NULL;
-
-  /* The number of compilation units in ALL_COMP_UNITS.  */
-  int n_comp_units = 0;
-
-  /* The number of .debug_types-related CUs.  */
-  int n_type_units = 0;
-
-  /* The number of elements allocated in all_type_units.
-     If there are skeleton-less TUs, we add them to all_type_units lazily.  */
-  int n_allocated_type_units = 0;
-
-  /* The .debug_types-related CUs (TUs).
-     This is stored in malloc space because we may realloc it.  */
-  struct signatured_type **all_type_units = NULL;
-
-  /* Table of struct type_unit_group objects.
-     The hash key is the DW_AT_stmt_list value.  */
-  htab_t type_unit_groups {};
-
-  /* A table mapping .debug_types signatures to its signatured_type entry.
-     This is NULL if the .debug_types section hasn't been read in yet.  */
-  htab_t signatured_types {};
-
-  /* Type unit statistics, to see how well the scaling improvements
-     are doing.  */
-  struct tu_stats tu_stats {};
-
-  /* A chain of compilation units that are currently read in, so that
-     they can be freed later.  */
-  dwarf2_per_cu_data *read_in_chain = NULL;
-
-  /* A table mapping DW_AT_dwo_name values to struct dwo_file objects.
-     This is NULL if the table hasn't been allocated yet.  */
-  htab_t dwo_files {};
-
-  /* True if we've checked for whether there is a DWP file.  */
-  bool dwp_checked = false;
-
-  /* The DWP file if there is one, or NULL.  */
-  struct dwp_file *dwp_file = NULL;
-
-  /* The shared '.dwz' file, if one exists.  This is used when the
-     original data was compressed using 'dwz -m'.  */
-  struct dwz_file *dwz_file = NULL;
-
-  /* A flag indicating whether this objfile has a section loaded at a
-     VMA of 0.  */
-  bool has_section_at_zero = false;
-
-  /* True if we are using the mapped index,
-     or we are faking it for OBJF_READNOW's sake.  */
-  bool using_index = false;
-
-  /* The mapped index, or NULL if .gdb_index is missing or not being used.  */
-  mapped_index *index_table = NULL;
-
-  /* The mapped index, or NULL if .debug_names is missing or not being used.  */
-  std::unique_ptr<mapped_debug_names> debug_names_table;
-
-  /* When using index_table, this keeps track of all quick_file_names entries.
-     TUs typically share line table entries with a CU, so we maintain a
-     separate table of all line table entries to support the sharing.
-     Note that while there can be way more TUs than CUs, we've already
-     sorted all the TUs into "type unit groups", grouped by their
-     DW_AT_stmt_list value.  Therefore the only sharing done here is with a
-     CU and its associated TU group if there is one.  */
-  htab_t quick_file_names_table {};
-
-  /* Set during partial symbol reading, to prevent queueing of full
-     symbols.  */
-  bool reading_partial_symbols = false;
-
-  /* Table mapping type DIEs to their struct type *.
-     This is NULL if not allocated yet.
-     The mapping is done via (CU/TU + DIE offset) -> type.  */
-  htab_t die_type_hash {};
-
-  /* The CUs we recently read.  */
-  VEC (dwarf2_per_cu_ptr) *just_read_cus = NULL;
-
-  /* Table containing line_header indexed by offset and offset_in_dwz.  */
-  htab_t line_header_hash {};
-
-  /* Table containing all filenames.  This is an optional because the
-     table is lazily constructed on first access.  */
-  gdb::optional<filename_seen_cache> filenames_cache;
-};
-
-/* Get the dwarf2_per_objfile associated to OBJFILE.  */
+/* See dwarf2read.h.  */
 
-struct dwarf2_per_objfile *
+dwarf2_per_objfile *
 get_dwarf2_per_objfile (struct objfile *objfile)
 {
   return ((struct dwarf2_per_objfile *)
@@ -762,6 +522,14 @@ struct dwarf2_cu
      whether the DW_AT_ranges attribute came from the skeleton or DWO.  */
   ULONGEST ranges_base = 0;
 
+  /* When reading debug info generated by older versions of rustc, we
+     have to rewrite some union types to be struct types with a
+     variant part.  This rewriting must be done after the CU is fully
+     read in, because otherwise at the point of rewriting some struct
+     type might not have been fully processed.  So, we keep a list of
+     all such types here and process them after expansion.  */
+  std::vector<struct type *> rust_unions;
+
   /* Mark used when releasing cached dies.  */
   unsigned int mark : 1;
 
@@ -785,147 +553,10 @@ struct dwarf2_cu
      this information, but later versions do.  */
 
   unsigned int processing_has_namespace_info : 1;
-};
-
-/* Persistent data held for a compilation unit, even when not
-   processing it.  We put a pointer to this structure in the
-   read_symtab_private field of the psymtab.  */
-
-struct dwarf2_per_cu_data
-{
-  /* The start offset and length of this compilation unit.
-     NOTE: Unlike comp_unit_head.length, this length includes
-     initial_length_size.
-     If the DIE refers to a DWO file, this is always of the original die,
-     not the DWO file.  */
-  sect_offset sect_off;
-  unsigned int length;
-
-  /* DWARF standard version this data has been read from (such as 4 or 5).  */
-  short dwarf_version;
-
-  /* Flag indicating this compilation unit will be read in before
-     any of the current compilation units are processed.  */
-  unsigned int queued : 1;
-
-  /* This flag will be set when reading partial DIEs if we need to load
-     absolutely all DIEs for this compilation unit, instead of just the ones
-     we think are interesting.  It gets set if we look for a DIE in the
-     hash table and don't find it.  */
-  unsigned int load_all_dies : 1;
-
-  /* Non-zero if this CU is from .debug_types.
-     Struct dwarf2_per_cu_data is contained in struct signatured_type iff
-     this is non-zero.  */
-  unsigned int is_debug_types : 1;
-
-  /* Non-zero if this CU is from the .dwz file.  */
-  unsigned int is_dwz : 1;
-
-  /* Non-zero if reading a TU directly from a DWO file, bypassing the stub.
-     This flag is only valid if is_debug_types is true.
-     We can't read a CU directly from a DWO file: There are required
-     attributes in the stub.  */
-  unsigned int reading_dwo_directly : 1;
-
-  /* Non-zero if the TU has been read.
-     This is used to assist the "Stay in DWO Optimization" for Fission:
-     When reading a DWO, it's faster to read TUs from the DWO instead of
-     fetching them from random other DWOs (due to comdat folding).
-     If the TU has already been read, the optimization is unnecessary
-     (and unwise - we don't want to change where gdb thinks the TU lives
-     "midflight").
-     This flag is only valid if is_debug_types is true.  */
-  unsigned int tu_read : 1;
-
-  /* The section this CU/TU lives in.
-     If the DIE refers to a DWO file, this is always the original die,
-     not the DWO file.  */
-  struct dwarf2_section_info *section;
-
-  /* Set to non-NULL iff this CU is currently loaded.  When it gets freed out
-     of the CU cache it gets reset to NULL again.  This is left as NULL for
-     dummy CUs (a CU header, but nothing else).  */
-  struct dwarf2_cu *cu;
-
-  /* The corresponding dwarf2_per_objfile.  */
-  struct dwarf2_per_objfile *dwarf2_per_objfile;
-
-  /* When dwarf2_per_objfile->using_index is true, the 'quick' field
-     is active.  Otherwise, the 'psymtab' field is active.  */
-  union
-  {
-    /* The partial symbol table associated with this compilation unit,
-       or NULL for unread partial units.  */
-    struct partial_symtab *psymtab;
-
-    /* Data needed by the "quick" functions.  */
-    struct dwarf2_per_cu_quick_data *quick;
-  } v;
-
-  /* The CUs we import using DW_TAG_imported_unit.  This is filled in
-     while reading psymtabs, used to compute the psymtab dependencies,
-     and then cleared.  Then it is filled in again while reading full
-     symbols, and only deleted when the objfile is destroyed.
-
-     This is also used to work around a difference between the way gold
-     generates .gdb_index version <=7 and the way gdb does.  Arguably this
-     is a gold bug.  For symbols coming from TUs, gold records in the index
-     the CU that includes the TU instead of the TU itself.  This breaks
-     dw2_lookup_symbol: It assumes that if the index says symbol X lives
-     in CU/TU Y, then one need only expand Y and a subsequent lookup in Y
-     will find X.  Alas TUs live in their own symtab, so after expanding CU Y
-     we need to look in TU Z to find X.  Fortunately, this is akin to
-     DW_TAG_imported_unit, so we just use the same mechanism: For
-     .gdb_index version <=7 this also records the TUs that the CU referred
-     to.  Concurrently with this change gdb was modified to emit version 8
-     indices so we only pay a price for gold generated indices.
-     http://sourceware.org/bugzilla/show_bug.cgi?id=15021.  */
-  VEC (dwarf2_per_cu_ptr) *imported_symtabs;
-};
-
-/* Entry in the signatured_types hash table.  */
-
-struct signatured_type
-{
-  /* The "per_cu" object of this type.
-     This struct is used iff per_cu.is_debug_types.
-     N.B.: This is the first member so that it's easy to convert pointers
-     between them.  */
-  struct dwarf2_per_cu_data per_cu;
-
-  /* The type's signature.  */
-  ULONGEST signature;
-
-  /* Offset in the TU of the type's DIE, as read from the TU header.
-     If this TU is a DWO stub and the definition lives in a DWO file
-     (specified by DW_AT_GNU_dwo_name), this value is unusable.  */
-  cu_offset type_offset_in_tu;
-
-  /* Offset in the section of the type's DIE.
-     If the definition lives in a DWO file, this is the offset in the
-     .debug_types.dwo section.
-     The value is zero until the actual value is known.
-     Zero is otherwise not a valid section offset.  */
-  sect_offset type_offset_in_section;
-
-  /* Type units are grouped by their DW_AT_stmt_list entry so that they
-     can share them.  This points to the containing symtab.  */
-  struct type_unit_group *type_unit_group;
-
-  /* The type.
-     The first time we encounter this type we fully read it in and install it
-     in the symbol tables.  Subsequent times we only need the type.  */
-  struct type *type;
 
-  /* Containing DWO unit.
-     This field is valid iff per_cu.reading_dwo_directly.  */
-  struct dwo_unit *dwo_unit;
+  struct partial_die_info *find_partial_die (sect_offset sect_off);
 };
 
-typedef struct signatured_type *sig_type_ptr;
-DEF_VEC_P (sig_type_ptr);
-
 /* A struct that can be used as a hash key for tables based on DW_AT_stmt_list.
    This includes type_unit_group and quick_file_names.  */
 
@@ -1400,16 +1031,34 @@ file_entry::include_dir (const line_header *lh) const
 
 /* When we construct a partial symbol table entry we only
    need this much information.  */
-struct partial_die_info
+struct partial_die_info : public allocate_on_obstack
   {
+    partial_die_info (sect_offset sect_off, struct abbrev_info *abbrev);
+
+    /* Disable assign but still keep copy ctor, which is needed
+       load_partial_dies.   */
+    partial_die_info& operator=(const partial_die_info& rhs) = delete;
+
+    /* Adjust the partial die before generating a symbol for it.  This
+       function may set the is_external flag or change the DIE's
+       name.  */
+    void fixup (struct dwarf2_cu *cu);
+
+    /* Read a minimal amount of information into the minimal die
+       structure.  */
+    const gdb_byte *read (const struct die_reader_specs *reader,
+                         const struct abbrev_info &abbrev,
+                         const gdb_byte *info_ptr);
+
     /* Offset of this DIE.  */
-    sect_offset sect_off;
+    const sect_offset sect_off;
 
     /* DWARF-2 tag for this DIE.  */
-    ENUM_BITFIELD(dwarf_tag) tag : 16;
+    const ENUM_BITFIELD(dwarf_tag) tag : 16;
 
     /* Assorted flags describing the data found in this DIE.  */
-    unsigned int has_children : 1;
+    const unsigned int has_children : 1;
+
     unsigned int is_external : 1;
     unsigned int is_declaration : 1;
     unsigned int has_type : 1;
@@ -1433,7 +1082,7 @@ struct partial_die_info
     /* Flag set if any of the DIE's children are template arguments.  */
     unsigned int has_template_arguments : 1;
 
-    /* Flag set if fixup_partial_die has been called on this die.  */
+    /* Flag set if fixup has been called on this die.  */
     unsigned int fixup_called : 1;
 
     /* Flag set if DW_TAG_imported_unit uses DW_FORM_GNU_ref_alt.  */
@@ -1444,15 +1093,15 @@ struct partial_die_info
 
     /* The name of this DIE.  Normally the value of DW_AT_name, but
        sometimes a default name for unnamed DIEs.  */
-    const char *name;
+    const char *name = nullptr;
 
     /* The linkage name, if present.  */
-    const char *linkage_name;
+    const char *linkage_name = nullptr;
 
     /* The scope to prepend to our children.  This is generally
        allocated on the comp_unit_obstack, so will disappear
        when this compilation unit leaves the cache.  */
-    const char *scope;
+    const char *scope = nullptr;
 
     /* Some data associated with the partial DIE.  The tag determines
        which field is live.  */
@@ -1462,26 +1111,58 @@ struct partial_die_info
       struct dwarf_block *locdesc;
       /* The offset of an import, for DW_TAG_imported_unit.  */
       sect_offset sect_off;
-    } d;
+    } d {};
 
     /* If HAS_PC_INFO, the PC range associated with this DIE.  */
-    CORE_ADDR lowpc;
-    CORE_ADDR highpc;
+    CORE_ADDR lowpc = 0;
+    CORE_ADDR highpc = 0;
 
     /* Pointer into the info_buffer (or types_buffer) pointing at the target of
        DW_AT_sibling, if any.  */
-    /* NOTE: This member isn't strictly necessary, read_partial_die could
-       return DW_AT_sibling values to its caller load_partial_dies.  */
-    const gdb_byte *sibling;
+    /* NOTE: This member isn't strictly necessary, partial_die_info::read
+       could return DW_AT_sibling values to its caller load_partial_dies.  */
+    const gdb_byte *sibling = nullptr;
 
     /* If HAS_SPECIFICATION, the offset of the DIE referred to by
        DW_AT_specification (or DW_AT_abstract_origin or
        DW_AT_extension).  */
-    sect_offset spec_offset;
+    sect_offset spec_offset {};
 
     /* Pointers to this DIE's parent, first child, and next sibling,
        if any.  */
-    struct partial_die_info *die_parent, *die_child, *die_sibling;
+    struct partial_die_info *die_parent = nullptr;
+    struct partial_die_info *die_child = nullptr;
+    struct partial_die_info *die_sibling = nullptr;
+
+    friend struct partial_die_info *
+    dwarf2_cu::find_partial_die (sect_offset sect_off);
+
+  private:
+    /* Only need to do look up in dwarf2_cu::find_partial_die.  */
+    partial_die_info (sect_offset sect_off)
+      : partial_die_info (sect_off, DW_TAG_padding, 0)
+    {
+    }
+
+    partial_die_info (sect_offset sect_off_, enum dwarf_tag tag_,
+                     int has_children_)
+      : sect_off (sect_off_), tag (tag_), has_children (has_children_)
+    {
+      is_external = 0;
+      is_declaration = 0;
+      has_type = 0;
+      has_specification = 0;
+      has_pc_info = 0;
+      may_be_inlined = 0;
+      main_subprogram = 0;
+      scope_set = 0;
+      has_byte_size = 0;
+      has_const_value = 0;
+      has_template_arguments = 0;
+      fixup_called = 0;
+      is_dwz = 0;
+      spec_is_dwz = 0;
+    }
   };
 
 /* This data structure holds the information of an abbrev.  */
@@ -1644,31 +1325,36 @@ struct dwarf_block
    and friends.  */
 static int bits_per_byte = 8;
 
-struct nextfield
-{
-  struct nextfield *next;
-  int accessibility;
-  int virtuality;
-  struct field field;
-};
+/* When reading a variant or variant part, we track a bit more
+   information about the field, and store it in an object of this
+   type.  */
 
-struct nextfnfield
+struct variant_field
 {
-  struct nextfnfield *next;
-  struct fn_field fnfield;
+  /* If we see a DW_TAG_variant, then this will be the discriminant
+     value.  */
+  ULONGEST discriminant_value;
+  /* If we see a DW_TAG_variant, then this will be set if this is the
+     default branch.  */
+  bool default_branch;
+  /* While reading a DW_TAG_variant_part, this will be set if this
+     field is the discriminant.  */
+  bool is_discriminant;
 };
 
-struct fnfieldlist
+struct nextfield
 {
-  const char *name;
-  int length;
-  struct nextfnfield *head;
+  int accessibility = 0;
+  int virtuality = 0;
+  /* Extra information to describe a variant or variant part.  */
+  struct variant_field variant {};
+  struct field field {};
 };
 
-struct decl_field_list
+struct fnfieldlist
 {
-  struct decl_field field;
-  struct decl_field_list *next;
+  const char *name = nullptr;
+  std::vector<struct fn_field> fnfields;
 };
 
 /* The routines that read and process dies for a C struct or C++ class
@@ -1677,34 +1363,27 @@ struct decl_field_list
 struct field_info
   {
     /* List of data member and baseclasses fields.  */
-    struct nextfield *fields, *baseclasses;
+    std::vector<struct nextfield> fields;
+    std::vector<struct nextfield> baseclasses;
 
     /* Number of fields (including baseclasses).  */
-    int nfields;
-
-    /* Number of baseclasses.  */
-    int nbaseclasses;
+    int nfields = 0;
 
     /* Set if the accesibility of one of the fields is not public.  */
-    int non_public_fields;
+    int non_public_fields = 0;
 
     /* Member function fieldlist array, contains name of possibly overloaded
        member function, number of overloaded member functions and a pointer
        to the head of the member function field chain.  */
-    struct fnfieldlist *fnfieldlists;
-
-    /* Number of entries in the fnfieldlists array.  */
-    int nfnfields;
+    std::vector<struct fnfieldlist> fnfieldlists;
 
     /* typedefs defined inside this class.  TYPEDEF_FIELD_LIST contains head of
        a NULL terminated list of TYPEDEF_FIELD_LIST_COUNT elements.  */
-    struct decl_field_list *typedef_field_list;
-    unsigned typedef_field_list_count;
+    std::vector<struct decl_field> typedef_field_list;
 
     /* Nested types defined by this class and the number of elements in this
        list.  */
-    struct decl_field_list *nested_types_list;
-    unsigned nested_types_list_count;
+    std::vector<struct decl_field> nested_types_list;
   };
 
 /* One item on the queue of compilation units to read in full symbols
@@ -1790,18 +1469,9 @@ static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
 static struct partial_die_info *load_partial_dies
   (const struct die_reader_specs *, const gdb_byte *, int);
 
-static const gdb_byte *read_partial_die (const struct die_reader_specs *,
-                                        struct partial_die_info *,
-                                        const struct abbrev_info &,
-                                        unsigned int,
-                                        const gdb_byte *);
-
 static struct partial_die_info *find_partial_die (sect_offset, int,
                                                  struct dwarf2_cu *);
 
-static void fixup_partial_die (struct partial_die_info *,
-                              struct dwarf2_cu *);
-
 static const gdb_byte *read_attribute (const struct die_reader_specs *,
                                       struct attribute *, struct attr_abbrev *,
                                       const gdb_byte *);
@@ -2433,11 +2103,6 @@ attr_value_as_address (struct attribute *attr)
   return addr;
 }
 
-/* The suffix for an index file.  */
-#define INDEX4_SUFFIX ".gdb-index"
-#define INDEX5_SUFFIX ".debug_names"
-#define DEBUG_STR_SUFFIX ".debug_str"
-
 /* See declaration.  */
 
 dwarf2_per_objfile::dwarf2_per_objfile (struct objfile *objfile_,
@@ -2758,14 +2423,10 @@ dwarf2_section_empty_p (const struct dwarf2_section_info *section)
   return section->s.section == NULL || section->size == 0;
 }
 
-/* Read the contents of the section INFO.
-   OBJFILE is the main object file, but not necessarily the file where
-   the section comes from.  E.g., for DWO files the bfd of INFO is the bfd
-   of the DWO file.
-   If the section is compressed, uncompress it before returning.  */
+/* See dwarf2read.h.  */
 
-static void
-dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
+void
+dwarf2_read_section (struct objfile *objfile, dwarf2_section_info *info)
 {
   asection *sectp;
   bfd *abfd;
@@ -3684,31 +3345,6 @@ create_addrmap_from_aranges (struct dwarf2_per_objfile *dwarf2_per_objfile,
                                                    &objfile->objfile_obstack);
 }
 
-/* The hash function for strings in the mapped index.  This is the same as
-   SYMBOL_HASH_NEXT, but we keep a separate copy to maintain control over the
-   implementation.  This is necessary because the hash function is tied to the
-   format of the mapped index file.  The hash values do not have to match with
-   SYMBOL_HASH_NEXT.
-   
-   Use INT_MAX for INDEX_VERSION if you generate the current index format.  */
-
-static hashval_t
-mapped_index_string_hash (int index_version, const void *p)
-{
-  const unsigned char *str = (const unsigned char *) p;
-  hashval_t r = 0;
-  unsigned char c;
-
-  while ((c = *str++) != 0)
-    {
-      if (index_version >= 5)
-       c = tolower (c);
-      r = r * 67 + c - 113;
-    }
-
-  return r;
-}
-
 /* Find a slot in the mapped index INDEX for the object named NAME.
    If NAME is found, set *VEC_OUT to point to the CU vector in the
    constant pool and return true.  If NAME cannot be found, return
@@ -6050,22 +5686,6 @@ dwarf2_read_debug_names (struct dwarf2_per_objfile *dwarf2_per_objfile)
   return true;
 }
 
-/* Symbol name hashing function as specified by DWARF-5.  */
-
-static uint32_t
-dwarf5_djb_hash (const char *str_)
-{
-  const unsigned char *str = (const unsigned char *) str_;
-
-  /* Note: tolower here ignores UTF-8, which isn't fully compliant.
-     See http://dwarfstd.org/ShowIssue.php?issue=161027.1.  */
-
-  uint32_t hash = 5381;
-  while (int c = *str++)
-    hash = hash * 33 + tolower (c);
-  return hash;
-}
-
 /* Type used to manage iterating over all CUs looking for a symbol for
    .debug_names.  */
 
@@ -8538,19 +8158,13 @@ struct tu_abbrev_offset
   sect_offset abbrev_offset;
 };
 
-/* Helper routine for build_type_psymtabs_1, passed to qsort.  */
+/* Helper routine for build_type_psymtabs_1, passed to std::sort.  */
 
-static int
-sort_tu_by_abbrev_offset (const void *ap, const void *bp)
+static bool
+sort_tu_by_abbrev_offset (const struct tu_abbrev_offset &a,
+                         const struct tu_abbrev_offset &b)
 {
-  const struct tu_abbrev_offset * const *a
-    = (const struct tu_abbrev_offset * const*) ap;
-  const struct tu_abbrev_offset * const *b
-    = (const struct tu_abbrev_offset * const*) bp;
-  sect_offset aoff = (*a)->abbrev_offset;
-  sect_offset boff = (*b)->abbrev_offset;
-
-  return (aoff > boff) - (aoff < boff);
+  return a.abbrev_offset < b.abbrev_offset;
 }
 
 /* Efficiently read all the type units.
@@ -8575,10 +8189,8 @@ static void
 build_type_psymtabs_1 (struct dwarf2_per_objfile *dwarf2_per_objfile)
 {
   struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
-  struct cleanup *cleanups;
   abbrev_table_up abbrev_table;
   sect_offset abbrev_offset;
-  struct tu_abbrev_offset *sorted_by_abbrev;
   int i;
 
   /* It's up to the caller to not call us multiple times.  */
@@ -8611,8 +8223,8 @@ build_type_psymtabs_1 (struct dwarf2_per_objfile *dwarf2_per_objfile)
 
   /* Sort in a separate table to maintain the order of all_type_units
      for .gdb_index: TU indices directly index all_type_units.  */
-  sorted_by_abbrev = XNEWVEC (struct tu_abbrev_offset,
-                             dwarf2_per_objfile->n_type_units);
+  std::vector<struct tu_abbrev_offset> sorted_by_abbrev
+    (dwarf2_per_objfile->n_type_units);
   for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
     {
       struct signatured_type *sig_type = dwarf2_per_objfile->all_type_units[i];
@@ -8623,9 +8235,8 @@ build_type_psymtabs_1 (struct dwarf2_per_objfile *dwarf2_per_objfile)
                            sig_type->per_cu.section,
                            sig_type->per_cu.sect_off);
     }
-  cleanups = make_cleanup (xfree, sorted_by_abbrev);
-  qsort (sorted_by_abbrev, dwarf2_per_objfile->n_type_units,
-        sizeof (struct tu_abbrev_offset), sort_tu_by_abbrev_offset);
+  std::sort (sorted_by_abbrev.begin (), sorted_by_abbrev.end (),
+            sort_tu_by_abbrev_offset);
 
   abbrev_offset = (sect_offset) ~(unsigned) 0;
 
@@ -8648,8 +8259,6 @@ build_type_psymtabs_1 (struct dwarf2_per_objfile *dwarf2_per_objfile)
       init_cutu_and_read_dies (&tu->sig_type->per_cu, abbrev_table.get (),
                               0, 0, build_type_psymtabs_reader, NULL);
     }
-
-  do_cleanups (cleanups);
 }
 
 /* Print collected type unit statistics.  */
@@ -9043,7 +8652,7 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
 
   while (pdi != NULL)
     {
-      fixup_partial_die (pdi, cu);
+      pdi->fixup (cu);
 
       /* Anonymous namespaces or modules have no name but have interesting
         children, so we need to look at them.  Ditto for anonymous
@@ -9076,7 +8685,8 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
                {
                  add_partial_symbol (pdi, cu);
                }
-             if (cu->language == language_rust && pdi->has_children)
+             if ((cu->language == language_rust
+                  || cu->language == language_cplus) && pdi->has_children)
                scan_partial_symbols (pdi->die_child, lowpc, highpc,
                                      set_addrmap, cu);
              break;
@@ -9179,7 +8789,7 @@ partial_die_parent_scope (struct partial_die_info *pdi,
   if (parent->scope_set)
     return parent->scope;
 
-  fixup_partial_die (parent, cu);
+  parent->fixup (cu);
 
   grandparent_scope = partial_die_parent_scope (parent, cu);
 
@@ -9244,7 +8854,7 @@ partial_die_full_name (struct partial_die_info *pdi,
      types here will be reused if full symbols are loaded later.  */
   if (pdi->has_template_arguments)
     {
-      fixup_partial_die (pdi, cu);
+      pdi->fixup (cu);
 
       if (pdi->name != NULL && strchr (pdi->name, '<') == NULL)
        {
@@ -9553,7 +9163,7 @@ add_partial_subprogram (struct partial_die_info *pdi,
       pdi = pdi->die_child;
       while (pdi != NULL)
        {
-         fixup_partial_die (pdi, cu);
+         pdi->fixup (cu);
          if (pdi->tag == DW_TAG_subprogram
              || pdi->tag == DW_TAG_inlined_subroutine
              || pdi->tag == DW_TAG_lexical_block)
@@ -10275,6 +9885,305 @@ fixup_go_packaging (struct dwarf2_cu *cu)
     }
 }
 
+/* Allocate a fully-qualified name consisting of the two parts on the
+   obstack.  */
+
+static const char *
+rust_fully_qualify (struct obstack *obstack, const char *p1, const char *p2)
+{
+  return obconcat (obstack, p1, "::", p2, (char *) NULL);
+}
+
+/* A helper that allocates a struct discriminant_info to attach to a
+   union type.  */
+
+static struct discriminant_info *
+alloc_discriminant_info (struct type *type, int discriminant_index,
+                        int default_index)
+{
+  gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
+  gdb_assert (discriminant_index == -1
+             || (discriminant_index >= 0
+                 && discriminant_index < TYPE_NFIELDS (type)));
+  gdb_assert (default_index == -1
+             || (default_index >= 0 && default_index < TYPE_NFIELDS (type)));
+
+  TYPE_FLAG_DISCRIMINATED_UNION (type) = 1;
+
+  struct discriminant_info *disc
+    = ((struct discriminant_info *)
+       TYPE_ZALLOC (type,
+                   offsetof (struct discriminant_info, discriminants)
+                   + TYPE_NFIELDS (type) * sizeof (disc->discriminants[0])));
+  disc->default_index = default_index;
+  disc->discriminant_index = discriminant_index;
+
+  struct dynamic_prop prop;
+  prop.kind = PROP_UNDEFINED;
+  prop.data.baton = disc;
+
+  add_dyn_prop (DYN_PROP_DISCRIMINATED, prop, type);
+
+  return disc;
+}
+
+/* Some versions of rustc emitted enums in an unusual way.
+
+   Ordinary enums were emitted as unions.  The first element of each
+   structure in the union was named "RUST$ENUM$DISR".  This element
+   held the discriminant.
+
+   These versions of Rust also implemented the "non-zero"
+   optimization.  When the enum had two values, and one is empty and
+   the other holds a pointer that cannot be zero, the pointer is used
+   as the discriminant, with a zero value meaning the empty variant.
+   Here, the union's first member is of the form
+   RUST$ENCODED$ENUM$<fieldno>$<fieldno>$...$<variantname>
+   where the fieldnos are the indices of the fields that should be
+   traversed in order to find the field (which may be several fields deep)
+   and the variantname is the name of the variant of the case when the
+   field is zero.
+
+   This function recognizes whether TYPE is of one of these forms,
+   and, if so, smashes it to be a variant type.  */
+
+static void
+quirk_rust_enum (struct type *type, struct objfile *objfile)
+{
+  gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
+
+  /* We don't need to deal with empty enums.  */
+  if (TYPE_NFIELDS (type) == 0)
+    return;
+
+#define RUST_ENUM_PREFIX "RUST$ENCODED$ENUM$"
+  if (TYPE_NFIELDS (type) == 1
+      && startswith (TYPE_FIELD_NAME (type, 0), RUST_ENUM_PREFIX))
+    {
+      const char *name = TYPE_FIELD_NAME (type, 0) + strlen (RUST_ENUM_PREFIX);
+
+      /* Decode the field name to find the offset of the
+        discriminant.  */
+      ULONGEST bit_offset = 0;
+      struct type *field_type = TYPE_FIELD_TYPE (type, 0);
+      while (name[0] >= '0' && name[0] <= '9')
+       {
+         char *tail;
+         unsigned long index = strtoul (name, &tail, 10);
+         name = tail;
+         if (*name != '$'
+             || index >= TYPE_NFIELDS (field_type)
+             || (TYPE_FIELD_LOC_KIND (field_type, index)
+                 != FIELD_LOC_KIND_BITPOS))
+           {
+             complaint (&symfile_complaints,
+                        _("Could not parse Rust enum encoding string \"%s\""
+                          "[in module %s]"),
+                        TYPE_FIELD_NAME (type, 0),
+                        objfile_name (objfile));
+             return;
+           }
+         ++name;
+
+         bit_offset += TYPE_FIELD_BITPOS (field_type, index);
+         field_type = TYPE_FIELD_TYPE (field_type, index);
+       }
+
+      /* Make a union to hold the variants.  */
+      struct type *union_type = alloc_type (objfile);
+      TYPE_CODE (union_type) = TYPE_CODE_UNION;
+      TYPE_NFIELDS (union_type) = 3;
+      TYPE_FIELDS (union_type)
+       = (struct field *) TYPE_ZALLOC (type, 3 * sizeof (struct field));
+      TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
+
+      /* Put the discriminant must at index 0.  */
+      TYPE_FIELD_TYPE (union_type, 0) = field_type;
+      TYPE_FIELD_ARTIFICIAL (union_type, 0) = 1;
+      TYPE_FIELD_NAME (union_type, 0) = "<<discriminant>>";
+      SET_FIELD_BITPOS (TYPE_FIELD (union_type, 0), bit_offset);
+
+      /* The order of fields doesn't really matter, so put the real
+        field at index 1 and the data-less field at index 2.  */
+      struct discriminant_info *disc
+       = alloc_discriminant_info (union_type, 0, 1);
+      TYPE_FIELD (union_type, 1) = TYPE_FIELD (type, 0);
+      TYPE_FIELD_NAME (union_type, 1)
+       = rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (union_type, 1)));
+      TYPE_NAME (TYPE_FIELD_TYPE (union_type, 1))
+       = rust_fully_qualify (&objfile->objfile_obstack, TYPE_NAME (type),
+                             TYPE_FIELD_NAME (union_type, 1));
+
+      const char *dataless_name
+       = rust_fully_qualify (&objfile->objfile_obstack, TYPE_NAME (type),
+                             name);
+      struct type *dataless_type = init_type (objfile, TYPE_CODE_VOID, 0,
+                                             dataless_name);
+      TYPE_FIELD_TYPE (union_type, 2) = dataless_type;
+      /* NAME points into the original discriminant name, which
+        already has the correct lifetime.  */
+      TYPE_FIELD_NAME (union_type, 2) = name;
+      SET_FIELD_BITPOS (TYPE_FIELD (union_type, 2), 0);
+      disc->discriminants[2] = 0;
+
+      /* Smash this type to be a structure type.  We have to do this
+        because the type has already been recorded.  */
+      TYPE_CODE (type) = TYPE_CODE_STRUCT;
+      TYPE_NFIELDS (type) = 1;
+      TYPE_FIELDS (type)
+       = (struct field *) TYPE_ZALLOC (type, sizeof (struct field));
+
+      /* Install the variant part.  */
+      TYPE_FIELD_TYPE (type, 0) = union_type;
+      SET_FIELD_BITPOS (TYPE_FIELD (type, 0), 0);
+      TYPE_FIELD_NAME (type, 0) = "<<variants>>";
+    }
+  else if (TYPE_NFIELDS (type) == 1)
+    {
+      /* We assume that a union with a single field is a univariant
+        enum.  */
+      /* Smash this type to be a structure type.  We have to do this
+        because the type has already been recorded.  */
+      TYPE_CODE (type) = TYPE_CODE_STRUCT;
+
+      /* Make a union to hold the variants.  */
+      struct type *union_type = alloc_type (objfile);
+      TYPE_CODE (union_type) = TYPE_CODE_UNION;
+      TYPE_NFIELDS (union_type) = TYPE_NFIELDS (type);
+      TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
+      TYPE_FIELDS (union_type) = TYPE_FIELDS (type);
+
+      struct type *field_type = TYPE_FIELD_TYPE (union_type, 0);
+      const char *variant_name
+       = rust_last_path_segment (TYPE_NAME (field_type));
+      TYPE_FIELD_NAME (union_type, 0) = variant_name;
+      TYPE_NAME (field_type)
+       = rust_fully_qualify (&objfile->objfile_obstack,
+                             TYPE_NAME (type), variant_name);
+
+      /* Install the union in the outer struct type.  */
+      TYPE_NFIELDS (type) = 1;
+      TYPE_FIELDS (type)
+       = (struct field *) TYPE_ZALLOC (union_type, sizeof (struct field));
+      TYPE_FIELD_TYPE (type, 0) = union_type;
+      TYPE_FIELD_NAME (type, 0) = "<<variants>>";
+      SET_FIELD_BITPOS (TYPE_FIELD (type, 0), 0);
+
+      alloc_discriminant_info (union_type, -1, 0);
+    }
+  else
+    {
+      struct type *disr_type = nullptr;
+      for (int i = 0; i < TYPE_NFIELDS (type); ++i)
+       {
+         disr_type = TYPE_FIELD_TYPE (type, i);
+
+         if (TYPE_NFIELDS (disr_type) == 0)
+           {
+             /* Could be data-less variant, so keep going.  */
+           }
+         else if (strcmp (TYPE_FIELD_NAME (disr_type, 0),
+                          "RUST$ENUM$DISR") != 0)
+           {
+             /* Not a Rust enum.  */
+             return;
+           }
+         else
+           {
+             /* Found one.  */
+             break;
+           }
+       }
+
+      /* If we got here without a discriminant, then it's probably
+        just a union.  */
+      if (disr_type == nullptr)
+       return;
+
+      /* Smash this type to be a structure type.  We have to do this
+        because the type has already been recorded.  */
+      TYPE_CODE (type) = TYPE_CODE_STRUCT;
+
+      /* Make a union to hold the variants.  */
+      struct field *disr_field = &TYPE_FIELD (disr_type, 0);
+      struct type *union_type = alloc_type (objfile);
+      TYPE_CODE (union_type) = TYPE_CODE_UNION;
+      TYPE_NFIELDS (union_type) = 1 + TYPE_NFIELDS (type);
+      TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
+      TYPE_FIELDS (union_type)
+       = (struct field *) TYPE_ZALLOC (union_type,
+                                       (TYPE_NFIELDS (union_type)
+                                        * sizeof (struct field)));
+
+      memcpy (TYPE_FIELDS (union_type) + 1, TYPE_FIELDS (type),
+             TYPE_NFIELDS (type) * sizeof (struct field));
+
+      /* Install the discriminant at index 0 in the union.  */
+      TYPE_FIELD (union_type, 0) = *disr_field;
+      TYPE_FIELD_ARTIFICIAL (union_type, 0) = 1;
+      TYPE_FIELD_NAME (union_type, 0) = "<<discriminant>>";
+
+      /* Install the union in the outer struct type.  */
+      TYPE_FIELD_TYPE (type, 0) = union_type;
+      TYPE_FIELD_NAME (type, 0) = "<<variants>>";
+      TYPE_NFIELDS (type) = 1;
+
+      /* Set the size and offset of the union type.  */
+      SET_FIELD_BITPOS (TYPE_FIELD (type, 0), 0);
+
+      /* We need a way to find the correct discriminant given a
+        variant name.  For convenience we build a map here.  */
+      struct type *enum_type = FIELD_TYPE (*disr_field);
+      std::unordered_map<std::string, ULONGEST> discriminant_map;
+      for (int i = 0; i < TYPE_NFIELDS (enum_type); ++i)
+       {
+         if (TYPE_FIELD_LOC_KIND (enum_type, i) == FIELD_LOC_KIND_ENUMVAL)
+           {
+             const char *name
+               = rust_last_path_segment (TYPE_FIELD_NAME (enum_type, i));
+             discriminant_map[name] = TYPE_FIELD_ENUMVAL (enum_type, i);
+           }
+       }
+
+      int n_fields = TYPE_NFIELDS (union_type);
+      struct discriminant_info *disc
+       = alloc_discriminant_info (union_type, 0, -1);
+      /* Skip the discriminant here.  */
+      for (int i = 1; i < n_fields; ++i)
+       {
+         /* Find the final word in the name of this variant's type.
+            That name can be used to look up the correct
+            discriminant.  */
+         const char *variant_name
+           = rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (union_type,
+                                                                 i)));
+
+         auto iter = discriminant_map.find (variant_name);
+         if (iter != discriminant_map.end ())
+           disc->discriminants[i] = iter->second;
+
+         /* Remove the discriminant field.  */
+         struct type *sub_type = TYPE_FIELD_TYPE (union_type, i);
+         --TYPE_NFIELDS (sub_type);
+         ++TYPE_FIELDS (sub_type);
+         TYPE_FIELD_NAME (union_type, i) = variant_name;
+         TYPE_NAME (sub_type)
+           = rust_fully_qualify (&objfile->objfile_obstack,
+                                 TYPE_NAME (type), variant_name);
+       }
+    }
+}
+
+/* Rewrite some Rust unions to be structures with variants parts.  */
+
+static void
+rust_union_quirks (struct dwarf2_cu *cu)
+{
+  gdb_assert (cu->language == language_rust);
+  for (struct type *type : cu->rust_unions)
+    quirk_rust_enum (type, cu->per_cu->dwarf2_per_objfile->objfile);
+}
+
 /* Return the symtab for PER_CU.  This works properly regardless of
    whether we're using the index or psymtabs.  */
 
@@ -10459,6 +10368,9 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
      physnames.  */
   compute_delayed_physnames (cu);
 
+  if (cu->language == language_rust)
+    rust_union_quirks (cu);
+
   /* Some compilers don't define a DW_AT_high_pc attribute for the
      compilation unit.  If the DW_AT_high_pc is missing, synthesize
      it, by scanning the DIE's below the compilation unit.  */
@@ -10561,6 +10473,9 @@ process_full_type_unit (struct dwarf2_per_cu_data *per_cu,
      physnames.  */
   compute_delayed_physnames (cu);
 
+  if (cu->language == language_rust)
+    rust_union_quirks (cu);
+
   /* TUs share symbol tables.
      If this is the first TU to use this symtab, complete the construction
      of it with end_expandable_symtab.  Otherwise, complete the addition of
@@ -11148,7 +11063,11 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   if (mangled != NULL)
     {
 
-      if (cu->language == language_go)
+      if (language_def (cu->language)->la_store_sym_names_in_linkage_form_p)
+       {
+         /* Do nothing (do not demangle the symbol name).  */
+       }
+      else if (cu->language == language_go)
        {
          /* This is a lie, but we already lie to the caller new_symbol.
             new_symbol assumes we return the mangled name.
@@ -14798,7 +14717,7 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
        return PC_BOUNDS_NOT_PRESENT;
     }
 
-  /* read_partial_die has also the strict LOW < HIGH requirement.  */
+  /* partial_die_info::read has also the strict LOW < HIGH requirement.  */
   if (high <= low)
     return PC_BOUNDS_INVALID;
 
@@ -15114,21 +15033,17 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
   struct field *fp;
   const char *fieldname = "";
 
-  /* Allocate a new field list entry and link it in.  */
-  new_field = XNEW (struct nextfield);
-  make_cleanup (xfree, new_field);
-  memset (new_field, 0, sizeof (struct nextfield));
-
   if (die->tag == DW_TAG_inheritance)
     {
-      new_field->next = fip->baseclasses;
-      fip->baseclasses = new_field;
+      fip->baseclasses.emplace_back ();
+      new_field = &fip->baseclasses.back ();
     }
   else
     {
-      new_field->next = fip->fields;
-      fip->fields = new_field;
+      fip->fields.emplace_back ();
+      new_field = &fip->fields.back ();
     }
+
   fip->nfields++;
 
   attr = dwarf2_attr (die, DW_AT_accessibility, cu);
@@ -15288,8 +15203,21 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
       FIELD_BITSIZE (*fp) = 0;
       FIELD_TYPE (*fp) = die_type (die, cu);
       FIELD_NAME (*fp) = type_name_no_tag (fp->type);
-      fip->nbaseclasses++;
     }
+  else if (die->tag == DW_TAG_variant_part)
+    {
+      /* process_structure_scope will treat this DIE as a union.  */
+      process_structure_scope (die, cu);
+
+      /* The variant part is relative to the start of the enclosing
+        structure.  */
+      SET_FIELD_BITPOS (*fp, 0);
+      fp->type = get_die_type (die, cu);
+      fp->artificial = 1;
+      fp->name = "<<variant>>";
+    }
+  else
+    gdb_assert_not_reached ("missing case in dwarf2_add_field");
 }
 
 /* Can the type given by DIE define another type?  */
@@ -15317,20 +15245,14 @@ static void
 dwarf2_add_type_defn (struct field_info *fip, struct die_info *die,
                      struct dwarf2_cu *cu)
 {
-  struct decl_field_list *new_field;
-  struct decl_field *fp;
-
-  /* Allocate a new field list entry and link it in.  */
-  new_field = XCNEW (struct decl_field_list);
-  make_cleanup (xfree, new_field);
+  struct decl_field fp;
+  memset (&fp, 0, sizeof (fp));
 
   gdb_assert (type_can_define_types (die));
 
-  fp = &new_field->field;
-
   /* Get name of field.  NULL is okay here, meaning an anonymous type.  */
-  fp->name = dwarf2_name (die, cu);
-  fp->type = read_type_die (die, cu);
+  fp.name = dwarf2_name (die, cu);
+  fp.type = read_type_die (die, cu);
 
   /* Save accessibility.  */
   enum dwarf_access_attribute accessibility;
@@ -15345,10 +15267,10 @@ dwarf2_add_type_defn (struct field_info *fip, struct die_info *die,
       /* The assumed value if neither private nor protected.  */
       break;
     case DW_ACCESS_private:
-      fp->is_private = 1;
+      fp.is_private = 1;
       break;
     case DW_ACCESS_protected:
-      fp->is_protected = 1;
+      fp.is_protected = 1;
       break;
     default:
       complaint (&symfile_complaints,
@@ -15356,17 +15278,9 @@ dwarf2_add_type_defn (struct field_info *fip, struct die_info *die,
     }
 
   if (die->tag == DW_TAG_typedef)
-    {
-      new_field->next = fip->typedef_field_list;
-      fip->typedef_field_list = new_field;
-      fip->typedef_field_list_count++;
-    }
+    fip->typedef_field_list.push_back (fp);
   else
-    {
-      new_field->next = fip->nested_types_list;
-      fip->nested_types_list = new_field;
-      fip->nested_types_list_count++;
-    }
+    fip->nested_types_list.push_back (fp);
 }
 
 /* Create the vector of fields, and attach it to the type.  */
@@ -15381,8 +15295,7 @@ dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
      and create blank accessibility bitfields if necessary.  */
   TYPE_NFIELDS (type) = nfields;
   TYPE_FIELDS (type) = (struct field *)
-    TYPE_ALLOC (type, sizeof (struct field) * nfields);
-  memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields);
+    TYPE_ZALLOC (type, sizeof (struct field) * nfields);
 
   if (fip->non_public_fields && cu->language != language_ada)
     {
@@ -15403,47 +15316,53 @@ dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
 
   /* If the type has baseclasses, allocate and clear a bit vector for
      TYPE_FIELD_VIRTUAL_BITS.  */
-  if (fip->nbaseclasses && cu->language != language_ada)
+  if (!fip->baseclasses.empty () && cu->language != language_ada)
     {
-      int num_bytes = B_BYTES (fip->nbaseclasses);
+      int num_bytes = B_BYTES (fip->baseclasses.size ());
       unsigned char *pointer;
 
       ALLOCATE_CPLUS_STRUCT_TYPE (type);
       pointer = (unsigned char *) TYPE_ALLOC (type, num_bytes);
       TYPE_FIELD_VIRTUAL_BITS (type) = pointer;
-      B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->nbaseclasses);
-      TYPE_N_BASECLASSES (type) = fip->nbaseclasses;
+      B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->baseclasses.size ());
+      TYPE_N_BASECLASSES (type) = fip->baseclasses.size ();
     }
 
-  /* Copy the saved-up fields into the field vector.  Start from the head of
-     the list, adding to the tail of the field array, so that they end up in
-     the same order in the array in which they were added to the list.  */
-  while (nfields-- > 0)
+  if (TYPE_FLAG_DISCRIMINATED_UNION (type))
     {
-      struct nextfield *fieldp;
+      struct discriminant_info *di = alloc_discriminant_info (type, -1, -1);
 
-      if (fip->fields)
-       {
-         fieldp = fip->fields;
-         fip->fields = fieldp->next;
-       }
-      else
+      for (int index = 0; index < nfields; ++index)
        {
-         fieldp = fip->baseclasses;
-         fip->baseclasses = fieldp->next;
+         struct nextfield &field = fip->fields[index];
+
+         if (field.variant.is_discriminant)
+           di->discriminant_index = index;
+         else if (field.variant.default_branch)
+           di->default_index = index;
+         else
+           di->discriminants[index] = field.variant.discriminant_value;
        }
+    }
 
-      TYPE_FIELD (type, nfields) = fieldp->field;
-      switch (fieldp->accessibility)
+  /* Copy the saved-up fields into the field vector.  */
+  for (int i = 0; i < nfields; ++i)
+    {
+      struct nextfield &field
+       = ((i < fip->baseclasses.size ()) ? fip->baseclasses[i]
+          : fip->fields[i - fip->baseclasses.size ()]);
+
+      TYPE_FIELD (type, i) = field.field;
+      switch (field.accessibility)
        {
        case DW_ACCESS_private:
          if (cu->language != language_ada)
-           SET_TYPE_FIELD_PRIVATE (type, nfields);
+           SET_TYPE_FIELD_PRIVATE (type, i);
          break;
 
        case DW_ACCESS_protected:
          if (cu->language != language_ada)
-           SET_TYPE_FIELD_PROTECTED (type, nfields);
+           SET_TYPE_FIELD_PROTECTED (type, i);
          break;
 
        case DW_ACCESS_public:
@@ -15453,19 +15372,19 @@ dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
          /* Unknown accessibility.  Complain and treat it as public.  */
          {
            complaint (&symfile_complaints, _("unsupported accessibility %d"),
-                      fieldp->accessibility);
+                      field.accessibility);
          }
          break;
        }
-      if (nfields < fip->nbaseclasses)
+      if (i < fip->baseclasses.size ())
        {
-         switch (fieldp->virtuality)
+         switch (field.virtuality)
            {
            case DW_VIRTUALITY_virtual:
            case DW_VIRTUALITY_pure_virtual:
              if (cu->language == language_ada)
                error (_("unexpected virtuality in component of Ada type"));
-             SET_TYPE_FIELD_VIRTUAL (type, nfields);
+             SET_TYPE_FIELD_VIRTUAL (type, i);
              break;
            }
        }
@@ -15508,11 +15427,10 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
 {
   struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
   struct attribute *attr;
-  struct fnfieldlist *flp;
   int i;
+  struct fnfieldlist *flp = nullptr;
   struct fn_field *fnp;
   const char *fieldname;
-  struct nextfnfield *new_fnfield;
   struct type *this_type;
   enum dwarf_access_attribute accessibility;
 
@@ -15525,51 +15443,33 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
     return;
 
   /* Look up member function name in fieldlist.  */
-  for (i = 0; i < fip->nfnfields; i++)
+  for (i = 0; i < fip->fnfieldlists.size (); i++)
     {
       if (strcmp (fip->fnfieldlists[i].name, fieldname) == 0)
-       break;
+       {
+         flp = &fip->fnfieldlists[i];
+         break;
+       }
     }
 
-  /* Create new list element if necessary.  */
-  if (i < fip->nfnfields)
-    flp = &fip->fnfieldlists[i];
-  else
+  /* Create a new fnfieldlist if necessary.  */
+  if (flp == nullptr)
     {
-      if ((fip->nfnfields % DW_FIELD_ALLOC_CHUNK) == 0)
-       {
-         fip->fnfieldlists = (struct fnfieldlist *)
-           xrealloc (fip->fnfieldlists,
-                     (fip->nfnfields + DW_FIELD_ALLOC_CHUNK)
-                     * sizeof (struct fnfieldlist));
-         if (fip->nfnfields == 0)
-           make_cleanup (free_current_contents, &fip->fnfieldlists);
-       }
-      flp = &fip->fnfieldlists[fip->nfnfields];
+      fip->fnfieldlists.emplace_back ();
+      flp = &fip->fnfieldlists.back ();
       flp->name = fieldname;
-      flp->length = 0;
-      flp->head = NULL;
-      i = fip->nfnfields++;
+      i = fip->fnfieldlists.size () - 1;
     }
 
-  /* Create a new member function field and chain it to the field list
-     entry.  */
-  new_fnfield = XNEW (struct nextfnfield);
-  make_cleanup (xfree, new_fnfield);
-  memset (new_fnfield, 0, sizeof (struct nextfnfield));
-  new_fnfield->next = flp->head;
-  flp->head = new_fnfield;
-  flp->length++;
-
-  /* Fill in the member function field info.  */
-  fnp = &new_fnfield->fnfield;
+  /* Create a new member function field and add it to the vector of
+     fnfieldlists.  */
+  flp->fnfields.emplace_back ();
+  fnp = &flp->fnfields.back ();
 
   /* Delay processing of the physname until later.  */
   if (cu->language == language_cplus)
-    {
-      add_to_method_list (type, i, flp->length - 1, fieldname,
-                         die, cu);
-    }
+    add_to_method_list (type, i, flp->fnfields.size () - 1, fieldname,
+                       die, cu);
   else
     {
       const char *physname = dwarf2_physname (fieldname, die, cu);
@@ -15716,31 +15616,29 @@ static void
 dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
                                 struct dwarf2_cu *cu)
 {
-  struct fnfieldlist *flp;
-  int i;
-
   if (cu->language == language_ada)
     error (_("unexpected member functions in Ada type"));
 
   ALLOCATE_CPLUS_STRUCT_TYPE (type);
   TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
-    TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * fip->nfnfields);
+    TYPE_ALLOC (type,
+               sizeof (struct fn_fieldlist) * fip->fnfieldlists.size ());
 
-  for (i = 0, flp = fip->fnfieldlists; i < fip->nfnfields; i++, flp++)
+  for (int i = 0; i < fip->fnfieldlists.size (); i++)
     {
-      struct nextfnfield *nfp = flp->head;
+      struct fnfieldlist &nf = fip->fnfieldlists[i];
       struct fn_fieldlist *fn_flp = &TYPE_FN_FIELDLIST (type, i);
-      int k;
 
-      TYPE_FN_FIELDLIST_NAME (type, i) = flp->name;
-      TYPE_FN_FIELDLIST_LENGTH (type, i) = flp->length;
+      TYPE_FN_FIELDLIST_NAME (type, i) = nf.name;
+      TYPE_FN_FIELDLIST_LENGTH (type, i) = nf.fnfields.size ();
       fn_flp->fn_fields = (struct fn_field *)
-       TYPE_ALLOC (type, sizeof (struct fn_field) * flp->length);
-      for (k = flp->length; (k--, nfp); nfp = nfp->next)
-       fn_flp->fn_fields[k] = nfp->fnfield;
+       TYPE_ALLOC (type, sizeof (struct fn_field) * nf.fnfields.size ());
+
+      for (int k = 0; k < nf.fnfields.size (); ++k)
+       fn_flp->fn_fields[k] = nf.fnfields[k];
     }
 
-  TYPE_NFN_FIELDS (type) = fip->nfnfields;
+  TYPE_NFN_FIELDS (type) = fip->fnfieldlists.size ();
 }
 
 /* Returns non-zero if NAME is the name of a vtable member in CU's
@@ -15876,6 +15774,11 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
     {
       TYPE_CODE (type) = TYPE_CODE_UNION;
     }
+  else if (die->tag == DW_TAG_variant_part)
+    {
+      TYPE_CODE (type) = TYPE_CODE_UNION;
+      TYPE_FLAG_DISCRIMINATED_UNION (type) = 1;
+    }
   else
     {
       TYPE_CODE (type) = TYPE_CODE_STRUCT;
@@ -15935,70 +15838,152 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
   return type;
 }
 
-/* Finish creating a structure or union type, including filling in
-   its members and creating a symbol for it.  */
+/* A helper for process_structure_scope that handles a single member
+   DIE.  */
 
 static void
-process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
+handle_struct_member_die (struct die_info *child_die, struct type *type,
+                         struct field_info *fi,
+                         std::vector<struct symbol *> *template_args,
+                         struct dwarf2_cu *cu)
 {
-  struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
-  struct die_info *child_die;
-  struct type *type;
-
-  type = get_die_type (die, cu);
-  if (type == NULL)
-    type = read_structure_type (die, cu);
-
-  if (die->child != NULL && ! die_is_declaration (die, cu))
+  if (child_die->tag == DW_TAG_member
+      || child_die->tag == DW_TAG_variable
+      || child_die->tag == DW_TAG_variant_part)
     {
-      struct field_info fi;
-      std::vector<struct symbol *> template_args;
-      struct cleanup *back_to = make_cleanup (null_cleanup, 0);
-
-      memset (&fi, 0, sizeof (struct field_info));
-
-      child_die = die->child;
+      /* NOTE: carlton/2002-11-05: A C++ static data member
+        should be a DW_TAG_member that is a declaration, but
+        all versions of G++ as of this writing (so through at
+        least 3.2.1) incorrectly generate DW_TAG_variable
+        tags for them instead.  */
+      dwarf2_add_field (fi, child_die, cu);
+    }
+  else if (child_die->tag == DW_TAG_subprogram)
+    {
+      /* Rust doesn't have member functions in the C++ sense.
+        However, it does emit ordinary functions as children
+        of a struct DIE.  */
+      if (cu->language == language_rust)
+       read_func_scope (child_die, cu);
+      else
+       {
+         /* C++ member function.  */
+         dwarf2_add_member_fn (fi, child_die, type, cu);
+       }
+    }
+  else if (child_die->tag == DW_TAG_inheritance)
+    {
+      /* C++ base class field.  */
+      dwarf2_add_field (fi, child_die, cu);
+    }
+  else if (type_can_define_types (child_die))
+    dwarf2_add_type_defn (fi, child_die, cu);
+  else if (child_die->tag == DW_TAG_template_type_param
+          || child_die->tag == DW_TAG_template_value_param)
+    {
+      struct symbol *arg = new_symbol (child_die, NULL, cu);
 
-      while (child_die && child_die->tag)
+      if (arg != NULL)
+       template_args->push_back (arg);
+    }
+  else if (child_die->tag == DW_TAG_variant)
+    {
+      /* In a variant we want to get the discriminant and also add a
+        field for our sole member child.  */
+      struct attribute *discr = dwarf2_attr (child_die, DW_AT_discr_value, cu);
+
+      for (struct die_info *variant_child = child_die->child;
+          variant_child != NULL;
+          variant_child = sibling_die (variant_child))
        {
-         if (child_die->tag == DW_TAG_member
-             || child_die->tag == DW_TAG_variable)
-           {
-             /* NOTE: carlton/2002-11-05: A C++ static data member
-                should be a DW_TAG_member that is a declaration, but
-                all versions of G++ as of this writing (so through at
-                least 3.2.1) incorrectly generate DW_TAG_variable
-                tags for them instead.  */
-             dwarf2_add_field (&fi, child_die, cu);
-           }
-         else if (child_die->tag == DW_TAG_subprogram)
+         if (variant_child->tag == DW_TAG_member)
            {
-             /* Rust doesn't have member functions in the C++ sense.
-                However, it does emit ordinary functions as children
-                of a struct DIE.  */
-             if (cu->language == language_rust)
-               read_func_scope (child_die, cu);
-             else
-               {
-                 /* C++ member function.  */
-                 dwarf2_add_member_fn (&fi, child_die, type, cu);
-               }
-           }
-         else if (child_die->tag == DW_TAG_inheritance)
-           {
-             /* C++ base class field.  */
-             dwarf2_add_field (&fi, child_die, cu);
+             handle_struct_member_die (variant_child, type, fi,
+                                       template_args, cu);
+             /* Only handle the one.  */
+             break;
            }
-         else if (type_can_define_types (child_die))
-           dwarf2_add_type_defn (&fi, child_die, cu);
-         else if (child_die->tag == DW_TAG_template_type_param
-                  || child_die->tag == DW_TAG_template_value_param)
-           {
-             struct symbol *arg = new_symbol (child_die, NULL, cu);
+       }
 
-             if (arg != NULL)
-               template_args.push_back (arg);
-           }
+      /* We don't handle this but we might as well report it if we see
+        it.  */
+      if (dwarf2_attr (child_die, DW_AT_discr_list, cu) != nullptr)
+         complaint (&symfile_complaints,
+                    _("DW_AT_discr_list is not supported yet"
+                      " - DIE at %s [in module %s]"),
+                    sect_offset_str (child_die->sect_off),
+                    objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+
+      /* The first field was just added, so we can stash the
+        discriminant there.  */
+      gdb_assert (!fi->fields.empty ());
+      if (discr == NULL)
+       fi->fields.back ().variant.default_branch = true;
+      else
+       fi->fields.back ().variant.discriminant_value = DW_UNSND (discr);
+    }
+}
+
+/* Finish creating a structure or union type, including filling in
+   its members and creating a symbol for it.  */
+
+static void
+process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
+  struct die_info *child_die;
+  struct type *type;
+
+  type = get_die_type (die, cu);
+  if (type == NULL)
+    type = read_structure_type (die, cu);
+
+  /* When reading a DW_TAG_variant_part, we need to notice when we
+     read the discriminant member, so we can record it later in the
+     discriminant_info.  */
+  bool is_variant_part = TYPE_FLAG_DISCRIMINATED_UNION (type);
+  sect_offset discr_offset;
+
+  if (is_variant_part)
+    {
+      struct attribute *discr = dwarf2_attr (die, DW_AT_discr, cu);
+      if (discr == NULL)
+       {
+         /* Maybe it's a univariant form, an extension we support.
+            In this case arrange not to check the offset.  */
+         is_variant_part = false;
+       }
+      else if (attr_form_is_ref (discr))
+       {
+         struct dwarf2_cu *target_cu = cu;
+         struct die_info *target_die = follow_die_ref (die, discr, &target_cu);
+
+         discr_offset = target_die->sect_off;
+       }
+      else
+       {
+         complaint (&symfile_complaints,
+                    _("DW_AT_discr does not have DIE reference form"
+                      " - DIE at %s [in module %s]"),
+                    sect_offset_str (die->sect_off),
+                    objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+         is_variant_part = false;
+       }
+    }
+
+  if (die->child != NULL && ! die_is_declaration (die, cu))
+    {
+      struct field_info fi;
+      std::vector<struct symbol *> template_args;
+
+      child_die = die->child;
+
+      while (child_die && child_die->tag)
+       {
+         handle_struct_member_die (child_die, type, &fi, &template_args, cu);
+
+         if (is_variant_part && discr_offset == child_die->sect_off)
+           fi.fields.back ().variant.is_discriminant = true;
 
          child_die = sibling_die (child_die);
        }
@@ -16021,7 +16006,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
       /* Attach fields and member functions to the type.  */
       if (fi.nfields)
        dwarf2_attach_fields_to_type (&fi, type, cu);
-      if (fi.nfnfields)
+      if (!fi.fnfieldlists.empty ())
        {
          dwarf2_attach_fn_fields_to_type (&fi, type, cu);
 
@@ -16091,56 +16076,41 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
 
       /* Copy fi.typedef_field_list linked list elements content into the
         allocated array TYPE_TYPEDEF_FIELD_ARRAY (type).  */
-      if (fi.typedef_field_list)
+      if (!fi.typedef_field_list.empty ())
        {
-         int i = fi.typedef_field_list_count;
+         int count = fi.typedef_field_list.size ();
 
          ALLOCATE_CPLUS_STRUCT_TYPE (type);
          TYPE_TYPEDEF_FIELD_ARRAY (type)
            = ((struct decl_field *)
-              TYPE_ALLOC (type, sizeof (TYPE_TYPEDEF_FIELD (type, 0)) * i));
-         TYPE_TYPEDEF_FIELD_COUNT (type) = i;
-
-         /* Reverse the list order to keep the debug info elements order.  */
-         while (--i >= 0)
-           {
-             struct decl_field *dest, *src;
+              TYPE_ALLOC (type,
+                          sizeof (TYPE_TYPEDEF_FIELD (type, 0)) * count));
+         TYPE_TYPEDEF_FIELD_COUNT (type) = count;
 
-             dest = &TYPE_TYPEDEF_FIELD (type, i);
-             src = &fi.typedef_field_list->field;
-             fi.typedef_field_list = fi.typedef_field_list->next;
-             *dest = *src;
-           }
+         for (int i = 0; i < fi.typedef_field_list.size (); ++i)
+           TYPE_TYPEDEF_FIELD (type, i) = fi.typedef_field_list[i];
        }
 
       /* Copy fi.nested_types_list linked list elements content into the
         allocated array TYPE_NESTED_TYPES_ARRAY (type).  */
-      if (fi.nested_types_list != NULL && cu->language != language_ada)
+      if (!fi.nested_types_list.empty () && cu->language != language_ada)
        {
-         int i = fi.nested_types_list_count;
+         int count = fi.nested_types_list.size ();
 
          ALLOCATE_CPLUS_STRUCT_TYPE (type);
          TYPE_NESTED_TYPES_ARRAY (type)
            = ((struct decl_field *)
-              TYPE_ALLOC (type, sizeof (struct decl_field) * i));
-         TYPE_NESTED_TYPES_COUNT (type) = i;
+              TYPE_ALLOC (type, sizeof (struct decl_field) * count));
+         TYPE_NESTED_TYPES_COUNT (type) = count;
 
-         /* Reverse the list order to keep the debug info elements order.  */
-         while (--i >= 0)
-           {
-             struct decl_field *dest, *src;
-
-             dest = &TYPE_NESTED_TYPES_FIELD (type, i);
-             src = &fi.nested_types_list->field;
-             fi.nested_types_list = fi.nested_types_list->next;
-             *dest = *src;
-           }
+         for (int i = 0; i < fi.nested_types_list.size (); ++i)
+           TYPE_NESTED_TYPES_FIELD (type, i) = fi.nested_types_list[i];
        }
-
-      do_cleanups (back_to);
     }
 
   quirk_gcc_member_function_pointer (type, objfile);
+  if (cu->language == language_rust && die->tag == DW_TAG_union_type)
+    cu->rust_unions.push_back (type);
 
   /* NOTE: carlton/2004-03-16: GCC 3.4 (or at least one of its
      snapshots) has been known to create a die giving a declaration
@@ -18307,11 +18277,10 @@ load_partial_dies (const struct die_reader_specs *reader,
          continue;
        }
 
-      struct partial_die_info pdi;
+      struct partial_die_info pdi ((sect_offset) (info_ptr - reader->buffer),
+                                  abbrev);
 
-      memset (&pdi, 0, sizeof (pdi));
-      info_ptr = read_partial_die (reader, &pdi, *abbrev, bytes_read,
-                                  info_ptr);
+      info_ptr = pdi.read (reader, *abbrev, info_ptr + bytes_read);
 
       /* This two-pass algorithm for processing partial symbols has a
         high cost in cache pressure.  Thus, handle some simple cases
@@ -18385,9 +18354,8 @@ load_partial_dies (const struct die_reader_specs *reader,
        }
 
       struct partial_die_info *part_die
-         = XOBNEW (&cu->comp_unit_obstack, struct partial_die_info);
+       = new (&cu->comp_unit_obstack) partial_die_info (pdi);
 
-      memcpy (part_die, &pdi, sizeof (pdi));
       /* We'll save this DIE so link it in.  */
       part_die->die_parent = parent_die;
       part_die->die_sibling = NULL;
@@ -18481,36 +18449,31 @@ load_partial_dies (const struct die_reader_specs *reader,
     }
 }
 
-/* Read a minimal amount of information into the minimal die structure.  */
+partial_die_info::partial_die_info (sect_offset sect_off_,
+                                   struct abbrev_info *abbrev)
+  : partial_die_info (sect_off_, abbrev->tag, abbrev->has_children)
+{
+}
 
-static const gdb_byte *
-read_partial_die (const struct die_reader_specs *reader,
-                 struct partial_die_info *part_die,
-                 const struct abbrev_info &abbrev, unsigned int abbrev_len,
-                 const gdb_byte *info_ptr)
+/* Read a minimal amount of information into the minimal die structure.
+   INFO_PTR should point just after the initial uleb128 of a DIE.  */
+
+const gdb_byte *
+partial_die_info::read (const struct die_reader_specs *reader,
+                       const struct abbrev_info &abbrev, const gdb_byte *info_ptr)
 {
   struct dwarf2_cu *cu = reader->cu;
   struct dwarf2_per_objfile *dwarf2_per_objfile
     = cu->per_cu->dwarf2_per_objfile;
-  struct objfile *objfile = dwarf2_per_objfile->objfile;
-  const gdb_byte *buffer = reader->buffer;
   unsigned int i;
-  struct attribute attr;
   int has_low_pc_attr = 0;
   int has_high_pc_attr = 0;
   int high_pc_relative = 0;
 
-  memset (part_die, 0, sizeof (struct partial_die_info));
-
-  part_die->sect_off = (sect_offset) (info_ptr - buffer);
-
-  info_ptr += abbrev_len;
-
-  part_die->tag = abbrev.tag;
-  part_die->has_children = abbrev.has_children;
-
   for (i = 0; i < abbrev.num_attrs; ++i)
     {
+      struct attribute attr;
+
       info_ptr = read_attribute (reader, &attr, &abbrev.attrs[i], info_ptr);
 
       /* Store the data if it is of an attribute we want to keep in a
@@ -18518,7 +18481,7 @@ read_partial_die (const struct die_reader_specs *reader,
       switch (attr.name)
        {
        case DW_AT_name:
-         switch (part_die->tag)
+         switch (tag)
            {
            case DW_TAG_compile_unit:
            case DW_TAG_partial_unit:
@@ -18529,12 +18492,16 @@ read_partial_die (const struct die_reader_specs *reader,
            case DW_TAG_enumerator:
              /* These tags always have simple identifiers already; no need
                 to canonicalize them.  */
-             part_die->name = DW_STRING (&attr);
+             name = DW_STRING (&attr);
              break;
            default:
-             part_die->name
-               = dwarf2_canonicalize_name (DW_STRING (&attr), cu,
-                                           &objfile->per_bfd->storage_obstack);
+             {
+               struct objfile *objfile = dwarf2_per_objfile->objfile;
+
+               name
+                 = dwarf2_canonicalize_name (DW_STRING (&attr), cu,
+                                             &objfile->per_bfd->storage_obstack);
+             }
              break;
            }
          break;
@@ -18544,16 +18511,16 @@ read_partial_die (const struct die_reader_specs *reader,
             assume they will be the same, and we only store the last
             one we see.  */
          if (cu->language == language_ada)
-           part_die->name = DW_STRING (&attr);
-         part_die->linkage_name = DW_STRING (&attr);
+           name = DW_STRING (&attr);
+         linkage_name = DW_STRING (&attr);
          break;
        case DW_AT_low_pc:
          has_low_pc_attr = 1;
-         part_die->lowpc = attr_value_as_address (&attr);
+         lowpc = attr_value_as_address (&attr);
          break;
        case DW_AT_high_pc:
          has_high_pc_attr = 1;
-         part_die->highpc = attr_value_as_address (&attr);
+         highpc = attr_value_as_address (&attr);
          if (cu->header.version >= 4 && attr_form_is_constant (&attr))
                high_pc_relative = 1;
          break;
@@ -18561,7 +18528,7 @@ read_partial_die (const struct die_reader_specs *reader,
           /* Support the .debug_loc offsets.  */
           if (attr_form_is_block (&attr))
             {
-              part_die->d.locdesc = DW_BLOCK (&attr);
+              d.locdesc = DW_BLOCK (&attr);
             }
           else if (attr_form_is_section_offset (&attr))
             {
@@ -18574,20 +18541,20 @@ read_partial_die (const struct die_reader_specs *reader,
             }
          break;
        case DW_AT_external:
-         part_die->is_external = DW_UNSND (&attr);
+         is_external = DW_UNSND (&attr);
          break;
        case DW_AT_declaration:
-         part_die->is_declaration = DW_UNSND (&attr);
+         is_declaration = DW_UNSND (&attr);
          break;
        case DW_AT_type:
-         part_die->has_type = 1;
+         has_type = 1;
          break;
        case DW_AT_abstract_origin:
        case DW_AT_specification:
        case DW_AT_extension:
-         part_die->has_specification = 1;
-         part_die->spec_offset = dwarf2_get_ref_die_offset (&attr);
-         part_die->spec_is_dwz = (attr.form == DW_FORM_GNU_ref_alt
+         has_specification = 1;
+         spec_offset = dwarf2_get_ref_die_offset (&attr);
+         spec_is_dwz = (attr.form == DW_FORM_GNU_ref_alt
                                   || cu->per_cu->is_dwz);
          break;
        case DW_AT_sibling:
@@ -18598,6 +18565,7 @@ read_partial_die (const struct die_reader_specs *reader,
                       _("ignoring absolute DW_AT_sibling"));
          else
            {
+             const gdb_byte *buffer = reader->buffer;
              sect_offset off = dwarf2_get_ref_die_offset (&attr);
              const gdb_byte *sibling_ptr = buffer + to_underlying (off);
 
@@ -18607,14 +18575,14 @@ read_partial_die (const struct die_reader_specs *reader,
              else if (sibling_ptr > reader->buffer_end)
                dwarf2_section_buffer_overflow_complaint (reader->die_section);
              else
-               part_die->sibling = sibling_ptr;
+               sibling = sibling_ptr;
            }
          break;
         case DW_AT_byte_size:
-          part_die->has_byte_size = 1;
+          has_byte_size = 1;
           break;
         case DW_AT_const_value:
-          part_die->has_const_value = 1;
+          has_const_value = 1;
           break;
        case DW_AT_calling_convention:
          /* DWARF doesn't provide a way to identify a program's source-level
@@ -18633,25 +18601,25 @@ read_partial_die (const struct die_reader_specs *reader,
             compatibility.  */
          if (DW_UNSND (&attr) == DW_CC_program
              && cu->language == language_fortran)
-           part_die->main_subprogram = 1;
+           main_subprogram = 1;
          break;
        case DW_AT_inline:
          if (DW_UNSND (&attr) == DW_INL_inlined
              || DW_UNSND (&attr) == DW_INL_declared_inlined)
-           part_die->may_be_inlined = 1;
+           may_be_inlined = 1;
          break;
 
        case DW_AT_import:
-         if (part_die->tag == DW_TAG_imported_unit)
+         if (tag == DW_TAG_imported_unit)
            {
-             part_die->d.sect_off = dwarf2_get_ref_die_offset (&attr);
-             part_die->is_dwz = (attr.form == DW_FORM_GNU_ref_alt
+             d.sect_off = dwarf2_get_ref_die_offset (&attr);
+             is_dwz = (attr.form == DW_FORM_GNU_ref_alt
                                  || cu->per_cu->is_dwz);
            }
          break;
 
        case DW_AT_main_subprogram:
-         part_die->main_subprogram = DW_UNSND (&attr);
+         main_subprogram = DW_UNSND (&attr);
          break;
 
        default:
@@ -18660,7 +18628,7 @@ read_partial_die (const struct die_reader_specs *reader,
     }
 
   if (high_pc_relative)
-    part_die->highpc += part_die->lowpc;
+    highpc += lowpc;
 
   if (has_low_pc_attr && has_high_pc_attr)
     {
@@ -18672,32 +18640,34 @@ read_partial_die (const struct die_reader_specs *reader,
         labels are not in the output, so the relocs get a value of 0.
         If this is a discarded function, mark the pc bounds as invalid,
         so that GDB will ignore it.  */
-      if (part_die->lowpc == 0 && !dwarf2_per_objfile->has_section_at_zero)
+      if (lowpc == 0 && !dwarf2_per_objfile->has_section_at_zero)
        {
+         struct objfile *objfile = dwarf2_per_objfile->objfile;
          struct gdbarch *gdbarch = get_objfile_arch (objfile);
 
          complaint (&symfile_complaints,
                     _("DW_AT_low_pc %s is zero "
                       "for DIE at %s [in module %s]"),
-                    paddress (gdbarch, part_die->lowpc),
-                    sect_offset_str (part_die->sect_off),
+                    paddress (gdbarch, lowpc),
+                    sect_offset_str (sect_off),
                     objfile_name (objfile));
        }
       /* dwarf2_get_pc_bounds has also the strict low < high requirement.  */
-      else if (part_die->lowpc >= part_die->highpc)
+      else if (lowpc >= highpc)
        {
+         struct objfile *objfile = dwarf2_per_objfile->objfile;
          struct gdbarch *gdbarch = get_objfile_arch (objfile);
 
          complaint (&symfile_complaints,
                     _("DW_AT_low_pc %s is not < DW_AT_high_pc %s "
                       "for DIE at %s [in module %s]"),
-                    paddress (gdbarch, part_die->lowpc),
-                    paddress (gdbarch, part_die->highpc),
-                    sect_offset_str (part_die->sect_off),
+                    paddress (gdbarch, lowpc),
+                    paddress (gdbarch, highpc),
+                    sect_offset_str (sect_off),
                     objfile_name (objfile));
        }
       else
-       part_die->has_pc_info = 1;
+       has_pc_info = 1;
     }
 
   return info_ptr;
@@ -18705,15 +18675,14 @@ read_partial_die (const struct die_reader_specs *reader,
 
 /* Find a cached partial DIE at OFFSET in CU.  */
 
-static struct partial_die_info *
-find_partial_die_in_comp_unit (sect_offset sect_off, struct dwarf2_cu *cu)
+struct partial_die_info *
+dwarf2_cu::find_partial_die (sect_offset sect_off)
 {
   struct partial_die_info *lookup_die = NULL;
-  struct partial_die_info part_die;
+  struct partial_die_info part_die (sect_off);
 
-  part_die.sect_off = sect_off;
   lookup_die = ((struct partial_die_info *)
-               htab_find_with_hash (cu->partial_dies, &part_die,
+               htab_find_with_hash (partial_dies, &part_die,
                                     to_underlying (sect_off)));
 
   return lookup_die;
@@ -18736,7 +18705,7 @@ find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu)
   if (offset_in_dwz == cu->per_cu->is_dwz
       && offset_in_cu_p (&cu->header, sect_off))
     {
-      pd = find_partial_die_in_comp_unit (sect_off, cu);
+      pd = cu->find_partial_die (sect_off);
       if (pd != NULL)
        return pd;
       /* We missed recording what we needed.
@@ -18760,7 +18729,7 @@ find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu)
        load_partial_comp_unit (per_cu);
 
       per_cu->cu->last_used = 0;
-      pd = find_partial_die_in_comp_unit (sect_off, per_cu->cu);
+      pd = per_cu->cu->find_partial_die (sect_off);
     }
 
   /* If we didn't find it, and not all dies have been loaded,
@@ -18778,7 +18747,7 @@ find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu)
         set.  */
       load_partial_comp_unit (per_cu);
 
-      pd = find_partial_die_in_comp_unit (sect_off, per_cu->cu);
+      pd = per_cu->cu->find_partial_die (sect_off);
     }
 
   if (pd == NULL)
@@ -18843,45 +18812,40 @@ guess_partial_die_structure_name (struct partial_die_info *struct_pdi,
     }
 }
 
-/* Adjust PART_DIE before generating a symbol for it.  This function
-   may set the is_external flag or change the DIE's name.  */
-
-static void
-fixup_partial_die (struct partial_die_info *part_die,
-                  struct dwarf2_cu *cu)
+void
+partial_die_info::fixup (struct dwarf2_cu *cu)
 {
   /* Once we've fixed up a die, there's no point in doing so again.
      This also avoids a memory leak if we were to call
      guess_partial_die_structure_name multiple times.  */
-  if (part_die->fixup_called)
+  if (fixup_called)
     return;
 
   /* If we found a reference attribute and the DIE has no name, try
      to find a name in the referred to DIE.  */
 
-  if (part_die->name == NULL && part_die->has_specification)
+  if (name == NULL && has_specification)
     {
       struct partial_die_info *spec_die;
 
-      spec_die = find_partial_die (part_die->spec_offset,
-                                  part_die->spec_is_dwz, cu);
+      spec_die = find_partial_die (spec_offset, spec_is_dwz, cu);
 
-      fixup_partial_die (spec_die, cu);
+      spec_die->fixup (cu);
 
       if (spec_die->name)
        {
-         part_die->name = spec_die->name;
+         name = spec_die->name;
 
          /* Copy DW_AT_external attribute if it is set.  */
          if (spec_die->is_external)
-           part_die->is_external = spec_die->is_external;
+           is_external = spec_die->is_external;
        }
     }
 
   /* Set default names for some unnamed DIEs.  */
 
-  if (part_die->name == NULL && part_die->tag == DW_TAG_namespace)
-    part_die->name = CP_ANONYMOUS_NAMESPACE_STR;
+  if (name == NULL && tag == DW_TAG_namespace)
+    name = CP_ANONYMOUS_NAMESPACE_STR;
 
   /* If there is no parent die to provide a namespace, and there are
      children, see if we can determine the namespace from their linkage
@@ -18889,25 +18853,25 @@ fixup_partial_die (struct partial_die_info *part_die,
   if (cu->language == language_cplus
       && !VEC_empty (dwarf2_section_info_def,
                     cu->per_cu->dwarf2_per_objfile->types)
-      && part_die->die_parent == NULL
-      && part_die->has_children
-      && (part_die->tag == DW_TAG_class_type
-         || part_die->tag == DW_TAG_structure_type
-         || part_die->tag == DW_TAG_union_type))
-    guess_partial_die_structure_name (part_die, cu);
+      && die_parent == NULL
+      && has_children
+      && (tag == DW_TAG_class_type
+         || tag == DW_TAG_structure_type
+         || tag == DW_TAG_union_type))
+    guess_partial_die_structure_name (this, cu);
 
   /* GCC might emit a nameless struct or union that has a linkage
      name.  See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47510.  */
-  if (part_die->name == NULL
-      && (part_die->tag == DW_TAG_class_type
-         || part_die->tag == DW_TAG_interface_type
-         || part_die->tag == DW_TAG_structure_type
-         || part_die->tag == DW_TAG_union_type)
-      && part_die->linkage_name != NULL)
+  if (name == NULL
+      && (tag == DW_TAG_class_type
+         || tag == DW_TAG_interface_type
+         || tag == DW_TAG_structure_type
+         || tag == DW_TAG_union_type)
+      && linkage_name != NULL)
     {
       char *demangled;
 
-      demangled = gdb_demangle (part_die->linkage_name, DMGL_TYPES);
+      demangled = gdb_demangle (linkage_name, DMGL_TYPES);
       if (demangled)
        {
          const char *base;
@@ -18921,7 +18885,7 @@ fixup_partial_die (struct partial_die_info *part_die,
            base = demangled;
 
          struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
-         part_die->name
+         name
            = ((const char *)
               obstack_copy0 (&objfile->per_bfd->storage_obstack,
                              base, strlen (base)));
@@ -18929,7 +18893,7 @@ fixup_partial_die (struct partial_die_info *part_die,
        }
     }
 
-  part_die->fixup_called = 1;
+  fixup_called = 1;
 }
 
 /* Read an attribute value described by an attribute form.  */
@@ -25495,1711 +25459,105 @@ show_dwarf_cmd (const char *args, int from_tty)
   cmd_show_list (show_dwarf_cmdlist, from_tty, "");
 }
 
-/* The "save gdb-index" command.  */
-
-/* Write SIZE bytes from the buffer pointed to by DATA to FILE, with
-   error checking.  */
+int dwarf_always_disassemble;
 
 static void
-file_write (FILE *file, const void *data, size_t size)
+show_dwarf_always_disassemble (struct ui_file *file, int from_tty,
+                              struct cmd_list_element *c, const char *value)
 {
-  if (fwrite (data, 1, size, file) != size)
-    error (_("couldn't data write to file"));
+  fprintf_filtered (file,
+                   _("Whether to always disassemble "
+                     "DWARF expressions is %s.\n"),
+                   value);
 }
 
-/* Write the contents of VEC to FILE, with error checking.  */
-
-template<typename Elem, typename Alloc>
 static void
-file_write (FILE *file, const std::vector<Elem, Alloc> &vec)
-{
-  file_write (file, vec.data (), vec.size () * sizeof (vec[0]));
-}
-
-/* In-memory buffer to prepare data to be written later to a file.  */
-class data_buf
-{
-public:
-  /* Copy DATA to the end of the buffer.  */
-  template<typename T>
-  void append_data (const T &data)
-  {
-    std::copy (reinterpret_cast<const gdb_byte *> (&data),
-              reinterpret_cast<const gdb_byte *> (&data + 1),
-              grow (sizeof (data)));
-  }
-
-  /* Copy CSTR (a zero-terminated string) to the end of buffer.  The
-     terminating zero is appended too.  */
-  void append_cstr0 (const char *cstr)
-  {
-    const size_t size = strlen (cstr) + 1;
-    std::copy (cstr, cstr + size, grow (size));
-  }
-
-  /* Store INPUT as ULEB128 to the end of buffer.  */
-  void append_unsigned_leb128 (ULONGEST input)
-  {
-    for (;;)
-      {
-       gdb_byte output = input & 0x7f;
-       input >>= 7;
-       if (input)
-         output |= 0x80;
-       append_data (output);
-       if (input == 0)
-         break;
-      }
-  }
-
-  /* Accept a host-format integer in VAL and append it to the buffer
-     as a target-format integer which is LEN bytes long.  */
-  void append_uint (size_t len, bfd_endian byte_order, ULONGEST val)
-  {
-    ::store_unsigned_integer (grow (len), len, byte_order, val);
-  }
-
-  /* Return the size of the buffer.  */
-  size_t size () const
-  {
-    return m_vec.size ();
-  }
-
-  /* Return true iff the buffer is empty.  */
-  bool empty () const
-  {
-    return m_vec.empty ();
-  }
-
-  /* Write the buffer to FILE.  */
-  void file_write (FILE *file) const
-  {
-    ::file_write (file, m_vec);
-  }
-
-private:
-  /* Grow SIZE bytes at the end of the buffer.  Returns a pointer to
-     the start of the new block.  */
-  gdb_byte *grow (size_t size)
-  {
-    m_vec.resize (m_vec.size () + size);
-    return &*m_vec.end () - size;
-  }
-
-  gdb::byte_vector m_vec;
-};
-
-/* An entry in the symbol table.  */
-struct symtab_index_entry
-{
-  /* The name of the symbol.  */
-  const char *name;
-  /* The offset of the name in the constant pool.  */
-  offset_type index_offset;
-  /* A sorted vector of the indices of all the CUs that hold an object
-     of this name.  */
-  std::vector<offset_type> cu_indices;
-};
-
-/* The symbol table.  This is a power-of-2-sized hash table.  */
-struct mapped_symtab
-{
-  mapped_symtab ()
-  {
-    data.resize (1024);
-  }
-
-  offset_type n_elements = 0;
-  std::vector<symtab_index_entry> data;
-};
-
-/* Find a slot in SYMTAB for the symbol NAME.  Returns a reference to
-   the slot.
-   
-   Function is used only during write_hash_table so no index format backward
-   compatibility is needed.  */
-
-static symtab_index_entry &
-find_slot (struct mapped_symtab *symtab, const char *name)
+show_check_physname (struct ui_file *file, int from_tty,
+                    struct cmd_list_element *c, const char *value)
 {
-  offset_type index, step, hash = mapped_index_string_hash (INT_MAX, name);
-
-  index = hash & (symtab->data.size () - 1);
-  step = ((hash * 17) & (symtab->data.size () - 1)) | 1;
-
-  for (;;)
-    {
-      if (symtab->data[index].name == NULL
-         || strcmp (name, symtab->data[index].name) == 0)
-       return symtab->data[index];
-      index = (index + step) & (symtab->data.size () - 1);
-    }
+  fprintf_filtered (file,
+                   _("Whether to check \"physname\" is %s.\n"),
+                   value);
 }
 
-/* Expand SYMTAB's hash table.  */
-
-static void
-hash_expand (struct mapped_symtab *symtab)
+void
+_initialize_dwarf2_read (void)
 {
-  auto old_entries = std::move (symtab->data);
 
-  symtab->data.clear ();
-  symtab->data.resize (old_entries.size () * 2);
+  dwarf2_objfile_data_key = register_objfile_data ();
 
-  for (auto &it : old_entries)
-    if (it.name != NULL)
-      {
-       auto &ref = find_slot (symtab, it.name);
-       ref = std::move (it);
-      }
-}
+  add_prefix_cmd ("dwarf", class_maintenance, set_dwarf_cmd, _("\
+Set DWARF specific variables.\n\
+Configure DWARF variables such as the cache size"),
+                  &set_dwarf_cmdlist, "maintenance set dwarf ",
+                  0/*allow-unknown*/, &maintenance_set_cmdlist);
 
-/* Add an entry to SYMTAB.  NAME is the name of the symbol.
-   CU_INDEX is the index of the CU in which the symbol appears.
-   IS_STATIC is one if the symbol is static, otherwise zero (global).  */
+  add_prefix_cmd ("dwarf", class_maintenance, show_dwarf_cmd, _("\
+Show DWARF specific variables\n\
+Show DWARF variables such as the cache size"),
+                  &show_dwarf_cmdlist, "maintenance show dwarf ",
+                  0/*allow-unknown*/, &maintenance_show_cmdlist);
 
-static void
-add_index_entry (struct mapped_symtab *symtab, const char *name,
-                int is_static, gdb_index_symbol_kind kind,
-                offset_type cu_index)
-{
-  offset_type cu_index_and_attrs;
+  add_setshow_zinteger_cmd ("max-cache-age", class_obscure,
+                           &dwarf_max_cache_age, _("\
+Set the upper bound on the age of cached DWARF compilation units."), _("\
+Show the upper bound on the age of cached DWARF compilation units."), _("\
+A higher limit means that cached compilation units will be stored\n\
+in memory longer, and more total memory will be used.  Zero disables\n\
+caching, which can slow down startup."),
+                           NULL,
+                           show_dwarf_max_cache_age,
+                           &set_dwarf_cmdlist,
+                           &show_dwarf_cmdlist);
 
-  ++symtab->n_elements;
-  if (4 * symtab->n_elements / 3 >= symtab->data.size ())
-    hash_expand (symtab);
+  add_setshow_boolean_cmd ("always-disassemble", class_obscure,
+                          &dwarf_always_disassemble, _("\
+Set whether `info address' always disassembles DWARF expressions."), _("\
+Show whether `info address' always disassembles DWARF expressions."), _("\
+When enabled, DWARF expressions are always printed in an assembly-like\n\
+syntax.  When disabled, expressions will be printed in a more\n\
+conversational style, when possible."),
+                          NULL,
+                          show_dwarf_always_disassemble,
+                          &set_dwarf_cmdlist,
+                          &show_dwarf_cmdlist);
 
-  symtab_index_entry &slot = find_slot (symtab, name);
-  if (slot.name == NULL)
-    {
-      slot.name = name;
-      /* index_offset is set later.  */
-    }
+  add_setshow_zuinteger_cmd ("dwarf-read", no_class, &dwarf_read_debug, _("\
+Set debugging of the DWARF reader."), _("\
+Show debugging of the DWARF reader."), _("\
+When enabled (non-zero), debugging messages are printed during DWARF\n\
+reading and symtab expansion.  A value of 1 (one) provides basic\n\
+information.  A value greater than 1 provides more verbose information."),
+                           NULL,
+                           NULL,
+                           &setdebuglist, &showdebuglist);
 
-  cu_index_and_attrs = 0;
-  DW2_GDB_INDEX_CU_SET_VALUE (cu_index_and_attrs, cu_index);
-  DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE (cu_index_and_attrs, is_static);
-  DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE (cu_index_and_attrs, kind);
+  add_setshow_zuinteger_cmd ("dwarf-die", no_class, &dwarf_die_debug, _("\
+Set debugging of the DWARF DIE reader."), _("\
+Show debugging of the DWARF DIE reader."), _("\
+When enabled (non-zero), DIEs are dumped after they are read in.\n\
+The value is the maximum depth to print."),
+                            NULL,
+                            NULL,
+                            &setdebuglist, &showdebuglist);
 
-  /* We don't want to record an index value twice as we want to avoid the
-     duplication.
-     We process all global symbols and then all static symbols
-     (which would allow us to avoid the duplication by only having to check
-     the last entry pushed), but a symbol could have multiple kinds in one CU.
-     To keep things simple we don't worry about the duplication here and
-     sort and uniqufy the list after we've processed all symbols.  */
-  slot.cu_indices.push_back (cu_index_and_attrs);
-}
+  add_setshow_zuinteger_cmd ("dwarf-line", no_class, &dwarf_line_debug, _("\
+Set debugging of the dwarf line reader."), _("\
+Show debugging of the dwarf line reader."), _("\
+When enabled (non-zero), line number entries are dumped as they are read in.\n\
+A value of 1 (one) provides basic information.\n\
+A value greater than 1 provides more verbose information."),
+                            NULL,
+                            NULL,
+                            &setdebuglist, &showdebuglist);
 
-/* Sort and remove duplicates of all symbols' cu_indices lists.  */
-
-static void
-uniquify_cu_indices (struct mapped_symtab *symtab)
-{
-  for (auto &entry : symtab->data)
-    {
-      if (entry.name != NULL && !entry.cu_indices.empty ())
-       {
-         auto &cu_indices = entry.cu_indices;
-         std::sort (cu_indices.begin (), cu_indices.end ());
-         auto from = std::unique (cu_indices.begin (), cu_indices.end ());
-         cu_indices.erase (from, cu_indices.end ());
-       }
-    }
-}
-
-/* A form of 'const char *' suitable for container keys.  Only the
-   pointer is stored.  The strings themselves are compared, not the
-   pointers.  */
-class c_str_view
-{
-public:
-  c_str_view (const char *cstr)
-    : m_cstr (cstr)
-  {}
-
-  bool operator== (const c_str_view &other) const
-  {
-    return strcmp (m_cstr, other.m_cstr) == 0;
-  }
-
-  /* Return the underlying C string.  Note, the returned string is
-     only a reference with lifetime of this object.  */
-  const char *c_str () const
-  {
-    return m_cstr;
-  }
-
-private:
-  friend class c_str_view_hasher;
-  const char *const m_cstr;
-};
-
-/* A std::unordered_map::hasher for c_str_view that uses the right
-   hash function for strings in a mapped index.  */
-class c_str_view_hasher
-{
-public:
-  size_t operator () (const c_str_view &x) const
-  {
-    return mapped_index_string_hash (INT_MAX, x.m_cstr);
-  }
-};
-
-/* A std::unordered_map::hasher for std::vector<>.  */
-template<typename T>
-class vector_hasher
-{
-public:
-  size_t operator () (const std::vector<T> &key) const
-  {
-    return iterative_hash (key.data (),
-                          sizeof (key.front ()) * key.size (), 0);
-  }
-};
-
-/* Write the mapped hash table SYMTAB to the data buffer OUTPUT, with
-   constant pool entries going into the data buffer CPOOL.  */
-
-static void
-write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool)
-{
-  {
-    /* Elements are sorted vectors of the indices of all the CUs that
-       hold an object of this name.  */
-    std::unordered_map<std::vector<offset_type>, offset_type,
-                      vector_hasher<offset_type>>
-      symbol_hash_table;
-
-    /* We add all the index vectors to the constant pool first, to
-       ensure alignment is ok.  */
-    for (symtab_index_entry &entry : symtab->data)
-      {
-       if (entry.name == NULL)
-         continue;
-       gdb_assert (entry.index_offset == 0);
-
-       /* Finding before inserting is faster than always trying to
-          insert, because inserting always allocates a node, does the
-          lookup, and then destroys the new node if another node
-          already had the same key.  C++17 try_emplace will avoid
-          this.  */
-       const auto found
-         = symbol_hash_table.find (entry.cu_indices);
-       if (found != symbol_hash_table.end ())
-         {
-           entry.index_offset = found->second;
-           continue;
-         }
-
-       symbol_hash_table.emplace (entry.cu_indices, cpool.size ());
-       entry.index_offset = cpool.size ();
-       cpool.append_data (MAYBE_SWAP (entry.cu_indices.size ()));
-       for (const auto index : entry.cu_indices)
-         cpool.append_data (MAYBE_SWAP (index));
-      }
-  }
-
-  /* Now write out the hash table.  */
-  std::unordered_map<c_str_view, offset_type, c_str_view_hasher> str_table;
-  for (const auto &entry : symtab->data)
-    {
-      offset_type str_off, vec_off;
-
-      if (entry.name != NULL)
-       {
-         const auto insertpair = str_table.emplace (entry.name, cpool.size ());
-         if (insertpair.second)
-           cpool.append_cstr0 (entry.name);
-         str_off = insertpair.first->second;
-         vec_off = entry.index_offset;
-       }
-      else
-       {
-         /* While 0 is a valid constant pool index, it is not valid
-            to have 0 for both offsets.  */
-         str_off = 0;
-         vec_off = 0;
-       }
-
-      output.append_data (MAYBE_SWAP (str_off));
-      output.append_data (MAYBE_SWAP (vec_off));
-    }
-}
-
-typedef std::unordered_map<partial_symtab *, unsigned int> psym_index_map;
-
-/* Helper struct for building the address table.  */
-struct addrmap_index_data
-{
-  addrmap_index_data (data_buf &addr_vec_, psym_index_map &cu_index_htab_)
-    : addr_vec (addr_vec_), cu_index_htab (cu_index_htab_)
-  {}
-
-  struct objfile *objfile;
-  data_buf &addr_vec;
-  psym_index_map &cu_index_htab;
-
-  /* Non-zero if the previous_* fields are valid.
-     We can't write an entry until we see the next entry (since it is only then
-     that we know the end of the entry).  */
-  int previous_valid;
-  /* Index of the CU in the table of all CUs in the index file.  */
-  unsigned int previous_cu_index;
-  /* Start address of the CU.  */
-  CORE_ADDR previous_cu_start;
-};
-
-/* Write an address entry to ADDR_VEC.  */
-
-static void
-add_address_entry (struct objfile *objfile, data_buf &addr_vec,
-                  CORE_ADDR start, CORE_ADDR end, unsigned int cu_index)
-{
-  CORE_ADDR baseaddr;
-
-  baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
-
-  addr_vec.append_uint (8, BFD_ENDIAN_LITTLE, start - baseaddr);
-  addr_vec.append_uint (8, BFD_ENDIAN_LITTLE, end - baseaddr);
-  addr_vec.append_data (MAYBE_SWAP (cu_index));
-}
-
-/* Worker function for traversing an addrmap to build the address table.  */
-
-static int
-add_address_entry_worker (void *datap, CORE_ADDR start_addr, void *obj)
-{
-  struct addrmap_index_data *data = (struct addrmap_index_data *) datap;
-  struct partial_symtab *pst = (struct partial_symtab *) obj;
-
-  if (data->previous_valid)
-    add_address_entry (data->objfile, data->addr_vec,
-                      data->previous_cu_start, start_addr,
-                      data->previous_cu_index);
-
-  data->previous_cu_start = start_addr;
-  if (pst != NULL)
-    {
-      const auto it = data->cu_index_htab.find (pst);
-      gdb_assert (it != data->cu_index_htab.cend ());
-      data->previous_cu_index = it->second;
-      data->previous_valid = 1;
-    }
-  else
-    data->previous_valid = 0;
-
-  return 0;
-}
-
-/* Write OBJFILE's address map to ADDR_VEC.
-   CU_INDEX_HTAB is used to map addrmap entries to their CU indices
-   in the index file.  */
-
-static void
-write_address_map (struct objfile *objfile, data_buf &addr_vec,
-                  psym_index_map &cu_index_htab)
-{
-  struct addrmap_index_data addrmap_index_data (addr_vec, cu_index_htab);
-
-  /* When writing the address table, we have to cope with the fact that
-     the addrmap iterator only provides the start of a region; we have to
-     wait until the next invocation to get the start of the next region.  */
-
-  addrmap_index_data.objfile = objfile;
-  addrmap_index_data.previous_valid = 0;
-
-  addrmap_foreach (objfile->psymtabs_addrmap, add_address_entry_worker,
-                  &addrmap_index_data);
-
-  /* It's highly unlikely the last entry (end address = 0xff...ff)
-     is valid, but we should still handle it.
-     The end address is recorded as the start of the next region, but that
-     doesn't work here.  To cope we pass 0xff...ff, this is a rare situation
-     anyway.  */
-  if (addrmap_index_data.previous_valid)
-    add_address_entry (objfile, addr_vec,
-                      addrmap_index_data.previous_cu_start, (CORE_ADDR) -1,
-                      addrmap_index_data.previous_cu_index);
-}
-
-/* Return the symbol kind of PSYM.  */
-
-static gdb_index_symbol_kind
-symbol_kind (struct partial_symbol *psym)
-{
-  domain_enum domain = PSYMBOL_DOMAIN (psym);
-  enum address_class aclass = PSYMBOL_CLASS (psym);
-
-  switch (domain)
-    {
-    case VAR_DOMAIN:
-      switch (aclass)
-       {
-       case LOC_BLOCK:
-         return GDB_INDEX_SYMBOL_KIND_FUNCTION;
-       case LOC_TYPEDEF:
-         return GDB_INDEX_SYMBOL_KIND_TYPE;
-       case LOC_COMPUTED:
-       case LOC_CONST_BYTES:
-       case LOC_OPTIMIZED_OUT:
-       case LOC_STATIC:
-         return GDB_INDEX_SYMBOL_KIND_VARIABLE;
-       case LOC_CONST:
-         /* Note: It's currently impossible to recognize psyms as enum values
-            short of reading the type info.  For now punt.  */
-         return GDB_INDEX_SYMBOL_KIND_VARIABLE;
-       default:
-         /* There are other LOC_FOO values that one might want to classify
-            as variables, but dwarf2read.c doesn't currently use them.  */
-         return GDB_INDEX_SYMBOL_KIND_OTHER;
-       }
-    case STRUCT_DOMAIN:
-      return GDB_INDEX_SYMBOL_KIND_TYPE;
-    default:
-      return GDB_INDEX_SYMBOL_KIND_OTHER;
-    }
-}
-
-/* Add a list of partial symbols to SYMTAB.  */
-
-static void
-write_psymbols (struct mapped_symtab *symtab,
-               std::unordered_set<partial_symbol *> &psyms_seen,
-               struct partial_symbol **psymp,
-               int count,
-               offset_type cu_index,
-               int is_static)
-{
-  for (; count-- > 0; ++psymp)
-    {
-      struct partial_symbol *psym = *psymp;
-
-      if (SYMBOL_LANGUAGE (psym) == language_ada)
-       error (_("Ada is not currently supported by the index"));
-
-      /* Only add a given psymbol once.  */
-      if (psyms_seen.insert (psym).second)
-       {
-         gdb_index_symbol_kind kind = symbol_kind (psym);
-
-         add_index_entry (symtab, SYMBOL_SEARCH_NAME (psym),
-                          is_static, kind, cu_index);
-       }
-    }
-}
-
-/* A helper struct used when iterating over debug_types.  */
-struct signatured_type_index_data
-{
-  signatured_type_index_data (data_buf &types_list_,
-                              std::unordered_set<partial_symbol *> &psyms_seen_)
-    : types_list (types_list_), psyms_seen (psyms_seen_)
-  {}
-
-  struct objfile *objfile;
-  struct mapped_symtab *symtab;
-  data_buf &types_list;
-  std::unordered_set<partial_symbol *> &psyms_seen;
-  int cu_index;
-};
-
-/* A helper function that writes a single signatured_type to an
-   obstack.  */
-
-static int
-write_one_signatured_type (void **slot, void *d)
-{
-  struct signatured_type_index_data *info
-    = (struct signatured_type_index_data *) d;
-  struct signatured_type *entry = (struct signatured_type *) *slot;
-  struct partial_symtab *psymtab = entry->per_cu.v.psymtab;
-
-  write_psymbols (info->symtab,
-                 info->psyms_seen,
-                 &info->objfile->global_psymbols[psymtab->globals_offset],
-                 psymtab->n_global_syms, info->cu_index,
-                 0);
-  write_psymbols (info->symtab,
-                 info->psyms_seen,
-                 &info->objfile->static_psymbols[psymtab->statics_offset],
-                 psymtab->n_static_syms, info->cu_index,
-                 1);
-
-  info->types_list.append_uint (8, BFD_ENDIAN_LITTLE,
-                               to_underlying (entry->per_cu.sect_off));
-  info->types_list.append_uint (8, BFD_ENDIAN_LITTLE,
-                               to_underlying (entry->type_offset_in_tu));
-  info->types_list.append_uint (8, BFD_ENDIAN_LITTLE, entry->signature);
-
-  ++info->cu_index;
-
-  return 1;
-}
-
-/* Recurse into all "included" dependencies and count their symbols as
-   if they appeared in this psymtab.  */
-
-static void
-recursively_count_psymbols (struct partial_symtab *psymtab,
-                           size_t &psyms_seen)
-{
-  for (int i = 0; i < psymtab->number_of_dependencies; ++i)
-    if (psymtab->dependencies[i]->user != NULL)
-      recursively_count_psymbols (psymtab->dependencies[i],
-                                 psyms_seen);
-
-  psyms_seen += psymtab->n_global_syms;
-  psyms_seen += psymtab->n_static_syms;
-}
-
-/* Recurse into all "included" dependencies and write their symbols as
-   if they appeared in this psymtab.  */
-
-static void
-recursively_write_psymbols (struct objfile *objfile,
-                           struct partial_symtab *psymtab,
-                           struct mapped_symtab *symtab,
-                           std::unordered_set<partial_symbol *> &psyms_seen,
-                           offset_type cu_index)
-{
-  int i;
-
-  for (i = 0; i < psymtab->number_of_dependencies; ++i)
-    if (psymtab->dependencies[i]->user != NULL)
-      recursively_write_psymbols (objfile, psymtab->dependencies[i],
-                                 symtab, psyms_seen, cu_index);
-
-  write_psymbols (symtab,
-                 psyms_seen,
-                 &objfile->global_psymbols[psymtab->globals_offset],
-                 psymtab->n_global_syms, cu_index,
-                 0);
-  write_psymbols (symtab,
-                 psyms_seen,
-                 &objfile->static_psymbols[psymtab->statics_offset],
-                 psymtab->n_static_syms, cu_index,
-                 1);
-}
-
-/* DWARF-5 .debug_names builder.  */
-class debug_names
-{
-public:
-  debug_names (struct dwarf2_per_objfile *dwarf2_per_objfile, bool is_dwarf64,
-              bfd_endian dwarf5_byte_order)
-    : m_dwarf5_byte_order (dwarf5_byte_order),
-      m_dwarf32 (dwarf5_byte_order),
-      m_dwarf64 (dwarf5_byte_order),
-      m_dwarf (is_dwarf64
-              ? static_cast<dwarf &> (m_dwarf64)
-              : static_cast<dwarf &> (m_dwarf32)),
-      m_name_table_string_offs (m_dwarf.name_table_string_offs),
-      m_name_table_entry_offs (m_dwarf.name_table_entry_offs),
-      m_debugstrlookup (dwarf2_per_objfile)
-  {}
-
-  int dwarf5_offset_size () const
-  {
-    const bool dwarf5_is_dwarf64 = &m_dwarf == &m_dwarf64;
-    return dwarf5_is_dwarf64 ? 8 : 4;
-  }
-
-  /* Is this symbol from DW_TAG_compile_unit or DW_TAG_type_unit?  */
-  enum class unit_kind { cu, tu };
-
-  /* Insert one symbol.  */
-  void insert (const partial_symbol *psym, int cu_index, bool is_static,
-              unit_kind kind)
-  {
-    const int dwarf_tag = psymbol_tag (psym);
-    if (dwarf_tag == 0)
-      return;
-    const char *const name = SYMBOL_SEARCH_NAME (psym);
-    const auto insertpair
-      = m_name_to_value_set.emplace (c_str_view (name),
-                                    std::set<symbol_value> ());
-    std::set<symbol_value> &value_set = insertpair.first->second;
-    value_set.emplace (symbol_value (dwarf_tag, cu_index, is_static, kind));
-  }
-
-  /* Build all the tables.  All symbols must be already inserted.
-     This function does not call file_write, caller has to do it
-     afterwards.  */
-  void build ()
-  {
-    /* Verify the build method has not be called twice.  */
-    gdb_assert (m_abbrev_table.empty ());
-    const size_t name_count = m_name_to_value_set.size ();
-    m_bucket_table.resize
-      (std::pow (2, std::ceil (std::log2 (name_count * 4 / 3))));
-    m_hash_table.reserve (name_count);
-    m_name_table_string_offs.reserve (name_count);
-    m_name_table_entry_offs.reserve (name_count);
-
-    /* Map each hash of symbol to its name and value.  */
-    struct hash_it_pair
-    {
-      uint32_t hash;
-      decltype (m_name_to_value_set)::const_iterator it;
-    };
-    std::vector<std::forward_list<hash_it_pair>> bucket_hash;
-    bucket_hash.resize (m_bucket_table.size ());
-    for (decltype (m_name_to_value_set)::const_iterator it
-          = m_name_to_value_set.cbegin ();
-        it != m_name_to_value_set.cend ();
-        ++it)
-      {
-       const char *const name = it->first.c_str ();
-       const uint32_t hash = dwarf5_djb_hash (name);
-       hash_it_pair hashitpair;
-       hashitpair.hash = hash;
-       hashitpair.it = it;
-       auto &slot = bucket_hash[hash % bucket_hash.size()];
-       slot.push_front (std::move (hashitpair));
-      }
-    for (size_t bucket_ix = 0; bucket_ix < bucket_hash.size (); ++bucket_ix)
-      {
-       const std::forward_list<hash_it_pair> &hashitlist
-         = bucket_hash[bucket_ix];
-       if (hashitlist.empty ())
-         continue;
-       uint32_t &bucket_slot = m_bucket_table[bucket_ix];
-       /* The hashes array is indexed starting at 1.  */
-       store_unsigned_integer (reinterpret_cast<gdb_byte *> (&bucket_slot),
-                               sizeof (bucket_slot), m_dwarf5_byte_order,
-                               m_hash_table.size () + 1);
-       for (const hash_it_pair &hashitpair : hashitlist)
-         {
-           m_hash_table.push_back (0);
-           store_unsigned_integer (reinterpret_cast<gdb_byte *>
-                                                       (&m_hash_table.back ()),
-                                   sizeof (m_hash_table.back ()),
-                                   m_dwarf5_byte_order, hashitpair.hash);
-           const c_str_view &name = hashitpair.it->first;
-           const std::set<symbol_value> &value_set = hashitpair.it->second;
-           m_name_table_string_offs.push_back_reorder
-             (m_debugstrlookup.lookup (name.c_str ()));
-           m_name_table_entry_offs.push_back_reorder (m_entry_pool.size ());
-           gdb_assert (!value_set.empty ());
-           for (const symbol_value &value : value_set)
-             {
-               int &idx = m_indexkey_to_idx[index_key (value.dwarf_tag,
-                                                       value.is_static,
-                                                       value.kind)];
-               if (idx == 0)
-                 {
-                   idx = m_idx_next++;
-                   m_abbrev_table.append_unsigned_leb128 (idx);
-                   m_abbrev_table.append_unsigned_leb128 (value.dwarf_tag);
-                   m_abbrev_table.append_unsigned_leb128
-                             (value.kind == unit_kind::cu ? DW_IDX_compile_unit
-                                                          : DW_IDX_type_unit);
-                   m_abbrev_table.append_unsigned_leb128 (DW_FORM_udata);
-                   m_abbrev_table.append_unsigned_leb128 (value.is_static
-                                                          ? DW_IDX_GNU_internal
-                                                          : DW_IDX_GNU_external);
-                   m_abbrev_table.append_unsigned_leb128 (DW_FORM_flag_present);
-
-                   /* Terminate attributes list.  */
-                   m_abbrev_table.append_unsigned_leb128 (0);
-                   m_abbrev_table.append_unsigned_leb128 (0);
-                 }
-
-               m_entry_pool.append_unsigned_leb128 (idx);
-               m_entry_pool.append_unsigned_leb128 (value.cu_index);
-             }
-
-           /* Terminate the list of CUs.  */
-           m_entry_pool.append_unsigned_leb128 (0);
-         }
-      }
-    gdb_assert (m_hash_table.size () == name_count);
-
-    /* Terminate tags list.  */
-    m_abbrev_table.append_unsigned_leb128 (0);
-  }
-
-  /* Return .debug_names bucket count.  This must be called only after
-     calling the build method.  */
-  uint32_t bucket_count () const
-  {
-    /* Verify the build method has been already called.  */
-    gdb_assert (!m_abbrev_table.empty ());
-    const uint32_t retval = m_bucket_table.size ();
-
-    /* Check for overflow.  */
-    gdb_assert (retval == m_bucket_table.size ());
-    return retval;
-  }
-
-  /* Return .debug_names names count.  This must be called only after
-     calling the build method.  */
-  uint32_t name_count () const
-  {
-    /* Verify the build method has been already called.  */
-    gdb_assert (!m_abbrev_table.empty ());
-    const uint32_t retval = m_hash_table.size ();
-
-    /* Check for overflow.  */
-    gdb_assert (retval == m_hash_table.size ());
-    return retval;
-  }
-
-  /* Return number of bytes of .debug_names abbreviation table.  This
-     must be called only after calling the build method.  */
-  uint32_t abbrev_table_bytes () const
-  {
-    gdb_assert (!m_abbrev_table.empty ());
-    return m_abbrev_table.size ();
-  }
-
-  /* Recurse into all "included" dependencies and store their symbols
-     as if they appeared in this psymtab.  */
-  void recursively_write_psymbols
-    (struct objfile *objfile,
-     struct partial_symtab *psymtab,
-     std::unordered_set<partial_symbol *> &psyms_seen,
-     int cu_index)
-  {
-    for (int i = 0; i < psymtab->number_of_dependencies; ++i)
-      if (psymtab->dependencies[i]->user != NULL)
-       recursively_write_psymbols (objfile, psymtab->dependencies[i],
-                                   psyms_seen, cu_index);
-
-    write_psymbols (psyms_seen,
-                   &objfile->global_psymbols[psymtab->globals_offset],
-                   psymtab->n_global_syms, cu_index, false, unit_kind::cu);
-    write_psymbols (psyms_seen,
-                   &objfile->static_psymbols[psymtab->statics_offset],
-                   psymtab->n_static_syms, cu_index, true, unit_kind::cu);
-  }
-
-  /* Return number of bytes the .debug_names section will have.  This
-     must be called only after calling the build method.  */
-  size_t bytes () const
-  {
-    /* Verify the build method has been already called.  */
-    gdb_assert (!m_abbrev_table.empty ());
-    size_t expected_bytes = 0;
-    expected_bytes += m_bucket_table.size () * sizeof (m_bucket_table[0]);
-    expected_bytes += m_hash_table.size () * sizeof (m_hash_table[0]);
-    expected_bytes += m_name_table_string_offs.bytes ();
-    expected_bytes += m_name_table_entry_offs.bytes ();
-    expected_bytes += m_abbrev_table.size ();
-    expected_bytes += m_entry_pool.size ();
-    return expected_bytes;
-  }
-
-  /* Write .debug_names to FILE_NAMES and .debug_str addition to
-     FILE_STR.  This must be called only after calling the build
-     method.  */
-  void file_write (FILE *file_names, FILE *file_str) const
-  {
-    /* Verify the build method has been already called.  */
-    gdb_assert (!m_abbrev_table.empty ());
-    ::file_write (file_names, m_bucket_table);
-    ::file_write (file_names, m_hash_table);
-    m_name_table_string_offs.file_write (file_names);
-    m_name_table_entry_offs.file_write (file_names);
-    m_abbrev_table.file_write (file_names);
-    m_entry_pool.file_write (file_names);
-    m_debugstrlookup.file_write (file_str);
-  }
-
-  /* A helper user data for write_one_signatured_type.  */
-  class write_one_signatured_type_data
-  {
-  public:
-    write_one_signatured_type_data (debug_names &nametable_,
-                                    signatured_type_index_data &&info_)
-    : nametable (nametable_), info (std::move (info_))
-    {}
-    debug_names &nametable;
-    struct signatured_type_index_data info;
-  };
-
-  /* A helper function to pass write_one_signatured_type to
-     htab_traverse_noresize.  */
-  static int
-  write_one_signatured_type (void **slot, void *d)
-  {
-    write_one_signatured_type_data *data = (write_one_signatured_type_data *) d;
-    struct signatured_type_index_data *info = &data->info;
-    struct signatured_type *entry = (struct signatured_type *) *slot;
-
-    data->nametable.write_one_signatured_type (entry, info);
-
-    return 1;
-  }
-
-private:
-
-  /* Storage for symbol names mapping them to their .debug_str section
-     offsets.  */
-  class debug_str_lookup
-  {
-  public:
-
-    /* Object costructor to be called for current DWARF2_PER_OBJFILE.
-       All .debug_str section strings are automatically stored.  */
-    debug_str_lookup (struct dwarf2_per_objfile *dwarf2_per_objfile)
-      : m_abfd (dwarf2_per_objfile->objfile->obfd),
-       m_dwarf2_per_objfile (dwarf2_per_objfile)
-    {
-      dwarf2_read_section (dwarf2_per_objfile->objfile,
-                          &dwarf2_per_objfile->str);
-      if (dwarf2_per_objfile->str.buffer == NULL)
-       return;
-      for (const gdb_byte *data = dwarf2_per_objfile->str.buffer;
-          data < (dwarf2_per_objfile->str.buffer
-                  + dwarf2_per_objfile->str.size);)
-       {
-         const char *const s = reinterpret_cast<const char *> (data);
-         const auto insertpair
-           = m_str_table.emplace (c_str_view (s),
-                                  data - dwarf2_per_objfile->str.buffer);
-         if (!insertpair.second)
-           complaint (&symfile_complaints,
-                      _("Duplicate string \"%s\" in "
-                        ".debug_str section [in module %s]"),
-                      s, bfd_get_filename (m_abfd));
-         data += strlen (s) + 1;
-       }
-    }
-
-    /* Return offset of symbol name S in the .debug_str section.  Add
-       such symbol to the section's end if it does not exist there
-       yet.  */
-    size_t lookup (const char *s)
-    {
-      const auto it = m_str_table.find (c_str_view (s));
-      if (it != m_str_table.end ())
-       return it->second;
-      const size_t offset = (m_dwarf2_per_objfile->str.size
-                            + m_str_add_buf.size ());
-      m_str_table.emplace (c_str_view (s), offset);
-      m_str_add_buf.append_cstr0 (s);
-      return offset;
-    }
-
-    /* Append the end of the .debug_str section to FILE.  */
-    void file_write (FILE *file) const
-    {
-      m_str_add_buf.file_write (file);
-    }
-
-  private:
-    std::unordered_map<c_str_view, size_t, c_str_view_hasher> m_str_table;
-    bfd *const m_abfd;
-    struct dwarf2_per_objfile *m_dwarf2_per_objfile;
-
-    /* Data to add at the end of .debug_str for new needed symbol names.  */
-    data_buf m_str_add_buf;
-  };
-
-  /* Container to map used DWARF tags to their .debug_names abbreviation
-     tags.  */
-  class index_key
-  {
-  public:
-    index_key (int dwarf_tag_, bool is_static_, unit_kind kind_)
-      : dwarf_tag (dwarf_tag_), is_static (is_static_), kind (kind_)
-    {
-    }
-
-    bool
-    operator== (const index_key &other) const
-    {
-      return (dwarf_tag == other.dwarf_tag && is_static == other.is_static
-             && kind == other.kind);
-    }
-
-    const int dwarf_tag;
-    const bool is_static;
-    const unit_kind kind;
-  };
-
-  /* Provide std::unordered_map::hasher for index_key.  */
-  class index_key_hasher
-  {
-  public:
-    size_t
-    operator () (const index_key &key) const
-    {
-      return (std::hash<int>() (key.dwarf_tag) << 1) | key.is_static;
-    }
-  };
-
-  /* Parameters of one symbol entry.  */
-  class symbol_value
-  {
-  public:
-    const int dwarf_tag, cu_index;
-    const bool is_static;
-    const unit_kind kind;
-
-    symbol_value (int dwarf_tag_, int cu_index_, bool is_static_,
-                 unit_kind kind_)
-      : dwarf_tag (dwarf_tag_), cu_index (cu_index_), is_static (is_static_),
-        kind (kind_)
-    {}
-
-    bool
-    operator< (const symbol_value &other) const
-    {
-#define X(n) \
-  do \
-    { \
-      if (n < other.n) \
-       return true; \
-      if (n > other.n) \
-       return false; \
-    } \
-  while (0)
-      X (dwarf_tag);
-      X (is_static);
-      X (kind);
-      X (cu_index);
-#undef X
-      return false;
-    }
-  };
-
-  /* Abstract base class to unify DWARF-32 and DWARF-64 name table
-     output.  */
-  class offset_vec
-  {
-  protected:
-    const bfd_endian dwarf5_byte_order;
-  public:
-    explicit offset_vec (bfd_endian dwarf5_byte_order_)
-      : dwarf5_byte_order (dwarf5_byte_order_)
-    {}
-
-    /* Call std::vector::reserve for NELEM elements.  */
-    virtual void reserve (size_t nelem) = 0;
-
-    /* Call std::vector::push_back with store_unsigned_integer byte
-       reordering for ELEM.  */
-    virtual void push_back_reorder (size_t elem) = 0;
-
-    /* Return expected output size in bytes.  */
-    virtual size_t bytes () const = 0;
-
-    /* Write name table to FILE.  */
-    virtual void file_write (FILE *file) const = 0;
-  };
-
-  /* Template to unify DWARF-32 and DWARF-64 output.  */
-  template<typename OffsetSize>
-  class offset_vec_tmpl : public offset_vec
-  {
-  public:
-    explicit offset_vec_tmpl (bfd_endian dwarf5_byte_order_)
-      : offset_vec (dwarf5_byte_order_)
-    {}
-
-    /* Implement offset_vec::reserve.  */
-    void reserve (size_t nelem) override
-    {
-      m_vec.reserve (nelem);
-    }
-
-    /* Implement offset_vec::push_back_reorder.  */
-    void push_back_reorder (size_t elem) override
-    {
-      m_vec.push_back (elem);
-      /* Check for overflow.  */
-      gdb_assert (m_vec.back () == elem);
-      store_unsigned_integer (reinterpret_cast<gdb_byte *> (&m_vec.back ()),
-                             sizeof (m_vec.back ()), dwarf5_byte_order, elem);
-    }
-
-    /* Implement offset_vec::bytes.  */
-    size_t bytes () const override
-    {
-      return m_vec.size () * sizeof (m_vec[0]);
-    }
-
-    /* Implement offset_vec::file_write.  */
-    void file_write (FILE *file) const override
-    {
-      ::file_write (file, m_vec);
-    }
-
-  private:
-    std::vector<OffsetSize> m_vec;
-  };
-
-  /* Base class to unify DWARF-32 and DWARF-64 .debug_names output
-     respecting name table width.  */
-  class dwarf
-  {
-  public:
-    offset_vec &name_table_string_offs, &name_table_entry_offs;
-
-    dwarf (offset_vec &name_table_string_offs_,
-          offset_vec &name_table_entry_offs_)
-      : name_table_string_offs (name_table_string_offs_),
-       name_table_entry_offs (name_table_entry_offs_)
-    {
-    }
-  };
-
-  /* Template to unify DWARF-32 and DWARF-64 .debug_names output
-     respecting name table width.  */
-  template<typename OffsetSize>
-  class dwarf_tmpl : public dwarf
-  {
-  public:
-    explicit dwarf_tmpl (bfd_endian dwarf5_byte_order_)
-      : dwarf (m_name_table_string_offs, m_name_table_entry_offs),
-       m_name_table_string_offs (dwarf5_byte_order_),
-       m_name_table_entry_offs (dwarf5_byte_order_)
-    {}
-
-  private:
-    offset_vec_tmpl<OffsetSize> m_name_table_string_offs;
-    offset_vec_tmpl<OffsetSize> m_name_table_entry_offs;
-  };
-
-  /* Try to reconstruct original DWARF tag for given partial_symbol.
-     This function is not DWARF-5 compliant but it is sufficient for
-     GDB as a DWARF-5 index consumer.  */
-  static int psymbol_tag (const struct partial_symbol *psym)
-  {
-    domain_enum domain = PSYMBOL_DOMAIN (psym);
-    enum address_class aclass = PSYMBOL_CLASS (psym);
-
-    switch (domain)
-      {
-      case VAR_DOMAIN:
-       switch (aclass)
-         {
-         case LOC_BLOCK:
-           return DW_TAG_subprogram;
-         case LOC_TYPEDEF:
-           return DW_TAG_typedef;
-         case LOC_COMPUTED:
-         case LOC_CONST_BYTES:
-         case LOC_OPTIMIZED_OUT:
-         case LOC_STATIC:
-           return DW_TAG_variable;
-         case LOC_CONST:
-           /* Note: It's currently impossible to recognize psyms as enum values
-              short of reading the type info.  For now punt.  */
-           return DW_TAG_variable;
-         default:
-           /* There are other LOC_FOO values that one might want to classify
-              as variables, but dwarf2read.c doesn't currently use them.  */
-           return DW_TAG_variable;
-         }
-      case STRUCT_DOMAIN:
-       return DW_TAG_structure_type;
-      default:
-       return 0;
-      }
-  }
-
-  /* Call insert for all partial symbols and mark them in PSYMS_SEEN.  */
-  void write_psymbols (std::unordered_set<partial_symbol *> &psyms_seen,
-                      struct partial_symbol **psymp, int count, int cu_index,
-                      bool is_static, unit_kind kind)
-  {
-    for (; count-- > 0; ++psymp)
-      {
-       struct partial_symbol *psym = *psymp;
-
-       if (SYMBOL_LANGUAGE (psym) == language_ada)
-         error (_("Ada is not currently supported by the index"));
-
-       /* Only add a given psymbol once.  */
-       if (psyms_seen.insert (psym).second)
-         insert (psym, cu_index, is_static, kind);
-      }
-  }
-
-  /* A helper function that writes a single signatured_type
-     to a debug_names.  */
-  void
-  write_one_signatured_type (struct signatured_type *entry,
-                            struct signatured_type_index_data *info)
-  {
-    struct partial_symtab *psymtab = entry->per_cu.v.psymtab;
-
-    write_psymbols (info->psyms_seen,
-                   &info->objfile->global_psymbols[psymtab->globals_offset],
-                   psymtab->n_global_syms, info->cu_index, false,
-                   unit_kind::tu);
-    write_psymbols (info->psyms_seen,
-                   &info->objfile->static_psymbols[psymtab->statics_offset],
-                   psymtab->n_static_syms, info->cu_index, true,
-                   unit_kind::tu);
-
-    info->types_list.append_uint (dwarf5_offset_size (), m_dwarf5_byte_order,
-                                 to_underlying (entry->per_cu.sect_off));
-
-    ++info->cu_index;
-  }
-
-  /* Store value of each symbol.  */
-  std::unordered_map<c_str_view, std::set<symbol_value>, c_str_view_hasher>
-    m_name_to_value_set;
-
-  /* Tables of DWARF-5 .debug_names.  They are in object file byte
-     order.  */
-  std::vector<uint32_t> m_bucket_table;
-  std::vector<uint32_t> m_hash_table;
-
-  const bfd_endian m_dwarf5_byte_order;
-  dwarf_tmpl<uint32_t> m_dwarf32;
-  dwarf_tmpl<uint64_t> m_dwarf64;
-  dwarf &m_dwarf;
-  offset_vec &m_name_table_string_offs, &m_name_table_entry_offs;
-  debug_str_lookup m_debugstrlookup;
-
-  /* Map each used .debug_names abbreviation tag parameter to its
-     index value.  */
-  std::unordered_map<index_key, int, index_key_hasher> m_indexkey_to_idx;
-
-  /* Next unused .debug_names abbreviation tag for
-     m_indexkey_to_idx.  */
-  int m_idx_next = 1;
-
-  /* .debug_names abbreviation table.  */
-  data_buf m_abbrev_table;
-
-  /* .debug_names entry pool.  */
-  data_buf m_entry_pool;
-};
-
-/* Return iff any of the needed offsets does not fit into 32-bit
-   .debug_names section.  */
-
-static bool
-check_dwarf64_offsets (struct dwarf2_per_objfile *dwarf2_per_objfile)
-{
-  for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
-    {
-      const dwarf2_per_cu_data &per_cu = *dwarf2_per_objfile->all_comp_units[i];
-
-      if (to_underlying (per_cu.sect_off) >= (static_cast<uint64_t> (1) << 32))
-       return true;
-    }
-  for (int i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
-    {
-      const signatured_type &sigtype = *dwarf2_per_objfile->all_type_units[i];
-      const dwarf2_per_cu_data &per_cu = sigtype.per_cu;
-
-      if (to_underlying (per_cu.sect_off) >= (static_cast<uint64_t> (1) << 32))
-       return true;
-    }
-  return false;
-}
-
-/* The psyms_seen set is potentially going to be largish (~40k
-   elements when indexing a -g3 build of GDB itself).  Estimate the
-   number of elements in order to avoid too many rehashes, which
-   require rebuilding buckets and thus many trips to
-   malloc/free.  */
-
-static size_t
-psyms_seen_size (struct dwarf2_per_objfile *dwarf2_per_objfile)
-{
-  size_t psyms_count = 0;
-  for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
-    {
-      struct dwarf2_per_cu_data *per_cu
-       = dwarf2_per_objfile->all_comp_units[i];
-      struct partial_symtab *psymtab = per_cu->v.psymtab;
-
-      if (psymtab != NULL && psymtab->user == NULL)
-       recursively_count_psymbols (psymtab, psyms_count);
-    }
-  /* Generating an index for gdb itself shows a ratio of
-     TOTAL_SEEN_SYMS/UNIQUE_SYMS or ~5.  4 seems like a good bet.  */
-  return psyms_count / 4;
-}
-
-/* Write new .gdb_index section for OBJFILE into OUT_FILE.
-   Return how many bytes were expected to be written into OUT_FILE.  */
-
-static size_t
-write_gdbindex (struct dwarf2_per_objfile *dwarf2_per_objfile, FILE *out_file)
-{
-  struct objfile *objfile = dwarf2_per_objfile->objfile;
-  mapped_symtab symtab;
-  data_buf cu_list;
-
-  /* While we're scanning CU's create a table that maps a psymtab pointer
-     (which is what addrmap records) to its index (which is what is recorded
-     in the index file).  This will later be needed to write the address
-     table.  */
-  psym_index_map cu_index_htab;
-  cu_index_htab.reserve (dwarf2_per_objfile->n_comp_units);
-
-  /* The CU list is already sorted, so we don't need to do additional
-     work here.  Also, the debug_types entries do not appear in
-     all_comp_units, but only in their own hash table.  */
-
-  std::unordered_set<partial_symbol *> psyms_seen
-    (psyms_seen_size (dwarf2_per_objfile));
-  for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
-    {
-      struct dwarf2_per_cu_data *per_cu
-       = dwarf2_per_objfile->all_comp_units[i];
-      struct partial_symtab *psymtab = per_cu->v.psymtab;
-
-      /* CU of a shared file from 'dwz -m' may be unused by this main file.
-        It may be referenced from a local scope but in such case it does not
-        need to be present in .gdb_index.  */
-      if (psymtab == NULL)
-       continue;
-
-      if (psymtab->user == NULL)
-       recursively_write_psymbols (objfile, psymtab, &symtab,
-                                   psyms_seen, i);
-
-      const auto insertpair = cu_index_htab.emplace (psymtab, i);
-      gdb_assert (insertpair.second);
-
-      cu_list.append_uint (8, BFD_ENDIAN_LITTLE,
-                          to_underlying (per_cu->sect_off));
-      cu_list.append_uint (8, BFD_ENDIAN_LITTLE, per_cu->length);
-    }
-
-  /* Dump the address map.  */
-  data_buf addr_vec;
-  write_address_map (objfile, addr_vec, cu_index_htab);
-
-  /* Write out the .debug_type entries, if any.  */
-  data_buf types_cu_list;
-  if (dwarf2_per_objfile->signatured_types)
-    {
-      signatured_type_index_data sig_data (types_cu_list,
-                                          psyms_seen);
-
-      sig_data.objfile = objfile;
-      sig_data.symtab = &symtab;
-      sig_data.cu_index = dwarf2_per_objfile->n_comp_units;
-      htab_traverse_noresize (dwarf2_per_objfile->signatured_types,
-                             write_one_signatured_type, &sig_data);
-    }
-
-  /* Now that we've processed all symbols we can shrink their cu_indices
-     lists.  */
-  uniquify_cu_indices (&symtab);
-
-  data_buf symtab_vec, constant_pool;
-  write_hash_table (&symtab, symtab_vec, constant_pool);
-
-  data_buf contents;
-  const offset_type size_of_contents = 6 * sizeof (offset_type);
-  offset_type total_len = size_of_contents;
-
-  /* The version number.  */
-  contents.append_data (MAYBE_SWAP (8));
-
-  /* The offset of the CU list from the start of the file.  */
-  contents.append_data (MAYBE_SWAP (total_len));
-  total_len += cu_list.size ();
-
-  /* The offset of the types CU list from the start of the file.  */
-  contents.append_data (MAYBE_SWAP (total_len));
-  total_len += types_cu_list.size ();
-
-  /* The offset of the address table from the start of the file.  */
-  contents.append_data (MAYBE_SWAP (total_len));
-  total_len += addr_vec.size ();
-
-  /* The offset of the symbol table from the start of the file.  */
-  contents.append_data (MAYBE_SWAP (total_len));
-  total_len += symtab_vec.size ();
-
-  /* The offset of the constant pool from the start of the file.  */
-  contents.append_data (MAYBE_SWAP (total_len));
-  total_len += constant_pool.size ();
-
-  gdb_assert (contents.size () == size_of_contents);
-
-  contents.file_write (out_file);
-  cu_list.file_write (out_file);
-  types_cu_list.file_write (out_file);
-  addr_vec.file_write (out_file);
-  symtab_vec.file_write (out_file);
-  constant_pool.file_write (out_file);
-
-  return total_len;
-}
-
-/* DWARF-5 augmentation string for GDB's DW_IDX_GNU_* extension.  */
-static const gdb_byte dwarf5_gdb_augmentation[] = { 'G', 'D', 'B', 0 };
-
-/* Write a new .debug_names section for OBJFILE into OUT_FILE, write
-   needed addition to .debug_str section to OUT_FILE_STR.  Return how
-   many bytes were expected to be written into OUT_FILE.  */
-
-static size_t
-write_debug_names (struct dwarf2_per_objfile *dwarf2_per_objfile,
-                  FILE *out_file, FILE *out_file_str)
-{
-  const bool dwarf5_is_dwarf64 = check_dwarf64_offsets (dwarf2_per_objfile);
-  struct objfile *objfile = dwarf2_per_objfile->objfile;
-  const enum bfd_endian dwarf5_byte_order
-    = gdbarch_byte_order (get_objfile_arch (objfile));
-
-  /* The CU list is already sorted, so we don't need to do additional
-     work here.  Also, the debug_types entries do not appear in
-     all_comp_units, but only in their own hash table.  */
-  data_buf cu_list;
-  debug_names nametable (dwarf2_per_objfile, dwarf5_is_dwarf64,
-                        dwarf5_byte_order);
-  std::unordered_set<partial_symbol *>
-    psyms_seen (psyms_seen_size (dwarf2_per_objfile));
-  for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
-    {
-      const dwarf2_per_cu_data *per_cu = dwarf2_per_objfile->all_comp_units[i];
-      partial_symtab *psymtab = per_cu->v.psymtab;
-
-      /* CU of a shared file from 'dwz -m' may be unused by this main
-        file.  It may be referenced from a local scope but in such
-        case it does not need to be present in .debug_names.  */
-      if (psymtab == NULL)
-       continue;
-
-      if (psymtab->user == NULL)
-       nametable.recursively_write_psymbols (objfile, psymtab, psyms_seen, i);
-
-      cu_list.append_uint (nametable.dwarf5_offset_size (), dwarf5_byte_order,
-                          to_underlying (per_cu->sect_off));
-    }
-
-  /* Write out the .debug_type entries, if any.  */
-  data_buf types_cu_list;
-  if (dwarf2_per_objfile->signatured_types)
-    {
-      debug_names::write_one_signatured_type_data sig_data (nametable,
-                       signatured_type_index_data (types_cu_list, psyms_seen));
-
-      sig_data.info.objfile = objfile;
-      /* It is used only for gdb_index.  */
-      sig_data.info.symtab = nullptr;
-      sig_data.info.cu_index = 0;
-      htab_traverse_noresize (dwarf2_per_objfile->signatured_types,
-                             debug_names::write_one_signatured_type,
-                             &sig_data);
-    }
-
-  nametable.build ();
-
-  /* No addr_vec - DWARF-5 uses .debug_aranges generated by GCC.  */
-
-  const offset_type bytes_of_header
-    = ((dwarf5_is_dwarf64 ? 12 : 4)
-       + 2 + 2 + 7 * 4
-       + sizeof (dwarf5_gdb_augmentation));
-  size_t expected_bytes = 0;
-  expected_bytes += bytes_of_header;
-  expected_bytes += cu_list.size ();
-  expected_bytes += types_cu_list.size ();
-  expected_bytes += nametable.bytes ();
-  data_buf header;
-
-  if (!dwarf5_is_dwarf64)
-    {
-      const uint64_t size64 = expected_bytes - 4;
-      gdb_assert (size64 < 0xfffffff0);
-      header.append_uint (4, dwarf5_byte_order, size64);
-    }
-  else
-    {
-      header.append_uint (4, dwarf5_byte_order, 0xffffffff);
-      header.append_uint (8, dwarf5_byte_order, expected_bytes - 12);
-    }
-
-  /* The version number.  */
-  header.append_uint (2, dwarf5_byte_order, 5);
-
-  /* Padding.  */
-  header.append_uint (2, dwarf5_byte_order, 0);
-
-  /* comp_unit_count - The number of CUs in the CU list.  */
-  header.append_uint (4, dwarf5_byte_order, dwarf2_per_objfile->n_comp_units);
-
-  /* local_type_unit_count - The number of TUs in the local TU
-     list.  */
-  header.append_uint (4, dwarf5_byte_order, dwarf2_per_objfile->n_type_units);
-
-  /* foreign_type_unit_count - The number of TUs in the foreign TU
-     list.  */
-  header.append_uint (4, dwarf5_byte_order, 0);
-
-  /* bucket_count - The number of hash buckets in the hash lookup
-     table.  */
-  header.append_uint (4, dwarf5_byte_order, nametable.bucket_count ());
-
-  /* name_count - The number of unique names in the index.  */
-  header.append_uint (4, dwarf5_byte_order, nametable.name_count ());
-
-  /* abbrev_table_size - The size in bytes of the abbreviations
-     table.  */
-  header.append_uint (4, dwarf5_byte_order, nametable.abbrev_table_bytes ());
-
-  /* augmentation_string_size - The size in bytes of the augmentation
-     string.  This value is rounded up to a multiple of 4.  */
-  static_assert (sizeof (dwarf5_gdb_augmentation) % 4 == 0, "");
-  header.append_uint (4, dwarf5_byte_order, sizeof (dwarf5_gdb_augmentation));
-  header.append_data (dwarf5_gdb_augmentation);
-
-  gdb_assert (header.size () == bytes_of_header);
-
-  header.file_write (out_file);
-  cu_list.file_write (out_file);
-  types_cu_list.file_write (out_file);
-  nametable.file_write (out_file, out_file_str);
-
-  return expected_bytes;
-}
-
-/* Assert that FILE's size is EXPECTED_SIZE.  Assumes file's seek
-   position is at the end of the file.  */
-
-static void
-assert_file_size (FILE *file, const char *filename, size_t expected_size)
-{
-  const auto file_size = ftell (file);
-  if (file_size == -1)
-    error (_("Can't get `%s' size"), filename);
-  gdb_assert (file_size == expected_size);
-}
-
-/* Create an index file for OBJFILE in the directory DIR.  */
-
-static void
-write_psymtabs_to_index (struct dwarf2_per_objfile *dwarf2_per_objfile,
-                        const char *dir,
-                        dw_index_kind index_kind)
-{
-  struct objfile *objfile = dwarf2_per_objfile->objfile;
-
-  if (dwarf2_per_objfile->using_index)
-    error (_("Cannot use an index to create the index"));
-
-  if (VEC_length (dwarf2_section_info_def, dwarf2_per_objfile->types) > 1)
-    error (_("Cannot make an index when the file has multiple .debug_types sections"));
-
-  if (!objfile->psymtabs || !objfile->psymtabs_addrmap)
-    return;
-
-  struct stat st;
-  if (stat (objfile_name (objfile), &st) < 0)
-    perror_with_name (objfile_name (objfile));
-
-  std::string filename (std::string (dir) + SLASH_STRING
-                       + lbasename (objfile_name (objfile))
-                       + (index_kind == dw_index_kind::DEBUG_NAMES
-                          ? INDEX5_SUFFIX : INDEX4_SUFFIX));
-
-  FILE *out_file = gdb_fopen_cloexec (filename.c_str (), "wb").release ();
-  if (!out_file)
-    error (_("Can't open `%s' for writing"), filename.c_str ());
-
-  /* Order matters here; we want FILE to be closed before FILENAME is
-     unlinked, because on MS-Windows one cannot delete a file that is
-     still open.  (Don't call anything here that might throw until
-     file_closer is created.)  */
-  gdb::unlinker unlink_file (filename.c_str ());
-  gdb_file_up close_out_file (out_file);
-
-  if (index_kind == dw_index_kind::DEBUG_NAMES)
-    {
-      std::string filename_str (std::string (dir) + SLASH_STRING
-                               + lbasename (objfile_name (objfile))
-                               + DEBUG_STR_SUFFIX);
-      FILE *out_file_str
-       = gdb_fopen_cloexec (filename_str.c_str (), "wb").release ();
-      if (!out_file_str)
-       error (_("Can't open `%s' for writing"), filename_str.c_str ());
-      gdb::unlinker unlink_file_str (filename_str.c_str ());
-      gdb_file_up close_out_file_str (out_file_str);
-
-      const size_t total_len
-       = write_debug_names (dwarf2_per_objfile, out_file, out_file_str);
-      assert_file_size (out_file, filename.c_str (), total_len);
-
-      /* We want to keep the file .debug_str file too.  */
-      unlink_file_str.keep ();
-    }
-  else
-    {
-      const size_t total_len
-       = write_gdbindex (dwarf2_per_objfile, out_file);
-      assert_file_size (out_file, filename.c_str (), total_len);
-    }
-
-  /* We want to keep the file.  */
-  unlink_file.keep ();
-}
-
-/* Implementation of the `save gdb-index' command.
-   
-   Note that the .gdb_index file format used by this command is
-   documented in the GDB manual.  Any changes here must be documented
-   there.  */
-
-static void
-save_gdb_index_command (const char *arg, int from_tty)
-{
-  struct objfile *objfile;
-  const char dwarf5space[] = "-dwarf-5 ";
-  dw_index_kind index_kind = dw_index_kind::GDB_INDEX;
-
-  if (!arg)
-    arg = "";
-
-  arg = skip_spaces (arg);
-  if (strncmp (arg, dwarf5space, strlen (dwarf5space)) == 0)
-    {
-      index_kind = dw_index_kind::DEBUG_NAMES;
-      arg += strlen (dwarf5space);
-      arg = skip_spaces (arg);
-    }
-
-  if (!*arg)
-    error (_("usage: save gdb-index [-dwarf-5] DIRECTORY"));
-
-  ALL_OBJFILES (objfile)
-  {
-    struct stat st;
-
-    /* If the objfile does not correspond to an actual file, skip it.  */
-    if (stat (objfile_name (objfile), &st) < 0)
-      continue;
-
-    struct dwarf2_per_objfile *dwarf2_per_objfile
-      = get_dwarf2_per_objfile (objfile);
-
-    if (dwarf2_per_objfile != NULL)
-      {
-       TRY
-         {
-           write_psymtabs_to_index (dwarf2_per_objfile, arg, index_kind);
-         }
-       CATCH (except, RETURN_MASK_ERROR)
-         {
-           exception_fprintf (gdb_stderr, except,
-                              _("Error while writing index for `%s': "),
-                              objfile_name (objfile));
-         }
-       END_CATCH
-      }
-
-  }
-}
-
-\f
-
-int dwarf_always_disassemble;
-
-static void
-show_dwarf_always_disassemble (struct ui_file *file, int from_tty,
-                              struct cmd_list_element *c, const char *value)
-{
-  fprintf_filtered (file,
-                   _("Whether to always disassemble "
-                     "DWARF expressions is %s.\n"),
-                   value);
-}
-
-static void
-show_check_physname (struct ui_file *file, int from_tty,
-                    struct cmd_list_element *c, const char *value)
-{
-  fprintf_filtered (file,
-                   _("Whether to check \"physname\" is %s.\n"),
-                   value);
-}
-
-void
-_initialize_dwarf2_read (void)
-{
-  struct cmd_list_element *c;
-
-  dwarf2_objfile_data_key = register_objfile_data ();
-
-  add_prefix_cmd ("dwarf", class_maintenance, set_dwarf_cmd, _("\
-Set DWARF specific variables.\n\
-Configure DWARF variables such as the cache size"),
-                  &set_dwarf_cmdlist, "maintenance set dwarf ",
-                  0/*allow-unknown*/, &maintenance_set_cmdlist);
-
-  add_prefix_cmd ("dwarf", class_maintenance, show_dwarf_cmd, _("\
-Show DWARF specific variables\n\
-Show DWARF variables such as the cache size"),
-                  &show_dwarf_cmdlist, "maintenance show dwarf ",
-                  0/*allow-unknown*/, &maintenance_show_cmdlist);
-
-  add_setshow_zinteger_cmd ("max-cache-age", class_obscure,
-                           &dwarf_max_cache_age, _("\
-Set the upper bound on the age of cached DWARF compilation units."), _("\
-Show the upper bound on the age of cached DWARF compilation units."), _("\
-A higher limit means that cached compilation units will be stored\n\
-in memory longer, and more total memory will be used.  Zero disables\n\
-caching, which can slow down startup."),
-                           NULL,
-                           show_dwarf_max_cache_age,
-                           &set_dwarf_cmdlist,
-                           &show_dwarf_cmdlist);
-
-  add_setshow_boolean_cmd ("always-disassemble", class_obscure,
-                          &dwarf_always_disassemble, _("\
-Set whether `info address' always disassembles DWARF expressions."), _("\
-Show whether `info address' always disassembles DWARF expressions."), _("\
-When enabled, DWARF expressions are always printed in an assembly-like\n\
-syntax.  When disabled, expressions will be printed in a more\n\
-conversational style, when possible."),
-                          NULL,
-                          show_dwarf_always_disassemble,
-                          &set_dwarf_cmdlist,
-                          &show_dwarf_cmdlist);
-
-  add_setshow_zuinteger_cmd ("dwarf-read", no_class, &dwarf_read_debug, _("\
-Set debugging of the DWARF reader."), _("\
-Show debugging of the DWARF reader."), _("\
-When enabled (non-zero), debugging messages are printed during DWARF\n\
-reading and symtab expansion.  A value of 1 (one) provides basic\n\
-information.  A value greater than 1 provides more verbose information."),
-                           NULL,
-                           NULL,
-                           &setdebuglist, &showdebuglist);
-
-  add_setshow_zuinteger_cmd ("dwarf-die", no_class, &dwarf_die_debug, _("\
-Set debugging of the DWARF DIE reader."), _("\
-Show debugging of the DWARF DIE reader."), _("\
-When enabled (non-zero), DIEs are dumped after they are read in.\n\
-The value is the maximum depth to print."),
-                            NULL,
-                            NULL,
-                            &setdebuglist, &showdebuglist);
-
-  add_setshow_zuinteger_cmd ("dwarf-line", no_class, &dwarf_line_debug, _("\
-Set debugging of the dwarf line reader."), _("\
-Show debugging of the dwarf line reader."), _("\
-When enabled (non-zero), line number entries are dumped as they are read in.\n\
-A value of 1 (one) provides basic information.\n\
-A value greater than 1 provides more verbose information."),
-                            NULL,
-                            NULL,
-                            &setdebuglist, &showdebuglist);
-
-  add_setshow_boolean_cmd ("check-physname", no_class, &check_physname, _("\
-Set cross-checking of \"physname\" code against demangler."), _("\
-Show cross-checking of \"physname\" code against demangler."), _("\
-When enabled, GDB's internal \"physname\" code is checked against\n\
-the demangler."),
-                          NULL, show_check_physname,
-                          &setdebuglist, &showdebuglist);
+  add_setshow_boolean_cmd ("check-physname", no_class, &check_physname, _("\
+Set cross-checking of \"physname\" code against demangler."), _("\
+Show cross-checking of \"physname\" code against demangler."), _("\
+When enabled, GDB's internal \"physname\" code is checked against\n\
+the demangler."),
+                          NULL, show_check_physname,
+                          &setdebuglist, &showdebuglist);
 
   add_setshow_boolean_cmd ("use-deprecated-index-sections",
                           no_class, &use_deprecated_index_sections, _("\
@@ -27213,17 +25571,6 @@ Warning: This option must be enabled before gdb reads the file."),
                           NULL,
                           &setlist, &showlist);
 
-  c = add_cmd ("gdb-index", class_files, save_gdb_index_command,
-              _("\
-Save a gdb-index file.\n\
-Usage: save gdb-index [-dwarf-5] DIRECTORY\n\
-\n\
-No options create one file with .gdb-index extension for pre-DWARF-5\n\
-compatible .gdb_index section.  With -dwarf-5 creates two files with\n\
-extension .debug_names and .debug_str for DWARF-5 .debug_names section."),
-              &save_cmdlist);
-  set_cmd_completer (c, filename_completer);
-
   dwarf2_locexpr_index = register_symbol_computed_impl (LOC_COMPUTED,
                                                        &dwarf2_locexpr_funcs);
   dwarf2_loclist_index = register_symbol_computed_impl (LOC_COMPUTED,
This page took 0.08232 seconds and 4 git commands to generate.