gdb: use decltype instead of typeof in dwarf2/read.c
[binutils-gdb.git] / gdb / dwarf2 / read.c
index f2d7da7de52d46fbc34bb9985c8434a29e2350ce..7c148aecdf5aec45b02374b90a0d4f92c14cd909 100644 (file)
@@ -1,6 +1,6 @@
 /* DWARF 2 debugging format support for GDB.
 
 /* 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
 
    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 "block.h"
 #include "addrmap.h"
 #include "typeprint.h"
-#include "psympriv.h"
 #include "c-lang.h"
 #include "go-lang.h"
 #include "valprint.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 "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.
 
 /* When == 1, print basic high level tracing messages.
    When > 1, be more verbose.
@@ -362,7 +366,7 @@ struct mapped_debug_names final : public mapped_index_base
   { return this->name_count; }
 };
 
   { return this->name_count; }
 };
 
-/* See dwarf2read.h.  */
+/* See dwarf2/read.h.  */
 
 dwarf2_per_objfile *
 get_dwarf2_per_objfile (struct objfile *objfile)
 
 dwarf2_per_objfile *
 get_dwarf2_per_objfile (struct objfile *objfile)
@@ -477,13 +481,8 @@ struct stmt_list_hash
    that can be shared across objfiles.  The non-shareable parts are in
    type_unit_group_unshareable.  */
 
    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 {};
 };
   /* The data used to construct the hash key.  */
   struct stmt_list_hash hash {};
 };
@@ -791,7 +790,8 @@ public:
               dwarf2_per_objfile *per_objfile,
               struct abbrev_table *abbrev_table,
               dwarf2_cu *existing_cu,
               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,
 
   explicit cutu_reader (struct dwarf2_per_cu_data *this_cu,
                        dwarf2_per_objfile *per_objfile,
@@ -800,6 +800,8 @@ public:
 
   DISABLE_COPY_AND_ASSIGN (cutu_reader);
 
 
   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;
   const gdb_byte *info_ptr = nullptr;
   struct die_info *comp_unit_die = nullptr;
   bool dummy_p = false;
@@ -808,6 +810,13 @@ public:
      for dummy CUs.  */
   void keep ();
 
      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,
 private:
   void init_tu_and_read_dwo_dies (dwarf2_per_cu_data *this_cu,
                                  dwarf2_per_objfile *per_objfile,
@@ -823,164 +832,6 @@ private:
   abbrev_table_up m_dwo_abbrev_table;
 };
 
   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.  */
 /* 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 +941,9 @@ static void
 show_dwarf_max_cache_age (struct ui_file *file, int from_tty,
                          struct cmd_list_element *c, const char *value)
 {
 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 */
 }
 \f
 /* local function prototypes */
@@ -1100,63 +951,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 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 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 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 *,
 static const gdb_byte *read_attribute (const struct die_reader_specs *,
                                       struct attribute *,
                                       const struct attr_abbrev *,
@@ -1207,8 +1009,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 *,
                                                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 *,
                                CORE_ADDR, int decode_mapping);
 
 static void dwarf2_start_subfile (struct dwarf2_cu *, const char *,
@@ -1297,7 +1098,8 @@ enum pc_bounds_kind
 static enum pc_bounds_kind dwarf2_get_pc_bounds (struct die_info *,
                                                 CORE_ADDR *, CORE_ADDR *,
                                                 struct dwarf2_cu *,
 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 *,
 
 static void get_scope_pc_bounds (struct die_info *,
                                 CORE_ADDR *, CORE_ADDR *,
@@ -1441,11 +1243,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,
 
 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,
 
 static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit
   (sect_offset sect_off, unsigned int offset_in_dwz,
@@ -2024,6 +1823,25 @@ dwarf2_get_section_info (struct objfile *objfile,
   *sizep = info->size;
 }
 
   *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.  */
 
 \f
 /* DWARF quick_symbol_functions support.  */
 
@@ -2053,49 +1871,6 @@ struct quick_file_names
   const char **real_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;
 struct dwarf2_base_index_functions : public quick_symbol_functions
 {
   bool has_symbols (struct objfile *objfile) override;
@@ -2279,11 +2054,6 @@ static void
 dw2_do_instantiate_symtab (dwarf2_per_cu_data *per_cu,
                           dwarf2_per_objfile *per_objfile, bool skip_partial)
 {
 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
   {
     /* The destructor of dwarf2_queue_guard frees any entries left on
        the queue.  After this point we're guaranteed to leave this function
@@ -2326,8 +2096,6 @@ dw2_instantiate_symtab (dwarf2_per_cu_data *per_cu,
                        dwarf2_per_objfile *per_objfile,
                        bool skip_partial)
 {
                        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);
   if (!per_objfile->symtab_set_p (per_cu))
     {
       free_cached_comp_units freer (per_objfile);
@@ -2376,8 +2144,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->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;
 }
   the_cu->is_dwz = is_dwz;
   return the_cu;
 }
@@ -2458,9 +2224,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->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 ();
 
       slot = htab_find_slot (sig_types_hash.get (), sig_type.get (), INSERT);
       *slot = sig_type.get ();
@@ -2509,9 +2272,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->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 ();
 
       slot = htab_find_slot (sig_types_hash.get (), sig_type.get (), INSERT);
       *slot = sig_type.get ();
@@ -2579,12 +2339,14 @@ create_addrmap_from_index (dwarf2_per_objfile *per_objfile,
                                                 &per_bfd->obstack);
 }
 
                                                 &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;
 {
   struct objfile *objfile = per_objfile->objfile;
   bfd *abfd = objfile->obfd;
@@ -2592,9 +2354,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;
 
   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>>
   std::unordered_map<sect_offset,
                     dwarf2_per_cu_data *,
                     gdb::hash_enum<sect_offset>>
@@ -2603,8 +2362,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
     {
       /* 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
        continue;
 
       const auto insertpair
@@ -2615,7 +2375,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));
          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 +2406,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                   plongest (entry_addr - section->buffer),
                   plongest (bytes_read + entry_length),
                   pulongest (section->size));
                   plongest (entry_addr - section->buffer),
                   plongest (bytes_read + entry_length),
                   pulongest (section->size));
-         return;
+         return false;
        }
 
       /* The version number.  */
        }
 
       /* The version number.  */
@@ -2658,7 +2418,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);
                     "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
        }
 
       const uint64_t debug_info_offset
@@ -2674,7 +2434,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                   objfile_name (objfile),
                   plongest (entry_addr - section->buffer),
                   pulongest (debug_info_offset));
                   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;
 
        }
       dwarf2_per_cu_data *const per_cu = per_cu_it->second;
 
@@ -2685,7 +2445,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);
                     "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++;
        }
 
       const uint8_t segment_selector_size = *addr++;
