[gdb/symtab] Fix Dwarf Error: cannot find DIE
[binutils-gdb.git] / gdb / dwarf2 / read.c
index 704ba9f36655b786f21a15153120c293a727cd26..3f496347cce22ae3160585235d8ae27928b31a0b 100644 (file)
@@ -32,7 +32,8 @@
 #include "dwarf2/read.h"
 #include "dwarf2/abbrev.h"
 #include "dwarf2/attribute.h"
-#include "dwarf2/comp-unit.h"
+#include "dwarf2/comp-unit-head.h"
+#include "dwarf2/cu.h"
 #include "dwarf2/index-cache.h"
 #include "dwarf2/index-common.h"
 #include "dwarf2/leb.h"
 #include "dwarf2/die.h"
 #include "dwarf2/sect-names.h"
 #include "dwarf2/stringify.h"
+#include "dwarf2/public.h"
 #include "bfd.h"
 #include "elf-bfd.h"
 #include "symtab.h"
 #include "gdbtypes.h"
 #include "objfiles.h"
 #include "dwarf2.h"
-#include "buildsym.h"
 #include "demangle.h"
 #include "gdb-demangle.h"
 #include "filenames.h" /* for DOSish file names */
@@ -87,6 +88,7 @@
 #include "rust-lang.h"
 #include "gdbsupport/pathstuff.h"
 #include "count-one-bits.h"
+#include <unordered_set>
 
 /* When == 1, print basic high level tracing messages.
    When > 1, be more verbose.
@@ -222,17 +224,50 @@ protected:
   ~mapped_index_base() = default;
 };
 
+/* This is a view into the index that converts from bytes to an
+   offset_type, and allows indexing.  Unaligned bytes are specifically
+   allowed here, and handled via unpacking.  */
+
+class offset_view
+{
+public:
+  offset_view () = default;
+
+  explicit offset_view (gdb::array_view<const gdb_byte> bytes)
+    : m_bytes (bytes)
+  {
+  }
+
+  /* Extract the INDEXth offset_type from the array.  */
+  offset_type operator[] (size_t index) const
+  {
+    const gdb_byte *bytes = &m_bytes[index * sizeof (offset_type)];
+    return (offset_type) extract_unsigned_integer (bytes,
+                                                  sizeof (offset_type),
+                                                  BFD_ENDIAN_LITTLE);
+  }
+
+  /* Return the number of offset_types in this array.  */
+  size_t size () const
+  {
+    return m_bytes.size () / sizeof (offset_type);
+  }
+
+  /* Return true if this view is empty.  */
+  bool empty () const
+  {
+    return m_bytes.empty ();
+  }
+
+private:
+  /* The underlying bytes.  */
+  gdb::array_view<const gdb_byte> m_bytes;
+};
+
 /* A description of the mapped index.  The file format is described in
    a comment by the code that writes the index.  */
 struct mapped_index final : public mapped_index_base
 {
-  /* A slot/bucket in the symbol table hash.  */
-  struct symbol_table_slot
-  {
-    const offset_type name;
-    const offset_type vec;
-  };
-
   /* Index data format version.  */
   int version = 0;
 
@@ -240,25 +275,42 @@ struct mapped_index final : public mapped_index_base
   gdb::array_view<const gdb_byte> address_table;
 
   /* The symbol table, implemented as a hash table.  */
-  gdb::array_view<symbol_table_slot> symbol_table;
+  offset_view symbol_table;
 
   /* A pointer to the constant pool.  */
-  const char *constant_pool = nullptr;
+  gdb::array_view<const gdb_byte> constant_pool;
+
+  /* Return the index into the constant pool of the name of the IDXth
+     symbol in the symbol table.  */
+  offset_type symbol_name_index (offset_type idx) const
+  {
+    return symbol_table[2 * idx];
+  }
+
+  /* Return the index into the constant pool of the CU vector of the
+     IDXth symbol in the symbol table.  */
+  offset_type symbol_vec_index (offset_type idx) const
+  {
+    return symbol_table[2 * idx + 1];
+  }
 
   bool symbol_name_slot_invalid (offset_type idx) const override
   {
-    const auto &bucket = this->symbol_table[idx];
-    return bucket.name == 0 && bucket.vec == 0;
+    return (symbol_name_index (idx) == 0
+           && symbol_vec_index (idx) == 0);
   }
 
   /* Convenience method to get at the name of the symbol at IDX in the
      symbol table.  */
   const char *symbol_name_at
     (offset_type idx, dwarf2_per_objfile *per_objfile) const override
-  { return this->constant_pool + MAYBE_SWAP (this->symbol_table[idx].name); }
+  {
+    return (const char *) (this->constant_pool.data ()
+                          + symbol_name_index (idx));
+  }
 
   size_t symbol_name_count () const override
-  { return this->symbol_table.size (); }
+  { return this->symbol_table.size () / 2; }
 };
 
 /* A description of the mapped .debug_names.
@@ -408,249 +460,6 @@ struct loclists_rnglists_header
   unsigned int offset_entry_count;
 };
 
-/* Type used for delaying computation of method physnames.
-   See comments for compute_delayed_physnames.  */
-struct delayed_method_info
-{
-  /* The type to which the method is attached, i.e., its parent class.  */
-  struct type *type;
-
-  /* The index of the method in the type's function fieldlists.  */
-  int fnfield_index;
-
-  /* The index of the method in the fieldlist.  */
-  int index;
-
-  /* The name of the DIE.  */
-  const char *name;
-
-  /*  The DIE associated with this method.  */
-  struct die_info *die;
-};
-
-/* Internal state when decoding a particular compilation unit.  */
-struct dwarf2_cu
-{
-  explicit dwarf2_cu (dwarf2_per_cu_data *per_cu,
-                     dwarf2_per_objfile *per_objfile);
-
-  DISABLE_COPY_AND_ASSIGN (dwarf2_cu);
-
-  /* TU version of handle_DW_AT_stmt_list for read_type_unit_scope.
-     Create the set of symtabs used by this TU, or if this TU is sharing
-     symtabs with another TU and the symtabs have already been created
-     then restore those symtabs in the line header.
-     We don't need the pc/line-number mapping for type units.  */
-  void setup_type_unit_groups (struct die_info *die);
-
-  /* Start a symtab for DWARF.  NAME, COMP_DIR, LOW_PC are passed to the
-     buildsym_compunit constructor.  */
-  struct compunit_symtab *start_symtab (const char *name,
-                                       const char *comp_dir,
-                                       CORE_ADDR low_pc);
-
-  /* Reset the builder.  */
-  void reset_builder () { m_builder.reset (); }
-
-  /* Return a type that is a generic pointer type, the size of which
-     matches the address size given in the compilation unit header for
-     this CU.  */
-  struct type *addr_type () const;
-
-  /* Find an integer type the same size as the address size given in
-     the compilation unit header for this CU.  UNSIGNED_P controls if
-     the integer is unsigned or not.  */
-  struct type *addr_sized_int_type (bool unsigned_p) const;
-
-  /* The header of the compilation unit.  */
-  struct comp_unit_head header {};
-
-  /* Base address of this compilation unit.  */
-  gdb::optional<CORE_ADDR> base_address;
-
-  /* The language we are debugging.  */
-  enum language language = language_unknown;
-  const struct language_defn *language_defn = nullptr;
-
-  const char *producer = nullptr;
-
-private:
-  /* The symtab builder for this CU.  This is only non-NULL when full
-     symbols are being read.  */
-  std::unique_ptr<buildsym_compunit> m_builder;
-
-public:
-  /* The generic symbol table building routines have separate lists for
-     file scope symbols and all all other scopes (local scopes).  So
-     we need to select the right one to pass to add_symbol_to_list().
-     We do it by keeping a pointer to the correct list in list_in_scope.
-
-     FIXME: The original dwarf code just treated the file scope as the
-     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 = nullptr;
-
-  /* Hash table holding all the loaded partial DIEs
-     with partial_die->offset.SECT_OFF as hash.  */
-  htab_t partial_dies = nullptr;
-
-  /* Storage for things with the same lifetime as this read-in compilation
-     unit, including partial DIEs.  */
-  auto_obstack comp_unit_obstack;
-
-  /* Backlink to our per_cu entry.  */
-  struct dwarf2_per_cu_data *per_cu;
-
-  /* The dwarf2_per_objfile that owns this.  */
-  dwarf2_per_objfile *per_objfile;
-
-  /* How many compilation units ago was this CU last referenced?  */
-  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 = nullptr;
-
-  /* Full DIEs if read in.  */
-  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 = nullptr;
-
-  /* Header data from the line table, during full symbol processing.  */
-  struct line_header *line_header = nullptr;
-  /* Non-NULL if LINE_HEADER is owned by this DWARF_CU.  Otherwise,
-     it's owned by dwarf2_per_bfd::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 = nullptr;
-
-  /* A list of methods which need to have physnames computed
-     after all type information has been read.  */
-  std::vector<delayed_method_info> method_list;
-
-  /* To be copied to symtab->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:
-     Except for attributes copied from the top level DIE in the "main"
-     (or "stub") file in preparation for reading the DWO file
-     (e.g., DW_AT_addr_base), we KISS: there is only *one* CU.
-     Either there isn't a DWO file (in which case this is NULL and the point
-     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 = nullptr;
-
-  /* The DW_AT_addr_base (DW_AT_GNU_addr_base) attribute if present.
-     Note this value comes from the Fission stub CU/TU's DIE.  */
-  gdb::optional<ULONGEST> addr_base;
-
-  /* The DW_AT_GNU_ranges_base attribute, if present.
-
-     This is only relevant in the context of pre-DWARF 5 split units.  In this
-     context, there is a .debug_ranges section in the linked executable,
-     containing all the ranges data for all the compilation units.  Each
-     skeleton/stub unit has (if needed) a DW_AT_GNU_ranges_base attribute that
-     indicates the base of its contribution to that section.  The DW_AT_ranges
-     attributes in the split-unit are of the form DW_FORM_sec_offset and point
-     into the .debug_ranges section of the linked file.  However, they are not
-     "true" DW_FORM_sec_offset, because they are relative to the base of their
-     compilation unit's contribution, rather than relative to the beginning of
-     the section.  The DW_AT_GNU_ranges_base value must be added to it to make
-     it relative to the beginning of the section.
-
-     Note that the value is zero when we are not in a pre-DWARF 5 split-unit
-     case, so this value can be added without needing to know whether we are in
-     this case or not.
-
-     N.B. If a DW_AT_ranges attribute is found on the DW_TAG_compile_unit in the
-     skeleton/stub, it must not have the base added, as it already points to the
-     right place.  And since the DW_TAG_compile_unit DIE in the split-unit can't
-     have a DW_AT_ranges attribute, we can use the
-
-       die->tag != DW_AT_compile_unit
-
-     to determine whether the base should be added or not.  */
-  ULONGEST gnu_ranges_base = 0;
-
-  /* The DW_AT_rnglists_base attribute, if present.
-
-     This is used when processing attributes of form DW_FORM_rnglistx in
-     non-split units.  Attributes of this form found in a split unit don't
-     use it, as split-unit files have their own non-shared .debug_rnglists.dwo
-     section.  */
-  ULONGEST rnglists_base = 0;
-
-  /* The DW_AT_loclists_base attribute if present.  */
-  ULONGEST loclist_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;
-
-  /* The DW_AT_str_offsets_base attribute if present.  For DWARF 4 version DWO
-     files, the value is implicitly zero.  For DWARF 5 version DWO files, the
-     value is often implicit and is the size of the header of
-     .debug_str_offsets section (8 or 4, depending on the address size).  */
-  gdb::optional<ULONGEST> str_offsets_base;
-
-  /* Mark used when releasing cached dies.  */
-  bool mark : 1;
-
-  /* This CU references .debug_loc.  See the symtab->locations_valid field.
-     This test is imperfect as there may exist optimized debug code not using
-     any location list and still facing inlining issues if handled as
-     unoptimized code.  For a future better test see GCC PR other/32998.  */
-  bool has_loclist : 1;
-
-  /* These cache the results for producer_is_* fields.  CHECKED_PRODUCER is true
-     if all the producer_is_* fields are valid.  This information is cached
-     because profiling CU expansion showed excessive time spent in
-     producer_is_gxx_lt_4_6.  */
-  bool checked_producer : 1;
-  bool producer_is_gxx_lt_4_6 : 1;
-  bool producer_is_gcc_lt_4_3 : 1;
-  bool producer_is_icc : 1;
-  bool producer_is_icc_lt_14 : 1;
-  bool producer_is_codewarrior : 1;
-
-  /* When true, the file that we're processing is known to have
-     debugging info for C++ namespaces.  GCC 3.3.x did not produce
-     this information, but later versions do.  */
-
-  bool processing_has_namespace_info : 1;
-
-  struct partial_die_info *find_partial_die (sect_offset sect_off);
-
-  /* If this CU was inherited by another CU (via specification,
-     abstract_origin, etc), this is the ancestor CU.  */
-  dwarf2_cu *ancestor;
-
-  /* Get the buildsym_compunit for this CU.  */
-  buildsym_compunit *get_builder ()
-  {
-    /* If this CU has a builder associated with it, use that.  */
-    if (m_builder != nullptr)
-      return m_builder.get ();
-
-    /* Otherwise, search ancestors for a valid builder.  */
-    if (ancestor != nullptr)
-      return ancestor->get_builder ();
-
-    return nullptr;
-  }
-};
-
 /* 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.  */
 
@@ -668,21 +477,15 @@ struct stmt_list_hash
    that can be shared across objfiles.  The non-shareable parts are in
    type_unit_group_unshareable.  */
 
-struct type_unit_group
+struct type_unit_group : public dwarf2_per_cu_data
 {
-  /* dwarf2read.c's main "handle" on a TU symtab.
-     To simplify things we create an artificial CU that "includes" all the
-     type units using this stmt_list so that the rest of the code still has
-     a "per_cu" handle on the symtab.  */
-  struct dwarf2_per_cu_data per_cu;
-
   /* The TUs that share this DW_AT_stmt_list entry.
      This is added to while parsing type units to build partial symtabs,
      and is deleted afterwards and not used again.  */
-  std::vector<signatured_type *> *tus;
+  std::vector<signatured_type *> *tus = nullptr;
 
   /* The data used to construct the hash key.  */
-  struct stmt_list_hash hash;
+  struct stmt_list_hash hash {};
 };
 
 /* These sections are what may appear in a (real or virtual) DWO file.  */
