Fix "fall through" comments
[deliverable/binutils-gdb.git] / gdb / dwarf2read.c
index 34552a8a6316b0b2003a68567bda1d9e9beb8be1..26ec5efc286609a5275fcec4e959adb170962bf2 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,9 +88,8 @@
 #include <cmath>
 #include <set>
 #include <forward_list>
-
-typedef struct symbol *symbolp;
-DEF_VEC_P (symbolp);
+#include "rust-lang.h"
+#include "common/pathstuff.h"
 
 /* When == 1, print basic high level tracing messages.
    When > 1, be more verbose.
@@ -116,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
@@ -368,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
-{
-  /* 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 *)
@@ -655,26 +412,28 @@ struct delayed_method_info
   struct die_info *die;
 };
 
-typedef struct delayed_method_info delayed_method_info;
-DEF_VEC_O (delayed_method_info);
-
 /* Internal state when decoding a particular compilation unit.  */
 struct dwarf2_cu
 {
+  explicit dwarf2_cu (struct dwarf2_per_cu_data *per_cu);
+  ~dwarf2_cu ();
+
+  DISABLE_COPY_AND_ASSIGN (dwarf2_cu);
+
   /* The header of the compilation unit.  */
-  struct comp_unit_head header;
+  struct comp_unit_head header {};
 
   /* Base address of this compilation unit.  */
-  CORE_ADDR base_address;
+  CORE_ADDR base_address = 0;
 
   /* Non-zero if base_address has been set.  */
-  int base_known;
+  int base_known = 0;
 
   /* The language we are debugging.  */
-  enum language language;
-  const struct language_defn *language_defn;
+  enum language language = language_unknown;
+  const struct language_defn *language_defn = nullptr;
 
-  const char *producer;
+  const char *producer = nullptr;
 
   /* The generic symbol table building routines have separate lists for
      file scope symbols and all all other scopes (local scopes).  So
@@ -685,55 +444,55 @@ struct dwarf2_cu
      first local scope, and all other local scopes as nested local
      scopes, and worked fine.  Check to see if we really need to
      distinguish these in buildsym.c.  */
-  struct pending **list_in_scope;
+  struct pending **list_in_scope = nullptr;
 
   /* Hash table holding all the loaded partial DIEs
      with partial_die->offset.SECT_OFF as hash.  */
-  htab_t partial_dies;
+  htab_t partial_dies = nullptr;
 
   /* Storage for things with the same lifetime as this read-in compilation
      unit, including partial DIEs.  */
-  struct obstack comp_unit_obstack;
+  auto_obstack comp_unit_obstack;
 
   /* When multiple dwarf2_cu structures are living in memory, this field
      chains them all together, so that they can be released efficiently.
      We will probably also want a generation counter so that most-recently-used
      compilation units are cached...  */
-  struct dwarf2_per_cu_data *read_in_chain;
+  struct dwarf2_per_cu_data *read_in_chain = nullptr;
 
   /* Backlink to our per_cu entry.  */
   struct dwarf2_per_cu_data *per_cu;
 
   /* How many compilation units ago was this CU last referenced?  */
-  int last_used;
+  int last_used = 0;
 
   /* A hash table of DIE cu_offset for following references with
      die_info->offset.sect_off as hash.  */
-  htab_t die_hash;
+  htab_t die_hash = nullptr;
 
   /* Full DIEs if read in.  */
-  struct die_info *dies;
+  struct die_info *dies = nullptr;
 
   /* A set of pointers to dwarf2_per_cu_data objects for compilation
      units referenced by this one.  Only set during full symbol processing;
      partial symbol tables do not have dependencies.  */
-  htab_t dependencies;
+  htab_t dependencies = nullptr;
 
   /* Header data from the line table, during full symbol processing.  */
-  struct line_header *line_header;
+  struct line_header *line_header = nullptr;
   /* Non-NULL if LINE_HEADER is owned by this DWARF_CU.  Otherwise,
      it's owned by dwarf2_per_objfile::line_header_hash.  If non-NULL,
      this is the DW_TAG_compile_unit die for this CU.  We'll hold on
      to the line header as long as this DIE is being processed.  See
      process_die_scope.  */
-  die_info *line_header_die_owner;
+  die_info *line_header_die_owner = nullptr;
 
   /* A list of methods which need to have physnames computed
      after all type information has been read.  */
-  VEC (delayed_method_info) *method_list;
+  std::vector<delayed_method_info> method_list;
 
   /* To be copied to symtab->call_site_htab.  */
-  htab_t call_site_htab;
+  htab_t call_site_htab = nullptr;
 
   /* Non-NULL if this CU came from a DWO file.
      There is an invariant here that is important to remember:
@@ -744,12 +503,12 @@ struct dwarf2_cu
      is moot), or there is and either we're not going to read it (in which
      case this is NULL) or there is and we are reading it (in which case this
      is non-NULL).  */
-  struct dwo_unit *dwo_unit;
+  struct dwo_unit *dwo_unit = nullptr;
 
   /* The DW_AT_addr_base attribute if present, zero otherwise
      (zero is a valid value though).
      Note this value comes from the Fission stub CU/TU's DIE.  */
-  ULONGEST addr_base;
+  ULONGEST addr_base = 0;
 
   /* The DW_AT_ranges_base attribute if present, zero otherwise
      (zero is a valid value though).
@@ -761,7 +520,15 @@ struct dwarf2_cu
      DW_AT_ranges appeared in the DW_TAG_compile_unit of DWO DIEs: then
      DW_AT_ranges_base *would* have to be applied, and we'd have to care
      whether the DW_AT_ranges attribute came from the skeleton or DWO.  */
-  ULONGEST ranges_base;
+  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;
@@ -786,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.  */
 
@@ -1401,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;
@@ -1434,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.  */
@@ -1445,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.  */
@@ -1463,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.  */
@@ -1515,9 +1195,9 @@ struct abbrev_table
   explicit abbrev_table (sect_offset off)
     : sect_off (off)
   {
-    abbrevs =
+    m_abbrevs =
       XOBNEWVEC (&abbrev_obstack, struct abbrev_info *, ABBREV_HASH_SIZE);
-    memset (abbrevs, 0, ABBREV_HASH_SIZE * sizeof (struct abbrev_info *));
+    memset (m_abbrevs, 0, ABBREV_HASH_SIZE * sizeof (struct abbrev_info *));
   }
 
   DISABLE_COPY_AND_ASSIGN (abbrev_table);
@@ -1542,11 +1222,13 @@ struct abbrev_table
   /* Storage for the abbrev table.  */
   auto_obstack abbrev_obstack;
 
+private:
+
   /* Hash table of abbrevs.
      This is an array of size ABBREV_HASH_SIZE allocated in abbrev_obstack.
      It could be statically allocated, but the previous code didn't so we
      don't either.  */
-  struct abbrev_info **abbrevs;
+  struct abbrev_info **m_abbrevs;
 };
 
 typedef std::unique_ptr<struct abbrev_table> abbrev_table_up;
@@ -1643,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
@@ -1676,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
@@ -1789,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 *,
-                                        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 *);
@@ -2138,8 +1809,6 @@ static const gdb_byte *skip_one_die (const struct die_reader_specs *reader,
                                     const gdb_byte *info_ptr,
                                     struct abbrev_info *abbrev);
 
-static void free_stack_comp_unit (void *);
-
 static hashval_t partial_die_hash (const void *item);
 
 static int partial_die_eq (const void *item_lhs, const void *item_rhs);
@@ -2148,17 +1817,10 @@ static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit
   (sect_offset sect_off, unsigned int offset_in_dwz,
    struct dwarf2_per_objfile *dwarf2_per_objfile);
 
-static void init_one_comp_unit (struct dwarf2_cu *cu,
-                               struct dwarf2_per_cu_data *per_cu);
-
 static void prepare_one_comp_unit (struct dwarf2_cu *cu,
                                   struct die_info *comp_unit_die,
                                   enum language pretend_language);
 
-static void free_heap_comp_unit (void *);
-
-static void free_cached_comp_units (void *);
-
 static void age_cached_comp_units (struct dwarf2_per_objfile *dwarf2_per_objfile);
 
 static void free_one_cached_comp_unit (struct dwarf2_per_cu_data *);
@@ -2191,13 +1853,48 @@ static struct type *get_die_type_at_offset (sect_offset,
 
 static struct type *get_die_type (struct die_info *die, struct dwarf2_cu *cu);
 
-static void dwarf2_release_queue (void *dummy);
-
 static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu,
                             enum language pretend_language);
 
 static void process_queue (struct dwarf2_per_objfile *dwarf2_per_objfile);
 
+/* Class, the destructor of which frees all allocated queue entries.  This
+   will only have work to do if an error was thrown while processing the
+   dwarf.  If no error was thrown then the queue entries should have all
+   been processed, and freed, as we went along.  */
+
+class dwarf2_queue_guard
+{
+public:
+  dwarf2_queue_guard () = default;
+
+  /* Free any entries remaining on the queue.  There should only be
+     entries left if we hit an error while processing the dwarf.  */
+  ~dwarf2_queue_guard ()
+  {
+    struct dwarf2_queue_item *item, *last;
+
+    item = dwarf2_queue;
+    while (item)
+      {
+       /* Anything still marked queued is likely to be in an
+          inconsistent state, so discard it.  */
+       if (item->per_cu->queued)
+         {
+           if (item->per_cu->cu != NULL)
+             free_one_cached_comp_unit (item->per_cu);
+           item->per_cu->queued = 0;
+         }
+
+       last = item;
+       item = item->next;
+       xfree (last);
+      }
+
+    dwarf2_queue = dwarf2_queue_tail = NULL;
+  }
+};
+
 /* The return type of find_file_and_directory.  Note, the enclosed
    string pointers are only valid while this object is valid.  */
 
@@ -2262,14 +1959,22 @@ static struct dwo_unit *lookup_dwo_type_unit
 
 static void queue_and_load_all_dwo_tus (struct dwarf2_per_cu_data *);
 
-static void free_dwo_file_cleanup (void *);
+static void free_dwo_file (struct dwo_file *);
 
-struct free_dwo_file_cleanup_data
+/* A unique_ptr helper to free a dwo_file.  */
+
+struct dwo_file_deleter
 {
-  struct dwo_file *dwo_file;
-  struct dwarf2_per_objfile *dwarf2_per_objfile;
+  void operator() (struct dwo_file *df) const
+  {
+    free_dwo_file (df);
+  }
 };
 
+/* A unique pointer to a dwo_file.  */
+
+typedef std::unique_ptr<struct dwo_file, dwo_file_deleter> dwo_file_up;
+
 static void process_cu_includes (struct dwarf2_per_objfile *dwarf2_per_objfile);
 
 static void check_producer (struct dwarf2_cu *cu);
@@ -2404,11 +2109,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_,
@@ -2424,6 +2124,8 @@ dwarf2_per_objfile::dwarf2_per_objfile (struct objfile *objfile_,
     locate_sections (obfd, sec, *names);
 }
 
+static void free_dwo_files (htab_t dwo_files, struct objfile *objfile);
+
 dwarf2_per_objfile::~dwarf2_per_objfile ()
 {
   /* Cached DIE trees use xmalloc and the comp_unit_obstack.  */
@@ -2435,6 +2137,25 @@ dwarf2_per_objfile::~dwarf2_per_objfile ()
   if (line_header_hash)
     htab_delete (line_header_hash);
 
+  for (dwarf2_per_cu_data *per_cu : all_comp_units)
+    VEC_free (dwarf2_per_cu_ptr, per_cu->imported_symtabs);
+
+  for (signatured_type *sig_type : all_type_units)
+    VEC_free (dwarf2_per_cu_ptr, sig_type->per_cu.imported_symtabs);
+
+  VEC_free (dwarf2_section_info_def, types);
+
+  if (dwo_files != NULL)
+    free_dwo_files (dwo_files, objfile);
+  if (dwp_file != NULL)
+    gdb_bfd_unref (dwp_file->dbfd);
+
+  if (dwz_file != NULL && dwz_file->dwz_bfd)
+    gdb_bfd_unref (dwz_file->dwz_bfd);
+
+  if (index_table != NULL)
+    index_table->~mapped_index ();
+
   /* Everything else should be on the objfile obstack.  */
 }
 
@@ -2449,12 +2170,36 @@ dwarf2_per_objfile::free_cached_comp_units ()
     {
       dwarf2_per_cu_data *next_cu = per_cu->cu->read_in_chain;
 
-      free_heap_comp_unit (per_cu->cu);
+      delete per_cu->cu;
       *last_chain = next_cu;
       per_cu = next_cu;
     }
 }
 
+/* A helper class that calls free_cached_comp_units on
+   destruction.  */
+
+class free_cached_comp_units
+{
+public:
+
+  explicit free_cached_comp_units (dwarf2_per_objfile *per_objfile)
+    : m_per_objfile (per_objfile)
+  {
+  }
+
+  ~free_cached_comp_units ()
+  {
+    m_per_objfile->free_cached_comp_units ();
+  }
+
+  DISABLE_COPY_AND_ASSIGN (free_cached_comp_units);
+
+private:
+
+  dwarf2_per_objfile *m_per_objfile;
+};
+
 /* Try to locate the sections we need for DWARF 2 debugging
    information and return true if we have enough to do something.
    NAMES points to the dwarf2 section names, or is NULL if the standard
@@ -2473,10 +2218,9 @@ dwarf2_has_info (struct objfile *objfile,
   if (dwarf2_per_objfile == NULL)
     {
       /* Initialize per-objfile state.  */