@@ -2697,7 +2457,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                   objfile_name (objfile),
                   plongest (entry_addr - section->buffer),
                   segment_selector_size);
                   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
        }
 
       /* Must pad to an alignment boundary that is twice the address
@@ -2718,7 +2478,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                         "ignoring .debug_aranges."),
                       objfile_name (objfile),
                       plongest (entry_addr - section->buffer));
                         "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);
            }
          ULONGEST start = extract_unsigned_integer (addr, address_size,
                                                     dwarf5_byte_order);
@@ -2740,10 +2500,28 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                 - baseaddr);
          addrmap_set_empty (mutable_map, start, end - 1, per_cu);
        }
                 - 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
 }
 
 /* A helper function that reads the .gdb_index from BUFFER and fills
@@ -2948,7 +2726,6 @@ dwarf2_read_gdb_index
   create_addrmap_from_index (per_objfile, map.get ());
 
   per_bfd->index_table = std::move (map);
   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 ());
 
   per_bfd->quick_file_names_table =
     create_quick_file_names_table (per_bfd->all_comp_units.size ());
 
@@ -2971,7 +2748,7 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
 
   gdb_assert (! this_cu->is_debug_types);
 
 
   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)
   /* 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 +2775,7 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
                             &find_entry, INSERT);
       if (*slot != NULL)
        {
                             &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;
        }
 
          return;
        }
 
@@ -3008,7 +2785,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;
   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;
     ++offset;
   else if (lh == nullptr)
     return;
@@ -3050,7 +2827,7 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
 
   qfn->real_names = NULL;
 
 
   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
 }
 
 /* A helper for the "quick" functions which attempts to read the line
@@ -3062,17 +2839,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);
 {
   /* 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);
 
 
   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
 }
 
 /* A helper for the "quick" functions which computes and caches the
@@ -3113,7 +2888,7 @@ dwarf2_base_index_functions::find_last_source_symtab (struct objfile *objfile)
   if (cust == NULL)
     return NULL;
 
   if (cust == NULL)
     return NULL;
 
-  return compunit_primary_filetab (cust);
+  return cust->primary_filetab ();
 }
 
 /* See read.h.  */
 }
 
 /* See read.h.  */
@@ -3121,10 +2896,13 @@ dwarf2_base_index_functions::find_last_source_symtab (struct objfile *objfile)
 void
 dwarf2_per_cu_data::free_cached_file_names ()
 {
 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;
 
     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)
   if (file_data != nullptr && file_data->real_names != nullptr)
     {
       for (int i = 0; i < file_data->num_file_names; ++i)
@@ -3311,8 +3089,8 @@ dwarf2_base_index_functions::print_stats (struct objfile *objfile,
       if (!per_objfile->symtab_set_p (per_cu))
        ++count;
     }
       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.
 }
 
 /* This dumps minimal information about the index.
@@ -3325,16 +3103,15 @@ dwarf2_gdb_index::dump (struct objfile *objfile)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
-  gdb_assert (per_objfile->per_bfd->using_index);
-  printf_filtered (".gdb_index:");
+  gdb_printf (".gdb_index:");
   if (per_objfile->per_bfd->index_table != NULL)
     {
   if (per_objfile->per_bfd->index_table != NULL)
     {
-      printf_filtered (" version %d\n",
-                      per_objfile->per_bfd->index_table->version);
+      gdb_printf (" version %d\n",
+                 per_objfile->per_bfd->index_table->version);
     }
   else
     }
   else
-    printf_filtered (" faked for \"readnow\"\n");
-  printf_filtered ("\n");
+    gdb_printf (" faked for \"readnow\"\n");
+  gdb_printf ("\n");
 }
 
 void
 }
 
 void
@@ -4197,7 +3974,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)
 {
    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);
 
     {
       bool symtab_was_null = !per_objfile->symtab_set_p (per_cu);
 
@@ -4338,12 +4115,33 @@ dw_expand_symtabs_matching_file_matcher
 
       if (per_cu->is_debug_types)
        continue;
 
       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;
 
 
       /* 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)
       quick_file_names *file_data = dw2_get_file_names (per_cu.get (),
                                                        per_objfile);
       if (file_data == NULL)
@@ -4353,7 +4151,7 @@ dw_expand_symtabs_matching_file_matcher
        continue;
       else if (htab_find (visited_found.get (), file_data) != NULL)
        {
        continue;
       else if (htab_find (visited_found.get (), file_data) != NULL)
        {
-         per_cu->v.quick->mark = 1;
+         per_cu->mark = 1;
          continue;
        }
 
          continue;
        }
 
@@ -4363,7 +4161,7 @@ dw_expand_symtabs_matching_file_matcher
 
          if (file_matcher (file_data->file_names[j], false))
            {
 
          if (file_matcher (file_data->file_names[j], false))
            {
-             per_cu->v.quick->mark = 1;
+             per_cu->mark = 1;
              break;
            }
 
              break;
            }
 
@@ -4377,12 +4175,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))
            {
          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;
            }
        }
 
              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);
                                    ? visited_found.get ()
                                    : visited_not_found.get (),
                                    file_data, INSERT);
@@ -4451,8 +4249,8 @@ recursively_find_pc_sect_compunit_symtab (struct compunit_symtab *cust,
 {
   int i;
 
 {
   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)
     return cust;
 
   if (cust->includes == NULL)
@@ -4526,8 +4324,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->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 +4336,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->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 ())
       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 ())
@@ -4907,7 +4723,6 @@ 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);
   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->quick_file_names_table =
     create_quick_file_names_table (per_bfd->all_comp_units.size ());
 
   per_bfd->quick_file_names_table =
     create_quick_file_names_table (per_bfd->all_comp_units.size ());
 
@@ -5333,13 +5148,12 @@ dwarf2_debug_names_index::dump (struct objfile *objfile)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
-  gdb_assert (per_objfile->per_bfd->using_index);
-  printf_filtered (".debug_names:");
+  gdb_printf (".debug_names:");
   if (per_objfile->per_bfd->debug_names_table)
   if (per_objfile->per_bfd->debug_names_table)
-    printf_filtered (" exists\n");
+    gdb_printf (" exists\n");
   else
   else
-    printf_filtered (" faked for \"readnow\"\n");
-  printf_filtered ("\n");
+    gdb_printf (" faked for \"readnow\"\n");
+  gdb_printf ("\n");
 }
 
 void
 }
 
 void
@@ -5496,6 +5310,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);
 }
 
   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
 /* See dwarf2/public.h.  */
 
 void
@@ -5514,28 +5330,10 @@ dwarf2_initialize_objfile (struct objfile *objfile)
     {
       dwarf_read_debug_printf ("readnow requested");
 
     {
       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 ());
 
       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.  */
       /* Arrange for gdb to see the "quick" functions.  However, these
         functions will be no-ops because we will have expanded all
         symtabs.  */
@@ -5561,15 +5359,10 @@ dwarf2_initialize_objfile (struct objfile *objfile)
       return;
     }
 
       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)