@@ -1643,8 +1446,6 @@ static struct type *set_die_type (struct die_info *, struct type *,
 
 static void create_all_comp_units (dwarf2_per_objfile *per_objfile);
 
-static int create_all_type_units (dwarf2_per_objfile *per_objfile);
-
 static void load_full_comp_unit (dwarf2_per_cu_data *per_cu,
                                 dwarf2_per_objfile *per_objfile,
                                 dwarf2_cu *existing_cu,
@@ -1657,11 +1458,6 @@ static void process_full_comp_unit (dwarf2_cu *cu,
 static void process_full_type_unit (dwarf2_cu *cu,
                                    enum language pretend_language);
 
-static void dwarf2_add_dependence (struct dwarf2_cu *,
-                                  struct dwarf2_per_cu_data *);
-
-static void dwarf2_mark (struct dwarf2_cu *);
-
 static struct type *get_die_type_at_offset (sect_offset,
                                            dwarf2_per_cu_data *per_cu,
                                            dwarf2_per_objfile *per_objfile);
@@ -1716,6 +1512,17 @@ dwarf2_queue_item::~dwarf2_queue_item ()
     }
 }
 
+/* See dwarf2/read.h.  */
+
+void
+dwarf2_per_cu_data_deleter::operator() (dwarf2_per_cu_data *data)
+{
+  if (data->is_debug_types)
+    delete static_cast<signatured_type *> (data);
+  else
+    delete data;
+}
+
 /* The return type of find_file_and_directory.  Note, the enclosed
    string pointers are only valid while this object is valid.  */
 
@@ -1764,8 +1571,6 @@ typedef std::unique_ptr<struct dwo_file> dwo_file_up;
 static void process_cu_includes (dwarf2_per_objfile *per_objfile);
 
 static void check_producer (struct dwarf2_cu *cu);
-
-static void free_line_header_voidp (void *arg);
 \f
 /* Various complaints about symbol reading that don't abort the process.  */
 
@@ -1851,12 +1656,9 @@ dwarf2_per_bfd::dwarf2_per_bfd (bfd *obfd, const dwarf2_debug_sections *names,
 
 dwarf2_per_bfd::~dwarf2_per_bfd ()
 {
-  for (dwarf2_per_cu_data *per_cu : all_comp_units)
+  for (auto &per_cu : all_comp_units)
     per_cu->imported_symtabs_free ();
 
-  for (signatured_type *sig_type : all_type_units)
-    sig_type->per_cu.imported_symtabs_free ();
-
   /* Everything else should be on this->obstack.  */
 }
 
@@ -1950,11 +1752,14 @@ dwarf2_has_info (struct objfile *objfile,
     {
       dwarf2_per_bfd *per_bfd;
 
-      /* We can share a "dwarf2_per_bfd" with other objfiles if the BFD
-        doesn't require relocations and if there aren't partial symbols
-        from some other reader.  */
-      if (!objfile_has_partial_symbols (objfile)
-         && !gdb_bfd_requires_relocations (objfile->obfd))
+      /* We can share a "dwarf2_per_bfd" with other objfiles if the
+        BFD doesn't require relocations.
+
+        We don't share with objfiles for which -readnow was requested,
+        because it would complicate things when loading the same BFD with
+        -readnow and then without -readnow.  */
+      if (!gdb_bfd_requires_relocations (objfile->obfd)
+         && (objfile->flags & OBJF_READNOW) == 0)
        {
          /* See if one has been created for this BFD yet.  */
          per_bfd = dwarf2_per_bfd_bfd_data_key.get (objfile->obfd);
@@ -2149,7 +1954,7 @@ dwarf2_get_section_info (struct objfile *objfile,
 }
 
 \f
-/* DWARF quick_symbols_functions support.  */
+/* DWARF quick_symbol_functions support.  */
 
 /* TUs can share .debug_line entries, and there can be a lot more TUs than
    unique line tables, so we maintain a separate table of all .debug_line
@@ -2192,6 +1997,122 @@ struct dwarf2_per_cu_quick_data
   unsigned int no_file_data : 1;
 };
 
+/* A subclass of psymbol_functions that arranges to read the DWARF
+   partial symbols when needed.  */
+struct lazy_dwarf_reader : public psymbol_functions
+{
+  using psymbol_functions::psymbol_functions;
+
+  bool can_lazily_read_symbols () override
+  {
+    return true;
+  }
+
+  void read_partial_symbols (struct objfile *objfile) override
+  {
+    if (dwarf2_has_info (objfile, nullptr))
+      dwarf2_build_psymtabs (objfile, this);
+  }
+};
+
+static quick_symbol_functions_up
+make_lazy_dwarf_reader ()
+{
+  return quick_symbol_functions_up (new lazy_dwarf_reader);
+}
+
+struct dwarf2_base_index_functions : public quick_symbol_functions
+{
+  bool has_symbols (struct objfile *objfile) override;
+
+  struct symtab *find_last_source_symtab (struct objfile *objfile) override;
+
+  void forget_cached_source_info (struct objfile *objfile) override;
+
+  enum language lookup_global_symbol_language (struct objfile *objfile,
+                                              const char *name,
+                                              domain_enum domain,
+                                              bool *symbol_found_p) override
+  {
+    *symbol_found_p = false;
+    return language_unknown;
+  }
+
+  void print_stats (struct objfile *objfile, bool print_bcache) override;
+
+  void expand_all_symtabs (struct objfile *objfile) override;
+
+  struct compunit_symtab *find_pc_sect_compunit_symtab
+    (struct objfile *objfile, struct bound_minimal_symbol msymbol,
+     CORE_ADDR pc, struct obj_section *section, int warn_if_readin) override;
+
+  struct compunit_symtab *find_compunit_symtab_by_address
+    (struct objfile *objfile, CORE_ADDR address) override
+  {
+    return nullptr;
+  }
+
+  void map_symbol_filenames (struct objfile *objfile,
+                            gdb::function_view<symbol_filename_ftype> fun,
+                            bool need_fullname) override;
+};
+
+struct dwarf2_gdb_index : public dwarf2_base_index_functions
+{
+  void dump (struct objfile *objfile) override;
+
+  void expand_matching_symbols
+    (struct objfile *,
+     const lookup_name_info &lookup_name,
+     domain_enum domain,
+     int global,
+     symbol_compare_ftype *ordered_compare) override;
+
+  bool expand_symtabs_matching
+    (struct objfile *objfile,
+     gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
+     const lookup_name_info *lookup_name,
+     gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
+     gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+     block_search_flags search_flags,
+     domain_enum domain,
+     enum search_domain kind) override;
+};
+
+struct dwarf2_debug_names_index : public dwarf2_base_index_functions
+{
+  void dump (struct objfile *objfile) override;
+
+  void expand_matching_symbols
+    (struct objfile *,
+     const lookup_name_info &lookup_name,
+     domain_enum domain,
+     int global,
+     symbol_compare_ftype *ordered_compare) override;
+
+  bool expand_symtabs_matching
+    (struct objfile *objfile,
+     gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
+     const lookup_name_info *lookup_name,
+     gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
+     gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+     block_search_flags search_flags,
+     domain_enum domain,
+     enum search_domain kind) override;
+};
+
+static quick_symbol_functions_up
+make_dwarf_gdb_index ()
+{
+  return quick_symbol_functions_up (new dwarf2_gdb_index);
+}
+
+static quick_symbol_functions_up
+make_dwarf_debug_names ()
+{
+  return quick_symbol_functions_up (new dwarf2_debug_names_index);
+}
+
 /* Utility hash function for a stmt_list_hash.  */
 
 static hashval_t
@@ -2360,47 +2281,12 @@ dw2_instantiate_symtab (dwarf2_per_cu_data *per_cu,
   return per_objfile->get_symtab (per_cu);
 }
 
-/* See declaration.  */
-
-dwarf2_per_cu_data *
-dwarf2_per_bfd::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;
-    }
-
-  return this->all_comp_units[index];
-}
-
-/* See declaration.  */
-
-dwarf2_per_cu_data *
-dwarf2_per_bfd::get_cu (int index)
-{
-  gdb_assert (index >= 0 && index < this->all_comp_units.size ());
-
-  return this->all_comp_units[index];
-}
-
-/* See declaration.  */
-
-signatured_type *
-dwarf2_per_bfd::get_tu (int index)
-{
-  gdb_assert (index >= 0 && index < this->all_type_units.size ());
-
-  return this->all_type_units[index];
-}
-
 /* See read.h.  */
 
-dwarf2_per_cu_data *
+dwarf2_per_cu_data_up
 dwarf2_per_bfd::allocate_per_cu ()
 {
-  dwarf2_per_cu_data *result = OBSTACK_ZALLOC (&obstack, dwarf2_per_cu_data);
+  dwarf2_per_cu_data_up result (new dwarf2_per_cu_data);
   result->per_bfd = this;
   result->index = m_num_psymtabs++;
   return result;
@@ -2408,25 +2294,26 @@ dwarf2_per_bfd::allocate_per_cu ()
 
 /* See read.h.  */
 
-signatured_type *
+std::unique_ptr<signatured_type>
 dwarf2_per_bfd::allocate_signatured_type ()
 {
-  signatured_type *result = OBSTACK_ZALLOC (&obstack, signatured_type);
-  result->per_cu.per_bfd = this;
-  result->per_cu.index = m_num_psymtabs++;
+  std::unique_ptr<signatured_type> result (new signatured_type);
+  result->per_bfd = this;
+  result->index = m_num_psymtabs++;
+  tu_stats.nr_tus++;
   return result;
 }
 
 /* Return a new dwarf2_per_cu_data allocated on the per-bfd
    obstack, and constructed with the specified field values.  */
 
-static dwarf2_per_cu_data *
+static dwarf2_per_cu_data_up
 create_cu_from_index_list (dwarf2_per_bfd *per_bfd,
                           struct dwarf2_section_info *section,
                           int is_dwz,
                           sect_offset sect_off, ULONGEST length)
 {
-  dwarf2_per_cu_data *the_cu = per_bfd->allocate_per_cu ();
+  dwarf2_per_cu_data_up the_cu = per_bfd->allocate_per_cu ();
   the_cu->sect_off = sect_off;
   the_cu->length = length;
   the_cu->section = section;
@@ -2454,10 +2341,10 @@ create_cus_from_index_list (dwarf2_per_bfd *per_bfd,
       ULONGEST length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE);
       cu_list += 2 * 8;
 
-      dwarf2_per_cu_data *per_cu
+      dwarf2_per_cu_data_up per_cu
        = create_cu_from_index_list (per_bfd, section, is_dwz, sect_off,
                                     length);
-      per_bfd->all_comp_units.push_back (per_cu);
+      per_bfd->all_comp_units.push_back (std::move (per_cu));
     }
 }
 
@@ -2490,14 +2377,11 @@ create_signatured_type_table_from_index
   (dwarf2_per_bfd *per_bfd, struct dwarf2_section_info *section,
    const gdb_byte *bytes, offset_type elements)
 {
-  gdb_assert (per_bfd->all_type_units.empty ());
-  per_bfd->all_type_units.reserve (elements / 3);
-
   htab_up sig_types_hash = allocate_signatured_type_table ();
 
   for (offset_type i = 0; i < elements; i += 3)
     {
-      struct signatured_type *sig_type;
+      std::unique_ptr<signatured_type> sig_type;
       ULONGEST signature;
       void **slot;
       cu_offset type_offset_in_tu;
@@ -2514,17 +2398,17 @@ create_signatured_type_table_from_index
       sig_type = per_bfd->allocate_signatured_type ();
       sig_type->signature = signature;
       sig_type->type_offset_in_tu = type_offset_in_tu;
-      sig_type->per_cu.is_debug_types = 1;
-      sig_type->per_cu.section = section;
-      sig_type->per_cu.sect_off = sect_off;
-      sig_type->per_cu.v.quick
+      sig_type->is_debug_types = 1;
+      sig_type->section = section;
+      sig_type->sect_off = sect_off;
+      sig_type->v.quick
        = OBSTACK_ZALLOC (&per_bfd->obstack,
                          struct dwarf2_per_cu_quick_data);
 
-      slot = htab_find_slot (sig_types_hash.get (), sig_type, INSERT);
-      *slot = sig_type;
+      slot = htab_find_slot (sig_types_hash.get (), sig_type.get (), INSERT);
+      *slot = sig_type.get ();
 
-      per_bfd->all_type_units.push_back (sig_type);
+      per_bfd->all_comp_units.emplace_back (sig_type.release ());
     }
 
   per_bfd->signatured_types = std::move (sig_types_hash);
@@ -2544,14 +2428,11 @@ create_signatured_type_table_from_debug_names
   section->read (objfile);
   abbrev_section->read (objfile);
 
-  gdb_assert (per_objfile->per_bfd->all_type_units.empty ());
-  per_objfile->per_bfd->all_type_units.reserve (map.tu_count);
-
   htab_up sig_types_hash = allocate_signatured_type_table ();
 
   for (uint32_t i = 0; i < map.tu_count; ++i)
     {
-      struct signatured_type *sig_type;
+      std::unique_ptr<signatured_type> sig_type;
       void **slot;
 
       sect_offset sect_off
@@ -2569,30 +2450,31 @@ create_signatured_type_table_from_debug_names
       sig_type = per_objfile->per_bfd->allocate_signatured_type ();
       sig_type->signature = cu_header.signature;
       sig_type->type_offset_in_tu = cu_header.type_cu_offset_in_tu;
-      sig_type->per_cu.is_debug_types = 1;
-      sig_type->per_cu.section = section;
-      sig_type->per_cu.sect_off = sect_off;
-      sig_type->per_cu.v.quick
+      sig_type->is_debug_types = 1;
+      sig_type->section = section;
+      sig_type->sect_off = sect_off;
+      sig_type->v.quick
        = OBSTACK_ZALLOC (&per_objfile->per_bfd->obstack,
                          struct dwarf2_per_cu_quick_data);
 
-      slot = htab_find_slot (sig_types_hash.get (), sig_type, INSERT);
-      *slot = sig_type;
+      slot = htab_find_slot (sig_types_hash.get (), sig_type.get (), INSERT);
+      *slot = sig_type.get ();
 
-      per_objfile->per_bfd->all_type_units.push_back (sig_type);
+      per_objfile->per_bfd->all_comp_units.emplace_back (sig_type.release ());
     }
 
   per_objfile->per_bfd->signatured_types = std::move (sig_types_hash);
 }
 
 /* Read the address map data from the mapped index, and use it to
-   populate the objfile's psymtabs_addrmap.  */
+   populate the psymtabs_addrmap.  */
 
 static void
 create_addrmap_from_index (dwarf2_per_objfile *per_objfile,
                           struct mapped_index *index)
 {
   struct objfile *objfile = per_objfile->objfile;
+  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
   struct gdbarch *gdbarch = objfile->arch ();
   const gdb_byte *iter, *end;
   struct addrmap *mutable_map;
@@ -2624,7 +2506,7 @@ create_addrmap_from_index (dwarf2_per_objfile *per_objfile,
          continue;
        }
 
-      if (cu_index >= per_objfile->per_bfd->all_comp_units.size ())
+      if (cu_index >= per_bfd->all_comp_units.size ())
        {
          complaint (_(".gdb_index address table has invalid CU number %u"),
                     (unsigned) cu_index);
@@ -2634,15 +2516,15 @@ create_addrmap_from_index (dwarf2_per_objfile *per_objfile,
       lo = gdbarch_adjust_dwarf2_addr (gdbarch, lo + baseaddr) - baseaddr;
       hi = gdbarch_adjust_dwarf2_addr (gdbarch, hi + baseaddr) - baseaddr;
       addrmap_set_empty (mutable_map, lo, hi - 1,
-                        per_objfile->per_bfd->get_cu (cu_index));
+                        per_bfd->get_cu (cu_index));
     }
 
-  objfile->partial_symtabs->psymtabs_addrmap
-    = addrmap_create_fixed (mutable_map, objfile->partial_symtabs->obstack ());
+  per_bfd->index_addrmap = addrmap_create_fixed (mutable_map,
+                                                &per_bfd->obstack);
 }
 
 /* Read the address map data from DWARF-5 .debug_aranges, and use it to
-   populate the objfile's psymtabs_addrmap.  */
+   populate the psymtabs_addrmap.  */
 
 static void
 create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
@@ -2652,6 +2534,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
   bfd *abfd = objfile->obfd;
   struct gdbarch *gdbarch = objfile->arch ();
   const CORE_ADDR baseaddr = objfile->text_section_offset ();
+  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
 
   auto_obstack temp_obstack;
   addrmap *mutable_map = addrmap_create_mutable (&temp_obstack);
@@ -2660,10 +2543,11 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                     dwarf2_per_cu_data *,
                     gdb::hash_enum<sect_offset>>
     debug_info_offset_to_per_cu;
-  for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
+  for (const auto &per_cu : per_bfd->all_comp_units)
     {
       const auto insertpair
-       = debug_info_offset_to_per_cu.emplace (per_cu->sect_off, per_cu);
+       = debug_info_offset_to_per_cu.emplace (per_cu->sect_off,
+                                              per_cu.get ());
       if (!insertpair.second)
        {
          warning (_("Section .debug_aranges in %s has duplicate "
@@ -2788,7 +2672,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
          addr += address_size;
          if (start == 0 && length == 0)
            break;
-         if (start == 0 && !per_objfile->per_bfd->has_section_at_zero)
+         if (start == 0 && !per_bfd->has_section_at_zero)
            {
              /* Symbol was eliminated due to a COMDAT group.  */
              continue;
@@ -2802,70 +2686,8 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
        }
     }
 
-  objfile->partial_symtabs->psymtabs_addrmap
-    = addrmap_create_fixed (mutable_map, objfile->partial_symtabs->obstack ());
-}
-
-/* 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
-   false.  */
-
-static bool
-find_slot_in_mapped_hash (struct mapped_index *index, const char *name,
-                         offset_type **vec_out)
-{
-  offset_type hash;
-  offset_type slot, step;
-  int (*cmp) (const char *, const char *);
-
-  gdb::unique_xmalloc_ptr<char> without_params;
-  if (current_language->la_language == language_cplus
-      || current_language->la_language == language_fortran
-      || current_language->la_language == language_d)
-    {
-      /* NAME is already canonical.  Drop any qualifiers as .gdb_index does
-        not contain any.  */
-
-      if (strchr (name, '(') != NULL)
-       {
-         without_params = cp_remove_params (name);
-
-         if (without_params != NULL)
-           name = without_params.get ();
-       }
-    }
-
-  /* Index version 4 did not support case insensitive searches.  But the
-     indices for case insensitive languages are built in lowercase, therefore
-     simulate our NAME being searched is also lowercased.  */
-  hash = mapped_index_string_hash ((index->version == 4
-                                   && case_sensitivity == case_sensitive_off
-                                   ? 5 : index->version),
-                                  name);
-
-  slot = hash & (index->symbol_table.size () - 1);
-  step = ((hash * 17) & (index->symbol_table.size () - 1)) | 1;
-  cmp = (case_sensitivity == case_sensitive_on ? strcmp : strcasecmp);
-
-  for (;;)
-    {
-      const char *str;
-
-      const auto &bucket = index->symbol_table[slot];
-      if (bucket.name == 0 && bucket.vec == 0)
-       return false;
-
-      str = index->constant_pool + MAYBE_SWAP (bucket.name);
-      if (!cmp (name, str))
-       {
-         *vec_out = (offset_type *) (index->constant_pool
-                                     + MAYBE_SWAP (bucket.vec));
-         return true;
-       }
-
-      slot = (slot + step) & (index->symbol_table.size () - 1);
-    }
+  per_bfd->index_addrmap = addrmap_create_fixed (mutable_map,
+                                                &per_bfd->obstack);
 }
 
 /* A helper function that reads the .gdb_index from BUFFER and fills
@@ -2890,9 +2712,10 @@ read_gdb_index_from_buffer (const char *filename,
                            offset_type *types_list_elements)
 {
   const gdb_byte *addr = &buffer[0];
+  offset_view metadata (buffer);
 
   /* Version check.  */
-  offset_type version = MAYBE_SWAP (*(offset_type *) addr);
+  offset_type version = metadata[0];
   /* Versions earlier than 3 emitted every copy of a psymbol.  This
      causes the index to behave very poorly for certain requests.  Version 3
      contained incomplete addrmap.  So, it seems better to just ignore such
@@ -2945,35 +2768,29 @@ to use the section anyway."),
 
   map->version = version;
 
-  offset_type *metadata = (offset_type *) (addr + sizeof (offset_type));
-
-  int i = 0;
-  *cu_list = addr + MAYBE_SWAP (metadata[i]);
-  *cu_list_elements = ((MAYBE_SWAP (metadata[i + 1]) - MAYBE_SWAP (metadata[i]))
-                      / 8);
+  int i = 1;
+  *cu_list = addr + metadata[i];
+  *cu_list_elements = (metadata[i + 1] - metadata[i]) / 8;
   ++i;
 
-  *types_list = addr + MAYBE_SWAP (metadata[i]);
-  *types_list_elements = ((MAYBE_SWAP (metadata[i + 1])
-                          - MAYBE_SWAP (metadata[i]))
-                         / 8);
+  *types_list = addr + metadata[i];
+  *types_list_elements = (metadata[i + 1] - metadata[i]) / 8;
   ++i;
 
-  const gdb_byte *address_table = addr + MAYBE_SWAP (metadata[i]);
-  const gdb_byte *address_table_end = addr + MAYBE_SWAP (metadata[i + 1]);
+  const gdb_byte *address_table = addr + metadata[i];
+  const gdb_byte *address_table_end = addr + metadata[i + 1];
   map->address_table
     = gdb::array_view<const gdb_byte> (address_table, address_table_end);
   ++i;
 
-  const gdb_byte *symbol_table = addr + MAYBE_SWAP (metadata[i]);
-  const gdb_byte *symbol_table_end = addr + MAYBE_SWAP (metadata[i + 1]);
+  const gdb_byte *symbol_table = addr + metadata[i];
+  const gdb_byte *symbol_table_end = addr + metadata[i + 1];
   map->symbol_table
-    = gdb::array_view<mapped_index::symbol_table_slot>
-       ((mapped_index::symbol_table_slot *) symbol_table,
-       (mapped_index::symbol_table_slot *) symbol_table_end);
+    = offset_view (gdb::array_view<const gdb_byte> (symbol_table,
+                                                   symbol_table_end));
 
   ++i;
-  map->constant_pool = (char *) (addr + MAYBE_SWAP (metadata[i]));
+  map->constant_pool = buffer.slice (metadata[i]);
 
   return 1;
 }
@@ -3070,11 +2887,6 @@ dwarf2_read_gdb_index
   per_bfd->quick_file_names_table =
     create_quick_file_names_table (per_bfd->all_comp_units.size ());
 
-  /* Save partial symtabs in the per_bfd object, for the benefit of subsequent
-     objfiles using the same BFD.  */
-  gdb_assert (per_bfd->partial_symtabs == nullptr);
-  per_bfd->partial_symtabs = objfile->partial_symtabs;
-
   return 1;
 }
 
@@ -3205,11 +3017,12 @@ dw2_get_real_path (dwarf2_per_objfile *per_objfile,
   return qfn->real_names[index];
 }
 
-static struct symtab *
-dw2_find_last_source_symtab (struct objfile *objfile)
+struct symtab *
+dwarf2_base_index_functions::find_last_source_symtab (struct objfile *objfile)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-  dwarf2_per_cu_data *dwarf_cu = per_objfile->per_bfd->all_comp_units.back ();
+  dwarf2_per_cu_data *dwarf_cu
+    = per_objfile->per_bfd->all_comp_units.back ().get ();
   compunit_symtab *cust = dw2_instantiate_symtab (dwarf_cu, per_objfile, false);
 
   if (cust == NULL)
@@ -3239,8 +3052,9 @@ dw2_free_cached_file_names (void **slot, void *info)
   return 1;
 }
 
-static void
-dw2_forget_cached_source_info (struct objfile *objfile)
+void
+dwarf2_base_index_functions::forget_cached_source_info
+     (struct objfile *objfile)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
@@ -3248,100 +3062,6 @@ dw2_forget_cached_source_info (struct objfile *objfile)
                          dw2_free_cached_file_names, NULL);
 }
 
-/* Helper function for dw2_map_symtabs_matching_filename that expands
-   the symtabs and calls the iterator.  */
-
-static int
-dw2_map_expand_apply (struct objfile *objfile,
-                     struct dwarf2_per_cu_data *per_cu,
-                     const char *name, const char *real_path,
-                     gdb::function_view<bool (symtab *)> callback)
-{
-  struct compunit_symtab *last_made = objfile->compunit_symtabs;
-
-  /* Don't visit already-expanded CUs.  */
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-  if (per_objfile->symtab_set_p (per_cu))
-    return 0;
-
-  /* This may expand more than one symtab, and we want to iterate over
-     all of them.  */
-  dw2_instantiate_symtab (per_cu, per_objfile, false);
-
-  return iterate_over_some_symtabs (name, real_path, objfile->compunit_symtabs,
-                                   last_made, callback);
-}
-
-/* Implementation of the map_symtabs_matching_filename method.  */
-
-static bool
-dw2_map_symtabs_matching_filename
-  (struct objfile *objfile, const char *name, const char *real_path,
-   gdb::function_view<bool (symtab *)> callback)
-{
-  const char *name_basename = lbasename (name);
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
-  /* The rule is CUs specify all the files, including those used by
-     any TU, so there's no need to scan TUs here.  */
-
-  for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
-    {
-      /* We only need to look at symtabs not already expanded.  */
-      if (per_objfile->symtab_set_p (per_cu))
-       continue;
-
-      quick_file_names *file_data = dw2_get_file_names (per_cu, per_objfile);
-      if (file_data == NULL)
-       continue;
-
-      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;
-
-         if (compare_filenames_for_search (this_name, name))
-           {
-             if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
-                                       callback))
-               return true;
-             continue;
-           }
-
-         /* Before we invoke realpath, which can get expensive when many
-            files are involved, do a quick comparison of the basenames.  */
-         if (! basenames_may_differ
-             && FILENAME_CMP (lbasename (this_name), name_basename) != 0)
-           continue;
-
-         this_real_name = dw2_get_real_path (per_objfile, file_data, j);
-         if (compare_filenames_for_search (this_real_name, name))
-           {
-             if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
-                                       callback))
-               return true;
-             continue;
-           }
-
-         if (real_path != NULL)
-           {
-             gdb_assert (IS_ABSOLUTE_PATH (real_path));
-             gdb_assert (IS_ABSOLUTE_PATH (name));
-             if (this_real_name != NULL
-                 && FILENAME_CMP (real_path, this_real_name) == 0)
-               {
-                 if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
-                                           callback))
-                   return true;
-                 continue;
-               }
-           }
-       }
-    }
-
-  return false;
-}
-
 /* Struct used to manage iterating over all CUs looking for a symbol.  */
 
 struct dw2_symtab_iterator