-      struct dwarf2_per_objfile *data
-       = XOBNEW (&objfile->objfile_obstack, struct dwarf2_per_objfile);
-
-      dwarf2_per_objfile = new (data) struct dwarf2_per_objfile (objfile, names);
+      dwarf2_per_objfile
+       = new (&objfile->objfile_obstack) struct dwarf2_per_objfile (objfile,
+                                                                    names);
       set_dwarf2_per_objfile (objfile, dwarf2_per_objfile);
     }
   return (!dwarf2_per_objfile->info.is_virtual
@@ -2707,14 +2451,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;
@@ -3113,7 +2853,6 @@ load_cu (struct dwarf2_per_cu_data *per_cu)
 static void
 dw2_do_instantiate_symtab (struct dwarf2_per_cu_data *per_cu)
 {
-  struct cleanup *back_to;
   struct dwarf2_per_objfile *dwarf2_per_objfile = per_cu->dwarf2_per_objfile;
 
   /* Skip type_unit_groups, reading the type units they contain
@@ -3121,7 +2860,10 @@ dw2_do_instantiate_symtab (struct dwarf2_per_cu_data *per_cu)
   if (IS_TYPE_UNIT_GROUP (per_cu))
     return;
 
-  back_to = make_cleanup (dwarf2_release_queue, NULL);
+  /* The destructor of dwarf2_queue_guard frees any entries left on
+     the queue.  After this point we're guaranteed to leave this function
+     with the dwarf queue empty.  */
+  dwarf2_queue_guard q_guard;
 
   if (dwarf2_per_objfile->using_index
       ? per_cu->v.quick->compunit_symtab == NULL
@@ -3148,8 +2890,6 @@ dw2_do_instantiate_symtab (struct dwarf2_per_cu_data *per_cu)
   /* Age the cache, releasing compilation units that have not
      been used recently.  */
   age_cached_comp_units (dwarf2_per_objfile);
-
-  do_cleanups (back_to);
 }
 
 /* Ensure that the symbols for PER_CU have been read in.  OBJFILE is
@@ -3164,54 +2904,48 @@ dw2_instantiate_symtab (struct dwarf2_per_cu_data *per_cu)
   gdb_assert (dwarf2_per_objfile->using_index);
   if (!per_cu->v.quick->compunit_symtab)
     {
-      struct cleanup *back_to = make_cleanup (free_cached_comp_units,
-                                             dwarf2_per_objfile);
+      free_cached_comp_units freer (dwarf2_per_objfile);
       scoped_restore decrementer = increment_reading_symtab ();
       dw2_do_instantiate_symtab (per_cu);
       process_cu_includes (dwarf2_per_objfile);
-      do_cleanups (back_to);
     }
 
   return per_cu->v.quick->compunit_symtab;
 }
 
-/* Return the CU/TU given its index.
+/* See declaration.  */
 
-   This is intended for loops like:
+dwarf2_per_cu_data *
+dwarf2_per_objfile::get_cutu (int index)
+{
+  if (index >= this->all_comp_units.size ())
+    {
+      index -= this->all_comp_units.size ();
+      gdb_assert (index < this->all_type_units.size ());
+      return &this->all_type_units[index]->per_cu;
+    }
 
-   for (i = 0; i < (dwarf2_per_objfile->n_comp_units
-                   + dwarf2_per_objfile->n_type_units); ++i)
-     {
-       struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
+  return this->all_comp_units[index];
+}
 
-       ...;
-     }
-*/
+/* See declaration.  */
 
-static struct dwarf2_per_cu_data *
-dw2_get_cutu (struct dwarf2_per_objfile *dwarf2_per_objfile,
-             int index)
+dwarf2_per_cu_data *
+dwarf2_per_objfile::get_cu (int index)
 {
-  if (index >= dwarf2_per_objfile->n_comp_units)
-    {
-      index -= dwarf2_per_objfile->n_comp_units;
-      gdb_assert (index < dwarf2_per_objfile->n_type_units);
-      return &dwarf2_per_objfile->all_type_units[index]->per_cu;
-    }
+  gdb_assert (index >= 0 && index < this->all_comp_units.size ());
 
-  return dwarf2_per_objfile->all_comp_units[index];
+  return this->all_comp_units[index];
 }
 
-/* Return the CU given its index.
-   This differs from dw2_get_cutu in that it's for when you know INDEX
-   refers to a CU.  */
+/* See declaration.  */
 
-static struct dwarf2_per_cu_data *
-dw2_get_cu (struct dwarf2_per_objfile *dwarf2_per_objfile, int index)
+signatured_type *
+dwarf2_per_objfile::get_tu (int index)
 {
-  gdb_assert (index >= 0 && index < dwarf2_per_objfile->n_comp_units);
+  gdb_assert (index >= 0 && index < this->all_type_units.size ());
 
-  return dwarf2_per_objfile->all_comp_units[index];
+  return this->all_type_units[index];
 }
 
 /* Return a new dwarf2_per_cu_data allocated on OBJFILE's
@@ -3242,17 +2976,12 @@ create_cu_from_index_list (struct dwarf2_per_objfile *dwarf2_per_objfile,
    CUs.  */
 
 static void
-create_cus_from_index_list (struct objfile *objfile,
+create_cus_from_index_list (struct dwarf2_per_objfile *dwarf2_per_objfile,
                            const gdb_byte *cu_list, offset_type n_elements,
                            struct dwarf2_section_info *section,
-                           int is_dwz,
-                           int base_offset)
+                           int is_dwz)
 {
-  offset_type i;
-  struct dwarf2_per_objfile *dwarf2_per_objfile
-    = get_dwarf2_per_objfile (objfile);
-
-  for (i = 0; i < n_elements; i += 2)
+  for (offset_type i = 0; i < n_elements; i += 2)
     {
       gdb_static_assert (sizeof (ULONGEST) >= 8);
 
@@ -3261,9 +2990,10 @@ create_cus_from_index_list (struct objfile *objfile,
       ULONGEST length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE);
       cu_list += 2 * 8;
 
-      dwarf2_per_objfile->all_comp_units[base_offset + i / 2]
+      dwarf2_per_cu_data *per_cu
        = create_cu_from_index_list (dwarf2_per_objfile, section, is_dwz,
                                     sect_off, length);
+      dwarf2_per_objfile->all_comp_units.push_back (per_cu);
     }
 }
 
@@ -3271,52 +3001,42 @@ create_cus_from_index_list (struct objfile *objfile,
    the CU objects for this objfile.  */
 
 static void
-create_cus_from_index (struct objfile *objfile,
+create_cus_from_index (struct dwarf2_per_objfile *dwarf2_per_objfile,
                       const gdb_byte *cu_list, offset_type cu_list_elements,
                       const gdb_byte *dwz_list, offset_type dwz_elements)
 {
-  struct dwz_file *dwz;
-  struct dwarf2_per_objfile *dwarf2_per_objfile
-    = get_dwarf2_per_objfile (objfile);
+  gdb_assert (dwarf2_per_objfile->all_comp_units.empty ());
+  dwarf2_per_objfile->all_comp_units.reserve
+    ((cu_list_elements + dwz_elements) / 2);
 
-  dwarf2_per_objfile->n_comp_units = (cu_list_elements + dwz_elements) / 2;
-  dwarf2_per_objfile->all_comp_units =
-    XOBNEWVEC (&objfile->objfile_obstack, struct dwarf2_per_cu_data *,
-              dwarf2_per_objfile->n_comp_units);
-
-  create_cus_from_index_list (objfile, cu_list, cu_list_elements,
-                             &dwarf2_per_objfile->info, 0, 0);
+  create_cus_from_index_list (dwarf2_per_objfile, cu_list, cu_list_elements,
+                             &dwarf2_per_objfile->info, 0);
 
   if (dwz_elements == 0)
     return;
 
-  dwz = dwarf2_get_dwz_file (dwarf2_per_objfile);
-  create_cus_from_index_list (objfile, dwz_list, dwz_elements, &dwz->info, 1,
-                             cu_list_elements / 2);
+  dwz_file *dwz = dwarf2_get_dwz_file (dwarf2_per_objfile);
+  create_cus_from_index_list (dwarf2_per_objfile, dwz_list, dwz_elements,
+                             &dwz->info, 1);
 }
 
 /* Create the signatured type hash table from the index.  */
 
 static void
-create_signatured_type_table_from_index (struct objfile *objfile,
-                                        struct dwarf2_section_info *section,
-                                        const gdb_byte *bytes,
-                                        offset_type elements)
+create_signatured_type_table_from_index
+  (struct dwarf2_per_objfile *dwarf2_per_objfile,
+   struct dwarf2_section_info *section,
+   const gdb_byte *bytes,
+   offset_type elements)
 {
-  offset_type i;
-  htab_t sig_types_hash;
-  struct dwarf2_per_objfile *dwarf2_per_objfile
-    = get_dwarf2_per_objfile (objfile);
+  struct objfile *objfile = dwarf2_per_objfile->objfile;
 
-  dwarf2_per_objfile->n_type_units
-    = dwarf2_per_objfile->n_allocated_type_units
-    = elements / 3;
-  dwarf2_per_objfile->all_type_units =
-    XNEWVEC (struct signatured_type *, dwarf2_per_objfile->n_type_units);
+  gdb_assert (dwarf2_per_objfile->all_type_units.empty ());
+  dwarf2_per_objfile->all_type_units.reserve (elements / 3);
 
-  sig_types_hash = allocate_signatured_type_table (objfile);
+  htab_t sig_types_hash = allocate_signatured_type_table (objfile);
 
-  for (i = 0; i < elements; i += 3)
+  for (offset_type i = 0; i < elements; i += 3)
     {
       struct signatured_type *sig_type;
       ULONGEST signature;
@@ -3347,7 +3067,7 @@ create_signatured_type_table_from_index (struct objfile *objfile,
       slot = htab_find_slot (sig_types_hash, sig_type, INSERT);
       *slot = sig_type;
 
-      dwarf2_per_objfile->all_type_units[i / 3] = sig_type;
+      dwarf2_per_objfile->all_type_units.push_back (sig_type);
     }
 
   dwarf2_per_objfile->signatured_types = sig_types_hash;
@@ -3367,20 +3087,15 @@ create_signatured_type_table_from_debug_names
   dwarf2_read_section (objfile, section);
   dwarf2_read_section (objfile, abbrev_section);
 
-  dwarf2_per_objfile->n_type_units
-    = dwarf2_per_objfile->n_allocated_type_units
-    = map.tu_count;
-  dwarf2_per_objfile->all_type_units
-    = XNEWVEC (struct signatured_type *, dwarf2_per_objfile->n_type_units);
+  gdb_assert (dwarf2_per_objfile->all_type_units.empty ());
+  dwarf2_per_objfile->all_type_units.reserve (map.tu_count);
 
   htab_t sig_types_hash = allocate_signatured_type_table (objfile);
 
   for (uint32_t i = 0; i < map.tu_count; ++i)
     {
       struct signatured_type *sig_type;
-      ULONGEST signature;
       void **slot;
-      cu_offset type_offset_in_tu;
 
       sect_offset sect_off
        = (sect_offset) (extract_unsigned_integer
@@ -3409,7 +3124,7 @@ create_signatured_type_table_from_debug_names
       slot = htab_find_slot (sig_types_hash, sig_type, INSERT);
       *slot = sig_type;
 
-      dwarf2_per_objfile->all_type_units[i] = sig_type;
+      dwarf2_per_objfile->all_type_units.push_back (sig_type);
     }
 
   dwarf2_per_objfile->signatured_types = sig_types_hash;
@@ -3455,7 +3170,7 @@ create_addrmap_from_index (struct dwarf2_per_objfile *dwarf2_per_objfile,
          continue;
        }
 
-      if (cu_index >= dwarf2_per_objfile->n_comp_units)
+      if (cu_index >= dwarf2_per_objfile->all_comp_units.size ())
        {
          complaint (&symfile_complaints,
                     _(".gdb_index address table has invalid CU number %u"),
@@ -3466,7 +3181,7 @@ create_addrmap_from_index (struct dwarf2_per_objfile *dwarf2_per_objfile,
       lo = gdbarch_adjust_dwarf2_addr (gdbarch, lo + baseaddr);
       hi = gdbarch_adjust_dwarf2_addr (gdbarch, hi + baseaddr);
       addrmap_set_empty (mutable_map, lo, hi - 1,
-                        dw2_get_cutu (dwarf2_per_objfile, cu_index));
+                        dwarf2_per_objfile->get_cu (cu_index));
     }
 
   objfile->psymtabs_addrmap = addrmap_create_fixed (mutable_map,
@@ -3493,16 +3208,15 @@ create_addrmap_from_aranges (struct dwarf2_per_objfile *dwarf2_per_objfile,
                     dwarf2_per_cu_data *,
                     gdb::hash_enum<sect_offset>>
     debug_info_offset_to_per_cu;
-  for (int cui = 0; cui < dwarf2_per_objfile->n_comp_units; ++cui)
+  for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units)
     {
-      dwarf2_per_cu_data *per_cu = dw2_get_cutu (dwarf2_per_objfile, cui);
       const auto insertpair
        = debug_info_offset_to_per_cu.emplace (per_cu->sect_off, per_cu);
       if (!insertpair.second)
        {
          warning (_("Section .debug_aranges in %s has duplicate "
-                    "debug_info_offset %u, ignoring .debug_aranges."),
-                  objfile_name (objfile), to_underlying (per_cu->sect_off));
+                    "debug_info_offset %s, ignoring .debug_aranges."),
+                  objfile_name (objfile), sect_offset_str (per_cu->sect_off));
          return;
        }
     }
@@ -3633,31 +3347,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
@@ -3722,7 +3411,7 @@ find_slot_in_mapped_hash (struct mapped_index *index, const char *name,
 
 /* A helper function that reads the .gdb_index from SECTION and fills
    in MAP.  FILENAME is the name of the file containing the section;
-   it is used for error reporting.  DEPRECATED_OK is nonzero if it is
+   it is used for error reporting.  DEPRECATED_OK is true if it is
    ok to use deprecated sections.
 
    CU_LIST, CU_LIST_ELEMENTS, TYPES_LIST, and TYPES_LIST_ELEMENTS are
@@ -3731,10 +3420,10 @@ find_slot_in_mapped_hash (struct mapped_index *index, const char *name,
 
    Returns 1 if all went well, 0 otherwise.  */
 
-static int
+static bool
 read_index_from_section (struct objfile *objfile,
                         const char *filename,
-                        int deprecated_ok,
+                        bool deprecated_ok,
                         struct dwarf2_section_info *section,
                         struct mapped_index *map,
                         const gdb_byte **cu_list,
@@ -3850,14 +3539,13 @@ to use the section anyway."),
    elements of all the CUs and return 1.  Otherwise, return 0.  */
 
 static int
-dwarf2_read_index (struct objfile *objfile)
+dwarf2_read_index (struct dwarf2_per_objfile *dwarf2_per_objfile)
 {
   struct mapped_index local_map, *map;
   const gdb_byte *cu_list, *types_list, *dwz_list = NULL;
   offset_type cu_list_elements, types_list_elements, dwz_list_elements = 0;
   struct dwz_file *dwz;
-  struct dwarf2_per_objfile *dwarf2_per_objfile
-    = get_dwarf2_per_objfile (objfile);
+  struct objfile *objfile = dwarf2_per_objfile->objfile;
 
   if (!read_index_from_section (objfile, objfile_name (objfile),
                                use_deprecated_index_sections,
@@ -3892,8 +3580,8 @@ dwarf2_read_index (struct objfile *objfile)
        }
     }
 
-  create_cus_from_index (objfile, cu_list, cu_list_elements, dwz_list,
-                        dwz_list_elements);
+  create_cus_from_index (dwarf2_per_objfile, cu_list, cu_list_elements,
+                        dwz_list, dwz_list_elements);
 
   if (types_list_elements)
     {
@@ -3907,8 +3595,8 @@ dwarf2_read_index (struct objfile *objfile)
       section = VEC_index (dwarf2_section_info_def,
                           dwarf2_per_objfile->types, 0);
 
-      create_signatured_type_table_from_index (objfile, section, types_list,
-                                              types_list_elements);
+      create_signatured_type_table_from_index (dwarf2_per_objfile, section,
+                                              types_list, types_list_elements);
     }
 
   create_addrmap_from_index (dwarf2_per_objfile, &local_map);
@@ -3920,7 +3608,7 @@ dwarf2_read_index (struct objfile *objfile)
   dwarf2_per_objfile->index_table = map;
   dwarf2_per_objfile->using_index = 1;
   dwarf2_per_objfile->quick_file_names_table =
-    create_quick_file_names_table (dwarf2_per_objfile->n_comp_units);
+    create_quick_file_names_table (dwarf2_per_objfile->all_comp_units.size ());
 
   return 1;
 }
@@ -4052,8 +3740,7 @@ dw2_find_last_source_symtab (struct objfile *objfile)
 {
   struct dwarf2_per_objfile *dwarf2_per_objfile
     = get_dwarf2_per_objfile (objfile);
-  int index = dwarf2_per_objfile->n_comp_units - 1;
-  dwarf2_per_cu_data *dwarf_cu = dw2_get_cutu (dwarf2_per_objfile, index);
+  dwarf2_per_cu_data *dwarf_cu = dwarf2_per_objfile->all_comp_units.back ();
   compunit_symtab *cust = dw2_instantiate_symtab (dwarf_cu);
 
   if (cust == NULL)
@@ -4123,7 +3810,6 @@ dw2_map_symtabs_matching_filename
   (struct objfile *objfile, const char *name, const char *real_path,
    gdb::function_view<bool (symtab *)> callback)
 {
-  int i;
   const char *name_basename = lbasename (name);
   struct dwarf2_per_objfile *dwarf2_per_objfile
     = get_dwarf2_per_objfile (objfile);
@@ -4131,21 +3817,17 @@ dw2_map_symtabs_matching_filename
   /* The rule is CUs specify all the files, including those used by
      any TU, so there's no need to scan TUs here.  */
 
-  for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+  for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units)
     {
-      int j;
-      struct dwarf2_per_cu_data *per_cu = dw2_get_cu (dwarf2_per_objfile, i);
-      struct quick_file_names *file_data;
-
       /* We only need to look at symtabs not already expanded.  */
       if (per_cu->v.quick->compunit_symtab)
        continue;
 
-      file_data = dw2_get_file_names (per_cu);
+      quick_file_names *file_data = dw2_get_file_names (per_cu);
       if (file_data == NULL)
        continue;
 
-      for (j = 0; j < file_data->num_file_names; ++j)
+      for (int j = 0; j < file_data->num_file_names; ++j)
        {
          const char *this_name = file_data->file_names[j];
          const char *this_real_name;
@@ -4262,7 +3944,6 @@ dw2_symtab_iter_next (struct dw2_symtab_iterator *iter)
       offset_type cu_index_and_attrs =
        MAYBE_SWAP (iter->vec[iter->next + 1]);
       offset_type cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
-      struct dwarf2_per_cu_data *per_cu;
       int want_static = iter->block_index != GLOBAL_BLOCK;
       /* This value is only valid for index versions >= 7.  */
       int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
@@ -4277,8 +3958,8 @@ dw2_symtab_iter_next (struct dw2_symtab_iterator *iter)
         && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
 
       /* Don't crash on bad data.  */
-      if (cu_index >= (dwarf2_per_objfile->n_comp_units
-                      + dwarf2_per_objfile->n_type_units))
+      if (cu_index >= (dwarf2_per_objfile->all_comp_units.size ()
+                      + dwarf2_per_objfile->all_type_units.size ()))
        {
          complaint (&symfile_complaints,
                     _(".gdb_index entry has bad CU index"
@@ -4287,7 +3968,7 @@ dw2_symtab_iter_next (struct dw2_symtab_iterator *iter)
          continue;
        }
 
-      per_cu = dw2_get_cutu (dwarf2_per_objfile, cu_index);
+      dwarf2_per_cu_data *per_cu = dwarf2_per_objfile->get_cutu (cu_index);
 
       /* Skip if already read in.  */
       if (per_cu->v.quick->compunit_symtab)
@@ -4386,12 +4067,13 @@ dw2_print_stats (struct objfile *objfile)
 {
   struct dwarf2_per_objfile *dwarf2_per_objfile
     = get_dwarf2_per_objfile (objfile);
-  int total = dwarf2_per_objfile->n_comp_units + dwarf2_per_objfile->n_type_units;
+  int total = (dwarf2_per_objfile->all_comp_units.size ()
+              + dwarf2_per_objfile->all_type_units.size ());
   int count = 0;
 
   for (int i = 0; i < total; ++i)
     {
-      struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (dwarf2_per_objfile, i);
+      dwarf2_per_cu_data *per_cu = dwarf2_per_objfile->get_cutu (i);
 
       if (!per_cu->v.quick->compunit_symtab)
        ++count;
@@ -4455,13 +4137,12 @@ dw2_expand_all_symtabs (struct objfile *objfile)
 {
   struct dwarf2_per_objfile *dwarf2_per_objfile
     = get_dwarf2_per_objfile (objfile);
-  int total_units = (dwarf2_per_objfile->n_comp_units
-                    + dwarf2_per_objfile->n_type_units);
+  int total_units = (dwarf2_per_objfile->all_comp_units.size ()
+                    + dwarf2_per_objfile->all_type_units.size ());
 
   for (int i = 0; i < total_units; ++i)
     {
-      struct dwarf2_per_cu_data *per_cu
-       = dw2_get_cutu (dwarf2_per_objfile, i);
+      dwarf2_per_cu_data *per_cu = dwarf2_per_objfile->get_cutu (i);
 
       dw2_instantiate_symtab (per_cu);
     }
@@ -4479,21 +4160,17 @@ dw2_expand_symtabs_with_fullname (struct objfile *objfile,
      There can be an order of magnitude (or more) more type units
      than comp units, and we avoid them if we can.  */
 
-  for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+  for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units)
     {
-      int j;
-      struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (dwarf2_per_objfile, i);
-      struct quick_file_names *file_data;
-
       /* We only need to look at symtabs not already expanded.  */
       if (per_cu->v.quick->compunit_symtab)
        continue;
 
-      file_data = dw2_get_file_names (per_cu);
+      quick_file_names *file_data = dw2_get_file_names (per_cu);
       if (file_data == NULL)
        continue;
 
-      for (j = 0; j < file_data->num_file_names; ++j)
+      for (int j = 0; j < file_data->num_file_names; ++j)
        {
          const char *this_fullname = file_data->file_names[j];
 
@@ -4900,13 +4577,13 @@ public:
   DISABLE_COPY_AND_ASSIGN (mock_mapped_index);
 
   /* Return the number of names in the symbol table.  */
-  virtual size_t symbol_name_count () const
+  size_t symbol_name_count () const override
   {
     return m_symbol_table.size ();
   }
 
   /* Get the name of the symbol at IDX in the symbol table.  */
-  virtual const char *symbol_name_at (offset_type idx) const
+  const char *symbol_name_at (offset_type idx) const override
   {
     return m_symbol_table[idx];
   }
@@ -5352,7 +5029,6 @@ dw2_expand_marked_cus
   vec_len = MAYBE_SWAP (vec[0]);
   for (vec_idx = 0; vec_idx < vec_len; ++vec_idx)
     {
-      struct dwarf2_per_cu_data *per_cu;
       offset_type cu_index_and_attrs = MAYBE_SWAP (vec[vec_idx + 1]);
       /* This value is only valid for index versions >= 7.  */
       int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
@@ -5399,8 +5075,8 @@ dw2_expand_marked_cus
        }
 
       /* Don't crash on bad data.  */
-      if (cu_index >= (dwarf2_per_objfile->n_comp_units
-                      + dwarf2_per_objfile->n_type_units))
+      if (cu_index >= (dwarf2_per_objfile->all_comp_units.size ()
+                      + dwarf2_per_objfile->all_type_units.size ()))
        {
          complaint (&symfile_complaints,
                     _(".gdb_index entry has bad CU index"
@@ -5409,7 +5085,7 @@ dw2_expand_marked_cus
          continue;
        }
 
-      per_cu = dw2_get_cutu (dwarf2_per_objfile, cu_index);
+      dwarf2_per_cu_data *per_cu = dwarf2_per_objfile->get_cutu (cu_index);
       dw2_expand_symtabs_matching_one (per_cu, file_matcher,
                                       expansion_notify);
     }
@@ -5439,13 +5115,8 @@ dw_expand_symtabs_matching_file_matcher
   /* The rule is CUs specify all the files, including those used by
      any TU, so there's no need to scan TUs here.  */
 
-  for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+  for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units)
     {
-      int j;
-      struct dwarf2_per_cu_data *per_cu = dw2_get_cu (dwarf2_per_objfile, i);
-      struct quick_file_names *file_data;
-      void **slot;
-
       QUIT;
 
       per_cu->v.quick->mark = 0;
@@ -5454,7 +5125,7 @@ dw_expand_symtabs_matching_file_matcher
       if (per_cu->v.quick->compunit_symtab)
        continue;
 
-      file_data = dw2_get_file_names (per_cu);
+      quick_file_names *file_data = dw2_get_file_names (per_cu);
       if (file_data == NULL)
        continue;
 
@@ -5466,7 +5137,7 @@ dw_expand_symtabs_matching_file_matcher
          continue;
        }
 
-      for (j = 0; j < file_data->num_file_names; ++j)
+      for (int j = 0; j < file_data->num_file_names; ++j)
        {
          const char *this_real_name;
 
@@ -5491,10 +5162,10 @@ dw_expand_symtabs_matching_file_matcher
            }
        }
 
-      slot = htab_find_slot (per_cu->v.quick->mark
-                            ? visited_found.get ()
-                            : visited_not_found.get (),
-                            file_data, INSERT);
+      void **slot = htab_find_slot (per_cu->v.quick->mark
+                                   ? visited_found.get ()
+                                   : visited_not_found.get (),
+                                   file_data, INSERT);
       *slot = file_data;
     }
 }
@@ -5604,10 +5275,8 @@ dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
         by any TU, so there's no need to scan TUs here.  We can
         ignore file names coming from already-expanded CUs.  */
 
-      for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+      for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units)
        {
-         dwarf2_per_cu_data *per_cu = dw2_get_cutu (dwarf2_per_objfile, i);
-
          if (per_cu->v.quick->compunit_symtab)
            {
              void **slot = htab_find_slot (visited.get (),
@@ -5618,21 +5287,17 @@ dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
            }
        }
 
-      for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+      for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units)
        {
-         dwarf2_per_cu_data *per_cu = dw2_get_cu (dwarf2_per_objfile, i);
-         struct quick_file_names *file_data;
-         void **slot;
-
          /* We only need to look at symtabs not already expanded.  */
          if (per_cu->v.quick->compunit_symtab)
            continue;
 
-         file_data = dw2_get_file_names (per_cu);
+         quick_file_names *file_data = dw2_get_file_names (per_cu);
          if (file_data == NULL)
            continue;
 
-         slot = htab_find_slot (visited.get (), file_data, INSERT);
+         void **slot = htab_find_slot (visited.get (), file_data, INSERT);
          if (*slot)
            {
              /* Already visited.  */
@@ -5880,7 +5545,7 @@ static void
 create_cus_from_debug_names_list (struct dwarf2_per_objfile *dwarf2_per_objfile,
                                  const mapped_debug_names &map,
                                  dwarf2_section_info &section,
-                                 bool is_dwz, int base_offset)
+                                 bool is_dwz)
 {
   sect_offset sect_off_prev;
   for (uint32_t i = 0; i <= map.cu_count; ++i)
@@ -5899,9 +5564,10 @@ create_cus_from_debug_names_list (struct dwarf2_per_objfile *dwarf2_per_objfile,
       if (i >= 1)
        {
          const ULONGEST length = sect_off_next - sect_off_prev;
-         dwarf2_per_objfile->all_comp_units[base_offset + (i - 1)]
+         dwarf2_per_cu_data *per_cu
            = create_cu_from_index_list (dwarf2_per_objfile, &section, is_dwz,
                                         sect_off_prev, length);
+         dwarf2_per_objfile->all_comp_units.push_back (per_cu);
        }
       sect_off_prev = sect_off_next;
     }
@@ -5915,25 +5581,19 @@ create_cus_from_debug_names (struct dwarf2_per_objfile *dwarf2_per_objfile,
                             const mapped_debug_names &map,
                             const mapped_debug_names &dwz_map)
 {
-  struct objfile *objfile = dwarf2_per_objfile->objfile;
-
-  dwarf2_per_objfile->n_comp_units = map.cu_count + dwz_map.cu_count;
-  dwarf2_per_objfile->all_comp_units
-    = XOBNEWVEC (&objfile->objfile_obstack, struct dwarf2_per_cu_data *,
-                dwarf2_per_objfile->n_comp_units);
+  gdb_assert (dwarf2_per_objfile->all_comp_units.empty ());
+  dwarf2_per_objfile->all_comp_units.reserve (map.cu_count + dwz_map.cu_count);
 
   create_cus_from_debug_names_list (dwarf2_per_objfile, map,
                                    dwarf2_per_objfile->info,
-                                   false /* is_dwz */,
-                                   0 /* base_offset */);
+                                   false /* is_dwz */);
 
   if (dwz_map.cu_count == 0)
     return;
 
   dwz_file *dwz = dwarf2_get_dwz_file (dwarf2_per_objfile);
   create_cus_from_debug_names_list (dwarf2_per_objfile, dwz_map, dwz->info,
-                                   true /* is_dwz */,
-                                   map.cu_count /* base_offset */);
+                                   true /* is_dwz */);
 }
 
 /* Read .debug_names.  If everything went ok, initialize the "quick"
@@ -5994,27 +5654,11 @@ dwarf2_read_debug_names (struct dwarf2_per_objfile *dwarf2_per_objfile)
   *dwarf2_per_objfile->debug_names_table = std::move (local_map);
   dwarf2_per_objfile->using_index = 1;
   dwarf2_per_objfile->quick_file_names_table =
-    create_quick_file_names_table (dwarf2_per_objfile->n_comp_units);
+    create_quick_file_names_table (dwarf2_per_objfile->all_comp_units.size ());
 
   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.  */
 
@@ -6250,7 +5894,7 @@ dw2_debug_names_iterator::next ()
        {
        case DW_IDX_compile_unit:
          /* Don't crash on bad data.  */
-         if (ull >= dwarf2_per_objfile->n_comp_units)
+         if (ull >= dwarf2_per_objfile->all_comp_units.size ())
            {
              complaint (&symfile_complaints,
                         _(".debug_names entry has bad CU index %s"
@@ -6259,11 +5903,11 @@ dw2_debug_names_iterator::next ()
                         objfile_name (dwarf2_per_objfile->objfile));
              continue;
            }
-         per_cu = dw2_get_cutu (dwarf2_per_objfile, ull);
+         per_cu = dwarf2_per_objfile->get_cutu (ull);
          break;
        case DW_IDX_type_unit:
          /* Don't crash on bad data.  */
-         if (ull >= dwarf2_per_objfile->n_type_units)
+         if (ull >= dwarf2_per_objfile->all_type_units.size ())
            {
              complaint (&symfile_complaints,
                         _(".debug_names entry has bad TU index %s"
@@ -6272,8 +5916,7 @@ dw2_debug_names_iterator::next ()
                         objfile_name (dwarf2_per_objfile->objfile));
              continue;
            }
-         per_cu = dw2_get_cutu (dwarf2_per_objfile,
-                                dwarf2_per_objfile->n_comp_units + ull);
+         per_cu = &dwarf2_per_objfile->get_tu (ull)->per_cu;
          break;
        case DW_IDX_GNU_internal:
          if (!m_map.augmentation_is_gdb)
@@ -6541,18 +6184,17 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
      expanded anyway.  */
   if ((objfile->flags & OBJF_READNOW))
     {
-      int i;
-
       dwarf2_per_objfile->using_index = 1;
       create_all_comp_units (dwarf2_per_objfile);
       create_all_type_units (dwarf2_per_objfile);
-      dwarf2_per_objfile->quick_file_names_table =
-       create_quick_file_names_table (dwarf2_per_objfile->n_comp_units);
+      dwarf2_per_objfile->quick_file_names_table
+       = create_quick_file_names_table
+           (dwarf2_per_objfile->all_comp_units.size ());
 
-      for (i = 0; i < (dwarf2_per_objfile->n_comp_units
-                      + dwarf2_per_objfile->n_type_units); ++i)
+      for (int i = 0; i < (dwarf2_per_objfile->all_comp_units.size ()
+                          + dwarf2_per_objfile->all_type_units.size ()); ++i)
        {
-         dwarf2_per_cu_data *per_cu = dw2_get_cutu (dwarf2_per_objfile, i);
+         dwarf2_per_cu_data *per_cu = dwarf2_per_objfile->get_cutu (i);
 
          per_cu->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack,
                                            struct dwarf2_per_cu_quick_data);
@@ -6571,7 +6213,7 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
       return true;
     }
 
-  if (dwarf2_read_index (objfile))
+  if (dwarf2_read_index (dwarf2_per_objfile))
     {
       *index_kind = dw_index_kind::GDB_INDEX;
       return true;
@@ -6790,10 +6432,10 @@ error_check_comp_unit_head (struct dwarf2_per_objfile *dwarf2_per_objfile,
 
   if (to_underlying (header->abbrev_sect_off)
       >= dwarf2_section_size (dwarf2_per_objfile->objfile, abbrev_section))
-    error (_("Dwarf Error: bad offset (0x%x) in compilation unit header "
-          "(offset 0x%x + 6) [in module %s]"),
-          to_underlying (header->abbrev_sect_off),
-          to_underlying (header->sect_off),
+    error (_("Dwarf Error: bad offset (%s) in compilation unit header "
+          "(offset %s + 6) [in module %s]"),
+          sect_offset_str (header->abbrev_sect_off),
+          sect_offset_str (header->sect_off),
           filename);
 
   /* Cast to ULONGEST to use 64-bit arithmetic when possible to
@@ -6801,8 +6443,8 @@ error_check_comp_unit_head (struct dwarf2_per_objfile *dwarf2_per_objfile,
   if (((ULONGEST) header->sect_off + get_cu_length (header))
       > section->size)
     error (_("Dwarf Error: bad length (0x%x) in compilation unit header "
-          "(offset 0x%x + 0) [in module %s]"),
-          header->length, to_underlying (header->sect_off),
+          "(offset %s + 0) [in module %s]"),
+          header->length, sect_offset_str (header->sect_off),
           filename);
 }
 
@@ -6959,10 +6601,10 @@ static int
 add_signatured_type_cu_to_table (void **slot, void *datum)
 {
   struct signatured_type *sigt = (struct signatured_type *) *slot;
-  struct signatured_type ***datap = (struct signatured_type ***) datum;
+  std::vector<signatured_type *> *all_type_units
+    = (std::vector<signatured_type *> *) datum;
 
-  **datap = sigt;
-  ++*datap;
+  all_type_units->push_back (sigt);
 
   return 1;
 }
@@ -7098,16 +6740,16 @@ create_debug_type_hash_table (struct dwarf2_per_objfile *dwarf2_per_objfile,
            }
 
          complaint (&symfile_complaints,
-                    _("debug type entry at offset 0x%x is duplicate to"
-                      " the entry at offset 0x%x, signature %s"),
-                    to_underlying (sect_off), to_underlying (dup_sect_off),
+                    _("debug type entry at offset %s is duplicate to"
+                      " the entry at offset %s, signature %s"),
+                    sect_offset_str (sect_off), sect_offset_str (dup_sect_off),
                     hex_string (header.signature));
        }
       *slot = dwo_file ? (void *) dwo_tu : (void *) sig_type;
 
       if (dwarf_read_debug > 1)
-       fprintf_unfiltered (gdb_stdlog, "  offset 0x%x, signature %s\n",
-                           to_underlying (sect_off),
+       fprintf_unfiltered (gdb_stdlog, "  offset %s, signature %s\n",
+                           sect_offset_str (sect_off),
                            hex_string (header.signature));
 
       info_ptr += length;
@@ -7151,7 +6793,6 @@ static int
 create_all_type_units (struct dwarf2_per_objfile *dwarf2_per_objfile)
 {
   htab_t types_htab = NULL;
-  struct signatured_type **iter;
 
   create_debug_type_hash_table (dwarf2_per_objfile, NULL,
                                &dwarf2_per_objfile->info, types_htab,
@@ -7166,15 +6807,11 @@ create_all_type_units (struct dwarf2_per_objfile *dwarf2_per_objfile)
 
   dwarf2_per_objfile->signatured_types = types_htab;
 
-  dwarf2_per_objfile->n_type_units
-    = dwarf2_per_objfile->n_allocated_type_units
-    = htab_elements (types_htab);
-  dwarf2_per_objfile->all_type_units =
-    XNEWVEC (struct signatured_type *, dwarf2_per_objfile->n_type_units);
-  iter = &dwarf2_per_objfile->all_type_units[0];
-  htab_traverse_noresize (types_htab, add_signatured_type_cu_to_table, &iter);
-  gdb_assert (iter - &dwarf2_per_objfile->all_type_units[0]
-             == dwarf2_per_objfile->n_type_units);
+  gdb_assert (dwarf2_per_objfile->all_type_units.empty ());
+  dwarf2_per_objfile->all_type_units.reserve (htab_elements (types_htab));
+
+  htab_traverse_noresize (types_htab, add_signatured_type_cu_to_table,
+                         &dwarf2_per_objfile->all_type_units);
 
   return 1;
 }
@@ -7188,27 +6825,15 @@ add_type_unit (struct dwarf2_per_objfile *dwarf2_per_objfile, ULONGEST sig,
               void **slot)
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
-  int n_type_units = dwarf2_per_objfile->n_type_units;
-  struct signatured_type *sig_type;
 
-  gdb_assert (n_type_units <= dwarf2_per_objfile->n_allocated_type_units);
-  ++n_type_units;
-  if (n_type_units > dwarf2_per_objfile->n_allocated_type_units)
-    {
-      if (dwarf2_per_objfile->n_allocated_type_units == 0)
-       dwarf2_per_objfile->n_allocated_type_units = 1;
-      dwarf2_per_objfile->n_allocated_type_units *= 2;
-      dwarf2_per_objfile->all_type_units
-       = XRESIZEVEC (struct signatured_type *,
-                     dwarf2_per_objfile->all_type_units,
-                     dwarf2_per_objfile->n_allocated_type_units);
-      ++dwarf2_per_objfile->tu_stats.nr_all_type_units_reallocs;
-    }
-  dwarf2_per_objfile->n_type_units = n_type_units;
+  if (dwarf2_per_objfile->all_type_units.size ()
+      == dwarf2_per_objfile->all_type_units.capacity ())
+    ++dwarf2_per_objfile->tu_stats.nr_all_type_units_reallocs;
 
-  sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
-                            struct signatured_type);
-  dwarf2_per_objfile->all_type_units[n_type_units - 1] = sig_type;
+  signatured_type *sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+                                             struct signatured_type);
+
+  dwarf2_per_objfile->all_type_units.push_back (sig_type);
   sig_type->signature = sig;
   sig_type->per_cu.is_debug_types = 1;
   if (dwarf2_per_objfile->using_index)
@@ -7558,10 +7183,10 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data *this_cu,
       if (sig_type->signature != cu->header.signature)
        {
          error (_("Dwarf Error: signature mismatch %s vs %s while reading"
-                  " TU at offset 0x%x [in module %s]"),
+                  " TU at offset %s [in module %s]"),
                 hex_string (sig_type->signature),
                 hex_string (cu->header.signature),
-                to_underlying (dwo_unit->sect_off),
+                sect_offset_str (dwo_unit->sect_off),
                 bfd_get_filename (abfd));
        }
       gdb_assert (dwo_unit->sect_off == cu->header.sect_off);
@@ -7694,12 +7319,7 @@ lookup_dwo_unit (struct dwarf2_per_cu_data *this_cu,
 
 /* Subroutine of init_cutu_and_read_dies to simplify it.
    See it for a description of the parameters.
-   Read a TU directly from a DWO file, bypassing the stub.
-
-   Note: This function could be a little bit simpler if we shared cleanups
-   with our caller, init_cutu_and_read_dies.  That's generally a fragile thing
-   to do, so we keep this function self-contained.  Or we could move this
-   into our caller, but it's complex enough already.  */
+   Read a TU directly from a DWO file, bypassing the stub.  */
 
 static void
 init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu,
@@ -7707,9 +7327,8 @@ init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu,
                           die_reader_func_ftype *die_reader_func,
                           void *data)
 {
-  struct dwarf2_cu *cu;
+  std::unique_ptr<dwarf2_cu> new_cu;
   struct signatured_type *sig_type;
-  struct cleanup *cleanups, *free_cu_cleanup = NULL;
   struct die_reader_specs reader;
   const gdb_byte *info_ptr;
   struct die_info *comp_unit_die;
@@ -7722,12 +7341,9 @@ init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu,
   sig_type = (struct signatured_type *) this_cu;
   gdb_assert (sig_type->dwo_unit != NULL);
 
-  cleanups = make_cleanup (null_cleanup, NULL);
-
   if (use_existing_cu && this_cu->cu != NULL)
     {
       gdb_assert (this_cu->cu->dwo_unit == sig_type->dwo_unit);
-      cu = this_cu->cu;
       /* There's no need to do the rereading_dwo_cu handling that
         init_cutu_and_read_dies does since we don't read the stub.  */
     }
@@ -7735,10 +7351,7 @@ init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu,
     {
       /* If !use_existing_cu, this_cu->cu must be NULL.  */
       gdb_assert (this_cu->cu == NULL);
-      cu = XNEW (struct dwarf2_cu);
-      init_one_comp_unit (cu, this_cu);
-      /* If an error occurs while loading, release our storage.  */
-      free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
+      new_cu.reset (new dwarf2_cu (this_cu));
     }
 
   /* A future optimization, if needed, would be to use an existing
@@ -7757,7 +7370,6 @@ init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu,
                              &dwo_abbrev_table) == 0)
     {
       /* Dummy die.  */
-      do_cleanups (cleanups);
       return;
     }
 
@@ -7768,23 +7380,14 @@ init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu,
      but the alternative is making the latter more complex.
      This function is only for the special case of using DWO files directly:
      no point in overly complicating the general case just to handle this.  */
-  if (free_cu_cleanup != NULL)
+  if (new_cu != NULL && keep)
     {
-      if (keep)
-       {
-         /* We've successfully allocated this compilation unit.  Let our
-            caller clean it up when finished with it.  */
-         discard_cleanups (free_cu_cleanup);
-
-         /* Link this CU into read_in_chain.  */
-         this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
-         dwarf2_per_objfile->read_in_chain = this_cu;
-       }
-      else
-       do_cleanups (free_cu_cleanup);
+      /* Link this CU into read_in_chain.  */
+      this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+      dwarf2_per_objfile->read_in_chain = this_cu;
+      /* The chain owns it now.  */
+      new_cu.release ();
     }
-
-  do_cleanups (cleanups);
 }
 
 /* Initialize a CU (or TU) and read its DIEs.
@@ -7820,7 +7423,6 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
   struct die_info *comp_unit_die;
   int has_children;
   struct attribute *attr;
-  struct cleanup *cleanups, *free_cu_cleanup = NULL;
   struct signatured_type *sig_type = NULL;
   struct dwarf2_section_info *abbrev_section;
   /* Non-zero if CU currently points to a DWO file and we need to
@@ -7829,9 +7431,9 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
   int rereading_dwo_cu = 0;
 
   if (dwarf_die_debug)
-    fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset 0x%x\n",
+    fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset %s\n",
                        this_cu->is_debug_types ? "type" : "comp",
-                       to_underlying (this_cu->sect_off));
+                       sect_offset_str (this_cu->sect_off));
 
   if (use_existing_cu)
     gdb_assert (keep);
@@ -7848,8 +7450,6 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
       return;
     }
 
-  cleanups = make_cleanup (null_cleanup, NULL);
-
   /* This is cheap if the section is already read in.  */
   dwarf2_read_section (objfile, section);
 
@@ -7857,6 +7457,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
 
   abbrev_section = get_abbrev_section_for_cu (this_cu);
 
+  std::unique_ptr<dwarf2_cu> new_cu;
   if (use_existing_cu && this_cu->cu != NULL)
     {
       cu = this_cu->cu;
@@ -7873,10 +7474,8 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
     {
       /* If !use_existing_cu, this_cu->cu must be NULL.  */
       gdb_assert (this_cu->cu == NULL);
-      cu = XNEW (struct dwarf2_cu);
-      init_one_comp_unit (cu, this_cu);
-      /* If an error occurs while loading, release our storage.  */
-      free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
+      new_cu.reset (new dwarf2_cu (this_cu));
+      cu = new_cu.get ();
     }
 
   /* Get the header.  */
@@ -7929,10 +7528,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
   /* Skip dummy compilation units.  */
   if (info_ptr >= begin_info_ptr + this_cu->length
       || peek_abbrev_code (abfd, info_ptr) == 0)
-    {
-      do_cleanups (cleanups);
-      return;
-    }
+    return;
 
   /* If we don't have them yet, read the abbrevs for this compilation unit.
      And if we need to read them now, make sure they're freed when we're
@@ -7971,8 +7567,9 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
        {
          complaint (&symfile_complaints,
                     _("compilation unit with DW_AT_GNU_dwo_name"
-                      " has children (offset 0x%x) [in module %s]"),
-                    to_underlying (this_cu->sect_off), bfd_get_filename (abfd));
+                      " has children (offset %s) [in module %s]"),
+                    sect_offset_str (this_cu->sect_off),
+                    bfd_get_filename (abfd));
        }
       dwo_unit = lookup_dwo_unit (this_cu, comp_unit_die);
       if (dwo_unit != NULL)
@@ -7984,7 +7581,6 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
                                      &dwo_abbrev_table) == 0)
            {
              /* Dummy die.  */
-             do_cleanups (cleanups);
              return;
            }
          comp_unit_die = dwo_comp_unit_die;
@@ -8003,23 +7599,14 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
   die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data);
 
   /* Done, clean up.  */
-  if (free_cu_cleanup != NULL)
+  if (new_cu != NULL && keep)
     {
-      if (keep)
-       {
-         /* We've successfully allocated this compilation unit.  Let our
-            caller clean it up when finished with it.  */
-         discard_cleanups (free_cu_cleanup);
-
-         /* Link this CU into read_in_chain.  */
-         this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
-         dwarf2_per_objfile->read_in_chain = this_cu;
-       }
-      else
-       do_cleanups (free_cu_cleanup);
+      /* Link this CU into read_in_chain.  */
+      this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+      dwarf2_per_objfile->read_in_chain = this_cu;
+      /* The chain owns it now.  */
+      new_cu.release ();
     }
-
-  do_cleanups (cleanups);
 }
 
 /* Read CU/TU THIS_CU but do not follow DW_AT_GNU_dwo_name if present.
@@ -8049,17 +7636,15 @@ init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
   struct dwarf2_section_info *section = this_cu->section;
   bfd *abfd = get_section_bfd_owner (section);
   struct dwarf2_section_info *abbrev_section;
-  struct dwarf2_cu cu;
   const gdb_byte *begin_info_ptr, *info_ptr;
   struct die_reader_specs reader;
-  struct cleanup *cleanups;
   struct die_info *comp_unit_die;
   int has_children;
 
   if (dwarf_die_debug)
-    fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset 0x%x\n",
+    fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset %s\n",
                        this_cu->is_debug_types ? "type" : "comp",
-                       to_underlying (this_cu->sect_off));
+                       sect_offset_str (this_cu->sect_off));
 
   gdb_assert (this_cu->cu == NULL);
 
@@ -8070,9 +7655,7 @@ init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
   /* This is cheap if the section is already read in.  */
   dwarf2_read_section (objfile, section);
 
-  init_one_comp_unit (&cu, this_cu);
-
-  cleanups = make_cleanup (free_stack_comp_unit, &cu);
+  struct dwarf2_cu cu (this_cu);
 
   begin_info_ptr = info_ptr = section->buffer + to_underlying (this_cu->sect_off);
   info_ptr = read_and_check_comp_unit_head (dwarf2_per_objfile,
@@ -8087,10 +7670,7 @@ init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
   /* Skip dummy compilation units.  */
   if (info_ptr >= begin_info_ptr + this_cu->length
       || peek_abbrev_code (abfd, info_ptr) == 0)
-    {
-      do_cleanups (cleanups);
-      return;
-    }
+    return;
 
   abbrev_table_up abbrev_table
     = abbrev_table_read_table (dwarf2_per_objfile, abbrev_section,
@@ -8100,8 +7680,6 @@ init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
   info_ptr = read_full_die (&reader, &comp_unit_die, info_ptr, &has_children);
 
   die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data);
-
-  do_cleanups (cleanups);
 }
 
 /* Read a CU/TU, except that this does not look for DW_AT_GNU_dwo_name and
@@ -8437,10 +8015,10 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
       struct gdbarch *gdbarch = get_objfile_arch (objfile);
 
       fprintf_unfiltered (gdb_stdlog,
-                         "Psymtab for %s unit @0x%x: %s - %s"
+                         "Psymtab for %s unit @%s: %s - %s"
                          ", %d global, %d static syms\n",
                          per_cu->is_debug_types ? "type" : "comp",
-                         to_underlying (per_cu->sect_off),
+                         sect_offset_str (per_cu->sect_off),
                          paddress (gdbarch, pst->textlow),
                          paddress (gdbarch, pst->texthigh),
                          pst->n_global_syms, pst->n_static_syms);
@@ -8530,23 +8108,21 @@ build_type_psymtabs_reader (const struct die_reader_specs *reader,
 
 struct tu_abbrev_offset
 {
-  struct signatured_type *sig_type;
+  tu_abbrev_offset (signatured_type *sig_type_, sect_offset abbrev_offset_)
+  : sig_type (sig_type_), abbrev_offset (abbrev_offset_)
+  {}
+
+  signatured_type *sig_type;
   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.
@@ -8571,16 +8147,13 @@ 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.  */
   gdb_assert (dwarf2_per_objfile->type_unit_groups == NULL);
 
-  if (dwarf2_per_objfile->n_type_units == 0)
+  if (dwarf2_per_objfile->all_type_units.empty ())
     return;
 
   /* TUs typically share abbrev tables, and there can be way more TUs than
@@ -8607,33 +8180,27 @@ 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);
-  for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
-    {
-      struct signatured_type *sig_type = dwarf2_per_objfile->all_type_units[i];
+  std::vector<tu_abbrev_offset> sorted_by_abbrev;
+  sorted_by_abbrev.reserve (dwarf2_per_objfile->all_type_units.size ());
 
-      sorted_by_abbrev[i].sig_type = sig_type;
-      sorted_by_abbrev[i].abbrev_offset =
-       read_abbrev_offset (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);
+  for (signatured_type *sig_type : dwarf2_per_objfile->all_type_units)
+    sorted_by_abbrev.emplace_back
+      (sig_type, read_abbrev_offset (dwarf2_per_objfile,
+                                    sig_type->per_cu.section,
+                                    sig_type->per_cu.sect_off));
+
+  std::sort (sorted_by_abbrev.begin (), sorted_by_abbrev.end (),
+            sort_tu_by_abbrev_offset);
 
   abbrev_offset = (sect_offset) ~(unsigned) 0;
 
-  for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
+  for (const tu_abbrev_offset &tu : sorted_by_abbrev)
     {
-      const struct tu_abbrev_offset *tu = &sorted_by_abbrev[i];
-
       /* Switch to the next abbrev table if necessary.  */
       if (abbrev_table == NULL
-         || tu->abbrev_offset != abbrev_offset)
+         || tu.abbrev_offset != abbrev_offset)
        {
-         abbrev_offset = tu->abbrev_offset;
+         abbrev_offset = tu.abbrev_offset;
          abbrev_table =
            abbrev_table_read_table (dwarf2_per_objfile,
                                     &dwarf2_per_objfile->abbrev,
@@ -8641,11 +8208,9 @@ build_type_psymtabs_1 (struct dwarf2_per_objfile *dwarf2_per_objfile)
          ++tu_stats->nr_uniq_abbrev_tables;
        }
 
-      init_cutu_and_read_dies (&tu->sig_type->per_cu, abbrev_table.get (),
+      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.  */
@@ -8656,8 +8221,8 @@ print_tu_stats (struct dwarf2_per_objfile *dwarf2_per_objfile)
   struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
 
   fprintf_unfiltered (gdb_stdlog, "Type unit statistics:\n");
-  fprintf_unfiltered (gdb_stdlog, "  %d TUs\n",
-                     dwarf2_per_objfile->n_type_units);
+  fprintf_unfiltered (gdb_stdlog, "  %zu TUs\n",
+                     dwarf2_per_objfile->all_type_units.size ());
   fprintf_unfiltered (gdb_stdlog, "  %d uniq abbrev tables\n",
                      tu_stats->nr_uniq_abbrev_tables);
   fprintf_unfiltered (gdb_stdlog, "  %d symtabs from stmt_list entries\n",
@@ -8795,18 +8360,14 @@ process_skeletonless_type_units (struct dwarf2_per_objfile *dwarf2_per_objfile)
 static void
 set_partial_user (struct dwarf2_per_objfile *dwarf2_per_objfile)
 {
-  int i;
-
-  for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+  for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units)
     {
-      struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (dwarf2_per_objfile, i);
       struct partial_symtab *pst = per_cu->v.psymtab;
-      int j;
 
       if (pst == NULL)
        continue;
 
-      for (j = 0; j < pst->number_of_dependencies; ++j)
+      for (int j = 0; j < pst->number_of_dependencies; ++j)
        {
          /* Set the 'user' field only if it is not already set.  */
          if (pst->dependencies[j]->user == NULL)
@@ -8821,8 +8382,6 @@ set_partial_user (struct dwarf2_per_objfile *dwarf2_per_objfile)
 static void
 dwarf2_build_psymtabs_hard (struct dwarf2_per_objfile *dwarf2_per_objfile)
 {
-  struct cleanup *back_to;
-  int i;
   struct objfile *objfile = dwarf2_per_objfile->objfile;
 
   if (dwarf_read_debug)
@@ -8837,7 +8396,7 @@ dwarf2_build_psymtabs_hard (struct dwarf2_per_objfile *dwarf2_per_objfile)
 
   /* Any cached compilation units will be linked by the per-objfile
      read_in_chain.  Make sure to free them when we're done.  */
-  back_to = make_cleanup (free_cached_comp_units, dwarf2_per_objfile);
+  free_cached_comp_units freer (dwarf2_per_objfile);
 
   build_type_psymtabs (dwarf2_per_objfile);
 
@@ -8851,12 +8410,8 @@ dwarf2_build_psymtabs_hard (struct dwarf2_per_objfile *dwarf2_per_objfile)
     = make_scoped_restore (&objfile->psymtabs_addrmap,
                           addrmap_create_mutable (&temp_obstack));
 
-  for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
-    {
-      struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (dwarf2_per_objfile, i);
-
-      process_psymtab_comp_unit (per_cu, 0, language_minimal);
-    }
+  for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units)
+    process_psymtab_comp_unit (per_cu, 0, language_minimal);
 
   /* This has to wait until we read the CUs, we need the list of DWOs.  */
   process_skeletonless_type_units (dwarf2_per_objfile);
@@ -8878,8 +8433,6 @@ dwarf2_build_psymtabs_hard (struct dwarf2_per_objfile *dwarf2_per_objfile)
   /* At this point we want to keep the address map.  */
   save_psymtabs_addrmap.release ();
 
-  do_cleanups (back_to);
-
   if (dwarf_read_debug)
     fprintf_unfiltered (gdb_stdlog, "Done building psymtabs of %s\n",
                        objfile_name (objfile));
@@ -8919,10 +8472,7 @@ static void
 read_comp_units_from_section (struct dwarf2_per_objfile *dwarf2_per_objfile,
                              struct dwarf2_section_info *section,
                              struct dwarf2_section_info *abbrev_section,
-                             unsigned int is_dwz,
-                             int *n_allocated,
-                             int *n_comp_units,
-                             struct dwarf2_per_cu_data ***all_comp_units)
+                             unsigned int is_dwz)
 {
   const gdb_byte *info_ptr;
   struct objfile *objfile = dwarf2_per_objfile->objfile;
@@ -8970,14 +8520,7 @@ read_comp_units_from_section (struct dwarf2_per_objfile *dwarf2_per_objfile,
       this_cu->dwarf2_per_objfile = dwarf2_per_objfile;
       this_cu->section = section;
 
-      if (*n_comp_units == *n_allocated)
-       {
-         *n_allocated *= 2;
-         *all_comp_units = XRESIZEVEC (struct dwarf2_per_cu_data *,
-                                       *all_comp_units, *n_allocated);
-       }
-      (*all_comp_units)[*n_comp_units] = this_cu;
-      ++*n_comp_units;
+      dwarf2_per_objfile->all_comp_units.push_back (this_cu);
 
       info_ptr = info_ptr + this_cu->length;
     }
@@ -8989,33 +8532,14 @@ read_comp_units_from_section (struct dwarf2_per_objfile *dwarf2_per_objfile,
 static void
 create_all_comp_units (struct dwarf2_per_objfile *dwarf2_per_objfile)
 {
-  int n_allocated;
-  int n_comp_units;
-  struct dwarf2_per_cu_data **all_comp_units;
-  struct dwz_file *dwz;
-  struct objfile *objfile = dwarf2_per_objfile->objfile;
-
-  n_comp_units = 0;
-  n_allocated = 10;
-  all_comp_units = XNEWVEC (struct dwarf2_per_cu_data *, n_allocated);
-
+  gdb_assert (dwarf2_per_objfile->all_comp_units.empty ());
   read_comp_units_from_section (dwarf2_per_objfile, &dwarf2_per_objfile->info,
-                               &dwarf2_per_objfile->abbrev, 0,
-                               &n_allocated, &n_comp_units, &all_comp_units);
+                               &dwarf2_per_objfile->abbrev, 0);
 
-  dwz = dwarf2_get_dwz_file (dwarf2_per_objfile);
+  dwz_file *dwz = dwarf2_get_dwz_file (dwarf2_per_objfile);
   if (dwz != NULL)
     read_comp_units_from_section (dwarf2_per_objfile, &dwz->info, &dwz->abbrev,
-                                 1, &n_allocated, &n_comp_units,
-                                 &all_comp_units);
-
-  dwarf2_per_objfile->all_comp_units = XOBNEWVEC (&objfile->objfile_obstack,
-                                                 struct dwarf2_per_cu_data *,
-                                                 n_comp_units);
-  memcpy (dwarf2_per_objfile->all_comp_units, all_comp_units,
-         n_comp_units * sizeof (struct dwarf2_per_cu_data *));
-  xfree (all_comp_units);
-  dwarf2_per_objfile->n_comp_units = n_comp_units;
+                                 1);
 }
 
 /* Process all loaded DIEs for compilation unit CU, starting at
@@ -9039,7 +8563,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
@@ -9072,7 +8596,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;
@@ -9175,7 +8700,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);
 
@@ -9216,8 +8741,8 @@ partial_die_parent_scope (struct partial_die_info *pdi,
         function-local names?  For partial symbols, we should probably be
         ignoring them.  */
       complaint (&symfile_complaints,
-                _("unhandled containing DIE tag %d for DIE at %d"),
-                parent->tag, to_underlying (pdi->sect_off));
+                _("unhandled containing DIE tag %d for DIE at %s"),
+                parent->tag, sect_offset_str (pdi->sect_off));
       parent->scope = grandparent_scope;
     }
 
@@ -9240,7 +8765,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)
        {
@@ -9549,7 +9074,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)
@@ -9614,9 +9139,9 @@ peek_die_abbrev (const die_reader_specs &reader,
   if (!abbrev)
     {
       error (_("Dwarf Error: Could not find abbrev number %d in %s"
-              " at offset 0x%x [in module %s]"),
+              " at offset %s [in module %s]"),
             abbrev_number, cu->per_cu->is_debug_types ? "TU" : "CU",
-            to_underlying (cu->header.sect_off), bfd_get_filename (abfd));
+            sect_offset_str (cu->header.sect_off), bfd_get_filename (abfd));
     }
 
   return abbrev;
@@ -9953,17 +9478,17 @@ process_queue (struct dwarf2_per_objfile *dwarf2_per_objfile)
              struct signatured_type *sig_type =
                (struct signatured_type *) per_cu;
 
-             sprintf (buf, "TU %s at offset 0x%x",
+             sprintf (buf, "TU %s at offset %s",
                       hex_string (sig_type->signature),
-                      to_underlying (per_cu->sect_off));
+                      sect_offset_str (per_cu->sect_off));
              /* There can be 100s of TUs.
                 Only print them in verbose mode.  */
              debug_print_threshold = 2;
            }
          else
            {
-             sprintf (buf, "CU at offset 0x%x",
-                      to_underlying (per_cu->sect_off));
+             sprintf (buf, "CU at offset %s",
+                      sect_offset_str (per_cu->sect_off));
              debug_print_threshold = 1;
            }
 
@@ -9993,35 +9518,6 @@ process_queue (struct dwarf2_per_objfile *dwarf2_per_objfile)
     }
 }
 
-/* Free all allocated queue entries.  This function only releases anything if
-   an error was thrown; if the queue was processed then it would have been
-   freed as we went along.  */
-
-static void
-dwarf2_release_queue (void *dummy)
-{
-  struct dwarf2_queue_item *item, *last;
-
-  item = dwarf2_queue;
-  while (item)
-    {
-      /* Anything still marked queued is likely to be in an
-        inconsistent state, so discard it.  */
-      if (item->per_cu->queued)
-       {
-         if (item->per_cu->cu != NULL)
-           free_one_cached_comp_unit (item->per_cu);
-         item->per_cu->queued = 0;
-       }
-
-      last = item;
-      item = item->next;
-      xfree (last);
-    }
-
-  dwarf2_queue = dwarf2_queue_tail = NULL;
-}
-
 /* Read in full symbols for PST, and anything it depends on.  */
 
 static void
@@ -10152,20 +9648,7 @@ add_to_method_list (struct type *type, int fnfield_index, int index,
   mi.index = index;
   mi.name = name;
   mi.die = die;
-  VEC_safe_push (delayed_method_info, cu->method_list, &mi);
-}
-
-/* A cleanup for freeing the delayed method list.  */
-
-static void
-free_delayed_list (void *ptr)
-{
-  struct dwarf2_cu *cu = (struct dwarf2_cu *) ptr;
-  if (cu->method_list != NULL)
-    {
-      VEC_free (delayed_method_info, cu->method_list);
-      cu->method_list = NULL;
-    }
+  cu->method_list.push_back (mi);
 }
 
 /* Check whether [PHYSNAME, PHYSNAME+LEN) ends with a modifier like
@@ -10194,21 +9677,18 @@ check_modifier (const char *physname, size_t &len, const char (&mod)[N])
 static void
 compute_delayed_physnames (struct dwarf2_cu *cu)
 {
-  int i;
-  struct delayed_method_info *mi;
-
   /* Only C++ delays computing physnames.  */
-  if (VEC_empty (delayed_method_info, cu->method_list))
+  if (cu->method_list.empty ())
     return;
   gdb_assert (cu->language == language_cplus);
 
-  for (i = 0; VEC_iterate (delayed_method_info, cu->method_list, i, mi) ; ++i)
+  for (struct delayed_method_info &mi : cu->method_list)
     {
       const char *physname;
       struct fn_fieldlist *fn_flp
-       = &TYPE_FN_FIELDLIST (mi->type, mi->fnfield_index);
-      physname = dwarf2_physname (mi->name, mi->die, cu);
-      TYPE_FN_FIELD_PHYSNAME (fn_flp->fn_fields, mi->index)
+       = &TYPE_FN_FIELDLIST (mi.type, mi.fnfield_index);
+      physname = dwarf2_physname (mi.name, mi.die, cu);
+      TYPE_FN_FIELD_PHYSNAME (fn_flp->fn_fields, mi.index)
        = physname ? physname : "";
 
       /* Since there's no tag to indicate whether a method is a
@@ -10223,14 +9703,17 @@ compute_delayed_physnames (struct dwarf2_cu *cu)
              if (physname[len] == ')') /* shortcut */
                break;
              else if (check_modifier (physname, len, " const"))
-               TYPE_FN_FIELD_CONST (fn_flp->fn_fields, mi->index) = 1;
+               TYPE_FN_FIELD_CONST (fn_flp->fn_fields, mi.index) = 1;
              else if (check_modifier (physname, len, " volatile"))
-               TYPE_FN_FIELD_VOLATILE (fn_flp->fn_fields, mi->index) = 1;
+               TYPE_FN_FIELD_VOLATILE (fn_flp->fn_fields, mi.index) = 1;
              else
                break;
            }
        }
     }
+
+  /* The list is no longer needed.  */
+  cu->method_list.clear ();
 }
 
 /* Go objects should be embedded in a DW_TAG_module DIE,
@@ -10313,6 +9796,317 @@ 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);
+      set_type_align (union_type, TYPE_RAW_ALIGN (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);
+      set_type_align (union_type, TYPE_RAW_ALIGN (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_CODE (disr_type) != TYPE_CODE_STRUCT)
+           {
+             /* All fields of a true enum will be structs.  */
+             return;
+           }
+         else if (TYPE_NFIELDS (disr_type) == 0)
+           {
+             /* Could be data-less variant, so keep going.  */
+             disr_type = nullptr;
+           }
+         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);
+      set_type_align (union_type, TYPE_RAW_ALIGN (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, if it exists.  */
+         struct type *sub_type = TYPE_FIELD_TYPE (union_type, i);
+         if (TYPE_NFIELDS (sub_type) > 0)
+           {
+             --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.  */
 
@@ -10468,7 +10262,6 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   CORE_ADDR lowpc, highpc;
   struct compunit_symtab *cust;
-  struct cleanup *delayed_list_cleanup;
   CORE_ADDR baseaddr;
   struct block *static_block;
   CORE_ADDR addr;
@@ -10477,7 +10270,9 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
 
   buildsym_init ();
   scoped_free_pendings free_pending;
-  delayed_list_cleanup = make_cleanup (free_delayed_list, cu);
+
+  /* Clear the list here in case something was left over.  */
+  cu->method_list.clear ();
 
   cu->list_in_scope = &file_symbols;
 
@@ -10495,7 +10290,9 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
      should be complete, and it should now be safe to compute all of the
      physnames.  */
   compute_delayed_physnames (cu);
-  do_cleanups (delayed_list_cleanup);
+
+  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
@@ -10571,7 +10368,6 @@ process_full_type_unit (struct dwarf2_per_cu_data *per_cu,
   struct dwarf2_per_objfile *dwarf2_per_objfile = per_cu->dwarf2_per_objfile;
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct compunit_symtab *cust;
-  struct cleanup *delayed_list_cleanup;
   struct signatured_type *sig_type;
 
   gdb_assert (per_cu->is_debug_types);
@@ -10579,7 +10375,9 @@ process_full_type_unit (struct dwarf2_per_cu_data *per_cu,
 
   buildsym_init ();
   scoped_free_pendings free_pending;
-  delayed_list_cleanup = make_cleanup (free_delayed_list, cu);
+
+  /* Clear the list here in case something was left over.  */
+  cu->method_list.clear ();
 
   cu->list_in_scope = &file_symbols;
 
@@ -10597,7 +10395,9 @@ process_full_type_unit (struct dwarf2_per_cu_data *per_cu,
      should be complete, and it should now be safe to compute all of the
      physnames.  */
   compute_delayed_physnames (cu);
-  do_cleanups (delayed_list_cleanup);
+
+  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
@@ -10778,7 +10578,8 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       cu->processing_has_namespace_info = 1;
       if (read_namespace_alias (die, cu))
        break;
-      /* The declaration is not a global namespace alias: fall through.  */
+      /* The declaration is not a global namespace alias.  */
+      /* Fall through.  */
     case DW_TAG_imported_module:
       cu->processing_has_namespace_info = 1;
       if (die->child != NULL && (die->tag == DW_TAG_imported_declaration
@@ -11072,7 +10873,6 @@ dwarf2_compute_name (const char *name,
                      opts.raw = 1;
                      value_print (v, &buf, &opts);
                      release_value (v);
-                     value_free (v);
                    }
                }
 
@@ -11185,16 +10985,12 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   gdb::unique_xmalloc_ptr<char> demangled;
   if (mangled != NULL)
     {
-      /* Use DMGL_RET_DROP for C++ template functions to suppress their return
-        type.  It is easier for GDB users to search for such functions as
-        `name(params)' than `long name(params)'.  In such case the minimal
-        symbol names do not match the full symbol names but for template
-        functions there is never a need to look up their definition from their
-        declaration so the only disadvantage remains the minimal symbol
-        variant `long name(params)' does not have the proper inferior type.
-        */
 
-      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.
@@ -11202,6 +10998,14 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
        }
       else
        {
+         /* Use DMGL_RET_DROP for C++ template functions to suppress
+            their return type.  It is easier for GDB users to search
+            for such functions as `name(params)' than `long name(params)'.
+            In such case the minimal symbol names do not match the full
+            symbol names but for template functions there is never a need
+            to look up their definition from their declaration so
+            the only disadvantage remains the minimal symbol variant
+            `long name(params)' does not have the proper inferior type.  */
          demangled.reset (gdb_demangle (mangled,
                                         (DMGL_PARAMS | DMGL_ANSI
                                          | DMGL_RET_DROP)));
@@ -11227,8 +11031,8 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
 
          complaint (&symfile_complaints,
                     _("Computed physname <%s> does not match demangled <%s> "
-                      "(from linkage <%s>) - DIE at 0x%x [in module %s]"),
-                    physname, canon, mangled, to_underlying (die->sect_off),
+                      "(from linkage <%s>) - DIE at %s [in module %s]"),
+                    physname, canon, mangled, sect_offset_str (die->sect_off),
                     objfile_name (objfile));
 
          /* Prefer DW_AT_linkage_name (in the CANON form) - when it
@@ -11290,8 +11094,8 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
       if (num == MAX_NESTED_IMPORTED_DECLARATIONS)
        {
          complaint (&symfile_complaints,
-                    _("DIE at 0x%x has too many recursively imported "
-                      "declarations"), to_underlying (d->sect_off));
+                    _("DIE at %s has too many recursively imported "
+                      "declarations"), sect_offset_str (d->sect_off));
          return 0;
        }
 
@@ -11434,8 +11238,9 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
          {
            complaint (&symfile_complaints,
                       _("child DW_TAG_imported_declaration expected "
-                        "- DIE at 0x%x [in module %s]"),
-                      to_underlying (child_die->sect_off), objfile_name (objfile));
+                        "- DIE at %s [in module %s]"),
+                      sect_offset_str (child_die->sect_off),
+                      objfile_name (objfile));
            continue;
          }
 
@@ -11455,8 +11260,9 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
          {
            complaint (&symfile_complaints,
                       _("child DW_TAG_imported_declaration has unknown "
-                        "imported name - DIE at 0x%x [in module %s]"),
-                      to_underlying (child_die->sect_off), objfile_name (objfile));
+                        "imported name - DIE at %s [in module %s]"),
+                      sect_offset_str (child_die->sect_off),
+                      objfile_name (objfile));
            continue;
          }
 
@@ -11998,9 +11804,9 @@ create_dwo_cu_reader (const struct die_reader_specs *reader,
   if (attr == NULL)
     {
       complaint (&symfile_complaints,
-                _("Dwarf Error: debug entry at offset 0x%x is missing"
+                _("Dwarf Error: debug entry at offset %s is missing"
                   " its dwo_id [in module %s]"),
-                to_underlying (sect_off), dwo_file->dwo_name);
+                sect_offset_str (sect_off), dwo_file->dwo_name);
       return;
     }
 
@@ -12011,8 +11817,8 @@ create_dwo_cu_reader (const struct die_reader_specs *reader,
   dwo_unit->length = cu->per_cu->length;
 
   if (dwarf_read_debug)
-    fprintf_unfiltered (gdb_stdlog, "  offset 0x%x, dwo_id %s\n",
-                       to_underlying (sect_off),
+    fprintf_unfiltered (gdb_stdlog, "  offset %s, dwo_id %s\n",
+                       sect_offset_str (sect_off),
                        hex_string (dwo_unit->signature));
 }
 
@@ -12079,9 +11885,9 @@ create_cus_hash_table (struct dwarf2_per_objfile *dwarf2_per_objfile,
          sect_offset dup_sect_off = dup_cu->sect_off;
 
          complaint (&symfile_complaints,
-                    _("debug cu entry at offset 0x%x is duplicate to"
-                      " the entry at offset 0x%x, signature %s"),
-                    to_underlying (sect_off), to_underlying (dup_sect_off),
+                    _("debug cu entry at offset %s is duplicate to"
+                      " the entry at offset %s, signature %s"),
+                    sect_offset_str (sect_off), sect_offset_str (dup_sect_off),
                     hex_string (dwo_unit->signature));
        }
       *slot = (void *)dwo_unit;
@@ -12918,36 +12724,41 @@ static gdb_bfd_ref_ptr
 try_open_dwop_file (struct dwarf2_per_objfile *dwarf2_per_objfile,
                    const char *file_name, int is_dwp, int search_cwd)
 {
-  int desc, flags;
-  char *absolute_name;
+  int desc;
   /* Blech.  OPF_TRY_CWD_FIRST also disables searching the path list if
      FILE_NAME contains a '/'.  So we can't use it.  Instead prepend "."
      to debug_file_directory.  */
-  char *search_path;
+  const char *search_path;
   static const char dirname_separator_string[] = { DIRNAME_SEPARATOR, '\0' };
 
+  gdb::unique_xmalloc_ptr<char> search_path_holder;
   if (search_cwd)
     {
       if (*debug_file_directory != '\0')
-       search_path = concat (".", dirname_separator_string,
-                             debug_file_directory, (char *) NULL);
+       {
+         search_path_holder.reset (concat (".", dirname_separator_string,
+                                           debug_file_directory,
+                                           (char *) NULL));
+         search_path = search_path_holder.get ();
+       }
       else
-       search_path = xstrdup (".");
+       search_path = ".";
     }
   else
-    search_path = xstrdup (debug_file_directory);
+    search_path = debug_file_directory;
 
-  flags = OPF_RETURN_REALPATH;
+  openp_flags flags = OPF_RETURN_REALPATH;
   if (is_dwp)
     flags |= OPF_SEARCH_IN_PATH;
+
+  gdb::unique_xmalloc_ptr<char> absolute_name;
   desc = openp (search_path, flags, file_name,
                O_RDONLY | O_BINARY, &absolute_name);
-  xfree (search_path);
   if (desc < 0)
     return NULL;
 
-  gdb_bfd_ref_ptr sym_bfd (gdb_bfd_open (absolute_name, gnutarget, desc));
-  xfree (absolute_name);
+  gdb_bfd_ref_ptr sym_bfd (gdb_bfd_open (absolute_name.get (),
+                                        gnutarget, desc));
   if (sym_bfd == NULL)
     return NULL;
   bfd_set_cacheable (sym_bfd.get (), 1);
@@ -13078,8 +12889,6 @@ open_and_init_dwo_file (struct dwarf2_per_cu_data *per_cu,
 {
   struct dwarf2_per_objfile *dwarf2_per_objfile = per_cu->dwarf2_per_objfile;
   struct objfile *objfile = dwarf2_per_objfile->objfile;
-  struct dwo_file *dwo_file;
-  struct cleanup *cleanups;
 
   gdb_bfd_ref_ptr dbfd (open_dwo_file (dwarf2_per_objfile, dwo_name, comp_dir));
   if (dbfd == NULL)
@@ -13088,32 +12897,28 @@ open_and_init_dwo_file (struct dwarf2_per_cu_data *per_cu,
        fprintf_unfiltered (gdb_stdlog, "DWO file not found: %s\n", dwo_name);
       return NULL;
     }
-  dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_file);
+
+  /* We use a unique pointer here, despite the obstack allocation,
+     because a dwo_file needs some cleanup if it is abandoned.  */
+  dwo_file_up dwo_file (OBSTACK_ZALLOC (&objfile->objfile_obstack,
+                                       struct dwo_file));
   dwo_file->dwo_name = dwo_name;
   dwo_file->comp_dir = comp_dir;
   dwo_file->dbfd = dbfd.release ();
 
-  free_dwo_file_cleanup_data *cleanup_data = XNEW (free_dwo_file_cleanup_data);
-  cleanup_data->dwo_file = dwo_file;
-  cleanup_data->dwarf2_per_objfile = dwarf2_per_objfile;
-
-  cleanups = make_cleanup (free_dwo_file_cleanup, cleanup_data);
-
   bfd_map_over_sections (dwo_file->dbfd, dwarf2_locate_dwo_sections,
                         &dwo_file->sections);
 
   create_cus_hash_table (dwarf2_per_objfile, *dwo_file, dwo_file->sections.info,
                         dwo_file->cus);
 
-  create_debug_types_hash_table (dwarf2_per_objfile, dwo_file,
+  create_debug_types_hash_table (dwarf2_per_objfile, dwo_file.get (),
                                 dwo_file->sections.types, dwo_file->tus);
 
-  discard_cleanups (cleanups);
-
   if (dwarf_read_debug)
     fprintf_unfiltered (gdb_stdlog, "DWO file found: %s\n", dwo_name);
 
-  return dwo_file;
+  return dwo_file.release ();
 }
 
 /* This function is mapped across the sections and remembers the offset and
@@ -13527,12 +13332,12 @@ lookup_dwo_cutu (struct dwarf2_per_cu_data *this_unit,
       dwp_text = string_printf (" [in DWP file %s]",
                                lbasename (dwp_file->name));
 
-    warning (_("Could not find DWO %s %s(%s)%s referenced by %s at offset 0x%x"
+    warning (_("Could not find DWO %s %s(%s)%s referenced by %s at offset %s"
               " [in module %s]"),
             kind, dwo_name, hex_string (signature),
             dwp_text.c_str (),
             this_unit->is_debug_types ? "TU" : "CU",
-            to_underlying (this_unit->sect_off), objfile_name (objfile));
+            sect_offset_str (this_unit->sect_off), objfile_name (objfile));
   }
   return NULL;
 }
@@ -13608,42 +13413,25 @@ queue_and_load_all_dwo_tus (struct dwarf2_per_cu_data *per_cu)
 }
 
 /* Free all resources associated with DWO_FILE.
-   Close the DWO file and munmap the sections.
-   All memory should be on the objfile obstack.  */
+   Close the DWO file and munmap the sections.  */
 
 static void
-free_dwo_file (struct dwo_file *dwo_file, struct objfile *objfile)
+free_dwo_file (struct dwo_file *dwo_file)
 {
-
   /* Note: dbfd is NULL for virtual DWO files.  */
   gdb_bfd_unref (dwo_file->dbfd);
 
   VEC_free (dwarf2_section_info_def, dwo_file->sections.types);
 }
 
-/* Wrapper for free_dwo_file for use in cleanups.  */
-
-static void
-free_dwo_file_cleanup (void *arg)
-{
-  struct free_dwo_file_cleanup_data *data
-    = (struct free_dwo_file_cleanup_data *) arg;
-  struct objfile *objfile = data->dwarf2_per_objfile->objfile;
-
-  free_dwo_file (data->dwo_file, objfile);
-
-  xfree (data);
-}
-
 /* Traversal function for free_dwo_files.  */
 
 static int
 free_dwo_file_from_slot (void **slot, void *info)
 {
   struct dwo_file *dwo_file = (struct dwo_file *) *slot;
-  struct objfile *objfile = (struct objfile *) info;
 
-  free_dwo_file (dwo_file, objfile);
+  free_dwo_file (dwo_file);
 
   return 1;
 }
@@ -13695,9 +13483,9 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
       && !(die->tag == DW_TAG_inlined_subroutine
           && origin_die->tag == DW_TAG_subprogram))
     complaint (&symfile_complaints,
-              _("DIE 0x%x and its abstract origin 0x%x have different tags"),
-              to_underlying (die->sect_off),
-              to_underlying (origin_die->sect_off));
+              _("DIE %s and its abstract origin %s have different tags"),
+              sect_offset_str (die->sect_off),
+              sect_offset_str (origin_die->sect_off));
 
   std::vector<sect_offset> offsets;
 
@@ -13742,16 +13530,16 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
              && !(child_die->tag == DW_TAG_inlined_subroutine
                   && child_origin_die->tag == DW_TAG_subprogram))
            complaint (&symfile_complaints,
-                      _("Child DIE 0x%x and its abstract origin 0x%x have "
+                      _("Child DIE %s and its abstract origin %s have "
                         "different tags"),
-                      to_underlying (child_die->sect_off),
-                      to_underlying (child_origin_die->sect_off));
+                      sect_offset_str (child_die->sect_off),
+                      sect_offset_str (child_origin_die->sect_off));
          if (child_origin_die->parent != origin_die)
            complaint (&symfile_complaints,
-                      _("Child DIE 0x%x and its abstract origin 0x%x have "
+                      _("Child DIE %s and its abstract origin %s have "
                         "different parents"),
-                      to_underlying (child_die->sect_off),
-                      to_underlying (child_origin_die->sect_off));
+                      sect_offset_str (child_die->sect_off),
+                      sect_offset_str (child_origin_die->sect_off));
          else
            offsets.push_back (child_origin_die->sect_off);
        }
@@ -13761,9 +13549,9 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
   for (offsetp = offsets.data () + 1; offsetp < offsets_end; offsetp++)
     if (offsetp[-1] == *offsetp)
       complaint (&symfile_complaints,
-                _("Multiple children of DIE 0x%x refer "
-                  "to DIE 0x%x as their abstract origin"),
-                to_underlying (die->sect_off), to_underlying (*offsetp));
+                _("Multiple children of DIE %s refer "
+                  "to DIE %s as their abstract origin"),
+                sect_offset_str (die->sect_off), sect_offset_str (*offsetp));
 
   offsetp = offsets.data ();
   origin_child_die = origin_die->child;
@@ -13828,8 +13616,8 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
   if (name == NULL)
     {
       complaint (&symfile_complaints,
-                _("missing name for subprogram DIE at %d"),
-                to_underlying (die->sect_off));
+                _("missing name for subprogram DIE at %s"),
+                sect_offset_str (die->sect_off));
       return;
     }
 
@@ -13841,8 +13629,8 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
       if (!attr || !DW_UNSND (attr))
        complaint (&symfile_complaints,
                   _("cannot get low and high bounds "
-                    "for subprogram DIE at %d"),
-                  to_underlying (die->sect_off));
+                    "for subprogram DIE at %s"),
+                  sect_offset_str (die->sect_off));
       return;
     }
 
@@ -14075,8 +13863,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
     {
       complaint (&symfile_complaints,
                 _("missing DW_AT_call_return_pc for DW_TAG_call_site "
-                  "DIE 0x%x [in module %s]"),
-                to_underlying (die->sect_off), objfile_name (objfile));
+                  "DIE %s [in module %s]"),
+                sect_offset_str (die->sect_off), objfile_name (objfile));
       return;
     }
   pc = attr_value_as_address (attr) + baseaddr;
@@ -14092,8 +13880,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
     {
       complaint (&symfile_complaints,
                 _("Duplicate PC %s for DW_TAG_call_site "
-                  "DIE 0x%x [in module %s]"),
-                paddress (gdbarch, pc), to_underlying (die->sect_off),
+                  "DIE %s [in module %s]"),
+                paddress (gdbarch, pc), sect_offset_str (die->sect_off),
                 objfile_name (objfile));
       return;
     }
@@ -14109,8 +13897,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
        {
          complaint (&symfile_complaints,
                     _("Tag %d is not DW_TAG_call_site_parameter in "
-                      "DW_TAG_call_site child DIE 0x%x [in module %s]"),
-                    child_die->tag, to_underlying (child_die->sect_off),
+                      "DW_TAG_call_site child DIE %s [in module %s]"),
+                    child_die->tag, sect_offset_str (child_die->sect_off),
                     objfile_name (objfile));
          continue;
        }
@@ -14172,8 +13960,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
          else
            complaint (&symfile_complaints,
                       _("Cannot find function owning DW_TAG_call_site "
-                        "DIE 0x%x [in module %s]"),
-                      to_underlying (die->sect_off), objfile_name (objfile));
+                        "DIE %s [in module %s]"),
+                      sect_offset_str (die->sect_off), objfile_name (objfile));
        }
     }
 