+  if (per_bfd->cooked_index_table != nullptr)
     {
     {
-      dwarf_read_debug_printf ("re-using shared partial symtabs");
-      objfile->qf.push_front (make_lazy_dwarf_reader ());
+      dwarf_read_debug_printf ("re-using cooked index table");
+      objfile->qf.push_front (make_cooked_index_funcs ());
       return;
     }
 
       return;
     }
 
@@ -5601,7 +5394,7 @@ dwarf2_initialize_objfile (struct objfile *objfile)
     }
 
   global_index_cache.miss ();
     }
 
   global_index_cache.miss ();
-  objfile->qf.push_front (make_lazy_dwarf_reader ());
+  objfile->qf.push_front (make_cooked_index_funcs ());
 }
 
 \f
 }
 
 \f
@@ -5609,47 +5402,21 @@ dwarf2_initialize_objfile (struct objfile *objfile)
 /* Build a partial symbol table.  */
 
 void
 /* 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_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->cooked_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
     {
 
   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);
       dwarf2_build_psymtabs_hard (per_objfile);
-      psymtabs.keep ();
 
       /* (maybe) store an index in the cache.  */
       global_index_cache.store (per_objfile);
 
       /* (maybe) store an index in the cache.  */
       global_index_cache.store (per_objfile);
@@ -5730,111 +5497,6 @@ read_abbrev_offset (dwarf2_per_objfile *per_objfile,
   return (sect_offset) read_offset (abfd, info_ptr, offset_size);
 }
 
   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)
 {
 static hashval_t
 hash_signatured_type (const void *item)
 {
@@ -5998,12 +5660,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 ());
 
   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)
     {
 
   if (slot == NULL)
     {
@@ -6029,17 +5685,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);
   /* 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 (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->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;
 
   sig_entry->section = dwo_entry->section;
   sig_entry->sect_off = dwo_entry->sect_off;
@@ -6070,7 +5723,7 @@ lookup_dwo_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
   struct dwo_unit find_dwo_entry, *dwo_entry;
   void **slot;
 
   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.  */
 
   /* If TU skeletons have been removed then we may not have read in any
      TUs yet.  */
@@ -6117,7 +5770,8 @@ lookup_dwo_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
   if (sig_entry == NULL)
     sig_entry = add_type_unit (per_objfile, sig, slot);
 
   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;
 }
   sig_entry->tu_read = 1;
   return sig_entry;
 }
@@ -6135,7 +5789,7 @@ lookup_dwp_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
   struct dwo_unit *dwo_entry;
   void **slot;
 
   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
   gdb_assert (dwp_file != NULL);
 
   /* If TU skeletons have been removed then we may not have read in any
@@ -6176,7 +5830,7 @@ lookup_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
 {
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
 
 {
   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.  */
     {
       /* We're in a DWO/DWP file, and we're using .gdb_index.
         These cases require special processing.  */
@@ -6390,11 +6044,11 @@ read_cutu_die_from_dwo (dwarf2_cu *cu,
 
   if (dwarf_die_debug)
     {
 
   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);
     }
 
       dump_die (comp_unit_die, dwarf_die_debug);
     }
 
@@ -6429,6 +6083,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)
 {
 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;
   dwarf2_per_cu_data *per_cu = cu->per_cu;
   struct dwo_unit *dwo_unit;
   const char *comp_dir;
@@ -6521,7 +6183,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,
                          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)
 {
   : die_reader_specs {},
     m_this_cu (this_cu)
 {
@@ -6537,9 +6200,9 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
   int rereading_dwo_cu = 0;
 
   if (dwarf_die_debug)
   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.  */
 
   /* 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 +6238,14 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
     }
   else
     {
     }
   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 ();
     }
       m_new_cu.reset (new dwarf2_cu (this_cu, per_objfile));
       cu = m_new_cu.get ();
     }
@@ -6645,10 +6313,16 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
     gdb_assert (cu->header.abbrev_sect_off == abbrev_table->sect_off);
   else
     {
     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.  */
     }
 
   /* Read the top level CU/TU die.  */
@@ -6752,9 +6426,9 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
   const gdb_byte *begin_info_ptr, *info_ptr;
 
   if (dwarf_die_debug)
   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);
 
 
   gdb_assert (per_objfile->get_cu (this_cu) == nullptr);
 
@@ -6849,34 +6523,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)
 {
 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);
   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;
 
   tu_group->hash.dwo_unit = cu->dwo_unit;
   tu_group->hash.line_sect_off = line_offset_struct;
@@ -6938,162 +6585,235 @@ get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list)
   return tu_group;
 }
 \f
   return tu_group;
 }
 \f
-/* Partial symbol tables.  */
 
 
-/* Create a psymtab named NAME and assign it to PER_CU.
+/* An instance of this is created when scanning DWARF to create a
+   cooked index.  */
 
 
-   The caller must fill in the following details:
-   dirname, textlow, texthigh.  */
-
-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);
+public:
 
 
-  pst->psymtabs_addrmap_supported = true;
+  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))
+  {
+  }
 
 
-  /* This is the glue that links PST into GDB's symbol API.  */
-  per_cu->v.psymtab = pst;
+  DISABLE_COPY_AND_ASSIGN (cooked_index_storage);
 
 
-  return pst;
-}
-
-/* DIE reader function for process_psymtab_comp_unit.  */
-
-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;
-
-  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.  */
-  static const char artificial[] = "<artificial>";
-  file_and_directory &fnd = find_file_and_directory (comp_unit_die, cu);
-  if (strcmp (fnd.get_name (), artificial) == 0)
-    {
-      gdb::unique_xmalloc_ptr<char> debug_filename
-       (concat (artificial, "@",
-                sect_offset_str (per_cu->sect_off),
-                (char *) NULL));
-      fnd.set_name (std::move (debug_filename));
-    }
+  /* 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.  */
 
 /* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
    Process compilation unit THIS_CU for a psymtab.  */
@@ -7101,17 +6821,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,
 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;
 
   if (reader.comp_unit_die == nullptr)
     return;
@@ -7139,59 +6852,41 @@ process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu,
       /* Nothing.  */
     }
   else if (this_cu->is_debug_types)
       /* 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
 }
 
 /* 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 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);
 
   gdb_assert (per_cu->is_debug_types);
-  sig_type = (struct signatured_type *) per_cu;
 
   if (! type_unit_die->has_children)
     return;
 
 
   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);
   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.  */
 }
 
 /* Struct used to sort TUs by their abbreviation table offset.  */
@@ -7230,7 +6925,8 @@ struct tu_abbrev_offset
    dwarf2_per_objfile->per_bfd->type_unit_groups.  */
 
 static void
    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;
 {
   struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
   abbrev_table_up abbrev_table;
@@ -7299,8 +6995,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)
       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 +7020,11 @@ print_tu_stats (dwarf2_per_objfile *per_objfile)
                           tu_stats->nr_all_type_units_reallocs);
 }
 
                           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.  */
 
 /* Traversal function for process_skeletonless_type_unit.
    Read a TU in a DWO file and build partial symbols for it.  */
