]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/dwarf2/read.c
gdbsupport: add path_join function
[thirdparty/binutils-gdb.git] / gdb / dwarf2 / read.c
index ff5758eb0a4350b3e4a87a697a5f0969e2e3d899..8586463f5505a563831bca7c251d360f5b9bf1af 100644 (file)
@@ -1,6 +1,6 @@
 /* DWARF 2 debugging format support for GDB.
 
-   Copyright (C) 1994-2021 Free Software Foundation, Inc.
+   Copyright (C) 1994-2022 Free Software Foundation, Inc.
 
    Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
    Inc.  with support from Florida State University (under contract
@@ -64,7 +64,6 @@
 #include "block.h"
 #include "addrmap.h"
 #include "typeprint.h"
-#include "psympriv.h"
 #include "c-lang.h"
 #include "go-lang.h"
 #include "valprint.h"
 #include "gdbsupport/pathstuff.h"
 #include "count-one-bits.h"
 #include <unordered_set>
+#include "dwarf2/abbrev-cache.h"
+#include "cooked-index.h"
+#include "split-name.h"
+#include "gdbsupport/parallel-for.h"
+#include "gdbsupport/thread-pool.h"
 
 /* When == 1, print basic high level tracing messages.
    When > 1, be more verbose.
@@ -152,78 +156,6 @@ static int dwarf2_loclist_block_index;
 /* Size of .debug_rnglists section header for 64-bit DWARF format.  */
 #define RNGLIST_HEADER_SIZE64 20
 
-/* An index into a (C++) symbol name component in a symbol name as
-   recorded in the mapped_index's symbol table.  For each C++ symbol
-   in the symbol table, we record one entry for the start of each
-   component in the symbol in a table of name components, and then
-   sort the table, in order to be able to binary search symbol names,
-   ignoring leading namespaces, both completion and regular look up.
-   For example, for symbol "A::B::C", we'll have an entry that points
-   to "A::B::C", another that points to "B::C", and another for "C".
-   Note that function symbols in GDB index have no parameter
-   information, just the function/method names.  You can convert a
-   name_component to a "const char *" using the
-   'mapped_index::symbol_name_at(offset_type)' method.  */
-
-struct name_component
-{
-  /* Offset in the symbol name where the component starts.  Stored as
-     a (32-bit) offset instead of a pointer to save memory and improve
-     locality on 64-bit architectures.  */
-  offset_type name_offset;
-
-  /* The symbol's index in the symbol and constant pool tables of a
-     mapped_index.  */
-  offset_type idx;
-};
-
-/* Base class containing bits shared by both .gdb_index and
-   .debug_name indexes.  */
-
-struct mapped_index_base
-{
-  mapped_index_base () = default;
-  DISABLE_COPY_AND_ASSIGN (mapped_index_base);
-
-  /* The name_component table (a sorted vector).  See name_component's
-     description above.  */
-  std::vector<name_component> name_components;
-
-  /* How NAME_COMPONENTS is sorted.  */
-  enum case_sensitivity name_components_casing;
-
-  /* Return the number of names in the symbol table.  */
-  virtual size_t symbol_name_count () const = 0;
-
-  /* Get the name of the symbol at IDX in the symbol table.  */
-  virtual const char *symbol_name_at
-    (offset_type idx, dwarf2_per_objfile *per_objfile) const = 0;
-
-  /* Return whether the name at IDX in the symbol table should be
-     ignored.  */
-  virtual bool symbol_name_slot_invalid (offset_type idx) const
-  {
-    return false;
-  }
-
-  /* Build the symbol name component sorted vector, if we haven't
-     yet.  */
-  void build_name_components (dwarf2_per_objfile *per_objfile);
-
-  /* Returns the lower (inclusive) and upper (exclusive) bounds of the
-     possible matches for LN_NO_PARAMS in the name component
-     vector.  */
-  std::pair<std::vector<name_component>::const_iterator,
-           std::vector<name_component>::const_iterator>
-    find_name_components_bounds (const lookup_name_info &ln_no_params,
-                                enum language lang,
-                                dwarf2_per_objfile *per_objfile) const;
-
-  /* Prevent deleting/destroying via a base class pointer.  */
-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.  */
@@ -311,6 +243,13 @@ struct mapped_index final : public mapped_index_base
 
   size_t symbol_name_count () const override
   { return this->symbol_table.size () / 2; }
+
+  quick_symbol_functions_up make_quick_functions () const override;
+
+  bool version_check () const override
+  {
+    return version >= 8;
+  }
 };
 
 /* A description of the mapped .debug_names.
@@ -360,9 +299,11 @@ struct mapped_debug_names final : public mapped_index_base
 
   size_t symbol_name_count () const override
   { return this->name_count; }
+
+  quick_symbol_functions_up make_quick_functions () const override;
 };
 
-/* See dwarf2read.h.  */
+/* See dwarf2/read.h.  */
 
 dwarf2_per_objfile *
 get_dwarf2_per_objfile (struct objfile *objfile)
@@ -477,13 +418,8 @@ struct stmt_list_hash
    that can be shared across objfiles.  The non-shareable parts are in
    type_unit_group_unshareable.  */
 
-struct type_unit_group : public dwarf2_per_cu_data
+struct type_unit_group
 {
-  /* 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 = nullptr;
-
   /* The data used to construct the hash key.  */
   struct stmt_list_hash hash {};
 };
@@ -791,7 +727,8 @@ public:
               dwarf2_per_objfile *per_objfile,
               struct abbrev_table *abbrev_table,
               dwarf2_cu *existing_cu,
-              bool skip_partial);
+              bool skip_partial,
+              abbrev_cache *cache = nullptr);
 
   explicit cutu_reader (struct dwarf2_per_cu_data *this_cu,
                        dwarf2_per_objfile *per_objfile,
@@ -800,6 +737,8 @@ public:
 
   DISABLE_COPY_AND_ASSIGN (cutu_reader);
 
+  cutu_reader (cutu_reader &&) = default;
+
   const gdb_byte *info_ptr = nullptr;
   struct die_info *comp_unit_die = nullptr;
   bool dummy_p = false;
@@ -808,6 +747,13 @@ public:
      for dummy CUs.  */
   void keep ();
 
+  /* Release the abbrev table, transferring ownership to the
+     caller.  */
+  abbrev_table_up release_abbrev_table ()
+  {
+    return std::move (m_abbrev_table_holder);
+  }
+
 private:
   void init_tu_and_read_dwo_dies (dwarf2_per_cu_data *this_cu,
                                  dwarf2_per_objfile *per_objfile,
@@ -823,164 +769,6 @@ private:
   abbrev_table_up m_dwo_abbrev_table;
 };
 
-/* When we construct a partial symbol table entry we only
-   need this much information.  */
-struct partial_die_info : public allocate_on_obstack
-  {
-    partial_die_info (sect_offset sect_off, const struct abbrev_info *abbrev);
-
-    /* Disable assign but still keep copy ctor, which is needed
-       load_partial_dies.   */
-    partial_die_info& operator=(const partial_die_info& rhs) = delete;
-    partial_die_info (const partial_die_info &) = default;
-
-    /* Adjust the partial die before generating a symbol for it.  This
-       function may set the is_external flag or change the DIE's
-       name.  */
-    void fixup (struct dwarf2_cu *cu);
-
-    /* Read a minimal amount of information into the minimal die
-       structure.  */
-    const gdb_byte *read (const struct die_reader_specs *reader,
-                         const struct abbrev_info &abbrev,
-                         const gdb_byte *info_ptr);
-
-    /* Compute the name of this partial DIE.  This memoizes the
-       result, so it is safe to call multiple times.  */
-    const char *name (dwarf2_cu *cu);
-
-    /* Offset of this DIE.  */
-    const sect_offset sect_off;
-
-    /* DWARF-2 tag for this DIE.  */
-    const ENUM_BITFIELD(dwarf_tag) tag : 16;
-
-    /* Assorted flags describing the data found in this DIE.  */
-    const unsigned int has_children : 1;
-
-    unsigned int is_external : 1;
-    unsigned int is_declaration : 1;
-    unsigned int has_type : 1;
-    unsigned int has_specification : 1;
-    unsigned int has_pc_info : 1;
-    unsigned int has_range_info : 1;
-    unsigned int may_be_inlined : 1;
-
-    /* This DIE has been marked DW_AT_main_subprogram.  */
-    unsigned int main_subprogram : 1;
-
-    /* Flag set if the SCOPE field of this structure has been
-       computed.  */
-    unsigned int scope_set : 1;
-
-    /* Flag set if the DIE has a byte_size attribute.  */
-    unsigned int has_byte_size : 1;
-
-    /* Flag set if the DIE has a DW_AT_const_value attribute.  */
-    unsigned int has_const_value : 1;
-
-    /* Flag set if any of the DIE's children are template arguments.  */
-    unsigned int has_template_arguments : 1;
-
-    /* Flag set if fixup has been called on this die.  */
-    unsigned int fixup_called : 1;
-
-    /* Flag set if DW_TAG_imported_unit uses DW_FORM_GNU_ref_alt.  */
-    unsigned int is_dwz : 1;
-
-    /* Flag set if spec_offset uses DW_FORM_GNU_ref_alt.  */
-    unsigned int spec_is_dwz : 1;
-
-    unsigned int canonical_name : 1;
-
-    /* The name of this DIE.  Normally the value of DW_AT_name, but
-       sometimes a default name for unnamed DIEs.  */
-    const char *raw_name = nullptr;
-
-    /* The linkage name, if present.  */
-    const char *linkage_name = nullptr;
-
-    /* The scope to prepend to our children.  This is generally
-       allocated on the comp_unit_obstack, so will disappear
-       when this compilation unit leaves the cache.  */
-    const char *scope = nullptr;
-
-    /* Some data associated with the partial DIE.  The tag determines
-       which field is live.  */
-    union
-    {
-      /* The location description associated with this DIE, if any.  */
-      struct dwarf_block *locdesc;
-      /* The offset of an import, for DW_TAG_imported_unit.  */
-      sect_offset sect_off;
-    } d {};
-
-    union
-    {
-      /* If HAS_PC_INFO, the PC range associated with this DIE.  */
-      struct
-      {
-       CORE_ADDR lowpc;
-       CORE_ADDR highpc;
-      };
-      /* If HAS_RANGE_INFO, the ranges offset associated with this DIE.  */
-      ULONGEST ranges_offset;
-    };
-
-    /* Pointer into the info_buffer (or types_buffer) pointing at the target of
-       DW_AT_sibling, if any.  */
-    /* NOTE: This member isn't strictly necessary, partial_die_info::read
-       could return DW_AT_sibling values to its caller load_partial_dies.  */
-    const gdb_byte *sibling = nullptr;
-
-    /* If HAS_SPECIFICATION, the offset of the DIE referred to by
-       DW_AT_specification (or DW_AT_abstract_origin or
-       DW_AT_extension).  */
-    sect_offset spec_offset {};
-
-    /* Pointers to this DIE's parent, first child, and next sibling,
-       if any.  */
-    struct partial_die_info *die_parent = nullptr;
-    struct partial_die_info *die_child = nullptr;
-    struct partial_die_info *die_sibling = nullptr;
-
-    friend struct partial_die_info *
-    dwarf2_cu::find_partial_die (sect_offset sect_off);
-
-  private:
-    /* Only need to do look up in dwarf2_cu::find_partial_die.  */
-    partial_die_info (sect_offset sect_off)
-      : partial_die_info (sect_off, DW_TAG_padding, 0)
-    {
-    }
-
-    partial_die_info (sect_offset sect_off_, enum dwarf_tag tag_,
-                     int has_children_)
-      : sect_off (sect_off_), tag (tag_), has_children (has_children_)
-    {
-      is_external = 0;
-      is_declaration = 0;
-      has_type = 0;
-      has_specification = 0;
-      has_pc_info = 0;
-      has_range_info = 0;
-      may_be_inlined = 0;
-      main_subprogram = 0;
-      scope_set = 0;
-      has_byte_size = 0;
-      has_const_value = 0;
-      has_template_arguments = 0;
-      fixup_called = 0;
-      is_dwz = 0;
-      spec_is_dwz = 0;
-      canonical_name = 0;
-      /* Don't set these using NSDMI (Non-static data member initialisation),
-        because g++-4.8 will error out.  */
-      lowpc = 0;
-      highpc = 0;
-    }
-  };
-
 /* FIXME: We might want to set this from BFD via bfd_arch_bits_per_byte,
    but this would require a corresponding change in unpack_field_as_long
    and friends.  */
@@ -1090,9 +878,9 @@ static void
 show_dwarf_max_cache_age (struct ui_file *file, int from_tty,
                          struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("The upper bound on the age of cached "
-                           "DWARF compilation units is %s.\n"),
-                   value);
+  gdb_printf (file, _("The upper bound on the age of cached "
+                     "DWARF compilation units is %s.\n"),
+             value);
 }
 \f
 /* local function prototypes */
@@ -1100,63 +888,14 @@ show_dwarf_max_cache_age (struct ui_file *file, int from_tty,
 static void dwarf2_find_base_address (struct die_info *die,
                                      struct dwarf2_cu *cu);
 
-static dwarf2_psymtab *create_partial_symtab
-  (dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile,
-   const char *name);
-
-static void build_type_psymtabs_reader (const struct die_reader_specs *reader,
-                                       const gdb_byte *info_ptr,
-                                       struct die_info *type_unit_die);
+class cooked_index_storage;
+static void build_type_psymtabs_reader (cutu_reader *reader,
+                                       cooked_index_storage *storage);
 
 static void dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile);
 
-static void scan_partial_symbols (struct partial_die_info *,
-                                 CORE_ADDR *, CORE_ADDR *,
-                                 int, struct dwarf2_cu *);
-
-static void add_partial_symbol (struct partial_die_info *,
-                               struct dwarf2_cu *);
-
-static void add_partial_namespace (struct partial_die_info *pdi,
-                                  CORE_ADDR *lowpc, CORE_ADDR *highpc,
-                                  int set_addrmap, struct dwarf2_cu *cu);
-
-static void add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
-                               CORE_ADDR *highpc, int set_addrmap,
-                               struct dwarf2_cu *cu);
-
-static void add_partial_enumeration (struct partial_die_info *enum_pdi,
-                                    struct dwarf2_cu *cu);
-
-static void add_partial_subprogram (struct partial_die_info *pdi,
-                                   CORE_ADDR *lowpc, CORE_ADDR *highpc,
-                                   int need_pc, struct dwarf2_cu *cu);
-
 static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
 
-static struct partial_die_info *load_partial_dies
-  (const struct die_reader_specs *, const gdb_byte *, int);
-
-/* A pair of partial_die_info and compilation unit.  */
-struct cu_partial_die_info
-{
-  /* The compilation unit of the partial_die_info.  */
-  struct dwarf2_cu *cu;
-  /* A partial_die_info.  */
-  struct partial_die_info *pdi;
-
-  cu_partial_die_info (struct dwarf2_cu *cu, struct partial_die_info *pdi)
-    : cu (cu),
-      pdi (pdi)
-  { /* Nothing.  */ }
-
-private:
-  cu_partial_die_info () = delete;
-};
-
-static const struct cu_partial_die_info find_partial_die (sect_offset, int,
-                                                         struct dwarf2_cu *);
-
 static const gdb_byte *read_attribute (const struct die_reader_specs *,
                                       struct attribute *,
                                       const struct attr_abbrev *,
@@ -1207,8 +946,7 @@ static line_header_up dwarf_decode_line_header (sect_offset sect_off,
                                                struct dwarf2_cu *cu);
 
 static void dwarf_decode_lines (struct line_header *,
-                               const file_and_directory &,
-                               struct dwarf2_cu *, dwarf2_psymtab *,
+                               struct dwarf2_cu *,
                                CORE_ADDR, int decode_mapping);
 
 static void dwarf2_start_subfile (struct dwarf2_cu *, const char *,
@@ -1297,7 +1035,8 @@ enum pc_bounds_kind
 static enum pc_bounds_kind dwarf2_get_pc_bounds (struct die_info *,
                                                 CORE_ADDR *, CORE_ADDR *,
                                                 struct dwarf2_cu *,
-                                                dwarf2_psymtab *);
+                                                addrmap *,
+                                                void *);
 
 static void get_scope_pc_bounds (struct die_info *,
                                 CORE_ADDR *, CORE_ADDR *,
@@ -1441,11 +1180,8 @@ static void dwarf2_symbol_mark_computed (const struct attribute *attr,
 
 static const gdb_byte *skip_one_die (const struct die_reader_specs *reader,
                                     const gdb_byte *info_ptr,
-                                    const struct abbrev_info *abbrev);
-
-static hashval_t partial_die_hash (const void *item);
-
-static int partial_die_eq (const void *item_lhs, const void *item_rhs);
+                                    const struct abbrev_info *abbrev,
+                                    bool do_skip_children = true);
 
 static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit
   (sect_offset sect_off, unsigned int offset_in_dwz,
@@ -1544,7 +1280,7 @@ static const char *compute_include_file_name
      (const struct line_header *lh,
       const file_entry &fe,
       const file_and_directory &cu_info,
-      gdb::unique_xmalloc_ptr<char> *name_holder);
+      std::string &name_holder);
 
 static htab_up allocate_signatured_type_table ();
 
@@ -2024,6 +1760,25 @@ dwarf2_get_section_info (struct objfile *objfile,
   *sizep = info->size;
 }
 
+/* See dwarf2/read.h.  */
+
+void
+dwarf2_per_bfd::map_info_sections (struct objfile *objfile)
+{
+  info.read (objfile);
+  abbrev.read (objfile);
+  line.read (objfile);
+  str.read (objfile);
+  str_offsets.read (objfile);
+  line_str.read (objfile);
+  ranges.read (objfile);
+  rnglists.read (objfile);
+  addr.read (objfile);
+
+  for (auto &section : types)
+    section.read (objfile);
+}
+
 \f
 /* DWARF quick_symbol_functions support.  */
 
@@ -2053,49 +1808,6 @@ struct quick_file_names
   const char **real_names;
 };
 
-/* When using the index (and thus not using psymtabs), each CU has an
-   object of this type.  This is used to hold information needed by
-   the various "quick" methods.  */
-struct dwarf2_per_cu_quick_data
-{
-  /* The file table.  This can be NULL if there was no file table
-     or it's currently not read in.
-     NOTE: This points into dwarf2_per_objfile->per_bfd->quick_file_names_table.  */
-  struct quick_file_names *file_names;
-
-  /* A temporary mark bit used when iterating over all CUs in
-     expand_symtabs_matching.  */
-  unsigned int mark : 1;
-
-  /* True if we've tried to read the file table.  There will be no
-     point in trying to read it again next time.  */
-  bool files_read : 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;
@@ -2134,6 +1846,40 @@ struct dwarf2_base_index_functions : public quick_symbol_functions
                             bool need_fullname) override;
 };
 
+/* With OBJF_READNOW, the DWARF reader expands all CUs immediately.
+   It's handy in this case to have an empty implementation of the
+   quick symbol functions, to avoid special cases in the rest of the
+   code.  */
+
+struct readnow_functions : 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
+  {
+    return true;
+  }
+};
+
 struct dwarf2_gdb_index : public dwarf2_base_index_functions
 {
   void dump (struct objfile *objfile) override;
@@ -2178,14 +1924,14 @@ struct dwarf2_debug_names_index : public dwarf2_base_index_functions
      enum search_domain kind) override;
 };
 
-static quick_symbol_functions_up
-make_dwarf_gdb_index ()
+quick_symbol_functions_up
+mapped_index::make_quick_functions () const
 {
   return quick_symbol_functions_up (new dwarf2_gdb_index);
 }
 
-static quick_symbol_functions_up
-make_dwarf_debug_names ()
+quick_symbol_functions_up
+mapped_debug_names::make_quick_functions () const
 {
   return quick_symbol_functions_up (new dwarf2_debug_names_index);
 }
@@ -2279,11 +2025,6 @@ static void
 dw2_do_instantiate_symtab (dwarf2_per_cu_data *per_cu,
                           dwarf2_per_objfile *per_objfile, bool skip_partial)
 {
-  /* Skip type_unit_groups, reading the type units they contain
-     is handled elsewhere.  */
-  if (per_cu->type_unit_group_p ())
-    return;
-
   {
     /* The destructor of dwarf2_queue_guard frees any entries left on
        the queue.  After this point we're guaranteed to leave this function
@@ -2302,7 +2043,7 @@ dw2_do_instantiate_symtab (dwarf2_per_cu_data *per_cu,
            && cu != NULL
            && cu->dwo_unit != NULL
            && per_objfile->per_bfd->index_table != NULL
-           && per_objfile->per_bfd->index_table->version <= 7
+           && !per_objfile->per_bfd->index_table->version_check ()
            /* DWP files aren't supported yet.  */
            && get_dwp_file (per_objfile) == NULL)
          queue_and_load_all_dwo_tus (cu);
@@ -2326,8 +2067,6 @@ dw2_instantiate_symtab (dwarf2_per_cu_data *per_cu,
                        dwarf2_per_objfile *per_objfile,
                        bool skip_partial)
 {
-  gdb_assert (per_objfile->per_bfd->using_index);
-
   if (!per_objfile->symtab_set_p (per_cu))
     {
       free_cached_comp_units freer (per_objfile);
@@ -2376,8 +2115,6 @@ create_cu_from_index_list (dwarf2_per_bfd *per_bfd,
   the_cu->sect_off = sect_off;
   the_cu->length = length;
   the_cu->section = section;
-  the_cu->v.quick = OBSTACK_ZALLOC (&per_bfd->obstack,
-                                   struct dwarf2_per_cu_quick_data);
   the_cu->is_dwz = is_dwz;
   return the_cu;
 }
@@ -2458,9 +2195,6 @@ create_signatured_type_table_from_index
       sig_type->type_offset_in_tu = type_offset_in_tu;
       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.get (), INSERT);
       *slot = sig_type.get ();
@@ -2509,9 +2243,6 @@ create_signatured_type_table_from_debug_names
       sig_type->type_offset_in_tu = cu_header.type_cu_offset_in_tu;
       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.get (), INSERT);
       *slot = sig_type.get ();
@@ -2579,12 +2310,14 @@ create_addrmap_from_index (dwarf2_per_objfile *per_objfile,
                                                 &per_bfd->obstack);
 }
 
-/* Read the address map data from DWARF-5 .debug_aranges, and use it to
-   populate the psymtabs_addrmap.  */
+/* Read the address map data from DWARF-5 .debug_aranges, and use it
+   to populate given addrmap.  Returns true on success, false on
+   failure.  */
 
-static void
-create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
-                            struct dwarf2_section_info *section)
+static bool
+read_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
+                          struct dwarf2_section_info *section,
+                          addrmap *mutable_map)
 {
   struct objfile *objfile = per_objfile->objfile;
   bfd *abfd = objfile->obfd;
@@ -2592,9 +2325,6 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
   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);
-
   std::unordered_map<sect_offset,
                     dwarf2_per_cu_data *,
                     gdb::hash_enum<sect_offset>>
@@ -2603,8 +2333,9 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
     {
       /* A TU will not need aranges, and skipping them here is an easy
         way of ignoring .debug_types -- and possibly seeing a
-        duplicate section offset -- entirely.  */
-      if (per_cu->is_debug_types)
+        duplicate section offset -- entirely.  The same applies to
+        units coming from a dwz file.  */
+      if (per_cu->is_debug_types || per_cu->is_dwz)
        continue;
 
       const auto insertpair
@@ -2615,7 +2346,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
          warning (_("Section .debug_aranges in %s has duplicate "
                     "debug_info_offset %s, ignoring .debug_aranges."),
                   objfile_name (objfile), sect_offset_str (per_cu->sect_off));
-         return;
+         return false;
        }
     }
 
@@ -2646,7 +2377,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                   plongest (entry_addr - section->buffer),
                   plongest (bytes_read + entry_length),
                   pulongest (section->size));
-         return;
+         return false;
        }
 
       /* The version number.  */
@@ -2658,7 +2389,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                     "has unsupported version %d, ignoring .debug_aranges."),
                   objfile_name (objfile),
                   plongest (entry_addr - section->buffer), version);
-         return;
+         return false;
        }
 
       const uint64_t debug_info_offset
@@ -2674,7 +2405,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                   objfile_name (objfile),
                   plongest (entry_addr - section->buffer),
                   pulongest (debug_info_offset));
-         return;
+         return false;
        }
       dwarf2_per_cu_data *const per_cu = per_cu_it->second;
 
@@ -2685,7 +2416,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                     "address_size %u is invalid, ignoring .debug_aranges."),
                   objfile_name (objfile),
                   plongest (entry_addr - section->buffer), address_size);
-         return;
+         return false;
        }
 
       const uint8_t segment_selector_size = *addr++;
@@ -2697,7 +2428,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                   objfile_name (objfile),
                   plongest (entry_addr - section->buffer),
                   segment_selector_size);
-         return;
+         return false;
        }
 
       /* Must pad to an alignment boundary that is twice the address
@@ -2709,7 +2440,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
         bytes.  */
       addr += (entry_end - addr) % (2 * address_size);
 
-      for (;;)
+      while (addr < entry_end)
        {
          if (addr + 2 * address_size > entry_end)
            {
@@ -2718,7 +2449,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                         "ignoring .debug_aranges."),
                       objfile_name (objfile),
                       plongest (entry_addr - section->buffer));
-             return;
+             return false;
            }
          ULONGEST start = extract_unsigned_integer (addr, address_size,
                                                     dwarf5_byte_order);
@@ -2727,7 +2458,14 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                                                      dwarf5_byte_order);
          addr += address_size;
          if (start == 0 && length == 0)
-           break;
+           {
+             /* This can happen on some targets with --gc-sections.
+                This pair of values is also used to mark the end of
+                the entries for a given CU, but we ignore it and
+                instead handle termination using the check at the top
+                of the loop.  */
+             continue;
+           }
          if (start == 0 && !per_bfd->has_section_at_zero)
            {
              /* Symbol was eliminated due to a COMDAT group.  */
@@ -2740,10 +2478,28 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                 - baseaddr);
          addrmap_set_empty (mutable_map, start, end - 1, per_cu);
        }
+
+      per_cu->addresses_seen = true;
     }
 
-  per_bfd->index_addrmap = addrmap_create_fixed (mutable_map,
-                                                &per_bfd->obstack);
+  return true;
+}
+
+/* Read the address map data from DWARF-5 .debug_aranges, and use it to
+   populate the psymtabs_addrmap.  */
+
+static void
+create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
+                            struct dwarf2_section_info *section)
+{
+  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
+
+  auto_obstack temp_obstack;
+  addrmap *mutable_map = addrmap_create_mutable (&temp_obstack);
+
+  if (read_addrmap_from_aranges (per_objfile, section, mutable_map))
+    per_bfd->index_addrmap = addrmap_create_fixed (mutable_map,
+                                                  &per_bfd->obstack);
 }
 
 /* A helper function that reads the .gdb_index from BUFFER and fills
@@ -2948,7 +2704,6 @@ dwarf2_read_gdb_index
   create_addrmap_from_index (per_objfile, map.get ());
 
   per_bfd->index_table = std::move (map);
-  per_bfd->using_index = 1;
   per_bfd->quick_file_names_table =
     create_quick_file_names_table (per_bfd->all_comp_units.size ());
 
@@ -2971,7 +2726,7 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
 
   gdb_assert (! this_cu->is_debug_types);
 
-  this_cu->v.quick->files_read = true;
+  this_cu->files_read = true;
   /* Our callers never want to match partial units -- instead they
      will match the enclosing full CU.  */
   if (comp_unit_die->tag == DW_TAG_partial_unit)
@@ -2998,7 +2753,7 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
                             &find_entry, INSERT);
       if (*slot != NULL)
        {
-         lh_cu->v.quick->file_names = (struct quick_file_names *) *slot;
+         lh_cu->file_names = (struct quick_file_names *) *slot;
          return;
        }
 
@@ -3008,7 +2763,7 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
   file_and_directory &fnd = find_file_and_directory (comp_unit_die, cu);
 
   int offset = 0;
-  if (fnd.is_unknown ())
+  if (!fnd.is_unknown ())
     ++offset;
   else if (lh == nullptr)
     return;