@@ -14219,8 +14007,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
          if (target_physname == NULL)
            complaint (&symfile_complaints,
                       _("DW_AT_call_target target DIE has invalid "
-                        "physname, for referencing DIE 0x%x [in module %s]"),
-                      to_underlying (die->sect_off), objfile_name (objfile));
+                        "physname, for referencing DIE %s [in module %s]"),
+                      sect_offset_str (die->sect_off), objfile_name (objfile));
          else
            SET_FIELD_PHYSNAME (call_site->target, target_physname);
        }
@@ -14233,8 +14021,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
              <= PC_BOUNDS_INVALID)
            complaint (&symfile_complaints,
                       _("DW_AT_call_target target DIE has invalid "
-                        "low pc, for referencing DIE 0x%x [in module %s]"),
-                      to_underlying (die->sect_off), objfile_name (objfile));
+                        "low pc, for referencing DIE %s [in module %s]"),
+                      sect_offset_str (die->sect_off), objfile_name (objfile));
          else
            {
              lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
@@ -14245,8 +14033,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
   else
     complaint (&symfile_complaints,
               _("DW_TAG_call_site DW_AT_call_target is neither "
-                "block nor reference, for DIE 0x%x [in module %s]"),
-              to_underlying (die->sect_off), objfile_name (objfile));
+                "block nor reference, for DIE %s [in module %s]"),
+              sect_offset_str (die->sect_off), objfile_name (objfile));
 
   call_site->per_cu = cu->per_cu;
 