@@ -3355,7 +3075,7 @@ struct dw2_symtab_iterator
   domain_enum domain;
   /* The list of CUs from the index entry of the symbol,
      or NULL if not found.  */
-  offset_type *vec;
+  offset_view vec;
   /* The next element in VEC to look at.  */
   int next;
   /* The number of elements in VEC, or zero if there is no match.  */
@@ -3367,52 +3087,21 @@ struct dw2_symtab_iterator
   int global_seen;
 };
 
-/* Initialize the index symtab iterator ITER, common part.  */
+/* Initialize the index symtab iterator ITER, offset_type NAMEI variant.  */
 
 static void
-dw2_symtab_iter_init_common (struct dw2_symtab_iterator *iter,
-                            dwarf2_per_objfile *per_objfile,
-                            gdb::optional<block_enum> block_index,
-                            domain_enum domain)
+dw2_symtab_iter_init (struct dw2_symtab_iterator *iter,
+                     dwarf2_per_objfile *per_objfile,
+                     gdb::optional<block_enum> block_index,
+                     domain_enum domain, offset_type namei)
 {
   iter->per_objfile = per_objfile;
   iter->block_index = block_index;
   iter->domain = domain;
   iter->next = 0;
   iter->global_seen = 0;
-  iter->vec = NULL;
+  iter->vec = {};
   iter->length = 0;
-}
-
-/* Initialize the index symtab iterator ITER, const char *NAME variant.  */
-
-static void
-dw2_symtab_iter_init (struct dw2_symtab_iterator *iter,
-                     dwarf2_per_objfile *per_objfile,
-                     gdb::optional<block_enum> block_index,
-                     domain_enum domain,
-                     const char *name)
-{
-  dw2_symtab_iter_init_common (iter, per_objfile, block_index, domain);
-
-  mapped_index *index = per_objfile->per_bfd->index_table.get ();
-  /* index is NULL if OBJF_READNOW.  */
-  if (index == NULL)
-    return;
-
-  if (find_slot_in_mapped_hash (index, name, &iter->vec))
-    iter->length = MAYBE_SWAP (*iter->vec);
-}
-
-/* Initialize the index symtab iterator ITER, offset_type NAMEI variant.  */
-
-static void
-dw2_symtab_iter_init (struct dw2_symtab_iterator *iter,
-                     dwarf2_per_objfile *per_objfile,
-                     gdb::optional<block_enum> block_index,
-                     domain_enum domain, offset_type namei)
-{
-  dw2_symtab_iter_init_common (iter, per_objfile, block_index, domain);
 
   mapped_index *index = per_objfile->per_bfd->index_table.get ();
   /* index is NULL if OBJF_READNOW.  */
@@ -3420,11 +3109,10 @@ dw2_symtab_iter_init (struct dw2_symtab_iterator *iter,
     return;
 
   gdb_assert (!index->symbol_name_slot_invalid (namei));
-  const auto &bucket = index->symbol_table[namei];
+  offset_type vec_idx = index->symbol_vec_index (namei);
 
-  iter->vec = (offset_type *) (index->constant_pool
-                              + MAYBE_SWAP (bucket.vec));
-  iter->length = MAYBE_SWAP (*iter->vec);
+  iter->vec = offset_view (index->constant_pool.slice (vec_idx));
+  iter->length = iter->vec[0];
 }
 
 /* Return the next matching CU or NULL if there are no more.  */
@@ -3436,8 +3124,7 @@ dw2_symtab_iter_next (struct dw2_symtab_iterator *iter)
 
   for ( ; iter->next < iter->length; ++iter->next)
     {
-      offset_type cu_index_and_attrs =
-       MAYBE_SWAP (iter->vec[iter->next + 1]);
+      offset_type cu_index_and_attrs = iter->vec[iter->next + 1];
       offset_type cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
       gdb_index_symbol_kind symbol_kind =
        GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
@@ -3450,15 +3137,14 @@ 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 >= (per_objfile->per_bfd->all_comp_units.size ()
-                      + per_objfile->per_bfd->all_type_units.size ()))
+      if (cu_index >= per_objfile->per_bfd->all_comp_units.size ())
        {
          complaint (_(".gdb_index entry has bad CU index"
                       " [in module %s]"), objfile_name (per_objfile->objfile));
          continue;
        }
 
-      dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cutu (cu_index);
+      dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cu (cu_index);
 
       /* Skip if already read in.  */
       if (per_objfile->symtab_set_p (per_cu))
@@ -3524,60 +3210,20 @@ dw2_symtab_iter_next (struct dw2_symtab_iterator *iter)
   return NULL;
 }
 
-static struct compunit_symtab *
-dw2_lookup_symbol (struct objfile *objfile, block_enum block_index,
-                  const char *name, domain_enum domain)
+void
+dwarf2_base_index_functions::print_stats (struct objfile *objfile,
+                                         bool print_bcache)
 {
-  struct compunit_symtab *stab_best = NULL;
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
-  lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
-
-  struct dw2_symtab_iterator iter;
-  struct dwarf2_per_cu_data *per_cu;
-
-  dw2_symtab_iter_init (&iter, per_objfile, block_index, domain, name);
-
-  while ((per_cu = dw2_symtab_iter_next (&iter)) != NULL)
-    {
-      struct symbol *sym, *with_opaque = NULL;
-      struct compunit_symtab *stab
-       = dw2_instantiate_symtab (per_cu, per_objfile, false);
-      const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (stab);
-      const struct block *block = BLOCKVECTOR_BLOCK (bv, block_index);
-
-      sym = block_find_symbol (block, name, domain,
-                              block_find_non_opaque_type_preferred,
-                              &with_opaque);
-
-      /* Some caution must be observed with overloaded functions
-        and methods, since the index will not contain any overload
-        information (but NAME might contain it).  */
-
-      if (sym != NULL
-         && SYMBOL_MATCHES_SEARCH_NAME (sym, lookup_name))
-       return stab;
-      if (with_opaque != NULL
-         && SYMBOL_MATCHES_SEARCH_NAME (with_opaque, lookup_name))
-       stab_best = stab;
-
-      /* Keep looking through other CUs.  */
-    }
-
-  return stab_best;
-}
+  if (print_bcache)
+    return;
 
-static void
-dw2_print_stats (struct objfile *objfile)
-{
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-  int total = (per_objfile->per_bfd->all_comp_units.size ()
-              + per_objfile->per_bfd->all_type_units.size ());
+  int total = per_objfile->per_bfd->all_comp_units.size ();
   int count = 0;
 
   for (int i = 0; i < total; ++i)
     {
-      dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cutu (i);
+      dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cu (i);
 
       if (!per_objfile->symtab_set_p (per_cu))
        ++count;
@@ -3591,8 +3237,8 @@ dw2_print_stats (struct objfile *objfile)
    One use is to verify .gdb_index has been loaded by the
    gdb.dwarf2/gdb-index.exp testcase.  */
 
-static void
-dw2_dump (struct objfile *objfile)
+void
+dwarf2_gdb_index::dump (struct objfile *objfile)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
@@ -3608,32 +3254,15 @@ dw2_dump (struct objfile *objfile)
   printf_filtered ("\n");
 }
 
-static void
-dw2_expand_symtabs_for_function (struct objfile *objfile,
-                                const char *func_name)
-{
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
-  struct dw2_symtab_iterator iter;
-  struct dwarf2_per_cu_data *per_cu;
-
-  dw2_symtab_iter_init (&iter, per_objfile, {}, VAR_DOMAIN, func_name);
-
-  while ((per_cu = dw2_symtab_iter_next (&iter)) != NULL)
-    dw2_instantiate_symtab (per_cu, per_objfile, false);
-
-}
-
-static void
-dw2_expand_all_symtabs (struct objfile *objfile)
+void
+dwarf2_base_index_functions::expand_all_symtabs (struct objfile *objfile)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-  int total_units = (per_objfile->per_bfd->all_comp_units.size ()
-                    + per_objfile->per_bfd->all_type_units.size ());
+  int total_units = per_objfile->per_bfd->all_comp_units.size ();
 
   for (int i = 0; i < total_units; ++i)
     {
-      dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cutu (i);
+      dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cu (i);
 
       /* We don't want to directly expand a partial CU, because if we
         read it with the wrong language, then assertion failures can
@@ -3644,62 +3273,26 @@ dw2_expand_all_symtabs (struct objfile *objfile)
     }
 }
 
-static void
-dw2_expand_symtabs_with_fullname (struct objfile *objfile,
-                                 const char *fullname)
-{
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
-  /* We don't need to consider type units here.
-     This is only called for examining code, e.g. expand_line_sal.
-     There can be an order of magnitude (or more) more type units
-     than comp units, and we avoid them if we can.  */
-
-  for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
-    {
-      /* We only need to look at symtabs not already expanded.  */
-      if (per_objfile->symtab_set_p (per_cu))
-       continue;
-
-      quick_file_names *file_data = dw2_get_file_names (per_cu, per_objfile);
-      if (file_data == NULL)
-       continue;
-
-      for (int j = 0; j < file_data->num_file_names; ++j)
-       {
-         const char *this_fullname = file_data->file_names[j];
-
-         if (filename_cmp (this_fullname, fullname) == 0)
-           {
-             dw2_instantiate_symtab (per_cu, per_objfile, false);
-             break;
-           }
-       }
-    }
-}
-
-static void
+static bool
 dw2_expand_symtabs_matching_symbol
   (mapped_index_base &index,
    const lookup_name_info &lookup_name_in,
    gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
-   enum search_domain kind,
    gdb::function_view<bool (offset_type)> match_callback,
    dwarf2_per_objfile *per_objfile);
 
-static void
+static bool
 dw2_expand_symtabs_matching_one
   (dwarf2_per_cu_data *per_cu,
    dwarf2_per_objfile *per_objfile,
    gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
    gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify);
 
-static void
-dw2_map_matching_symbols
+void
+dwarf2_gdb_index::expand_matching_symbols
   (struct objfile *objfile,
    const lookup_name_info &name, domain_enum domain,
    int global,
-   gdb::function_view<symbol_found_callback_ftype> callback,
    symbol_compare_ftype *ordered_compare)
 {
   /* Used for Ada.  */
@@ -3719,7 +3312,7 @@ dw2_map_matching_symbols
          return ordered_compare (symname, match_name) == 0;
        };
 
-      dw2_expand_symtabs_matching_symbol (index, name, matcher, ALL_DOMAIN,
+      dw2_expand_symtabs_matching_symbol (index, name, matcher,
                                          [&] (offset_type namei)
       {
        struct dw2_symtab_iterator iter;
@@ -3738,18 +3331,6 @@ dw2_map_matching_symbols
       /* We have -readnow: no .gdb_index, but no partial symtabs either.  So,
         proceed assuming all symtabs have been read in.  */
     }
-
-  for (compunit_symtab *cust : objfile->compunits ())
-    {
-      const struct block *block;
-
-      if (cust == NULL)
-       continue;
-      block = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), block_kind);
-      if (!iterate_over_symbols_terminated (block, name,
-                                           domain, callback))
-       return;
-    }
 }
 
 /* Starting from a search name, return the string that finds the upper
@@ -3982,12 +3563,11 @@ mapped_index_base::build_name_components (dwarf2_per_objfile *per_objfile)
    symbol name that matches, calls MATCH_CALLBACK, passing it the
    symbol's index in the mapped_index_base symbol table.  */
 
-static void
+static bool
 dw2_expand_symtabs_matching_symbol
   (mapped_index_base &index,
    const lookup_name_info &lookup_name_in,
    gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
-   enum search_domain kind,
    gdb::function_view<bool (offset_type)> match_callback,
    dwarf2_per_objfile *per_objfile)
 {
@@ -4068,12 +3648,16 @@ dw2_expand_symtabs_matching_symbol
 
   /* Finally call the callback, once per match.  */
   ULONGEST prev = -1;
+  bool result = true;
   for (offset_type idx : matches)
     {
       if (prev != idx)
        {
          if (!match_callback (idx))
-           break;
+           {
+             result = false;
+             break;
+           }
          prev = idx;
        }
     }
@@ -4081,6 +3665,8 @@ dw2_expand_symtabs_matching_symbol
   /* Above we use a type wider than idx's for 'prev', since 0 and
      (offset_type)-1 are both possible values.  */
   static_assert (sizeof (prev) > sizeof (offset_type), "");
+
+  return result;
 }
 
 #if GDB_SELF_TEST
@@ -4161,7 +3747,7 @@ check_match (const char *file, int line,
   auto expected_end = expected_list.end ();
 
   dw2_expand_symtabs_matching_symbol (mock_index, lookup_name,
-                                     NULL, ALL_DOMAIN,
+                                     nullptr,
                                      [&] (offset_type idx)
   {
     const char *matched_name = mock_index.symbol_name_at (idx, per_objfile);
@@ -4521,7 +4107,7 @@ run_test ()
    dw_expand_symtabs_matching_file_matcher), expand the CU and call
    EXPANSION_NOTIFY on it.  */
 
-static void
+static bool
 dw2_expand_symtabs_matching_one
   (dwarf2_per_cu_data *per_cu,
    dwarf2_per_objfile *per_objfile,
@@ -4537,31 +4123,32 @@ dw2_expand_symtabs_matching_one
       gdb_assert (symtab != nullptr);
 
       if (expansion_notify != NULL && symtab_was_null)
-       expansion_notify (symtab);
+       return expansion_notify (symtab);
     }
+  return true;
 }
 
 /* Helper for dw2_expand_matching symtabs.  Called on each symbol
    matched, to expand corresponding CUs that were marked.  IDX is the
    index of the symbol name that matched.  */
 
-static void
+static bool
 dw2_expand_marked_cus
   (dwarf2_per_objfile *per_objfile, offset_type idx,
    gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
    gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+   block_search_flags search_flags,
    search_domain kind)
 {
-  offset_type *vec, vec_len, vec_idx;
+  offset_type vec_len, vec_idx;
   bool global_seen = false;
   mapped_index &index = *per_objfile->per_bfd->index_table;
 
-  vec = (offset_type *) (index.constant_pool
-                        + MAYBE_SWAP (index.symbol_table[idx].vec));
-  vec_len = MAYBE_SWAP (vec[0]);
+  offset_view vec (index.constant_pool.slice (index.symbol_vec_index (idx)));
+  vec_len = vec[0];
   for (vec_idx = 0; vec_idx < vec_len; ++vec_idx)
     {
-      offset_type cu_index_and_attrs = MAYBE_SWAP (vec[vec_idx + 1]);
+      offset_type cu_index_and_attrs = 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);
       gdb_index_symbol_kind symbol_kind =
@@ -4589,6 +4176,17 @@ dw2_expand_marked_cus
       /* Only check the symbol's kind if it has one.  */
       if (attrs_valid)
        {
+         if (is_static)
+           {
+             if ((search_flags & SEARCH_STATIC_BLOCK) == 0)
+               continue;
+           }
+         else
+           {
+             if ((search_flags & SEARCH_GLOBAL_BLOCK) == 0)
+               continue;
+           }
+
          switch (kind)
            {
            case VARIABLES_DOMAIN:
@@ -4613,18 +4211,20 @@ dw2_expand_marked_cus
        }
 
       /* Don't crash on bad data.  */
-      if (cu_index >= (per_objfile->per_bfd->all_comp_units.size ()
-                      + per_objfile->per_bfd->all_type_units.size ()))
+      if (cu_index >= per_objfile->per_bfd->all_comp_units.size ())
        {
          complaint (_(".gdb_index entry has bad CU index"
                       " [in module %s]"), objfile_name (per_objfile->objfile));
          continue;
        }
 
-      dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cutu (cu_index);
-      dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher,
-                                      expansion_notify);
+      dwarf2_per_cu_data *per_cu = per_objfile->per_bfd->get_cu (cu_index);
+      if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher,
+                                           expansion_notify))
+       return false;
     }