@@ -3025,9 +2780,9 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
     {
       for (const auto &entry : lh->file_names ())
        {
-         gdb::unique_xmalloc_ptr<char> name_holder;
+         std::string name_holder;
          const char *include_name =
-           compute_include_file_name (lh.get (), entry, fnd, &name_holder);
+           compute_include_file_name (lh.get (), entry, fnd, name_holder);
          if (include_name != nullptr)
            {
              include_name = per_objfile->objfile->intern (include_name);
@@ -3050,7 +2805,7 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
 
   qfn->real_names = NULL;
 
-  lh_cu->v.quick->file_names = qfn;
+  lh_cu->file_names = qfn;
 }
 
 /* A helper for the "quick" functions which attempts to read the line
@@ -3062,17 +2817,15 @@ dw2_get_file_names (dwarf2_per_cu_data *this_cu,
 {
   /* This should never be called for TUs.  */
   gdb_assert (! this_cu->is_debug_types);
-  /* Nor type unit groups.  */
-  gdb_assert (! this_cu->type_unit_group_p ());
 
-  if (this_cu->v.quick->files_read)
-    return this_cu->v.quick->file_names;
+  if (this_cu->files_read)
+    return this_cu->file_names;
 
   cutu_reader reader (this_cu, per_objfile);
   if (!reader.dummy_p)
     dw2_get_file_names_reader (&reader, reader.comp_unit_die);
 
-  return this_cu->v.quick->file_names;
+  return this_cu->file_names;
 }
 
 /* A helper for the "quick" functions which computes and caches the
@@ -3113,7 +2866,7 @@ dwarf2_base_index_functions::find_last_source_symtab (struct objfile *objfile)
   if (cust == NULL)
     return NULL;
 
-  return compunit_primary_filetab (cust);
+  return cust->primary_filetab ();
 }
 
 /* See read.h.  */
@@ -3121,10 +2874,13 @@ dwarf2_base_index_functions::find_last_source_symtab (struct objfile *objfile)
 void
 dwarf2_per_cu_data::free_cached_file_names ()
 {
-  if (per_bfd == nullptr || !per_bfd->using_index || v.quick == nullptr)
+  if (fnd != nullptr)
+    fnd->forget_fullname ();
+
+  if (per_bfd == nullptr)
     return;
 
-  struct quick_file_names *file_data = v.quick->file_names;
+  struct quick_file_names *file_data = file_names;
   if (file_data != nullptr && file_data->real_names != nullptr)
     {
       for (int i = 0; i < file_data->num_file_names; ++i)
@@ -3176,7 +2932,8 @@ 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)
+                     domain_enum domain, offset_type namei,
+                     mapped_index &index)
 {
   iter->per_objfile = per_objfile;
   iter->block_index = block_index;
@@ -3186,22 +2943,18 @@ dw2_symtab_iter_init (struct dw2_symtab_iterator *iter,
   iter->vec = {};
   iter->length = 0;
 
-  mapped_index *index = per_objfile->per_bfd->index_table.get ();
-  /* index is NULL if OBJF_READNOW.  */
-  if (index == NULL)
-    return;
-
-  gdb_assert (!index->symbol_name_slot_invalid (namei));
-  offset_type vec_idx = index->symbol_vec_index (namei);
+  gdb_assert (!index.symbol_name_slot_invalid (namei));
+  offset_type vec_idx = index.symbol_vec_index (namei);
 
-  iter->vec = offset_view (index->constant_pool.slice (vec_idx));
+  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.  */
 
 static struct dwarf2_per_cu_data *
-dw2_symtab_iter_next (struct dw2_symtab_iterator *iter)
+dw2_symtab_iter_next (struct dw2_symtab_iterator *iter,
+                     mapped_index &index)
 {
   dwarf2_per_objfile *per_objfile = iter->per_objfile;
 
@@ -3215,9 +2968,8 @@ dw2_symtab_iter_next (struct dw2_symtab_iterator *iter)
         Indices prior to version 7 don't record them,
         and indices >= 7 may elide them for certain symbols
         (gold does this).  */
-      int attrs_valid =
-       (per_objfile->per_bfd->index_table->version >= 7
-        && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
+      int attrs_valid = (index.version >= 7
+                        && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
 
       /* Don't crash on bad data.  */
       if (cu_index >= per_objfile->per_bfd->all_comp_units.size ())
@@ -3311,8 +3063,8 @@ dwarf2_base_index_functions::print_stats (struct objfile *objfile,
       if (!per_objfile->symtab_set_p (per_cu))
        ++count;
     }
-  printf_filtered (_("  Number of read CUs: %d\n"), total - count);
-  printf_filtered (_("  Number of unread CUs: %d\n"), count);
+  gdb_printf (_("  Number of read CUs: %d\n"), total - count);
+  gdb_printf (_("  Number of unread CUs: %d\n"), count);
 }
 
 /* This dumps minimal information about the index.
@@ -3325,16 +3077,10 @@ dwarf2_gdb_index::dump (struct objfile *objfile)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
-  gdb_assert (per_objfile->per_bfd->using_index);
-  printf_filtered (".gdb_index:");
-  if (per_objfile->per_bfd->index_table != NULL)
-    {
-      printf_filtered (" version %d\n",
-                      per_objfile->per_bfd->index_table->version);
-    }
-  else
-    printf_filtered (" faked for \"readnow\"\n");
-  printf_filtered ("\n");
+  mapped_index *index = (static_cast<mapped_index *>
+                        (per_objfile->per_bfd->index_table.get ()));
+  gdb_printf (".gdb_index: version %d\n", index->version);
+  gdb_printf ("\n");
 }
 
 void
@@ -3383,37 +3129,31 @@ dwarf2_gdb_index::expand_matching_symbols
 
   const block_enum block_kind = global ? GLOBAL_BLOCK : STATIC_BLOCK;
 
-  if (per_objfile->per_bfd->index_table != nullptr)
-    {
-      mapped_index &index = *per_objfile->per_bfd->index_table;
+  mapped_index &index
+    = (static_cast<mapped_index &>
+       (*per_objfile->per_bfd->index_table.get ()));
 
-      const char *match_name = name.ada ().lookup_name ().c_str ();
-      auto matcher = [&] (const char *symname)
-       {
-         if (ordered_compare == nullptr)
-           return true;
-         return ordered_compare (symname, match_name) == 0;
-       };
+  const char *match_name = name.ada ().lookup_name ().c_str ();
+  auto matcher = [&] (const char *symname)
+  {
+    if (ordered_compare == nullptr)
+      return true;
+    return ordered_compare (symname, match_name) == 0;
+  };
 
-      dw2_expand_symtabs_matching_symbol (index, name, matcher,
-                                         [&] (offset_type namei)
-      {
-       struct dw2_symtab_iterator iter;
-       struct dwarf2_per_cu_data *per_cu;
-
-       dw2_symtab_iter_init (&iter, per_objfile, block_kind, domain,
-                             namei);
-       while ((per_cu = dw2_symtab_iter_next (&iter)) != NULL)
-         dw2_expand_symtabs_matching_one (per_cu, per_objfile, nullptr,
-                                          nullptr);
-       return true;
-      }, per_objfile);
-    }
-  else
+  dw2_expand_symtabs_matching_symbol (index, name, matcher,
+                                     [&] (offset_type namei)
     {
-      /* We have -readnow: no .gdb_index, but no partial symtabs either.  So,
-        proceed assuming all symtabs have been read in.  */
-    }
+      struct dw2_symtab_iterator iter;
+      struct dwarf2_per_cu_data *per_cu;
+
+      dw2_symtab_iter_init (&iter, per_objfile, block_kind, domain, namei,
+                           index);
+      while ((per_cu = dw2_symtab_iter_next (&iter, index)) != NULL)
+       dw2_expand_symtabs_matching_one (per_cu, per_objfile, nullptr,
+                                        nullptr);
+      return true;
+    }, per_objfile);
 }
 
 /* Starting from a search name, return the string that finds the upper
@@ -3782,6 +3522,11 @@ public:
     return m_symbol_table[idx];
   }
 
+  quick_symbol_functions_up make_quick_functions () const override
+  {
+    return nullptr;
+  }
+
 private:
   gdb::array_view<const char *> m_symbol_table;
 };
@@ -4197,7 +3942,7 @@ dw2_expand_symtabs_matching_one
    gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
    gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify)
 {
-  if (file_matcher == NULL || per_cu->v.quick->mark)
+  if (file_matcher == NULL || per_cu->mark)
     {
       bool symtab_was_null = !per_objfile->symtab_set_p (per_cu);
 
@@ -4225,7 +3970,9 @@ dw2_expand_marked_cus
 {
   offset_type vec_len, vec_idx;
   bool global_seen = false;
-  mapped_index &index = *per_objfile->per_bfd->index_table;
+  mapped_index &index
+    = (static_cast<mapped_index &>
+       (*per_objfile->per_bfd->index_table.get ()));
 
   offset_view vec (index.constant_pool.slice (index.symbol_vec_index (idx)));
   vec_len = vec[0];
@@ -4338,12 +4085,33 @@ dw_expand_symtabs_matching_file_matcher
 
       if (per_cu->is_debug_types)
        continue;
-      per_cu->v.quick->mark = 0;
+      per_cu->mark = 0;
 
       /* We only need to look at symtabs not already expanded.  */
       if (per_objfile->symtab_set_p (per_cu.get ()))
        continue;
 
+      if (per_cu->fnd != nullptr)
+       {
+         file_and_directory *fnd = per_cu->fnd.get ();
+
+         if (file_matcher (fnd->get_name (), false))
+           {
+             per_cu->mark = 1;
+             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
+              || file_matcher (lbasename (fnd->get_name ()), true))
+             && file_matcher (fnd->get_fullname (), false))
+           {
+             per_cu->mark = 1;
+             continue;
+           }
+       }
+
       quick_file_names *file_data = dw2_get_file_names (per_cu.get (),
                                                        per_objfile);
       if (file_data == NULL)
@@ -4353,7 +4121,7 @@ dw_expand_symtabs_matching_file_matcher
        continue;
       else if (htab_find (visited_found.get (), file_data) != NULL)
        {
-         per_cu->v.quick->mark = 1;
+         per_cu->mark = 1;
          continue;
        }
 
@@ -4363,7 +4131,7 @@ dw_expand_symtabs_matching_file_matcher
 
          if (file_matcher (file_data->file_names[j], false))
            {
-             per_cu->v.quick->mark = 1;
+             per_cu->mark = 1;
              break;
            }
 
@@ -4377,12 +4145,12 @@ dw_expand_symtabs_matching_file_matcher
          this_real_name = dw2_get_real_path (per_objfile, file_data, j);
          if (file_matcher (this_real_name, false))
            {
-             per_cu->v.quick->mark = 1;
+             per_cu->mark = 1;
              break;
            }
        }
 
-      void **slot = htab_find_slot (per_cu->v.quick->mark
+      void **slot = htab_find_slot (per_cu->mark
                                    ? visited_found.get ()
                                    : visited_not_found.get (),
                                    file_data, INSERT);
@@ -4403,10 +4171,6 @@ dwarf2_gdb_index::expand_symtabs_matching
 {
   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 true;
-
   dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
 
   /* This invariant is documented in quick-functions.h.  */
@@ -4426,7 +4190,9 @@ dwarf2_gdb_index::expand_symtabs_matching
       return true;
     }
 
-  mapped_index &index = *per_objfile->per_bfd->index_table;
+  mapped_index &index
+    = (static_cast<mapped_index &>
+       (*per_objfile->per_bfd->index_table.get ()));
 
   bool result
     = dw2_expand_symtabs_matching_symbol (index, *lookup_name,
@@ -4451,8 +4217,8 @@ recursively_find_pc_sect_compunit_symtab (struct compunit_symtab *cust,
 {
   int i;
 
-  if (COMPUNIT_BLOCKVECTOR (cust) != NULL
-      && blockvector_contains_pc (COMPUNIT_BLOCKVECTOR (cust), pc))
+  if (cust->blockvector () != nullptr
+      && blockvector_contains_pc (cust->blockvector (), pc))
     return cust;
 
   if (cust->includes == NULL)
@@ -4526,8 +4292,8 @@ dwarf2_base_index_functions::map_symbol_filenames
       if (!per_cu->is_debug_types
          && per_objfile->symtab_set_p (per_cu.get ()))
        {
-         if (per_cu->v.quick->file_names != nullptr)
-           qfn_cache.insert (per_cu->v.quick->file_names);
+         if (per_cu->file_names != nullptr)
+           qfn_cache.insert (per_cu->file_names);
        }
     }
 
@@ -4538,6 +4304,24 @@ dwarf2_base_index_functions::map_symbol_filenames
       if (per_cu->is_debug_types || per_objfile->symtab_set_p (per_cu))
        continue;
 
+      if (per_cu->fnd != nullptr)
+       {
+         file_and_directory *fnd = per_cu->fnd.get ();
+
+         const char *filename = fnd->get_name ();
+         const char *key = filename;
+         const char *fullname = nullptr;
+
+         if (need_fullname)
+           {
+             fullname = fnd->get_fullname ();
+             key = fullname;
+           }
+
+         if (!filenames_cache.seen (key))
+           fun (filename, fullname);
+       }
+
       quick_file_names *file_data = dw2_get_file_names (per_cu, per_objfile);
       if (file_data == nullptr
          || qfn_cache.find (file_data) != qfn_cache.end ())
@@ -4906,8 +4690,7 @@ dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
 
   create_addrmap_from_aranges (per_objfile, &per_bfd->debug_aranges);
 
-  per_bfd->debug_names_table = std::move (map);
-  per_bfd->using_index = 1;
+  per_bfd->index_table = std::move (map);
   per_bfd->quick_file_names_table =
     create_quick_file_names_table (per_bfd->all_comp_units.size ());
 
@@ -5331,15 +5114,7 @@ dw2_debug_names_iterator::next ()
 void
 dwarf2_debug_names_index::dump (struct objfile *objfile)
 {
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
-  gdb_assert (per_objfile->per_bfd->using_index);
-  printf_filtered (".debug_names:");
-  if (per_objfile->per_bfd->debug_names_table)
-    printf_filtered (" exists\n");
-  else
-    printf_filtered (" faked for \"readnow\"\n");
-  printf_filtered ("\n");
+  gdb_printf (".debug_names: exists\n");
 }
 
 void
@@ -5351,11 +5126,9 @@ dwarf2_debug_names_index::expand_matching_symbols
 {
   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;
-
-  mapped_debug_names &map = *per_objfile->per_bfd->debug_names_table;
+  mapped_debug_names &map
+    = (static_cast<mapped_debug_names &>
+       (*per_objfile->per_bfd->index_table.get ()));
   const block_search_flags block_flags
     = global ? SEARCH_GLOBAL_BLOCK : SEARCH_STATIC_BLOCK;
 
@@ -5396,10 +5169,6 @@ dwarf2_debug_names_index::expand_symtabs_matching
 {
   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 true;
-
   dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
 
   /* This invariant is documented in quick-functions.h.  */
@@ -5419,7 +5188,9 @@ dwarf2_debug_names_index::expand_symtabs_matching
       return true;
     }
 
-  mapped_debug_names &map = *per_objfile->per_bfd->debug_names_table;
+  mapped_debug_names &map
+    = (static_cast<mapped_debug_names &>
+       (*per_objfile->per_bfd->index_table.get ()));
 
   bool result
     = dw2_expand_symtabs_matching_symbol (map, *lookup_name,
@@ -5496,6 +5267,8 @@ 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);
 }
 
+static quick_symbol_functions_up make_cooked_index_funcs ();
+
 /* See dwarf2/public.h.  */
 
 void
@@ -5514,41 +5287,11 @@ dwarf2_initialize_objfile (struct objfile *objfile)
     {
       dwarf_read_debug_printf ("readnow requested");
 
-      /* When using READNOW, the using_index flag (set below) indicates that
-        PER_BFD was already initialized, when we loaded some other objfile.  */
-      if (per_bfd->using_index)
-       {
-         dwarf_read_debug_printf ("using_index already set");
-         objfile->qf.push_front (make_dwarf_gdb_index ());
-         return;
-       }
-
-      per_bfd->using_index = 1;
       create_all_comp_units (per_objfile);
       per_bfd->quick_file_names_table
        = create_quick_file_names_table (per_bfd->all_comp_units.size ());
 
-      for (int i = 0; i < per_bfd->all_comp_units.size (); ++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);
-       }
-
-      /* 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
-     PER_BFD?  */
-  if (per_bfd->debug_names_table != nullptr)
-    {
-      dwarf_read_debug_printf ("re-using shared debug names table");
-      objfile->qf.push_front (make_dwarf_debug_names ());
+      objfile->qf.emplace_front (new readnow_functions);
       return;
     }
 
@@ -5556,27 +5299,16 @@ dwarf2_initialize_objfile (struct objfile *objfile)
      PER_BFD?  */
   if (per_bfd->index_table != nullptr)
     {
-      dwarf_read_debug_printf ("re-using shared index table");
-      objfile->qf.push_front (make_dwarf_gdb_index ());
-      return;
-    }
-
-  /* There might already be partial symtabs built for this BFD.  This happens
-     when loading the same binary twice with the index-cache enabled.  If so,
-     don't try to read an index.  The objfile / per_objfile initialization will
-     be completed in dwarf2_build_psymtabs, in the standard partial symtabs
-     code path.  */
-  if (per_bfd->partial_symtabs != nullptr)
-    {
-      dwarf_read_debug_printf ("re-using shared partial symtabs");
-      objfile->qf.push_front (make_lazy_dwarf_reader ());
+      dwarf_read_debug_printf ("re-using symbols");
+      objfile->qf.push_front (per_bfd->index_table->make_quick_functions ());
       return;
     }
 
   if (dwarf2_read_debug_names (per_objfile))
     {
       dwarf_read_debug_printf ("found debug names");
-      objfile->qf.push_front (make_dwarf_debug_names ());
+      objfile->qf.push_front
+       (per_bfd->index_table->make_quick_functions ());
       return;
     }
 
@@ -5585,7 +5317,7 @@ dwarf2_initialize_objfile (struct objfile *objfile)
                             get_gdb_index_contents_from_section<dwz_file>))
     {
       dwarf_read_debug_printf ("found gdb index from file");
-      objfile->qf.push_front (make_dwarf_gdb_index ());
+      objfile->qf.push_front (per_bfd->index_table->make_quick_functions ());
       return;
     }
 
@@ -5596,12 +5328,12 @@ dwarf2_initialize_objfile (struct objfile *objfile)
     {
       dwarf_read_debug_printf ("found gdb index from cache");
       global_index_cache.hit ();
-      objfile->qf.push_front (make_dwarf_gdb_index ());
+      objfile->qf.push_front (per_bfd->index_table->make_quick_functions ());
       return;
     }
 
   global_index_cache.miss ();
-  objfile->qf.push_front (make_lazy_dwarf_reader ());
+  objfile->qf.push_front (make_cooked_index_funcs ());
 }
 
 \f
@@ -5609,47 +5341,21 @@ dwarf2_initialize_objfile (struct objfile *objfile)
 /* Build a partial symbol table.  */
 
 void
-dwarf2_build_psymtabs (struct objfile *objfile, psymbol_functions *psf)
+dwarf2_build_psymtabs (struct objfile *objfile, bool already_attached)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
-
-  if (per_bfd->partial_symtabs != nullptr)
-    {
-      /* Partial symbols were already read, so now we can simply
-        attach them.  */
-      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);
-      return;
-    }
 
-  if (psf == nullptr)
+  if (already_attached)
     {
-      psf = new psymbol_functions;
-      objfile->qf.emplace_front (psf);
+      if (per_objfile->per_bfd->index_table != nullptr)
+       return;
     }
-  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;
+  else
+    objfile->qf.push_front (make_cooked_index_funcs ());
 
   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 (partial_symtabs.get ());
       dwarf2_build_psymtabs_hard (per_objfile);
-      psymtabs.keep ();
 
       /* (maybe) store an index in the cache.  */
       global_index_cache.store (per_objfile);
@@ -5730,111 +5436,6 @@ read_abbrev_offset (dwarf2_per_objfile *per_objfile,
   return (sect_offset) read_offset (abfd, info_ptr, offset_size);
 }
 
-/* A partial symtab that is used only for include files.  */
-struct dwarf2_include_psymtab : public partial_symtab
-{
-  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)
-  {
-  }
-
-  void read_symtab (struct objfile *objfile) override
-  {
-    /* It's an include file, no symbols to read for it.
-       Everything is in the includer symtab.  */
-
-    /* The expansion of a dwarf2_include_psymtab is just a trigger for
-       expansion of the includer psymtab.  We use the dependencies[0] field to
-       model the includer.  But if we go the regular route of calling
-       expand_psymtab here, and having expand_psymtab call expand_dependencies
-       to expand the includer, we'll only use expand_psymtab on the includer
-       (making it a non-toplevel psymtab), while if we expand the includer via
-       another path, we'll use read_symtab (making it a toplevel psymtab).
-       So, don't pretend a dwarf2_include_psymtab is an actual toplevel
-       psymtab, and trigger read_symtab on the includer here directly.  */
-    includer ()->read_symtab (objfile);
-  }
-
-  void expand_psymtab (struct objfile *objfile) override
-  {
-    /* This is not called by read_symtab, and should not be called by any
-       expand_dependencies.  */
-    gdb_assert (false);
-  }
-
-  bool readin_p (struct objfile *objfile) const override
-  {
-    return includer ()->readin_p (objfile);
-  }
-
-  compunit_symtab *get_compunit_symtab (struct objfile *objfile) const override
-  {
-    compunit_symtab *cust = includer ()->get_compunit_symtab (objfile);
-    while (cust != nullptr && cust->user != nullptr)
-      cust = cust->user;
-    return cust;
-  }
-
-private:
-  partial_symtab *includer () const
-  {
-    /* An include psymtab has exactly one dependency: the psymtab that
-       includes it.  */
-    gdb_assert (this->number_of_dependencies == 1);
-    return this->dependencies[0];
-  }
-};
-
-/* Allocate a new partial symtab for file named NAME and mark this new
-   partial symtab as being an include of PST.  */
-
-static void
-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, partial_symtabs, objfile_per_bfd);
-
-  if (!IS_ABSOLUTE_PATH (subpst->filename))
-    subpst->dirname = pst->dirname;
-
-  subpst->dependencies = per_bfd->partial_symtabs->allocate_dependencies (1);
-  subpst->dependencies[0] = pst;
-  subpst->number_of_dependencies = 1;
-}
-
-/* Read the Line Number Program data and extract the list of files
-   included by the source file represented by PST.  Build an include
-   partial symtab for each of these included files.  */
-
-static void
-dwarf2_build_include_psymtabs (struct dwarf2_cu *cu,
-                              struct die_info *die,
-                              const file_and_directory &fnd,
-                              dwarf2_psymtab *pst)
-{
-  line_header_up lh;
-  struct attribute *attr;
-
-  attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
-  if (attr != nullptr && attr->form_is_unsigned ())
-    lh = dwarf_decode_line_header ((sect_offset) attr->as_unsigned (), cu);
-  if (lh == NULL)
-    return;  /* No linetable, so no includes.  */
-
-  /* NOTE: pst->dirname is DW_AT_comp_dir (if present).  Also note
-     that we pass in the raw text_low here; that is ok because we're
-     only decoding the line table to make include partial symtabs, and
-     so the addresses aren't really used.  */
-  dwarf_decode_lines (lh.get (), fnd, cu, pst,
-                     pst->raw_text_low (), 1);
-}
-
 static hashval_t
 hash_signatured_type (const void *item)
 {
@@ -5998,12 +5599,6 @@ add_type_unit (dwarf2_per_objfile *per_objfile, ULONGEST sig, void **slot)
 
   per_objfile->per_bfd->all_comp_units.emplace_back
     (sig_type_holder.release ());
-  if (per_objfile->per_bfd->using_index)
-    {
-      sig_type->v.quick =
-       OBSTACK_ZALLOC (&per_objfile->per_bfd->obstack,
-                       struct dwarf2_per_cu_quick_data);
-    }
 
   if (slot == NULL)
     {
@@ -6029,17 +5624,14 @@ fill_in_sig_entry_from_dwo_entry (dwarf2_per_objfile *per_objfile,
   /* Make sure we're not clobbering something we don't expect to.  */
   gdb_assert (! sig_entry->queued);
   gdb_assert (per_objfile->get_cu (sig_entry) == NULL);
-  if (per_bfd->using_index)
-    {
-      gdb_assert (sig_entry->v.quick != NULL);
-      gdb_assert (!per_objfile->symtab_set_p (sig_entry));
-    }
-  else
-      gdb_assert (sig_entry->v.psymtab == NULL);
+  gdb_assert (!per_objfile->symtab_set_p (sig_entry));
   gdb_assert (sig_entry->signature == dwo_entry->signature);
-  gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0);
+  gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0
+             || (to_underlying (sig_entry->type_offset_in_section)
+                 == to_underlying (dwo_entry->type_offset_in_tu)));
   gdb_assert (sig_entry->type_unit_group == NULL);
-  gdb_assert (sig_entry->dwo_unit == NULL);
+  gdb_assert (sig_entry->dwo_unit == NULL
+             || sig_entry->dwo_unit == dwo_entry);
 
   sig_entry->section = dwo_entry->section;
   sig_entry->sect_off = dwo_entry->sect_off;
@@ -6070,7 +5662,7 @@ lookup_dwo_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
   struct dwo_unit find_dwo_entry, *dwo_entry;
   void **slot;
 
-  gdb_assert (cu->dwo_unit && per_objfile->per_bfd->using_index);
+  gdb_assert (cu->dwo_unit);
 
   /* If TU skeletons have been removed then we may not have read in any
      TUs yet.  */
@@ -6117,7 +5709,8 @@ lookup_dwo_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
   if (sig_entry == NULL)
     sig_entry = add_type_unit (per_objfile, sig, slot);
 
-  fill_in_sig_entry_from_dwo_entry (per_objfile, sig_entry, dwo_entry);
+  if (sig_entry->dwo_unit == nullptr)
+    fill_in_sig_entry_from_dwo_entry (per_objfile, sig_entry, dwo_entry);
   sig_entry->tu_read = 1;
   return sig_entry;
 }
@@ -6135,7 +5728,7 @@ lookup_dwp_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
   struct dwo_unit *dwo_entry;
   void **slot;
 
-  gdb_assert (cu->dwo_unit && per_objfile->per_bfd->using_index);
+  gdb_assert (cu->dwo_unit);
   gdb_assert (dwp_file != NULL);
 
   /* If TU skeletons have been removed then we may not have read in any
@@ -6176,7 +5769,7 @@ lookup_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
 {
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
 
-  if (cu->dwo_unit && per_objfile->per_bfd->using_index)
+  if (cu->dwo_unit)
     {
       /* We're in a DWO/DWP file, and we're using .gdb_index.
         These cases require special processing.  */
@@ -6390,11 +5983,11 @@ read_cutu_die_from_dwo (dwarf2_cu *cu,
 
   if (dwarf_die_debug)
     {
-      fprintf_unfiltered (gdb_stdlog,
-                         "Read die from %s@0x%x of %s:\n",
-                         section->get_name (),
-                         (unsigned) (begin_info_ptr - section->buffer),
-                         bfd_get_filename (abfd));
+      gdb_printf (gdb_stdlog,
+                 "Read die from %s@0x%x of %s:\n",
+                 section->get_name (),
+                 (unsigned) (begin_info_ptr - section->buffer),
+                 bfd_get_filename (abfd));
       dump_die (comp_unit_die, dwarf_die_debug);
     }
 
@@ -6429,6 +6022,14 @@ lookup_dwo_id (struct dwarf2_cu *cu, struct die_info* comp_unit_die)
 static struct dwo_unit *
 lookup_dwo_unit (dwarf2_cu *cu, die_info *comp_unit_die, const char *dwo_name)
 {
+#if CXX_STD_THREAD
+  /* We need a lock here both to handle the DWO hash table, and BFD,
+     which is not thread-safe.  */
+  static std::mutex dwo_lock;
+
+  std::lock_guard<std::mutex> guard (dwo_lock);
+#endif
+
   dwarf2_per_cu_data *per_cu = cu->per_cu;
   struct dwo_unit *dwo_unit;
   const char *comp_dir;
@@ -6521,7 +6122,8 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
                          dwarf2_per_objfile *per_objfile,
                          struct abbrev_table *abbrev_table,
                          dwarf2_cu *existing_cu,
-                         bool skip_partial)
+                         bool skip_partial,
+                         abbrev_cache *cache)
   : die_reader_specs {},
     m_this_cu (this_cu)
 {
@@ -6537,9 +6139,9 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
   int rereading_dwo_cu = 0;
 
   if (dwarf_die_debug)
-    fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset %s\n",
-                       this_cu->is_debug_types ? "type" : "comp",
-                       sect_offset_str (this_cu->sect_off));
+    gdb_printf (gdb_stdlog, "Reading %s unit at offset %s\n",
+               this_cu->is_debug_types ? "type" : "comp",
+               sect_offset_str (this_cu->sect_off));
 
   /* If we're reading a TU directly from a DWO file, including a virtual DWO
      file (instead of going through the stub), short-circuit all of this.  */
@@ -6575,9 +6177,14 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
     }
   else
     {
-      /* If an existing_cu is provided, a dwarf2_cu must not exist for this_cu
-        in per_objfile yet.  */
-      gdb_assert (per_objfile->get_cu (this_cu) == nullptr);
+      /* If an existing_cu is provided, a dwarf2_cu must not exist for
+        this_cu in per_objfile yet.  Here, CACHE doubles as a flag to
+        let us know that the CU is being scanned using the parallel
+        indexer.  This assert is avoided in this case because (1) it
+        is irrelevant, and (2) the get_cu method is not
+        thread-safe.  */
+      gdb_assert (cache != nullptr
+                 || per_objfile->get_cu (this_cu) == nullptr);
       m_new_cu.reset (new dwarf2_cu (this_cu, per_objfile));
       cu = m_new_cu.get ();
     }
@@ -6645,10 +6252,16 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
     gdb_assert (cu->header.abbrev_sect_off == abbrev_table->sect_off);
   else
     {
-      abbrev_section->read (objfile);
-      m_abbrev_table_holder
-       = abbrev_table::read (abbrev_section, cu->header.abbrev_sect_off);
-      abbrev_table = m_abbrev_table_holder.get ();
+      if (cache != nullptr)
+       abbrev_table = cache->find (abbrev_section,
+                                   cu->header.abbrev_sect_off);
+      if (abbrev_table == nullptr)
+       {
+         abbrev_section->read (objfile);
+         m_abbrev_table_holder
+           = abbrev_table::read (abbrev_section, cu->header.abbrev_sect_off);
+         abbrev_table = m_abbrev_table_holder.get ();
+       }
     }
 
   /* Read the top level CU/TU die.  */
@@ -6752,9 +6365,9 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
   const gdb_byte *begin_info_ptr, *info_ptr;
 
   if (dwarf_die_debug)
-    fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset %s\n",
-                       this_cu->is_debug_types ? "type" : "comp",
-                       sect_offset_str (this_cu->sect_off));
+    gdb_printf (gdb_stdlog, "Reading %s unit at offset %s\n",
+               this_cu->is_debug_types ? "type" : "comp",
+               sect_offset_str (this_cu->sect_off));
 
   gdb_assert (per_objfile->get_cu (this_cu) == nullptr);
 
@@ -6849,34 +6462,7 @@ allocate_type_unit_groups_table ()
 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;
-
   std::unique_ptr<type_unit_group> tu_group (new type_unit_group);
-  tu_group->per_bfd = per_bfd;
-
-  if (per_bfd->using_index)
-    {
-      tu_group->v.quick = OBSTACK_ZALLOC (&per_bfd->obstack,
-                                         struct dwarf2_per_cu_quick_data);
-    }
-  else
-    {
-      unsigned int line_offset = to_underlying (line_offset_struct);
-      dwarf2_psymtab *pst;
-      std::string name;
-
-      /* Give the symtab a useful name for debug purposes.  */
-      if ((line_offset & NO_STMT_LIST_TYPE_UNIT_PSYMTAB) != 0)
-       name = string_printf ("<type_units_%d>",
-                             (line_offset & ~NO_STMT_LIST_TYPE_UNIT_PSYMTAB));
-      else
-       name = string_printf ("<type_units_at_0x%x>", line_offset);
-
-      pst = create_partial_symtab (tu_group.get (), per_objfile,
-                                  name.c_str ());
-      pst->anonymous = true;
-    }
 
   tu_group->hash.dwo_unit = cu->dwo_unit;
   tu_group->hash.line_sect_off = line_offset_struct;
@@ -6938,162 +6524,235 @@ get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list)
   return tu_group;
 }
 \f
-/* Partial symbol tables.  */
-
-/* Create a psymtab named NAME and assign it to PER_CU.
 
-   The caller must fill in the following details:
-   dirname, textlow, texthigh.  */
+/* An instance of this is created when scanning DWARF to create a
+   cooked index.  */
 
-static dwarf2_psymtab *
-create_partial_symtab (dwarf2_per_cu_data *per_cu,
-                      dwarf2_per_objfile *per_objfile,
-                      const char *name)
+class cooked_index_storage
 {
-  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;
-
-  /* This is the glue that links PST into GDB's symbol API.  */
-  per_cu->v.psymtab = pst;
-
-  return pst;
-}
+public:
 
-/* DIE reader function for process_psymtab_comp_unit.  */
+  cooked_index_storage ()
+    : m_reader_hash (htab_create_alloc (10, hash_cutu_reader,
+                                       eq_cutu_reader,
+                                       htab_delete_entry<cutu_reader>,
+                                       xcalloc, xfree)),
+      m_index (new cooked_index),
+      m_addrmap_storage (),
+      m_addrmap (addrmap_create_mutable (&m_addrmap_storage))
+  {
+  }
 