@@ -14292,8 +14080,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
                 therefore cannot be even moved to DW_TAG_partial_unit.  */
              complaint (&symfile_complaints,
                         _("DW_AT_call_parameter offset is not in CU for "
-                          "DW_TAG_call_site child DIE 0x%x [in module %s]"),
-                        to_underlying (child_die->sect_off),
+                          "DW_TAG_call_site child DIE %s [in module %s]"),
+                        sect_offset_str (child_die->sect_off),
                         objfile_name (objfile));
              continue;
            }
@@ -14304,8 +14092,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
        {
          complaint (&symfile_complaints,
                     _("No DW_FORM_block* DW_AT_location for "
-                      "DW_TAG_call_site child DIE 0x%x [in module %s]"),
-                    to_underlying (child_die->sect_off), objfile_name (objfile));
+                      "DW_TAG_call_site child DIE %s [in module %s]"),
+                    sect_offset_str (child_die->sect_off), objfile_name (objfile));
          continue;
        }
       else
@@ -14323,9 +14111,9 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
              complaint (&symfile_complaints,
                         _("Only single DW_OP_reg or DW_OP_fbreg is supported "
                           "for DW_FORM_block* DW_AT_location is supported for "
-                          "DW_TAG_call_site child DIE 0x%x "
+                          "DW_TAG_call_site child DIE %s "
                           "[in module %s]"),
-                        to_underlying (child_die->sect_off),
+                        sect_offset_str (child_die->sect_off),
                         objfile_name (objfile));
              continue;
            }