@@ -7363,15 +7033,16 @@ static int
 process_skeletonless_type_unit (void **slot, void *info)
 {
   struct dwo_unit *dwo_unit = (struct dwo_unit *) *slot;
 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 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);
 
   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.  */
                         &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 +7052,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
   /* 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.  */
   *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)
   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;
 }
 
   return 1;
 }
@@ -7413,36 +7083,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
    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,
   /* 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 +7110,97 @@ dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile)
   dwarf_read_debug_printf ("Building psymtabs of objfile %s ...",
                           objfile_name (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);
   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.  */
 
   /* 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);
 
 
   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 ();
+  per_bfd->cooked_index_table.reset
+    (new cooked_index_vector (std::move (indexes)));
+
+  const cooked_index_entry *main_entry
+    = per_bfd->cooked_index_table->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));
 }
 
 
   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,
 static void
 read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
                              struct dwarf2_section_info *section,
@@ -7619,677 +7283,65 @@ create_all_comp_units (dwarf2_per_objfile *per_objfile)
 
   dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd);
   if (dwz != NULL)
 
   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);
+    {
+      /* 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);
+    }
 
   per_objfile->per_bfd->signatured_types = std::move (types_htab);
 }
 
 
   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.  */
+/* Return the initial uleb128 in the die at INFO_PTR.  */
 
 
-static void
-scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
-                     CORE_ADDR *highpc, int set_addrmap,
-                     struct dwarf2_cu *cu)
+static unsigned int
+peek_abbrev_code (bfd *abfd, const gdb_byte *info_ptr)
 {
 {
-  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.  */
+  unsigned int bytes_read;
 
 
-      pdi = pdi->die_sibling;
-    }
+  return read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
 }
 
 }
 
-/* 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.
+/* Read the initial uleb128 in the die at INFO_PTR in compilation unit
+   READER::CU.  Use READER::ABBREV_TABLE to lookup any abbreviation.
 
 
-   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.  */
+   Return the corresponding abbrev, or NULL if the number is zero (indicating
+   an empty DIE).  In either case *BYTES_READ will be set to the length of
+   the initial number.  */
 
 
-/* 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)
+static const struct abbrev_info *
+peek_die_abbrev (const die_reader_specs &reader,
+                const gdb_byte *info_ptr, unsigned int *bytes_read)
 {
 {
-  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;
-    }
+  dwarf2_cu *cu = reader.cu;
+  bfd *abfd = reader.abfd;
+  unsigned int abbrev_number
+    = read_unsigned_leb128 (abfd, info_ptr, bytes_read);
 
 
-  parent = real_pdi->die_parent;
-  if (parent == NULL)
+  if (abbrev_number == 0)
     return 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
+  const abbrev_info *abbrev
+    = reader.abbrev_table->lookup_abbrev (abbrev_number);
+  if (!abbrev)
     {
     {
-      /* 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;
+      error (_("Dwarf Error: Could not find abbrev number %d in %s"
+              " at offset %s [in module %s]"),
+            abbrev_number, cu->per_cu->is_debug_types ? "TU" : "CU",
+            sect_offset_str (cu->header.sect_off), bfd_get_filename (abfd));
     }
 
     }
 
-  parent->scope_set = 1;
-  return parent->scope;
+  return abbrev;
 }
 
 }
 
-/* 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;
-       }
-    }
-}
-
-/* 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;
-    }
-}
-
-/* Return the initial uleb128 in the die at INFO_PTR.  */
-
-static unsigned int
-peek_abbrev_code (bfd *abfd, const gdb_byte *info_ptr)
-{
-  unsigned int bytes_read;
-
-  return read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
-}
-
-/* Read the initial uleb128 in the die at INFO_PTR in compilation unit
-   READER::CU.  Use READER::ABBREV_TABLE to lookup any abbreviation.
-
-   Return the corresponding abbrev, or NULL if the number is zero (indicating
-   an empty DIE).  In either case *BYTES_READ will be set to the length of
-   the initial number.  */
-
-static const struct abbrev_info *
-peek_die_abbrev (const die_reader_specs &reader,
-                const gdb_byte *info_ptr, unsigned int *bytes_read)
-{
-  dwarf2_cu *cu = reader.cu;
-  bfd *abfd = reader.abfd;
-  unsigned int abbrev_number
-    = read_unsigned_leb128 (abfd, info_ptr, bytes_read);
-
-  if (abbrev_number == 0)
-    return NULL;
-
-  const abbrev_info *abbrev
-    = reader.abbrev_table->lookup_abbrev (abbrev_number);
-  if (!abbrev)
-    {
-      error (_("Dwarf Error: Could not find abbrev number %d in %s"
-              " at offset %s [in module %s]"),
-            abbrev_number, cu->per_cu->is_debug_types ? "TU" : "CU",
-            sect_offset_str (cu->header.sect_off), bfd_get_filename (abfd));
-    }
-
-  return abbrev;
-}
-
-/* Scan the debug information for CU starting at INFO_PTR in buffer BUFFER.
-   Returns a pointer to the end of a series of DIEs, terminated by an empty
-   DIE.  Any children of the skipped DIEs will also be skipped.  */
+/* Scan the debug information for CU starting at INFO_PTR in buffer BUFFER.
+   Returns a pointer to the end of a series of DIEs, terminated by an empty
+   DIE.  Any children of the skipped DIEs will also be skipped.  */
 
 static const gdb_byte *
 skip_children (const struct die_reader_specs *reader, const gdb_byte *info_ptr)
 
 static const gdb_byte *
 skip_children (const struct die_reader_specs *reader, const gdb_byte *info_ptr)
@@ -8310,12 +7362,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
 /* 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,
 
 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;
 {
   unsigned int bytes_read;
   struct attribute attr;
@@ -8325,10 +7380,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;
 
   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.  */
   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)
        {
          read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
          if (attr.form == DW_FORM_ref_addr)
@@ -8445,62 +7519,11 @@ 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;
 }
     return skip_children (reader, info_ptr);
   else
     return info_ptr;
 }
-
-/* Locate ORIG_PDI's sibling.
-   INFO_PTR should point to the start of the next DIE after ORIG_PDI.  */
-
-static const gdb_byte *
-locate_pdi_sibling (const struct die_reader_specs *reader,
-                   struct partial_die_info *orig_pdi,
-                   const gdb_byte *info_ptr)
-{
-  /* 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.  */
-
-  return skip_children (reader, info_ptr);
-}
-
-/* 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.  */
 
 \f
 /* Reading in full CUs.  */
 
@@ -8548,18 +7571,6 @@ maybe_queue_comp_unit (struct dwarf2_cu *dependent_cu,
                       dwarf2_per_objfile *per_objfile,
                       enum language pretend_language)
 {
                       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)
   /* Mark the dependence relation so that we don't flush PER_CU
      too early.  */
   if (dependent_cu != NULL)