+
+  return true;
 }
 
 /* If FILE_MATCHER is non-NULL, set all the
@@ -4649,17 +4249,20 @@ 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 (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
+  for (const auto &per_cu : per_objfile->per_bfd->all_comp_units)
     {
       QUIT;
 
+      if (per_cu->is_debug_types)
+       continue;
       per_cu->v.quick->mark = 0;
 
       /* We only need to look at symtabs not already expanded.  */
-      if (per_objfile->symtab_set_p (per_cu))
+      if (per_objfile->symtab_set_p (per_cu.get ()))
        continue;
 
-      quick_file_names *file_data = dw2_get_file_names (per_cu, per_objfile);
+      quick_file_names *file_data = dw2_get_file_names (per_cu.get (),
+                                                       per_objfile);
       if (file_data == NULL)
        continue;
 
@@ -4704,45 +4307,53 @@ dw_expand_symtabs_matching_file_matcher
     }
 }
 
-static void
-dw2_expand_symtabs_matching
-  (struct objfile *objfile,
-   gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
-   const lookup_name_info *lookup_name,
-   gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
-   gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
-   enum search_domain kind)
+bool
+dwarf2_gdb_index::expand_symtabs_matching
+    (struct objfile *objfile,
+     gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
+     const lookup_name_info *lookup_name,
+     gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
+     gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+     block_search_flags search_flags,
+     domain_enum domain,
+     enum search_domain kind)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
   /* index_table is NULL if OBJF_READNOW.  */
   if (!per_objfile->per_bfd->index_table)
-    return;
+    return true;
 
   dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
 
   if (symbol_matcher == NULL && lookup_name == NULL)
     {
-      for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
+      for (const auto &per_cu : per_objfile->per_bfd->all_comp_units)
        {
          QUIT;
 
-         dw2_expand_symtabs_matching_one (per_cu, per_objfile,
-                                          file_matcher, expansion_notify);
+         if (!dw2_expand_symtabs_matching_one (per_cu.get (), per_objfile,
+                                               file_matcher,
+                                               expansion_notify))
+           return false;
        }
-      return;
+      return true;
     }
 
   mapped_index &index = *per_objfile->per_bfd->index_table;
 
-  dw2_expand_symtabs_matching_symbol (index, *lookup_name,
-                                     symbol_matcher,
-                                     kind, [&] (offset_type idx)
+  bool result
+    = dw2_expand_symtabs_matching_symbol (index, *lookup_name,
+                                         symbol_matcher,
+                                         [&] (offset_type idx)
     {
-      dw2_expand_marked_cus (per_objfile, idx, file_matcher, expansion_notify,
-                            kind);
+      if (!dw2_expand_marked_cus (per_objfile, idx, file_matcher,
+                                 expansion_notify, search_flags, kind))
+       return false;
       return true;
     }, per_objfile);
+
+  return result;
 }
 
 /* A helper for dw2_find_pc_sect_compunit_symtab which finds the most specific
@@ -4773,26 +4384,28 @@ recursively_find_pc_sect_compunit_symtab (struct compunit_symtab *cust,
   return NULL;
 }
 
-static struct compunit_symtab *
-dw2_find_pc_sect_compunit_symtab (struct objfile *objfile,
-                                 struct bound_minimal_symbol msymbol,
-                                 CORE_ADDR pc,
-                                 struct obj_section *section,
-                                 int warn_if_readin)
+struct compunit_symtab *
+dwarf2_base_index_functions::find_pc_sect_compunit_symtab
+     (struct objfile *objfile,
+      struct bound_minimal_symbol msymbol,
+      CORE_ADDR pc,
+      struct obj_section *section,
+      int warn_if_readin)
 {
   struct dwarf2_per_cu_data *data;
   struct compunit_symtab *result;
 
-  if (!objfile->partial_symtabs->psymtabs_addrmap)
+  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+  if (per_objfile->per_bfd->index_addrmap == nullptr)
     return NULL;
 
   CORE_ADDR baseaddr = objfile->text_section_offset ();
-  data = (struct dwarf2_per_cu_data *) addrmap_find
-    (objfile->partial_symtabs->psymtabs_addrmap, pc - baseaddr);
+  data = ((struct dwarf2_per_cu_data *)
+         addrmap_find (per_objfile->per_bfd->index_addrmap,
+                       pc - baseaddr));
   if (!data)
     return NULL;
 
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
   if (warn_if_readin && per_objfile->symtab_set_p (data))
     warning (_("(Internal error: pc %s in read in CU, but not in symtab.)"),
             paddress (objfile->arch (), pc));
@@ -4804,99 +4417,68 @@ dw2_find_pc_sect_compunit_symtab (struct objfile *objfile,
   return result;
 }
 
-static void
-dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
-                         void *data, int need_fullname)
+void
+dwarf2_base_index_functions::map_symbol_filenames
+     (struct objfile *objfile,
+      gdb::function_view<symbol_filename_ftype> fun,
+      bool need_fullname)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
-  if (!per_objfile->per_bfd->filenames_cache)
-    {
-      per_objfile->per_bfd->filenames_cache.emplace ();
-
-      htab_up visited (htab_create_alloc (10,
-                                         htab_hash_pointer, htab_eq_pointer,
-                                         NULL, xcalloc, xfree));
+  /* Use caches to ensure we only call FUN once for each filename.  */
+  filename_seen_cache filenames_cache;
+  std::unordered_set<quick_file_names *> qfn_cache;
 
-      /* The rule is CUs specify all the files, including those used
-        by any TU, so there's no need to scan TUs here.  We can
-        ignore file names coming from already-expanded CUs.  */
+  /* The rule is CUs specify all the files, including those used by any TU,
+     so there's no need to scan TUs here.  We can ignore file names coming
+     from already-expanded CUs.  It is possible that an expanded CU might
+     reuse the file names data from a currently unexpanded CU, in this
+     case we don't want to report the files from the unexpanded CU.  */
 
-      for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
+  for (const auto &per_cu : per_objfile->per_bfd->all_comp_units)
+    {
+      if (per_objfile->symtab_set_p (per_cu.get ()))
        {
-         if (per_objfile->symtab_set_p (per_cu))
-           {
-             void **slot = htab_find_slot (visited.get (),
-                                           per_cu->v.quick->file_names,
-                                           INSERT);
-
-             *slot = per_cu->v.quick->file_names;
-           }
+         if (per_cu->v.quick->file_names != nullptr)
+           qfn_cache.insert (per_cu->v.quick->file_names);
        }
+    }
 
-      for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
-       {
-         /* We only need to look at symtabs not already expanded.  */
-         if (per_objfile->symtab_set_p (per_cu))
-           continue;
-
-         quick_file_names *file_data
-           = dw2_get_file_names (per_cu, per_objfile);
-         if (file_data == NULL)
-           continue;
+  for (const auto &per_cu : per_objfile->per_bfd->all_comp_units)
+    {
+      /* We only need to look at symtabs not already expanded.  */
+      if (per_objfile->symtab_set_p (per_cu.get ()))
+       continue;
 
-         void **slot = htab_find_slot (visited.get (), file_data, INSERT);
-         if (*slot)
-           {
-             /* Already visited.  */
-             continue;
-           }
-         *slot = file_data;
+      quick_file_names *file_data = dw2_get_file_names (per_cu.get (),
+                                                       per_objfile);
+      if (file_data == nullptr
+         || qfn_cache.find (file_data) != qfn_cache.end ())
+       continue;
 
-         for (int j = 0; j < file_data->num_file_names; ++j)
-           {
-             const char *filename = file_data->file_names[j];
-             per_objfile->per_bfd->filenames_cache->seen (filename);
-           }
+      for (int j = 0; j < file_data->num_file_names; ++j)
+       {
+         const char *filename = file_data->file_names[j];
+         filenames_cache.seen (filename);
        }
     }
 
-  per_objfile->per_bfd->filenames_cache->traverse ([&] (const char *filename)
+  filenames_cache.traverse ([&] (const char *filename)
     {
       gdb::unique_xmalloc_ptr<char> this_real_name;
 
       if (need_fullname)
        this_real_name = gdb_realpath (filename);
-      (*fun) (filename, this_real_name.get (), data);
+      fun (filename, this_real_name.get ());
     });
 }
 
-static int
-dw2_has_symbols (struct objfile *objfile)
+bool
+dwarf2_base_index_functions::has_symbols (struct objfile *objfile)
 {
-  return 1;
+  return true;
 }
 
-const struct quick_symbol_functions dwarf2_gdb_index_functions =
-{
-  dw2_has_symbols,
-  dw2_find_last_source_symtab,
-  dw2_forget_cached_source_info,
-  dw2_map_symtabs_matching_filename,
-  dw2_lookup_symbol,
-  NULL,
-  dw2_print_stats,
-  dw2_dump,
-  dw2_expand_symtabs_for_function,
-  dw2_expand_all_symtabs,
-  dw2_expand_symtabs_with_fullname,
-  dw2_map_matching_symbols,
-  dw2_expand_symtabs_matching,
-  dw2_find_pc_sect_compunit_symtab,
-  NULL,
-  dw2_map_symbol_filenames
-};
-
 /* DWARF-5 debug_names reader.  */
 
 /* DWARF-5 augmentation string for GDB's DW_IDX_GNU_* extension.  */
@@ -5109,10 +4691,10 @@ create_cus_from_debug_names_list (dwarf2_per_bfd *per_bfd,
             of the next CU as end of this CU.  We create the CUs here with
             length 0, and in cutu_reader::cutu_reader we'll fill in the
             actual length.  */
-         dwarf2_per_cu_data *per_cu
+         dwarf2_per_cu_data_up per_cu
            = create_cu_from_index_list (per_bfd, &section, is_dwz,
                                         sect_off, 0);
-         per_bfd->all_comp_units.push_back (per_cu);
+         per_bfd->all_comp_units.push_back (std::move (per_cu));
        }
       return;
     }
@@ -5134,10 +4716,10 @@ create_cus_from_debug_names_list (dwarf2_per_bfd *per_bfd,
       if (i >= 1)
        {
          const ULONGEST length = sect_off_next - sect_off_prev;
-         dwarf2_per_cu_data *per_cu
+         dwarf2_per_cu_data_up per_cu
            = create_cu_from_index_list (per_bfd, &section, is_dwz,
                                         sect_off_prev, length);
-         per_bfd->all_comp_units.push_back (per_cu);
+         per_bfd->all_comp_units.push_back (std::move (per_cu));
        }
       sect_off_prev = sect_off_next;
     }
@@ -5177,7 +4759,7 @@ dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
   dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
 
   if (!read_debug_names_from_section (objfile, objfile_name (objfile),
-                                     &per_objfile->per_bfd->debug_names, *map))
+                                     &per_bfd->debug_names, *map))
     return false;
 
   /* Don't use the index if it's empty.  */
@@ -5219,12 +4801,7 @@ dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
   per_bfd->debug_names_table = std::move (map);
   per_bfd->using_index = 1;
   per_bfd->quick_file_names_table =
-    create_quick_file_names_table (per_objfile->per_bfd->all_comp_units.size ());
-
-  /* Save partial symtabs in the per_bfd object, for the benefit of subsequent
-     objfiles using the same BFD.  */
-  gdb_assert (per_bfd->partial_symtabs == nullptr);
-  per_bfd->partial_symtabs = objfile->partial_symtabs;
+    create_quick_file_names_table (per_bfd->all_comp_units.size ());
 
   return true;
 }
@@ -5236,7 +4813,7 @@ class dw2_debug_names_iterator
 {
 public:
   dw2_debug_names_iterator (const mapped_debug_names &map,
-                           gdb::optional<block_enum> block_index,
+                           block_search_flags block_index,
                            domain_enum domain,
                            const char *name, dwarf2_per_objfile *per_objfile)
     : m_map (map), m_block_index (block_index), m_domain (domain),
@@ -5245,15 +4822,18 @@ public:
   {}
 
   dw2_debug_names_iterator (const mapped_debug_names &map,
-                           search_domain search, uint32_t namei, dwarf2_per_objfile *per_objfile)
+                           search_domain search, uint32_t namei,
+                           dwarf2_per_objfile *per_objfile,
+                           domain_enum domain = UNDEF_DOMAIN)
     : m_map (map),
+      m_domain (domain),
       m_search (search),
       m_addr (find_vec_in_debug_names (map, namei, per_objfile)),
       m_per_objfile (per_objfile)
   {}
 
   dw2_debug_names_iterator (const mapped_debug_names &map,
-                           block_enum block_index, domain_enum domain,
+                           block_search_flags block_index, domain_enum domain,
                            uint32_t namei, dwarf2_per_objfile *per_objfile)
     : m_map (map), m_block_index (block_index), m_domain (domain),
       m_addr (find_vec_in_debug_names (map, namei, per_objfile)),
@@ -5274,9 +4854,9 @@ private:
   /* The internalized form of .debug_names.  */
   const mapped_debug_names &m_map;
 
-  /* If set, only look for symbols that match that block.  Valid values are
-     GLOBAL_BLOCK and STATIC_BLOCK.  */
-  const gdb::optional<block_enum> m_block_index;
+  /* Restrict the search to these blocks.  */
+  block_search_flags m_block_index = (SEARCH_GLOBAL_BLOCK
+                                     | SEARCH_STATIC_BLOCK);
 
   /* The kind of symbol we're looking for.  */
   const domain_enum m_domain = UNDEF_DOMAIN;
@@ -5479,7 +5059,7 @@ dw2_debug_names_iterator::next ()
        {
        case DW_IDX_compile_unit:
          /* Don't crash on bad data.  */
-         if (ull >= m_per_objfile->per_bfd->all_comp_units.size ())
+         if (ull >= per_bfd->all_comp_units.size ())
            {
              complaint (_(".debug_names entry has bad CU index %s"
                           " [in module %s]"),
@@ -5487,11 +5067,11 @@ dw2_debug_names_iterator::next ()
                         objfile_name (objfile));
              continue;
            }
-         per_cu = per_bfd->get_cutu (ull);
+         per_cu = per_bfd->get_cu (ull);
          break;
        case DW_IDX_type_unit:
          /* Don't crash on bad data.  */
-         if (ull >= per_bfd->all_type_units.size ())
+         if (ull >= per_bfd->tu_stats.nr_tus)
            {
              complaint (_(".debug_names entry has bad TU index %s"
                           " [in module %s]"),
@@ -5499,7 +5079,7 @@ dw2_debug_names_iterator::next ()
                         objfile_name (objfile));
              continue;
            }
-         per_cu = &per_bfd->get_tu (ull)->per_cu;
+         per_cu = per_bfd->get_cu (ull + per_bfd->tu_stats.nr_tus);
          break;
        case DW_IDX_die_offset:
          /* In a per-CU index (as opposed to a per-module index), index
@@ -5525,13 +5105,18 @@ dw2_debug_names_iterator::next ()
     goto again;
 
   /* Check static vs global.  */
-  if (symbol_linkage_ != symbol_linkage::unknown && m_block_index.has_value ())
+  if (symbol_linkage_ != symbol_linkage::unknown)
     {
-       const bool want_static = *m_block_index == STATIC_BLOCK;
-       const bool symbol_is_static =
-         symbol_linkage_ == symbol_linkage::static_;
-       if (want_static != symbol_is_static)
-         goto again;
+      if (symbol_linkage_ == symbol_linkage::static_)
+       {
+         if ((m_block_index & SEARCH_STATIC_BLOCK) == 0)
+           goto again;
+       }
+      else
+       {
+         if ((m_block_index & SEARCH_GLOBAL_BLOCK) == 0)
+           goto again;
+       }
     }
 
   /* Match dw2_symtab_iter_next, symbol_kind
@@ -5631,59 +5216,12 @@ dw2_debug_names_iterator::next ()
   return per_cu;
 }
 
-static struct compunit_symtab *
-dw2_debug_names_lookup_symbol (struct objfile *objfile, block_enum block_index,
-                              const char *name, domain_enum domain)
-{
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
-  const auto &mapp = per_objfile->per_bfd->debug_names_table;
-  if (!mapp)
-    {
-      /* index is NULL if OBJF_READNOW.  */
-      return NULL;
-    }
-  const auto &map = *mapp;
-
-  dw2_debug_names_iterator iter (map, block_index, domain, name, per_objfile);
-
-  struct compunit_symtab *stab_best = NULL;
-  struct dwarf2_per_cu_data *per_cu;
-  while ((per_cu = iter.next ()) != NULL)
-    {
-      struct symbol *sym, *with_opaque = NULL;
-      compunit_symtab *stab
-       = dw2_instantiate_symtab (per_cu, per_objfile, false);
-      const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (stab);
-      const struct block *block = BLOCKVECTOR_BLOCK (bv, block_index);
-
-      sym = block_find_symbol (block, name, domain,
-                              block_find_non_opaque_type_preferred,
-                              &with_opaque);
-
-      /* Some caution must be observed with overloaded functions and
-        methods, since the index will not contain any overload
-        information (but NAME might contain it).  */
-
-      if (sym != NULL
-         && strcmp_iw (sym->search_name (), name) == 0)
-       return stab;
-      if (with_opaque != NULL
-         && strcmp_iw (with_opaque->search_name (), name) == 0)
-       stab_best = stab;
-
-      /* Keep looking through other CUs.  */
-    }
-
-  return stab_best;
-}
-
 /* This dumps minimal information about .debug_names.  It is called
    via "mt print objfiles".  The gdb.dwarf2/gdb-index.exp testcase
    uses this to verify that .debug_names has been loaded.  */
 