-static void
-process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
-                                 const gdb_byte *info_ptr,
-                                 struct die_info *comp_unit_die,
-                                 enum language pretend_language)
-{
-  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;
-  CORE_ADDR baseaddr;
-  CORE_ADDR best_lowpc = 0, best_highpc = 0;
-  dwarf2_psymtab *pst;
-  enum pc_bounds_kind cu_bounds_kind;
+  DISABLE_COPY_AND_ASSIGN (cooked_index_storage);
 
-  gdb_assert (! per_cu->is_debug_types);
+  /* Return the current abbrev cache.  */
+  abbrev_cache *get_abbrev_cache ()
+  {
+    return &m_abbrev_cache;
+  }
 
-  prepare_one_comp_unit (cu, comp_unit_die, pretend_language);
+  /* Return the DIE reader corresponding to PER_CU.  If no such reader
+     has been registered, return NULL.  */
+  cutu_reader *get_reader (dwarf2_per_cu_data *per_cu)
+  {
+    int index = per_cu->index;
+    return (cutu_reader *) htab_find_with_hash (m_reader_hash.get (),
+                                               &index, index);
+  }
 
-  /* Allocate a new partial symbol table structure.  */
-  gdb::unique_xmalloc_ptr<char> debug_filename;
-  static const char artificial[] = "<artificial>";
-  file_and_directory &fnd = find_file_and_directory (comp_unit_die, cu);
-  if (strcmp (fnd.get_name (), artificial) == 0)
-    {
-      debug_filename.reset (concat (artificial, "@",
-                                   sect_offset_str (per_cu->sect_off),
-                                   (char *) NULL));
-      fnd.set_name (debug_filename.get ());
-    }
+  /* Preserve READER by storing it in the local hash table.  */
+  cutu_reader *preserve (std::unique_ptr<cutu_reader> reader)
+  {
+    m_abbrev_cache.add (reader->release_abbrev_table ());
+
+    int index = reader->cu->per_cu->index;
+    void **slot = htab_find_slot_with_hash (m_reader_hash.get (), &index,
+                                           index, INSERT);
+    gdb_assert (*slot == nullptr);
+    cutu_reader *result = reader.get ();
+    *slot = reader.release ();
+    return result;
+  }
 
-  pst = create_partial_symtab (per_cu, per_objfile, fnd.get_name ());
+  /* Add an entry to the index.  The arguments describe the entry; see
+     cooked-index.h.  The new entry is returned.  */
+  const cooked_index_entry *add (sect_offset die_offset, enum dwarf_tag tag,
+                                cooked_index_flag flags,
+                                const char *name,
+                                const cooked_index_entry *parent_entry,
+                                dwarf2_per_cu_data *per_cu)
+  {
+    return m_index->add (die_offset, tag, flags, name, parent_entry, per_cu);
+  }
 
-  /* This must be done before calling dwarf2_build_include_psymtabs.  */
-  pst->dirname = dwarf2_string_attr (comp_unit_die, DW_AT_comp_dir, cu);
+  /* Install the current addrmap into the index being constructed,
+     then transfer ownership of the index to the caller.  */
+  std::unique_ptr<cooked_index> release ()
+  {
+    m_index->install_addrmap (m_addrmap);
+    return std::move (m_index);
+  }
 
-  baseaddr = objfile->text_section_offset ();
+  /* Return the mutable addrmap that is currently being created.  */
+  addrmap *get_addrmap ()
+  {
+    return m_addrmap;
+  }
 
-  dwarf2_find_base_address (comp_unit_die, cu);
+private:
 
-  /* Possibly set the default values of LOWPC and HIGHPC from
-     `DW_AT_ranges'.  */
-  cu_bounds_kind = dwarf2_get_pc_bounds (comp_unit_die, &best_lowpc,
-                                        &best_highpc, cu, pst);
-  if (cu_bounds_kind == PC_BOUNDS_HIGH_LOW && best_lowpc < best_highpc)
-    {
-      CORE_ADDR low
-       = (gdbarch_adjust_dwarf2_addr (gdbarch, best_lowpc + baseaddr)
-          - baseaddr);
-      CORE_ADDR high
-       = (gdbarch_adjust_dwarf2_addr (gdbarch, best_highpc + baseaddr)
-          - baseaddr - 1);
-      /* Store the contiguous range if it is not empty; it can be
-        empty for CUs with no code.  */
-      addrmap_set_empty (per_bfd->partial_symtabs->psymtabs_addrmap,
-                        low, high, pst);
-    }
+  /* Hash function for a cutu_reader.  */
+  static hashval_t hash_cutu_reader (const void *a)
+  {
+    const cutu_reader *reader = (const cutu_reader *) a;
+    return reader->cu->per_cu->index;
+  }
 
-  /* Check if comp unit has_children.
-     If so, read the rest of the partial symbols from this comp unit.
-     If not, there's no more debug_info for this comp unit.  */
-  if (comp_unit_die->has_children)
-    {
-      struct partial_die_info *first_die;
-      CORE_ADDR lowpc, highpc;
+  /* Equality function for cutu_reader.  */
+  static int eq_cutu_reader (const void *a, const void *b)
+  {
+    const cutu_reader *ra = (const cutu_reader *) a;
+    const int *rb = (const int *) b;
+    return ra->cu->per_cu->index == *rb;
+  }
 
-      lowpc = ((CORE_ADDR) -1);
-      highpc = ((CORE_ADDR) 0);
+  /* The abbrev cache used by this indexer.  */
+  abbrev_cache m_abbrev_cache;
+  /* A hash table of cutu_reader objects.  */
+  htab_up m_reader_hash;
+  /* The index that is being constructed.  */
+  std::unique_ptr<cooked_index> m_index;
+
+  /* Storage for the writeable addrmap.  */
+  auto_obstack m_addrmap_storage;
+  /* A writeable addrmap being constructed by this scanner.  */
+  addrmap *m_addrmap;
+};
 
-      first_die = load_partial_dies (reader, info_ptr, 1);
+/* An instance of this is created to index a CU.  */
 
-      scan_partial_symbols (first_die, &lowpc, &highpc,
-                           cu_bounds_kind <= PC_BOUNDS_INVALID, cu);
+class cooked_indexer
+{
+public:
 
-      /* If we didn't find a lowpc, set it to highpc to avoid
-        complaints from `maint check'.  */
-      if (lowpc == ((CORE_ADDR) -1))
-       lowpc = highpc;
+  cooked_indexer (cooked_index_storage *storage,
+                 dwarf2_per_cu_data *per_cu,
+                 enum language language)
+    : m_index_storage (storage),
+      m_per_cu (per_cu),
+      m_language (language),
+      m_obstack (),
+      m_die_range_map (addrmap_create_mutable (&m_obstack))
+  {
+  }
 
-      /* If the compilation unit didn't have an explicit address range,
-        then use the information extracted from its child dies.  */
-      if (cu_bounds_kind <= PC_BOUNDS_INVALID)
-       {
-         best_lowpc = lowpc;
-         best_highpc = highpc;
-       }
-    }
-  pst->set_text_low (gdbarch_adjust_dwarf2_addr (gdbarch,
-                                                best_lowpc + baseaddr)
-                    - baseaddr);
-  pst->set_text_high (gdbarch_adjust_dwarf2_addr (gdbarch,
-                                                 best_highpc + baseaddr)
-                     - baseaddr);
+  DISABLE_COPY_AND_ASSIGN (cooked_indexer);
 
-  pst->end ();
+  /* Index the given CU.  */
+  void make_index (cutu_reader *reader);
 
-  if (!cu->per_cu->imported_symtabs_empty ())
-    {
-      int i;
-      int len = cu->per_cu->imported_symtabs_size ();
+private:
 
-      /* Fill in 'dependencies' here; we fill in 'users' in a
-        post-pass.  */
-      pst->number_of_dependencies = len;
-      pst->dependencies
-       = per_bfd->partial_symtabs->allocate_dependencies (len);
-      for (i = 0; i < len; ++i)
-       {
-         pst->dependencies[i]
-           = cu->per_cu->imported_symtabs->at (i)->v.psymtab;
-       }
+  /* A helper function to turn a section offset into an address that
+     can be used in an addrmap.  */
+  CORE_ADDR form_addr (sect_offset offset, bool is_dwz)
+  {
+    CORE_ADDR value = to_underlying (offset);
+    if (is_dwz)
+      value |= ((CORE_ADDR) 1) << (8 * sizeof (CORE_ADDR) - 1);
+    return value;
+  }
 
-      cu->per_cu->imported_symtabs_free ();
-    }
+  /* A helper function to scan the PC bounds of READER and record them
+     in the storage's addrmap.  */
+  void check_bounds (cutu_reader *reader);
 
-  /* Get the list of files included in the current compilation unit,
-     and build a psymtab for each of them.  */
-  dwarf2_build_include_psymtabs (cu, comp_unit_die, fnd, pst);
+  /* Ensure that the indicated CU exists.  The cutu_reader for it is
+     returned.  FOR_SCANNING is true if the caller intends to scan all
+     the DIEs in the CU; when false, this use is assumed to be to look
+     up just a single DIE.  */
+  cutu_reader *ensure_cu_exists (cutu_reader *reader,
+                                dwarf2_per_objfile *per_objfile,
+                                sect_offset sect_off,
+                                bool is_dwz,
+                                bool for_scanning);
+
+  /* Index DIEs in the READER starting at INFO_PTR.  PARENT_ENTRY is
+     the entry for the enclosing scope (nullptr at top level).  FULLY
+     is true when a full scan must be done -- in some languages,
+     function scopes must be fully explored in order to find nested
+     functions.  This returns a pointer to just after the spot where
+     reading stopped.  */
+  const gdb_byte *index_dies (cutu_reader *reader,
+                             const gdb_byte *info_ptr,
+                             const cooked_index_entry *parent_entry,
+                             bool fully);
+
+  /* Scan the attributes for a given DIE and update the out
+     parameters.  Returns a pointer to the byte after the DIE.  */
+  const gdb_byte *scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
+                                  cutu_reader *reader,
+                                  const gdb_byte *watermark_ptr,
+                                  const gdb_byte *info_ptr,
+                                  const abbrev_info *abbrev,
+                                  const char **name,
+                                  const char **linkage_name,
+                                  cooked_index_flag *flags,
+                                  sect_offset *sibling_offset,
+                                  const cooked_index_entry **parent_entry,
+                                  CORE_ADDR *maybe_defer,
+                                  bool for_specification);
+
+  /* Handle DW_TAG_imported_unit, by scanning the DIE to find
+     DW_AT_import, and then scanning the referenced CU.  Returns a
+     pointer to the byte after the DIE.  */
+  const gdb_byte *index_imported_unit (cutu_reader *reader,
+                                      const gdb_byte *info_ptr,
+                                      const abbrev_info *abbrev);
+
+  /* Recursively read DIEs, recording the section offsets in
+     m_die_range_map and then calling index_dies.  */
+  const gdb_byte *recurse (cutu_reader *reader,
+                          const gdb_byte *info_ptr,
+                          const cooked_index_entry *parent_entry,
+                          bool fully);
+
+  /* The storage object, where the results are kept.  */
+  cooked_index_storage *m_index_storage;
+  /* The CU that we are reading on behalf of.  This object might be
+     asked to index one CU but to treat the results as if they come
+     from some including CU; in this case the including CU would be
+     recorded here.  */
+  dwarf2_per_cu_data *m_per_cu;
+  /* The language that we're assuming when reading.  */
+  enum language m_language;
+
+  /* Temporary storage.  */
+  auto_obstack m_obstack;
+  /* An addrmap that maps from section offsets (see the form_addr
+     method) to newly-created entries.  See m_deferred_entries to
+     understand this.  */
+  addrmap *m_die_range_map;
+
+  /* A single deferred entry.  */
+  struct deferred_entry
+  {
+    sect_offset die_offset;
+    const char *name;
+    CORE_ADDR spec_offset;
+    dwarf_tag tag;
+    cooked_index_flag flags;
+  };
 
-  dwarf_read_debug_printf ("Psymtab for %s unit @%s: %s - %s"
-                          ", %d global, %d static syms",
-                          per_cu->is_debug_types ? "type" : "comp",
-                          sect_offset_str (per_cu->sect_off),
-                          paddress (gdbarch, pst->text_low (objfile)),
-                          paddress (gdbarch, pst->text_high (objfile)),
-                          (int) pst->global_psymbols.size (),
-                          (int) pst->static_psymbols.size ());
-}
+  /* The generated DWARF can sometimes have the declaration for a
+     method in a class (or perhaps namespace) scope, with the
+     definition appearing outside this scope... just one of the many
+     bad things about DWARF.  In order to handle this situation, we
+     defer certain entries until the end of scanning, at which point
+     we'll know the containing context of all the DIEs that we might
+     have scanned.  This vector stores these deferred entries.  */
+  std::vector<deferred_entry> m_deferred_entries;
+};
 
 /* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
    Process compilation unit THIS_CU for a psymtab.  */
@@ -7101,17 +6760,10 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
 static void
 process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu,
                           dwarf2_per_objfile *per_objfile,
-                          bool want_partial_unit,
-                          enum language pretend_language)
+                          cooked_index_storage *storage)
 {
-  /* If this compilation unit was already read in, free the
-     cached copy in order to read it in again. This is
-     necessary because we skipped some symbols when we first
-     read in the compilation unit (see load_partial_dies).
-     This problem could be avoided, but the benefit is unclear.  */
-  per_objfile->remove_cu (this_cu);
-
-  cutu_reader reader (this_cu, per_objfile, nullptr, nullptr, false);
+  cutu_reader reader (this_cu, per_objfile, nullptr, nullptr, false,
+                     storage->get_abbrev_cache ());
 
   if (reader.comp_unit_die == nullptr)
     return;
@@ -7139,59 +6791,41 @@ process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu,
       /* Nothing.  */
     }
   else if (this_cu->is_debug_types)
-    build_type_psymtabs_reader (&reader, reader.info_ptr,
-                               reader.comp_unit_die);
-  else if (want_partial_unit
-          || reader.comp_unit_die->tag != DW_TAG_partial_unit)
-    process_psymtab_comp_unit_reader (&reader, reader.info_ptr,
-                                     reader.comp_unit_die,
-                                     pretend_language);
-
-  /* Age out any secondary CUs.  */
-  per_objfile->age_comp_units ();
+    build_type_psymtabs_reader (&reader, storage);
+  else if (reader.comp_unit_die->tag != DW_TAG_partial_unit)
+    {
+      bool nope = false;
+      if (this_cu->scanned.compare_exchange_strong (nope, true))
+       {
+         prepare_one_comp_unit (reader.cu, reader.comp_unit_die,
+                                language_minimal);
+         gdb_assert (storage != nullptr);
+         cooked_indexer indexer (storage, this_cu, reader.cu->per_cu->lang);
+         indexer.make_index (&reader);
+       }
+    }
 }
 
 /* Reader function for build_type_psymtabs.  */
 
 static void
-build_type_psymtabs_reader (const struct die_reader_specs *reader,
-                           const gdb_byte *info_ptr,
-                           struct die_info *type_unit_die)
+build_type_psymtabs_reader (cutu_reader *reader,
+                           cooked_index_storage *storage)
 {
-  dwarf2_per_objfile *per_objfile = reader->cu->per_objfile;
   struct dwarf2_cu *cu = reader->cu;
   struct dwarf2_per_cu_data *per_cu = cu->per_cu;
-  struct signatured_type *sig_type;
-  struct type_unit_group *tu_group;
-  struct attribute *attr;
-  struct partial_die_info *first_die;
-  CORE_ADDR lowpc, highpc;
-  dwarf2_psymtab *pst;
+  struct die_info *type_unit_die = reader->comp_unit_die;
 
   gdb_assert (per_cu->is_debug_types);
-  sig_type = (struct signatured_type *) per_cu;
 
   if (! type_unit_die->has_children)
     return;
 
-  attr = type_unit_die->attr (DW_AT_stmt_list);
-  tu_group = get_type_unit_group (cu, attr);
-
-  if (tu_group->tus == nullptr)
-    tu_group->tus = new std::vector<signatured_type *>;
-  tu_group->tus->push_back (sig_type);
-
   prepare_one_comp_unit (cu, type_unit_die, language_minimal);
-  pst = create_partial_symtab (per_cu, per_objfile, "");
-  pst->anonymous = true;
-
-  first_die = load_partial_dies (reader, info_ptr, 1);
 
-  lowpc = (CORE_ADDR) -1;
-  highpc = (CORE_ADDR) 0;
-  scan_partial_symbols (first_die, &lowpc, &highpc, 0, cu);
-
-  pst->end ();
+  gdb_assert (storage != nullptr);
+  cooked_indexer indexer (storage, per_cu, cu->per_cu->lang);
+  indexer.make_index (reader);
 }
 
 /* Struct used to sort TUs by their abbreviation table offset.  */
@@ -7230,7 +6864,8 @@ struct tu_abbrev_offset
    dwarf2_per_objfile->per_bfd->type_unit_groups.  */
 
 static void
-build_type_psymtabs (dwarf2_per_objfile *per_objfile)
+build_type_psymtabs (dwarf2_per_objfile *per_objfile,
+                    cooked_index_storage *storage)
 {
   struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
   abbrev_table_up abbrev_table;
@@ -7299,8 +6934,7 @@ build_type_psymtabs (dwarf2_per_objfile *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,
-                                   reader.comp_unit_die);
+       build_type_psymtabs_reader (&reader, storage);
     }
 }
 
@@ -7325,36 +6959,11 @@ print_tu_stats (dwarf2_per_objfile *per_objfile)
                           tu_stats->nr_all_type_units_reallocs);
 }
 
-/* Traversal function for build_type_psymtabs.  */
-
-static int
-build_type_psymtab_dependencies (void **slot, void *info)
+struct skeleton_data
 {
-  dwarf2_per_objfile *per_objfile = (dwarf2_per_objfile *) info;
-  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
-  struct type_unit_group *tu_group = (struct type_unit_group *) *slot;
-  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 (tu_group->type_unit_group_p ());
-
-  pst->number_of_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->is_debug_types);
-      pst->dependencies[i] = iter->v.psymtab;
-      iter->type_unit_group = tu_group;
-    }
-
-  delete tu_group->tus;
-  tu_group->tus = nullptr;
-
-  return 1;
-}
+  dwarf2_per_objfile *per_objfile;
+  cooked_index_storage *storage;
+};
 
 /* Traversal function for process_skeletonless_type_unit.
    Read a TU in a DWO file and build partial symbols for it.  */
@@ -7363,15 +6972,16 @@ static int
 process_skeletonless_type_unit (void **slot, void *info)
 {
   struct dwo_unit *dwo_unit = (struct dwo_unit *) *slot;
-  dwarf2_per_objfile *per_objfile = (dwarf2_per_objfile *) info;
+  skeleton_data *data = (skeleton_data *) info;
 
   /* If this TU doesn't exist in the global table, add it and read it in.  */
 
-  if (per_objfile->per_bfd->signatured_types == NULL)
-    per_objfile->per_bfd->signatured_types = allocate_signatured_type_table ();
+  if (data->per_objfile->per_bfd->signatured_types == NULL)
+    data->per_objfile->per_bfd->signatured_types
+      = allocate_signatured_type_table ();
 
   signatured_type find_entry (dwo_unit->signature);
-  slot = htab_find_slot (per_objfile->per_bfd->signatured_types.get (),
+  slot = htab_find_slot (data->per_objfile->per_bfd->signatured_types.get (),
                         &find_entry, INSERT);
   /* If we've already seen this type there's nothing to do.  What's happening
      is we're doing our own version of comdat-folding here.  */
@@ -7381,15 +6991,14 @@ process_skeletonless_type_unit (void **slot, void *info)
   /* This does the job that create_all_comp_units would have done for
      this TU.  */
   signatured_type *entry
-    = add_type_unit (per_objfile, dwo_unit->signature, slot);
-  fill_in_sig_entry_from_dwo_entry (per_objfile, entry, dwo_unit);
+    = add_type_unit (data->per_objfile, dwo_unit->signature, slot);
+  fill_in_sig_entry_from_dwo_entry (data->per_objfile, entry, dwo_unit);
   *slot = entry;
 
   /* This does the job that build_type_psymtabs would have done.  */
-  cutu_reader reader (entry, per_objfile, nullptr, nullptr, false);
+  cutu_reader reader (entry, data->per_objfile, nullptr, nullptr, false);
   if (!reader.dummy_p)
-    build_type_psymtabs_reader (&reader, reader.info_ptr,
-                               reader.comp_unit_die);
+    build_type_psymtabs_reader (&reader, data->storage);
 
   return 1;
 }
@@ -7413,36 +7022,18 @@ process_dwo_file_for_skeletonless_type_units (void **slot, void *info)
    Note: This can't be done until we know what all the DWO files are.  */
 
 static void
-process_skeletonless_type_units (dwarf2_per_objfile *per_objfile)
+process_skeletonless_type_units (dwarf2_per_objfile *per_objfile,
+                                cooked_index_storage *storage)
 {
+  skeleton_data data { per_objfile, storage };
+
   /* Skeletonless TUs in DWP files without .gdb_index is not supported yet.  */
   if (get_dwp_file (per_objfile) == NULL
       && per_objfile->per_bfd->dwo_files != NULL)
     {
       htab_traverse_noresize (per_objfile->per_bfd->dwo_files.get (),
                              process_dwo_file_for_skeletonless_type_units,
-                             per_objfile);
-    }
-}
-
-/* Compute the 'user' field for each psymtab in DWARF2_PER_OBJFILE.  */
-
-static void
-set_partial_user (dwarf2_per_objfile *per_objfile)
-{
-  for (const auto &per_cu : per_objfile->per_bfd->all_comp_units)
-    {
-      dwarf2_psymtab *pst = per_cu->v.psymtab;
-
-      if (pst == NULL)
-       continue;
-
-      for (int j = 0; j < pst->number_of_dependencies; ++j)
-       {
-         /* Set the 'user' field only if it is not already set.  */
-         if (pst->dependencies[j]->user == NULL)
-           pst->dependencies[j]->user = pst;
-       }
+                             &data);
     }
 }
 
@@ -7458,85 +7049,97 @@ dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile)
   dwarf_read_debug_printf ("Building psymtabs of objfile %s ...",
                           objfile_name (objfile));
 
-  scoped_restore restore_reading_psyms
-    = make_scoped_restore (&per_bfd->reading_partial_symbols, true);
-
-  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);
+  per_bfd->map_info_sections (objfile);
 
+  cooked_index_storage index_storage;
   create_all_comp_units (per_objfile);
-  build_type_psymtabs (per_objfile);
+  build_type_psymtabs (per_objfile, &index_storage);
+  std::vector<std::unique_ptr<cooked_index>> indexes;
 
-  /* Create a temporary address map on a temporary obstack.  We later
-     copy this to the final obstack.  */
-  auto_obstack temp_obstack;
+  per_bfd->quick_file_names_table
+    = create_quick_file_names_table (per_bfd->all_comp_units.size ());
+  if (!per_bfd->debug_aranges.empty ())
+    read_addrmap_from_aranges (per_objfile, &per_bfd->debug_aranges,
+                              index_storage.get_addrmap ());
 
-  scoped_restore save_psymtabs_addrmap
-    = make_scoped_restore (&per_bfd->partial_symtabs->psymtabs_addrmap,
-                          addrmap_create_mutable (&temp_obstack));
+  {
+    /* Ensure that complaints are handled correctly.  */
+    complaint_interceptor complaint_handler;
+
+    using iter_type = decltype (per_bfd->all_comp_units.begin ());
+
+    /* Each thread returns a pair holding a cooked index, and a vector
+       of errors that should be printed.  The latter is done because
+       GDB's I/O system is not thread-safe.  run_on_main_thread could be
+       used, but that would mean the messages are printed after the
+       prompt, which looks weird.  */
+    using result_type = std::pair<std::unique_ptr<cooked_index>,
+                                 std::vector<gdb_exception>>;
+    std::vector<result_type> results
+      = gdb::parallel_for_each (1, per_bfd->all_comp_units.begin (),
+                               per_bfd->all_comp_units.end (),
+                               [=] (iter_type iter, iter_type end)
+      {
+       std::vector<gdb_exception> errors;
+       cooked_index_storage thread_storage;
+       for (; iter != end; ++iter)
+         {
+           dwarf2_per_cu_data *per_cu = iter->get ();
+           try
+             {
+               process_psymtab_comp_unit (per_cu, per_objfile,
+                                          &thread_storage);
+             }
+           catch (gdb_exception &except)
+             {
+               errors.push_back (std::move (except));
+             }
+         }
+       return result_type (thread_storage.release (), std::move (errors));
+      });
 
-  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.get (), per_objfile, false,
-                                language_minimal);
-    }
+    /* Only show a given exception a single time.  */
+    std::unordered_set<gdb_exception> seen_exceptions;
+    for (auto &one_result : results)
+      {
+       indexes.push_back (std::move (one_result.first));
+       for (auto &one_exc : one_result.second)
+         if (seen_exceptions.insert (one_exc).second)
+           exception_print (gdb_stderr, one_exc);
+      }
+  }
 
   /* This has to wait until we read the CUs, we need the list of DWOs.  */
-  process_skeletonless_type_units (per_objfile);
-
-  /* Now that all TUs have been processed we can fill in the dependencies.  */
-  if (per_bfd->type_unit_groups != NULL)
-    {
-      htab_traverse_noresize (per_bfd->type_unit_groups.get (),
-                             build_type_psymtab_dependencies, per_objfile);
-    }
+  process_skeletonless_type_units (per_objfile, &index_storage);
 
   if (dwarf_read_debug > 0)
     print_tu_stats (per_objfile);
 
-  set_partial_user (per_objfile);
-
-  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 ();
+  indexes.push_back (index_storage.release ());
+  /* Remove any NULL entries.  This might happen if parallel-for
+     decides to throttle the number of threads that were used.  */
+  indexes.erase
+    (std::remove_if (indexes.begin (),
+                    indexes.end (),
+                    [] (const std::unique_ptr<cooked_index> &entry)
+                    {
+                      return entry == nullptr;
+                    }),
+     indexes.end ());
+  indexes.shrink_to_fit ();
+
+  cooked_index_vector *vec = new cooked_index_vector (std::move (indexes));
+  per_bfd->index_table.reset (vec);
+
+  const cooked_index_entry *main_entry = vec->get_main ();
+  if (main_entry != nullptr)
+    set_objfile_main_name (objfile, main_entry->name,
+                          main_entry->per_cu->lang);
 
   dwarf_read_debug_printf ("Done building psymtabs of %s",
                           objfile_name (objfile));
 }
 
-/* Load the partial DIEs for a secondary CU into memory.
-   This is also used when rereading a primary CU with load_all_dies.  */
-
-static void
-load_partial_comp_unit (dwarf2_per_cu_data *this_cu,
-                       dwarf2_per_objfile *per_objfile,
-                       dwarf2_cu *existing_cu)
-{
-  cutu_reader reader (this_cu, per_objfile, nullptr, existing_cu, false);
-
-  if (!reader.dummy_p)
-    {
-      prepare_one_comp_unit (reader.cu, reader.comp_unit_die,
-                            language_minimal);
-
-      /* Check if comp unit has_children.
-        If so, read the rest of the partial symbols from this comp unit.
-        If not, there's no more debug_info for this comp unit.  */
-      if (reader.comp_unit_die->has_children)
-       load_partial_dies (&reader, reader.info_ptr, 0);
-
-      reader.keep ();
-    }
-}
-
 static void
 read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
                              struct dwarf2_section_info *section,
@@ -7619,630 +7222,18 @@ create_all_comp_units (dwarf2_per_objfile *per_objfile)
 
   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,