@@ -8664,39 +7675,6 @@ process_queue (dwarf2_per_objfile *per_objfile)
                           objfile_name (per_objfile->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.  */
 
 /* Trivial hash function for die_info: the hash value of a DIE
    is its offset in .debug_info for this objfile.  */
 
@@ -8879,7 +7857,7 @@ fixup_go_packaging (struct dwarf2_cu *cu)
          struct symbol *sym = list->symbol[i];
 
          if (sym->language () == language_go
          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));
            {
              gdb::unique_xmalloc_ptr<char> this_package_name
                (go_symbol_package_name (sym));
@@ -8916,9 +7894,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().  */
       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 ());
     }
 
       add_symbol_to_list (sym, cu->get_builder ()->get_global_symbols ());
     }
@@ -9456,7 +8434,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);
   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
 
   /* 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 +8444,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);
 
      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)
     {
 
   if (cust != NULL)
     {
@@ -9477,8 +8455,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
         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
 
       /* 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 +8471,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)
         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)
 
       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);
     }
 
       cust->set_call_site_htab (cu->call_site_htab);
     }
@@ -9562,8 +8540,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
             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
        }
     }
   else
@@ -9694,6 +8672,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_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:
       process_structure_scope (die, cu);
       break;
     case DW_TAG_enumeration_type:
@@ -9721,6 +8700,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       /* FALLTHROUGH */
     case DW_TAG_base_type:
     case DW_TAG_subrange_type:
       /* 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.  */
     case DW_TAG_typedef:
       /* Add a typedef symbol for the type definition, if it has a
         DW_AT_name.  */
@@ -10502,7 +9482,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,
 
 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;
 {
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
   struct attribute *attr;
@@ -10590,9 +9570,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);
       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.  */
 }
 
 /* Process DW_TAG_compile_unit or DW_TAG_partial_unit.  */
@@ -10622,7 +9600,8 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
 
   file_and_directory &fnd = find_file_and_directory (die, 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
 
   gdb_assert (per_objfile->sym_cu == nullptr);
   scoped_restore restore_sym_cu
@@ -10630,8 +9609,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
 
   /* 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)
 
   /* Process all dies in compilation unit.  */
   if (die->child != NULL)
@@ -10710,15 +9694,15 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
   if (lh == NULL)
     {
       if (first_time)
   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
       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 ();
                            compunit_language (cust),
                            0, cust));
          list_in_scope = get_builder ()->get_file_symbols ();
@@ -10731,7 +9715,7 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
 
   if (first_time)
     {
 
   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)
 
       /* 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 +9723,7 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
         time.  */
 
       tug_unshare->symtabs
         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 ();
                     struct symtab *, line_header->file_names_size ());
 
       auto &file_names = line_header->file_names ();
@@ -10769,8 +9753,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
       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 ();
                        compunit_language (cust),
                        0, cust));
       list_in_scope = get_builder ()->get_file_symbols ();
@@ -12201,69 +11185,47 @@ open_dwo_file (dwarf2_per_objfile *per_objfile,
    size of each of the DWO debugging sections we are interested in.  */
 
 static void
    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;
 
 {
   const struct dwop_section_names *names = &dwop_section_names;
 
+  struct dwarf2_section_info *dw_sect = nullptr;
+
   if (names->abbrev_dwo.matches (sectp->name))
   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))
   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))
   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))
   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))
   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))
   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))
   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))
   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))
   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))
   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));
   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);
       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 +11253,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))
   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);
 
   create_cus_hash_table (per_objfile, cu, *dwo_file, dwo_file->sections.info,
                         dwo_file->cus);
@@ -12319,8 +11281,8 @@ open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name,
    we are interested in.  */
 
 static void
    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;
 {
   const struct dwop_section_names *names = &dwop_section_names;
   unsigned int elf_section_nr = elf_section_data (sectp)->this_idx;
@@ -12331,20 +11293,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.  */
   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))
   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))
   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))
   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 +11315,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
    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;
 {
   struct dwp_file *dwp_file = (struct dwp_file *) dwp_file_ptr;
   const struct dwop_section_names *names = &dwop_section_names;
@@ -12366,45 +11328,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.  */
   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))
   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))
   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))
   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))
   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))
   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))
   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))
   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))
   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 +11360,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
    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;
 {
   struct dwp_file *dwp_file = (struct dwp_file *) dwp_file_ptr;
   const struct dwop_section_names *names = &dwop_section_names;
@@ -12426,40 +11373,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.  */
   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))
   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))
   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))
   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))
   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))
   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))
   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))
   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 +11520,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))
                    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);
                                       dwp_file.get ());
 
   dwp_file->cus = create_dwp_hash_table (per_objfile, dwp_file.get (), 0);
@@ -12616,10 +11550,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)
   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
                                       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 ());
     }
 
                                       dwp_file.get ());
     }
 