-static void
-dw2_debug_names_dump (struct objfile *objfile)
+void
+dwarf2_debug_names_index::dump (struct objfile *objfile)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
@@ -5692,36 +5230,15 @@ dw2_debug_names_dump (struct objfile *objfile)
   if (per_objfile->per_bfd->debug_names_table)
     printf_filtered (" exists\n");
   else
-    printf_filtered (" faked for \"readnow\"\n");
-  printf_filtered ("\n");
-}
-
-static void
-dw2_debug_names_expand_symtabs_for_function (struct objfile *objfile,
-                                            const char *func_name)
-{
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
-  /* per_objfile->per_bfd->debug_names_table is NULL if OBJF_READNOW.  */
-  if (per_objfile->per_bfd->debug_names_table)
-    {
-      const mapped_debug_names &map = *per_objfile->per_bfd->debug_names_table;
-
-      dw2_debug_names_iterator iter (map, {}, VAR_DOMAIN, func_name,
-                                    per_objfile);
-
-      struct dwarf2_per_cu_data *per_cu;
-      while ((per_cu = iter.next ()) != NULL)
-       dw2_instantiate_symtab (per_cu, per_objfile, false);
-    }
+    printf_filtered (" faked for \"readnow\"\n");
+  printf_filtered ("\n");
 }
 
-static void
-dw2_debug_names_map_matching_symbols
+void
+dwarf2_debug_names_index::expand_matching_symbols
   (struct objfile *objfile,
    const lookup_name_info &name, domain_enum domain,
    int global,
-   gdb::function_view<symbol_found_callback_ftype> callback,
    symbol_compare_ftype *ordered_compare)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
@@ -5731,7 +5248,8 @@ dw2_debug_names_map_matching_symbols
     return;
 
   mapped_debug_names &map = *per_objfile->per_bfd->debug_names_table;
-  const block_enum block_kind = global ? GLOBAL_BLOCK : STATIC_BLOCK;
+  const block_search_flags block_flags
+    = global ? SEARCH_GLOBAL_BLOCK : SEARCH_STATIC_BLOCK;
 
   const char *match_name = name.ada ().lookup_name ().c_str ();
   auto matcher = [&] (const char *symname)
@@ -5741,12 +5259,12 @@ dw2_debug_names_map_matching_symbols
       return ordered_compare (symname, match_name) == 0;
     };
 
-  dw2_expand_symtabs_matching_symbol (map, name, matcher, ALL_DOMAIN,
+  dw2_expand_symtabs_matching_symbol (map, name, matcher,
                                      [&] (offset_type namei)
     {
       /* The name was matched, now expand corresponding CUs that were
         marked.  */
-      dw2_debug_names_iterator iter (map, block_kind, domain, namei,
+      dw2_debug_names_iterator iter (map, block_flags, domain, namei,
                                     per_objfile);
 
       struct dwarf2_per_cu_data *per_cu;
@@ -5755,91 +5273,63 @@ dw2_debug_names_map_matching_symbols
                                         nullptr);
       return true;
     }, per_objfile);
-
-  /* It's a shame we couldn't do this inside the
-     dw2_expand_symtabs_matching_symbol callback, but that skips CUs
-     that have already been expanded.  Instead, this loop matches what
-     the psymtab code does.  */
-  for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
-    {
-      compunit_symtab *symtab = per_objfile->get_symtab (per_cu);
-      if (symtab != nullptr)
-       {
-         const struct block *block
-           = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (symtab), block_kind);
-         if (!iterate_over_symbols_terminated (block, name,
-                                               domain, callback))
-           break;
-       }
-    }
 }
 
-static void
-dw2_debug_names_expand_symtabs_matching
+bool
+dwarf2_debug_names_index::expand_symtabs_matching
   (struct objfile *objfile,
    gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
    const lookup_name_info *lookup_name,
    gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
    gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+   block_search_flags search_flags,
+   domain_enum domain,
    enum search_domain kind)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
   /* debug_names_table is NULL if OBJF_READNOW.  */
   if (!per_objfile->per_bfd->debug_names_table)
-    return;
+    return true;
 
   dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
 
   if (symbol_matcher == NULL && lookup_name == NULL)
     {
-      for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
+      for (const auto &per_cu : per_objfile->per_bfd->all_comp_units)
        {
          QUIT;
 
-         dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher,
-                                          expansion_notify);
+         if (!dw2_expand_symtabs_matching_one (per_cu.get (), per_objfile,
+                                               file_matcher,
+                                               expansion_notify))
+           return false;
        }
-      return;
+      return true;
     }
 
   mapped_debug_names &map = *per_objfile->per_bfd->debug_names_table;
 
-  dw2_expand_symtabs_matching_symbol (map, *lookup_name,
-                                     symbol_matcher,
-                                     kind, [&] (offset_type namei)
+  bool result
+    = dw2_expand_symtabs_matching_symbol (map, *lookup_name,
+                                         symbol_matcher,
+                                         [&] (offset_type namei)
     {
       /* The name was matched, now expand corresponding CUs that were
         marked.  */
-      dw2_debug_names_iterator iter (map, kind, namei, per_objfile);
+      dw2_debug_names_iterator iter (map, kind, namei, per_objfile, domain);
 
       struct dwarf2_per_cu_data *per_cu;
       while ((per_cu = iter.next ()) != NULL)
-       dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher,
-                                        expansion_notify);
+       if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
+                                             file_matcher,
+                                             expansion_notify))
+         return false;
       return true;
     }, per_objfile);
-}
 
-const struct quick_symbol_functions dwarf2_debug_names_functions =
-{
-  dw2_has_symbols,
-  dw2_find_last_source_symtab,
-  dw2_forget_cached_source_info,
-  dw2_map_symtabs_matching_filename,
-  dw2_debug_names_lookup_symbol,
-  NULL,
-  dw2_print_stats,
-  dw2_debug_names_dump,
-  dw2_debug_names_expand_symtabs_for_function,
-  dw2_expand_all_symtabs,
-  dw2_expand_symtabs_with_fullname,
-  dw2_debug_names_map_matching_symbols,
-  dw2_debug_names_expand_symtabs_matching,
-  dw2_find_pc_sect_compunit_symtab,
-  NULL,
-  dw2_map_symbol_filenames
-};
+  return result;
+}
 
 /* Get the content of the .gdb_index section of OBJ.  SECTION_OWNER should point
    to either a dwarf2_per_bfd or dwz_file object.  */
@@ -5895,10 +5385,10 @@ get_gdb_index_contents_from_cache_dwz (objfile *obj, dwz_file *dwz)
   return global_index_cache.lookup_gdb_index (build_id, &dwz->index_cache_res);
 }
 
-/* See symfile.h.  */
+/* See dwarf2/public.h.  */
 
-bool
-dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
+void
+dwarf2_initialize_objfile (struct objfile *objfile)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
   dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
@@ -5918,32 +5408,30 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
       if (per_bfd->using_index)
        {
          dwarf_read_debug_printf ("using_index already set");
-         *index_kind = dw_index_kind::GDB_INDEX;
          per_objfile->resize_symtabs ();
-         return true;
+         objfile->qf.push_front (make_dwarf_gdb_index ());
+         return;
        }
 
       per_bfd->using_index = 1;
       create_all_comp_units (per_objfile);
-      create_all_type_units (per_objfile);
       per_bfd->quick_file_names_table
        = create_quick_file_names_table (per_bfd->all_comp_units.size ());
       per_objfile->resize_symtabs ();
 
-      for (int i = 0; i < (per_bfd->all_comp_units.size ()
-                          + per_bfd->all_type_units.size ()); ++i)
+      for (int i = 0; i < per_bfd->all_comp_units.size (); ++i)
        {
-         dwarf2_per_cu_data *per_cu = per_bfd->get_cutu (i);
+         dwarf2_per_cu_data *per_cu = per_bfd->get_cu (i);
 
          per_cu->v.quick = OBSTACK_ZALLOC (&per_bfd->obstack,
                                            struct dwarf2_per_cu_quick_data);
        }
 
-      /* Return 1 so that gdb sees the "quick" functions.  However,
-        these functions will be no-ops because we will have expanded
-        all symtabs.  */
-      *index_kind = dw_index_kind::GDB_INDEX;
-      return true;
+      /* Arrange for gdb to see the "quick" functions.  However, these
+        functions will be no-ops because we will have expanded all
+        symtabs.  */
+      objfile->qf.push_front (make_dwarf_gdb_index ());
+      return;
     }
 
   /* Was a debug names index already read when we processed an objfile sharing
@@ -5951,10 +5439,9 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
   if (per_bfd->debug_names_table != nullptr)
     {
       dwarf_read_debug_printf ("re-using shared debug names table");
-      *index_kind = dw_index_kind::DEBUG_NAMES;
-      per_objfile->objfile->partial_symtabs = per_bfd->partial_symtabs;
       per_objfile->resize_symtabs ();
-      return true;
+      objfile->qf.push_front (make_dwarf_debug_names ());
+      return;
     }
 
   /* Was a GDB index already read when we processed an objfile sharing
@@ -5962,10 +5449,9 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
   if (per_bfd->index_table != nullptr)
     {
       dwarf_read_debug_printf ("re-using shared index table");
-      *index_kind = dw_index_kind::GDB_INDEX;
-      per_objfile->objfile->partial_symtabs = per_bfd->partial_symtabs;
       per_objfile->resize_symtabs ();
-      return true;
+      objfile->qf.push_front (make_dwarf_gdb_index ());
+      return;
     }
 
   /* There might already be partial symtabs built for this BFD.  This happens
@@ -5976,15 +5462,16 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
   if (per_bfd->partial_symtabs != nullptr)
     {
       dwarf_read_debug_printf ("re-using shared partial symtabs");
-      return false;
+      objfile->qf.push_front (make_lazy_dwarf_reader ());
+      return;
     }
 
   if (dwarf2_read_debug_names (per_objfile))
     {
       dwarf_read_debug_printf ("found debug names");
-      *index_kind = dw_index_kind::DEBUG_NAMES;
       per_objfile->resize_symtabs ();
-      return true;
+      objfile->qf.push_front (make_dwarf_debug_names ());
+      return;
     }
 
   if (dwarf2_read_gdb_index (per_objfile,
@@ -5992,9 +5479,9 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
                             get_gdb_index_contents_from_section<dwz_file>))
     {
       dwarf_read_debug_printf ("found gdb index from file");
-      *index_kind = dw_index_kind::GDB_INDEX;
       per_objfile->resize_symtabs ();
-      return true;
+      objfile->qf.push_front (make_dwarf_gdb_index ());
+      return;
     }
 
   /* ... otherwise, try to find the index in the index cache.  */
@@ -6004,13 +5491,13 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
     {
       dwarf_read_debug_printf ("found gdb index from cache");
       global_index_cache.hit ();
-      *index_kind = dw_index_kind::GDB_INDEX;
       per_objfile->resize_symtabs ();
-      return true;
+      objfile->qf.push_front (make_dwarf_gdb_index ());
+      return;
     }
 
   global_index_cache.miss ();
-  return false;
+  objfile->qf.push_front (make_lazy_dwarf_reader ());
 }
 
 \f
@@ -6018,7 +5505,7 @@ dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
 /* Build a partial symbol table.  */
 
 void
-dwarf2_build_psymtabs (struct objfile *objfile)
+dwarf2_build_psymtabs (struct objfile *objfile, psymbol_functions *psf)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
   dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
@@ -6027,17 +5514,37 @@ dwarf2_build_psymtabs (struct objfile *objfile)
     {
       /* Partial symbols were already read, so now we can simply
         attach them.  */
-      objfile->partial_symtabs = per_bfd->partial_symtabs;
+      if (psf == nullptr)
+       {
+         psf = new psymbol_functions (per_bfd->partial_symtabs);
+         objfile->qf.emplace_front (psf);
+       }
+      else
+       psf->set_partial_symtabs (per_bfd->partial_symtabs);
       per_objfile->resize_symtabs ();
       return;
     }
 
+  if (psf == nullptr)
+    {
+      psf = new psymbol_functions;
+      objfile->qf.emplace_front (psf);
+    }
+  const std::shared_ptr<psymtab_storage> &partial_symtabs
+    = psf->get_partial_symtabs ();
+
+  /* Set the local reference to partial symtabs, so that we don't try
+     to read them again if reading another objfile with the same BFD.
+     If we can't in fact share, this won't make a difference anyway as
+     the dwarf2_per_bfd object won't be shared.  */
+  per_bfd->partial_symtabs = partial_symtabs;
+
   try
     {
       /* This isn't really ideal: all the data we allocate on the
         objfile's obstack is still uselessly kept around.  However,
         freeing it seems unsafe.  */
-      psymtab_discarder psymtabs (objfile);
+      psymtab_discarder psymtabs (partial_symtabs.get ());
       dwarf2_build_psymtabs_hard (per_objfile);
       psymtabs.keep ();
 
@@ -6050,12 +5557,6 @@ dwarf2_build_psymtabs (struct objfile *objfile)
     {
       exception_print (gdb_stderr, except);
     }
-
-  /* Finish by setting the local reference to partial symtabs, so that
-     we don't try to read them again if reading another objfile with the same
-     BFD.  If we can't in fact share, this won't make a difference anyway as
-     the dwarf2_per_bfd object won't be shared.  */
-  per_bfd->partial_symtabs = objfile->partial_symtabs;
 }
 
 /* Find the base address of the compilation unit for range lists and
@@ -6131,8 +5632,10 @@ read_abbrev_offset (dwarf2_per_objfile *per_objfile,
 /* A partial symtab that is used only for include files.  */
 struct dwarf2_include_psymtab : public partial_symtab
 {
-  dwarf2_include_psymtab (const char *filename, struct objfile *objfile)
-    : partial_symtab (filename, objfile)
+  dwarf2_include_psymtab (const char *filename,
+                         psymtab_storage *partial_symtabs,
+                         objfile_per_bfd_storage *objfile_per_bfd)
+    : partial_symtab (filename, partial_symtabs, objfile_per_bfd)
   {
   }
 
@@ -6184,15 +5687,19 @@ private:
    partial symtab as being an include of PST.  */
 
 static void
-dwarf2_create_include_psymtab (const char *name, dwarf2_psymtab *pst,
-                              struct objfile *objfile)
+dwarf2_create_include_psymtab (dwarf2_per_bfd *per_bfd,
+                              const char *name,
+                              dwarf2_psymtab *pst,
+                              psymtab_storage *partial_symtabs,
+                              objfile_per_bfd_storage *objfile_per_bfd)
 {
-  dwarf2_include_psymtab *subpst = new dwarf2_include_psymtab (name, objfile);
+  dwarf2_include_psymtab *subpst
+    = new dwarf2_include_psymtab (name, partial_symtabs, objfile_per_bfd);
 
   if (!IS_ABSOLUTE_PATH (subpst->filename))
     subpst->dirname = pst->dirname;
 
-  subpst->dependencies = objfile->partial_symtabs->allocate_dependencies (1);
+  subpst->dependencies = per_bfd->partial_symtabs->allocate_dependencies (1);
   subpst->dependencies[0] = pst;
   subpst->number_of_dependencies = 1;
 }
@@ -6253,20 +5760,6 @@ allocate_signatured_type_table ()
                                     NULL, xcalloc, xfree));
 }
 
-/* A helper function to add a signatured type CU to a table.  */
-
-static int
-add_signatured_type_cu_to_table (void **slot, void *datum)
-{
-  struct signatured_type *sigt = (struct signatured_type *) *slot;
-  std::vector<signatured_type *> *all_type_units
-    = (std::vector<signatured_type *> *) datum;
-
-  all_type_units->push_back (sigt);
-
-  return 1;
-}
-
 /* A helper for create_debug_types_hash_table.  Read types from SECTION
    and fill them into TYPES_HTAB.  It will process only type units,
    therefore DW_UT_type.  */