-                                 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
-   FIRST_DIE.  The caller should pass SET_ADDRMAP == 1 if the compilation
-   unit DIE did not have PC info (DW_AT_low_pc and DW_AT_high_pc, or
-   DW_AT_ranges).  See the comments of add_partial_subprogram on how
-   SET_ADDRMAP is used and how *LOWPC and *HIGHPC are updated.  */
-
-static void
-scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
-                     CORE_ADDR *highpc, int set_addrmap,
-                     struct dwarf2_cu *cu)
-{
-  struct partial_die_info *pdi;
-
-  /* Now, march along the PDI's, descending into ones which have
-     interesting children but skipping the children of the other ones,
-     until we reach the end of the compilation unit.  */
-
-  pdi = first_die;
-
-  while (pdi != NULL)
-    {
-      pdi->fixup (cu);
-
-      /* Anonymous namespaces or modules have no name but have interesting
-        children, so we need to look at them.  Ditto for anonymous
-        enums.  */
-
-      if (pdi->raw_name != NULL || pdi->tag == DW_TAG_namespace
-         || pdi->tag == DW_TAG_module || pdi->tag == DW_TAG_enumeration_type
-         || pdi->tag == DW_TAG_imported_unit
-         || pdi->tag == DW_TAG_inlined_subroutine)
-       {
-         switch (pdi->tag)
-           {
-           case DW_TAG_subprogram:
-           case DW_TAG_inlined_subroutine:
-             add_partial_subprogram (pdi, lowpc, highpc, set_addrmap, cu);
-             if (cu->per_cu->lang == language_cplus)
-               scan_partial_symbols (pdi->die_child, lowpc, highpc,
-                                     set_addrmap, cu);
-             break;
-           case DW_TAG_constant:
-           case DW_TAG_variable:
-           case DW_TAG_typedef:
-           case DW_TAG_union_type:
-             if (!pdi->is_declaration
-                 || (pdi->tag == DW_TAG_variable && pdi->is_external))
-               {
-                 add_partial_symbol (pdi, cu);
-               }
-             break;
-           case DW_TAG_class_type:
-           case DW_TAG_interface_type:
-           case DW_TAG_structure_type:
-             if (!pdi->is_declaration)
-               {
-                 add_partial_symbol (pdi, cu);
-               }
-             if ((cu->per_cu->lang == language_rust
-                  || cu->per_cu->lang == language_cplus)
-                 && pdi->has_children)
-               scan_partial_symbols (pdi->die_child, lowpc, highpc,
-                                     set_addrmap, cu);
-             break;
-           case DW_TAG_enumeration_type:
-             if (!pdi->is_declaration)
-               add_partial_enumeration (pdi, cu);
-             break;
-           case DW_TAG_base_type:
-           case DW_TAG_subrange_type:
-             /* File scope base type definitions are added to the partial
-                symbol table.  */
-             add_partial_symbol (pdi, cu);
-             break;
-           case DW_TAG_namespace:
-             add_partial_namespace (pdi, lowpc, highpc, set_addrmap, cu);
-             break;
-           case DW_TAG_module:
-             if (!pdi->is_declaration)
-               add_partial_module (pdi, lowpc, highpc, set_addrmap, cu);
-             break;
-           case DW_TAG_imported_unit:
-             {
-               struct dwarf2_per_cu_data *per_cu;
-
-               /* For now we don't handle imported units in type units.  */
-               if (cu->per_cu->is_debug_types)
-                 {
-                   error (_("Dwarf Error: DW_TAG_imported_unit is not"
-                            " supported in type units [in module %s]"),
-                          objfile_name (cu->per_objfile->objfile));
-                 }
-
-               per_cu = dwarf2_find_containing_comp_unit
-                          (pdi->d.sect_off, pdi->is_dwz,
-                           cu->per_objfile->per_bfd);
-
-               /* Go read the partial unit, if needed.  */
-               if (per_cu->v.psymtab == NULL)
-                 process_psymtab_comp_unit (per_cu, cu->per_objfile, true,
-                                            cu->per_cu->lang);
-
-               if (pdi->die_parent == nullptr
-                   && per_cu->unit_type == DW_UT_compile
-                   && per_cu->lang == language_cplus)
-                 /* Regard import as hint.  See corresponding code in
-                    process_imported_unit_die.  */
-                 break;
-
-               cu->per_cu->imported_symtabs_push (per_cu);
-             }
-             break;
-           case DW_TAG_imported_declaration:
-             add_partial_symbol (pdi, cu);
-             break;
-           default:
-             break;
-           }
-       }
-
-      /* If the die has a sibling, skip to the sibling.  */
-
-      pdi = pdi->die_sibling;
-    }
-}
-
-/* Functions used to compute the fully scoped name of a partial DIE.
-
-   Normally, this is simple.  For C++, the parent DIE's fully scoped
-   name is concatenated with "::" and the partial DIE's name.
-   Enumerators are an exception; they use the scope of their parent
-   enumeration type, i.e. the name of the enumeration type is not
-   prepended to the enumerator.
-
-   There are two complexities.  One is DW_AT_specification; in this
-   case "parent" means the parent of the target of the specification,
-   instead of the direct parent of the DIE.  The other is compilers
-   which do not emit DW_TAG_namespace; in this case we try to guess
-   the fully qualified name of structure types from their members'
-   linkage names.  This must be done using the DIE's children rather
-   than the children of any DW_AT_specification target.  We only need
-   to do this for structures at the top level, i.e. if the target of
-   any DW_AT_specification (if any; otherwise the DIE itself) does not
-   have a parent.  */
-
-/* Compute the scope prefix associated with PDI's parent, in
-   compilation unit CU.  The result will be allocated on CU's
-   comp_unit_obstack, or a copy of the already allocated PDI->NAME
-   field.  NULL is returned if no prefix is necessary.  */
-static const char *
-partial_die_parent_scope (struct partial_die_info *pdi,
-                         struct dwarf2_cu *cu)
-{
-  const char *grandparent_scope;
-  struct partial_die_info *parent, *real_pdi;
-
-  /* We need to look at our parent DIE; if we have a DW_AT_specification,
-     then this means the parent of the specification DIE.  */
-
-  real_pdi = pdi;
-  while (real_pdi->has_specification)
-    {
-      auto res = find_partial_die (real_pdi->spec_offset,
-                                  real_pdi->spec_is_dwz, cu);
-      real_pdi = res.pdi;
-      cu = res.cu;
-    }
-
-  parent = real_pdi->die_parent;
-  if (parent == NULL)
-    return NULL;
-
-  if (parent->scope_set)
-    return parent->scope;
-
-  parent->fixup (cu);
-
-  grandparent_scope = partial_die_parent_scope (parent, cu);
-
-  /* GCC 4.0 and 4.1 had a bug (PR c++/28460) where they generated bogus
-     DW_TAG_namespace DIEs with a name of "::" for the global namespace.
-     Work around this problem here.  */
-  if (cu->per_cu->lang == language_cplus
-      && parent->tag == DW_TAG_namespace
-      && strcmp (parent->name (cu), "::") == 0
-      && grandparent_scope == NULL)
-    {
-      parent->scope = NULL;
-      parent->scope_set = 1;
-      return NULL;
-    }
-
-  /* Nested subroutines in Fortran get a prefix.  */
-  if (pdi->tag == DW_TAG_enumerator)
-    /* Enumerators should not get the name of the enumeration as a prefix.  */
-    parent->scope = grandparent_scope;
-  else if (parent->tag == DW_TAG_namespace
-      || parent->tag == DW_TAG_module
-      || parent->tag == DW_TAG_structure_type
-      || parent->tag == DW_TAG_class_type
-      || parent->tag == DW_TAG_interface_type
-      || parent->tag == DW_TAG_union_type
-      || parent->tag == DW_TAG_enumeration_type
-      || (cu->per_cu->lang == language_fortran
-         && parent->tag == DW_TAG_subprogram
-         && pdi->tag == DW_TAG_subprogram))
-    {
-      if (grandparent_scope == NULL)
-       parent->scope = parent->name (cu);
-      else
-       parent->scope = typename_concat (&cu->comp_unit_obstack,
-                                        grandparent_scope,
-                                        parent->name (cu), 0, cu);
-    }
-  else
-    {
-      /* FIXME drow/2004-04-01: What should we be doing with
-        function-local names?  For partial symbols, we should probably be
-        ignoring them.  */
-      complaint (_("unhandled containing DIE tag %s for DIE at %s"),
-                dwarf_tag_name (parent->tag),
-                sect_offset_str (pdi->sect_off));
-      parent->scope = grandparent_scope;
-    }
-
-  parent->scope_set = 1;
-  return parent->scope;
-}
-
-/* Return the fully scoped name associated with PDI, from compilation unit
-   CU.  The result will be allocated with malloc.  */
-
-static gdb::unique_xmalloc_ptr<char>
-partial_die_full_name (struct partial_die_info *pdi,
-                      struct dwarf2_cu *cu)
-{
-  const char *parent_scope;
-
-  /* If this is a template instantiation, we can not work out the
-     template arguments from partial DIEs.  So, unfortunately, we have
-     to go through the full DIEs.  At least any work we do building
-     types here will be reused if full symbols are loaded later.  */
-  if (pdi->has_template_arguments)
-    {
-      pdi->fixup (cu);
-
-      if (pdi->name (cu) != NULL && strchr (pdi->name (cu), '<') == NULL)
-       {
-         struct die_info *die;
-         struct attribute attr;
-         struct dwarf2_cu *ref_cu = cu;
-
-         /* DW_FORM_ref_addr is using section offset.  */
-         attr.name = (enum dwarf_attribute) 0;
-         attr.form = DW_FORM_ref_addr;
-         attr.u.unsnd = to_underlying (pdi->sect_off);
-         die = follow_die_ref (NULL, &attr, &ref_cu);
-
-         return make_unique_xstrdup (dwarf2_full_name (NULL, die, ref_cu));
-       }
-    }
-
-  parent_scope = partial_die_parent_scope (pdi, cu);
-  if (parent_scope == NULL)
-    return NULL;
-  else
-    return gdb::unique_xmalloc_ptr<char> (typename_concat (NULL, parent_scope,
-                                                          pdi->name (cu),
-                                                          0, cu));
-}
-
-static void
-add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
-{
-  dwarf2_per_objfile *per_objfile = cu->per_objfile;
-  struct objfile *objfile = per_objfile->objfile;
-  struct gdbarch *gdbarch = objfile->arch ();
-  CORE_ADDR addr = 0;
-  const char *actual_name = NULL;
-  CORE_ADDR baseaddr;
-
-  baseaddr = objfile->text_section_offset ();
-
-  gdb::unique_xmalloc_ptr<char> built_actual_name
-    = partial_die_full_name (pdi, cu);
-  if (built_actual_name != NULL)
-    actual_name = built_actual_name.get ();
-
-  if (actual_name == NULL)
-    actual_name = pdi->name (cu);
-
-  partial_symbol psymbol;
-  memset (&psymbol, 0, sizeof (psymbol));
-  psymbol.ginfo.set_language (cu->per_cu->lang,
-                             &objfile->objfile_obstack);
-  psymbol.ginfo.set_section_index (-1);
-
-  /* The code below indicates that the psymbol should be installed by
-     setting this.  */
-  gdb::optional<psymbol_placement> where;
-
-  switch (pdi->tag)
-    {
-    case DW_TAG_inlined_subroutine:
-    case DW_TAG_subprogram:
-      addr = (gdbarch_adjust_dwarf2_addr (gdbarch, pdi->lowpc + baseaddr)
-             - baseaddr);
-      if (pdi->is_external
-         || cu->per_cu->lang == language_ada
-         || (cu->per_cu->lang == language_fortran
-             && pdi->die_parent != NULL
-             && pdi->die_parent->tag == DW_TAG_subprogram))
-       {
-         /* Normally, only "external" DIEs are part of the global scope.
-            But in Ada and Fortran, we want to be able to access nested
-            procedures globally.  So all Ada and Fortran subprograms are
-            stored in the global scope.  */
-         where = psymbol_placement::GLOBAL;
-       }
-      else
-       where = psymbol_placement::STATIC;
-
-      psymbol.domain = VAR_DOMAIN;
-      psymbol.aclass = LOC_BLOCK;
-      psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
-      psymbol.ginfo.value.address = addr;
-
-      if (pdi->main_subprogram && actual_name != NULL)
-       set_objfile_main_name (objfile, actual_name, cu->per_cu->lang);
-      break;
-    case DW_TAG_constant:
-      psymbol.domain = VAR_DOMAIN;
-      psymbol.aclass = LOC_STATIC;
-      where = (pdi->is_external
-              ? psymbol_placement::GLOBAL
-              : psymbol_placement::STATIC);
-      break;
-    case DW_TAG_variable:
-      if (pdi->d.locdesc)
-       addr = decode_locdesc (pdi->d.locdesc, cu);
-
-      if (pdi->d.locdesc
-         && addr == 0
-         && !per_objfile->per_bfd->has_section_at_zero)
-       {
-         /* A global or static variable may also have been stripped
-            out by the linker if unused, in which case its address
-            will be nullified; do not add such variables into partial
-            symbol table then.  */
-       }
-      else if (pdi->is_external)
-       {
-         /* Global Variable.
-            Don't enter into the minimal symbol tables as there is
-            a minimal symbol table entry from the ELF symbols already.
-            Enter into partial symbol table if it has a location
-            descriptor or a type.
-            If the location descriptor is missing, new_symbol will create
-            a LOC_UNRESOLVED symbol, the address of the variable will then
-            be determined from the minimal symbol table whenever the variable
-            is referenced.
-            The address for the partial symbol table entry is not
-            used by GDB, but it comes in handy for debugging partial symbol
-            table building.  */
-
-         if (pdi->d.locdesc || pdi->has_type)
-           {
-             psymbol.domain = VAR_DOMAIN;
-             psymbol.aclass = LOC_STATIC;
-             psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
-             psymbol.ginfo.value.address = addr;
-             where = psymbol_placement::GLOBAL;
-           }
-       }
-      else
-       {
-         int has_loc = pdi->d.locdesc != NULL;
-
-         /* Static Variable.  Skip symbols whose value we cannot know (those
-            without location descriptors or constant values).  */
-         if (!has_loc && !pdi->has_const_value)
-           return;
-
-         psymbol.domain = VAR_DOMAIN;
-         psymbol.aclass = LOC_STATIC;
-         psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
-         if (has_loc)
-           psymbol.ginfo.value.address = addr;
-         where = psymbol_placement::STATIC;
-       }
-      break;
-    case DW_TAG_array_type:
-    case DW_TAG_typedef:
-    case DW_TAG_base_type:
-    case DW_TAG_subrange_type:
-      psymbol.domain = VAR_DOMAIN;
-      psymbol.aclass = LOC_TYPEDEF;
-      where = psymbol_placement::STATIC;
-      break;
-    case DW_TAG_imported_declaration:
-    case DW_TAG_namespace:
-      psymbol.domain = VAR_DOMAIN;
-      psymbol.aclass = LOC_TYPEDEF;
-      where = psymbol_placement::GLOBAL;
-      break;
-    case DW_TAG_module:
-      /* With Fortran 77 there might be a "BLOCK DATA" module
-        available without any name.  If so, we skip the module as it
-        doesn't bring any value.  */
-      if (actual_name != nullptr)
-       {
-         psymbol.domain = MODULE_DOMAIN;
-         psymbol.aclass = LOC_TYPEDEF;
-         where = psymbol_placement::GLOBAL;
-       }
-      break;
-    case DW_TAG_class_type:
-    case DW_TAG_interface_type:
-    case DW_TAG_structure_type:
-    case DW_TAG_union_type:
-    case DW_TAG_enumeration_type:
-      /* Skip external references.  The DWARF standard says in the section
-        about "Structure, Union, and Class Type Entries": "An incomplete
-        structure, union or class type is represented by a structure,
-        union or class entry that does not have a byte size attribute
-        and that has a DW_AT_declaration attribute."  */
-      if (!pdi->has_byte_size && pdi->is_declaration)
-       return;
-
-      /* NOTE: carlton/2003-10-07: See comment in new_symbol about
-        static vs. global.  */
-      psymbol.domain = STRUCT_DOMAIN;
-      psymbol.aclass = LOC_TYPEDEF;
-      where = (cu->per_cu->lang == language_cplus
-              ? psymbol_placement::GLOBAL
-              : psymbol_placement::STATIC);
-      break;
-    case DW_TAG_enumerator:
-      psymbol.domain = VAR_DOMAIN;
-      psymbol.aclass = LOC_CONST;
-      where = (cu->per_cu->lang == language_cplus
-              ? psymbol_placement::GLOBAL
-              : psymbol_placement::STATIC);
-      break;
-    default:
-      break;
-    }
-
-  if (where.has_value ())
-    {
-      if (built_actual_name != nullptr)
-       actual_name = objfile->intern (actual_name);
-      if (pdi->linkage_name == nullptr
-         || cu->per_cu->lang == language_ada)
-       psymbol.ginfo.set_linkage_name (actual_name);
-      else
-       {
-         psymbol.ginfo.set_demangled_name (actual_name,
-                                           &objfile->objfile_obstack);
-         psymbol.ginfo.set_linkage_name (pdi->linkage_name);
-       }
-      cu->per_cu->v.psymtab->add_psymbol
-       (psymbol, *where, per_objfile->per_bfd->partial_symtabs.get (),
-        objfile);
-    }
-}
-
-/* Read a partial die corresponding to a namespace; also, add a symbol
-   corresponding to that namespace to the symbol table.  NAMESPACE is
-   the name of the enclosing namespace.  */
-
-static void
-add_partial_namespace (struct partial_die_info *pdi,
-                      CORE_ADDR *lowpc, CORE_ADDR *highpc,
-                      int set_addrmap, struct dwarf2_cu *cu)
-{
-  /* Add a symbol for the namespace.  */
-
-  add_partial_symbol (pdi, cu);
-
-  /* Now scan partial symbols in that namespace.  */
-
-  if (pdi->has_children)
-    scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu);
-}
-
-/* Read a partial die corresponding to a Fortran module.  */
-
-static void
-add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
-                   CORE_ADDR *highpc, int set_addrmap, struct dwarf2_cu *cu)
-{
-  /* Add a symbol for the namespace.  */
-
-  add_partial_symbol (pdi, cu);
-
-  /* Now scan partial symbols in that module.  */
-
-  if (pdi->has_children)
-    scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu);
-}
-
-static int
-dwarf2_ranges_read (unsigned, CORE_ADDR *, CORE_ADDR *, struct dwarf2_cu *,
-                   dwarf2_psymtab *, dwarf_tag);
-
-/* Read a partial die corresponding to a subprogram or an inlined
-   subprogram and create a partial symbol for that subprogram.
-   When the CU language allows it, this routine also defines a partial
-   symbol for each nested subprogram that this subprogram contains.
-   If SET_ADDRMAP is true, record the covered ranges in the addrmap.
-   Set *LOWPC and *HIGHPC to the lowest and highest PC values found in PDI.
-
-   PDI may also be a lexical block, in which case we simply search
-   recursively for subprograms defined inside that lexical block.
-   Again, this is only performed when the CU language allows this
-   type of definitions.  */
-
-static void
-add_partial_subprogram (struct partial_die_info *pdi,
-                       CORE_ADDR *lowpc, CORE_ADDR *highpc,
-                       int set_addrmap, struct dwarf2_cu *cu)
-{
-  if (pdi->tag == DW_TAG_subprogram || pdi->tag == DW_TAG_inlined_subroutine)
-    {
-      if (pdi->has_pc_info)
-       {
-         if (pdi->lowpc < *lowpc)
-           *lowpc = pdi->lowpc;
-         if (pdi->highpc > *highpc)
-           *highpc = pdi->highpc;
-         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;
-             CORE_ADDR this_lowpc;
-
-             baseaddr = objfile->text_section_offset ();
-             this_lowpc
-               = (gdbarch_adjust_dwarf2_addr (gdbarch,
-                                              pdi->lowpc + baseaddr)
-                  - baseaddr);
-             this_highpc
-               = (gdbarch_adjust_dwarf2_addr (gdbarch,
-                                              pdi->highpc + baseaddr)
-                  - baseaddr);
-             addrmap_set_empty (per_bfd->partial_symtabs->psymtabs_addrmap,
-                                this_lowpc, this_highpc - 1,
-                                cu->per_cu->v.psymtab);
-           }
-       }
-
-      if (pdi->has_range_info
-         && dwarf2_ranges_read (pdi->ranges_offset, &pdi->lowpc, &pdi->highpc,
-                                cu,
-                                set_addrmap ? cu->per_cu->v.psymtab : nullptr,
-                                pdi->tag))
-       {
-         if (pdi->lowpc < *lowpc)
-           *lowpc = pdi->lowpc;
-         if (pdi->highpc > *highpc)
-           *highpc = pdi->highpc;
-       }
-
-      if (pdi->has_pc_info || pdi->has_range_info
-         || (!pdi->is_external && pdi->may_be_inlined))
-       {
-         if (!pdi->is_declaration)
-           /* Ignore subprogram DIEs that do not have a name, they are
-              illegal.  Do not emit a complaint at this point, we will
-              do so when we convert this psymtab into a symtab.  */
-           if (pdi->name (cu))
-             add_partial_symbol (pdi, cu);
-       }
-    }
-
-  if (! pdi->has_children)
-    return;
-
-  if (cu->per_cu->lang == language_ada
-      || cu->per_cu->lang == language_fortran)
     {
-      pdi = pdi->die_child;
-      while (pdi != NULL)
-       {
-         pdi->fixup (cu);
-         if (pdi->tag == DW_TAG_subprogram
-             || pdi->tag == DW_TAG_inlined_subroutine
-             || pdi->tag == DW_TAG_lexical_block)
-           add_partial_subprogram (pdi, lowpc, highpc, set_addrmap, cu);
-         pdi = pdi->die_sibling;
-       }
+      /* Pre-read the sections we'll need to construct an index.  */
+      struct objfile *objfile = per_objfile->objfile;
+      dwz->abbrev.read (objfile);
+      dwz->info.read (objfile);
+      dwz->str.read (objfile);
+      dwz->line.read (objfile);
+      read_comp_units_from_section (per_objfile, &dwz->info, &dwz->abbrev, 1,
+                                   types_htab, rcuh_kind::COMPILE);
     }
-}
 
-/* Read a partial die corresponding to an enumeration type.  */
-
-static void
-add_partial_enumeration (struct partial_die_info *enum_pdi,
-                        struct dwarf2_cu *cu)
-{
-  struct partial_die_info *pdi;
-
-  if (enum_pdi->name (cu) != NULL)
-    add_partial_symbol (enum_pdi, cu);
-
-  pdi = enum_pdi->die_child;
-  while (pdi)
-    {
-      if (pdi->tag != DW_TAG_enumerator || pdi->raw_name == NULL)
-       complaint (_("malformed enumerator DIE ignored"));
-      else
-       add_partial_symbol (pdi, cu);
-      pdi = pdi->die_sibling;
-    }
+  per_objfile->per_bfd->signatured_types = std::move (types_htab);
 }
 
 /* Return the initial uleb128 in the die at INFO_PTR.  */
@@ -8310,12 +7301,15 @@ skip_children (const struct die_reader_specs *reader, const gdb_byte *info_ptr)
 /* Scan the debug information for CU starting at INFO_PTR in buffer BUFFER.
    INFO_PTR should point just after the initial uleb128 of a DIE, and the
    abbrev corresponding to that skipped uleb128 should be passed in
-   ABBREV.  Returns a pointer to this DIE's sibling, skipping any
-   children.  */
+   ABBREV.
+   
+   If DO_SKIP_CHILDREN is true, or if the DIE has no children, this
+   returns a pointer to this DIE's sibling, skipping any children.
+   Otherwise, returns a pointer to the DIE's first child.  */
 
 static const gdb_byte *
 skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
-             const struct abbrev_info *abbrev)
+             const struct abbrev_info *abbrev, bool do_skip_children)
 {
   unsigned int bytes_read;
   struct attribute attr;
@@ -8325,10 +7319,29 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
   const gdb_byte *buffer_end = reader->buffer_end;
   unsigned int form, i;
 
+  if (do_skip_children && abbrev->sibling_offset != (unsigned short) -1)
+    {
+      /* We only handle DW_FORM_ref4 here.  */
+      const gdb_byte *sibling_data = info_ptr + abbrev->sibling_offset;
+      unsigned int offset = read_4_bytes (abfd, sibling_data);
+      const gdb_byte *sibling_ptr
+       = buffer + to_underlying (cu->header.sect_off) + offset;
+      if (sibling_ptr >= info_ptr && sibling_ptr < reader->buffer_end)
+       return sibling_ptr;
+      /* Fall through to the slow way.  */
+    }
+  else if (abbrev->size_if_constant != 0)
+    {
+      info_ptr += abbrev->size_if_constant;
+      if (do_skip_children && abbrev->has_children)
+       return skip_children (reader, info_ptr);
+      return info_ptr;
+    }
+
   for (i = 0; i < abbrev->num_attrs; i++)
     {
       /* The only abbrev we care about is DW_AT_sibling.  */
-      if (abbrev->attrs[i].name == DW_AT_sibling)
+      if (do_skip_children && abbrev->attrs[i].name == DW_AT_sibling)
        {
          read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
          if (attr.form == DW_FORM_ref_addr)
@@ -8445,79 +7458,28 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
        }
     }
 
-  if (abbrev->has_children)
+  if (do_skip_children && abbrev->has_children)
     return skip_children (reader, info_ptr);
   else
     return info_ptr;
 }
+\f
+/* Reading in full CUs.  */
 
-/* Locate ORIG_PDI's sibling.
-   INFO_PTR should point to the start of the next DIE after ORIG_PDI.  */
+/* Add PER_CU to the queue.  */
 
-static const gdb_byte *
-locate_pdi_sibling (const struct die_reader_specs *reader,
-                   struct partial_die_info *orig_pdi,
-                   const gdb_byte *info_ptr)
+static void
+queue_comp_unit (dwarf2_per_cu_data *per_cu,
+                dwarf2_per_objfile *per_objfile,
+                enum language pretend_language)
 {
-  /* Do we know the sibling already?  */
-
-  if (orig_pdi->sibling)
-    return orig_pdi->sibling;
-
-  /* Are there any children to deal with?  */
-
-  if (!orig_pdi->has_children)
-    return info_ptr;
-
-  /* Skip the children the long way.  */
+  per_cu->queued = 1;
 
-  return skip_children (reader, info_ptr);
+  gdb_assert (per_objfile->per_bfd->queue.has_value ());
+  per_cu->per_bfd->queue->emplace (per_cu, per_objfile, pretend_language);
 }
 
-/* Expand this partial symbol table into a full symbol table.  SELF is
-   not NULL.  */
-
-void
-dwarf2_psymtab::read_symtab (struct objfile *objfile)
-{
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
-  gdb_assert (!per_objfile->symtab_set_p (per_cu_data));
-
-  /* If this psymtab is constructed from a debug-only objfile, the
-     has_section_at_zero flag will not necessarily be correct.  We
-     can get the correct value for this flag by looking at the data
-     associated with the (presumably stripped) associated objfile.  */
-  if (objfile->separate_debug_objfile_backlink)
-    {
-      dwarf2_per_objfile *per_objfile_backlink
-       = get_dwarf2_per_objfile (objfile->separate_debug_objfile_backlink);
-
-      per_objfile->per_bfd->has_section_at_zero
-       = per_objfile_backlink->per_bfd->has_section_at_zero;
-    }
-
-  expand_psymtab (objfile);
-
-  process_cu_includes (per_objfile);
-}
-\f
-/* Reading in full CUs.  */
-
-/* Add PER_CU to the queue.  */
-
-static void
-queue_comp_unit (dwarf2_per_cu_data *per_cu,
-                dwarf2_per_objfile *per_objfile,
-                enum language pretend_language)
-{
-  per_cu->queued = 1;
-
-  gdb_assert (per_objfile->per_bfd->queue.has_value ());
-  per_cu->per_bfd->queue->emplace (per_cu, per_objfile, pretend_language);
-}
-
-/* If PER_CU is not yet expanded of queued for expansion, add it to the queue.
+/* If PER_CU is not yet expanded of queued for expansion, add it to the queue.
 
    If DEPENDENT_CU is non-NULL, it has a reference to PER_CU so add a
    dependency.
@@ -8548,18 +7510,6 @@ maybe_queue_comp_unit (struct dwarf2_cu *dependent_cu,
                       dwarf2_per_objfile *per_objfile,
                       enum language pretend_language)
 {
-  /* We may arrive here during partial symbol reading, if we need full
-     DIEs to process an unusual case (e.g. template arguments).  Do
-     not queue PER_CU, just tell our caller to load its DIEs.  */
-  if (per_cu->per_bfd->reading_partial_symbols)
-    {
-      dwarf2_cu *cu = per_objfile->get_cu (per_cu);
-
-      if (cu == NULL || cu->dies == NULL)
-       return 1;
-      return 0;
-    }
-
   /* Mark the dependence relation so that we don't flush PER_CU
      too early.  */
   if (dependent_cu != NULL)
@@ -8664,39 +7614,6 @@ process_queue (dwarf2_per_objfile *per_objfile)
                           objfile_name (per_objfile->objfile));
 }
 
-/* Read in full symbols for PST, and anything it depends on.  */
-
-void
-dwarf2_psymtab::expand_psymtab (struct objfile *objfile)
-{
-  gdb_assert (!readin_p (objfile));
-
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-  free_cached_comp_units freer (per_objfile);
-  expand_dependencies (objfile);
-
-  dw2_do_instantiate_symtab (per_cu_data, per_objfile, false);
-  gdb_assert (get_compunit_symtab (objfile) != nullptr);
-}
-
-/* See psympriv.h.  */
-
-bool
-dwarf2_psymtab::readin_p (struct objfile *objfile) const
-{
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-  return per_objfile->symtab_set_p (per_cu_data);
-}
-
-/* See psympriv.h.  */
-
-compunit_symtab *
-dwarf2_psymtab::get_compunit_symtab (struct objfile *objfile) const
-{
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-  return per_objfile->get_symtab (per_cu_data);
-}
-
 /* Trivial hash function for die_info: the hash value of a DIE
    is its offset in .debug_info for this objfile.  */
 
@@ -8879,7 +7796,7 @@ fixup_go_packaging (struct dwarf2_cu *cu)
          struct symbol *sym = list->symbol[i];
 
          if (sym->language () == language_go
-             && SYMBOL_CLASS (sym) == LOC_BLOCK)
+             && sym->aclass () == LOC_BLOCK)
            {
              gdb::unique_xmalloc_ptr<char> this_package_name
                (go_symbol_package_name (sym));
@@ -8893,9 +7810,9 @@ fixup_go_packaging (struct dwarf2_cu *cu)
                  struct objfile *objfile = cu->per_objfile->objfile;
                  if (strcmp (package_name.get (), this_package_name.get ()) != 0)
                    complaint (_("Symtab %s has objects from two different Go packages: %s and %s"),
-                              (symbol_symtab (sym) != NULL
+                              (sym->symtab () != NULL
                                ? symtab_to_filename_for_display
-                                   (symbol_symtab (sym))
+                               (sym->symtab ())
                                : objfile_name (objfile)),
                               this_package_name.get (), package_name.get ());
                }
@@ -8916,9 +7833,9 @@ fixup_go_packaging (struct dwarf2_cu *cu)
       sym->compute_and_set_names (saved_package_name, false, objfile->per_bfd);
       /* This is not VAR_DOMAIN because we want a way to ensure a lookup of,
         e.g., "main" finds the "main" module and not C's main().  */
-      SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
-      SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
-      SYMBOL_TYPE (sym) = type;
+      sym->set_domain (STRUCT_DOMAIN);
+      sym->set_aclass_index (LOC_TYPEDEF);
+      sym->set_type (type);
 
       add_symbol_to_list (sym, cu->get_builder ()->get_global_symbols ());
     }
@@ -9456,7 +8373,8 @@ process_full_comp_unit (dwarf2_cu *cu, enum language pretend_language)
   get_scope_pc_bounds (cu->dies, &lowpc, &highpc, cu);
 
   addr = gdbarch_adjust_dwarf2_addr (gdbarch, highpc + baseaddr);
-  static_block = cu->get_builder ()->end_symtab_get_static_block (addr, 0, 1);
+  static_block
+    = cu->get_builder ()->end_compunit_symtab_get_static_block (addr, 0, 1);
 
   /* If the comp unit has DW_AT_ranges, it may have discontiguous ranges.
      Also, DW_AT_ranges may record ranges not belonging to any child DIEs
@@ -9465,9 +8383,8 @@ process_full_comp_unit (dwarf2_cu *cu, enum language pretend_language)
      this comp unit.  */
   dwarf2_record_block_ranges (cu->dies, static_block, baseaddr, cu);
 
-  cust = cu->get_builder ()->end_symtab_from_static_block (static_block,
-                                                   SECT_OFF_TEXT (objfile),
-                                                   0);
+  cust = cu->get_builder ()->end_compunit_symtab_from_static_block
+    (static_block, SECT_OFF_TEXT (objfile), 0);
 
   if (cust != NULL)
     {
@@ -9477,8 +8394,8 @@ process_full_comp_unit (dwarf2_cu *cu, enum language pretend_language)
         compilation is from a C file generated by language preprocessors, do
         not set the language if it was already deduced by start_subfile.  */
       if (!(cu->per_cu->lang == language_c
-           && COMPUNIT_FILETABS (cust)->language != language_unknown))
-       COMPUNIT_FILETABS (cust)->language = cu->per_cu->lang;
+           && cust->primary_filetab ()->language () != language_unknown))
+       cust->primary_filetab ()->set_language (cu->per_cu->lang);
 
       /* GCC-4.0 has started to support -fvar-tracking.  GCC-3.x still can
         produce DW_AT_location with location lists but it can be possibly
@@ -9493,10 +8410,10 @@ process_full_comp_unit (dwarf2_cu *cu, enum language pretend_language)
         options - this waits on GCC PR other/32998 (-frecord-gcc-switches).
         */
       if (cu->has_loclist && gcc_4_minor >= 5)
-       cust->locations_valid = 1;
+       cust->set_locations_valid (true);
 
       if (gcc_4_minor >= 5)
-       cust->epilogue_unwind_valid = 1;
+       cust->set_epilogue_unwind_valid (true);
 
       cust->set_call_site_htab (cu->call_site_htab);
     }
@@ -9562,8 +8479,8 @@ process_full_type_unit (dwarf2_cu *cu,
             do not set the language if it was already deduced by
             start_subfile.  */
          if (!(cu->per_cu->lang == language_c
-               && COMPUNIT_FILETABS (cust)->language != language_c))
-           COMPUNIT_FILETABS (cust)->language = cu->per_cu->lang;
+               && cust->primary_filetab ()->language () != language_c))
+           cust->primary_filetab ()->set_language (cu->per_cu->lang);
        }
     }
   else
@@ -9694,6 +8611,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
     case DW_TAG_interface_type:
     case DW_TAG_structure_type:
     case DW_TAG_union_type:
+    case DW_TAG_namelist:
       process_structure_scope (die, cu);
       break;
     case DW_TAG_enumeration_type:
@@ -9721,6 +8639,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       /* FALLTHROUGH */
     case DW_TAG_base_type:
     case DW_TAG_subrange_type:
+    case DW_TAG_generic_subrange:
     case DW_TAG_typedef:
       /* Add a typedef symbol for the type definition, if it has a
         DW_AT_name.  */
@@ -10502,7 +9421,7 @@ find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu)
 
 static void
 handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
-                       const file_and_directory &fnd, CORE_ADDR lowpc) /* ARI: editCase function */
+                       CORE_ADDR lowpc) /* ARI: editCase function */
 {
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
   struct attribute *attr;
@@ -10590,9 +9509,7 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
       gdb_assert (die->tag != DW_TAG_partial_unit);
     }
   decode_mapping = (die->tag != DW_TAG_partial_unit);
-  dwarf_decode_lines (cu->line_header, fnd, cu, nullptr, lowpc,
-                     decode_mapping);
-
+  dwarf_decode_lines (cu->line_header, cu, lowpc, decode_mapping);
 }
 
 /* Process DW_TAG_compile_unit or DW_TAG_partial_unit.  */
@@ -10622,7 +9539,8 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
 
   file_and_directory &fnd = find_file_and_directory (die, cu);
 