@@ -13070,7 +12004,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
     }
 
   /* Ignore functions with missing or invalid low and high pc attributes.  */
     }
 
   /* 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);
       <= PC_BOUNDS_INVALID)
     {
       attr = dwarf2_attr (die, DW_AT_external, cu);
@@ -13243,7 +12177,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.  */
      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
     {
     case PC_BOUNDS_NOT_PRESENT:
       /* DW_TAG_lexical_block has no attributes, process its children as if
@@ -13305,6 +12239,11 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
   cu->get_builder ()->set_local_using_directives (cstk.local_using_directives);
 }
 
   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
 /* Read in DW_TAG_call_site and insert it to CU->call_site_htab.  */
 
 static void
@@ -13468,6 +12407,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);
 
       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;
       if (die_is_declaration (target_die, target_cu))
        {
          const char *target_physname;
@@ -13483,12 +12426,25 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
          else
            call_site->target.set_loc_physname (target_physname);
        }
          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.  */
       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]"),
              <= PC_BOUNDS_INVALID)
            complaint (_("DW_AT_call_target target DIE has invalid "
                         "low pc, for referencing DIE %s [in module %s]"),
@@ -13989,15 +12945,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.
 
 /* 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,
 
 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;
 {
   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;
   struct gdbarch *gdbarch = objfile->arch ();
   const CORE_ADDR baseaddr = objfile->text_section_offset ();
   int low_set = 0;
@@ -14008,7 +12964,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)
     {
   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;
        {
          CORE_ADDR lowpc;
          CORE_ADDR highpc;
@@ -14019,8 +12975,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
          highpc = (gdbarch_adjust_dwarf2_addr (gdbarch,
                                                range_end + baseaddr)
                    - baseaddr);
          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
        }
 
       /* FIXME: This is recording everything as a low-high
@@ -14056,6 +13011,20 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
   return 1;
 }
 
   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.  */
 /* 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 +13032,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,
 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;
 {
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
   struct attribute *attr;
@@ -14106,8 +13075,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.  */
 
          /* 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;
            return PC_BOUNDS_INVALID;
          /* Found discontinuous range of addresses.  */
          ret = PC_BOUNDS_RANGES;
@@ -14150,7 +13119,8 @@ dwarf2_get_subprogram_pc_bounds (struct die_info *die,
   CORE_ADDR low, high;
   struct die_info *child = die->child;
 
   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);
     {
       *lowpc = std::min (*lowpc, low);
       *highpc = std::max (*highpc, high);
@@ -14187,7 +13157,8 @@ get_scope_pc_bounds (struct die_info *die,
   CORE_ADDR best_high = (CORE_ADDR) 0;
   CORE_ADDR current_low, current_high;
 
   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;
       >= PC_BOUNDS_RANGES)
     {
       best_low = current_low;
@@ -14315,6 +13286,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_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))
     {
     }
   else if (producer_is_icc (cu->producer, &major, &minor))
     {
@@ -14459,6 +13431,19 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
       if (attr->form_is_constant ())
        {
          LONGEST offset = attr->constant_value (0);
       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 ())
          field->set_loc_bitpos (offset * bits_per_byte);
        }
       else if (attr->form_is_section_offset ())
@@ -14537,8 +13522,21 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
 
   fp = &new_field->field;
 
 
   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.  */
       /* Data member other than a C++ static data member.  */
 
       /* Get type of field.  */
@@ -15596,6 +14594,10 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
     {
       type->set_code (TYPE_CODE_UNION);
     }
     {
       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);
   else
     {
       type->set_code (TYPE_CODE_STRUCT);
@@ -15798,7 +14800,8 @@ handle_struct_member_die (struct die_info *child_die, struct type *type,
                          struct dwarf2_cu *cu)
 {
   if (child_die->tag == DW_TAG_member
                          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
     {
       /* NOTE: carlton/2002-11-05: A C++ static data member
         should be a DW_TAG_member that is a declaration, but
@@ -15841,8 +14844,10 @@ handle_struct_member_die (struct die_info *child_die, struct type *type,
     handle_variant (child_die, type, fi, template_args, cu);
 }
 
     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)
 
 static void
 process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
@@ -16612,7 +15617,8 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
   child_die = die->child;
   while (child_die && child_die->tag)
     {
   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);
 
        {
          struct type *child_type = read_type_die (child_die, cu);
 
@@ -16846,7 +15852,7 @@ mark_common_block_symbol_computed (struct symbol *sym,
   gdb_assert (ptr - baton->data == baton->size);
 
   SYMBOL_LOCATION_BATON (sym) = baton;
   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
 }
 
 /* Create appropriate locally-scoped variables for all the
@@ -16945,7 +15951,7 @@ read_common_block (struct die_info *die, struct dwarf2_cu *cu)
        }
 
       sym = new_symbol (die, objfile_type (objfile)->builtin_void, 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 +17791,11 @@ read_die_and_siblings (const struct die_reader_specs *reader,
 
   if (dwarf_die_debug)
     {
 
   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);
     }
 
       dump_die (die, dwarf_die_debug);
     }
 
@@ -18891,11 +17897,11 @@ read_full_die (const struct die_reader_specs *reader,
 
   if (dwarf_die_debug)
     {
 
   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);
     }
 
       dump_die (*diep, dwarf_die_debug);
     }
 
@@ -18903,825 +17909,841 @@ read_full_die (const struct die_reader_specs *reader,
 }
 \f
 
 }
 \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_class_type:
-    case DW_TAG_interface_type:
-    case DW_TAG_enumeration_type:
     case DW_TAG_structure_type:
     case DW_TAG_structure_type:
-    case DW_TAG_subrange_type:
-    case DW_TAG_typedef:
     case DW_TAG_union_type:
     case DW_TAG_union_type:
-      return 1;
+    case DW_TAG_variable:
+    case DW_TAG_subprogram:
+      return true;
+
     default:
     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;
-
-  parent_die = NULL;
-  last_die = NULL;
-
-  gdb_assert (cu->per_cu != NULL);
-  if (cu->load_all_dies)
-    load_all = 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;
 
 
-  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);
+  dwarf2_per_cu_data *per_cu
+    = dwarf2_find_containing_comp_unit (sect_off, is_dwz,
+                                       per_objfile->per_bfd);
 
 
-  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 *
 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;
     {
       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 ())
       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:
       /* 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_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;
              break;
+
            default:
            default:
-             canonical_name = 0;
-             raw_name = attr.as_string ();
+             if (*name == nullptr)
+               *name = attr.as_string ();
              break;
            }
          break;
              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.  */
        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 ();
+         if (*linkage_name == nullptr)
+           *linkage_name = attr.as_string ();
          break;
          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");
-           }
-         break;
-       case DW_AT_external:
-         is_external = attr.as_boolean ();
+
+       case DW_AT_main_subprogram:
+         if (attr.as_boolean ())
+           *flags |= IS_MAIN;
          break;
          break;
+
        case DW_AT_declaration:
          is_declaration = attr.as_boolean ();
          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;
          break;
-       case DW_AT_abstract_origin:
+
        case DW_AT_specification:
        case DW_AT_specification:
+       case DW_AT_abstract_origin:
        case DW_AT_extension:
        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;
          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;
          break;
-       case DW_AT_const_value:
-         has_const_value = 1;
+
+       case DW_AT_enum_class:
+         if (attr.as_boolean ())
+           *flags |= IS_ENUM_CLASS;
          break;
          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;
          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;
 
          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;
 
            }
          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;
          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));
 
 
-           /* 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;
+         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);
+           }
 
 
-           has_range_info = 1;
-         }
-         break;
+         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);
+       }
+    }
 
 
-       default:
-         break;
+  if (!for_specification)
+    {
+      if (m_language == language_ada
+         && *linkage_name == nullptr)
+       *linkage_name = *name;
+
+      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;
 
 
-  if (high_pc_relative)
-    highpc += lowpc;
+           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 (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_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;
 
 
-         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 ();
+           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 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 != sect_offset (0))
+           {
+             const gdb_byte *sibling_ptr
+               = reader->buffer + to_underlying (sibling);
+
+             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;
 }
 
     }
 
   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");
+  }
+
+  void expand_matching_symbols
+    (struct objfile *,
+     const lookup_name_info &lookup_name,
+     domain_enum domain,
+     int global,
+     symbol_compare_ftype *ordered_compare) override;
 
 
-      cu = per_objfile->get_cu (per_cu);
+  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;
 
 
-      cu->last_used = 0;
-      pd = cu->find_partial_die (sect_off);
-    }
+  bool can_lazily_read_symbols () override
+  {
+    return true;
+  }
 
 
-  /* If we didn't find it, and not all dies have been loaded,
-     load them all and try again.  */
+  void read_partial_symbols (struct objfile *objfile) override
+  {
+    if (dwarf2_has_info (objfile, nullptr))
+      dwarf2_build_psymtabs (objfile, true);
+  }
+};
 
 
-  if (pd == NULL && cu->load_all_dies == 0)
-    {
-      cu->load_all_dies = 1;
+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->cooked_index_table == nullptr)
+    return nullptr;
 
 
-      /* 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);
+  CORE_ADDR baseaddr = objfile->text_section_offset ();
+  dwarf2_per_cu_data *per_cu
+    = per_objfile->per_bfd->cooked_index_table->lookup (pc - baseaddr);
+  if (per_cu == nullptr)
+    return nullptr;
 
 
-      pd = cu->find_partial_die (sect_off);
-    }
+  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));
 
 
-  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 };
+  compunit_symtab *result = (recursively_find_pc_sect_compunit_symtab
+                            (dw2_instantiate_symtab (per_cu, per_objfile,
+                                                     false),
+                             pc));
+  gdb_assert (result != nullptr);
+  return result;
 }
 
 }
 
-/* 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.  */
-
-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->cooked_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 ();
+  dwarf2_per_cu_data *per_cu
+    = per_objfile->per_bfd->cooked_index_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->cooked_index_table == nullptr)
     return;
     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);
 
 