@@ -6282,11 +5775,9 @@ create_debug_type_hash_table (dwarf2_per_objfile *per_objfile,
   bfd *abfd;
   const gdb_byte *info_ptr, *end_ptr;
 
-  abbrev_section = (dwo_file != NULL
-                   ? &dwo_file->sections.abbrev
-                   : &per_objfile->per_bfd->abbrev);
+  abbrev_section = &dwo_file->sections.abbrev;
 
-  dwarf_read_debug_printf ("Reading %s for %s:",
+  dwarf_read_debug_printf ("Reading %s for %s",
                           section->get_name (),
                           abbrev_section->get_file_name ());
 
@@ -6306,7 +5797,7 @@ create_debug_type_hash_table (dwarf2_per_objfile *per_objfile,
   end_ptr = info_ptr + section->size;
   while (info_ptr < end_ptr)
     {
-      struct signatured_type *sig_type;
+      std::unique_ptr<signatured_type> sig_type;
       struct dwo_unit *dwo_tu;
       void **slot;
       const gdb_byte *ptr = info_ptr;
@@ -6338,67 +5829,25 @@ create_debug_type_hash_table (dwarf2_per_objfile *per_objfile,
        }
 
       if (types_htab == NULL)
-       {
-         if (dwo_file)
-           types_htab = allocate_dwo_unit_table ();
-         else
-           types_htab = allocate_signatured_type_table ();
-       }
+       types_htab = allocate_dwo_unit_table ();
 
-      if (dwo_file)
-       {
-         sig_type = NULL;
-         dwo_tu = OBSTACK_ZALLOC (&per_objfile->per_bfd->obstack, dwo_unit);
-         dwo_tu->dwo_file = dwo_file;
-         dwo_tu->signature = header.signature;
-         dwo_tu->type_offset_in_tu = header.type_cu_offset_in_tu;
-         dwo_tu->section = section;
-         dwo_tu->sect_off = sect_off;
-         dwo_tu->length = length;
-       }
-      else
-       {
-         /* N.B.: type_offset is not usable if this type uses a DWO file.
-            The real type_offset is in the DWO file.  */
-         dwo_tu = NULL;
-         sig_type = per_objfile->per_bfd->allocate_signatured_type ();
-         sig_type->signature = header.signature;
-         sig_type->type_offset_in_tu = header.type_cu_offset_in_tu;
-         sig_type->per_cu.is_debug_types = 1;
-         sig_type->per_cu.section = section;
-         sig_type->per_cu.sect_off = sect_off;
-         sig_type->per_cu.length = length;
-       }
-
-      slot = htab_find_slot (types_htab.get (),
-                            dwo_file ? (void*) dwo_tu : (void *) sig_type,
-                            INSERT);
+      dwo_tu = OBSTACK_ZALLOC (&per_objfile->per_bfd->obstack, dwo_unit);
+      dwo_tu->dwo_file = dwo_file;
+      dwo_tu->signature = header.signature;
+      dwo_tu->type_offset_in_tu = header.type_cu_offset_in_tu;
+      dwo_tu->section = section;
+      dwo_tu->sect_off = sect_off;
+      dwo_tu->length = length;
+
+      slot = htab_find_slot (types_htab.get (), dwo_tu, INSERT);
       gdb_assert (slot != NULL);
       if (*slot != NULL)
-       {
-         sect_offset dup_sect_off;
-
-         if (dwo_file)
-           {
-             const struct dwo_unit *dup_tu
-               = (const struct dwo_unit *) *slot;
-
-             dup_sect_off = dup_tu->sect_off;
-           }
-         else
-           {
-             const struct signatured_type *dup_tu
-               = (const struct signatured_type *) *slot;
-
-             dup_sect_off = dup_tu->per_cu.sect_off;
-           }
-
-         complaint (_("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;
+       complaint (_("debug type entry at offset %s is duplicate to"
+                    " the entry at offset %s, signature %s"),
+                  sect_offset_str (sect_off),
+                  sect_offset_str (dwo_tu->sect_off),
+                  hex_string (header.signature));
+      *slot = dwo_tu;
 
       dwarf_read_debug_printf_v ("  offset %s, signature %s",
                                 sect_offset_str (sect_off),
@@ -6410,8 +5859,7 @@ create_debug_type_hash_table (dwarf2_per_objfile *per_objfile,
 
 /* Create the hash table of all entries in the .debug_types
    (or .debug_types.dwo) section(s).
-   If reading a DWO file, then DWO_FILE is a pointer to the DWO file object,
-   otherwise it is NULL.
+   DWO_FILE is a pointer to the DWO file object.
 
    The result is a pointer to the hash table or NULL if there are no types.
 
@@ -6428,39 +5876,6 @@ create_debug_types_hash_table (dwarf2_per_objfile *per_objfile,
                                  rcuh_kind::TYPE);
 }
 
-/* Create the hash table of all entries in the .debug_types section,
-   and initialize all_type_units.
-   The result is zero if there is an error (e.g. missing .debug_types section),
-   otherwise non-zero. */
-
-static int
-create_all_type_units (dwarf2_per_objfile *per_objfile)
-{
-  htab_up types_htab;
-
-  create_debug_type_hash_table (per_objfile, NULL, &per_objfile->per_bfd->info,
-                               types_htab, rcuh_kind::COMPILE);
-  create_debug_types_hash_table (per_objfile, NULL, per_objfile->per_bfd->types,
-                                types_htab);
-  if (types_htab == NULL)
-    {
-      per_objfile->per_bfd->signatured_types = NULL;
-      return 0;
-    }
-
-  per_objfile->per_bfd->signatured_types = std::move (types_htab);
-
-  gdb_assert (per_objfile->per_bfd->all_type_units.empty ());
-  per_objfile->per_bfd->all_type_units.reserve
-    (htab_elements (per_objfile->per_bfd->signatured_types.get ()));
-
-  htab_traverse_noresize (per_objfile->per_bfd->signatured_types.get (),
-                         add_signatured_type_cu_to_table,
-                         &per_objfile->per_bfd->all_type_units);
-
-  return 1;
-}
-
 /* Add an entry for signature SIG to dwarf2_per_objfile->per_bfd->signatured_types.
    If SLOT is non-NULL, it is the entry to use in the hash table.
    Otherwise we find one.  */
@@ -6468,20 +5883,23 @@ create_all_type_units (dwarf2_per_objfile *per_objfile)
 static struct signatured_type *
 add_type_unit (dwarf2_per_objfile *per_objfile, ULONGEST sig, void **slot)
 {
-  if (per_objfile->per_bfd->all_type_units.size ()
-      == per_objfile->per_bfd->all_type_units.capacity ())
+  if (per_objfile->per_bfd->all_comp_units.size ()
+      == per_objfile->per_bfd->all_comp_units.capacity ())
     ++per_objfile->per_bfd->tu_stats.nr_all_type_units_reallocs;
 
-  signatured_type *sig_type = per_objfile->per_bfd->allocate_signatured_type ();
+  std::unique_ptr<signatured_type> sig_type_holder
+    = per_objfile->per_bfd->allocate_signatured_type ();
+  signatured_type *sig_type = sig_type_holder.get ();
 
   per_objfile->resize_symtabs ();
 
-  per_objfile->per_bfd->all_type_units.push_back (sig_type);
+  per_objfile->per_bfd->all_comp_units.emplace_back
+    (sig_type_holder.release ());
   sig_type->signature = sig;
-  sig_type->per_cu.is_debug_types = 1;
+  sig_type->is_debug_types = 1;
   if (per_objfile->per_bfd->using_index)
     {
-      sig_type->per_cu.v.quick =
+      sig_type->v.quick =
        OBSTACK_ZALLOC (&per_objfile->per_bfd->obstack,
                        struct dwarf2_per_cu_quick_data);
     }
@@ -6508,25 +5926,25 @@ fill_in_sig_entry_from_dwo_entry (dwarf2_per_objfile *per_objfile,
   dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
 
   /* Make sure we're not clobbering something we don't expect to.  */
-  gdb_assert (! sig_entry->per_cu.queued);
-  gdb_assert (per_objfile->get_cu (&sig_entry->per_cu) == NULL);
+  gdb_assert (! sig_entry->queued);
+  gdb_assert (per_objfile->get_cu (sig_entry) == NULL);
   if (per_bfd->using_index)
     {
-      gdb_assert (sig_entry->per_cu.v.quick != NULL);
-      gdb_assert (!per_objfile->symtab_set_p (&sig_entry->per_cu));
+      gdb_assert (sig_entry->v.quick != NULL);
+      gdb_assert (!per_objfile->symtab_set_p (sig_entry));
     }
   else
-      gdb_assert (sig_entry->per_cu.v.psymtab == NULL);
+      gdb_assert (sig_entry->v.psymtab == NULL);
   gdb_assert (sig_entry->signature == dwo_entry->signature);
   gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0);
   gdb_assert (sig_entry->type_unit_group == NULL);
   gdb_assert (sig_entry->dwo_unit == NULL);
 
-  sig_entry->per_cu.section = dwo_entry->section;
-  sig_entry->per_cu.sect_off = dwo_entry->sect_off;
-  sig_entry->per_cu.length = dwo_entry->length;
-  sig_entry->per_cu.reading_dwo_directly = 1;
-  sig_entry->per_cu.per_bfd = per_bfd;
+  sig_entry->section = dwo_entry->section;
+  sig_entry->sect_off = dwo_entry->sect_off;
+  sig_entry->length = dwo_entry->length;
+  sig_entry->reading_dwo_directly = 1;
+  sig_entry->per_bfd = per_bfd;
   sig_entry->type_offset_in_tu = dwo_entry->type_offset_in_tu;
   sig_entry->dwo_unit = dwo_entry;
 }
@@ -6579,7 +5997,7 @@ lookup_dwo_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
   /* Have we already tried to read this TU?
      Note: sig_entry can be NULL if the skeleton TU was removed (thus it
      needn't exist in the global table yet).  */
-  if (sig_entry != NULL && sig_entry->per_cu.tu_read)
+  if (sig_entry != NULL && sig_entry->tu_read)
     return sig_entry;
 
   /* Note: cu->dwo_unit is the dwo_unit that references this TU, not the
@@ -6600,7 +6018,7 @@ lookup_dwo_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
     sig_entry = add_type_unit (per_objfile, sig, slot);
 
   fill_in_sig_entry_from_dwo_entry (per_objfile, sig_entry, dwo_entry);
-  sig_entry->per_cu.tu_read = 1;
+  sig_entry->tu_read = 1;
   return sig_entry;
 }
 
@@ -7319,7 +6737,8 @@ allocate_type_unit_groups_table ()
   return htab_up (htab_create_alloc (3,
                                     hash_type_unit_group,
                                     eq_type_unit_group,
-                                    NULL, xcalloc, xfree));
+                                    htab_delete_entry<type_unit_group>,
+                                    xcalloc, xfree));
 }
 
 /* Type units that don't have DW_AT_stmt_list are grouped into their own
@@ -7331,22 +6750,19 @@ allocate_type_unit_groups_table ()
 /* Helper routine for get_type_unit_group.
    Create the type_unit_group object used to hold one or more TUs.  */
 
-static struct type_unit_group *
+static std::unique_ptr<type_unit_group>
 create_type_unit_group (struct dwarf2_cu *cu, sect_offset line_offset_struct)
 {
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
   dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
-  struct dwarf2_per_cu_data *per_cu;
-  struct type_unit_group *tu_group;
 
-  tu_group = OBSTACK_ZALLOC (&per_objfile->per_bfd->obstack, type_unit_group);
-  per_cu = &tu_group->per_cu;
-  per_cu->per_bfd = per_bfd;
+  std::unique_ptr<type_unit_group> tu_group (new type_unit_group);
+  tu_group->per_bfd = per_bfd;
 
   if (per_bfd->using_index)
     {
-      per_cu->v.quick = OBSTACK_ZALLOC (&per_bfd->obstack,
-                                       struct dwarf2_per_cu_quick_data);
+      tu_group->v.quick = OBSTACK_ZALLOC (&per_bfd->obstack,
+                                         struct dwarf2_per_cu_quick_data);
     }
   else
     {
@@ -7361,7 +6777,8 @@ create_type_unit_group (struct dwarf2_cu *cu, sect_offset line_offset_struct)
       else
        name = string_printf ("<type_units_at_0x%x>", line_offset);
 
-      pst = create_partial_symtab (per_cu, per_objfile, name.c_str ());
+      pst = create_partial_symtab (tu_group.get (), per_objfile,
+                                  name.c_str ());
       pst->anonymous = true;
     }
 
@@ -7411,19 +6828,17 @@ get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list)
   type_unit_group_for_lookup.hash.line_sect_off = (sect_offset) line_offset;
   slot = htab_find_slot (per_objfile->per_bfd->type_unit_groups.get (),
                         &type_unit_group_for_lookup, INSERT);
-  if (*slot != NULL)
-    {
-      tu_group = (struct type_unit_group *) *slot;
-      gdb_assert (tu_group != NULL);
-    }
-  else
+  if (*slot == nullptr)
     {
       sect_offset line_offset_struct = (sect_offset) line_offset;
-      tu_group = create_type_unit_group (cu, line_offset_struct);
-      *slot = tu_group;
+      std::unique_ptr<type_unit_group> grp
+       = create_type_unit_group (cu, line_offset_struct);
+      *slot = grp.release ();
       ++tu_stats->nr_symtabs;
     }
 
+  tu_group = (struct type_unit_group *) *slot;
+  gdb_assert (tu_group != nullptr);
   return tu_group;
 }
 \f
@@ -7439,10 +6854,9 @@ create_partial_symtab (dwarf2_per_cu_data *per_cu,
                       dwarf2_per_objfile *per_objfile,
                       const char *name)
 {
-  struct objfile *objfile = per_objfile->objfile;
-  dwarf2_psymtab *pst;
-
-  pst = new dwarf2_psymtab (name, objfile, per_cu);
+  dwarf2_psymtab *pst
+    = new dwarf2_psymtab (name, per_objfile->per_bfd->partial_symtabs.get (),
+                         per_objfile->objfile->per_bfd, per_cu);
 
   pst->psymtabs_addrmap_supported = true;
 
@@ -7462,6 +6876,7 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
 {
   struct dwarf2_cu *cu = reader->cu;
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
+  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
   struct objfile *objfile = per_objfile->objfile;
   struct gdbarch *gdbarch = objfile->arch ();
   struct dwarf2_per_cu_data *per_cu = cu->per_cu;
@@ -7512,7 +6927,7 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
           - baseaddr - 1);
       /* Store the contiguous range if it is not empty; it can be
         empty for CUs with no code.  */
-      addrmap_set_empty (objfile->partial_symtabs->psymtabs_addrmap,
+      addrmap_set_empty (per_bfd->partial_symtabs->psymtabs_addrmap,
                         low, high, pst);
     }
 
@@ -7563,7 +6978,7 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
         post-pass.  */
       pst->number_of_dependencies = len;
       pst->dependencies
-       = objfile->partial_symtabs->allocate_dependencies (len);
+       = per_bfd->partial_symtabs->allocate_dependencies (len);
       for (i = 0; i < len; ++i)
        {
          pst->dependencies[i]
@@ -7617,7 +7032,10 @@ process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu,
       this_cu->unit_type = DW_UT_type;
       break;
     default:
-      abort ();
+      error (_("Dwarf Error: unexpected tag '%s' at offset %s [in module %s]"),
+            dwarf_tag_name (reader.comp_unit_die->tag),
+            sect_offset_str (reader.cu->per_cu->sect_off),
+            objfile_name (per_objfile->objfile));
     }
 
   if (reader.dummy_p)
@@ -7690,21 +7108,17 @@ struct tu_abbrev_offset
   : sig_type (sig_type_), abbrev_offset (abbrev_offset_)
   {}
 
+  /* This is used when sorting.  */
+  bool operator< (const tu_abbrev_offset &other) const
+  {
+    return abbrev_offset < other.abbrev_offset;
+  }
+
   signatured_type *sig_type;
   sect_offset abbrev_offset;
 };
 
-/* Helper routine for build_type_psymtabs_1, passed to std::sort.  */
-
-static bool
-sort_tu_by_abbrev_offset (const struct tu_abbrev_offset &a,
-                         const struct tu_abbrev_offset &b)
-{
-  return a.abbrev_offset < b.abbrev_offset;
-}
-
 /* Efficiently read all the type units.
-   This does the bulk of the work for build_type_psymtabs.
 
    The efficiency is because we sort TUs by the abbrev table they use and
    only read each abbrev table once.  In one program there are 200K TUs
@@ -7722,7 +7136,7 @@ sort_tu_by_abbrev_offset (const struct tu_abbrev_offset &a,
    dwarf2_per_objfile->per_bfd->type_unit_groups.  */
 
 static void
-build_type_psymtabs_1 (dwarf2_per_objfile *per_objfile)
+build_type_psymtabs (dwarf2_per_objfile *per_objfile)
 {
   struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
   abbrev_table_up abbrev_table;
@@ -7731,7 +7145,7 @@ build_type_psymtabs_1 (dwarf2_per_objfile *per_objfile)
   /* It's up to the caller to not call us multiple times.  */
   gdb_assert (per_objfile->per_bfd->type_unit_groups == NULL);
 
-  if (per_objfile->per_bfd->all_type_units.empty ())
+  if (per_objfile->per_bfd->tu_stats.nr_tus == 0)
     return;
 
   /* TUs typically share abbrev tables, and there can be way more TUs than
@@ -7755,18 +7169,23 @@ build_type_psymtabs_1 (dwarf2_per_objfile *per_objfile)
 
   dwarf_read_debug_printf ("Building type unit groups ...");
 
-  /* Sort in a separate table to maintain the order of all_type_units
+  /* Sort in a separate table to maintain the order of all_comp_units
      for .gdb_index: TU indices directly index all_type_units.  */
   std::vector<tu_abbrev_offset> sorted_by_abbrev;
-  sorted_by_abbrev.reserve (per_objfile->per_bfd->all_type_units.size ());
+  sorted_by_abbrev.reserve (per_objfile->per_bfd->tu_stats.nr_tus);
 
-  for (signatured_type *sig_type : per_objfile->per_bfd->all_type_units)
-    sorted_by_abbrev.emplace_back
-      (sig_type, read_abbrev_offset (per_objfile, sig_type->per_cu.section,
-                                    sig_type->per_cu.sect_off));
+  for (const auto &cu : per_objfile->per_bfd->all_comp_units)
+    {
+      if (cu->is_debug_types)
+       {
+         auto sig_type = static_cast<signatured_type *> (cu.get ());
+         sorted_by_abbrev.emplace_back
+           (sig_type, read_abbrev_offset (per_objfile, sig_type->section,
+                                          sig_type->sect_off));
+       }
+    }
 
-  std::sort (sorted_by_abbrev.begin (), sorted_by_abbrev.end (),
-            sort_tu_by_abbrev_offset);
+  std::sort (sorted_by_abbrev.begin (), sorted_by_abbrev.end ());
 
   abbrev_offset = (sect_offset) ~(unsigned) 0;
 
@@ -7783,7 +7202,7 @@ build_type_psymtabs_1 (dwarf2_per_objfile *per_objfile)
          ++tu_stats->nr_uniq_abbrev_tables;
        }
 
-      cutu_reader reader (&tu.sig_type->per_cu, per_objfile,
+      cutu_reader reader (tu.sig_type, per_objfile,
                          abbrev_table.get (), nullptr, false);
       if (!reader.dummy_p)
        build_type_psymtabs_reader (&reader, reader.info_ptr,
@@ -7799,8 +7218,7 @@ print_tu_stats (dwarf2_per_objfile *per_objfile)
   struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
 
   dwarf_read_debug_printf ("Type unit statistics:");
-  dwarf_read_debug_printf ("  %zu TUs",
-                          per_objfile->per_bfd->all_type_units.size ());
+  dwarf_read_debug_printf ("  %d TUs", tu_stats->nr_tus);
   dwarf_read_debug_printf ("  %d uniq abbrev tables",
                           tu_stats->nr_uniq_abbrev_tables);
   dwarf_read_debug_printf ("  %d symtabs from stmt_list entries",
@@ -7819,23 +7237,22 @@ static int
 build_type_psymtab_dependencies (void **slot, void *info)
 {
   dwarf2_per_objfile *per_objfile = (dwarf2_per_objfile *) info;
-  struct objfile *objfile = per_objfile->objfile;
+  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
   struct type_unit_group *tu_group = (struct type_unit_group *) *slot;
-  struct dwarf2_per_cu_data *per_cu = &tu_group->per_cu;
-  dwarf2_psymtab *pst = per_cu->v.psymtab;
+  dwarf2_psymtab *pst = tu_group->v.psymtab;
   int len = (tu_group->tus == nullptr) ? 0 : tu_group->tus->size ();
   int i;
 
   gdb_assert (len > 0);
-  gdb_assert (per_cu->type_unit_group_p ());
+  gdb_assert (tu_group->type_unit_group_p ());
 
   pst->number_of_dependencies = len;
-  pst->dependencies = objfile->partial_symtabs->allocate_dependencies (len);
+  pst->dependencies = per_bfd->partial_symtabs->allocate_dependencies (len);
   for (i = 0; i < len; ++i)
     {
       struct signatured_type *iter = tu_group->tus->at (i);
-      gdb_assert (iter->per_cu.is_debug_types);
-      pst->dependencies[i] = iter->per_cu.v.psymtab;
+      gdb_assert (iter->is_debug_types);
+      pst->dependencies[i] = iter->v.psymtab;
       iter->type_unit_group = tu_group;
     }
 
@@ -7845,18 +7262,6 @@ build_type_psymtab_dependencies (void **slot, void *info)
   return 1;
 }
 
-/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
-   Build partial symbol tables for the .debug_types comp-units.  */
-
-static void
-build_type_psymtabs (dwarf2_per_objfile *per_objfile)
-{
-  if (! create_all_type_units (per_objfile))
-    return;
-
-  build_type_psymtabs_1 (per_objfile);
-}
-
 /* Traversal function for process_skeletonless_type_unit.
    Read a TU in a DWO file and build partial symbols for it.  */
 
@@ -7880,14 +7285,14 @@ process_skeletonless_type_unit (void **slot, void *info)
   if (*slot != NULL)
     return 1;
 
-  /* This does the job that create_all_type_units would have done for
+  /* This does the job that create_all_comp_units would have done for
      this TU.  */
   entry = add_type_unit (per_objfile, dwo_unit->signature, slot);
   fill_in_sig_entry_from_dwo_entry (per_objfile, entry, dwo_unit);
   *slot = entry;
 
-  /* This does the job that build_type_psymtabs_1 would have done.  */
-  cutu_reader reader (&entry->per_cu, per_objfile, nullptr, nullptr, false);
+  /* This does the job that build_type_psymtabs would have done.  */
+  cutu_reader reader (entry, per_objfile, nullptr, nullptr, false);
   if (!reader.dummy_p)
     build_type_psymtabs_reader (&reader, reader.info_ptr,
                                reader.comp_unit_die);
@@ -7931,7 +7336,7 @@ process_skeletonless_type_units (dwarf2_per_objfile *per_objfile)
 static void
 set_partial_user (dwarf2_per_objfile *per_objfile)
 {
-  for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
+  for (const auto &per_cu : per_objfile->per_bfd->all_comp_units)
     {
       dwarf2_psymtab *pst = per_cu->v.psymtab;
 
@@ -7954,38 +7359,37 @@ static void
 dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile)
 {
   struct objfile *objfile = per_objfile->objfile;
+  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
 
   dwarf_read_debug_printf ("Building psymtabs of objfile %s ...",
                           objfile_name (objfile));
 
   scoped_restore restore_reading_psyms
-    = make_scoped_restore (&per_objfile->per_bfd->reading_partial_symbols,
-                          true);
+    = make_scoped_restore (&per_bfd->reading_partial_symbols, true);
 
-  per_objfile->per_bfd->info.read (objfile);
+  per_bfd->info.read (objfile);
 
   /* Any cached compilation units will be linked by the per-objfile
      read_in_chain.  Make sure to free them when we're done.  */
   free_cached_comp_units freer (per_objfile);
 
-  build_type_psymtabs (per_objfile);
-
   create_all_comp_units (per_objfile);
+  build_type_psymtabs (per_objfile);
 
   /* Create a temporary address map on a temporary obstack.  We later
      copy this to the final obstack.  */
   auto_obstack temp_obstack;
 
   scoped_restore save_psymtabs_addrmap
-    = make_scoped_restore (&objfile->partial_symtabs->psymtabs_addrmap,
+    = make_scoped_restore (&per_bfd->partial_symtabs->psymtabs_addrmap,
                           addrmap_create_mutable (&temp_obstack));
 
-  for (dwarf2_per_cu_data *per_cu : per_objfile->per_bfd->all_comp_units)
+  for (const auto &per_cu : per_bfd->all_comp_units)
     {
       if (per_cu->v.psymtab != NULL)
        /* In case a forward DW_TAG_imported_unit has read the CU already.  */
        continue;
-      process_psymtab_comp_unit (per_cu, per_objfile, false,
+      process_psymtab_comp_unit (per_cu.get (), per_objfile, false,
                                 language_minimal);
     }
 
@@ -7993,9 +7397,9 @@ dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile)
   process_skeletonless_type_units (per_objfile);
 
   /* Now that all TUs have been processed we can fill in the dependencies.  */
-  if (per_objfile->per_bfd->type_unit_groups != NULL)
+  if (per_bfd->type_unit_groups != NULL)
     {
-      htab_traverse_noresize (per_objfile->per_bfd->type_unit_groups.get (),
+      htab_traverse_noresize (per_bfd->type_unit_groups.get (),
                              build_type_psymtab_dependencies, per_objfile);
     }
 
@@ -8004,9 +7408,9 @@ dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile)
 
   set_partial_user (per_objfile);
 
-  objfile->partial_symtabs->psymtabs_addrmap
-    = addrmap_create_fixed (objfile->partial_symtabs->psymtabs_addrmap,
-                           objfile->partial_symtabs->obstack ());
+  per_bfd->partial_symtabs->psymtabs_addrmap
+    = addrmap_create_fixed (per_bfd->partial_symtabs->psymtabs_addrmap,
+                           per_bfd->partial_symtabs->obstack ());
   /* At this point we want to keep the address map.  */
   save_psymtabs_addrmap.release ();
 
@@ -8043,7 +7447,9 @@ static void
 read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
                              struct dwarf2_section_info *section,
                              struct dwarf2_section_info *abbrev_section,
-                             unsigned int is_dwz)
+                             unsigned int is_dwz,
+                             htab_up &types_htab,
+                             rcuh_kind section_kind)
 {
   const gdb_byte *info_ptr;
   struct objfile *objfile = per_objfile->objfile;
@@ -8058,24 +7464,38 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
 
   while (info_ptr < section->buffer + section->size)
     {
-      struct dwarf2_per_cu_data *this_cu;
+      dwarf2_per_cu_data_up this_cu;
 
       sect_offset sect_off = (sect_offset) (info_ptr - section->buffer);
 
       comp_unit_head cu_header;
       read_and_check_comp_unit_head (per_objfile, &cu_header, section,
                                     abbrev_section, info_ptr,
-                                    rcuh_kind::COMPILE);
+                                    section_kind);
 
       /* Save the compilation unit for later lookup.  */
       if (cu_header.unit_type != DW_UT_type)
        this_cu = per_objfile->per_bfd->allocate_per_cu ();
       else
        {
+         if (types_htab == nullptr)
+           types_htab = allocate_signatured_type_table ();
+
          auto sig_type = per_objfile->per_bfd->allocate_signatured_type ();
+         signatured_type *sig_ptr = sig_type.get ();
          sig_type->signature = cu_header.signature;
          sig_type->type_offset_in_tu = cu_header.type_cu_offset_in_tu;
-         this_cu = &sig_type->per_cu;
+         this_cu.reset (sig_type.release ());
+
+         void **slot = htab_find_slot (types_htab.get (), sig_ptr, INSERT);
+         gdb_assert (slot != nullptr);
+         if (*slot != nullptr)
+           complaint (_("debug type entry at offset %s is duplicate to"
+                        " the entry at offset %s, signature %s"),
+                      sect_offset_str (sect_off),
+                      sect_offset_str (sig_ptr->sect_off),
+                      hex_string (sig_ptr->signature));
+         *slot = sig_ptr;
        }
       this_cu->is_debug_types = (cu_header.unit_type == DW_UT_type);
       this_cu->sect_off = sect_off;
@@ -8083,9 +7503,8 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
       this_cu->is_dwz = is_dwz;
       this_cu->section = section;
 
-      per_objfile->per_bfd->all_comp_units.push_back (this_cu);
-
       info_ptr = info_ptr + this_cu->length;
+      per_objfile->per_bfd->all_comp_units.push_back (std::move (this_cu));
     }
 }
 
@@ -8095,13 +7514,22 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
 static void
 create_all_comp_units (dwarf2_per_objfile *per_objfile)
 {
-  gdb_assert (per_objfile->per_bfd->all_comp_units.empty ());
+  htab_up types_htab;
+
   read_comp_units_from_section (per_objfile, &per_objfile->per_bfd->info,
-                               &per_objfile->per_bfd->abbrev, 0);
+                               &per_objfile->per_bfd->abbrev, 0,
+                               types_htab, rcuh_kind::COMPILE);
+  for (dwarf2_section_info &section : per_objfile->per_bfd->types)
+    read_comp_units_from_section (per_objfile, &section,
+                                 &per_objfile->per_bfd->abbrev, 0,
+                                 types_htab, rcuh_kind::TYPE);
 
   dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd);
   if (dwz != NULL)
-    read_comp_units_from_section (per_objfile, &dwz->info, &dwz->abbrev, 1);
+    read_comp_units_from_section (per_objfile, &dwz->info, &dwz->abbrev, 1,
+                                 types_htab, rcuh_kind::COMPILE);
+
+  per_objfile->per_bfd->signatured_types = std::move (types_htab);
 }
 
 /* Process all loaded DIEs for compilation unit CU, starting at
@@ -8554,7 +7982,9 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
                                            &objfile->objfile_obstack);
          psymbol.ginfo.set_linkage_name (pdi->linkage_name);
        }
-      cu->per_cu->v.psymtab->add_psymbol (psymbol, *where, objfile);
+      cu->per_cu->v.psymtab->add_psymbol
+       (psymbol, *where, per_objfile->per_bfd->partial_symtabs.get (),
+        objfile);
     }
 }
 
@@ -8621,6 +8051,7 @@ add_partial_subprogram (struct partial_die_info *pdi,
          if (set_addrmap)
            {
              struct objfile *objfile = cu->per_objfile->objfile;
+             dwarf2_per_bfd *per_bfd = cu->per_objfile->per_bfd;
              struct gdbarch *gdbarch = objfile->arch ();
              CORE_ADDR baseaddr;
              CORE_ADDR this_highpc;
@@ -8635,7 +8066,7 @@ add_partial_subprogram (struct partial_die_info *pdi,
                = (gdbarch_adjust_dwarf2_addr (gdbarch,
                                               pdi->highpc + baseaddr)
                   - baseaddr);
-             addrmap_set_empty (objfile->partial_symtabs->psymtabs_addrmap,
+             addrmap_set_empty (per_bfd->partial_symtabs->psymtabs_addrmap,
                                 this_lowpc, this_highpc - 1,
                                 cu->per_cu->v.psymtab);
            }
@@ -9010,7 +8441,7 @@ maybe_queue_comp_unit (struct dwarf2_cu *dependent_cu,
   /* Mark the dependence relation so that we don't flush PER_CU
      too early.  */
   if (dependent_cu != NULL)
-    dwarf2_add_dependence (dependent_cu, per_cu);
+    dependent_cu->add_dependence (per_cu);
 
   /* If it's already on the queue, we have nothing to do.  */
   if (per_cu->queued)
@@ -9870,6 +9301,21 @@ process_full_comp_unit (dwarf2_cu *cu, enum language pretend_language)
 
   dwarf2_find_base_address (cu->dies, cu);
 
+  /* Before we start reading the top-level DIE, ensure it has a valid tag
+     type.  */
+  switch (cu->dies->tag)
+    {
+    case DW_TAG_compile_unit:
+    case DW_TAG_partial_unit:
+    case DW_TAG_type_unit:
+      break;
+    default:
+      error (_("Dwarf Error: unexpected tag '%s' at offset %s [in module %s]"),
+            dwarf_tag_name (cu->dies->tag),
+            sect_offset_str (cu->per_cu->sect_off),
+            objfile_name (per_objfile->objfile));
+    }
+
   /* Do line number decoding in read_file_scope () */
   process_die (cu->dies, cu);
 
@@ -10978,7 +10424,7 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
       per_objfile->line_header_hash
        .reset (htab_create_alloc (127, line_header_hash_voidp,
                                   line_header_eq_voidp,
-                                  free_line_header_voidp,
+                                  htab_delete_entry<line_header>,
                                   xcalloc, xfree));
     }
 
@@ -11309,17 +10755,10 @@ eq_dwo_file (const void *item_lhs, const void *item_rhs)
 static htab_up
 allocate_dwo_file_hash_table ()
 {
-  auto delete_dwo_file = [] (void *item)
-    {
-      struct dwo_file *dwo_file = (struct dwo_file *) item;
-
-      delete dwo_file;
-    };
-
   return htab_up (htab_create_alloc (41,
                                     hash_dwo_file,
                                     eq_dwo_file,
-                                    delete_dwo_file,
+                                    htab_delete_entry<dwo_file>,
                                     xcalloc, xfree));
 }
 
@@ -11444,7 +10883,6 @@ create_cus_hash_table (dwarf2_per_objfile *per_objfile,
       void **slot;
       sect_offset sect_off = (sect_offset) (info_ptr - section.buffer);
 
-      memset (&per_cu, 0, sizeof (per_cu));
       per_cu.per_bfd = per_bfd;
       per_cu.is_debug_types = 0;
       per_cu.sect_off = sect_offset (info_ptr - section.buffer);
@@ -12581,6 +12019,13 @@ try_open_dwop_file (dwarf2_per_objfile *per_objfile,
   else
     search_path = debug_file_directory;
 
+  /* Add the path for the executable binary to the list of search paths.  */
+  std::string objfile_dir = ldirname (objfile_name (per_objfile->objfile));
+  search_path_holder.reset (concat (objfile_dir.c_str (),
+                                   dirname_separator_string,
+                                   search_path, nullptr));
+  search_path = search_path_holder.get ();
+
   openp_flags flags = OPF_RETURN_REALPATH;
   if (is_dwp)
     flags |= OPF_SEARCH_IN_PATH;
@@ -13265,14 +12710,13 @@ queue_and_load_dwo_tu (void **slot, void *info)
 
   if (sig_type != NULL)
     {
-      struct dwarf2_per_cu_data *sig_cu = &sig_type->per_cu;
-
       /* We pass NULL for DEPENDENT_CU because we don't yet know if there's
         a real dependency of PER_CU on SIG_TYPE.  That is detected later
         while processing PER_CU.  */
-      if (maybe_queue_comp_unit (NULL, sig_cu, cu->per_objfile, cu->language))
-       load_full_type_unit (sig_cu, cu->per_objfile);
-      cu->per_cu->imported_symtabs_push (sig_cu);
+      if (maybe_queue_comp_unit (NULL, sig_type, cu->per_objfile,
+                                cu->language))
+       load_full_type_unit (sig_type, cu->per_objfile);
+      cu->per_cu->imported_symtabs_push (sig_type);
     }
 
   return 1;
@@ -13343,6 +12787,37 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
               sect_offset_str (die->sect_off),
               sect_offset_str (origin_die->sect_off));
 
+  /* Find if the concrete and abstract trees are structurally the
+     same.  This is a shallow traversal and it is not bullet-proof;
+     the compiler can trick the debugger into believing that the trees
+     are isomorphic, whereas they actually are not.  However, the
+     likelyhood of this happening is pretty low, and a full-fledged
+     check would be an overkill.  */
+  bool are_isomorphic = true;
+  die_info *concrete_child = die->child;
+  die_info *abstract_child = origin_die->child;
+  while (concrete_child != nullptr || abstract_child != nullptr)
+    {
+      if (concrete_child == nullptr
+         || abstract_child == nullptr
+         || concrete_child->tag != abstract_child->tag)
+       {
+         are_isomorphic = false;
+         break;
+       }
+
+      concrete_child = concrete_child->sibling;
+      abstract_child = abstract_child->sibling;
+    }
+
+  /* Walk the origin's children in parallel to the concrete children.
+     This helps match an origin child in case the debug info misses
+     DW_AT_abstract_origin attributes.  Keep in mind that the abstract
+     origin tree may not have the same tree structure as the concrete
+     DIE, though.  */
+  die_info *corresponding_abstract_child
+    = are_isomorphic ? origin_die->child : nullptr;
+
   std::vector<sect_offset> offsets;
 
   for (child_die = die->child;
@@ -13359,7 +12834,12 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
         one.  */
       if (child_die->tag == DW_TAG_call_site
          || child_die->tag == DW_TAG_GNU_call_site)
-       continue;
+       {
+         if (are_isomorphic)
+           corresponding_abstract_child
+             = corresponding_abstract_child->sibling;
+         continue;
+       }
 
       /* For each CHILD_DIE, find the corresponding child of
         ORIGIN_DIE.  If there is more than one layer of
@@ -13378,6 +12858,14 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
                                             &child_origin_cu);
        }
 
+      /* If missing DW_AT_abstract_origin, try the corresponding child
+        of the origin.  Clang emits such lexical scopes.  */
+      if (child_origin_die == child_die
+         && dwarf2_attr (child_die, DW_AT_abstract_origin, cu) == nullptr
+         && are_isomorphic
+         && child_die->tag == DW_TAG_lexical_block)
+       child_origin_die = corresponding_abstract_child;
+
       /* According to DWARF3 3.3.8.2 #3 new entries without their abstract
         counterpart may exist.  */
       if (child_origin_die != child_die)
@@ -13397,6 +12885,9 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
          else
            offsets.push_back (child_origin_die->sect_off);
        }
+
+      if (are_isomorphic)
+       corresponding_abstract_child = corresponding_abstract_child->sibling;
     }
   std::sort (offsets.begin (), offsets.end ());
   sect_offset *offsets_end = offsets.data () + offsets.size ();
@@ -13504,6 +12995,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
        }
     }
 
+  gdb_assert (cu->get_builder () != nullptr);
   newobj = cu->get_builder ()->push_context (0, lowpc);
   newobj->name = new_symbol (die, read_type_die (die, cu), cu,
                             (struct symbol *) templ_func);
@@ -14399,7 +13891,7 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu, dwarf_tag tag,
 
 /* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
    Return 1 if the attributes are present and valid, otherwise, return 0.
-   If RANGES_PST is not NULL we should setup `objfile->psymtabs_addrmap'.  */
+   If RANGES_PST is not NULL we should set up the `psymtabs_addrmap'.  */
 
 static int
 dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
@@ -14407,6 +13899,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
                    dwarf2_psymtab *ranges_pst, dwarf_tag tag)
 {
   struct objfile *objfile = cu->per_objfile->objfile;
+  dwarf2_per_bfd *per_bfd = cu->per_objfile->per_bfd;
   struct gdbarch *gdbarch = objfile->arch ();
   const CORE_ADDR baseaddr = objfile->text_section_offset ();
   int low_set = 0;
@@ -14428,7 +13921,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
          highpc = (gdbarch_adjust_dwarf2_addr (gdbarch,
                                                range_end + baseaddr)
                    - baseaddr);
-         addrmap_set_empty (objfile->partial_symtabs->psymtabs_addrmap,
+         addrmap_set_empty (per_bfd->partial_symtabs->psymtabs_addrmap,
                             lowpc, highpc - 1, ranges_pst);
        }
 
@@ -16001,7 +15494,7 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
     }
 
   if (cu->language == language_cplus && die->tag == DW_TAG_class_type)
-    TYPE_DECLARED_CLASS (type) = 1;
+    type->set_is_declared_class (true);
 
   /* Store the calling convention in the type if it's available in
      the die.  Otherwise the calling convention remains set to
@@ -16531,7 +16024,7 @@ update_enumeration_type_from_children (struct die_info *die,
     type->set_is_unsigned (true);
 
   if (flag_enum)
-    TYPE_FLAG_ENUM (type) = 1;
+    type->set_is_flag_enum (true);
 }
 
 /* Given a DW_AT_enumeration_type die, set its type.  We do not
@@ -16615,7 +16108,7 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
        set_type_align (type, TYPE_RAW_ALIGN (underlying_type));
     }
 
-  TYPE_DECLARED_CLASS (type) = dwarf2_flag_true_p (die, DW_AT_enum_class, cu);
+  type->set_is_declared_class (dwarf2_flag_true_p (die, DW_AT_enum_class, cu));
 
   set_die_type (die, type, cu);
 
@@ -18829,15 +18322,6 @@ dwarf2_per_objfile::int_type (int size_in_bytes, bool unsigned_p) const
   gdb_assert_not_reached ("unable to find suitable integer type");
 }
 
-/* See read.h.  */
-
-struct type *
-dwarf2_cu::addr_sized_int_type (bool unsigned_p) const
-{
-  int addr_size = this->per_cu->addr_size ();
-  return this->per_objfile->int_type (addr_size, unsigned_p);
-}
-
 /* Read the DW_AT_type attribute for a sub-range.  If this attribute is not
    present (which is valid) then compute the default type based on the
    compilation units address size.  */
@@ -19333,7 +18817,7 @@ load_partial_dies (const struct die_reader_specs *reader,
   last_die = NULL;
 
   gdb_assert (cu->per_cu != NULL);
-  if (cu->per_cu->load_all_dies)
+  if (cu->load_all_dies)
     load_all = 1;
 
   cu->partial_dies
@@ -19901,9 +19385,9 @@ find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu)
   /* If we didn't find it, and not all dies have been loaded,
      load them all and try again.  */
 
-  if (pd == NULL && cu->per_cu->load_all_dies == 0)
+  if (pd == NULL && cu->load_all_dies == 0)
     {
-      cu->per_cu->load_all_dies = 1;
+      cu->load_all_dies = 1;
 
       /* This is nasty.  When we reread the DIEs, somewhere up the call chain
         THIS_CU->cu may already be in use.  So we can't just free it and
@@ -21015,16 +20499,6 @@ die_specification (struct die_info *die, struct dwarf2_cu **spec_cu)
     return follow_die_ref (die, spec_attr, spec_cu);
 }
 
-/* Stub for free_line_header to match void * callback types.  */
-
-static void
-free_line_header_voidp (void *arg)
-{
-  struct line_header *lh = (struct line_header *) arg;
-
-  delete lh;
-}
-
 /* A convenience function to find the proper .debug_line section for a CU.  */
 
 static struct dwarf2_section_info *
@@ -21861,7 +21335,10 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
              psymtab_include_file_name (lh, file_entry, pst,
                                         comp_dir, &name_holder);
            if (include_name != NULL)
-             dwarf2_create_include_psymtab (include_name, pst, objfile);
+             dwarf2_create_include_psymtab
+               (cu->per_objfile->per_bfd, include_name, pst,
+                cu->per_objfile->per_bfd->partial_symtabs.get (),
+                objfile->per_bfd);
          }
     }
   else
@@ -21931,29 +21408,6 @@ dwarf2_start_subfile (struct dwarf2_cu *cu, const char *filename,
   cu->get_builder ()->start_subfile (filename);
 }
 
-/* Start a symtab for DWARF.  NAME, COMP_DIR, LOW_PC are passed to the
-   buildsym_compunit constructor.  */
-
-struct compunit_symtab *
-dwarf2_cu::start_symtab (const char *name, const char *comp_dir,
-                        CORE_ADDR low_pc)
-{
-  gdb_assert (m_builder == nullptr);
-
-  m_builder.reset (new struct buildsym_compunit
-                  (this->per_objfile->objfile,
-                   name, comp_dir, language, low_pc));
-
-  list_in_scope = get_builder ()->get_file_symbols ();
-
-  get_builder ()->record_debugformat ("DWARF 2");
-  get_builder ()->record_producer (producer);
-
-  processing_has_namespace_info = false;
-
-  return get_builder ()->get_compunit_symtab ();
-}
-
 static void
 var_decode_location (struct attribute *attr, struct symbol *sym,
                     struct dwarf2_cu *cu)
@@ -23158,7 +22612,7 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
        return determine_prefix (parent, cu);
       case DW_TAG_enumeration_type:
        parent_type = read_type_die (parent, cu);
-       if (TYPE_DECLARED_CLASS (parent_type))
+       if (parent_type->is_declared_class ())
          {
            if (parent_type->name () != NULL)
              return parent_type->name ();
@@ -24005,12 +23459,12 @@ follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type,
      Even if maybe_queue_comp_unit doesn't require us to load the CU's DIEs,
      it doesn't mean they are currently loaded.  Since we require them
      to be loaded, we must check for ourselves.  */
-  if (maybe_queue_comp_unit (*ref_cu, &sig_type->per_cu, per_objfile,
+  if (maybe_queue_comp_unit (*ref_cu, sig_type, per_objfile,
                             language_minimal)
-      || per_objfile->get_cu (&sig_type->per_cu) == nullptr)
+      || per_objfile->get_cu (sig_type) == nullptr)
     read_signatured_type (sig_type, per_objfile);
 
-  sig_cu = per_objfile->get_cu (&sig_type->per_cu);
+  sig_cu = per_objfile->get_cu (sig_type);
   gdb_assert (sig_cu != NULL);
   gdb_assert (to_underlying (sig_type->type_offset_in_section) != 0);
   temp_die.sect_off = sig_type->type_offset_in_section;
@@ -24199,12 +23653,10 @@ static void
 read_signatured_type (signatured_type *sig_type,
                      dwarf2_per_objfile *per_objfile)
 {
-  struct dwarf2_per_cu_data *per_cu = &sig_type->per_cu;
-
-  gdb_assert (per_cu->is_debug_types);
-  gdb_assert (per_objfile->get_cu (per_cu) == nullptr);
+  gdb_assert (sig_type->is_debug_types);
+  gdb_assert (per_objfile->get_cu (sig_type) == nullptr);
 
-  cutu_reader reader (per_cu, per_objfile, nullptr, nullptr, false);
+  cutu_reader reader (sig_type, per_objfile, nullptr, nullptr, false);
 
   if (!reader.dummy_p)
     {
@@ -24239,7 +23691,7 @@ read_signatured_type (signatured_type *sig_type,
       reader.keep ();
     }
 
-  sig_type->per_cu.tu_read = 1;
+  sig_type->tu_read = 1;
 }
 
 /* Decode simple location descriptions.
@@ -24806,23 +24258,6 @@ dwarf2_per_cu_data::ref_addr_size () const
     return header->offset_size;
 }
 
-/* See read.h.  */
-
-struct type *
-dwarf2_cu::addr_type () const
-{
-  struct objfile *objfile = this->per_objfile->objfile;
-  struct type *void_type = objfile_type (objfile)->builtin_void;
-  struct type *addr_type = lookup_pointer_type (void_type);
-  int addr_size = this->per_cu->addr_size ();
-
-  if (TYPE_LENGTH (addr_type) == addr_size)
-    return addr_type;
-
-  addr_type = addr_sized_int_type (addr_type->is_unsigned ());
-  return addr_type;
-}
-
 /* A helper function for dwarf2_find_containing_comp_unit that returns
    the index of the result, and that searches a vector.  It will
    return a result even if the offset in question does not actually
@@ -24833,7 +24268,7 @@ static int
 dwarf2_find_containing_comp_unit
   (sect_offset sect_off,
    unsigned int offset_in_dwz,
-   const std::vector<dwarf2_per_cu_data *> &all_comp_units)
+   const std::vector<dwarf2_per_cu_data_up> &all_comp_units)
 {
   int low, high;
 
@@ -24844,7 +24279,7 @@ dwarf2_find_containing_comp_unit
       struct dwarf2_per_cu_data *mid_cu;
       int mid = low + (high - low) / 2;
 
-      mid_cu = all_comp_units[mid];
+      mid_cu = all_comp_units[mid].get ();
       if (mid_cu->is_dwz > offset_in_dwz
          || (mid_cu->is_dwz == offset_in_dwz
              && mid_cu->sect_off + mid_cu->length > sect_off))
@@ -24866,7 +24301,8 @@ dwarf2_find_containing_comp_unit (sect_offset sect_off,
 {
   int low = dwarf2_find_containing_comp_unit
     (sect_off, offset_in_dwz, per_objfile->per_bfd->all_comp_units);
-  dwarf2_per_cu_data *this_cu = per_objfile->per_bfd->all_comp_units[low];
+  dwarf2_per_cu_data *this_cu
+    = per_objfile->per_bfd->all_comp_units[low].get ();
 
   if (this_cu->is_dwz != offset_in_dwz || this_cu->sect_off > sect_off)
     {
@@ -24878,7 +24314,7 @@ dwarf2_find_containing_comp_unit (sect_offset sect_off,
 
       gdb_assert (per_objfile->per_bfd->all_comp_units[low-1]->sect_off
                  <= sect_off);
-      return per_objfile->per_bfd->all_comp_units[low-1];
+      return per_objfile->per_bfd->all_comp_units[low - 1].get ();
     }
   else
     {
@@ -24898,42 +24334,46 @@ namespace find_containing_comp_unit {
 static void
 run_test ()
 {
-  struct dwarf2_per_cu_data one {};
-  struct dwarf2_per_cu_data two {};
-  struct dwarf2_per_cu_data three {};
-  struct dwarf2_per_cu_data four {};
-
-  one.length = 5;
-  two.sect_off = sect_offset (one.length);
-  two.length = 7;
-
-  three.length = 5;
-  three.is_dwz = 1;
-  four.sect_off = sect_offset (three.length);
-  four.length = 7;
-  four.is_dwz = 1;
-
-  std::vector<dwarf2_per_cu_data *> units;
-  units.push_back (&one);
-  units.push_back (&two);
-  units.push_back (&three);
-  units.push_back (&four);
+  dwarf2_per_cu_data_up one (new dwarf2_per_cu_data);
+  dwarf2_per_cu_data *one_ptr = one.get ();
+  dwarf2_per_cu_data_up two (new dwarf2_per_cu_data);
+  dwarf2_per_cu_data *two_ptr = two.get ();
+  dwarf2_per_cu_data_up three (new dwarf2_per_cu_data);
+  dwarf2_per_cu_data *three_ptr = three.get ();
+  dwarf2_per_cu_data_up four (new dwarf2_per_cu_data);
+  dwarf2_per_cu_data *four_ptr = four.get ();
+
+  one->length = 5;
+  two->sect_off = sect_offset (one->length);
+  two->length = 7;
+
+  three->length = 5;
+  three->is_dwz = 1;
+  four->sect_off = sect_offset (three->length);
+  four->length = 7;
+  four->is_dwz = 1;
+
+  std::vector<dwarf2_per_cu_data_up> units;
+  units.push_back (std::move (one));
+  units.push_back (std::move (two));
+  units.push_back (std::move (three));
+  units.push_back (std::move (four));
 
   int result;
 
   result = dwarf2_find_containing_comp_unit (sect_offset (0), 0, units);
-  SELF_CHECK (units[result] == &one);
+  SELF_CHECK (units[result].get () == one_ptr);
   result = dwarf2_find_containing_comp_unit (sect_offset (3), 0, units);
-  SELF_CHECK (units[result] == &one);
+  SELF_CHECK (units[result].get () == one_ptr);
   result = dwarf2_find_containing_comp_unit (sect_offset (5), 0, units);
-  SELF_CHECK (units[result] == &two);
+  SELF_CHECK (units[result].get () == two_ptr);
 
   result = dwarf2_find_containing_comp_unit (sect_offset (0), 1, units);
-  SELF_CHECK (units[result] == &three);
+  SELF_CHECK (units[result].get () == three_ptr);
   result = dwarf2_find_containing_comp_unit (sect_offset (3), 1, units);
-  SELF_CHECK (units[result] == &three);
+  SELF_CHECK (units[result].get () == three_ptr);
   result = dwarf2_find_containing_comp_unit (sect_offset (5), 1, units);
-  SELF_CHECK (units[result] == &four);
+  SELF_CHECK (units[result].get () == four_ptr);
 }
 
 }
@@ -24941,24 +24381,6 @@ run_test ()
 
 #endif /* GDB_SELF_TEST */
 
-/* Initialize dwarf2_cu to read PER_CU, in the context of PER_OBJFILE.  */
-
-dwarf2_cu::dwarf2_cu (dwarf2_per_cu_data *per_cu,
-                     dwarf2_per_objfile *per_objfile)
-  : per_cu (per_cu),
-    per_objfile (per_objfile),
-    mark (false),
-    has_loclist (false),
-    checked_producer (false),
-    producer_is_gxx_lt_4_6 (false),
-    producer_is_gcc_lt_4_3 (false),
-    producer_is_icc (false),
-    producer_is_icc_lt_14 (false),
-    producer_is_codewarrior (false),
-    processing_has_namespace_info (false)
-{
-}
-
 /* Initialize basic fields of dwarf_cu CU according to DIE COMP_UNIT_DIE.  */
 
 static void
@@ -25018,7 +24440,7 @@ dwarf2_per_objfile::age_comp_units ()
 
   /* Start by clearing all marks.  */
   for (auto pair : m_dwarf2_cus)
-    pair.second->mark = false;
+    pair.second->clear_mark ();
 
   /* Traverse all CUs, mark them and their dependencies if used recently
      enough.  */
@@ -25028,7 +24450,7 @@ dwarf2_per_objfile::age_comp_units ()
 
       cu->last_used++;
       if (cu->last_used <= dwarf_max_cache_age)
-       dwarf2_mark (cu);
+       cu->mark ();
     }
 
   /* Delete all CUs still not marked.  */
@@ -25036,7 +24458,7 @@ dwarf2_per_objfile::age_comp_units ()
     {
       dwarf2_cu *cu = it->second;
 
-      if (!cu->mark)
+      if (!cu->is_marked ())
        {
          dwarf_read_debug_printf_v ("deleting old CU %s",
                                     sect_offset_str (cu->per_cu->sect_off));
@@ -25237,71 +24659,6 @@ get_die_type (struct die_info *die, struct dwarf2_cu *cu)
   return get_die_type_at_offset (die->sect_off, cu->per_cu, cu->per_objfile);
 }
 
-/* Add a dependence relationship from CU to REF_PER_CU.  */
-
-static void
-dwarf2_add_dependence (struct dwarf2_cu *cu,
-                      struct dwarf2_per_cu_data *ref_per_cu)
-{
-  void **slot;
-
-  if (cu->dependencies == NULL)
-    cu->dependencies
-      = htab_create_alloc_ex (5, htab_hash_pointer, htab_eq_pointer,
-                             NULL, &cu->comp_unit_obstack,
-                             hashtab_obstack_allocate,
-                             dummy_obstack_deallocate);
-
-  slot = htab_find_slot (cu->dependencies, ref_per_cu, INSERT);
-  if (*slot == NULL)
-    *slot = ref_per_cu;
-}
-
-/* Subroutine of dwarf2_mark to pass to htab_traverse.
-   Set the mark field in every compilation unit in the
-   cache that we must keep because we are keeping CU.
-
-   DATA is the dwarf2_per_objfile object in which to look up CUs.  */
-
-static int
-dwarf2_mark_helper (void **slot, void *data)
-{
-  dwarf2_per_cu_data *per_cu = (dwarf2_per_cu_data *) *slot;
-  dwarf2_per_objfile *per_objfile = (dwarf2_per_objfile *) data;
-  dwarf2_cu *cu = per_objfile->get_cu (per_cu);
-
-  /* cu->dependencies references may not yet have been ever read if QUIT aborts
-     reading of the chain.  As such dependencies remain valid it is not much
-     useful to track and undo them during QUIT cleanups.  */
-  if (cu == nullptr)
-    return 1;
-
-  if (cu->mark)
-    return 1;
-
-  cu->mark = true;
-
-  if (cu->dependencies != nullptr)
-    htab_traverse (cu->dependencies, dwarf2_mark_helper, per_objfile);
-
-  return 1;
-}
-
-/* Set the mark field in CU and in every other compilation unit in the
-   cache that we must keep because we are keeping CU.  */
-
-static void
-dwarf2_mark (struct dwarf2_cu *cu)
-{
-  if (cu->mark)
-    return;
-
-  cu->mark = true;
-
-  if (cu->dependencies != nullptr)
-    htab_traverse (cu->dependencies, dwarf2_mark_helper, cu->per_objfile);
-}
-
 /* Trivial hash function for partial_die_info: the hash value of a DIE
    is its offset in .debug_info for this objfile.  */
 
@@ -25347,13 +24704,13 @@ _initialize_dwarf2_read ()
   add_basic_prefix_cmd ("dwarf", class_maintenance, _("\
 Set DWARF specific variables.\n\
 Configure DWARF variables such as the cache size."),
-                       &set_dwarf_cmdlist, "maintenance set dwarf ",
+                       &set_dwarf_cmdlist,
                        0/*allow-unknown*/, &maintenance_set_cmdlist);
 
   add_show_prefix_cmd ("dwarf", class_maintenance, _("\
 Show DWARF specific variables.\n\
 Show DWARF variables such as the cache size."),
-                      &show_dwarf_cmdlist, "maintenance show dwarf ",
+                      &show_dwarf_cmdlist,
                       0/*allow-unknown*/, &maintenance_show_cmdlist);
 
   add_setshow_zinteger_cmd ("max-cache-age", class_obscure,