@@ -14338,8 +14126,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
        {
          complaint (&symfile_complaints,
                     _("No DW_FORM_block* DW_AT_call_value for "
-                      "DW_TAG_call_site child DIE 0x%x [in module %s]"),
-                    to_underlying (child_die->sect_off),
+                      "DW_TAG_call_site child DIE %s [in module %s]"),
+                    sect_offset_str (child_die->sect_off),
                     objfile_name (objfile));
          continue;
        }
@@ -14359,8 +14147,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
          if (!attr_form_is_block (attr))
            complaint (&symfile_complaints,
                       _("No DW_FORM_block* DW_AT_call_data_value for "
-                        "DW_TAG_call_site child DIE 0x%x [in module %s]"),
-                      to_underlying (child_die->sect_off),
+                        "DW_TAG_call_site child DIE %s [in module %s]"),
+                      sect_offset_str (child_die->sect_off),
                       objfile_name (objfile));
          else
            {
@@ -14829,7 +14617,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;
 
@@ -14989,24 +14777,6 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
          address range list in the .debug_ranges section.  */
       unsigned long offset = (DW_UNSND (attr)
                              + (need_ranges_base ? cu->ranges_base : 0));
-      const gdb_byte *buffer;
-
-      /* For some target architectures, but not others, the
-         read_address function sign-extends the addresses it returns.
-         To recognize base address selection entries, we need a
-         mask.  */
-      unsigned int addr_size = cu->header.addr_size;
-      CORE_ADDR base_select_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
-
-      /* The base address, to which the next pair is relative.  Note
-         that this 'base' is a DWARF concept: most entries in a range
-         list are relative, to reduce the number of relocs against the
-         debugging information.  This is separate from this function's
-         'baseaddr' argument, which GDB uses to relocate debugging
-         information from a shared library based on the address at
-         which the library was loaded.  */
-      CORE_ADDR base = cu->base_address;
-      int base_known = cu->base_known;
 
       dwarf2_ranges_process (offset, cu,
        [&] (CORE_ADDR start, CORE_ADDR end)
@@ -15145,21 +14915,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);
@@ -15319,8 +15085,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?  */
@@ -15348,20 +15127,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;
@@ -15376,10 +15149,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,
@@ -15387,17 +15160,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.  */
@@ -15412,8 +15177,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)
     {
@@ -15434,47 +15198,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;
        }