-  cu->start_symtab (fnd.get_name (), fnd.intern_comp_dir (objfile), lowpc);
+  cu->start_compunit_symtab (fnd.get_name (), fnd.intern_comp_dir (objfile),
+                            lowpc);
 
   gdb_assert (per_objfile->sym_cu == nullptr);
   scoped_restore restore_sym_cu
@@ -10630,8 +9548,13 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
 
   /* Decode line number information if present.  We do this before
      processing child DIEs, so that the line header table is available
-     for DW_AT_decl_file.  */
-  handle_DW_AT_stmt_list (die, cu, fnd, lowpc);
+     for DW_AT_decl_file.  The PC check is here because, if LOWPC and
+     HIGHPC are both 0x0, then there won't be any interesting code in
+     the CU, but a check later on (in
+     lnp_state_machine::check_line_address) will fail to properly
+     exclude an entry that was removed via --gc-sections.  */
+  if (lowpc != highpc)
+    handle_DW_AT_stmt_list (die, cu, lowpc);
 
   /* Process all dies in compilation unit.  */
   if (die->child != NULL)
@@ -10710,15 +9633,15 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
   if (lh == NULL)
     {
       if (first_time)
-       start_symtab ("", NULL, 0);
+       start_compunit_symtab ("", NULL, 0);
       else
        {
          gdb_assert (tug_unshare->symtabs == NULL);
          gdb_assert (m_builder == nullptr);
          struct compunit_symtab *cust = tug_unshare->compunit_symtab;
          m_builder.reset (new struct buildsym_compunit
-                          (COMPUNIT_OBJFILE (cust), "",
-                           COMPUNIT_DIRNAME (cust),
+                          (cust->objfile (), "",
+                           cust->dirname (),
                            compunit_language (cust),
                            0, cust));
          list_in_scope = get_builder ()->get_file_symbols ();
@@ -10731,7 +9654,7 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
 
   if (first_time)
     {
-      struct compunit_symtab *cust = start_symtab ("", NULL, 0);
+      struct compunit_symtab *cust = start_compunit_symtab ("", NULL, 0);
 
       /* Note: We don't assign tu_group->compunit_symtab yet because we're
         still initializing it, and our caller (a few levels up)
@@ -10739,7 +9662,7 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
         time.  */
 
       tug_unshare->symtabs
-       = XOBNEWVEC (&COMPUNIT_OBJFILE (cust)->objfile_obstack,
+       = XOBNEWVEC (&cust->objfile ()->objfile_obstack,
                     struct symtab *, line_header->file_names_size ());
 
       auto &file_names = line_header->file_names ();
@@ -10756,8 +9679,8 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
                 assume there's a simple mapping from
                 cu->line_header->file_names to subfiles, plus
                 cu->line_header->file_names may contain dups.  */
-             b->get_current_subfile ()->symtab
-               = allocate_symtab (cust, b->get_current_subfile ()->name);
+             const char *name = b->get_current_subfile ()->name.c_str ();
+             b->get_current_subfile ()->symtab = allocate_symtab (cust, name);
            }
 
          fe.symtab = b->get_current_subfile ()->symtab;
@@ -10769,8 +9692,8 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
       gdb_assert (m_builder == nullptr);
       struct compunit_symtab *cust = tug_unshare->compunit_symtab;
       m_builder.reset (new struct buildsym_compunit
-                      (COMPUNIT_OBJFILE (cust), "",
-                       COMPUNIT_DIRNAME (cust),
+                      (cust->objfile (), "",
+                       cust->dirname (),
                        compunit_language (cust),
                        0, cust));
       list_in_scope = get_builder ()->get_file_symbols ();
@@ -12175,14 +11098,13 @@ open_dwo_file (dwarf2_per_objfile *per_objfile,
 
   if (comp_dir != NULL)
     {
-      gdb::unique_xmalloc_ptr<char> path_to_try
-       (concat (comp_dir, SLASH_STRING, file_name, (char *) NULL));
+      std::string path_to_try = path_join (comp_dir, file_name);
 
       /* NOTE: If comp_dir is a relative path, this will also try the
         search path, which seems useful.  */
-      gdb_bfd_ref_ptr abfd (try_open_dwop_file (per_objfile, path_to_try.get (),
-                                               0 /*is_dwp*/,
-                                               1 /*search_cwd*/));
+      gdb_bfd_ref_ptr abfd (try_open_dwop_file
+       (per_objfile, path_to_try.c_str (), 0 /*is_dwp*/, 1 /*search_cwd*/));
+
       if (abfd != NULL)
        return abfd;
     }
@@ -12201,69 +11123,47 @@ open_dwo_file (dwarf2_per_objfile *per_objfile,
    size of each of the DWO debugging sections we are interested in.  */
 
 static void
-dwarf2_locate_dwo_sections (bfd *abfd, asection *sectp,
-                           dwo_sections *dwo_sections)
+dwarf2_locate_dwo_sections (struct objfile *objfile, bfd *abfd,
+                           asection *sectp, dwo_sections *dwo_sections)
 {
   const struct dwop_section_names *names = &dwop_section_names;
 
+  struct dwarf2_section_info *dw_sect = nullptr;
+
   if (names->abbrev_dwo.matches (sectp->name))
-    {
-      dwo_sections->abbrev.s.section = sectp;
-      dwo_sections->abbrev.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->abbrev;
   else if (names->info_dwo.matches (sectp->name))
-    {
-      dwo_sections->info.s.section = sectp;
-      dwo_sections->info.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->info;
   else if (names->line_dwo.matches (sectp->name))
-    {
-      dwo_sections->line.s.section = sectp;
-      dwo_sections->line.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->line;
   else if (names->loc_dwo.matches (sectp->name))
-    {
-      dwo_sections->loc.s.section = sectp;
-      dwo_sections->loc.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->loc;
   else if (names->loclists_dwo.matches (sectp->name))
-    {
-      dwo_sections->loclists.s.section = sectp;
-      dwo_sections->loclists.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->loclists;
   else if (names->macinfo_dwo.matches (sectp->name))
-    {
-      dwo_sections->macinfo.s.section = sectp;
-      dwo_sections->macinfo.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->macinfo;
   else if (names->macro_dwo.matches (sectp->name))
-    {
-      dwo_sections->macro.s.section = sectp;
-      dwo_sections->macro.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->macro;
   else if (names->rnglists_dwo.matches (sectp->name))
-    {
-      dwo_sections->rnglists.s.section = sectp;
-      dwo_sections->rnglists.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->rnglists;
   else if (names->str_dwo.matches (sectp->name))
-    {
-      dwo_sections->str.s.section = sectp;
-      dwo_sections->str.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->str;
   else if (names->str_offsets_dwo.matches (sectp->name))
-    {
-      dwo_sections->str_offsets.s.section = sectp;
-      dwo_sections->str_offsets.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->str_offsets;
   else if (names->types_dwo.matches (sectp->name))
     {
       struct dwarf2_section_info type_section;
 
       memset (&type_section, 0, sizeof (type_section));
-      type_section.s.section = sectp;
-      type_section.size = bfd_section_size (sectp);
       dwo_sections->types.push_back (type_section);
+      dw_sect = &dwo_sections->types.back ();
+    }
+
+  if (dw_sect != nullptr)
+    {
+      dw_sect->s.section = sectp;
+      dw_sect->size = bfd_section_size (sectp);
+      dw_sect->read (objfile);
     }
 }
 
@@ -12291,8 +11191,8 @@ open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name,
   dwo_file->dbfd = std::move (dbfd);
 
   for (asection *sec : gdb_bfd_sections (dwo_file->dbfd))
-    dwarf2_locate_dwo_sections (dwo_file->dbfd.get (), sec,
-                               &dwo_file->sections);
+    dwarf2_locate_dwo_sections (per_objfile->objfile, dwo_file->dbfd.get (),
+                               sec, &dwo_file->sections);
 
   create_cus_hash_table (per_objfile, cu, *dwo_file, dwo_file->sections.info,
                         dwo_file->cus);
@@ -12319,8 +11219,8 @@ open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name,
    we are interested in.  */
 
 static void
-dwarf2_locate_common_dwp_sections (bfd *abfd, asection *sectp,
-                                  dwp_file *dwp_file)
+dwarf2_locate_common_dwp_sections (struct objfile *objfile, bfd *abfd,
+                                  asection *sectp, dwp_file *dwp_file)
 {
   const struct dwop_section_names *names = &dwop_section_names;
   unsigned int elf_section_nr = elf_section_data (sectp)->this_idx;
@@ -12331,20 +11231,19 @@ dwarf2_locate_common_dwp_sections (bfd *abfd, asection *sectp,
   dwp_file->elf_sections[elf_section_nr] = sectp;
 
   /* Look for specific sections that we need.  */
+  struct dwarf2_section_info *dw_sect = nullptr;
   if (names->str_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.str.s.section = sectp;
-      dwp_file->sections.str.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.str;
   else if (names->cu_index.matches (sectp->name))
-    {
-      dwp_file->sections.cu_index.s.section = sectp;
-      dwp_file->sections.cu_index.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.cu_index;
   else if (names->tu_index.matches (sectp->name))
+    dw_sect = &dwp_file->sections.tu_index;
+
+  if (dw_sect != nullptr)
     {
-      dwp_file->sections.tu_index.s.section = sectp;
-      dwp_file->sections.tu_index.size = bfd_section_size (sectp);
+      dw_sect->s.section = sectp;
+      dw_sect->size = bfd_section_size (sectp);
+      dw_sect->read (objfile);
     }
 }
 
@@ -12354,7 +11253,8 @@ dwarf2_locate_common_dwp_sections (bfd *abfd, asection *sectp,
    have version 1 or 2 or 5 until we parse the cu_index/tu_index sections.  */
 
 static void
-dwarf2_locate_v2_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
+dwarf2_locate_v2_dwp_sections (struct objfile *objfile, bfd *abfd,
+                              asection *sectp, void *dwp_file_ptr)
 {
   struct dwp_file *dwp_file = (struct dwp_file *) dwp_file_ptr;
   const struct dwop_section_names *names = &dwop_section_names;
@@ -12366,45 +11266,29 @@ dwarf2_locate_v2_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
   dwp_file->elf_sections[elf_section_nr] = sectp;
 
   /* Look for specific sections that we need.  */
+  struct dwarf2_section_info *dw_sect = nullptr;
   if (names->abbrev_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.abbrev.s.section = sectp;
-      dwp_file->sections.abbrev.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.abbrev;
   else if (names->info_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.info.s.section = sectp;
-      dwp_file->sections.info.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.info;
   else if (names->line_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.line.s.section = sectp;
-      dwp_file->sections.line.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.line;
   else if (names->loc_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.loc.s.section = sectp;
-      dwp_file->sections.loc.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.loc;
   else if (names->macinfo_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.macinfo.s.section = sectp;
-      dwp_file->sections.macinfo.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.macinfo;
   else if (names->macro_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.macro.s.section = sectp;
-      dwp_file->sections.macro.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.macro;
   else if (names->str_offsets_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.str_offsets.s.section = sectp;
-      dwp_file->sections.str_offsets.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.str_offsets;
   else if (names->types_dwo.matches (sectp->name))
+    dw_sect = &dwp_file->sections.types;
+
+  if (dw_sect != nullptr)
     {
-      dwp_file->sections.types.s.section = sectp;
-      dwp_file->sections.types.size = bfd_section_size (sectp);
+      dw_sect->s.section = sectp;
+      dw_sect->size = bfd_section_size (sectp);
+      dw_sect->read (objfile);
     }
 }
 
@@ -12414,7 +11298,8 @@ dwarf2_locate_v2_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
    have version 1 or 2 or 5 until we parse the cu_index/tu_index sections.  */
 
 static void
-dwarf2_locate_v5_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
+dwarf2_locate_v5_dwp_sections (struct objfile *objfile, bfd *abfd,
+                              asection *sectp, void *dwp_file_ptr)
 {
   struct dwp_file *dwp_file = (struct dwp_file *) dwp_file_ptr;
   const struct dwop_section_names *names = &dwop_section_names;
@@ -12426,40 +11311,27 @@ dwarf2_locate_v5_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
   dwp_file->elf_sections[elf_section_nr] = sectp;
 
   /* Look for specific sections that we need.  */
+  struct dwarf2_section_info *dw_sect = nullptr;
   if (names->abbrev_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.abbrev.s.section = sectp;
-      dwp_file->sections.abbrev.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.abbrev;
   else if (names->info_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.info.s.section = sectp;
-      dwp_file->sections.info.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.info;
   else if (names->line_dwo.matches (sectp->name))
-   {
-     dwp_file->sections.line.s.section = sectp;
-     dwp_file->sections.line.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.line;
   else if (names->loclists_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.loclists.s.section = sectp;
-      dwp_file->sections.loclists.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.loclists;
   else if (names->macro_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.macro.s.section = sectp;
-      dwp_file->sections.macro.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.macro;
   else if (names->rnglists_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.rnglists.s.section = sectp;
-      dwp_file->sections.rnglists.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.rnglists;
   else if (names->str_offsets_dwo.matches (sectp->name))
+    dw_sect = &dwp_file->sections.str_offsets;
+
+  if (dw_sect != nullptr)
     {
-      dwp_file->sections.str_offsets.s.section = sectp;
-      dwp_file->sections.str_offsets.size = bfd_section_size (sectp);
+      dw_sect->s.section = sectp;
+      dw_sect->size = bfd_section_size (sectp);
+      dw_sect->read (objfile);
     }
 }
 
@@ -12586,7 +11458,7 @@ open_and_init_dwp_file (dwarf2_per_objfile *per_objfile)
                    dwp_file->num_sections, asection *);
 
   for (asection *sec : gdb_bfd_sections (dwp_file->dbfd))
-    dwarf2_locate_common_dwp_sections (dwp_file->dbfd.get (), sec,
+    dwarf2_locate_common_dwp_sections (objfile, dwp_file->dbfd.get (), sec,
                                       dwp_file.get ());
 
   dwp_file->cus = create_dwp_hash_table (per_objfile, dwp_file.get (), 0);
@@ -12616,10 +11488,10 @@ open_and_init_dwp_file (dwarf2_per_objfile *per_objfile)
   for (asection *sec : gdb_bfd_sections (dwp_file->dbfd))
     {
       if (dwp_file->version == 2)
-       dwarf2_locate_v2_dwp_sections (dwp_file->dbfd.get (), sec,
+       dwarf2_locate_v2_dwp_sections (objfile, dwp_file->dbfd.get (), sec,
                                       dwp_file.get ());
       else
-       dwarf2_locate_v5_dwp_sections (dwp_file->dbfd.get (), sec,
+       dwarf2_locate_v5_dwp_sections (objfile, dwp_file->dbfd.get (), sec,
                                       dwp_file.get ());
     }
 
@@ -13070,7 +11942,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
     }
 
   /* Ignore functions with missing or invalid low and high pc attributes.  */
-  if (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL)
+  if (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, nullptr, nullptr)
       <= PC_BOUNDS_INVALID)
     {
       attr = dwarf2_attr (die, DW_AT_external, cu);
@@ -13208,7 +12080,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
         of gdb assume that symbols do, and this is reasonably
         true.  */
       for (symbol *sym : template_args)
-       symbol_set_symtab (sym, symbol_symtab (templ_func));
+       sym->set_symtab (templ_func->symtab ());
     }
 
   /* In C++, we can have functions nested inside functions (e.g., when
@@ -13243,7 +12115,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
      as multiple lexical blocks?  Handling children in a sane way would
      be nasty.  Might be easier to properly extend generic blocks to
      describe ranges.  */
-  switch (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL))
+  switch (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, nullptr, nullptr))
     {
     case PC_BOUNDS_NOT_PRESENT:
       /* DW_TAG_lexical_block has no attributes, process its children as if
@@ -13305,6 +12177,11 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
   cu->get_builder ()->set_local_using_directives (cstk.local_using_directives);
 }
 
+static void dwarf2_ranges_read_low_addrs (unsigned offset,
+                                         struct dwarf2_cu *cu,
+                                         dwarf_tag tag,
+                                         std::vector<CORE_ADDR> &result);
+
 /* Read in DW_TAG_call_site and insert it to CU->call_site_htab.  */
 
 static void
@@ -13468,6 +12345,10 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
 
       target_die = follow_die_ref (die, attr, &target_cu);
       gdb_assert (target_cu->per_objfile->objfile == objfile);
+
+      struct attribute *ranges_attr
+       = dwarf2_attr (target_die, DW_AT_ranges, target_cu);
+
       if (die_is_declaration (target_die, target_cu))
        {
          const char *target_physname;
@@ -13483,12 +12364,25 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
          else
            call_site->target.set_loc_physname (target_physname);
        }
+      else if (ranges_attr != nullptr && ranges_attr->form_is_unsigned ())
+       {
+         ULONGEST ranges_offset = (ranges_attr->as_unsigned ()
+                                   + target_cu->gnu_ranges_base);
+         std::vector<CORE_ADDR> addresses;
+         dwarf2_ranges_read_low_addrs (ranges_offset, target_cu,
+                                       target_die->tag, addresses);
+         CORE_ADDR *saved = XOBNEWVAR (&objfile->objfile_obstack, CORE_ADDR,
+                                       addresses.size ());
+         std::copy (addresses.begin (), addresses.end (), saved);
+         call_site->target.set_loc_array (addresses.size (), saved);
+       }
       else
        {
          CORE_ADDR lowpc;
 
          /* DW_AT_entry_pc should be preferred.  */
-         if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu, NULL)
+         if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu,
+                                   nullptr, nullptr)
              <= PC_BOUNDS_INVALID)
            complaint (_("DW_AT_call_target target DIE has invalid "
                         "low pc, for referencing DIE %s [in module %s]"),
@@ -13989,15 +12883,15 @@ 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 set up the `psymtabs_addrmap'.  */
+   TAG is passed to dwarf2_ranges_process.  If MAP is not NULL, then
+   ranges in MAP are set, using DATUM as the value.  */
 
 static int
 dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
                    CORE_ADDR *high_return, struct dwarf2_cu *cu,
-                   dwarf2_psymtab *ranges_pst, dwarf_tag tag)
+                   addrmap *map, void *datum, 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;
@@ -14008,7 +12902,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
   retval = dwarf2_ranges_process (offset, cu, tag,
     [&] (CORE_ADDR range_beginning, CORE_ADDR range_end)
     {
-      if (ranges_pst != NULL)
+      if (map != nullptr)
        {
          CORE_ADDR lowpc;
          CORE_ADDR highpc;
@@ -14019,8 +12913,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
          highpc = (gdbarch_adjust_dwarf2_addr (gdbarch,
                                                range_end + baseaddr)
                    - baseaddr);
-         addrmap_set_empty (per_bfd->partial_symtabs->psymtabs_addrmap,
-                            lowpc, highpc - 1, ranges_pst);
+         addrmap_set_empty (map, lowpc, highpc - 1, datum);
        }
 
       /* FIXME: This is recording everything as a low-high
@@ -14056,6 +12949,20 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
   return 1;
 }
 
+/* Process ranges and fill in a vector of the low PC values only.  */
+
+static void
+dwarf2_ranges_read_low_addrs (unsigned offset, struct dwarf2_cu *cu,
+                             dwarf_tag tag,
+                             std::vector<CORE_ADDR> &result)
+{
+  dwarf2_ranges_process (offset, cu, tag,
+                        [&] (CORE_ADDR start, CORE_ADDR end)
+    {
+      result.push_back (start);
+    });
+}
+
 /* Get low and high pc attributes from a die.  See enum pc_bounds_kind
    definition for the return value.  *LOWPC and *HIGHPC are set iff
    neither PC_BOUNDS_NOT_PRESENT nor PC_BOUNDS_INVALID are returned.  */
@@ -14063,7 +12970,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
 static enum pc_bounds_kind
 dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
                      CORE_ADDR *highpc, struct dwarf2_cu *cu,
-                     dwarf2_psymtab *pst)
+                     addrmap *map, void *datum)
 {
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
   struct attribute *attr;
@@ -14106,8 +13013,8 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
 
          /* Value of the DW_AT_ranges attribute is the offset in the
             .debug_ranges section.  */
-         if (!dwarf2_ranges_read (ranges_offset, &low, &high, cu, pst,
-                                  die->tag))
+         if (!dwarf2_ranges_read (ranges_offset, &low, &high, cu,
+                                  map, datum, die->tag))
            return PC_BOUNDS_INVALID;
          /* Found discontinuous range of addresses.  */
          ret = PC_BOUNDS_RANGES;
@@ -14150,7 +13057,8 @@ dwarf2_get_subprogram_pc_bounds (struct die_info *die,
   CORE_ADDR low, high;
   struct die_info *child = die->child;
 
-  if (dwarf2_get_pc_bounds (die, &low, &high, cu, NULL) >= PC_BOUNDS_RANGES)
+  if (dwarf2_get_pc_bounds (die, &low, &high, cu, nullptr, nullptr)
+      >= PC_BOUNDS_RANGES)
     {
       *lowpc = std::min (*lowpc, low);
       *highpc = std::max (*highpc, high);
@@ -14187,7 +13095,8 @@ get_scope_pc_bounds (struct die_info *die,
   CORE_ADDR best_high = (CORE_ADDR) 0;
   CORE_ADDR current_low, current_high;
 
-  if (dwarf2_get_pc_bounds (die, &current_low, &current_high, cu, NULL)
+  if (dwarf2_get_pc_bounds (die, &current_low, &current_high, cu,
+                           nullptr, nullptr)
       >= PC_BOUNDS_RANGES)
     {
       best_low = current_low;
@@ -14315,6 +13224,7 @@ check_producer (struct dwarf2_cu *cu)
     {
       cu->producer_is_gxx_lt_4_6 = major < 4 || (major == 4 && minor < 6);
       cu->producer_is_gcc_lt_4_3 = major < 4 || (major == 4 && minor < 3);
+      cu->producer_is_gcc_11 = major == 11;
     }
   else if (producer_is_icc (cu->producer, &major, &minor))
     {
@@ -14459,6 +13369,19 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
       if (attr->form_is_constant ())
        {
          LONGEST offset = attr->constant_value (0);
+
+         /* Work around this GCC 11 bug, where it would erroneously use -1
+            data member locations, instead of 0:
+
+              Negative DW_AT_data_member_location
+              https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101378
+            */
+         if (offset == -1 && cu->producer_is_gcc_11)
+           {
+             complaint (_("DW_AT_data_member_location value of -1, assuming 0"));
+             offset = 0;
+           }
+
          field->set_loc_bitpos (offset * bits_per_byte);
        }
       else if (attr->form_is_section_offset ())
@@ -14537,8 +13460,21 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
 
   fp = &new_field->field;
 
-  if (die->tag == DW_TAG_member && ! die_is_declaration (die, cu))
-    {
+  if ((die->tag == DW_TAG_member || die->tag == DW_TAG_namelist_item)
+      && !die_is_declaration (die, cu))
+    {
+      if (die->tag == DW_TAG_namelist_item)
+        {
+         /* Typically, DW_TAG_namelist_item are references to namelist items.
+            If so, follow that reference.  */
+         struct attribute *attr1 = dwarf2_attr (die, DW_AT_namelist_item, cu);
+         struct die_info *item_die = nullptr;
+         struct dwarf2_cu *item_cu = cu;
+          if (attr1->form_is_ref ())
+           item_die = follow_die_ref (die, attr1, &item_cu);
+         if (item_die != nullptr)
+           die = item_die;
+        }
       /* Data member other than a C++ static data member.  */
 
       /* Get type of field.  */
@@ -15596,6 +14532,10 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
     {
       type->set_code (TYPE_CODE_UNION);
     }
+  else if (die->tag == DW_TAG_namelist)
+    {
+      type->set_code (TYPE_CODE_NAMELIST);
+    }
   else
     {
       type->set_code (TYPE_CODE_STRUCT);
@@ -15798,7 +14738,8 @@ handle_struct_member_die (struct die_info *child_die, struct type *type,
                          struct dwarf2_cu *cu)
 {
   if (child_die->tag == DW_TAG_member
-      || child_die->tag == DW_TAG_variable)
+      || child_die->tag == DW_TAG_variable
+      || child_die->tag == DW_TAG_namelist_item)
     {
       /* NOTE: carlton/2002-11-05: A C++ static data member
         should be a DW_TAG_member that is a declaration, but
@@ -15841,8 +14782,10 @@ handle_struct_member_die (struct die_info *child_die, struct type *type,
     handle_variant (child_die, type, fi, template_args, cu);
 }
 
-/* Finish creating a structure or union type, including filling in
-   its members and creating a symbol for it.  */
+/* Finish creating a structure or union type, including filling in its
+   members and creating a symbol for it. This function also handles Fortran
+   namelist variables, their items or members and creating a symbol for
+   them.  */
 
 static void
 process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
@@ -16033,7 +14976,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
        {
          struct symtab *symtab;
          if (sym != nullptr)
-           symtab = symbol_symtab (sym);
+           symtab = sym->symtab ();
          else if (cu->line_header != nullptr)
            {
              /* Any related symtab will do.  */
@@ -16057,7 +15000,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
                 other parts of gdb assume that symbols do, and this is
                 reasonably true.  */
              for (int i = 0; i < TYPE_N_TEMPLATE_ARGUMENTS (type); ++i)
-               symbol_set_symtab (TYPE_TEMPLATE_ARGUMENT (type, i), symtab);
+               TYPE_TEMPLATE_ARGUMENT (type, i)->set_symtab (symtab);
            }
        }
     }
@@ -16612,7 +15555,8 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
   child_die = die->child;
   while (child_die && child_die->tag)
     {
-      if (child_die->tag == DW_TAG_subrange_type)
+      if (child_die->tag == DW_TAG_subrange_type
+         || child_die->tag == DW_TAG_generic_subrange)
        {
          struct type *child_type = read_type_die (child_die, cu);
 
@@ -16846,7 +15790,7 @@ mark_common_block_symbol_computed (struct symbol *sym,
   gdb_assert (ptr - baton->data == baton->size);
 
   SYMBOL_LOCATION_BATON (sym) = baton;
-  SYMBOL_ACLASS_INDEX (sym) = dwarf2_locexpr_index;
+  sym->set_aclass_index (dwarf2_locexpr_index);
 }
 
 /* Create appropriate locally-scoped variables for all the
@@ -16945,7 +15889,7 @@ read_common_block (struct die_info *die, struct dwarf2_cu *cu)
        }
 
       sym = new_symbol (die, objfile_type (objfile)->builtin_void, cu);
-      SYMBOL_VALUE_COMMON_BLOCK (sym) = common_block;
+      sym->set_value_common_block (common_block);
     }
 }
 
@@ -18785,11 +17729,11 @@ read_die_and_siblings (const struct die_reader_specs *reader,
 
   if (dwarf_die_debug)
     {
-      fprintf_unfiltered (gdb_stdlog,
-                         "Read die from %s@0x%x of %s:\n",
-                         reader->die_section->get_name (),
-                         (unsigned) (info_ptr - reader->die_section->buffer),
-                         bfd_get_filename (reader->abfd));
+      gdb_printf (gdb_stdlog,
+                 "Read die from %s@0x%x of %s:\n",
+                 reader->die_section->get_name (),
+                 (unsigned) (info_ptr - reader->die_section->buffer),
+                 bfd_get_filename (reader->abfd));
       dump_die (die, dwarf_die_debug);
     }
 
@@ -18891,11 +17835,11 @@ read_full_die (const struct die_reader_specs *reader,
 
   if (dwarf_die_debug)
     {
-      fprintf_unfiltered (gdb_stdlog,
-                         "Read die from %s@0x%x of %s:\n",
-                         reader->die_section->get_name (),
-                         (unsigned) (info_ptr - reader->die_section->buffer),
-                         bfd_get_filename (reader->abfd));
+      gdb_printf (gdb_stdlog,
+                 "Read die from %s@0x%x of %s:\n",
+                 reader->die_section->get_name (),
+                 (unsigned) (info_ptr - reader->die_section->buffer),
+                 bfd_get_filename (reader->abfd));
       dump_die (*diep, dwarf_die_debug);
     }
 
@@ -18903,825 +17847,855 @@ read_full_die (const struct die_reader_specs *reader,
 }
 \f
 
-/* Returns nonzero if TAG represents a type that we might generate a partial
-   symbol for.  */
-
-static int
-is_type_tag_for_partial (int tag, enum language lang)
+void
+cooked_indexer::check_bounds (cutu_reader *reader)
 {
-  switch (tag)
+  if (reader->cu->per_cu->addresses_seen)
+    return;
+
+  dwarf2_cu *cu = reader->cu;
+
+  CORE_ADDR best_lowpc = 0, best_highpc = 0;
+  /* Possibly set the default values of LOWPC and HIGHPC from
+     `DW_AT_ranges'.  */
+  dwarf2_find_base_address (reader->comp_unit_die, cu);
+  enum pc_bounds_kind cu_bounds_kind
+    = dwarf2_get_pc_bounds (reader->comp_unit_die, &best_lowpc, &best_highpc,
+                           cu, m_index_storage->get_addrmap (), cu->per_cu);
+  if (cu_bounds_kind == PC_BOUNDS_HIGH_LOW && best_lowpc < best_highpc)
     {
-#if 0
-    /* Some types that would be reasonable to generate partial symbols for,
-       that we don't at present.  Note that normally this does not
-       matter, mainly because C compilers don't give names to these
-       types, but instead emit DW_TAG_typedef.  */
-    case DW_TAG_file_type:
-    case DW_TAG_ptr_to_member_type:
-    case DW_TAG_set_type:
-    case DW_TAG_string_type:
-    case DW_TAG_subroutine_type:
-#endif
+      struct objfile *objfile = cu->per_objfile->objfile;
+      CORE_ADDR baseaddr = objfile->text_section_offset ();
+      struct gdbarch *gdbarch = objfile->arch ();
+      CORE_ADDR low
+       = (gdbarch_adjust_dwarf2_addr (gdbarch, best_lowpc + baseaddr)
+          - baseaddr);
+      CORE_ADDR high
+       = (gdbarch_adjust_dwarf2_addr (gdbarch, best_highpc + baseaddr)
+          - baseaddr - 1);
+      /* Store the contiguous range if it is not empty; it can be
+        empty for CUs with no code.  */
+      addrmap_set_empty (m_index_storage->get_addrmap (), low, high,
+                        cu->per_cu);
 
-      /* GNAT may emit an array with a name, but no typedef, so we
-        need to make a symbol in this case.  */
-    case DW_TAG_array_type:
-      return lang == language_ada;
+      cu->per_cu->addresses_seen = true;
+    }
+}
 
-    case DW_TAG_base_type:
+/* Helper function that returns true if TAG can have a linkage
+   name.  */
+
+static bool
+tag_can_have_linkage_name (enum dwarf_tag tag)
+{
+  switch (tag)
+    {
+      /* We include types here because an anonymous C++ type might
+        have a name for linkage purposes.  */
     case DW_TAG_class_type:
-    case DW_TAG_interface_type:
-    case DW_TAG_enumeration_type:
     case DW_TAG_structure_type:
-    case DW_TAG_subrange_type:
-    case DW_TAG_typedef:
     case DW_TAG_union_type:
-      return 1;
+    case DW_TAG_variable:
+    case DW_TAG_subprogram:
+      return true;
+
     default:
-      return 0;
+      return false;
     }
 }
 
-/* Load all DIEs that are interesting for partial symbols into memory.  */
-
-static struct partial_die_info *
-load_partial_dies (const struct die_reader_specs *reader,
-                  const gdb_byte *info_ptr, int building_psymtab)
+cutu_reader *
+cooked_indexer::ensure_cu_exists (cutu_reader *reader,
+                                 dwarf2_per_objfile *per_objfile,
+                                 sect_offset sect_off, bool is_dwz,
+                                 bool for_scanning)
 {
-  struct dwarf2_cu *cu = reader->cu;
-  struct objfile *objfile = cu->per_objfile->objfile;
-  struct partial_die_info *parent_die, *last_die, *first_die = NULL;
-  unsigned int bytes_read;
-  unsigned int load_all = 0;
-  int nesting_level = 1;
+  /* Lookups for type unit references are always in the CU, and
+     cross-CU references will crash.  */
+  if (reader->cu->per_cu->is_dwz == is_dwz
+      && reader->cu->header.offset_in_cu_p (sect_off))
+    return reader;
 
-  parent_die = NULL;
-  last_die = NULL;
+  dwarf2_per_cu_data *per_cu
+    = dwarf2_find_containing_comp_unit (sect_off, is_dwz,
+                                       per_objfile->per_bfd);
 
-  gdb_assert (cu->per_cu != NULL);
-  if (cu->load_all_dies)
-    load_all = 1;
-
-  cu->partial_dies
-    = htab_create_alloc_ex (cu->header.length / 12,
-                           partial_die_hash,
-                           partial_die_eq,
-                           NULL,
-                           &cu->comp_unit_obstack,
-                           hashtab_obstack_allocate,
-                           dummy_obstack_deallocate);
-
-  while (1)
+  /* When scanning, we only want to visit a given CU a single time.
+     Doing this check here avoids self-imports as well.  */
+  if (for_scanning)
     {
-      const abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr,
-                                                  &bytes_read);
-
-      /* A NULL abbrev means the end of a series of children.  */
-      if (abbrev == NULL)
-       {
-         if (--nesting_level == 0)
-           return first_die;
-
-         info_ptr += bytes_read;
-         last_die = parent_die;
-         parent_die = parent_die->die_parent;
-         continue;
-       }
-
-      /* Check for template arguments.  We never save these; if
-        they're seen, we just mark the parent, and go on our way.  */
-      if (parent_die != NULL
-         && cu->per_cu->lang == language_cplus
-         && (abbrev->tag == DW_TAG_template_type_param
-             || abbrev->tag == DW_TAG_template_value_param))
-       {
-         parent_die->has_template_arguments = 1;
-
-         if (!load_all)
-           {
-             /* We don't need a partial DIE for the template argument.  */
-             info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev);
-             continue;
-           }
-       }
-
-      /* We only recurse into c++ subprograms looking for template arguments.
-        Skip their other children.  */
-      if (!load_all
-         && cu->per_cu->lang == language_cplus
-         && parent_die != NULL
-         && parent_die->tag == DW_TAG_subprogram
-         && abbrev->tag != DW_TAG_inlined_subroutine)
-       {
-         info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev);
-         continue;
-       }
-
-      /* Check whether this DIE is interesting enough to save.  Normally
-        we would not be interested in members here, but there may be
-        later variables referencing them via DW_AT_specification (for
-        static members).  */
-      if (!load_all
-         && !is_type_tag_for_partial (abbrev->tag, cu->per_cu->lang)
-         && abbrev->tag != DW_TAG_constant
-         && abbrev->tag != DW_TAG_enumerator
-         && abbrev->tag != DW_TAG_subprogram
-         && abbrev->tag != DW_TAG_inlined_subroutine
-         && abbrev->tag != DW_TAG_lexical_block
-         && abbrev->tag != DW_TAG_variable
-         && abbrev->tag != DW_TAG_namespace
-         && abbrev->tag != DW_TAG_module
-         && abbrev->tag != DW_TAG_member
-         && abbrev->tag != DW_TAG_imported_unit
-         && abbrev->tag != DW_TAG_imported_declaration)
-       {
-         /* Otherwise we skip to the next sibling, if any.  */
-         info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev);
-         continue;
-       }
-
-      struct partial_die_info pdi ((sect_offset) (info_ptr - reader->buffer),
-                                  abbrev);
-
-      info_ptr = pdi.read (reader, *abbrev, info_ptr + bytes_read);
-
-      /* This two-pass algorithm for processing partial symbols has a
-        high cost in cache pressure.  Thus, handle some simple cases
-        here which cover the majority of C partial symbols.  DIEs
-        which neither have specification tags in them, nor could have
-        specification tags elsewhere pointing at them, can simply be
-        processed and discarded.
-
-        This segment is also optional; scan_partial_symbols and
-        add_partial_symbol will handle these DIEs if we chain
-        them in normally.  When compilers which do not emit large
-        quantities of duplicate debug information are more common,
-        this code can probably be removed.  */
-
-      /* Any complete simple types at the top level (pretty much all
-        of them, for a language without namespaces), can be processed
-        directly.  */
-      if (parent_die == NULL
-         && pdi.has_specification == 0
-         && pdi.is_declaration == 0
-         && ((pdi.tag == DW_TAG_typedef && !pdi.has_children)
-             || pdi.tag == DW_TAG_base_type
-             || pdi.tag == DW_TAG_array_type
-             || pdi.tag == DW_TAG_subrange_type))
-       {
-         if (building_psymtab && pdi.raw_name != NULL)
-           add_partial_symbol (&pdi, cu);
-
-         info_ptr = locate_pdi_sibling (reader, &pdi, info_ptr);
-         continue;
-       }
-
-      /* The exception for DW_TAG_typedef with has_children above is
-        a workaround of GCC PR debug/47510.  In the case of this complaint
-        type_name_or_error will error on such types later.
-
-        GDB skipped children of DW_TAG_typedef by the shortcut above and then
-        it could not find the child DIEs referenced later, this is checked
-        above.  In correct DWARF DW_TAG_typedef should have no children.  */
-
-      if (pdi.tag == DW_TAG_typedef && pdi.has_children)
-       complaint (_("DW_TAG_typedef has childen - GCC PR debug/47510 bug "
-                    "- DIE at %s [in module %s]"),
-                  sect_offset_str (pdi.sect_off), objfile_name (objfile));
-
-      /* If we're at the second level, and we're an enumerator, and
-        our parent has no specification (meaning possibly lives in a
-        namespace elsewhere), then we can add the partial symbol now
-        instead of queueing it.  */
-      if (pdi.tag == DW_TAG_enumerator
-         && parent_die != NULL
-         && parent_die->die_parent == NULL
-         && parent_die->tag == DW_TAG_enumeration_type
-         && parent_die->has_specification == 0)
-       {
-         if (pdi.raw_name == NULL)
-           complaint (_("malformed enumerator DIE ignored"));
-         else if (building_psymtab)
-           add_partial_symbol (&pdi, cu);
-
-         info_ptr = locate_pdi_sibling (reader, &pdi, info_ptr);
-         continue;
-       }
-
-      struct partial_die_info *part_die
-       = new (&cu->comp_unit_obstack) partial_die_info (pdi);
-
-      /* We'll save this DIE so link it in.  */
-      part_die->die_parent = parent_die;
-      part_die->die_sibling = NULL;
-      part_die->die_child = NULL;
-
-      if (last_die && last_die == parent_die)
-       last_die->die_child = part_die;
-      else if (last_die)
-       last_die->die_sibling = part_die;
-
-      last_die = part_die;
-
-      if (first_die == NULL)
-       first_die = part_die;
-
-      /* Maybe add the DIE to the hash table.  Not all DIEs that we
-        find interesting need to be in the hash table, because we
-        also have the parent/sibling/child chains; only those that we
-        might refer to by offset later during partial symbol reading.
-
-        For now this means things that might have be the target of a
-        DW_AT_specification, DW_AT_abstract_origin, or
-        DW_AT_extension.  DW_AT_extension will refer only to
-        namespaces; DW_AT_abstract_origin refers to functions (and
-        many things under the function DIE, but we do not recurse
-        into function DIEs during partial symbol reading) and
-        possibly variables as well; DW_AT_specification refers to
-        declarations.  Declarations ought to have the DW_AT_declaration
-        flag.  It happens that GCC forgets to put it in sometimes, but
-        only for functions, not for types.
-
-        Adding more things than necessary to the hash table is harmless
-        except for the performance cost.  Adding too few will result in
-        wasted time in find_partial_die, when we reread the compilation
-        unit with load_all_dies set.  */
-
-      if (load_all
-         || abbrev->tag == DW_TAG_constant
-         || abbrev->tag == DW_TAG_subprogram
-         || abbrev->tag == DW_TAG_variable
-         || abbrev->tag == DW_TAG_namespace
-         || part_die->is_declaration)
-       {
-         void **slot;
-
-         slot = htab_find_slot_with_hash (cu->partial_dies, part_die,
-                                          to_underlying (part_die->sect_off),
-                                          INSERT);
-         *slot = part_die;
-       }
-
-      /* For some DIEs we want to follow their children (if any).  For C
-        we have no reason to follow the children of structures; for other
-        languages we have to, so that we can get at method physnames
-        to infer fully qualified class names, for DW_AT_specification,
-        and for C++ template arguments.  For C++, we also look one level
-        inside functions to find template arguments (if the name of the
-        function does not already contain the template arguments).
-
-        For Ada and Fortran, we need to scan the children of subprograms
-        and lexical blocks as well because these languages allow the
-        definition of nested entities that could be interesting for the
-        debugger, such as nested subprograms for instance.  */
-      if (last_die->has_children
-         && (load_all
-             || last_die->tag == DW_TAG_namespace
-             || last_die->tag == DW_TAG_module
-             || last_die->tag == DW_TAG_enumeration_type
-             || (cu->per_cu->lang == language_cplus
-                 && last_die->tag == DW_TAG_subprogram
-                 && (last_die->raw_name == NULL
-                     || strchr (last_die->raw_name, '<') == NULL))
-             || (cu->per_cu->lang != language_c
-                 && (last_die->tag == DW_TAG_class_type
-                     || last_die->tag == DW_TAG_interface_type
-                     || last_die->tag == DW_TAG_structure_type
-                     || last_die->tag == DW_TAG_union_type))
-             || ((cu->per_cu->lang == language_ada
-                  || cu->per_cu->lang == language_fortran)
-                 && (last_die->tag == DW_TAG_subprogram
-                     || last_die->tag == DW_TAG_lexical_block))))
-       {
-         nesting_level++;
-         parent_die = last_die;
-         continue;
-       }
+      bool nope = false;
+      if (!per_cu->scanned.compare_exchange_strong (nope, true))
+       return nullptr;
+    }
+  if (per_cu == m_per_cu)
+    return reader;
 
-      /* Otherwise we skip to the next sibling, if any.  */
-      info_ptr = locate_pdi_sibling (reader, last_die, info_ptr);
+  cutu_reader *result = m_index_storage->get_reader (per_cu);
+  if (result == nullptr)
+    {
+      cutu_reader new_reader (per_cu, per_objfile, nullptr, nullptr, false,
+                             m_index_storage->get_abbrev_cache ());
 
-      /* Back to the top, do it again.  */
+      prepare_one_comp_unit (new_reader.cu, new_reader.comp_unit_die,
+                            language_minimal);
+      std::unique_ptr<cutu_reader> copy
+       (new cutu_reader (std::move (new_reader)));
+      result = m_index_storage->preserve (std::move (copy));
     }
-}
-
-partial_die_info::partial_die_info (sect_offset sect_off_,
-                                   const struct abbrev_info *abbrev)
-  : partial_die_info (sect_off_, abbrev->tag, abbrev->has_children)
-{
-}
 
-/* See class definition.  */
+  if (result->dummy_p || !result->comp_unit_die->has_children)
+    return nullptr;
 
-const char *
-partial_die_info::name (dwarf2_cu *cu)
-{
-  if (!canonical_name && raw_name != nullptr)
-    {
-      struct objfile *objfile = cu->per_objfile->objfile;
-      raw_name = dwarf2_canonicalize_name (raw_name, cu, objfile);
-      canonical_name = 1;
-    }
+  if (for_scanning)
+    check_bounds (result);
 
-  return raw_name;
+  return result;
 }
 
-/* Read a minimal amount of information into the minimal die structure.
-   INFO_PTR should point just after the initial uleb128 of a DIE.  */
-
 const gdb_byte *
-partial_die_info::read (const struct die_reader_specs *reader,
-                       const struct abbrev_info &abbrev, const gdb_byte *info_ptr)
-{
-  struct dwarf2_cu *cu = reader->cu;
-  dwarf2_per_objfile *per_objfile = cu->per_objfile;
-  unsigned int i;
-  int has_low_pc_attr = 0;
-  int has_high_pc_attr = 0;
-  int high_pc_relative = 0;
-
-  for (i = 0; i < abbrev.num_attrs; ++i)
+cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
+                                cutu_reader *reader,
+                                const gdb_byte *watermark_ptr,
+                                const gdb_byte *info_ptr,
+                                const abbrev_info *abbrev,
+                                const char **name,
+                                const char **linkage_name,
+                                cooked_index_flag *flags,
+                                sect_offset *sibling_offset,
+                                const cooked_index_entry **parent_entry,
+                                CORE_ADDR *maybe_defer,
+                                bool for_specification)
+{
+  bool origin_is_dwz = false;
+  bool is_declaration = false;
+  sect_offset origin_offset {};
+
+  gdb::optional<CORE_ADDR> low_pc;
+  gdb::optional<CORE_ADDR> high_pc;
+  bool high_pc_relative = false;
+
+  for (int i = 0; i < abbrev->num_attrs; ++i)
     {
       attribute attr;
-      info_ptr = read_attribute (reader, &attr, &abbrev.attrs[i], info_ptr);
-      /* String and address offsets that need to do the reprocessing have
-        already been read at this point, so there is no need to wait until
-        the loop terminates to do the reprocessing.  */
+      info_ptr = read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
       if (attr.requires_reprocessing_p ())
-       read_attribute_reprocess (reader, &attr, tag);
+       read_attribute_reprocess (reader, &attr, abbrev->tag);
+
       /* Store the data if it is of an attribute we want to keep in a
         partial symbol table.  */
       switch (attr.name)
        {
        case DW_AT_name:
-         switch (tag)
+         switch (abbrev->tag)
            {
            case DW_TAG_compile_unit:
            case DW_TAG_partial_unit:
            case DW_TAG_type_unit:
              /* Compilation units have a DW_AT_name that is a filename, not
                 a source language identifier.  */
-           case DW_TAG_enumeration_type:
-           case DW_TAG_enumerator:
-             /* These tags always have simple identifiers already; no need
-                to canonicalize them.  */
-             canonical_name = 1;
-             raw_name = attr.as_string ();
              break;
+
            default:
-             canonical_name = 0;
-             raw_name = attr.as_string ();
+             if (*name == nullptr)
+               *name = attr.as_string ();
              break;
            }
          break;
+
        case DW_AT_linkage_name:
        case DW_AT_MIPS_linkage_name:
          /* Note that both forms of linkage name might appear.  We
             assume they will be the same, and we only store the last
             one we see.  */
-         linkage_name = attr.as_string ();
-         break;
-       case DW_AT_low_pc:
-         has_low_pc_attr = 1;
-         lowpc = attr.as_address ();
-         break;
-       case DW_AT_high_pc:
-         has_high_pc_attr = 1;
-         highpc = attr.as_address ();
-         if (cu->header.version >= 4 && attr.form_is_constant ())
-               high_pc_relative = 1;
-         break;
-       case DW_AT_location:
-         /* Support the .debug_loc offsets.  */
-         if (attr.form_is_block ())
-           {
-             d.locdesc = attr.as_block ();
-           }
-         else if (attr.form_is_section_offset ())
-           {
-             dwarf2_complex_location_expr_complaint ();
-           }
-         else
-           {
-             dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
-                                                    "partial symbol information");
-           }
+         if (*linkage_name == nullptr)
+           *linkage_name = attr.as_string ();
          break;
-       case DW_AT_external:
-         is_external = attr.as_boolean ();
+
+       case DW_AT_main_subprogram:
+         if (attr.as_boolean ())
+           *flags |= IS_MAIN;
          break;
+
        case DW_AT_declaration:
          is_declaration = attr.as_boolean ();
          break;
-       case DW_AT_type:
-         has_type = 1;
+
+       case DW_AT_sibling:
+         if (sibling_offset != nullptr)
+           *sibling_offset = attr.get_ref_die_offset ();
          break;
-       case DW_AT_abstract_origin:
+
        case DW_AT_specification:
+       case DW_AT_abstract_origin:
        case DW_AT_extension:
-         has_specification = 1;
-         spec_offset = attr.get_ref_die_offset ();
-         spec_is_dwz = (attr.form == DW_FORM_GNU_ref_alt
-                                  || cu->per_cu->is_dwz);
+         origin_offset = attr.get_ref_die_offset ();
+         origin_is_dwz = attr.form == DW_FORM_GNU_ref_alt;
          break;
-       case DW_AT_sibling:
-         /* Ignore absolute siblings, they might point outside of
-            the current compile unit.  */
-         if (attr.form == DW_FORM_ref_addr)
-           complaint (_("ignoring absolute DW_AT_sibling"));
-         else
-           {
-             const gdb_byte *buffer = reader->buffer;
-             sect_offset off = attr.get_ref_die_offset ();
-             const gdb_byte *sibling_ptr = buffer + to_underlying (off);
 
-             if (sibling_ptr < info_ptr)
-               complaint (_("DW_AT_sibling points backwards"));
-             else if (sibling_ptr > reader->buffer_end)
-               reader->die_section->overflow_complaint ();
-             else
-               sibling = sibling_ptr;
-           }
-         break;
-       case DW_AT_byte_size:
-         has_byte_size = 1;
+       case DW_AT_external:
+         if (attr.as_boolean ())
+           *flags &= ~IS_STATIC;
          break;
-       case DW_AT_const_value:
-         has_const_value = 1;
+
+       case DW_AT_enum_class:
+         if (attr.as_boolean ())
+           *flags |= IS_ENUM_CLASS;
          break;
-       case DW_AT_calling_convention:
-         /* DWARF doesn't provide a way to identify a program's source-level
-            entry point.  DW_AT_calling_convention attributes are only meant
-            to describe functions' calling conventions.
-
-            However, because it's a necessary piece of information in
-            Fortran, and before DWARF 4 DW_CC_program was the only
-            piece of debugging information whose definition refers to
-            a 'main program' at all, several compilers marked Fortran
-            main programs with DW_CC_program --- even when those
-            functions use the standard calling conventions.
-
-            Although DWARF now specifies a way to provide this
-            information, we support this practice for backward
-            compatibility.  */
-         if (attr.constant_value (0) == DW_CC_program
-             && cu->per_cu->lang == language_fortran)
-           main_subprogram = 1;
+
+       case DW_AT_low_pc:
+         low_pc = attr.as_address ();
          break;
-       case DW_AT_inline:
-         {
-           LONGEST value = attr.constant_value (-1);
-           if (value == DW_INL_inlined
-               || value == DW_INL_declared_inlined)
-             may_be_inlined = 1;
-         }
+
+       case DW_AT_high_pc:
+         high_pc = attr.as_address ();
+         if (reader->cu->header.version >= 4 && attr.form_is_constant ())
+           high_pc_relative = true;
          break;
 
-       case DW_AT_import:
-         if (tag == DW_TAG_imported_unit)
+       case DW_AT_location:
+         if (!scanning_per_cu->addresses_seen && attr.form_is_block ())
            {
-             d.sect_off = attr.get_ref_die_offset ();
-             is_dwz = (attr.form == DW_FORM_GNU_ref_alt
-                                 || cu->per_cu->is_dwz);
+             struct dwarf_block *locdesc = attr.as_block ();
+             CORE_ADDR addr = decode_locdesc (locdesc, reader->cu);
+             if (addr != 0
+                 || reader->cu->per_objfile->per_bfd->has_section_at_zero)
+               {
+                 low_pc = addr;
+                 /* For variables, we don't want to try decoding the
+                    type just to find the size -- for gdb's purposes
+                    we only need the address of a variable.  */
+                 high_pc = addr + 1;
+                 high_pc_relative = false;
+               }
            }
          break;
 
-       case DW_AT_main_subprogram:
-         main_subprogram = attr.as_boolean ();
+       case DW_AT_ranges:
+         if (!scanning_per_cu->addresses_seen)
+           {
+             /* Offset in the .debug_ranges or .debug_rnglist section
+                (depending on DWARF version).  */
+             ULONGEST ranges_offset = attr.as_unsigned ();
+
+             /* See dwarf2_cu::gnu_ranges_base's doc for why we might
+                want to add this value.  */
+             ranges_offset += reader->cu->gnu_ranges_base;
+
+             CORE_ADDR lowpc, highpc;
+             dwarf2_ranges_read (ranges_offset, &lowpc, &highpc, reader->cu,
+                                 m_index_storage->get_addrmap (),
+                                 scanning_per_cu, abbrev->tag);
+           }
          break;
+       }
+    }
 
-       case DW_AT_ranges:
-         {
-           /* Offset in the .debug_ranges or .debug_rnglist section (depending
-              on DWARF version).  */
-           ranges_offset = attr.as_unsigned ();
+  /* We don't want to examine declarations, but if we found a
+     declaration when handling DW_AT_specification or the like, then
+     that is ok.  Similarly, we allow an external variable without a
+     location; those are resolved via minimal symbols.  */
+  if (is_declaration && !for_specification
+      && (abbrev->tag != DW_TAG_variable
+         || (*flags & IS_STATIC) != 0))
+    {
+      *linkage_name = nullptr;
+      *name = nullptr;
+    }
+  else if ((*name == nullptr
+           || (*linkage_name == nullptr
+               && tag_can_have_linkage_name (abbrev->tag))
+           || (*parent_entry == nullptr && m_language != language_c))
+          && origin_offset != sect_offset (0))
+    {
+      cutu_reader *new_reader
+       = ensure_cu_exists (reader, reader->cu->per_objfile, origin_offset,
+                           origin_is_dwz, false);
+      if (new_reader != nullptr)
+       {
+         const gdb_byte *new_info_ptr = (new_reader->buffer
+                                         + to_underlying (origin_offset));
+
+         if (new_reader->cu == reader->cu
+             && new_info_ptr > watermark_ptr
+             && maybe_defer != nullptr
+             && *parent_entry == nullptr)
+           *maybe_defer = form_addr (origin_offset, origin_is_dwz);
+         else if (*parent_entry == nullptr)
+           {
+             CORE_ADDR lookup = form_addr (origin_offset, origin_is_dwz);
+             *parent_entry
+               = (cooked_index_entry *) addrmap_find (m_die_range_map,
+                                                      lookup);
+           }
 
-           /* See dwarf2_cu::gnu_ranges_base's doc for why we might want to add
-              this value.  */
-           if (tag != DW_TAG_compile_unit)
-             ranges_offset += cu->gnu_ranges_base;
+         unsigned int bytes_read;
+         const abbrev_info *new_abbrev = peek_die_abbrev (*new_reader,
+                                                          new_info_ptr,
+                                                          &bytes_read);
+         new_info_ptr += bytes_read;
+         scan_attributes (scanning_per_cu, new_reader, new_info_ptr, new_info_ptr,
+                          new_abbrev, name, linkage_name, flags, nullptr,
+                          parent_entry, maybe_defer, true);
+       }
+    }
 
-           has_range_info = 1;
-         }
-         break;
+  if (!for_specification)
+    {
+      if (m_language == language_ada
+         && *linkage_name == nullptr)
+       *linkage_name = *name;
 
-       default:
-         break;
+      if (!scanning_per_cu->addresses_seen
+         && low_pc.has_value ()
+         && (reader->cu->per_objfile->per_bfd->has_section_at_zero
+             || *low_pc != 0)
+         && high_pc.has_value ())
+       {
+         if (high_pc_relative)
+           high_pc = *high_pc + *low_pc;
+
+         if (*high_pc > *low_pc)
+           {
+             struct objfile *objfile = reader->cu->per_objfile->objfile;
+             CORE_ADDR baseaddr = objfile->text_section_offset ();
+             struct gdbarch *gdbarch = objfile->arch ();
+             CORE_ADDR lo
+               = (gdbarch_adjust_dwarf2_addr (gdbarch, *low_pc + baseaddr)
+                  - baseaddr);
+             CORE_ADDR hi
+               = (gdbarch_adjust_dwarf2_addr (gdbarch, *high_pc + baseaddr)
+                  - baseaddr);
+             addrmap_set_empty (m_index_storage->get_addrmap (), lo, hi - 1,
+                                scanning_per_cu);
+           }
+       }
+
+      if (abbrev->tag == DW_TAG_module || abbrev->tag == DW_TAG_namespace)
+       *flags &= ~IS_STATIC;
+
+      if (abbrev->tag == DW_TAG_namespace && *name == nullptr)
+       *name = "(anonymous namespace)";
+
+      if (m_language == language_cplus
+         && (abbrev->tag == DW_TAG_class_type
+             || abbrev->tag == DW_TAG_interface_type
+             || abbrev->tag == DW_TAG_structure_type
+             || abbrev->tag == DW_TAG_union_type
+             || abbrev->tag == DW_TAG_enumeration_type
+             || abbrev->tag == DW_TAG_enumerator))
+       *flags &= ~IS_STATIC;
+    }
+
+  return info_ptr;
+}
+
+const gdb_byte *
+cooked_indexer::index_imported_unit (cutu_reader *reader,
+                                    const gdb_byte *info_ptr,
+                                    const abbrev_info *abbrev)
+{
+  sect_offset sect_off {};
+  bool is_dwz = false;
+
+  for (int i = 0; i < abbrev->num_attrs; ++i)
+    {
+      /* Note that we never need to reprocess attributes here.  */
+      attribute attr;
+      info_ptr = read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
+
+      if (attr.name == DW_AT_import)
+       {
+         sect_off = attr.get_ref_die_offset ();
+         is_dwz = (attr.form == DW_FORM_GNU_ref_alt
+                   || reader->cu->per_cu->is_dwz);
        }
     }
 
-  /* For Ada, if both the name and the linkage name appear, we prefer
-     the latter.  This lets "catch exception" work better, regardless
-     of the order in which the name and linkage name were emitted.
-     Really, though, this is just a workaround for the fact that gdb
-     doesn't store both the name and the linkage name.  */
-  if (cu->per_cu->lang == language_ada && linkage_name != nullptr)
-    raw_name = linkage_name;
+  /* Did not find DW_AT_import.  */
+  if (sect_off == sect_offset (0))
+    return info_ptr;
+
+  dwarf2_per_objfile *per_objfile = reader->cu->per_objfile;
+  cutu_reader *new_reader = ensure_cu_exists (reader, per_objfile, sect_off,
+                                             is_dwz, true);
+  if (new_reader != nullptr)
+    {
+      index_dies (new_reader, new_reader->info_ptr, nullptr, false);
+
+      reader->cu->add_dependence (new_reader->cu->per_cu);
+    }
+
+  return info_ptr;
+}
+
+const gdb_byte *
+cooked_indexer::recurse (cutu_reader *reader,
+                        const gdb_byte *info_ptr,
+                        const cooked_index_entry *parent_entry,
+                        bool fully)
+{
+  info_ptr = index_dies (reader, info_ptr, parent_entry, fully);
+
+  if (parent_entry != nullptr)
+    {
+      CORE_ADDR start = form_addr (parent_entry->die_offset,
+                                  reader->cu->per_cu->is_dwz);
+      CORE_ADDR end = form_addr (sect_offset (info_ptr - 1 - reader->buffer),
+                                reader->cu->per_cu->is_dwz);
+      addrmap_set_empty (m_die_range_map, start, end, (void *) parent_entry);
+    }
+
+  return info_ptr;
+}
+
+const gdb_byte *
+cooked_indexer::index_dies (cutu_reader *reader,
+                           const gdb_byte *info_ptr,
+                           const cooked_index_entry *parent_entry,
+                           bool fully)
+{
+  const gdb_byte *end_ptr = info_ptr + reader->cu->header.get_length ();
+
+  while (info_ptr < end_ptr)
+    {
+      sect_offset this_die = (sect_offset) (info_ptr - reader->buffer);
+      unsigned int bytes_read;
+      const abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr,
+                                                  &bytes_read);
+      info_ptr += bytes_read;
+      if (abbrev == nullptr)
+       break;
+
+      if (abbrev->tag == DW_TAG_imported_unit)
+       {
+         info_ptr = index_imported_unit (reader, info_ptr, abbrev);
+         continue;
+       }
+
+      if (!abbrev->interesting)
+       {
+         info_ptr = skip_one_die (reader, info_ptr, abbrev, !fully);
+         if (fully && abbrev->has_children)
+           info_ptr = index_dies (reader, info_ptr, parent_entry, fully);
+         continue;
+       }
+
+      const char *name = nullptr;
+      const char *linkage_name = nullptr;
+      CORE_ADDR defer = 0;
+      cooked_index_flag flags = IS_STATIC;
+      sect_offset sibling {};
+      const cooked_index_entry *this_parent_entry = parent_entry;
+      info_ptr = scan_attributes (reader->cu->per_cu, reader, info_ptr,
+                                 info_ptr, abbrev, &name, &linkage_name,
+                                 &flags, &sibling, &this_parent_entry,
+                                 &defer, false);
+
+      if (abbrev->tag == DW_TAG_namespace
+         && m_language == language_cplus
+         && strcmp (name, "::") == 0)
+       {
+         /* GCC 4.0 and 4.1 had a bug (PR c++/28460) where they
+            generated bogus DW_TAG_namespace DIEs with a name of "::"
+            for the global namespace.  Work around this problem
+            here.  */
+         name = nullptr;
+       }
+
+      const cooked_index_entry *this_entry = nullptr;
+      if (name != nullptr)
+       {
+         if (defer != 0)
+           m_deferred_entries.push_back ({
+               this_die, name, defer, abbrev->tag, flags
+             });
+         else
+           this_entry = m_index_storage->add (this_die, abbrev->tag, flags,
+                                              name, this_parent_entry,
+                                              m_per_cu);
+       }
+
+      if (linkage_name != nullptr)
+       {
+         /* We only want this to be "main" if it has a linkage name
+            but not an ordinary name.  */
+         if (name != nullptr)
+           flags = flags & ~IS_MAIN;
+         m_index_storage->add (this_die, abbrev->tag, flags | IS_LINKAGE,
+                               linkage_name, nullptr, m_per_cu);
+       }
+
+      if (abbrev->has_children)
+       {
+         switch (abbrev->tag)
+           {
+           case DW_TAG_class_type:
+           case DW_TAG_interface_type:
+           case DW_TAG_structure_type:
+           case DW_TAG_union_type:
+             if (m_language != language_c && this_entry != nullptr)
+               {
+                 info_ptr = recurse (reader, info_ptr, this_entry, fully);
+                 continue;
+               }
+             break;
+
+           case DW_TAG_enumeration_type:
+             /* We need to recurse even for an anonymous enumeration.
+                Which scope we record as the parent scope depends on
+                whether we're reading an "enum class".  If so, we use
+                the enum itself as the parent, yielding names like
+                "enum_class::enumerator"; otherwise we inject the
+                names into our own parent scope.  */
+             info_ptr = recurse (reader, info_ptr,
+                                 ((flags & IS_ENUM_CLASS) == 0)
+                                 ? parent_entry
+                                 : this_entry,
+                                 fully);
+             continue;
 
-  if (high_pc_relative)
-    highpc += lowpc;
+           case DW_TAG_module:
+             if (this_entry == nullptr)
+               break;
+             /* FALLTHROUGH */
+           case DW_TAG_namespace:
+             /* We don't check THIS_ENTRY for a namespace, to handle
+                the ancient G++ workaround pointed out above.  */
+             info_ptr = recurse (reader, info_ptr, this_entry, fully);
+             continue;
 
-  if (has_low_pc_attr && has_high_pc_attr)
-    {
-      /* When using the GNU linker, .gnu.linkonce. sections are used to
-        eliminate duplicate copies of functions and vtables and such.
-        The linker will arbitrarily choose one and discard the others.
-        The AT_*_pc values for such functions refer to local labels in
-        these sections.  If the section from that file was discarded, the
-        labels are not in the output, so the relocs get a value of 0.
-        If this is a discarded function, mark the pc bounds as invalid,
-        so that GDB will ignore it.  */
-      if (lowpc == 0 && !per_objfile->per_bfd->has_section_at_zero)
-       {
-         struct objfile *objfile = per_objfile->objfile;
-         struct gdbarch *gdbarch = objfile->arch ();
+           case DW_TAG_subprogram:
+             if ((m_language == language_fortran
+                  || m_language == language_ada)
+                 && this_entry != nullptr)
+               {
+                 info_ptr = recurse (reader, info_ptr, this_entry, true);
+                 continue;
+               }
+             break;
+           }
 
-         complaint (_("DW_AT_low_pc %s is zero "
-                      "for DIE at %s [in module %s]"),
-                    paddress (gdbarch, lowpc),
-                    sect_offset_str (sect_off),
-                    objfile_name (objfile));
-       }
-      /* dwarf2_get_pc_bounds has also the strict low < high requirement.  */
-      else if (lowpc >= highpc)
-       {
-         struct objfile *objfile = per_objfile->objfile;
-         struct gdbarch *gdbarch = objfile->arch ();
+         if (sibling != sect_offset (0))
+           {
+             const gdb_byte *sibling_ptr
+               = reader->buffer + to_underlying (sibling);
 
-         complaint (_("DW_AT_low_pc %s is not < DW_AT_high_pc %s "
-                      "for DIE at %s [in module %s]"),
-                    paddress (gdbarch, lowpc),
-                    paddress (gdbarch, highpc),
-                    sect_offset_str (sect_off),
-                    objfile_name (objfile));
+             if (sibling_ptr < info_ptr)
+               complaint (_("DW_AT_sibling points backwards"));
+             else if (sibling_ptr > reader->buffer_end)
+               reader->die_section->overflow_complaint ();
+             else
+               info_ptr = sibling_ptr;
+           }
+         else
+           info_ptr = skip_children (reader, info_ptr);
        }
-      else
-       has_pc_info = 1;
     }
 
   return info_ptr;
 }
 
-/* Find a cached partial DIE at OFFSET in CU.  */
-
-struct partial_die_info *
-dwarf2_cu::find_partial_die (sect_offset sect_off)
+void
+cooked_indexer::make_index (cutu_reader *reader)
 {
-  struct partial_die_info *lookup_die = NULL;
-  struct partial_die_info part_die (sect_off);
-
-  lookup_die = ((struct partial_die_info *)
-               htab_find_with_hash (partial_dies, &part_die,
-                                    to_underlying (sect_off)));
+  check_bounds (reader);
+  find_file_and_directory (reader->comp_unit_die, reader->cu);
+  if (!reader->comp_unit_die->has_children)
+    return;
+  index_dies (reader, reader->info_ptr, nullptr, false);
 
-  return lookup_die;
+  for (const auto &entry : m_deferred_entries)
+    {
+      CORE_ADDR key = form_addr (entry.die_offset, m_per_cu->is_dwz);
+      cooked_index_entry *parent
+       = (cooked_index_entry *) addrmap_find (m_die_range_map, key);
+      m_index_storage->add (entry.die_offset, entry.tag, entry.flags,
+                           entry.name, parent, m_per_cu);
+    }
 }
 
-/* Find a partial DIE at OFFSET, which may or may not be in CU,
-   except in the case of .debug_types DIEs which do not reference
-   outside their CU (they do however referencing other types via
-   DW_FORM_ref_sig8).  */
+/* An implementation of quick_symbol_functions for the cooked DWARF
+   index.  */
 
-static const struct cu_partial_die_info
-find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu)
+struct cooked_index_functions : public dwarf2_base_index_functions
 {
-  dwarf2_per_objfile *per_objfile = cu->per_objfile;
-  struct objfile *objfile = per_objfile->objfile;
-  struct partial_die_info *pd = NULL;
+  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;
 
-  if (offset_in_dwz == cu->per_cu->is_dwz
-      && cu->header.offset_in_cu_p (sect_off))
-    {
-      pd = cu->find_partial_die (sect_off);
-      if (pd != NULL)
-       return { cu, pd };
-      /* We missed recording what we needed.
-        Load all dies and try again.  */
-    }
-  else
-    {
-      /* TUs don't reference other CUs/TUs (except via type signatures).  */
-      if (cu->per_cu->is_debug_types)
-       {
-         error (_("Dwarf Error: Type Unit at offset %s contains"
-                  " external reference to offset %s [in module %s].\n"),
-                sect_offset_str (cu->header.sect_off), sect_offset_str (sect_off),
-                bfd_get_filename (objfile->obfd));
-       }
-      dwarf2_per_cu_data *per_cu
-       = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
-                                           per_objfile->per_bfd);
+  struct compunit_symtab *find_compunit_symtab_by_address
+    (struct objfile *objfile, CORE_ADDR address) override;
 
-      cu = per_objfile->get_cu (per_cu);
-      if (cu == NULL || cu->partial_dies == NULL)
-       load_partial_comp_unit (per_cu, per_objfile, nullptr);
+  void dump (struct objfile *objfile) override
+  {
+    gdb_printf ("Cooked index in use\n");
+  }
 
-      cu = per_objfile->get_cu (per_cu);
+  void expand_matching_symbols
+    (struct objfile *,
+     const lookup_name_info &lookup_name,
+     domain_enum domain,
+     int global,
+     symbol_compare_ftype *ordered_compare) override;
 
-      cu->last_used = 0;
-      pd = cu->find_partial_die (sect_off);
-    }
+  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;
 
-  /* If we didn't find it, and not all dies have been loaded,
-     load them all and try again.  */
+  bool can_lazily_read_symbols () override
+  {
+    return true;
+  }
 
-  if (pd == NULL && cu->load_all_dies == 0)
-    {
-      cu->load_all_dies = 1;
+  void read_partial_symbols (struct objfile *objfile) override
+  {
+    if (dwarf2_has_info (objfile, nullptr))
+      dwarf2_build_psymtabs (objfile, true);
+  }
+};
 
-      /* 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
-        replace its DIEs with the ones we read in.  Instead, we leave those
-        DIEs alone (which can still be in use, e.g. in scan_partial_symbols),
-        and clobber THIS_CU->cu->partial_dies with the hash table for the new
-        set.  */
-      load_partial_comp_unit (cu->per_cu, per_objfile, cu);
+struct compunit_symtab *
+cooked_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)
+{
+  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+  if (per_objfile->per_bfd->index_table == nullptr)
+    return nullptr;
 
-      pd = cu->find_partial_die (sect_off);
-    }
+  CORE_ADDR baseaddr = objfile->text_section_offset ();
+  cooked_index_vector *table
+    = (static_cast<cooked_index_vector *>
+       (per_objfile->per_bfd->index_table.get ()));
+  dwarf2_per_cu_data *per_cu = table->lookup (pc - baseaddr);
+  if (per_cu == nullptr)
+    return nullptr;
 
-  if (pd == NULL)
-    error (_("Dwarf Error: Cannot find DIE at %s [from module %s]\n"),
-                   sect_offset_str (sect_off), bfd_get_filename (objfile->obfd));
-  return { cu, pd };
-}
+  if (warn_if_readin && per_objfile->symtab_set_p (per_cu))
+    warning (_("(Internal error: pc %s in read in CU, but not in symtab.)"),
+            paddress (objfile->arch (), pc));
 
-/* See if we can figure out if the class lives in a namespace.  We do
-   this by looking for a member function; its demangled name will
-   contain namespace info, if there is any.  */
+  compunit_symtab *result = (recursively_find_pc_sect_compunit_symtab
+                            (dw2_instantiate_symtab (per_cu, per_objfile,
+                                                     false),
+                             pc));
+  gdb_assert (result != nullptr);
+  return result;
+}
 
-static void
-guess_partial_die_structure_name (struct partial_die_info *struct_pdi,
-                                 struct dwarf2_cu *cu)
+struct compunit_symtab *
+cooked_index_functions::find_compunit_symtab_by_address
+     (struct objfile *objfile, CORE_ADDR address)
 {
-  /* NOTE: carlton/2003-10-07: Getting the info this way changes
-     what template types look like, because the demangler
-     frequently doesn't give the same name as the debug info.  We
-     could fix this by only using the demangled name to get the
-     prefix (but see comment in read_structure_type).  */
+  if (objfile->sect_index_data == -1)
+    return nullptr;
 
-  struct partial_die_info *real_pdi;
-  struct partial_die_info *child_pdi;
+  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+  if (per_objfile->per_bfd->index_table == nullptr)
+    return nullptr;
 
-  /* If this DIE (this DIE's specification, if any) has a parent, then
-     we should not do this.  We'll prepend the parent's fully qualified
-     name when we create the partial symbol.  */
+  CORE_ADDR baseaddr = objfile->data_section_offset ();
+  cooked_index_vector *table
+    = (static_cast<cooked_index_vector *>
+       (per_objfile->per_bfd->index_table.get ()));
+  dwarf2_per_cu_data *per_cu = table->lookup (address - baseaddr);
+  if (per_cu == nullptr)
+    return nullptr;
 
-  real_pdi = struct_pdi;
-  while (real_pdi->has_specification)
-    {
-      auto res = find_partial_die (real_pdi->spec_offset,
-                                  real_pdi->spec_is_dwz, cu);
-      real_pdi = res.pdi;
-      cu = res.cu;
-    }
+  return dw2_instantiate_symtab (per_cu, per_objfile, false);
+}
 
-  if (real_pdi->die_parent != NULL)
+void
+cooked_index_functions::expand_matching_symbols
+     (struct objfile *objfile,
+      const lookup_name_info &lookup_name,
+      domain_enum domain,
+      int global,
+      symbol_compare_ftype *ordered_compare)
+{
+  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+  if (per_objfile->per_bfd->index_table == nullptr)
     return;
+  const block_search_flags search_flags = (global
+                                          ? SEARCH_GLOBAL_BLOCK
+                                          : SEARCH_STATIC_BLOCK);
+  const language_defn *lang = language_def (language_ada);
+  symbol_name_matcher_ftype *name_match
+    = lang->get_symbol_name_matcher (lookup_name);
+
+  cooked_index_vector *table
+    = (static_cast<cooked_index_vector *>
+       (per_objfile->per_bfd->index_table.get ()));
+  for (const cooked_index_entry *entry : table->all_entries ())
+    {
+      if (entry->parent_entry != nullptr)
+       continue;
 
-  for (child_pdi = struct_pdi->die_child;
-       child_pdi != NULL;
-       child_pdi = child_pdi->die_sibling)
-    {
-      if (child_pdi->tag == DW_TAG_subprogram
-         && child_pdi->linkage_name != NULL)
-       {
-         gdb::unique_xmalloc_ptr<char> actual_class_name
-           (cu->language_defn->class_name_from_physname
-            (child_pdi->linkage_name));
-         if (actual_class_name != NULL)
-           {
-             struct objfile *objfile = cu->per_objfile->objfile;
-             struct_pdi->raw_name = objfile->intern (actual_class_name.get ());
-             struct_pdi->canonical_name = 1;
-           }
-         break;
-       }
-    }
-}
-
-/* Return true if a DIE with TAG may have the DW_AT_const_value
-   attribute.  */
+      if (!entry->matches (search_flags)
+         || !entry->matches (domain))
+       continue;
 
-static bool
-can_have_DW_AT_const_value_p (enum dwarf_tag tag)
-{
-  switch (tag)
-    {
-    case DW_TAG_constant:
-    case DW_TAG_enumerator:
-    case DW_TAG_formal_parameter:
-    case DW_TAG_template_value_param:
-    case DW_TAG_variable:
-      return true;
+      if (name_match (entry->canonical, lookup_name, nullptr))
+       dw2_instantiate_symtab (entry->per_cu, per_objfile, false);
     }
-
-  return false;
 }
 
-void
-partial_die_info::fixup (struct dwarf2_cu *cu)
+bool
+cooked_index_functions::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)
 {
-  /* Once we've fixed up a die, there's no point in doing so again.
-     This also avoids a memory leak if we were to call
-     guess_partial_die_structure_name multiple times.  */
-  if (fixup_called)
-    return;
+  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+  if (per_objfile->per_bfd->index_table == nullptr)
+    return true;
 
-  /* If we found a reference attribute and the DIE has no name, try
-     to find a name in the referred to DIE.  */
+  dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
 
-  if (raw_name == NULL && has_specification)
+  /* This invariant is documented in quick-functions.h.  */
+  gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr);
+  if (lookup_name == nullptr)
     {
-      struct partial_die_info *spec_die;
-
-      auto res = find_partial_die (spec_offset, spec_is_dwz, cu);
-      spec_die = res.pdi;
-      cu = res.cu;
-
-      spec_die->fixup (cu);
-
-      if (spec_die->raw_name)
+      for (dwarf2_per_cu_data *per_cu
+            : all_comp_units_range (per_objfile->per_bfd))
        {
-         raw_name = spec_die->raw_name;
-         canonical_name = spec_die->canonical_name;
+         QUIT;
 
-         /* Copy DW_AT_external attribute if it is set.  */
-         if (spec_die->is_external)
-           is_external = spec_die->is_external;
+         if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
+                                               file_matcher,
+                                               expansion_notify))
+           return false;
        }
+      return true;
     }
 
-  if (!has_const_value && has_specification
-      && can_have_DW_AT_const_value_p (tag))
-    {
-      struct partial_die_info *spec_die;
+  lookup_name_info lookup_name_without_params
+    = lookup_name->make_ignore_params ();
+  bool completing = lookup_name->completion_mode ();
 
-      auto res = find_partial_die (spec_offset, spec_is_dwz, cu);
-      spec_die = res.pdi;
-      cu = res.cu;
+  /* Unique styles of language splitting.  */
+  static const enum language unique_styles[] =
+  {
+    /* No splitting is also a style.  */
+    language_c,
+    /* This includes Rust.  */
+    language_cplus,
+    /* This includes Go.  */
+    language_d,
+    language_ada
+  };
 
-      spec_die->fixup (cu);
+  cooked_index_vector *table
+    = (static_cast<cooked_index_vector *>
+       (per_objfile->per_bfd->index_table.get ()));
+  for (enum language lang : unique_styles)
+    {
+      std::vector<gdb::string_view> name_vec
+       = lookup_name_without_params.split_name (lang);
 
-      if (spec_die->has_const_value)
+      for (const cooked_index_entry *entry : table->find (name_vec.back (),
+                                                         completing))
        {
-         /* Copy DW_AT_const_value attribute if it is set.  */
-         has_const_value = spec_die->has_const_value;
-       }
-    }
+         /* No need to consider symbols from expanded CUs.  */
+         if (per_objfile->symtab_set_p (entry->per_cu))
+           continue;
 
-  /* Set default names for some unnamed DIEs.  */
+         /* If file-matching was done, we don't need to consider
+            symbols from unmarked CUs.  */
+         if (file_matcher != nullptr && !entry->per_cu->mark)
+           continue;
 
-  if (raw_name == NULL && tag == DW_TAG_namespace)
-    {
-      raw_name = CP_ANONYMOUS_NAMESPACE_STR;
-      canonical_name = 1;
-    }
+         /* See if the symbol matches the type filter.  */
+         if (!entry->matches (search_flags)
+             || !entry->matches (domain)
+             || !entry->matches (kind))
+           continue;
 
-  /* If there is no parent die to provide a namespace, and there are
-     children, see if we can determine the namespace from their linkage
-     name.  */
-  if (cu->per_cu->lang == language_cplus
-      && !cu->per_objfile->per_bfd->types.empty ()
-      && die_parent == NULL
-      && has_children
-      && (tag == DW_TAG_class_type
-         || tag == DW_TAG_structure_type
-         || tag == DW_TAG_union_type))
-    guess_partial_die_structure_name (this, cu);
-
-  /* GCC might emit a nameless struct or union that has a linkage
-     name.  See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47510.  */
-  if (raw_name == NULL
-      && (tag == DW_TAG_class_type
-         || tag == DW_TAG_interface_type
-         || tag == DW_TAG_structure_type
-         || tag == DW_TAG_union_type)
-      && linkage_name != NULL)
-    {
-      gdb::unique_xmalloc_ptr<char> demangled
-       (gdb_demangle (linkage_name, DMGL_TYPES));
-      if (demangled != nullptr)
-       {
-         const char *base;
-
-         /* Strip any leading namespaces/classes, keep only the base name.
-            DW_AT_name for named DIEs does not contain the prefixes.  */
-         base = strrchr (demangled.get (), ':');
-         if (base && base > demangled.get () && base[-1] == ':')
-           base++;
+         /* We've found the base name of the symbol; now walk its
+            parentage chain, ensuring that each component
+            matches.  */
+         bool found = true;
+
+         const cooked_index_entry *parent = entry->parent_entry;
+         for (int i = name_vec.size () - 1; i > 0; --i)
+           {
+             /* If we ran out of entries, or if this segment doesn't
+                match, this did not match.  */
+             if (parent == nullptr
+                 || strncmp (parent->name, name_vec[i - 1].data (),
+                             name_vec[i - 1].length ()) != 0)
+               {
+                 found = false;
+                 break;
+               }
+
+             parent = parent->parent_entry;
+           }
+
+         if (!found)
+           continue;
+
+         /* Might have been looking for "a::b" and found
+            "x::a::b".  */
+         if (symbol_matcher == nullptr)
+           {
+             symbol_name_match_type match_type
+               = lookup_name_without_params.match_type ();
+             if ((match_type == symbol_name_match_type::FULL
+                  || (lang != language_ada
+                      && match_type == symbol_name_match_type::EXPRESSION))
+                 && parent != nullptr)
+               continue;
+           }
          else
-           base = demangled.get ();
+           {
+             auto_obstack temp_storage;
+             const char *full_name = entry->full_name (&temp_storage);
+             if (!symbol_matcher (full_name))
+               continue;
+           }
 
-         struct objfile *objfile = cu->per_objfile->objfile;
-         raw_name = objfile->intern (base);
-         canonical_name = 1;
+         if (!dw2_expand_symtabs_matching_one (entry->per_cu, per_objfile,
+                                               file_matcher,
+                                               expansion_notify))
+           return false;
        }
     }
 
-  fixup_called = 1;
+  return true;
+}
+
+/* Return a new cooked_index_functions object.  */
+
+static quick_symbol_functions_up
+make_cooked_index_funcs ()
+{
+  return quick_symbol_functions_up (new cooked_index_functions);
+}
+
+quick_symbol_functions_up
+cooked_index_vector::make_quick_functions () const
+{
+  return make_cooked_index_funcs ();
 }
 
+\f
+
 /* Read the .debug_loclists or .debug_rnglists header (they are the same format)
    contents from the given SECTION in the HEADER.
 
@@ -20722,14 +19696,14 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu)
 static const char *
 compute_include_file_name (const struct line_header *lh, const file_entry &fe,
                           const file_and_directory &cu_info,
-                          gdb::unique_xmalloc_ptr<char> *name_holder)
+                          std::string &name_holder)
 {
   const char *include_name = fe.name;
   const char *include_name_to_compare = include_name;
 
   const char *dir_name = fe.include_dir (lh);
 
-  gdb::unique_xmalloc_ptr<char> hold_compare;
+  std::string hold_compare;
   if (!IS_ABSOLUTE_PATH (include_name)
       && (dir_name != nullptr || cu_info.get_comp_dir () != nullptr))
     {
@@ -20756,27 +19730,24 @@ compute_include_file_name (const struct line_header *lh, const file_entry &fe,
 
       if (dir_name != NULL)
        {
-         name_holder->reset (concat (dir_name, SLASH_STRING,
-                                     include_name, (char *) NULL));
-         include_name = name_holder->get ();
+         name_holder = path_join (dir_name, include_name);
+         include_name = name_holder.c_str ();
          include_name_to_compare = include_name;
        }
       if (!IS_ABSOLUTE_PATH (include_name)
          && cu_info.get_comp_dir () != nullptr)
        {
-         hold_compare.reset (concat (cu_info.get_comp_dir (), SLASH_STRING,
-                                     include_name, (char *) NULL));
-         include_name_to_compare = hold_compare.get ();
+         hold_compare = path_join (cu_info.get_comp_dir (), include_name);
+         include_name_to_compare = hold_compare.c_str ();
        }
     }
 
-  gdb::unique_xmalloc_ptr<char> copied_name;
+  std::string copied_name;
   const char *cu_filename = cu_info.get_name ();
   if (!IS_ABSOLUTE_PATH (cu_filename) && cu_info.get_comp_dir () != nullptr)
     {
-      copied_name.reset (concat (cu_info.get_comp_dir (), SLASH_STRING,
-                                cu_filename, (char *) NULL));
-      cu_filename = copied_name.get ();
+      copied_name = path_join (cu_info.get_comp_dir (), cu_filename);
+      cu_filename = copied_name.c_str ();
     }
 
   if (FILENAME_CMP (include_name_to_compare, cu_filename) == 0)
@@ -20791,8 +19762,7 @@ class lnp_state_machine
 public:
   /* Initialize a machine state for the start of a line number
      program.  */
-  lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch, line_header *lh,
-                    bool record_lines_p);
+  lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch, line_header *lh);
 
   file_entry *current_file ()
   {
@@ -20843,7 +19813,7 @@ public:
   /* Handle DW_LNS_negate_stmt.  */
   void handle_negate_stmt ()
   {
-    m_is_stmt = !m_is_stmt;
+    m_flags ^= LEF_IS_STMT;
   }
 
   /* Handle DW_LNS_const_add_pc.  */
@@ -20861,6 +19831,7 @@ public:
   {
     record_line (false);
     m_discriminator = 0;
+    m_flags &= ~LEF_PROLOGUE_END;
   }
 
   /* Handle DW_LNE_end_sequence.  */
@@ -20869,6 +19840,12 @@ public:
     m_currently_recording_lines = true;
   }
 
+  /* Handle DW_LNS_set_prologue_end.  */
+  void handle_set_prologue_end ()
+  {
+    m_flags |= LEF_PROLOGUE_END;
+  }
+
 private:
   /* Advance the line by LINE_DELTA.  */
   void advance_line (int line_delta)
@@ -20883,11 +19860,6 @@ private:
 
   gdbarch *m_gdbarch;
 
-  /* True if we're recording lines.
-     Otherwise we're building partial symtabs and are just interested in
-     finding include files mentioned by the line number program.  */
-  bool m_record_lines_p;
-
   /* The line number header.  */
   line_header *m_line_header;
 
@@ -20902,7 +19874,7 @@ private:
   /* These are initialized in the constructor.  */
 
   CORE_ADDR m_address;
-  bool m_is_stmt;
+  linetable_entry_flags m_flags;
   unsigned int m_discriminator;
 
   /* Additional bits of state we need to track.  */
@@ -20917,9 +19889,9 @@ private:
   CORE_ADDR m_last_address;
 
   /* Set to true when a previous line at the same address (using
-     m_last_address) had m_is_stmt true.  This is reset to false when a
-     line entry at a new address (m_address different to m_last_address) is
-     processed.  */
+     m_last_address) had LEF_IS_STMT set in m_flags.  This is reset to false
+     when a line entry at a new address (m_address different to
+     m_last_address) is processed.  */
   bool m_stmt_at_address = false;
 
   /* When true, record the lines we decode.  */
@@ -20960,6 +19932,7 @@ lnp_state_machine::handle_special_opcode (unsigned char op_code)
   advance_line (line_delta);
   record_line (false);
   m_discriminator = 0;
+  m_flags &= ~LEF_PROLOGUE_END;
 }
 
 void
@@ -20970,7 +19943,7 @@ lnp_state_machine::handle_set_file (file_name_index file)
   const file_entry *fe = current_file ();
   if (fe == NULL)
     dwarf2_debug_line_missing_file_complaint ();
-  else if (m_record_lines_p)
+  else
     {
       const char *dir = fe->include_dir (m_line_header);
 
@@ -21049,21 +20022,22 @@ dwarf_record_line_p (struct dwarf2_cu *cu,
 
 static void
 dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
-                    unsigned int line, CORE_ADDR address, bool is_stmt,
+                    unsigned int line, CORE_ADDR address,
+                    linetable_entry_flags flags,
                     struct dwarf2_cu *cu)
 {
   CORE_ADDR addr = gdbarch_addr_bits_remove (gdbarch, address);
 
   if (dwarf_line_debug)
     {
-      fprintf_unfiltered (gdb_stdlog,
-                         "Recording line %u, file %s, address %s\n",
-                         line, lbasename (subfile->name),
-                         paddress (gdbarch, address));
+      gdb_printf (gdb_stdlog,
+                 "Recording line %u, file %s, address %s\n",
+                 line, lbasename (subfile->name.c_str ()),
+                 paddress (gdbarch, address));
     }
 
   if (cu != nullptr)
-    cu->get_builder ()->record_line (subfile, line, addr, is_stmt);
+    cu->get_builder ()->record_line (subfile, line, addr, flags);
 }
 
 /* Subroutine of dwarf_decode_lines_1 to simplify it.
@@ -21080,13 +20054,13 @@ dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile,
 
   if (dwarf_line_debug)
     {
-      fprintf_unfiltered (gdb_stdlog,
-                         "Finishing current line, file %s, address %s\n",
-                         lbasename (subfile->name),
-                         paddress (gdbarch, address));
+      gdb_printf (gdb_stdlog,
+                 "Finishing current line, file %s, address %s\n",
+                 lbasename (subfile->name.c_str ()),
+                 paddress (gdbarch, address));
     }
 
-  dwarf_record_line_1 (gdbarch, subfile, 0, address, true, cu);
+  dwarf_record_line_1 (gdbarch, subfile, 0, address, LEF_IS_STMT, cu);
 }
 
 void
@@ -21094,13 +20068,15 @@ lnp_state_machine::record_line (bool end_sequence)
 {
   if (dwarf_line_debug)
     {
-      fprintf_unfiltered (gdb_stdlog,
-                         "Processing actual line %u: file %u,"
-                         " address %s, is_stmt %u, discrim %u%s\n",
-                         m_line, m_file,
-                         paddress (m_gdbarch, m_address),
-                         m_is_stmt, m_discriminator,
-                         (end_sequence ? "\t(end sequence)" : ""));
+      gdb_printf (gdb_stdlog,
+                 "Processing actual line %u: file %u,"
+                 " address %s, is_stmt %u, prologue_end %u, discrim %u%s\n",
+                 m_line, m_file,
+                 paddress (m_gdbarch, m_address),
+                 (m_flags & LEF_IS_STMT) != 0,
+                 (m_flags & LEF_PROLOGUE_END) != 0,
+                 m_discriminator,
+                 (end_sequence ? "\t(end sequence)" : ""));
     }
 
   file_entry *fe = current_file ();
@@ -21112,73 +20088,71 @@ lnp_state_machine::record_line (bool end_sequence)
      previous version of the code.  */
   else if (m_op_index == 0 || end_sequence)
     {
-      fe->included_p = true;
-      if (m_record_lines_p)
-       {
-         /* When we switch files we insert an end maker in the first file,
-            switch to the second file and add a new line entry.  The
-            problem is that the end marker inserted in the first file will
-            discard any previous line entries at the same address.  If the
-            line entries in the first file are marked as is-stmt, while
-            the new line in the second file is non-stmt, then this means
-            the end marker will discard is-stmt lines so we can have a
-            non-stmt line.  This means that there are less addresses at
-            which the user can insert a breakpoint.
-
-            To improve this we track the last address in m_last_address,
-            and whether we have seen an is-stmt at this address.  Then
-            when switching files, if we have seen a stmt at the current
-            address, and we are switching to create a non-stmt line, then
-            discard the new line.  */
-         bool file_changed
-           = m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
-         bool ignore_this_line
-          = ((file_changed && !end_sequence && m_last_address == m_address
-              && !m_is_stmt && m_stmt_at_address)
-             || (!end_sequence && m_line == 0));
-
-         if ((file_changed && !ignore_this_line) || end_sequence)
-           {
-             dwarf_finish_line (m_gdbarch, m_last_subfile, m_address,
-                                m_currently_recording_lines ? m_cu : nullptr);
-           }
-
-         if (!end_sequence && !ignore_this_line)
+      /* When we switch files we insert an end maker in the first file,
+        switch to the second file and add a new line entry.  The
+        problem is that the end marker inserted in the first file will
+        discard any previous line entries at the same address.  If the
+        line entries in the first file are marked as is-stmt, while
+        the new line in the second file is non-stmt, then this means
+        the end marker will discard is-stmt lines so we can have a
+        non-stmt line.  This means that there are less addresses at
+        which the user can insert a breakpoint.
+
+        To improve this we track the last address in m_last_address,
+        and whether we have seen an is-stmt at this address.  Then
+        when switching files, if we have seen a stmt at the current
+        address, and we are switching to create a non-stmt line, then
+        discard the new line.  */
+      bool file_changed
+       = m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
+      bool ignore_this_line
+       = ((file_changed && !end_sequence && m_last_address == m_address
+           && ((m_flags & LEF_IS_STMT) == 0)
+           && m_stmt_at_address)
+          || (!end_sequence && m_line == 0));
+
+      if ((file_changed && !ignore_this_line) || end_sequence)
+       {
+         dwarf_finish_line (m_gdbarch, m_last_subfile, m_address,
+                            m_currently_recording_lines ? m_cu : nullptr);
+       }
+
+      if (!end_sequence && !ignore_this_line)
+       {
+         linetable_entry_flags lte_flags = m_flags;
+         if (producer_is_codewarrior (m_cu))
+           lte_flags |= LEF_IS_STMT;
+
+         if (dwarf_record_line_p (m_cu, m_line, m_last_line,
+                                  m_line_has_non_zero_discriminator,
+                                  m_last_subfile))
            {
-             bool is_stmt = producer_is_codewarrior (m_cu) || m_is_stmt;
-
-             if (dwarf_record_line_p (m_cu, m_line, m_last_line,
-                                      m_line_has_non_zero_discriminator,
-                                      m_last_subfile))
-               {
-                 buildsym_compunit *builder = m_cu->get_builder ();
-                 dwarf_record_line_1 (m_gdbarch,
-                                      builder->get_current_subfile (),
-                                      m_line, m_address, is_stmt,
-                                      m_currently_recording_lines ? m_cu : nullptr);
-               }
-             m_last_subfile = m_cu->get_builder ()->get_current_subfile ();
-             m_last_line = m_line;
+             buildsym_compunit *builder = m_cu->get_builder ();
+             dwarf_record_line_1 (m_gdbarch,
+                                  builder->get_current_subfile (),
+                                  m_line, m_address, lte_flags,
+                                  m_currently_recording_lines ? m_cu : nullptr);
            }
+         m_last_subfile = m_cu->get_builder ()->get_current_subfile ();
+         m_last_line = m_line;
        }
     }
 
-  /* Track whether we have seen any m_is_stmt true at m_address in case we
+  /* Track whether we have seen any IS_STMT true at m_address in case we
      have multiple line table entries all at m_address.  */
   if (m_last_address != m_address)
     {
       m_stmt_at_address = false;
       m_last_address = m_address;
     }
-  m_stmt_at_address |= m_is_stmt;
+  m_stmt_at_address |= (m_flags & LEF_IS_STMT) != 0;
 }
 
 lnp_state_machine::lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch,
-                                     line_header *lh, bool record_lines_p)
+                                     line_header *lh)
 {
   m_cu = cu;
   m_gdbarch = arch;
-  m_record_lines_p = record_lines_p;
   m_line_header = lh;
 
   m_currently_recording_lines = true;
@@ -21188,7 +20162,9 @@ lnp_state_machine::lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch,
      and also record it in case it needs it.  This is currently used by MIPS
      code, cf. `mips_adjust_dwarf2_line'.  */
   m_address = gdbarch_adjust_dwarf2_line (arch, 0, 0);
-  m_is_stmt = lh->default_is_stmt;
+  m_flags = 0;
+  if (lh->default_is_stmt)
+    m_flags |= LEF_IS_STMT;
   m_discriminator = 0;
 
   m_last_address = m_address;
@@ -21223,13 +20199,11 @@ lnp_state_machine::check_line_address (struct dwarf2_cu *cu,
 }
 
 /* Subroutine of dwarf_decode_lines to simplify it.
-   Process the line number information in LH.
-   If DECODE_FOR_PST_P is non-zero, all we do is process the line number
-   program in order to set included_p for every referenced header.  */
+   Process the line number information in LH.  */
 
 static void
 dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
-                     const int decode_for_pst_p, CORE_ADDR lowpc)
+                     CORE_ADDR lowpc)
 {
   const gdb_byte *line_ptr, *extended_end;
   const gdb_byte *line_end;
@@ -21239,10 +20213,6 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
   struct objfile *objfile = cu->per_objfile->objfile;
   bfd *abfd = objfile->obfd;
   struct gdbarch *gdbarch = objfile->arch ();
-  /* True if we're recording line info (as opposed to building partial
-     symtabs and just interested in finding include files mentioned by
-     the line number program).  */
-  bool record_lines_p = !decode_for_pst_p;
 
   baseaddr = objfile->text_section_offset ();
 
@@ -21254,18 +20224,15 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
     {
       /* The DWARF line number program state machine.  Reset the state
         machine at the start of each sequence.  */
-      lnp_state_machine state_machine (cu, gdbarch, lh, record_lines_p);
+      lnp_state_machine state_machine (cu, gdbarch, lh);
       bool end_sequence = false;
 
-      if (record_lines_p)
-       {
-         /* Start a subfile for the current file of the state
-            machine.  */
-         const file_entry *fe = state_machine.current_file ();
+      /* Start a subfile for the current file of the state
+        machine.  */
+      const file_entry *fe = state_machine.current_file ();
 
-         if (fe != NULL)
-           dwarf2_start_subfile (cu, fe->name, fe->include_dir (lh));
-       }
+      if (fe != NULL)
+       dwarf2_start_subfile (cu, fe->name, fe->include_dir (lh));
 
       /* Decode the table.  */
       while (line_ptr < line_end && !end_sequence)
@@ -21416,6 +20383,9 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
                state_machine.handle_fixed_advance_pc (addr_adj);
              }
              break;
+           case DW_LNS_set_prologue_end:
+             state_machine.handle_set_prologue_end ();
+             break;
            default:
              {
                /* Unknown standard opcode, ignore it.  */
@@ -21443,13 +20413,6 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
    structure and CU.  The actual information extracted and the type
    of structures created from the LNP depends on the value of PST.
 
-   1. If PST is NULL, then this procedure uses the data from the program
-      to create all necessary symbol tables, and their linetables.
-
-   2. If PST is not NULL, this procedure reads the program to determine
-      the list of files included by the unit represented by PST, and
-      builds all the associated partial symbol tables.
-
    FND holds the CU file name and directory, if known.
    It is used for relative paths in the line table.
 
@@ -21467,52 +20430,28 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
    table is read in.  */
 
 static void
-dwarf_decode_lines (struct line_header *lh, const file_and_directory &fnd,
-                   struct dwarf2_cu *cu, dwarf2_psymtab *pst,
+dwarf_decode_lines (struct line_header *lh, struct dwarf2_cu *cu,
                    CORE_ADDR lowpc, int decode_mapping)
 {
-  struct objfile *objfile = cu->per_objfile->objfile;
-  const int decode_for_pst_p = (pst != NULL);
-
   if (decode_mapping)
-    dwarf_decode_lines_1 (lh, cu, decode_for_pst_p, lowpc);
+    dwarf_decode_lines_1 (lh, cu, lowpc);
 
-  if (decode_for_pst_p)
-    {
-      /* Now that we're done scanning the Line Header Program, we can
-        create the psymtab of each included file.  */
-      for (auto &file_entry : lh->file_names ())
-       if (file_entry.included_p)
-         {
-           gdb::unique_xmalloc_ptr<char> name_holder;
-           const char *include_name =
-             compute_include_file_name (lh, file_entry, fnd, &name_holder);
-           if (include_name != NULL)
-             dwarf2_create_include_psymtab
-               (cu->per_objfile->per_bfd, include_name, pst,
-                cu->per_objfile->per_bfd->partial_symtabs.get (),
-                objfile->per_bfd);
-         }
-    }
-  else
-    {
-      /* Make sure a symtab is created for every file, even files
-        which contain only variables (i.e. no code with associated
-        line numbers).  */
-      buildsym_compunit *builder = cu->get_builder ();
-      struct compunit_symtab *cust = builder->get_compunit_symtab ();
+  /* Make sure a symtab is created for every file, even files
+     which contain only variables (i.e. no code with associated
+     line numbers).  */
+  buildsym_compunit *builder = cu->get_builder ();
+  struct compunit_symtab *cust = builder->get_compunit_symtab ();
 
-      for (auto &fe : lh->file_names ())
+  for (auto &fe : lh->file_names ())
+    {
+      dwarf2_start_subfile (cu, fe.name, fe.include_dir (lh));
+      if (builder->get_current_subfile ()->symtab == NULL)
        {
-         dwarf2_start_subfile (cu, fe.name, fe.include_dir (lh));
-         if (builder->get_current_subfile ()->symtab == NULL)
-           {
-             builder->get_current_subfile ()->symtab
-               = allocate_symtab (cust,
-                                  builder->get_current_subfile ()->name);
-           }
-         fe.symtab = builder->get_current_subfile ()->symtab;
+         builder->get_current_subfile ()->symtab
+           = allocate_symtab (cust,
+                              builder->get_current_subfile ()->name.c_str ());
        }
+      fe.symtab = builder->get_current_subfile ()->symtab;
     }
 }
 
@@ -21543,7 +20482,7 @@ static void
 dwarf2_start_subfile (struct dwarf2_cu *cu, const char *filename,
                      const char *dirname)
 {
-  gdb::unique_xmalloc_ptr<char> copy;
+  std::string copy;
 
   /* In order not to lose the line information directory,
      we concatenate it to the filename when it makes sense.
@@ -21554,8 +20493,8 @@ dwarf2_start_subfile (struct dwarf2_cu *cu, const char *filename,
 
   if (!IS_ABSOLUTE_PATH (filename) && dirname != NULL)
     {
-      copy.reset (concat (dirname, SLASH_STRING, filename, (char *) NULL));
-      filename = copy.get ();
+      copy = path_join (dirname, filename);
+      filename = copy.c_str ();
     }
 
   cu->get_builder ()->start_subfile (filename);
@@ -21582,7 +20521,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
      variable has been optimized away.  */
   if (attr->form_is_block () && attr->as_block ()->size == 0)
     {
-      SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
+      sym->set_aclass_index (LOC_OPTIMIZED_OUT);
       return;
     }
 
@@ -21605,19 +20544,16 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
          unsigned int dummy;
 
          if (block->data[0] == DW_OP_addr)
-           SET_SYMBOL_VALUE_ADDRESS
-             (sym, cu->header.read_address (objfile->obfd,
-                                            block->data + 1,
-                                            &dummy));
+           sym->set_value_address
+             (cu->header.read_address (objfile->obfd, block->data + 1,
+                                       &dummy));
          else
-           SET_SYMBOL_VALUE_ADDRESS
-             (sym, read_addr_index_from_leb128 (cu, block->data + 1,
-                                                &dummy));
-         SYMBOL_ACLASS_INDEX (sym) = LOC_STATIC;
+           sym->set_value_address
+             (read_addr_index_from_leb128 (cu, block->data + 1, &dummy));
+         sym->set_aclass_index (LOC_STATIC);
          fixup_symbol_section (sym, objfile);
-         SET_SYMBOL_VALUE_ADDRESS
-           (sym,
-            SYMBOL_VALUE_ADDRESS (sym)
+         sym->set_value_address
+           (sym->value_address ()
             + objfile->section_offsets[sym->section_index ()]);
          return;
        }
@@ -21694,21 +20630,21 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
       /* Handle DW_AT_artificial.  */
       attr = dwarf2_attr (die, DW_AT_artificial, cu);
       if (attr != nullptr)
-       sym->artificial = attr->as_boolean ();
+       sym->set_is_artificial (attr->as_boolean ());
 
       /* Default assumptions.
         Use the passed type or decode it from the die.  */
-      SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
-      SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
+      sym->set_domain (VAR_DOMAIN);
+      sym->set_aclass_index (LOC_OPTIMIZED_OUT);
       if (type != NULL)
-       SYMBOL_TYPE (sym) = type;
+       sym->set_type (type);
       else
-       SYMBOL_TYPE (sym) = die_type (die, cu);
+       sym->set_type (die_type (die, cu));
       attr = dwarf2_attr (die,
                          inlined_func ? DW_AT_call_line : DW_AT_decl_line,
                          cu);
       if (attr != nullptr)
-       SYMBOL_LINE (sym) = attr->constant_value (0);
+       sym->set_line (attr->constant_value (0));
 
       attr = dwarf2_attr (die,
                          inlined_func ? DW_AT_call_file : DW_AT_decl_file,
@@ -21727,7 +20663,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
          if (fe == NULL)
            complaint (_("file index out of range"));
          else
-           symbol_set_symtab (sym, fe->symtab);
+           sym->set_symtab (fe->symtab);
        }
 
       switch (die->tag)
@@ -21740,19 +20676,19 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
 
              addr = attr->as_address ();
              addr = gdbarch_adjust_dwarf2_addr (gdbarch, addr + baseaddr);
-             SET_SYMBOL_VALUE_ADDRESS (sym, addr);
-             SYMBOL_ACLASS_INDEX (sym) = LOC_LABEL;
+             sym->set_value_address (addr);
+             sym->set_aclass_index (LOC_LABEL);
            }
          else
-           SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
-         SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_core_addr;
-         SYMBOL_DOMAIN (sym) = LABEL_DOMAIN;
+           sym->set_aclass_index (LOC_OPTIMIZED_OUT);
+         sym->set_type (objfile_type (objfile)->builtin_core_addr);
+         sym->set_domain (LABEL_DOMAIN);
          add_symbol_to_list (sym, cu->list_in_scope);
          break;
        case DW_TAG_subprogram:
          /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
             finish_block.  */
-         SYMBOL_ACLASS_INDEX (sym) = LOC_BLOCK;
+         sym->set_aclass_index (LOC_BLOCK);
          attr2 = dwarf2_attr (die, DW_AT_external, cu);
          if ((attr2 != nullptr && attr2->as_boolean ())
              || cu->per_cu->lang == language_ada
@@ -21774,8 +20710,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
        case DW_TAG_inlined_subroutine:
          /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
             finish_block.  */
-         SYMBOL_ACLASS_INDEX (sym) = LOC_BLOCK;
-         SYMBOL_INLINED (sym) = 1;
+         sym->set_aclass_index (LOC_BLOCK);
+         sym->set_is_inlined (1);
          list_to_add = cu->list_in_scope;
          break;
        case DW_TAG_template_value_param:
@@ -21787,8 +20723,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
          /* Compilation with minimal debug info may result in
             variables with missing type entries.  Change the
             misleading `void' type to something sensible.  */
-         if (SYMBOL_TYPE (sym)->code () == TYPE_CODE_VOID)
-           SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_int;
+         if (sym->type ()->code () == TYPE_CODE_VOID)
+           sym->set_type (objfile_type (objfile)->builtin_int);
 
          attr = dwarf2_attr (die, DW_AT_const_value, cu);
          /* In the case of DW_TAG_member, we should only be called for
@@ -21825,8 +20761,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
                  && die->parent->tag == DW_TAG_common_block)
                attr2 = NULL;
 
-             if (SYMBOL_CLASS (sym) == LOC_STATIC
-                 && SYMBOL_VALUE_ADDRESS (sym) == 0
+             if (sym->aclass () == LOC_STATIC
+                 && sym->value_address () == 0
                  && !per_objfile->per_bfd->has_section_at_zero)
                {
                  /* When a static variable is eliminated by the linker,
@@ -21836,7 +20772,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
                }
              else if (attr2 != nullptr && attr2->as_boolean ())
                {
-                 if (SYMBOL_CLASS (sym) == LOC_STATIC
+                 if (sym->aclass () == LOC_STATIC
                      && (objfile->flags & OBJF_MAINLINE) == 0
                      && per_objfile->per_bfd->can_copy)
                    {
@@ -21894,12 +20830,12 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
                       ? cu->get_builder ()->get_global_symbols ()
                       : cu->list_in_scope);
 
-                 SYMBOL_ACLASS_INDEX (sym) = LOC_UNRESOLVED;
+                 sym->set_aclass_index (LOC_UNRESOLVED);
                }
              else if (!die_is_declaration (die, cu))
                {
                  /* Use the default LOC_OPTIMIZED_OUT class.  */
-                 gdb_assert (SYMBOL_CLASS (sym) == LOC_OPTIMIZED_OUT);
+                 gdb_assert (sym->aclass () == LOC_OPTIMIZED_OUT);
                  if (!suppress_add)
                    list_to_add = cu->list_in_scope;
                }
@@ -21915,7 +20851,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
            struct context_stack *curr
              = cu->get_builder ()->get_current_context_stack ();
            if (curr != nullptr && curr->name != nullptr)
-             SYMBOL_IS_ARGUMENT (sym) = 1;
+             sym->set_is_argument (1);
            attr = dwarf2_attr (die, DW_AT_location, cu);
            if (attr != nullptr)
              {
@@ -21944,9 +20880,17 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
        case DW_TAG_union_type:
        case DW_TAG_set_type:
        case DW_TAG_enumeration_type:
-         SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
-         SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
-
+       case DW_TAG_namelist:
+         if (die->tag == DW_TAG_namelist)
+           {
+             sym->set_aclass_index (LOC_STATIC);
+             sym->set_domain (VAR_DOMAIN);
+           }
+         else
+           {
+             sym->set_aclass_index (LOC_TYPEDEF);
+             sym->set_domain (STRUCT_DOMAIN);
+           }
          {
            /* NOTE: carlton/2003-11-10: C++ class symbols shouldn't
               really ever be static objects: otherwise, if you try
@@ -21975,22 +20919,23 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
                    /* The symbol's name is already allocated along
                       with this objfile, so we don't need to
                       duplicate it for the type.  */
-                   if (SYMBOL_TYPE (sym)->name () == 0)
-                     SYMBOL_TYPE (sym)->set_name (sym->search_name ());
+                   if (sym->type ()->name () == 0)
+                     sym->type ()->set_name (sym->search_name ());
                  }
              }
          }
          break;
        case DW_TAG_typedef:
-         SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
-         SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
+         sym->set_aclass_index (LOC_TYPEDEF);
+         sym->set_domain (VAR_DOMAIN);
          list_to_add = cu->list_in_scope;
          break;
        case DW_TAG_array_type:
        case DW_TAG_base_type:
        case DW_TAG_subrange_type:
-         SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
-         SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
+       case DW_TAG_generic_subrange:
+         sym->set_aclass_index (LOC_TYPEDEF);
+         sym->set_domain (VAR_DOMAIN);
          list_to_add = cu->list_in_scope;
          break;
        case DW_TAG_enumerator:
@@ -22012,17 +20957,17 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
          break;
        case DW_TAG_imported_declaration:
        case DW_TAG_namespace:
-         SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
+         sym->set_aclass_index (LOC_TYPEDEF);
          list_to_add = cu->get_builder ()->get_global_symbols ();
          break;
        case DW_TAG_module:
-         SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
-         SYMBOL_DOMAIN (sym) = MODULE_DOMAIN;
+         sym->set_aclass_index (LOC_TYPEDEF);
+         sym->set_domain (MODULE_DOMAIN);
          list_to_add = cu->get_builder ()->get_global_symbols ();
          break;
        case DW_TAG_common_block:
-         SYMBOL_ACLASS_INDEX (sym) = LOC_COMMON_BLOCK;
-         SYMBOL_DOMAIN (sym) = COMMON_BLOCK_DOMAIN;
+         sym->set_aclass_index (LOC_COMMON_BLOCK);
+         sym->set_domain (COMMON_BLOCK_DOMAIN);
          add_symbol_to_list (sym, cu->list_in_scope);
          break;
        default:
@@ -22211,7 +21156,7 @@ dwarf2_const_value (const struct attribute *attr, struct symbol *sym,
   const gdb_byte *bytes;
   struct dwarf2_locexpr_baton *baton;
 
-  dwarf2_const_value_attr (attr, SYMBOL_TYPE (sym),
+  dwarf2_const_value_attr (attr, sym->type (),
                           sym->print_name (),
                           &objfile->objfile_obstack, cu,
                           &value, &bytes, &baton);
@@ -22219,17 +21164,17 @@ dwarf2_const_value (const struct attribute *attr, struct symbol *sym,
   if (baton != NULL)
     {
       SYMBOL_LOCATION_BATON (sym) = baton;
-      SYMBOL_ACLASS_INDEX (sym) = dwarf2_locexpr_index;
+      sym->set_aclass_index (dwarf2_locexpr_index);
     }
   else if (bytes != NULL)
-     {
-      SYMBOL_VALUE_BYTES (sym) = bytes;
-      SYMBOL_ACLASS_INDEX (sym) = LOC_CONST_BYTES;
+    {
+      sym->set_value_bytes (bytes);
+      sym->set_aclass_index (LOC_CONST_BYTES);
     }
   else
     {
-      SYMBOL_VALUE (sym) = value;
-      SYMBOL_ACLASS_INDEX (sym) = LOC_CONST;
+      sym->set_value_longest (value);
+      sym->set_aclass_index (LOC_CONST);
     }
 }
 
@@ -22482,6 +21427,7 @@ read_type_die_1 (struct die_info *die, struct dwarf2_cu *cu)
     case DW_TAG_typedef:
       this_type = read_typedef (die, cu);
       break;
+    case DW_TAG_generic_subrange:
     case DW_TAG_subrange_type:
       this_type = read_subrange_type (die, cu);
       break;
@@ -22883,6 +21829,7 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu)
       && die->tag != DW_TAG_class_type
       && die->tag != DW_TAG_interface_type
       && die->tag != DW_TAG_structure_type
+      && die->tag != DW_TAG_namelist
       && die->tag != DW_TAG_union_type)
     return NULL;
 
@@ -22907,6 +21854,7 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu)
     case DW_TAG_interface_type:
     case DW_TAG_structure_type:
     case DW_TAG_union_type:
+    case DW_TAG_namelist:
       /* Some GCC versions emit spurious DW_AT_name attributes for unnamed
         structures or unions.  These were of the form "._%d" in GCC 4.1,
         or simply "<anonymous struct>" or "<anonymous union>" in GCC 4.3
@@ -22980,85 +21928,82 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
 {
   unsigned int i;
 
-  print_spaces (indent, f);
-  fprintf_unfiltered (f, "Die: %s (abbrev %d, offset %s)\n",
-                     dwarf_tag_name (die->tag), die->abbrev,
-                     sect_offset_str (die->sect_off));
+  gdb_printf (f, "%*sDie: %s (abbrev %d, offset %s)\n",
+             indent, "",
+             dwarf_tag_name (die->tag), die->abbrev,
+             sect_offset_str (die->sect_off));
 
   if (die->parent != NULL)
-    {
-      print_spaces (indent, f);
-      fprintf_unfiltered (f, "  parent at offset: %s\n",
-                         sect_offset_str (die->parent->sect_off));
-    }
+    gdb_printf (f, "%*s  parent at offset: %s\n",
+               indent, "",
+               sect_offset_str (die->parent->sect_off));
 
-  print_spaces (indent, f);
-  fprintf_unfiltered (f, "  has children: %s\n",
-          dwarf_bool_name (die->child != NULL));
+  gdb_printf (f, "%*s  has children: %s\n",
+             indent, "",
+             dwarf_bool_name (die->child != NULL));
 
-  print_spaces (indent, f);
-  fprintf_unfiltered (f, "  attributes:\n");
+  gdb_printf (f, "%*s  attributes:\n", indent, "");
 
   for (i = 0; i < die->num_attrs; ++i)
     {
-      print_spaces (indent, f);
-      fprintf_unfiltered (f, "    %s (%s) ",
-              dwarf_attr_name (die->attrs[i].name),
-              dwarf_form_name (die->attrs[i].form));
+      gdb_printf (f, "%*s    %s (%s) ",
+                 indent, "",
+                 dwarf_attr_name (die->attrs[i].name),
+                 dwarf_form_name (die->attrs[i].form));
 
       switch (die->attrs[i].form)
        {
        case DW_FORM_addr:
        case DW_FORM_addrx:
        case DW_FORM_GNU_addr_index:
-         fprintf_unfiltered (f, "address: ");
-         fputs_filtered (hex_string (die->attrs[i].as_address ()), f);
+         gdb_printf (f, "address: ");
+         gdb_puts (hex_string (die->attrs[i].as_address ()), f);
          break;
        case DW_FORM_block2:
        case DW_FORM_block4:
        case DW_FORM_block:
        case DW_FORM_block1:
-         fprintf_unfiltered (f, "block: size %s",
-                             pulongest (die->attrs[i].as_block ()->size));
+         gdb_printf (f, "block: size %s",
+                     pulongest (die->attrs[i].as_block ()->size));
          break;
        case DW_FORM_exprloc:
-         fprintf_unfiltered (f, "expression: size %s",
-                             pulongest (die->attrs[i].as_block ()->size));
+         gdb_printf (f, "expression: size %s",
+                     pulongest (die->attrs[i].as_block ()->size));
          break;
        case DW_FORM_data16:
-         fprintf_unfiltered (f, "constant of 16 bytes");
+         gdb_printf (f, "constant of 16 bytes");
          break;
        case DW_FORM_ref_addr:
-         fprintf_unfiltered (f, "ref address: ");
-         fputs_filtered (hex_string (die->attrs[i].as_unsigned ()), f);
+         gdb_printf (f, "ref address: ");
+         gdb_puts (hex_string (die->attrs[i].as_unsigned ()), f);
          break;
        case DW_FORM_GNU_ref_alt:
-         fprintf_unfiltered (f, "alt ref address: ");
-         fputs_filtered (hex_string (die->attrs[i].as_unsigned ()), f);
+         gdb_printf (f, "alt ref address: ");
+         gdb_puts (hex_string (die->attrs[i].as_unsigned ()), f);
          break;
        case DW_FORM_ref1:
        case DW_FORM_ref2:
        case DW_FORM_ref4:
        case DW_FORM_ref8:
        case DW_FORM_ref_udata:
-         fprintf_unfiltered (f, "constant ref: 0x%lx (adjusted)",
-                             (long) (die->attrs[i].as_unsigned ()));
+         gdb_printf (f, "constant ref: 0x%lx (adjusted)",
+                     (long) (die->attrs[i].as_unsigned ()));
          break;
        case DW_FORM_data1:
        case DW_FORM_data2:
        case DW_FORM_data4:
        case DW_FORM_data8:
        case DW_FORM_udata:
-         fprintf_unfiltered (f, "constant: %s",
-                             pulongest (die->attrs[i].as_unsigned ()));
+         gdb_printf (f, "constant: %s",
+                     pulongest (die->attrs[i].as_unsigned ()));
          break;
        case DW_FORM_sec_offset:
-         fprintf_unfiltered (f, "section offset: %s",
-                             pulongest (die->attrs[i].as_unsigned ()));
+         gdb_printf (f, "section offset: %s",
+                     pulongest (die->attrs[i].as_unsigned ()));
          break;
        case DW_FORM_ref_sig8:
-         fprintf_unfiltered (f, "signature: %s",
-                             hex_string (die->attrs[i].as_signature ()));
+         gdb_printf (f, "signature: %s",
+                     hex_string (die->attrs[i].as_signature ()));
          break;
        case DW_FORM_string:
        case DW_FORM_strp:
@@ -23066,37 +22011,37 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
        case DW_FORM_strx:
        case DW_FORM_GNU_str_index:
        case DW_FORM_GNU_strp_alt:
-         fprintf_unfiltered (f, "string: \"%s\" (%s canonicalized)",
-                             die->attrs[i].as_string ()
-                             ? die->attrs[i].as_string () : "",
-                             die->attrs[i].canonical_string_p () ? "is" : "not");
+         gdb_printf (f, "string: \"%s\" (%s canonicalized)",
+                     die->attrs[i].as_string ()
+                     ? die->attrs[i].as_string () : "",
+                     die->attrs[i].canonical_string_p () ? "is" : "not");
          break;
        case DW_FORM_flag:
          if (die->attrs[i].as_boolean ())
-           fprintf_unfiltered (f, "flag: TRUE");
+           gdb_printf (f, "flag: TRUE");
          else
-           fprintf_unfiltered (f, "flag: FALSE");
+           gdb_printf (f, "flag: FALSE");
          break;
        case DW_FORM_flag_present:
-         fprintf_unfiltered (f, "flag: TRUE");
+         gdb_printf (f, "flag: TRUE");
          break;
        case DW_FORM_indirect:
          /* The reader will have reduced the indirect form to
             the "base form" so this form should not occur.  */
-         fprintf_unfiltered (f,
-                             "unexpected attribute form: DW_FORM_indirect");
+         gdb_printf (f,
+                     "unexpected attribute form: DW_FORM_indirect");
          break;
        case DW_FORM_sdata:
        case DW_FORM_implicit_const:
-         fprintf_unfiltered (f, "constant: %s",
-                             plongest (die->attrs[i].as_signed ()));
+         gdb_printf (f, "constant: %s",
+                     plongest (die->attrs[i].as_signed ()));
          break;
        default:
-         fprintf_unfiltered (f, "unsupported attribute form: %d.",
-                  die->attrs[i].form);
+         gdb_printf (f, "unsupported attribute form: %d.",
+                     die->attrs[i].form);
          break;
        }
-      fprintf_unfiltered (f, "\n");
+      gdb_printf (f, "\n");
     }
 }
 
@@ -23120,17 +22065,16 @@ dump_die_1 (struct ui_file *f, int level, int max_level, struct die_info *die)
 
   if (die->child != NULL)
     {
-      print_spaces (indent, f);
-      fprintf_unfiltered (f, "  Children:");
+      gdb_printf (f, "%*s  Children:", indent, "");
       if (level + 1 < max_level)
        {
-         fprintf_unfiltered (f, "\n");
+         gdb_printf (f, "\n");
          dump_die_1 (f, level + 1, max_level, die->child);
        }
       else
        {
-         fprintf_unfiltered (f,
-                             " [not printed, max nesting level reached]\n");
+         gdb_printf (f,
+                     " [not printed, max nesting level reached]\n");
        }
     }
 
@@ -23245,7 +22189,6 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz,
   else if (cu->dies == NULL)
     {
       /* We're loading full DIEs during partial symbol reading.  */
-      gdb_assert (per_objfile->per_bfd->reading_partial_symbols);
       load_full_comp_unit (cu->per_cu, per_objfile, cu, false,
                           language_minimal);
     }
@@ -23635,7 +22578,7 @@ follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type,
       /* For .gdb_index version 7 keep track of included TUs.
         http://sourceware.org/bugzilla/show_bug.cgi?id=15021.  */
       if (per_objfile->per_bfd->index_table != NULL
-         && per_objfile->per_bfd->index_table->version <= 7)
+         && !per_objfile->per_bfd->index_table->version_check ())
        {
          (*ref_cu)->per_cu->imported_symtabs_push (sig_cu->per_cu);
        }
@@ -23787,9 +22730,6 @@ load_full_type_unit (dwarf2_per_cu_data *per_cu,
 {
   struct signatured_type *sig_type;
 
-  /* Caller is responsible for ensuring type_unit_groups don't get here.  */
-  gdb_assert (! per_cu->type_unit_group_p ());
-
   /* We have the per_cu, but we need the signatured_type.
      Fortunately this is an easy translation.  */
   gdb_assert (per_cu->is_debug_types);
@@ -24326,9 +23266,9 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym,
        complaint (_("Location list used without "
                     "specifying the CU base address."));
 
-      SYMBOL_ACLASS_INDEX (sym) = (is_block
-                                  ? dwarf2_loclist_block_index
-                                  : dwarf2_loclist_index);
+      sym->set_aclass_index ((is_block
+                             ? dwarf2_loclist_block_index
+                             : dwarf2_loclist_index));
       SYMBOL_LOCATION_BATON (sym) = baton;
     }
   else
@@ -24358,9 +23298,9 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym,
          baton->size = 0;
        }
 
-      SYMBOL_ACLASS_INDEX (sym) = (is_block
-                                  ? dwarf2_locexpr_block_index
-                                  : dwarf2_locexpr_index);
+      sym->set_aclass_index ((is_block
+                             ? dwarf2_locexpr_block_index
+                             : dwarf2_locexpr_index));
       SYMBOL_LOCATION_BATON (sym) = baton;
     }
 }
@@ -24767,6 +23707,15 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
        type->add_dyn_prop (DYN_PROP_ASSOCIATED, prop);
     }
 
+  /* Read DW_AT_rank and set in type.  */
+  attr = dwarf2_attr (die, DW_AT_rank, cu);
+  if (attr != NULL)
+    {
+      struct type *prop_type = cu->addr_sized_int_type (false);
+      if (attr_to_dynamic_prop (attr, die, cu, &prop, prop_type))
+       type->add_dyn_prop (DYN_PROP_RANK, prop);
+    }
+
   /* Read DW_AT_data_location and set in type.  */
   if (!skip_data_location)
     {
@@ -24828,32 +23777,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);
 }
 
-/* Trivial hash function for partial_die_info: the hash value of a DIE
-   is its offset in .debug_info for this objfile.  */
-
-static hashval_t
-partial_die_hash (const void *item)
-{
-  const struct partial_die_info *part_die
-    = (const struct partial_die_info *) item;
-
-  return to_underlying (part_die->sect_off);
-}
-
-/* Trivial comparison function for partial_die_info structures: two DIEs
-   are equal if they have the same offset.  */
-
-static int
-partial_die_eq (const void *item_lhs, const void *item_rhs)
-{
-  const struct partial_die_info *part_die_lhs
-    = (const struct partial_die_info *) item_lhs;
-  const struct partial_die_info *part_die_rhs
-    = (const struct partial_die_info *) item_rhs;
-
-  return part_die_lhs->sect_off == part_die_rhs->sect_off;
-}
-
 struct cmd_list_element *set_dwarf_cmdlist;
 struct cmd_list_element *show_dwarf_cmdlist;
 
@@ -24861,9 +23784,9 @@ static void
 show_check_physname (struct ui_file *file, int from_tty,
                     struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file,
-                   _("Whether to check \"physname\" is %s.\n"),
-                   value);
+  gdb_printf (file,
+             _("Whether to check \"physname\" is %s.\n"),
+             value);
 }
 
 void _initialize_dwarf2_read ();