-  for (child_pdi = struct_pdi->die_child;
-       child_pdi != NULL;
-       child_pdi = child_pdi->die_sibling)
+  for (const cooked_index_entry *entry
+        : per_objfile->per_bfd->cooked_index_table->all_entries ())
     {
     {
-      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;
-       }
-    }
-}
+      if (entry->parent_entry != nullptr)
+       continue;
 
 
-/* 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->cooked_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);
+  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
+          : per_objfile->per_bfd->cooked_index_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
          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);
 }
 
 }
 
+\f
+
 /* Read the .debug_loclists or .debug_rnglists header (they are the same format)
    contents from the given SECTION in the HEADER.
 
 /* Read the .debug_loclists or .debug_rnglists header (they are the same format)
    contents from the given SECTION in the HEADER.
 
@@ -20791,8 +19813,7 @@ class lnp_state_machine
 public:
   /* Initialize a machine state for the start of a line number
      program.  */
 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 ()
   {
 
   file_entry *current_file ()
   {
@@ -20843,7 +19864,7 @@ public:
   /* Handle DW_LNS_negate_stmt.  */
   void handle_negate_stmt ()
   {
   /* 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.  */
   }
 
   /* Handle DW_LNS_const_add_pc.  */
@@ -20861,6 +19882,7 @@ public:
   {
     record_line (false);
     m_discriminator = 0;
   {
     record_line (false);
     m_discriminator = 0;
+    m_flags &= ~LEF_PROLOGUE_END;
   }
 
   /* Handle DW_LNE_end_sequence.  */
   }
 
   /* Handle DW_LNE_end_sequence.  */
@@ -20869,6 +19891,12 @@ public:
     m_currently_recording_lines = true;
   }
 
     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)
 private:
   /* Advance the line by LINE_DELTA.  */
   void advance_line (int line_delta)
@@ -20883,11 +19911,6 @@ private:
 
   gdbarch *m_gdbarch;
 
 
   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;
 
   /* The line number header.  */
   line_header *m_line_header;
 
@@ -20902,7 +19925,7 @@ private:
   /* These are initialized in the constructor.  */
 
   CORE_ADDR m_address;
   /* 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.  */
   unsigned int m_discriminator;
 
   /* Additional bits of state we need to track.  */
@@ -20917,9 +19940,9 @@ private:
   CORE_ADDR m_last_address;
 
   /* Set to true when a previous line at the same address (using
   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.  */
   bool m_stmt_at_address = false;
 
   /* When true, record the lines we decode.  */
@@ -20960,6 +19983,7 @@ lnp_state_machine::handle_special_opcode (unsigned char op_code)
   advance_line (line_delta);
   record_line (false);
   m_discriminator = 0;
   advance_line (line_delta);
   record_line (false);
   m_discriminator = 0;
+  m_flags &= ~LEF_PROLOGUE_END;
 }
 
 void
 }
 
 void
@@ -20970,7 +19994,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 ();
   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);
 
     {
       const char *dir = fe->include_dir (m_line_header);
 
@@ -21049,21 +20073,22 @@ dwarf_record_line_p (struct dwarf2_cu *cu,
 
 static void
 dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
 
 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)
     {
                     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),
+                 paddress (gdbarch, address));
     }
 
   if (cu != nullptr)
     }
 
   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.
 }
 
 /* Subroutine of dwarf_decode_lines_1 to simplify it.
@@ -21080,13 +20105,13 @@ dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile,
 
   if (dwarf_line_debug)
     {
 
   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),
+                 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
 }
 
 void
@@ -21094,13 +20119,15 @@ lnp_state_machine::record_line (bool end_sequence)
 {
   if (dwarf_line_debug)
     {
 {
   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 ();
     }
 
   file_entry *fe = current_file ();
@@ -21112,73 +20139,71 @@ lnp_state_machine::record_line (bool end_sequence)
      previous version of the code.  */
   else if (m_op_index == 0 || 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;
     }
      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,
 }
 
 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_cu = cu;
   m_gdbarch = arch;
-  m_record_lines_p = record_lines_p;
   m_line_header = lh;
 
   m_currently_recording_lines = true;
   m_line_header = lh;
 
   m_currently_recording_lines = true;
@@ -21188,7 +20213,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);
      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;
   m_discriminator = 0;
 
   m_last_address = m_address;
@@ -21223,13 +20250,11 @@ lnp_state_machine::check_line_address (struct dwarf2_cu *cu,
 }
 
 /* Subroutine of dwarf_decode_lines to simplify it.
 }
 
 /* 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,
 
 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;
 {
   const gdb_byte *line_ptr, *extended_end;
   const gdb_byte *line_end;
@@ -21239,10 +20264,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 ();
   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 ();
 
 
   baseaddr = objfile->text_section_offset ();
 
@@ -21254,18 +20275,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.  */
     {
       /* 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;
 
       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)
 
       /* Decode the table.  */
       while (line_ptr < line_end && !end_sequence)
@@ -21416,6 +20434,9 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
                state_machine.handle_fixed_advance_pc (addr_adj);
              }
              break;
                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.  */
            default:
              {
                /* Unknown standard opcode, ignore it.  */
@@ -21443,13 +20464,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.
 
    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.
 
    FND holds the CU file name and directory, if known.
    It is used for relative paths in the line table.
 
@@ -21467,52 +20481,28 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
    table is read in.  */
 
 static void
    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)
 {
                    CORE_ADDR lowpc, int decode_mapping)
 {
-  struct objfile *objfile = cu->per_objfile->objfile;
-  const int decode_for_pst_p = (pst != NULL);
-
   if (decode_mapping)
   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);
        }
        }
+      fe.symtab = builder->get_current_subfile ()->symtab;
     }
 }
 
     }
 }
 
@@ -21582,7 +20572,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)
     {
      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;
     }
 
       return;
     }
 