+    }
+
+  /* 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, nfields) = fieldp->field;
-      switch (fieldp->accessibility)
+      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:
@@ -15484,19 +15254,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;
            }
        }
@@ -15539,11 +15309,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;
 
@@ -15556,51 +15325,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);
@@ -15705,8 +15456,8 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
                {
                  complaint (&symfile_complaints,
                             _("cannot determine context for virtual member "
-                              "function \"%s\" (offset %d)"),
-                            fieldname, to_underlying (die->sect_off));
+                              "function \"%s\" (offset %s)"),
+                            fieldname, sect_offset_str (die->sect_off));
                }
              else
                {
@@ -15732,9 +15483,9 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
        {
          /* GCC does this, as of 2008-08-25; PR debug/37237.  */
          complaint (&symfile_complaints,
-                    _("Member function \"%s\" (offset %d) is virtual "
+                    _("Member function \"%s\" (offset %s) is virtual "
                       "but the vtable offset is not specified"),
-                    fieldname, to_underlying (die->sect_off));
+                    fieldname, sect_offset_str (die->sect_off));
          ALLOCATE_CPLUS_STRUCT_TYPE (type);
          TYPE_CPLUS_DYNAMIC (type) = 1;
        }
@@ -15747,31 +15498,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
@@ -15833,6 +15582,82 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
   smash_to_methodptr_type (type, new_type);
 }
 
+/* If the DIE has a DW_AT_alignment attribute, return its value, doing
+   appropriate error checking and issuing complaints if there is a
+   problem.  */
+
+static ULONGEST
+get_alignment (struct dwarf2_cu *cu, struct die_info *die)
+{
+  struct attribute *attr = dwarf2_attr (die, DW_AT_alignment, cu);
+
+  if (attr == nullptr)
+    return 0;
+
+  if (!attr_form_is_constant (attr))
+    {
+      complaint (&symfile_complaints,
+                _("DW_AT_alignment must have constant form"
+                  " - DIE at %s [in module %s]"),
+                sect_offset_str (die->sect_off),
+                objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+      return 0;
+    }
+
+  ULONGEST align;
+  if (attr->form == DW_FORM_sdata)
+    {
+      LONGEST val = DW_SND (attr);
+      if (val < 0)
+       {
+         complaint (&symfile_complaints,
+                    _("DW_AT_alignment value must not be negative"
+                      " - DIE at %s [in module %s]"),
+                    sect_offset_str (die->sect_off),
+                    objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+         return 0;
+       }
+      align = val;
+    }
+  else
+    align = DW_UNSND (attr);
+
+  if (align == 0)
+    {
+      complaint (&symfile_complaints,
+                _("DW_AT_alignment value must not be zero"
+                  " - DIE at %s [in module %s]"),
+                sect_offset_str (die->sect_off),
+                objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+      return 0;
+    }
+  if ((align & (align - 1)) != 0)
+    {
+      complaint (&symfile_complaints,
+                _("DW_AT_alignment value must be a power of 2"
+                  " - DIE at %s [in module %s]"),
+                sect_offset_str (die->sect_off),
+                objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+      return 0;
+    }
+
+  return align;
+}
+
+/* If the DIE has a DW_AT_alignment attribute, use its value to set
+   the alignment for TYPE.  */
+
+static void
+maybe_set_alignment (struct dwarf2_cu *cu, struct die_info *die,
+                    struct type *type)
+{
+  if (!set_type_align (type, get_alignment (cu, die)))
+    complaint (&symfile_complaints,
+              _("DW_AT_alignment value too large"
+                " - DIE at %s [in module %s]"),
+              sect_offset_str (die->sect_off),
+              objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+}
 
 /* Called when we find the DIE that starts a structure or union scope
    (definition) to create a type for the structure or union.  Fill in
@@ -15907,6 +15732,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;
@@ -15938,6 +15768,8 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
       TYPE_LENGTH (type) = 0;
     }
 
+  maybe_set_alignment (cu, die, type);
+
   if (producer_is_icc_lt_14 (cu) && (TYPE_LENGTH (type) == 0))
     {
       /* ICC<14 does not output the required DW_AT_declaration on
@@ -15966,70 +15798,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;
-
-      while (child_die && child_die->tag)
-       {
-         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)
-           {
-             /* 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)
+      /* 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);
+
+      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 (variant_child->tag == DW_TAG_member)
            {
-             /* 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);
        }
@@ -16052,7 +15966,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);
 
@@ -16122,56 +16036,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;
-
-         /* Reverse the list order to keep the debug info elements order.  */
-         while (--i >= 0)
-           {
-             struct decl_field *dest, *src;
+              TYPE_ALLOC (type, sizeof (struct decl_field) * count));
+         TYPE_NESTED_TYPES_COUNT (type) = count;
 
-             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
@@ -16315,6 +16214,8 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
       TYPE_LENGTH (type) = 0;
     }
 
+  maybe_set_alignment (cu, die, type);
+
   /* The enumeration DIE can be incomplete.  In Ada, any type can be
      declared as private in the package spec, and then defined only
      inside the package body.  Such types are known as Taft Amendment
@@ -16340,6 +16241,9 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
       TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TYPE_TARGET_TYPE (type));
       if (TYPE_LENGTH (type) == 0)
        TYPE_LENGTH (type) = TYPE_LENGTH (TYPE_TARGET_TYPE (type));
+      if (TYPE_RAW_ALIGN (type) == 0
+         && TYPE_RAW_ALIGN (TYPE_TARGET_TYPE (type)) != 0)
+       set_type_align (type, TYPE_RAW_ALIGN (TYPE_TARGET_TYPE (type)));
     }
 
   TYPE_DECLARED_CLASS (type) = dwarf2_flag_true_p (die, DW_AT_enum_class, cu);
@@ -16472,8 +16376,8 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
        {
          complaint (&symfile_complaints,
                     _("unable to read array DW_AT_byte_stride "
-                      " - DIE at 0x%x [in module %s]"),
-                    to_underlying (die->sect_off),
+                      " - DIE at %s [in module %s]"),
+                    sect_offset_str (die->sect_off),
                     objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
          /* Ignore this attribute.  We will likely not be able to print
             arrays of this type correctly, but there is little we can do
@@ -16564,6 +16468,8 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
   if (name)
     TYPE_NAME (type) = name;
 
+  maybe_set_alignment (cu, die, type);
+
   /* Install the type in the die.  */
   set_die_type (die, type, cu);
 
@@ -16628,6 +16534,8 @@ read_set_type (struct die_info *die, struct dwarf2_cu *cu)
   if (attr)
     TYPE_LENGTH (set_type) = DW_UNSND (attr);
 
+  maybe_set_alignment (cu, die, set_type);
+
   return set_die_type (die, set_type, cu);
 }
 
@@ -16781,8 +16689,8 @@ read_common_block (struct die_info *die, struct dwarf2_cu *cu)
                  complaint (&symfile_complaints,
                             _("Variable in common block has "
                               "DW_AT_data_member_location "
-                              "- DIE at 0x%x [in module %s]"),
-                            to_underlying (child_die->sect_off),
+                              "- DIE at %s [in module %s]"),
+                              sect_offset_str (child_die->sect_off),
                             objfile_name (objfile));
 
                  if (attr_form_is_section_offset (member_loc))
@@ -16902,8 +16810,8 @@ read_module_type (struct die_info *die, struct dwarf2_cu *cu)
   module_name = dwarf2_name (die, cu);
   if (!module_name)
     complaint (&symfile_complaints,
-              _("DW_TAG_module has no name, offset 0x%x"),
-               to_underlying (die->sect_off));
+              _("DW_TAG_module has no name, offset %s"),
+               sect_offset_str (die->sect_off));
   type = init_type (objfile, TYPE_CODE_MODULE, 0, module_name);
 
   /* determine_prefix uses TYPE_TAG_NAME.  */
@@ -16999,10 +16907,15 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
   else
     addr_class = DW_ADDR_none;
 
-  /* If the pointer size or address class is different than the
-     default, create a type variant marked as such and set the
-     length accordingly.  */
-  if (TYPE_LENGTH (type) != byte_size || addr_class != DW_ADDR_none)
+  ULONGEST alignment = get_alignment (cu, die);
+
+  /* If the pointer size, alignment, or address class is different
+     than the default, create a type variant marked as such and set
+     the length accordingly.  */
+  if (TYPE_LENGTH (type) != byte_size
+      || (alignment != 0 && TYPE_RAW_ALIGN (type) != 0
+         && alignment != TYPE_RAW_ALIGN (type))
+      || addr_class != DW_ADDR_none)
     {
       if (gdbarch_address_class_type_flags_p (gdbarch))
        {
@@ -17019,6 +16932,14 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
          complaint (&symfile_complaints,
                     _("invalid pointer size %d"), byte_size);
        }
+      else if (TYPE_RAW_ALIGN (type) != alignment)
+       {
+         complaint (&symfile_complaints,
+                    _("Invalid DW_AT_alignment"
+                      " - DIE at %s [in module %s]"),
+                    sect_offset_str (die->sect_off),
+                    objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+       }
       else
        {
          /* Should we also complain about unhandled address classes?  */
@@ -17026,6 +16947,7 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
     }
 
   TYPE_LENGTH (type) = byte_size;
+  set_type_align (type, alignment);
   return set_die_type (die, type, cu);
 }
 
@@ -17095,6 +17017,7 @@ read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu,
     {
       TYPE_LENGTH (type) = cu_header->addr_size;
     }
+  maybe_set_alignment (cu, die, type);
   return set_die_type (die, type, cu);
 }
 
@@ -17447,8 +17370,8 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu)
         spec and cause infinite loops in GDB.  */
       complaint (&symfile_complaints,
                 _("Self-referential DW_TAG_typedef "
-                  "- DIE at 0x%x [in module %s]"),
-                to_underlying (die->sect_off), objfile_name (objfile));
+                  "- DIE at %s [in module %s]"),
+                sect_offset_str (die->sect_off), objfile_name (objfile));
       TYPE_TARGET_TYPE (this_type) = NULL;
     }
   return this_type;
@@ -17581,6 +17504,8 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
   if (name && strcmp (name, "char") == 0)
     TYPE_NOSIGN (type) = 1;
 
+  maybe_set_alignment (cu, die, type);
+
   return set_die_type (die, type, cu);
 }
 
@@ -17754,8 +17679,8 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
     attr_to_dynamic_prop (attr, die, cu, &low);
   else if (!low_default_is_valid)
     complaint (&symfile_complaints, _("Missing DW_AT_lower_bound "
-                                     "- DIE at 0x%x [in module %s]"),
-              to_underlying (die->sect_off),
+                                     "- DIE at %s [in module %s]"),
+              sect_offset_str (die->sect_off),
               objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
 
   attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
@@ -17843,6 +17768,8 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
   if (attr)
     TYPE_LENGTH (range_type) = DW_UNSND (attr);
 
+  maybe_set_alignment (cu, die, range_type);
+
   set_die_type (die, range_type, cu);
 
   /* set_die_type should be already done.  */
@@ -18080,8 +18007,8 @@ abbrev_table::add_abbrev (unsigned int abbrev_number,
   unsigned int hash_number;
 
   hash_number = abbrev_number % ABBREV_HASH_SIZE;
-  abbrev->next = abbrevs[hash_number];
-  abbrevs[hash_number] = abbrev;
+  abbrev->next = m_abbrevs[hash_number];
+  m_abbrevs[hash_number] = abbrev;
 }
 
 /* Look up an abbrev in the table.
@@ -18094,7 +18021,7 @@ abbrev_table::lookup_abbrev (unsigned int abbrev_number)
   struct abbrev_info *abbrev;
 
   hash_number = abbrev_number % ABBREV_HASH_SIZE;
-  abbrev = abbrevs[hash_number];
+  abbrev = m_abbrevs[hash_number];
 
   while (abbrev)
     {
@@ -18250,7 +18177,6 @@ load_partial_dies (const struct die_reader_specs *reader,
 {
   struct dwarf2_cu *cu = reader->cu;
   struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
-  struct partial_die_info *part_die;
   struct partial_die_info *parent_die, *last_die, *first_die = NULL;
   unsigned int bytes_read;
   unsigned int load_all = 0;
@@ -18272,8 +18198,6 @@ load_partial_dies (const struct die_reader_specs *reader,
                            hashtab_obstack_allocate,
                            dummy_obstack_deallocate);
 
-  part_die = XOBNEW (&cu->comp_unit_obstack, struct partial_die_info);
-
   while (1)
     {
       abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr, &bytes_read);
@@ -18282,15 +18206,8 @@ load_partial_dies (const struct die_reader_specs *reader,
       if (abbrev == NULL)
        {
          if (--nesting_level == 0)
-           {
-             /* PART_DIE was probably the last thing allocated on the
-                comp_unit_obstack, so we could call obstack_free
-                here.  We don't do that because the waste is small,
-                and will be cleaned up when we're done with this
-                compilation unit.  This way, we're also more robust
-                against other users of the comp_unit_obstack.  */
-             return first_die;
-           }
+           return first_die;
+
          info_ptr += bytes_read;
          last_die = parent_die;
          parent_die = parent_die->die_parent;
@@ -18348,8 +18265,10 @@ load_partial_dies (const struct die_reader_specs *reader,
          continue;
        }
 
-      info_ptr = read_partial_die (reader, part_die, abbrev, bytes_read,
-                                  info_ptr);
+      struct partial_die_info pdi ((sect_offset) (info_ptr - reader->buffer),
+                                  abbrev);
+
+      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
@@ -18368,18 +18287,18 @@ load_partial_dies (const struct die_reader_specs *reader,
         of them, for a language without namespaces), can be processed
         directly.  */
       if (parent_die == NULL
-         && part_die->has_specification == 0
-         && part_die->is_declaration == 0
-         && ((part_die->tag == DW_TAG_typedef && !part_die->has_children)
-             || part_die->tag == DW_TAG_base_type
-             || part_die->tag == DW_TAG_subrange_type))
-       {
-         if (building_psymtab && part_die->name != NULL)
-           add_psymbol_to_list (part_die->name, strlen (part_die->name), 0,
+         && pdi.has_specification == 0
+         && pdi.is_declaration == 0
+         && ((pdi.tag == DW_TAG_typedef && !pdi.has_children)
+             || pdi.tag == DW_TAG_base_type
+             || pdi.tag == DW_TAG_subrange_type))
+       {
+         if (building_psymtab && pdi.name != NULL)
+           add_psymbol_to_list (pdi.name, strlen (pdi.name), 0,
                                 VAR_DOMAIN, LOC_TYPEDEF,
                                 &objfile->static_psymbols,
                                 0, cu->language, objfile);
-         info_ptr = locate_pdi_sibling (reader, part_die, info_ptr);
+         info_ptr = locate_pdi_sibling (reader, &pdi, info_ptr);
          continue;
        }
 
@@ -18391,37 +18310,40 @@ load_partial_dies (const struct die_reader_specs *reader,
         it could not find the child DIEs referenced later, this is checked
         above.  In correct DWARF DW_TAG_typedef should have no children.  */
 
-      if (part_die->tag == DW_TAG_typedef && part_die->has_children)
+      if (pdi.tag == DW_TAG_typedef && pdi.has_children)
        complaint (&symfile_complaints,
                   _("DW_TAG_typedef has childen - GCC PR debug/47510 bug "
-                    "- DIE at 0x%x [in module %s]"),
-                  to_underlying (part_die->sect_off), objfile_name (objfile));
+                    "- DIE at %s [in module %s]"),
+                  sect_offset_str (pdi.sect_off), objfile_name (objfile));
 
       /* If we're at the second level, and we're an enumerator, and
         our parent has no specification (meaning possibly lives in a
         namespace elsewhere), then we can add the partial symbol now
         instead of queueing it.  */
-      if (part_die->tag == DW_TAG_enumerator
+      if (pdi.tag == DW_TAG_enumerator
          && parent_die != NULL
          && parent_die->die_parent == NULL
          && parent_die->tag == DW_TAG_enumeration_type
          && parent_die->has_specification == 0)
        {
-         if (part_die->name == NULL)
+         if (pdi.name == NULL)
            complaint (&symfile_complaints,
                       _("malformed enumerator DIE ignored"));
          else if (building_psymtab)
-           add_psymbol_to_list (part_die->name, strlen (part_die->name), 0,
+           add_psymbol_to_list (pdi.name, strlen (pdi.name), 0,
                                 VAR_DOMAIN, LOC_CONST,
                                 cu->language == language_cplus
                                 ? &objfile->global_psymbols
                                 : &objfile->static_psymbols,
                                 0, cu->language, objfile);
 
-         info_ptr = locate_pdi_sibling (reader, part_die, info_ptr);
+         info_ptr = locate_pdi_sibling (reader, &pdi, info_ptr);
          continue;
        }
 
+      struct partial_die_info *part_die
+       = new (&cu->comp_unit_obstack) partial_die_info (pdi);
+
       /* We'll save this DIE so link it in.  */
       part_die->die_parent = parent_die;
       part_die->die_sibling = NULL;
@@ -18473,8 +18395,6 @@ load_partial_dies (const struct die_reader_specs *reader,
          *slot = part_die;
        }
 
-      part_die = XOBNEW (&cu->comp_unit_obstack, struct partial_die_info);
-
       /* For some DIEs we want to follow their children (if any).  For C
         we have no reason to follow the children of structures; for other
         languages we have to, so that we can get at method physnames
@@ -18517,47 +18437,39 @@ 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)
+{
+}
+
+/* Read a minimal amount of information into the minimal die structure.
+   INFO_PTR should point just after the initial uleb128 of a DIE.  */
 
-static const gdb_byte *
-read_partial_die (const struct die_reader_specs *reader,
-                 struct partial_die_info *part_die,
-                 struct abbrev_info *abbrev, unsigned int abbrev_len,
-                 const gdb_byte *info_ptr)
+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;
-
-  if (abbrev == NULL)
-    return info_ptr;
-
-  part_die->tag = abbrev->tag;
-  part_die->has_children = abbrev->has_children;
-
-  for (i = 0; i < abbrev->num_attrs; ++i)
+  for (i = 0; i < abbrev.num_attrs; ++i)
     {
-      info_ptr = read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
+      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
          partial symbol table.  */
       switch (attr.name)
        {
        case DW_AT_name:
-         switch (part_die->tag)
+         switch (tag)
            {
            case DW_TAG_compile_unit:
            case DW_TAG_partial_unit:
@@ -18568,12 +18480,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;
@@ -18583,16 +18499,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;
@@ -18600,7 +18516,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))
             {
@@ -18613,20 +18529,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:
@@ -18637,6 +18553,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);
 
@@ -18646,14 +18563,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
@@ -18672,25 +18589,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:
@@ -18699,7 +18616,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)
     {
@@ -18711,31 +18628,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 0x%x [in module %s]"),
-                    paddress (gdbarch, part_die->lowpc),
-                    to_underlying (part_die->sect_off), objfile_name (objfile));
+                      "for DIE at %s [in module %s]"),
+                    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 0x%x [in module %s]"),
-                    paddress (gdbarch, part_die->lowpc),
-                    paddress (gdbarch, part_die->highpc),
-                    to_underlying (part_die->sect_off),
+                      "for DIE at %s [in module %s]"),
+                    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;
@@ -18743,15 +18663,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;
@@ -18774,7 +18693,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.
@@ -18786,9 +18705,9 @@ find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu)
       /* TUs don't reference other CUs/TUs (except via type signatures).  */
       if (cu->per_cu->is_debug_types)
        {
-         error (_("Dwarf Error: Type Unit at offset 0x%x contains"
-                  " external reference to offset 0x%x [in module %s].\n"),
-                to_underlying (cu->header.sect_off), to_underlying (sect_off),
+         error (_("Dwarf Error: Type Unit at offset %s contains"
+                  " external reference to offset %s [in module %s].\n"),
+                sect_offset_str (cu->header.sect_off), sect_offset_str (sect_off),
                 bfd_get_filename (objfile->obfd));
        }
       per_cu = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
@@ -18798,7 +18717,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,
@@ -18816,14 +18735,14 @@ 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)
     internal_error (__FILE__, __LINE__,
-                   _("could not find partial DIE 0x%x "
+                   _("could not find partial DIE %s "
                      "in cache [from module %s]\n"),
-                   to_underlying (sect_off), bfd_get_filename (objfile->obfd));
+                   sect_offset_str (sect_off), bfd_get_filename (objfile->obfd));
   return pd;
 }
 
@@ -18881,45 +18800,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
@@ -18927,25 +18841,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;
@@ -18959,7 +18873,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)));
@@ -18967,7 +18881,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.  */
@@ -19732,7 +19646,6 @@ dwarf2_read_addr_index (struct dwarf2_per_cu_data *per_cu,
                        unsigned int addr_index)
 {
   struct dwarf2_per_objfile *dwarf2_per_objfile = per_cu->dwarf2_per_objfile;
-  struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct dwarf2_cu *cu = per_cu->cu;
   ULONGEST addr_base;
   int addr_size;
@@ -19797,16 +19710,16 @@ read_str_index (const struct die_reader_specs *reader, ULONGEST str_index)
   dwarf2_read_section (objfile, str_offsets_section);
   if (str_section->buffer == NULL)
     error (_("%s used without .debug_str.dwo section"
-            " in CU at offset 0x%x [in module %s]"),
-          form_name, to_underlying (cu->header.sect_off), objf_name);
+            " in CU at offset %s [in module %s]"),
+          form_name, sect_offset_str (cu->header.sect_off), objf_name);
   if (str_offsets_section->buffer == NULL)
     error (_("%s used without .debug_str_offsets.dwo section"
-            " in CU at offset 0x%x [in module %s]"),
-          form_name, to_underlying (cu->header.sect_off), objf_name);
+            " in CU at offset %s [in module %s]"),
+          form_name, sect_offset_str (cu->header.sect_off), objf_name);
   if (str_index * cu->header.offset_size >= str_offsets_section->size)
     error (_("%s pointing outside of .debug_str_offsets.dwo"
-            " section in CU at offset 0x%x [in module %s]"),
-          form_name, to_underlying (cu->header.sect_off), objf_name);
+            " section in CU at offset %s [in module %s]"),
+          form_name, sect_offset_str (cu->header.sect_off), objf_name);
   info_ptr = (str_offsets_section->buffer
              + str_index * cu->header.offset_size);
   if (cu->header.offset_size == 4)
@@ -19815,8 +19728,8 @@ read_str_index (const struct die_reader_specs *reader, ULONGEST str_index)
     str_offset = bfd_get_64 (abfd, info_ptr);
   if (str_offset >= str_section->size)
     error (_("Offset from %s pointing outside of"
-            " .debug_str.dwo section in CU at offset 0x%x [in module %s]"),
-          form_name, to_underlying (cu->header.sect_off), objf_name);
+            " .debug_str.dwo section in CU at offset %s [in module %s]"),
+          form_name, sect_offset_str (cu->header.sect_off), objf_name);
   return (const char *) (str_section->buffer + str_offset);
 }
 
@@ -19963,8 +19876,8 @@ dwarf2_string_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *c
       else
         complaint (&symfile_complaints,
                   _("string type expected for attribute %s for "
-                    "DIE at 0x%x in module %s"),
-                  dwarf_attr_name (name), to_underlying (die->sect_off),
+                    "DIE at %s in module %s"),
+                  dwarf_attr_name (name), sect_offset_str (die->sect_off),
                   objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
     }
 
@@ -20399,25 +20312,24 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu)
    Return the file name of the psymtab for included file FILE_INDEX
    in line header LH of PST.
    COMP_DIR is the compilation directory (DW_AT_comp_dir) or NULL if unknown.
-   If space for the result is malloc'd, it will be freed by a cleanup.
-   Returns NULL if FILE_INDEX should be ignored, i.e., it is pst->filename.
-
-   The function creates dangling cleanup registration.  */
+   If space for the result is malloc'd, *NAME_HOLDER will be set.
+   Returns NULL if FILE_INDEX should be ignored, i.e., it is pst->filename.  */
 
 static const char *
 psymtab_include_file_name (const struct line_header *lh, int file_index,
                           const struct partial_symtab *pst,
-                          const char *comp_dir)
+                          const char *comp_dir,
+                          gdb::unique_xmalloc_ptr<char> *name_holder)
 {
   const file_entry &fe = lh->file_names[file_index];
   const char *include_name = fe.name;
   const char *include_name_to_compare = include_name;
   const char *pst_filename;
-  char *copied_name = NULL;
   int file_is_pst;
 
   const char *dir_name = fe.include_dir (lh);
 
+  gdb::unique_xmalloc_ptr<char> hold_compare;
   if (!IS_ABSOLUTE_PATH (include_name)
       && (dir_name != NULL || comp_dir != NULL))
     {
@@ -20444,36 +20356,30 @@ psymtab_include_file_name (const struct line_header *lh, int file_index,
 
       if (dir_name != NULL)
        {
-         char *tem = concat (dir_name, SLASH_STRING,
-                             include_name, (char *)NULL);
-
-         make_cleanup (xfree, tem);
-         include_name = tem;
+         name_holder->reset (concat (dir_name, SLASH_STRING,
+                                     include_name, (char *) NULL));
+         include_name = name_holder->get ();
          include_name_to_compare = include_name;
        }
       if (!IS_ABSOLUTE_PATH (include_name) && comp_dir != NULL)
        {
-         char *tem = concat (comp_dir, SLASH_STRING,
-                             include_name, (char *)NULL);
-
-         make_cleanup (xfree, tem);
-         include_name_to_compare = tem;
+         hold_compare.reset (concat (comp_dir, SLASH_STRING,
+                                     include_name, (char *) NULL));
+         include_name_to_compare = hold_compare.get ();
        }
     }
 
   pst_filename = pst->filename;
+  gdb::unique_xmalloc_ptr<char> copied_name;
   if (!IS_ABSOLUTE_PATH (pst_filename) && pst->dirname != NULL)
     {
-      copied_name = concat (pst->dirname, SLASH_STRING,
-                           pst_filename, (char *)NULL);
-      pst_filename = copied_name;
+      copied_name.reset (concat (pst->dirname, SLASH_STRING,
+                                pst_filename, (char *) NULL));
+      pst_filename = copied_name.get ();
     }
 
   file_is_pst = FILENAME_CMP (include_name_to_compare, pst_filename) == 0;
 
-  if (copied_name != NULL)
-    xfree (copied_name);
-
   if (file_is_pst)
     return NULL;
   return include_name;
@@ -21131,8 +21037,10 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
       for (file_index = 0; file_index < lh->file_names.size (); file_index++)
         if (lh->file_names[file_index].included_p == 1)
           {
+           gdb::unique_xmalloc_ptr<char> name_holder;
            const char *include_name =
-             psymtab_include_file_name (lh, file_index, pst, comp_dir);
+             psymtab_include_file_name (lh, file_index, pst, comp_dir,
+                                        &name_holder);
            if (include_name != NULL)
               dwarf2_create_include_psymtab (include_name, pst, objfile);
           }
@@ -21888,15 +21796,9 @@ die_type (struct die_info *die, struct dwarf2_cu *cu)
 static int
 need_gnat_info (struct dwarf2_cu *cu)
 {
-  /* FIXME: brobecker/2010-10-12: As of now, only the AdaCore version
-     of GNAT produces this auxiliary information, without any indication
-     that it is produced.  Part of enhancing the FSF version of GNAT
-     to produce that information will be to put in place an indicator
-     that we can use in order to determine whether the descriptive type
-     info is available or not.  One suggestion that has been made is
-     to use a new attribute, attached to the CU die.  For now, assume
-     that the descriptive type info is not available.  */
-  return 0;
+  /* Assume that the Ada compiler was GNAT, which always produces
+     the auxiliary information.  */
+  return (cu->language == language_ada);
 }
 
 /* Return the auxiliary type of the die in question using its
@@ -21958,10 +21860,10 @@ build_error_marker_type (struct dwarf2_cu *cu, struct die_info *die)
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   char *message, *saved;
 
-  message = xstrprintf (_("<unknown type in %s, CU 0x%x, DIE 0x%x>"),
+  message = xstrprintf (_("<unknown type in %s, CU %s, DIE %s>"),
                        objfile_name (objfile),
-                       to_underlying (cu->header.sect_off),
-                       to_underlying (die->sect_off));
+                       sect_offset_str (cu->header.sect_off),
+                       sect_offset_str (die->sect_off));
   saved = (char *) obstack_copy0 (&objfile->objfile_obstack,
                                  message, strlen (message));
   xfree (message);
@@ -22014,8 +21916,8 @@ lookup_die_type (struct die_info *die, const struct attribute *attr,
     {
       complaint (&symfile_complaints,
                 _("Dwarf Error: Bad type attribute %s in DIE"
-                  " at 0x%x [in module %s]"),
-                dwarf_attr_name (attr->name), to_underlying (die->sect_off),
+                  " at %s [in module %s]"),
+                dwarf_attr_name (attr->name), sect_offset_str (die->sect_off),
                 objfile_name (objfile));
       return build_error_marker_type (cu, die);
     }
@@ -22705,15 +22607,15 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
   unsigned int i;
 
   print_spaces (indent, f);
-  fprintf_unfiltered (f, "Die: %s (abbrev %d, offset 0x%x)\n",
+  fprintf_unfiltered (f, "Die: %s (abbrev %d, offset %s)\n",
                      dwarf_tag_name (die->tag), die->abbrev,
-                     to_underlying (die->sect_off));
+                     sect_offset_str (die->sect_off));
 
   if (die->parent != NULL)
     {
       print_spaces (indent, f);
-      fprintf_unfiltered (f, "  parent at offset: 0x%x\n",
-                         to_underlying (die->parent->sect_off));
+      fprintf_unfiltered (f, "  parent at offset: %s\n",
+                         sect_offset_str (die->parent->sect_off));
     }
 
   print_spaces (indent, f);
@@ -22959,7 +22861,6 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz,
   struct dwarf2_cu *target_cu, *cu = *ref_cu;
   struct dwarf2_per_objfile *dwarf2_per_objfile
     = cu->per_cu->dwarf2_per_objfile;
-  struct objfile *objfile = dwarf2_per_objfile->objfile;
 
   gdb_assert (cu->per_cu != NULL);
 
@@ -23018,9 +22919,9 @@ follow_die_ref (struct die_info *src_die, const struct attribute *attr,
                            || cu->per_cu->is_dwz),
                           ref_cu);
   if (!die)
-    error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE "
-          "at 0x%x [in module %s]"),
-          to_underlying (sect_off), to_underlying (src_die->sect_off),
+    error (_("Dwarf Error: Cannot find DIE at %s referenced from DIE "
+          "at %s [in module %s]"),
+          sect_offset_str (sect_off), sect_offset_str (src_die->sect_off),
           objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
 
   return die;
@@ -23041,9 +22942,8 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off,
   struct die_info *die;
   struct attribute *attr;
   struct dwarf2_locexpr_baton retval;
-  struct objfile *objfile = per_cu->dwarf2_per_objfile->objfile;
-  struct dwarf2_per_objfile *dwarf2_per_objfile
-    = get_dwarf2_per_objfile (objfile);
+  struct dwarf2_per_objfile *dwarf2_per_objfile = per_cu->dwarf2_per_objfile;
+  struct objfile *objfile = dwarf2_per_objfile->objfile;
 
   if (per_cu->cu == NULL)
     load_cu (per_cu);
@@ -23052,14 +22952,14 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off,
     {
       /* We shouldn't get here for a dummy CU, but don't crash on the user.
         Instead just throw an error, not much else we can do.  */
-      error (_("Dwarf Error: Dummy CU at 0x%x referenced in module %s"),
-            to_underlying (sect_off), objfile_name (objfile));
+      error (_("Dwarf Error: Dummy CU at %s referenced in module %s"),
+            sect_offset_str (sect_off), objfile_name (objfile));
     }
 
   die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
   if (!die)
-    error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
-          to_underlying (sect_off), objfile_name (objfile));
+    error (_("Dwarf Error: Cannot find DIE at %s referenced in module %s"),
+          sect_offset_str (sect_off), objfile_name (objfile));
 
   attr = dwarf2_attr (die, DW_AT_location, cu);
   if (!attr)