@@ -21605,19 +20595,16 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
          unsigned int dummy;
 
          if (block->data[0] == DW_OP_addr)
          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
          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);
          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;
        }
             + objfile->section_offsets[sym->section_index ()]);
          return;
        }
@@ -21698,17 +20685,17 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
 
       /* Default assumptions.
         Use the passed type or decode it from the die.  */
 
       /* 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)
       if (type != NULL)
-       SYMBOL_TYPE (sym) = type;
+       sym->set_type (type);
       else
       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)
       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,
 
       attr = dwarf2_attr (die,
                          inlined_func ? DW_AT_call_file : DW_AT_decl_file,
@@ -21740,19 +20727,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);
 
              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
            }
          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.  */
          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
          attr2 = dwarf2_attr (die, DW_AT_external, cu);
          if ((attr2 != nullptr && attr2->as_boolean ())
              || cu->per_cu->lang == language_ada
@@ -21774,8 +20761,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.  */
        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:
          list_to_add = cu->list_in_scope;
          break;
        case DW_TAG_template_value_param:
@@ -21787,8 +20774,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.  */
          /* 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
 
          attr = dwarf2_attr (die, DW_AT_const_value, cu);
          /* In the case of DW_TAG_member, we should only be called for
@@ -21825,8 +20812,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
                  && die->parent->tag == DW_TAG_common_block)
                attr2 = NULL;
 
                  && 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,
                  && !per_objfile->per_bfd->has_section_at_zero)
                {
                  /* When a static variable is eliminated by the linker,
@@ -21836,7 +20823,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
                }
              else if (attr2 != nullptr && attr2->as_boolean ())
                {
                }
              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)
                    {
                      && (objfile->flags & OBJF_MAINLINE) == 0
                      && per_objfile->per_bfd->can_copy)
                    {
@@ -21894,12 +20881,12 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
                       ? cu->get_builder ()->get_global_symbols ()
                       : cu->list_in_scope);
 
                       ? 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.  */
                }
              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;
                }
                  if (!suppress_add)
                    list_to_add = cu->list_in_scope;
                }
@@ -21915,7 +20902,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)
            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)
              {
            attr = dwarf2_attr (die, DW_AT_location, cu);
            if (attr != nullptr)
              {
@@ -21944,9 +20931,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:
        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
          {
            /* NOTE: carlton/2003-11-10: C++ class symbols shouldn't
               really ever be static objects: otherwise, if you try
@@ -21975,22 +20970,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.  */
                    /* 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:
                  }
              }
          }
          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:
          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:
          list_to_add = cu->list_in_scope;
          break;
        case DW_TAG_enumerator:
@@ -22012,17 +21008,17 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
          break;
        case DW_TAG_imported_declaration:
        case DW_TAG_namespace:
          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:
          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:
          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:
          add_symbol_to_list (sym, cu->list_in_scope);
          break;
        default:
@@ -22211,7 +21207,7 @@ dwarf2_const_value (const struct attribute *attr, struct symbol *sym,
   const gdb_byte *bytes;
   struct dwarf2_locexpr_baton *baton;
 
   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);
                           sym->print_name (),
                           &objfile->objfile_obstack, cu,
                           &value, &bytes, &baton);
@@ -22219,17 +21215,17 @@ dwarf2_const_value (const struct attribute *attr, struct symbol *sym,
   if (baton != NULL)
     {
       SYMBOL_LOCATION_BATON (sym) = baton;
   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)
     }
   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
     {
     }
   else
     {
-      SYMBOL_VALUE (sym) = value;
-      SYMBOL_ACLASS_INDEX (sym) = LOC_CONST;
+      sym->set_value_longest (value);
+      sym->set_aclass_index (LOC_CONST);
     }
 }
 
     }
 }
 
@@ -22482,6 +21478,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_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;
     case DW_TAG_subrange_type:
       this_type = read_subrange_type (die, cu);
       break;
@@ -22883,6 +21880,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_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;
 
       && die->tag != DW_TAG_union_type)
     return NULL;
 
@@ -22907,6 +21905,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_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
       /* 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 +21979,82 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
 {
   unsigned int i;
 
 {
   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)
 
   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)
     {
 
   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:
 
       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:
          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:
          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:
          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:
          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:
          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:
          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:
          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:
          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:
          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:
          break;
        case DW_FORM_string:
        case DW_FORM_strp:
@@ -23066,37 +22062,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:
        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 ())
          break;
        case DW_FORM_flag:
          if (die->attrs[i].as_boolean ())
-           fprintf_unfiltered (f, "flag: TRUE");
+           gdb_printf (f, "flag: TRUE");
          else
          else
-           fprintf_unfiltered (f, "flag: FALSE");
+           gdb_printf (f, "flag: FALSE");
          break;
        case DW_FORM_flag_present:
          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.  */
          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:
          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:
          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;
        }
          break;
        }
-      fprintf_unfiltered (f, "\n");
+      gdb_printf (f, "\n");
     }
 }
 
     }
 }
 
@@ -23120,17 +22116,16 @@ dump_die_1 (struct ui_file *f, int level, int max_level, struct die_info *die)
 
   if (die->child != NULL)
     {
 
   if (die->child != NULL)
     {
-      print_spaces (indent, f);
-      fprintf_unfiltered (f, "  Children:");
+      gdb_printf (f, "%*s  Children:", indent, "");
       if (level + 1 < max_level)
        {
       if (level + 1 < max_level)
        {
-         fprintf_unfiltered (f, "\n");
+         gdb_printf (f, "\n");
          dump_die_1 (f, level + 1, max_level, die->child);
        }
       else
        {
          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 +22240,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.  */
   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);
     }
       load_full_comp_unit (cu->per_cu, per_objfile, cu, false,
                           language_minimal);
     }
@@ -23787,9 +22781,6 @@ load_full_type_unit (dwarf2_per_cu_data *per_cu,
 {
   struct signatured_type *sig_type;
 
 {
   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);
   /* 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 +23317,9 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym,
        complaint (_("Location list used without "
                     "specifying the CU base address."));
 
        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
       SYMBOL_LOCATION_BATON (sym) = baton;
     }
   else
@@ -24358,9 +23349,9 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym,
          baton->size = 0;
        }
 
          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;
     }
 }
       SYMBOL_LOCATION_BATON (sym) = baton;
     }
 }
@@ -24767,6 +23758,15 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
        type->add_dyn_prop (DYN_PROP_ASSOCIATED, prop);
     }
 
        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)
     {
   /* Read DW_AT_data_location and set in type.  */
   if (!skip_data_location)
     {
@@ -24828,32 +23828,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);
 }
 
   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;
 
 struct cmd_list_element *set_dwarf_cmdlist;
 struct cmd_list_element *show_dwarf_cmdlist;
 
@@ -24861,9 +23835,9 @@ static void
 show_check_physname (struct ui_file *file, int from_tty,
                     struct cmd_list_element *c, const char *value)
 {
 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 ();
 }
 
 void _initialize_dwarf2_read ();