@@ -23085,9 +22985,9 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off,
   else
     {
       if (!attr_form_is_block (attr))
-       error (_("Dwarf Error: DIE at 0x%x referenced in module %s "
+       error (_("Dwarf Error: DIE at %s referenced in module %s "
                 "is neither DW_FORM_block* nor DW_FORM_exprloc"),
-              to_underlying (sect_off), objfile_name (objfile));
+              sect_offset_str (sect_off), objfile_name (objfile));
 
       retval.data = DW_BLOCK (attr)->data;
       retval.size = DW_BLOCK (attr)->size;
@@ -23159,15 +23059,14 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
     {
       /* We shouldn't get here for a dummy CU, but don't crash on the user.
         Instead just throw an error, not much else we can do.  */
-      error (_("Dwarf Error: Dummy CU at 0x%x referenced in module %s"),
-            to_underlying (sect_off), objfile_name (objfile));
+      error (_("Dwarf Error: Dummy CU at %s referenced in module %s"),
+            sect_offset_str (sect_off), objfile_name (objfile));
     }
 
   die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
   if (!die)
-    error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
-          to_underlying (sect_off), objfile_name (objfile));
-
+    error (_("Dwarf Error: Cannot find DIE at %s referenced in module %s"),
+          sect_offset_str (sect_off), objfile_name (objfile));
 
   attr = dwarf2_attr (die, DW_AT_const_value, cu);
   if (attr == NULL)
@@ -23371,8 +23270,8 @@ follow_die_sig (struct die_info *src_die, const struct attribute *attr,
   if (sig_type == NULL)
     {
       error (_("Dwarf Error: Cannot find signatured DIE %s referenced"
-               " from DIE at 0x%x [in module %s]"),
-             hex_string (signature), to_underlying (src_die->sect_off),
+               " from DIE at %s [in module %s]"),
+             hex_string (signature), sect_offset_str (src_die->sect_off),
             objfile_name ((*ref_cu)->per_cu->dwarf2_per_objfile->objfile));
     }
 
@@ -23381,8 +23280,8 @@ follow_die_sig (struct die_info *src_die, const struct attribute *attr,
     {
       dump_die_for_error (src_die);
       error (_("Dwarf Error: Problem reading signatured DIE %s referenced"
-              " from DIE at 0x%x [in module %s]"),
-            hex_string (signature), to_underlying (src_die->sect_off),
+              " from DIE at %s [in module %s]"),
+            hex_string (signature), sect_offset_str (src_die->sect_off),
             objfile_name ((*ref_cu)->per_cu->dwarf2_per_objfile->objfile));
     }
 
@@ -23410,8 +23309,8 @@ get_signatured_type (struct die_info *die, ULONGEST signature,
     {
       complaint (&symfile_complaints,
                 _("Dwarf Error: Cannot find signatured DIE %s referenced"
-                  " from DIE at 0x%x [in module %s]"),
-                hex_string (signature), to_underlying (die->sect_off),
+                  " from DIE at %s [in module %s]"),
+                hex_string (signature), sect_offset_str (die->sect_off),
                 objfile_name (dwarf2_per_objfile->objfile));
       return build_error_marker_type (cu, die);
     }
@@ -23432,8 +23331,8 @@ get_signatured_type (struct die_info *die, ULONGEST signature,
        {
          complaint (&symfile_complaints,
                     _("Dwarf Error: Cannot build signatured type %s"
-                      " referenced from DIE at 0x%x [in module %s]"),
-                    hex_string (signature), to_underlying (die->sect_off),
+                      " referenced from DIE at %s [in module %s]"),
+                    hex_string (signature), sect_offset_str (die->sect_off),
                     objfile_name (dwarf2_per_objfile->objfile));
          type = build_error_marker_type (cu, die);
        }
@@ -23442,8 +23341,8 @@ get_signatured_type (struct die_info *die, ULONGEST signature,
     {
       complaint (&symfile_complaints,
                 _("Dwarf Error: Problem reading signatured DIE %s referenced"
-                  " from DIE at 0x%x [in module %s]"),
-                hex_string (signature), to_underlying (die->sect_off),
+                  " from DIE at %s [in module %s]"),
+                hex_string (signature), sect_offset_str (die->sect_off),
                 objfile_name (dwarf2_per_objfile->objfile));
       type = build_error_marker_type (cu, die);
     }
@@ -23478,8 +23377,8 @@ get_DW_AT_signature_type (struct die_info *die, const struct attribute *attr,
 
       complaint (&symfile_complaints,
                 _("Dwarf Error: DW_AT_signature has bad form %s in DIE"
-                  " at 0x%x [in module %s]"),
-                dwarf_form_name (attr->form), to_underlying (die->sect_off),
+                  " at %s [in module %s]"),
+                dwarf_form_name (attr->form), sect_offset_str (die->sect_off),
                 objfile_name (dwarf2_per_objfile->objfile));
       return build_error_marker_type (cu, die);
     }
@@ -25075,7 +24974,7 @@ dwarf2_find_containing_comp_unit (sect_offset sect_off,
   const sect_offset *cu_off;
 
   low = 0;
-  high = dwarf2_per_objfile->n_comp_units - 1;
+  high = dwarf2_per_objfile->all_comp_units.size () - 1;
   while (high > low)
     {
       struct dwarf2_per_cu_data *mid_cu;
@@ -25096,8 +24995,8 @@ dwarf2_find_containing_comp_unit (sect_offset sect_off,
     {
       if (low == 0 || this_cu->is_dwz != offset_in_dwz)
        error (_("Dwarf Error: could not find partial DIE containing "
-              "offset 0x%x [in module %s]"),
-              to_underlying (sect_off),
+              "offset %s [in module %s]"),
+              sect_offset_str (sect_off),
               bfd_get_filename (dwarf2_per_objfile->objfile->obfd));
 
       gdb_assert (dwarf2_per_objfile->all_comp_units[low-1]->sect_off
@@ -25107,9 +25006,9 @@ dwarf2_find_containing_comp_unit (sect_offset sect_off,
   else
     {
       this_cu = dwarf2_per_objfile->all_comp_units[low];
-      if (low == dwarf2_per_objfile->n_comp_units - 1
+      if (low == dwarf2_per_objfile->all_comp_units.size () - 1
          && sect_off >= this_cu->sect_off + this_cu->length)
-       error (_("invalid dwarf2 offset %u"), to_underlying (sect_off));
+       error (_("invalid dwarf2 offset %s"), sect_offset_str (sect_off));
       gdb_assert (sect_off < this_cu->sect_off + this_cu->length);
       return this_cu;
     }
@@ -25117,13 +25016,24 @@ dwarf2_find_containing_comp_unit (sect_offset sect_off,
 
 /* Initialize dwarf2_cu CU, owned by PER_CU.  */
 
-static void
-init_one_comp_unit (struct dwarf2_cu *cu, struct dwarf2_per_cu_data *per_cu)
+dwarf2_cu::dwarf2_cu (struct dwarf2_per_cu_data *per_cu_)
+  : per_cu (per_cu_),
+    mark (0),
+    has_loclist (0),
+    checked_producer (0),
+    producer_is_gxx_lt_4_6 (0),
+    producer_is_gcc_lt_4_3 (0),
+    producer_is_icc_lt_14 (0),
+    processing_has_namespace_info (0)
+{
+  per_cu->cu = this;
+}
+
+/* Destroy a dwarf2_cu.  */
+
+dwarf2_cu::~dwarf2_cu ()
 {
-  memset (cu, 0, sizeof (*cu));
-  per_cu->cu = cu;
-  cu->per_cu = per_cu;
-  obstack_init (&cu->comp_unit_obstack);
+  per_cu->cu = NULL;
 }
 
 /* Initialize basic fields of dwarf_cu CU according to DIE COMP_UNIT_DIE.  */
@@ -25147,54 +25057,6 @@ prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die,
   cu->producer = dwarf2_string_attr (comp_unit_die, DW_AT_producer, cu);
 }
 
-/* Release one cached compilation unit, CU.  We unlink it from the tree
-   of compilation units, but we don't remove it from the read_in_chain;
-   the caller is responsible for that.
-   NOTE: DATA is a void * because this function is also used as a
-   cleanup routine.  */
-
-static void
-free_heap_comp_unit (void *data)
-{
-  struct dwarf2_cu *cu = (struct dwarf2_cu *) data;
-
-  gdb_assert (cu->per_cu != NULL);
-  cu->per_cu->cu = NULL;
-  cu->per_cu = NULL;
-
-  obstack_free (&cu->comp_unit_obstack, NULL);
-
-  xfree (cu);
-}
-
-/* This cleanup function is passed the address of a dwarf2_cu on the stack
-   when we're finished with it.  We can't free the pointer itself, but be
-   sure to unlink it from the cache.  Also release any associated storage.  */
-
-static void
-free_stack_comp_unit (void *data)
-{
-  struct dwarf2_cu *cu = (struct dwarf2_cu *) data;
-
-  gdb_assert (cu->per_cu != NULL);
-  cu->per_cu->cu = NULL;
-  cu->per_cu = NULL;
-
-  obstack_free (&cu->comp_unit_obstack, NULL);
-  cu->partial_dies = NULL;
-}
-
-/* Free all cached compilation units.  */
-
-static void
-free_cached_comp_units (void *data)
-{
-  struct dwarf2_per_objfile *dwarf2_per_objfile
-    = (struct dwarf2_per_objfile *) data;
-
-  dwarf2_per_objfile->free_cached_comp_units ();
-}
-
 /* Increase the age counter on each cached compilation unit, and free
    any that are too old.  */
 
@@ -25223,7 +25085,7 @@ age_cached_comp_units (struct dwarf2_per_objfile *dwarf2_per_objfile)
 
       if (!per_cu->cu->mark)
        {
-         free_heap_comp_unit (per_cu->cu);
+         delete per_cu->cu;
          *last_chain = next_cu;
        }
       else
@@ -25252,7 +25114,7 @@ free_one_cached_comp_unit (struct dwarf2_per_cu_data *target_per_cu)
 
       if (per_cu == target_per_cu)
        {
-         free_heap_comp_unit (per_cu->cu);
+         delete per_cu->cu;
          per_cu->cu = NULL;
          *last_chain = next_cu;
          break;
@@ -25272,10 +25134,7 @@ dwarf2_free_objfile (struct objfile *objfile)
   struct dwarf2_per_objfile *dwarf2_per_objfile
     = get_dwarf2_per_objfile (objfile);
 
-  if (dwarf2_per_objfile == NULL)
-    return;
-
-  dwarf2_per_objfile->~dwarf2_per_objfile ();
+  delete dwarf2_per_objfile;
 }
 
 /* A set of CU "per_cu" pointer, DIE offset, and GDB type pointer.
@@ -25373,14 +25232,14 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
   if (attr_form_is_block (attr))
     {
       if (attr_to_dynamic_prop (attr, die, cu, &prop))
-        add_dyn_prop (DYN_PROP_ALLOCATED, prop, type, objfile);
+        add_dyn_prop (DYN_PROP_ALLOCATED, prop, type);
     }
   else if (attr != NULL)
     {
       complaint (&symfile_complaints,
-                _("DW_AT_allocated has the wrong form (%s) at DIE 0x%x"),
+                _("DW_AT_allocated has the wrong form (%s) at DIE %s"),
                 (attr != NULL ? dwarf_form_name (attr->form) : "n/a"),
-                to_underlying (die->sect_off));
+                sect_offset_str (die->sect_off));
     }
 
   /* Read DW_AT_associated and set in type.  */
@@ -25388,20 +25247,20 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
   if (attr_form_is_block (attr))
     {
       if (attr_to_dynamic_prop (attr, die, cu, &prop))
-        add_dyn_prop (DYN_PROP_ASSOCIATED, prop, type, objfile);
+        add_dyn_prop (DYN_PROP_ASSOCIATED, prop, type);
     }
   else if (attr != NULL)
     {
       complaint (&symfile_complaints,
-                _("DW_AT_associated has the wrong form (%s) at DIE 0x%x"),
+                _("DW_AT_associated has the wrong form (%s) at DIE %s"),
                 (attr != NULL ? dwarf_form_name (attr->form) : "n/a"),
-                to_underlying (die->sect_off));
+                sect_offset_str (die->sect_off));
     }
 
   /* Read DW_AT_data_location and set in type.  */
   attr = dwarf2_attr (die, DW_AT_data_location, cu);
   if (attr_to_dynamic_prop (attr, die, cu, &prop))
-    add_dyn_prop (DYN_PROP_DATA_LOCATION, prop, type, objfile);
+    add_dyn_prop (DYN_PROP_DATA_LOCATION, prop, type);
 
   if (dwarf2_per_objfile->die_type_hash == NULL)
     {
@@ -25422,8 +25281,8 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
     htab_find_slot (dwarf2_per_objfile->die_type_hash, &ofs, INSERT);
   if (*slot)
     complaint (&symfile_complaints,
-              _("A problem internal to GDB: DIE 0x%x has type already set"),
-              to_underlying (die->sect_off));
+              _("A problem internal to GDB: DIE %s has type already set"),
+              sect_offset_str (die->sect_off));
   *slot = XOBNEW (&objfile->objfile_obstack,
                  struct dwarf2_per_cu_offset_and_type);
   **slot = ofs;
@@ -25574,1716 +25433,78 @@ show_dwarf_cmd (const char *args, int from_tty)
   cmd_show_list (show_dwarf_cmdlist, from_tty, "");
 }
 
-/* Free data associated with OBJFILE, if necessary.  */
+int dwarf_always_disassemble;
 
 static void
-dwarf2_per_objfile_free (struct objfile *objfile, void *d)
+show_dwarf_always_disassemble (struct ui_file *file, int from_tty,
+                              struct cmd_list_element *c, const char *value)
 {
-  struct dwarf2_per_objfile *data = (struct dwarf2_per_objfile *) d;
-  int ix;
-
-  for (ix = 0; ix < data->n_comp_units; ++ix)
-   VEC_free (dwarf2_per_cu_ptr, data->all_comp_units[ix]->imported_symtabs);
-
-  for (ix = 0; ix < data->n_type_units; ++ix)
-    VEC_free (dwarf2_per_cu_ptr,
-             data->all_type_units[ix]->per_cu.imported_symtabs);
-  xfree (data->all_type_units);
-
-  VEC_free (dwarf2_section_info_def, data->types);
-
-  if (data->dwo_files)
-    free_dwo_files (data->dwo_files, objfile);
-  if (data->dwp_file)
-    gdb_bfd_unref (data->dwp_file->dbfd);
-
-  if (data->dwz_file && data->dwz_file->dwz_bfd)
-    gdb_bfd_unref (data->dwz_file->dwz_bfd);
-
-  if (data->index_table != NULL)
-    data->index_table->~mapped_index ();
+  fprintf_filtered (file,
+                   _("Whether to always disassemble "
+                     "DWARF expressions is %s.\n"),
+                   value);
 }
 
-\f
-/* The "save gdb-index" command.  */
-
-/* Write SIZE bytes from the buffer pointed to by DATA to FILE, with
-   error checking.  */
-
 static void
-file_write (FILE *file, const void *data, size_t size)
+show_check_physname (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 check \"physname\" 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)
+void
+_initialize_dwarf2_read (void)
 {
-  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)));
-  }
+  dwarf2_objfile_data_key = register_objfile_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));
-  }
+  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);
 
-  /* 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;
-      }
-  }
+  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);
 
-  /* 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);
-  }
+  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);
 
-  /* Return the size of the buffer.  */
-  size_t size () const
-  {
-    return m_vec.size ();
-  }
+  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);
 
-  /* 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)
-{
-  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);
-    }
-}
-
-/* Expand SYMTAB's hash table.  */
-
-static void
-hash_expand (struct mapped_symtab *symtab)
-{
-  auto old_entries = std::move (symtab->data);
-
-  symtab->data.clear ();
-  symtab->data.resize (old_entries.size () * 2);
-
-  for (auto &it : old_entries)
-    if (it.name != NULL)
-      {
-       auto &ref = find_slot (symtab, it.name);
-       ref = std::move (it);
-      }
-}
-
-/* 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).  */
-
-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;
-
-  ++symtab->n_elements;
-  if (4 * symtab->n_elements / 3 >= symtab->data.size ())
-    hash_expand (symtab);
-
-  symtab_index_entry &slot = find_slot (symtab, name);
-  if (slot.name == NULL)
-    {
-      slot.name = name;
-      /* index_offset is set later.  */
-    }
-
-  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);
-
-  /* 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);
-}
-
-/* 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_with_cleanup (NULL, dwarf2_per_objfile_free);
-
-  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-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."), _("\
@@ -27324,17 +25545,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.123397 seconds and 4 git commands to generate.