gdb: use decltype instead of typeof in dwarf2/read.c
[binutils-gdb.git] / gdb / dwarf2 / read.c
index 9292e52c0001c1779e1bc22cf65136ee3160e8dc..7c148aecdf5aec45b02374b90a0d4f92c14cd909 100644 (file)
@@ -1,6 +1,6 @@
 /* DWARF 2 debugging format support for GDB.
 
-   Copyright (C) 1994-2021 Free Software Foundation, Inc.
+   Copyright (C) 1994-2022 Free Software Foundation, Inc.
 
    Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
    Inc.  with support from Florida State University (under contract
@@ -64,7 +64,6 @@
 #include "block.h"
 #include "addrmap.h"
 #include "typeprint.h"
-#include "psympriv.h"
 #include "c-lang.h"
 #include "go-lang.h"
 #include "valprint.h"
 #include "gdbsupport/pathstuff.h"
 #include "count-one-bits.h"
 #include <unordered_set>
+#include "dwarf2/abbrev-cache.h"
+#include "cooked-index.h"
+#include "split-name.h"
+#include "gdbsupport/parallel-for.h"
+#include "gdbsupport/thread-pool.h"
 
 /* When == 1, print basic high level tracing messages.
    When > 1, be more verbose.
@@ -362,7 +366,7 @@ struct mapped_debug_names final : public mapped_index_base
   { return this->name_count; }
 };
 
-/* See dwarf2read.h.  */
+/* See dwarf2/read.h.  */
 
 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.  */
 
-struct type_unit_group : public dwarf2_per_cu_data
+struct type_unit_group
 {
-  /* The TUs that share this DW_AT_stmt_list entry.
-     This is added to while parsing type units to build partial symtabs,
-     and is deleted afterwards and not used again.  */
-  std::vector<signatured_type *> *tus = nullptr;
-
   /* The data used to construct the hash key.  */
   struct stmt_list_hash hash {};
 };
@@ -791,7 +790,8 @@ public:
               dwarf2_per_objfile *per_objfile,
               struct abbrev_table *abbrev_table,
               dwarf2_cu *existing_cu,
-              bool skip_partial);
+              bool skip_partial,
+              abbrev_cache *cache = nullptr);
 
   explicit cutu_reader (struct dwarf2_per_cu_data *this_cu,
                        dwarf2_per_objfile *per_objfile,
@@ -800,6 +800,8 @@ public:
 
   DISABLE_COPY_AND_ASSIGN (cutu_reader);
 
+  cutu_reader (cutu_reader &&) = default;
+
   const gdb_byte *info_ptr = nullptr;
   struct die_info *comp_unit_die = nullptr;
   bool dummy_p = false;
@@ -808,6 +810,13 @@ public:
      for dummy CUs.  */
   void keep ();
 
+  /* Release the abbrev table, transferring ownership to the
+     caller.  */
+  abbrev_table_up release_abbrev_table ()
+  {
+    return std::move (m_abbrev_table_holder);
+  }
+
 private:
   void init_tu_and_read_dwo_dies (dwarf2_per_cu_data *this_cu,
                                  dwarf2_per_objfile *per_objfile,
@@ -823,150 +832,6 @@ private:
   abbrev_table_up m_dwo_abbrev_table;
 };
 
-/* When we construct a partial symbol table entry we only
-   need this much information.  */
-struct partial_die_info : public allocate_on_obstack
-  {
-    partial_die_info (sect_offset sect_off, const struct abbrev_info *abbrev);
-
-    /* Disable assign but still keep copy ctor, which is needed
-       load_partial_dies.   */
-    partial_die_info& operator=(const partial_die_info& rhs) = delete;
-    partial_die_info (const partial_die_info &) = default;
-
-    /* Adjust the partial die before generating a symbol for it.  This
-       function may set the is_external flag or change the DIE's
-       name.  */
-    void fixup (struct dwarf2_cu *cu);
-
-    /* Read a minimal amount of information into the minimal die
-       structure.  */
-    const gdb_byte *read (const struct die_reader_specs *reader,
-                         const struct abbrev_info &abbrev,
-                         const gdb_byte *info_ptr);
-
-    /* Compute the name of this partial DIE.  This memoizes the
-       result, so it is safe to call multiple times.  */
-    const char *name (dwarf2_cu *cu);
-
-    /* Offset of this DIE.  */
-    const sect_offset sect_off;
-
-    /* DWARF-2 tag for this DIE.  */
-    const ENUM_BITFIELD(dwarf_tag) tag : 16;
-
-    /* Assorted flags describing the data found in this DIE.  */
-    const unsigned int has_children : 1;
-
-    unsigned int is_external : 1;
-    unsigned int is_declaration : 1;
-    unsigned int has_type : 1;
-    unsigned int has_specification : 1;
-    unsigned int has_pc_info : 1;
-    unsigned int 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 {};
-
-    /* If HAS_PC_INFO, the PC range associated with this DIE.  */
-    CORE_ADDR lowpc = 0;
-    CORE_ADDR highpc = 0;
-
-    /* Pointer into the info_buffer (or types_buffer) pointing at the target of
-       DW_AT_sibling, if any.  */
-    /* NOTE: This member isn't strictly necessary, 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;
-      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;
-    }
-  };
-
 /* 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.  */
@@ -1076,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)
 {
-  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 */
@@ -1086,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 dwarf2_psymtab *create_partial_symtab
-  (dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile,
-   const char *name);
-
-static void build_type_psymtabs_reader (const struct die_reader_specs *reader,
-                                       const gdb_byte *info_ptr,
-                                       struct die_info *type_unit_die);
+class cooked_index_storage;
+static void build_type_psymtabs_reader (cutu_reader *reader,
+                                       cooked_index_storage *storage);
 
 static void dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile);
 
-static void scan_partial_symbols (struct partial_die_info *,
-                                 CORE_ADDR *, CORE_ADDR *,
-                                 int, struct dwarf2_cu *);
-
-static void add_partial_symbol (struct partial_die_info *,
-                               struct dwarf2_cu *);
-
-static void add_partial_namespace (struct partial_die_info *pdi,
-                                  CORE_ADDR *lowpc, CORE_ADDR *highpc,
-                                  int set_addrmap, struct dwarf2_cu *cu);
-
-static void add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
-                               CORE_ADDR *highpc, int set_addrmap,
-                               struct dwarf2_cu *cu);
-
-static void add_partial_enumeration (struct partial_die_info *enum_pdi,
-                                    struct dwarf2_cu *cu);
-
-static void add_partial_subprogram (struct partial_die_info *pdi,
-                                   CORE_ADDR *lowpc, CORE_ADDR *highpc,
-                                   int need_pc, struct dwarf2_cu *cu);
-
 static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
 
-static struct partial_die_info *load_partial_dies
-  (const struct die_reader_specs *, const gdb_byte *, int);
-
-/* A pair of partial_die_info and compilation unit.  */
-struct cu_partial_die_info
-{
-  /* The compilation unit of the partial_die_info.  */
-  struct dwarf2_cu *cu;
-  /* A partial_die_info.  */
-  struct partial_die_info *pdi;
-
-  cu_partial_die_info (struct dwarf2_cu *cu, struct partial_die_info *pdi)
-    : cu (cu),
-      pdi (pdi)
-  { /* Nothing.  */ }
-
-private:
-  cu_partial_die_info () = delete;
-};
-
-static const struct cu_partial_die_info find_partial_die (sect_offset, int,
-                                                         struct dwarf2_cu *);
-
 static const gdb_byte *read_attribute (const struct die_reader_specs *,
                                       struct attribute *,
                                       const struct attr_abbrev *,
@@ -1192,8 +1008,8 @@ static struct die_info *die_specification (struct die_info *die,
 static line_header_up dwarf_decode_line_header (sect_offset sect_off,
                                                struct dwarf2_cu *cu);
 
-static void dwarf_decode_lines (struct line_header *, const char *,
-                               struct dwarf2_cu *, dwarf2_psymtab *,
+static void dwarf_decode_lines (struct line_header *,
+                               struct dwarf2_cu *,
                                CORE_ADDR, int decode_mapping);
 
 static void dwarf2_start_subfile (struct dwarf2_cu *, const char *,
@@ -1282,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 *,
-                                                dwarf2_psymtab *);
+                                                addrmap *,
+                                                void *);
 
 static void get_scope_pc_bounds (struct die_info *,
                                 CORE_ADDR *, CORE_ADDR *,
@@ -1426,15 +1243,12 @@ static void dwarf2_symbol_mark_computed (const struct attribute *attr,
 
 static const gdb_byte *skip_one_die (const struct die_reader_specs *reader,
                                     const gdb_byte *info_ptr,
-                                    const struct abbrev_info *abbrev);
-
-static hashval_t partial_die_hash (const void *item);
-
-static int partial_die_eq (const void *item_lhs, const void *item_rhs);
+                                    const struct abbrev_info *abbrev,
+                                    bool do_skip_children = true);
 
 static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit
   (sect_offset sect_off, unsigned int offset_in_dwz,
-   dwarf2_per_objfile *per_objfile);
+   dwarf2_per_bfd *per_bfd);
 
 static void prepare_one_comp_unit (struct dwarf2_cu *cu,
                                   struct die_info *comp_unit_die,
@@ -1522,27 +1336,14 @@ dwarf2_per_cu_data_deleter::operator() (dwarf2_per_cu_data *data)
     delete data;
 }
 
-/* The return type of find_file_and_directory.  Note, the enclosed
-   string pointers are only valid while this object is valid.  */
-
-struct file_and_directory
-{
-  /* The filename.  This is never NULL.  */
-  const char *name;
-
-  /* The compilation directory.  NULL if not known.  If we needed to
-     compute a new string, this points to COMP_DIR_STORAGE, otherwise,
-     points directly to the DW_AT_comp_dir string attribute owned by
-     the obstack that owns the DIE.  */
-  const char *comp_dir;
-
-  /* If we needed to build a new string for comp_dir, this is what
-     owns the storage.  */
-  std::string comp_dir_storage;
-};
+static file_and_directory &find_file_and_directory
+     (struct die_info *die, struct dwarf2_cu *cu);
 
-static file_and_directory find_file_and_directory (struct die_info *die,
-                                                  struct dwarf2_cu *cu);
+static const char *compute_include_file_name
+     (const struct line_header *lh,
+      const file_entry &fe,
+      const file_and_directory &cu_info,
+      gdb::unique_xmalloc_ptr<char> *name_holder);
 
 static htab_up allocate_signatured_type_table ();
 
@@ -1639,6 +1440,73 @@ line_header_eq_voidp (const void *item_lhs, const void *item_rhs)
 
 \f
 
+/* An iterator for all_comp_units that is based on index.  This
+   approach makes it possible to iterate over all_comp_units safely,
+   when some caller in the loop may add new units.  */
+
+class all_comp_units_iterator
+{
+public:
+
+  all_comp_units_iterator (dwarf2_per_bfd *per_bfd, bool start)
+    : m_per_bfd (per_bfd),
+      m_index (start ? 0 : per_bfd->all_comp_units.size ())
+  {
+  }
+
+  all_comp_units_iterator &operator++ ()
+  {
+    ++m_index;
+    return *this;
+  }
+
+  dwarf2_per_cu_data *operator* () const
+  {
+    return m_per_bfd->get_cu (m_index);
+  }
+
+  bool operator== (const all_comp_units_iterator &other) const
+  {
+    return m_index == other.m_index;
+  }
+
+
+  bool operator!= (const all_comp_units_iterator &other) const
+  {
+    return m_index != other.m_index;
+  }
+
+private:
+
+  dwarf2_per_bfd *m_per_bfd;
+  size_t m_index;
+};
+
+/* A range adapter for the all_comp_units_iterator.  */
+class all_comp_units_range
+{
+public:
+
+  all_comp_units_range (dwarf2_per_bfd *per_bfd)
+    : m_per_bfd (per_bfd)
+  {
+  }
+
+  all_comp_units_iterator begin ()
+  {
+    return all_comp_units_iterator (m_per_bfd, true);
+  }
+
+  all_comp_units_iterator end ()
+  {
+    return all_comp_units_iterator (m_per_bfd, false);
+  }
+
+private:
+
+  dwarf2_per_bfd *m_per_bfd;
+};
+
 /* See declaration.  */
 
 dwarf2_per_bfd::dwarf2_per_bfd (bfd *obfd, const dwarf2_debug_sections *names,
@@ -1656,7 +1524,10 @@ dwarf2_per_bfd::dwarf2_per_bfd (bfd *obfd, const dwarf2_debug_sections *names,
 dwarf2_per_bfd::~dwarf2_per_bfd ()
 {
   for (auto &per_cu : all_comp_units)
-    per_cu->imported_symtabs_free ();
+    {
+      per_cu->imported_symtabs_free ();
+      per_cu->free_cached_file_names ();
+    }
 
   /* Everything else should be on this->obstack.  */
 }
@@ -1703,9 +1574,9 @@ private:
 bool
 dwarf2_per_objfile::symtab_set_p (const dwarf2_per_cu_data *per_cu) const
 {
-  gdb_assert (per_cu->index < this->m_symtabs.size ());
-
-  return this->m_symtabs[per_cu->index] != nullptr;
+  if (per_cu->index < this->m_symtabs.size ())
+    return this->m_symtabs[per_cu->index] != nullptr;
+  return false;
 }
 
 /* See read.h.  */
@@ -1713,9 +1584,9 @@ dwarf2_per_objfile::symtab_set_p (const dwarf2_per_cu_data *per_cu) const
 compunit_symtab *
 dwarf2_per_objfile::get_symtab (const dwarf2_per_cu_data *per_cu) const
 {
-  gdb_assert (per_cu->index < this->m_symtabs.size ());
-
-  return this->m_symtabs[per_cu->index];
+  if (per_cu->index < this->m_symtabs.size ())
+    return this->m_symtabs[per_cu->index];
+  return nullptr;
 }
 
 /* See read.h.  */
@@ -1724,9 +1595,9 @@ void
 dwarf2_per_objfile::set_symtab (const dwarf2_per_cu_data *per_cu,
                                compunit_symtab *symtab)
 {
-  gdb_assert (per_cu->index < this->m_symtabs.size ());
+  if (per_cu->index >= this->m_symtabs.size ())
+    this->m_symtabs.resize (per_cu->index + 1);
   gdb_assert (this->m_symtabs[per_cu->index] == nullptr);
-
   this->m_symtabs[per_cu->index] = symtab;
 }
 
@@ -1952,6 +1823,25 @@ dwarf2_get_section_info (struct objfile *objfile,
   *sizep = info->size;
 }
 
+/* See dwarf2/read.h.  */
+
+void
+dwarf2_per_bfd::map_info_sections (struct objfile *objfile)
+{
+  info.read (objfile);
+  abbrev.read (objfile);
+  line.read (objfile);
+  str.read (objfile);
+  str_offsets.read (objfile);
+  line_str.read (objfile);
+  ranges.read (objfile);
+  rnglists.read (objfile);
+  addr.read (objfile);
+
+  for (auto &section : types)
+    section.read (objfile);
+}
+
 \f
 /* DWARF quick_symbol_functions support.  */
 
@@ -1968,6 +1858,10 @@ struct quick_file_names
   /* The number of entries in file_names, real_names.  */
   unsigned int num_file_names;
 
+  /* The CU directory, as given by DW_AT_comp_dir.  May be
+     nullptr.  */
+  const char *comp_dir;
+
   /* The file names from the line table, after being run through
      file_full_name.  */
   const char **file_names;
@@ -1977,49 +1871,6 @@ struct quick_file_names
   const char **real_names;
 };
 
-/* When using the index (and thus not using psymtabs), each CU has an
-   object of this type.  This is used to hold information needed by
-   the various "quick" methods.  */
-struct dwarf2_per_cu_quick_data
-{
-  /* The file table.  This can be NULL if there was no file table
-     or it's currently not read in.
-     NOTE: This points into dwarf2_per_objfile->per_bfd->quick_file_names_table.  */
-  struct quick_file_names *file_names;
-
-  /* A temporary mark bit used when iterating over all CUs in
-     expand_symtabs_matching.  */
-  unsigned int mark : 1;
-
-  /* True if we've tried to read the file table and found there isn't one.
-     There will be no point in trying to read it again next time.  */
-  unsigned int no_file_data : 1;
-};
-
-/* A subclass of psymbol_functions that arranges to read the DWARF
-   partial symbols when needed.  */
-struct lazy_dwarf_reader : public psymbol_functions
-{
-  using psymbol_functions::psymbol_functions;
-
-  bool can_lazily_read_symbols () override
-  {
-    return true;
-  }
-
-  void read_partial_symbols (struct objfile *objfile) override
-  {
-    if (dwarf2_has_info (objfile, nullptr))
-      dwarf2_build_psymtabs (objfile, this);
-  }
-};
-
-static quick_symbol_functions_up
-make_lazy_dwarf_reader ()
-{
-  return quick_symbol_functions_up (new lazy_dwarf_reader);
-}
-
 struct dwarf2_base_index_functions : public quick_symbol_functions
 {
   bool has_symbols (struct objfile *objfile) override;
@@ -2164,25 +2015,6 @@ eq_file_name_entry (const void *a, const void *b)
   return eq_stmt_list_entry (&ea->hash, &eb->hash);
 }
 
-/* Delete function for a quick_file_names.  */
-
-static void
-delete_file_name_entry (void *e)
-{
-  struct quick_file_names *file_data = (struct quick_file_names *) e;
-  int i;
-
-  for (i = 0; i < file_data->num_file_names; ++i)
-    {
-      xfree ((void*) file_data->file_names[i]);
-      if (file_data->real_names)
-       xfree ((void*) file_data->real_names[i]);
-    }
-
-  /* The space for the struct itself lives on the obstack, so we don't
-     free it here.  */
-}
-
 /* Create a quick_file_names hash table.  */
 
 static htab_up
@@ -2190,7 +2022,7 @@ create_quick_file_names_table (unsigned int nr_initial_entries)
 {
   return htab_up (htab_create_alloc (nr_initial_entries,
                                     hash_file_name_entry, eq_file_name_entry,
-                                    delete_file_name_entry, xcalloc, xfree));
+                                    nullptr, xcalloc, xfree));
 }
 
 /* Read in CU (dwarf2_cu object) for PER_CU in the context of PER_OBJFILE.  This
@@ -2222,11 +2054,6 @@ static void
 dw2_do_instantiate_symtab (dwarf2_per_cu_data *per_cu,
                           dwarf2_per_objfile *per_objfile, bool skip_partial)
 {
-  /* Skip type_unit_groups, reading the type units they contain
-     is handled elsewhere.  */
-  if (per_cu->type_unit_group_p ())
-    return;
-
   {
     /* The destructor of dwarf2_queue_guard frees any entries left on
        the queue.  After this point we're guaranteed to leave this function
@@ -2269,8 +2096,6 @@ dw2_instantiate_symtab (dwarf2_per_cu_data *per_cu,
                        dwarf2_per_objfile *per_objfile,
                        bool skip_partial)
 {
-  gdb_assert (per_objfile->per_bfd->using_index);
-
   if (!per_objfile->symtab_set_p (per_cu))
     {
       free_cached_comp_units freer (per_objfile);
@@ -2319,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->v.quick = OBSTACK_ZALLOC (&per_bfd->obstack,
-                                   struct dwarf2_per_cu_quick_data);
   the_cu->is_dwz = is_dwz;
   return the_cu;
 }
@@ -2401,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->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 ();
@@ -2452,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->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 ();
@@ -2522,12 +2339,14 @@ create_addrmap_from_index (dwarf2_per_objfile *per_objfile,
                                                 &per_bfd->obstack);
 }
 
-/* Read the address map data from DWARF-5 .debug_aranges, and use it to
-   populate the psymtabs_addrmap.  */
+/* Read the address map data from DWARF-5 .debug_aranges, and use it
+   to populate given addrmap.  Returns true on success, false on
+   failure.  */
 
-static void
-create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
-                            struct dwarf2_section_info *section)
+static bool
+read_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
+                          struct dwarf2_section_info *section,
+                          addrmap *mutable_map)
 {
   struct objfile *objfile = per_objfile->objfile;
   bfd *abfd = objfile->obfd;
@@ -2535,15 +2354,19 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
   const CORE_ADDR baseaddr = objfile->text_section_offset ();
   dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
 
-  auto_obstack temp_obstack;
-  addrmap *mutable_map = addrmap_create_mutable (&temp_obstack);
-
   std::unordered_map<sect_offset,
                     dwarf2_per_cu_data *,
                     gdb::hash_enum<sect_offset>>
     debug_info_offset_to_per_cu;
   for (const auto &per_cu : per_bfd->all_comp_units)
     {
+      /* 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.  The same applies to
+        units coming from a dwz file.  */
+      if (per_cu->is_debug_types || per_cu->is_dwz)
+       continue;
+
       const auto insertpair
        = debug_info_offset_to_per_cu.emplace (per_cu->sect_off,
                                               per_cu.get ());
@@ -2552,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));
-         return;
+         return false;
        }
     }
 
@@ -2583,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));
-         return;
+         return false;
        }
 
       /* The version number.  */
@@ -2595,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);
-         return;
+         return false;
        }
 
       const uint64_t debug_info_offset
@@ -2611,7 +2434,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                   objfile_name (objfile),
                   plongest (entry_addr - section->buffer),
                   pulongest (debug_info_offset));
-         return;
+         return false;
        }
       dwarf2_per_cu_data *const per_cu = per_cu_it->second;
 
@@ -2622,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);
-         return;
+         return false;
        }
 
       const uint8_t segment_selector_size = *addr++;
@@ -2634,7 +2457,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                   objfile_name (objfile),
                   plongest (entry_addr - section->buffer),
                   segment_selector_size);
-         return;
+         return false;
        }
 
       /* Must pad to an alignment boundary that is twice the address
@@ -2655,7 +2478,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                         "ignoring .debug_aranges."),
                       objfile_name (objfile),
                       plongest (entry_addr - section->buffer));
-             return;
+             return false;
            }
          ULONGEST start = extract_unsigned_integer (addr, address_size,
                                                     dwarf5_byte_order);
@@ -2677,10 +2500,28 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                 - baseaddr);
          addrmap_set_empty (mutable_map, start, end - 1, per_cu);
        }
+
+      per_cu->addresses_seen = true;
     }
 
-  per_bfd->index_addrmap = addrmap_create_fixed (mutable_map,
-                                                &per_bfd->obstack);
+  return true;
+}
+
+/* Read the address map data from DWARF-5 .debug_aranges, and use it to
+   populate the psymtabs_addrmap.  */
+
+static void
+create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
+                            struct dwarf2_section_info *section)
+{
+  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
+
+  auto_obstack temp_obstack;
+  addrmap *mutable_map = addrmap_create_mutable (&temp_obstack);
+
+  if (read_addrmap_from_aranges (per_objfile, section, mutable_map))
+    per_bfd->index_addrmap = addrmap_create_fixed (mutable_map,
+                                                  &per_bfd->obstack);
 }
 
 /* A helper function that reads the .gdb_index from BUFFER and fills
@@ -2785,6 +2626,15 @@ to use the section anyway."),
   ++i;
   map->constant_pool = buffer.slice (metadata[i]);
 
+  if (map->constant_pool.empty () && !map->symbol_table.empty ())
+    {
+      /* An empty constant pool implies that all symbol table entries are
+        empty.  Make map->symbol_table.empty () == true.  */
+      map->symbol_table
+       = offset_view (gdb::array_view<const gdb_byte> (symbol_table,
+                                                       symbol_table));
+    }
+
   return 1;
 }
 
@@ -2876,7 +2726,6 @@ dwarf2_read_gdb_index
   create_addrmap_from_index (per_objfile, map.get ());
 
   per_bfd->index_table = std::move (map);
-  per_bfd->using_index = 1;
   per_bfd->quick_file_names_table =
     create_quick_file_names_table (per_bfd->all_comp_units.size ());
 
@@ -2899,13 +2748,11 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
 
   gdb_assert (! this_cu->is_debug_types);
 
+  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)
-    {
-      this_cu->v.quick->no_file_data = 1;
-      return;
-    }
+    return;
 
   lh_cu = this_cu;
   slot = NULL;
@@ -2928,42 +2775,59 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
                             &find_entry, INSERT);
       if (*slot != NULL)
        {
-         lh_cu->v.quick->file_names = (struct quick_file_names *) *slot;
+         lh_cu->file_names = (struct quick_file_names *) *slot;
          return;
        }
 
       lh = dwarf_decode_line_header (line_offset, cu);
     }
-  if (lh == NULL)
-    {
-      lh_cu->v.quick->no_file_data = 1;
-      return;
-    }
+
+  file_and_directory &fnd = find_file_and_directory (comp_unit_die, cu);
+
+  int offset = 0;
+  if (!fnd.is_unknown ())
+    ++offset;
+  else if (lh == nullptr)
+    return;
 
   qfn = XOBNEW (&per_objfile->per_bfd->obstack, struct quick_file_names);
   qfn->hash.dwo_unit = cu->dwo_unit;
   qfn->hash.line_sect_off = line_offset;
-  gdb_assert (slot != NULL);
-  *slot = qfn;
-
-  file_and_directory fnd = find_file_and_directory (comp_unit_die, cu);
+  /* There may not be a DW_AT_stmt_list.  */
+  if (slot != nullptr)
+    *slot = qfn;
 
-  int offset = 0;
-  if (strcmp (fnd.name, "<unknown>") != 0)
-    ++offset;
+  std::vector<const char *> include_names;
+  if (lh != nullptr)
+    {
+      for (const auto &entry : lh->file_names ())
+       {
+         gdb::unique_xmalloc_ptr<char> name_holder;
+         const char *include_name =
+           compute_include_file_name (lh.get (), entry, fnd, &name_holder);
+         if (include_name != nullptr)
+           {
+             include_name = per_objfile->objfile->intern (include_name);
+             include_names.push_back (include_name);
+           }
+       }
+    }
 
-  qfn->num_file_names = offset + lh->file_names_size ();
+  qfn->num_file_names = offset + include_names.size ();
+  qfn->comp_dir = fnd.intern_comp_dir (per_objfile->objfile);
   qfn->file_names =
     XOBNEWVEC (&per_objfile->per_bfd->obstack, const char *,
               qfn->num_file_names);
   if (offset != 0)
-    qfn->file_names[0] = xstrdup (fnd.name);
-  for (int i = 0; i < lh->file_names_size (); ++i)
-    qfn->file_names[i + offset] = lh->file_full_name (i + 1,
-                                                     fnd.comp_dir).release ();
+    qfn->file_names[0] = xstrdup (fnd.get_name ());
+
+  if (!include_names.empty ())
+    memcpy (&qfn->file_names[offset], include_names.data (),
+           include_names.size () * sizeof (const char *));
+
   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
@@ -2975,22 +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);
-  /* Nor type unit groups.  */
-  gdb_assert (! this_cu->type_unit_group_p ());
 
-  if (this_cu->v.quick->file_names != NULL)
-    return this_cu->v.quick->file_names;
-  /* If we know there is no line data, no point in looking again.  */
-  if (this_cu->v.quick->no_file_data)
-    return NULL;
+  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);
 
-  if (this_cu->v.quick->no_file_data)
-    return NULL;
-  return this_cu->v.quick->file_names;
+  return this_cu->file_names;
 }
 
 /* A helper for the "quick" functions which computes and caches the
@@ -3005,7 +2862,17 @@ dw2_get_real_path (dwarf2_per_objfile *per_objfile,
                                      qfn->num_file_names, const char *);
 
   if (qfn->real_names[index] == NULL)
-    qfn->real_names[index] = gdb_realpath (qfn->file_names[index]).release ();
+    {
+      const char *dirname = nullptr;
+
+      if (!IS_ABSOLUTE_PATH (qfn->file_names[index]))
+       dirname = qfn->comp_dir;
+
+      gdb::unique_xmalloc_ptr<char> fullname;
+      fullname = find_source_or_rewrite (qfn->file_names[index], dirname);
+
+      qfn->real_names[index] = fullname.release ();
+    }
 
   return qfn->real_names[index];
 }
@@ -3021,28 +2888,29 @@ dwarf2_base_index_functions::find_last_source_symtab (struct objfile *objfile)
   if (cust == NULL)
     return NULL;
 
-  return compunit_primary_filetab (cust);
+  return cust->primary_filetab ();
 }
 
-/* Traversal function for dw2_forget_cached_source_info.  */
+/* See read.h.  */
 
-static int
-dw2_free_cached_file_names (void **slot, void *info)
+void
+dwarf2_per_cu_data::free_cached_file_names ()
 {
-  struct quick_file_names *file_data = (struct quick_file_names *) *slot;
+  if (fnd != nullptr)
+    fnd->forget_fullname ();
 
-  if (file_data->real_names)
-    {
-      int i;
+  if (per_bfd == nullptr)
+    return;
 
-      for (i = 0; i < file_data->num_file_names; ++i)
+  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)
        {
-         xfree ((void*) file_data->real_names[i]);
-         file_data->real_names[i] = NULL;
+         xfree ((void *) file_data->real_names[i]);
+         file_data->real_names[i] = nullptr;
        }
     }
-
-  return 1;
 }
 
 void
@@ -3051,8 +2919,8 @@ dwarf2_base_index_functions::forget_cached_source_info
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
-  htab_traverse_noresize (per_objfile->per_bfd->quick_file_names_table.get (),
-                         dw2_free_cached_file_names, NULL);
+  for (auto &per_cu : per_objfile->per_bfd->all_comp_units)
+    per_cu->free_cached_file_names ();
 }
 
 /* Struct used to manage iterating over all CUs looking for a symbol.  */
@@ -3221,8 +3089,8 @@ dwarf2_base_index_functions::print_stats (struct objfile *objfile,
       if (!per_objfile->symtab_set_p (per_cu))
        ++count;
     }
-  printf_filtered (_("  Number of read CUs: %d\n"), total - count);
-  printf_filtered (_("  Number of unread CUs: %d\n"), count);
+  gdb_printf (_("  Number of read CUs: %d\n"), total - count);
+  gdb_printf (_("  Number of unread CUs: %d\n"), count);
 }
 
 /* This dumps minimal information about the index.
@@ -3235,16 +3103,15 @@ dwarf2_gdb_index::dump (struct objfile *objfile)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
-  gdb_assert (per_objfile->per_bfd->using_index);
-  printf_filtered (".gdb_index:");
+  gdb_printf (".gdb_index:");
   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
-    printf_filtered (" faked for \"readnow\"\n");
-  printf_filtered ("\n");
+    gdb_printf (" faked for \"readnow\"\n");
+  gdb_printf ("\n");
 }
 
 void
@@ -4107,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)
 {
-  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);
 
@@ -4248,12 +4115,33 @@ dw_expand_symtabs_matching_file_matcher
 
       if (per_cu->is_debug_types)
        continue;
-      per_cu->v.quick->mark = 0;
+      per_cu->mark = 0;
 
       /* We only need to look at symtabs not already expanded.  */
       if (per_objfile->symtab_set_p (per_cu.get ()))
        continue;
 
+      if (per_cu->fnd != nullptr)
+       {
+         file_and_directory *fnd = per_cu->fnd.get ();
+
+         if (file_matcher (fnd->get_name (), false))
+           {
+             per_cu->mark = 1;
+             continue;
+           }
+
+         /* Before we invoke realpath, which can get expensive when many
+            files are involved, do a quick comparison of the basenames.  */
+         if ((basenames_may_differ
+              || file_matcher (lbasename (fnd->get_name ()), true))
+             && file_matcher (fnd->get_fullname (), false))
+           {
+             per_cu->mark = 1;
+             continue;
+           }
+       }
+
       quick_file_names *file_data = dw2_get_file_names (per_cu.get (),
                                                        per_objfile);
       if (file_data == NULL)
@@ -4263,7 +4151,7 @@ dw_expand_symtabs_matching_file_matcher
        continue;
       else if (htab_find (visited_found.get (), file_data) != NULL)
        {
-         per_cu->v.quick->mark = 1;
+         per_cu->mark = 1;
          continue;
        }
 
@@ -4273,7 +4161,7 @@ dw_expand_symtabs_matching_file_matcher
 
          if (file_matcher (file_data->file_names[j], false))
            {
-             per_cu->v.quick->mark = 1;
+             per_cu->mark = 1;
              break;
            }
 
@@ -4287,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))
            {
-             per_cu->v.quick->mark = 1;
+             per_cu->mark = 1;
              break;
            }
        }
 
-      void **slot = htab_find_slot (per_cu->v.quick->mark
+      void **slot = htab_find_slot (per_cu->mark
                                    ? visited_found.get ()
                                    : visited_not_found.get (),
                                    file_data, INSERT);
@@ -4319,13 +4207,16 @@ dwarf2_gdb_index::expand_symtabs_matching
 
   dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
 
-  if (symbol_matcher == NULL && lookup_name == NULL)
+  /* This invariant is documented in quick-functions.h.  */
+  gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr);
+  if (lookup_name == nullptr)
     {
-      for (const auto &per_cu : per_objfile->per_bfd->all_comp_units)
+      for (dwarf2_per_cu_data *per_cu
+            : all_comp_units_range (per_objfile->per_bfd))
        {
          QUIT;
 
-         if (!dw2_expand_symtabs_matching_one (per_cu.get (), per_objfile,
+         if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
                                                file_matcher,
                                                expansion_notify))
            return false;
@@ -4358,8 +4249,8 @@ recursively_find_pc_sect_compunit_symtab (struct compunit_symtab *cust,
 {
   int i;
 
-  if (COMPUNIT_BLOCKVECTOR (cust) != NULL
-      && blockvector_contains_pc (COMPUNIT_BLOCKVECTOR (cust), pc))
+  if (cust->blockvector () != nullptr
+      && blockvector_contains_pc (cust->blockvector (), pc))
     return cust;
 
   if (cust->includes == NULL)
@@ -4430,21 +4321,40 @@ dwarf2_base_index_functions::map_symbol_filenames
 
   for (const auto &per_cu : per_objfile->per_bfd->all_comp_units)
     {
-      if (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);
        }
     }
 
-  for (const auto &per_cu : per_objfile->per_bfd->all_comp_units)
+  for (dwarf2_per_cu_data *per_cu
+        : all_comp_units_range (per_objfile->per_bfd))
     {
       /* We only need to look at symtabs not already expanded.  */
-      if (per_objfile->symtab_set_p (per_cu.get ()))
+      if (per_cu->is_debug_types || per_objfile->symtab_set_p (per_cu))
        continue;
 
-      quick_file_names *file_data = dw2_get_file_names (per_cu.get (),
-                                                       per_objfile);
+      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 ())
        continue;
@@ -4452,18 +4362,19 @@ dwarf2_base_index_functions::map_symbol_filenames
       for (int j = 0; j < file_data->num_file_names; ++j)
        {
          const char *filename = file_data->file_names[j];
-         filenames_cache.seen (filename);
-       }
-    }
+         const char *key = filename;
+         const char *fullname = nullptr;
 
-  filenames_cache.traverse ([&] (const char *filename)
-    {
-      gdb::unique_xmalloc_ptr<char> this_real_name;
+         if (need_fullname)
+           {
+             fullname = dw2_get_real_path (per_objfile, file_data, j);
+             key = fullname;
+           }
 
-      if (need_fullname)
-       this_real_name = gdb_realpath (filename);
-      fun (filename, this_real_name.get ());
-    });
+         if (!filenames_cache.seen (key))
+           fun (filename, fullname);
+       }
+    }
 }
 
 bool
@@ -4812,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);
-  per_bfd->using_index = 1;
   per_bfd->quick_file_names_table =
     create_quick_file_names_table (per_bfd->all_comp_units.size ());
 
@@ -5238,13 +5148,12 @@ dwarf2_debug_names_index::dump (struct objfile *objfile)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
 
-  gdb_assert (per_objfile->per_bfd->using_index);
-  printf_filtered (".debug_names:");
+  gdb_printf (".debug_names:");
   if (per_objfile->per_bfd->debug_names_table)
-    printf_filtered (" exists\n");
+    gdb_printf (" exists\n");
   else
-    printf_filtered (" faked for \"readnow\"\n");
-  printf_filtered ("\n");
+    gdb_printf (" faked for \"readnow\"\n");
+  gdb_printf ("\n");
 }
 
 void
@@ -5307,13 +5216,16 @@ dwarf2_debug_names_index::expand_symtabs_matching
 
   dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
 
-  if (symbol_matcher == NULL && lookup_name == NULL)
+  /* This invariant is documented in quick-functions.h.  */
+  gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr);
+  if (lookup_name == nullptr)
     {
-      for (const auto &per_cu : per_objfile->per_bfd->all_comp_units)
+      for (dwarf2_per_cu_data *per_cu
+            : all_comp_units_range (per_objfile->per_bfd))
        {
          QUIT;
 
-         if (!dw2_expand_symtabs_matching_one (per_cu.get (), per_objfile,
+         if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
                                                file_matcher,
                                                expansion_notify))
            return false;
@@ -5398,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);
 }
 
+static quick_symbol_functions_up make_cooked_index_funcs ();
+
 /* See dwarf2/public.h.  */
 
 void
@@ -5416,29 +5330,9 @@ dwarf2_initialize_objfile (struct objfile *objfile)
     {
       dwarf_read_debug_printf ("readnow requested");
 
-      /* When using READNOW, the using_index flag (set below) indicates that
-        PER_BFD was already initialized, when we loaded some other objfile.  */
-      if (per_bfd->using_index)
-       {
-         dwarf_read_debug_printf ("using_index already set");
-         per_objfile->resize_symtabs ();
-         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 ());
-      per_objfile->resize_symtabs ();
-
-      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
@@ -5452,7 +5346,6 @@ dwarf2_initialize_objfile (struct objfile *objfile)
   if (per_bfd->debug_names_table != nullptr)
     {
       dwarf_read_debug_printf ("re-using shared debug names table");
-      per_objfile->resize_symtabs ();
       objfile->qf.push_front (make_dwarf_debug_names ());
       return;
     }
@@ -5462,27 +5355,20 @@ dwarf2_initialize_objfile (struct objfile *objfile)
   if (per_bfd->index_table != nullptr)
     {
       dwarf_read_debug_printf ("re-using shared index table");
-      per_objfile->resize_symtabs ();
       objfile->qf.push_front (make_dwarf_gdb_index ());
       return;
     }
 
-  /* There might already be partial symtabs built for this BFD.  This happens
-     when loading the same binary twice with the index-cache enabled.  If so,
-     don't try to read an index.  The objfile / per_objfile initialization will
-     be completed in dwarf2_build_psymtabs, in the standard partial symtabs
-     code path.  */
-  if (per_bfd->partial_symtabs != nullptr)
+  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;
     }
 
   if (dwarf2_read_debug_names (per_objfile))
     {
       dwarf_read_debug_printf ("found debug names");
-      per_objfile->resize_symtabs ();
       objfile->qf.push_front (make_dwarf_debug_names ());
       return;
     }
@@ -5492,7 +5378,6 @@ dwarf2_initialize_objfile (struct objfile *objfile)
                             get_gdb_index_contents_from_section<dwz_file>))
     {
       dwarf_read_debug_printf ("found gdb index from file");
-      per_objfile->resize_symtabs ();
       objfile->qf.push_front (make_dwarf_gdb_index ());
       return;
     }
@@ -5504,13 +5389,12 @@ dwarf2_initialize_objfile (struct objfile *objfile)
     {
       dwarf_read_debug_printf ("found gdb index from cache");
       global_index_cache.hit ();
-      per_objfile->resize_symtabs ();
       objfile->qf.push_front (make_dwarf_gdb_index ());
       return;
     }
 
   global_index_cache.miss ();
-  objfile->qf.push_front (make_lazy_dwarf_reader ());
+  objfile->qf.push_front (make_cooked_index_funcs ());
 }
 
 \f
@@ -5518,50 +5402,21 @@ dwarf2_initialize_objfile (struct objfile *objfile)
 /* Build a partial symbol table.  */
 
 void
-dwarf2_build_psymtabs (struct objfile *objfile, psymbol_functions *psf)
+dwarf2_build_psymtabs (struct objfile *objfile, bool already_attached)
 {
   dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
 
-  if (per_bfd->partial_symtabs != nullptr)
+  if (already_attached)
     {
-      /* 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);
-      per_objfile->resize_symtabs ();
-      return;
-    }
-
-  if (psf == nullptr)
-    {
-      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
     {
-      /* This isn't really ideal: all the data we allocate on the
-        objfile's obstack is still uselessly kept around.  However,
-        freeing it seems unsafe.  */
-      psymtab_discarder psymtabs (partial_symtabs.get ());
       dwarf2_build_psymtabs_hard (per_objfile);
-      psymtabs.keep ();
-
-      per_objfile->resize_symtabs ();
 
       /* (maybe) store an index in the cache.  */
       global_index_cache.store (per_objfile);
@@ -5642,107 +5497,6 @@ read_abbrev_offset (dwarf2_per_objfile *per_objfile,
   return (sect_offset) read_offset (abfd, info_ptr, offset_size);
 }
 
-/* A partial symtab that is used only for include files.  */
-struct dwarf2_include_psymtab : public partial_symtab
-{
-  dwarf2_include_psymtab (const char *filename,
-                         psymtab_storage *partial_symtabs,
-                         objfile_per_bfd_storage *objfile_per_bfd)
-    : partial_symtab (filename, partial_symtabs, objfile_per_bfd)
-  {
-  }
-
-  void read_symtab (struct objfile *objfile) override
-  {
-    /* It's an include file, no symbols to read for it.
-       Everything is in the includer symtab.  */
-
-    /* The expansion of a dwarf2_include_psymtab is just a trigger for
-       expansion of the includer psymtab.  We use the dependencies[0] field to
-       model the includer.  But if we go the regular route of calling
-       expand_psymtab here, and having expand_psymtab call expand_dependencies
-       to expand the includer, we'll only use expand_psymtab on the includer
-       (making it a non-toplevel psymtab), while if we expand the includer via
-       another path, we'll use read_symtab (making it a toplevel psymtab).
-       So, don't pretend a dwarf2_include_psymtab is an actual toplevel
-       psymtab, and trigger read_symtab on the includer here directly.  */
-    includer ()->read_symtab (objfile);
-  }
-
-  void expand_psymtab (struct objfile *objfile) override
-  {
-    /* This is not called by read_symtab, and should not be called by any
-       expand_dependencies.  */
-    gdb_assert (false);
-  }
-
-  bool readin_p (struct objfile *objfile) const override
-  {
-    return includer ()->readin_p (objfile);
-  }
-
-  compunit_symtab *get_compunit_symtab (struct objfile *objfile) const override
-  {
-    return nullptr;
-  }
-
-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,
-                              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 (), pst->dirname, cu, pst,
-                     pst->raw_text_low (), 1);
-}
-
 static hashval_t
 hash_signatured_type (const void *item)
 {
@@ -5904,16 +5658,8 @@ add_type_unit (dwarf2_per_objfile *per_objfile, ULONGEST sig, void **slot)
     = per_objfile->per_bfd->allocate_signatured_type (sig);
   signatured_type *sig_type = sig_type_holder.get ();
 
-  per_objfile->resize_symtabs ();
-
   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)
     {
@@ -5939,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);
-  if (per_bfd->using_index)
-    {
-      gdb_assert (sig_entry->v.quick != NULL);
-      gdb_assert (!per_objfile->symtab_set_p (sig_entry));
-    }
-  else
-      gdb_assert (sig_entry->v.psymtab == NULL);
+  gdb_assert (!per_objfile->symtab_set_p (sig_entry));
   gdb_assert (sig_entry->signature == dwo_entry->signature);
-  gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0);
+  gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0
+             || (to_underlying (sig_entry->type_offset_in_section)
+                 == to_underlying (dwo_entry->type_offset_in_tu)));
   gdb_assert (sig_entry->type_unit_group == NULL);
-  gdb_assert (sig_entry->dwo_unit == NULL);
+  gdb_assert (sig_entry->dwo_unit == NULL
+             || sig_entry->dwo_unit == dwo_entry);
 
   sig_entry->section = dwo_entry->section;
   sig_entry->sect_off = dwo_entry->sect_off;
@@ -5980,7 +5723,7 @@ lookup_dwo_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
   struct dwo_unit find_dwo_entry, *dwo_entry;
   void **slot;
 
-  gdb_assert (cu->dwo_unit && per_objfile->per_bfd->using_index);
+  gdb_assert (cu->dwo_unit);
 
   /* If TU skeletons have been removed then we may not have read in any
      TUs yet.  */
@@ -6027,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);
 
-  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;
 }
@@ -6045,7 +5789,7 @@ lookup_dwp_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
   struct dwo_unit *dwo_entry;
   void **slot;
 
-  gdb_assert (cu->dwo_unit && per_objfile->per_bfd->using_index);
+  gdb_assert (cu->dwo_unit);
   gdb_assert (dwp_file != NULL);
 
   /* If TU skeletons have been removed then we may not have read in any
@@ -6086,7 +5830,7 @@ lookup_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
 {
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
 
-  if (cu->dwo_unit && per_objfile->per_bfd->using_index)
+  if (cu->dwo_unit)
     {
       /* We're in a DWO/DWP file, and we're using .gdb_index.
         These cases require special processing.  */
@@ -6300,11 +6044,11 @@ read_cutu_die_from_dwo (dwarf2_cu *cu,
 
   if (dwarf_die_debug)
     {
-      fprintf_unfiltered (gdb_stdlog,
-                         "Read die from %s@0x%x of %s:\n",
-                         section->get_name (),
-                         (unsigned) (begin_info_ptr - section->buffer),
-                         bfd_get_filename (abfd));
+      gdb_printf (gdb_stdlog,
+                 "Read die from %s@0x%x of %s:\n",
+                 section->get_name (),
+                 (unsigned) (begin_info_ptr - section->buffer),
+                 bfd_get_filename (abfd));
       dump_die (comp_unit_die, dwarf_die_debug);
     }
 
@@ -6339,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)
 {
+#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;
@@ -6431,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,
-                         bool skip_partial)
+                         bool skip_partial,
+                         abbrev_cache *cache)
   : die_reader_specs {},
     m_this_cu (this_cu)
 {
@@ -6447,9 +6200,9 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
   int rereading_dwo_cu = 0;
 
   if (dwarf_die_debug)
-    fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset %s\n",
-                       this_cu->is_debug_types ? "type" : "comp",
-                       sect_offset_str (this_cu->sect_off));
+    gdb_printf (gdb_stdlog, "Reading %s unit at offset %s\n",
+               this_cu->is_debug_types ? "type" : "comp",
+               sect_offset_str (this_cu->sect_off));
 
   /* If we're reading a TU directly from a DWO file, including a virtual DWO
      file (instead of going through the stub), short-circuit all of this.  */
@@ -6485,9 +6238,14 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
     }
   else
     {
-      /* If an existing_cu is provided, a dwarf2_cu must not exist for this_cu
-        in per_objfile yet.  */
-      gdb_assert (per_objfile->get_cu (this_cu) == nullptr);
+      /* If an existing_cu is provided, a dwarf2_cu must not exist for
+        this_cu in per_objfile yet.  Here, CACHE doubles as a flag to
+        let us know that the CU is being scanned using the parallel
+        indexer.  This assert is avoided in this case because (1) it
+        is irrelevant, and (2) the get_cu method is not
+        thread-safe.  */
+      gdb_assert (cache != nullptr
+                 || per_objfile->get_cu (this_cu) == nullptr);
       m_new_cu.reset (new dwarf2_cu (this_cu, per_objfile));
       cu = m_new_cu.get ();
     }
@@ -6555,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
     {
-      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.  */
@@ -6662,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)
-    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);
 
@@ -6759,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)
 {
-  dwarf2_per_objfile *per_objfile = cu->per_objfile;
-  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
-
   std::unique_ptr<type_unit_group> tu_group (new type_unit_group);
-  tu_group->per_bfd = per_bfd;
-
-  if (per_bfd->using_index)
-    {
-      tu_group->v.quick = OBSTACK_ZALLOC (&per_bfd->obstack,
-                                         struct dwarf2_per_cu_quick_data);
-    }
-  else
-    {
-      unsigned int line_offset = to_underlying (line_offset_struct);
-      dwarf2_psymtab *pst;
-      std::string name;
-
-      /* Give the symtab a useful name for debug purposes.  */
-      if ((line_offset & NO_STMT_LIST_TYPE_UNIT_PSYMTAB) != 0)
-       name = string_printf ("<type_units_%d>",
-                             (line_offset & ~NO_STMT_LIST_TYPE_UNIT_PSYMTAB));
-      else
-       name = string_printf ("<type_units_at_0x%x>", line_offset);
-
-      pst = create_partial_symtab (tu_group.get (), per_objfile,
-                                  name.c_str ());
-      pst->anonymous = true;
-    }
 
   tu_group->hash.dwo_unit = cu->dwo_unit;
   tu_group->hash.line_sect_off = line_offset_struct;
@@ -6848,165 +6585,235 @@ get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list)
   return tu_group;
 }
 \f
-/* Partial symbol tables.  */
 
-/* Create a psymtab named NAME and assign it to PER_CU.
+/* 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);
-
-  pst->psymtabs_addrmap_supported = true;
-
-  /* This is the glue that links PST into GDB's symbol API.  */
-  per_cu->v.psymtab = pst;
-
-  return pst;
-}
+public:
 
-/* DIE reader function for process_psymtab_comp_unit.  */
+  cooked_index_storage ()
+    : m_reader_hash (htab_create_alloc (10, hash_cutu_reader,
+                                       eq_cutu_reader,
+                                       htab_delete_entry<cutu_reader>,
+                                       xcalloc, xfree)),
+      m_index (new cooked_index),
+      m_addrmap_storage (),
+      m_addrmap (addrmap_create_mutable (&m_addrmap_storage))
+  {
+  }
 
-static void
-process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
-                                 const gdb_byte *info_ptr,
-                                 struct die_info *comp_unit_die,
-                                 enum language pretend_language)
-{
-  struct dwarf2_cu *cu = reader->cu;
-  dwarf2_per_objfile *per_objfile = cu->per_objfile;
-  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
-  struct objfile *objfile = per_objfile->objfile;
-  struct gdbarch *gdbarch = objfile->arch ();
-  struct dwarf2_per_cu_data *per_cu = cu->per_cu;
-  CORE_ADDR baseaddr;
-  CORE_ADDR best_lowpc = 0, best_highpc = 0;
-  dwarf2_psymtab *pst;
-  enum pc_bounds_kind cu_bounds_kind;
-  const char *filename;
+  DISABLE_COPY_AND_ASSIGN (cooked_index_storage);
 
-  gdb_assert (! per_cu->is_debug_types);
+  /* Return the current abbrev cache.  */
+  abbrev_cache *get_abbrev_cache ()
+  {
+    return &m_abbrev_cache;
+  }
 
-  prepare_one_comp_unit (cu, comp_unit_die, pretend_language);
+  /* Return the DIE reader corresponding to PER_CU.  If no such reader
+     has been registered, return NULL.  */
+  cutu_reader *get_reader (dwarf2_per_cu_data *per_cu)
+  {
+    int index = per_cu->index;
+    return (cutu_reader *) htab_find_with_hash (m_reader_hash.get (),
+                                               &index, index);
+  }
 
-  /* Allocate a new partial symbol table structure.  */
-  gdb::unique_xmalloc_ptr<char> debug_filename;
-  static const char artificial[] = "<artificial>";
-  filename = dwarf2_string_attr (comp_unit_die, DW_AT_name, cu);
-  if (filename == NULL)
-    filename = "";
-  else if (strcmp (filename, artificial) == 0)
-    {
-      debug_filename.reset (concat (artificial, "@",
-                                   sect_offset_str (per_cu->sect_off),
-                                   (char *) NULL));
-      filename = debug_filename.get ();
-    }
+  /* Preserve READER by storing it in the local hash table.  */
+  cutu_reader *preserve (std::unique_ptr<cutu_reader> reader)
+  {
+    m_abbrev_cache.add (reader->release_abbrev_table ());
+
+    int index = reader->cu->per_cu->index;
+    void **slot = htab_find_slot_with_hash (m_reader_hash.get (), &index,
+                                           index, INSERT);
+    gdb_assert (*slot == nullptr);
+    cutu_reader *result = reader.get ();
+    *slot = reader.release ();
+    return result;
+  }
 
-  pst = create_partial_symtab (per_cu, per_objfile, filename);
+  /* 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, 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.  */
@@ -7014,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,
-                          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;
@@ -7052,59 +6852,41 @@ process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu,
       /* Nothing.  */
     }
   else if (this_cu->is_debug_types)
-    build_type_psymtabs_reader (&reader, reader.info_ptr,
-                               reader.comp_unit_die);
-  else if (want_partial_unit
-          || reader.comp_unit_die->tag != DW_TAG_partial_unit)
-    process_psymtab_comp_unit_reader (&reader, reader.info_ptr,
-                                     reader.comp_unit_die,
-                                     pretend_language);
-
-  /* Age out any secondary CUs.  */
-  per_objfile->age_comp_units ();
+    build_type_psymtabs_reader (&reader, storage);
+  else if (reader.comp_unit_die->tag != DW_TAG_partial_unit)
+    {
+      bool nope = false;
+      if (this_cu->scanned.compare_exchange_strong (nope, true))
+       {
+         prepare_one_comp_unit (reader.cu, reader.comp_unit_die,
+                                language_minimal);
+         gdb_assert (storage != nullptr);
+         cooked_indexer indexer (storage, this_cu, reader.cu->per_cu->lang);
+         indexer.make_index (&reader);
+       }
+    }
 }
 
 /* Reader function for build_type_psymtabs.  */
 
 static void
-build_type_psymtabs_reader (const struct die_reader_specs *reader,
-                           const gdb_byte *info_ptr,
-                           struct die_info *type_unit_die)
+build_type_psymtabs_reader (cutu_reader *reader,
+                           cooked_index_storage *storage)
 {
-  dwarf2_per_objfile *per_objfile = reader->cu->per_objfile;
   struct dwarf2_cu *cu = reader->cu;
   struct dwarf2_per_cu_data *per_cu = cu->per_cu;
-  struct signatured_type *sig_type;
-  struct type_unit_group *tu_group;
-  struct attribute *attr;
-  struct partial_die_info *first_die;
-  CORE_ADDR lowpc, highpc;
-  dwarf2_psymtab *pst;
+  struct die_info *type_unit_die = reader->comp_unit_die;
 
   gdb_assert (per_cu->is_debug_types);
-  sig_type = (struct signatured_type *) per_cu;
 
   if (! type_unit_die->has_children)
     return;
 
-  attr = type_unit_die->attr (DW_AT_stmt_list);
-  tu_group = get_type_unit_group (cu, attr);
-
-  if (tu_group->tus == nullptr)
-    tu_group->tus = new std::vector<signatured_type *>;
-  tu_group->tus->push_back (sig_type);
-
   prepare_one_comp_unit (cu, type_unit_die, language_minimal);
-  pst = create_partial_symtab (per_cu, per_objfile, "");
-  pst->anonymous = true;
-
-  first_die = load_partial_dies (reader, info_ptr, 1);
 
-  lowpc = (CORE_ADDR) -1;
-  highpc = (CORE_ADDR) 0;
-  scan_partial_symbols (first_die, &lowpc, &highpc, 0, cu);
-
-  pst->end ();
+  gdb_assert (storage != nullptr);
+  cooked_indexer indexer (storage, per_cu, cu->per_cu->lang);
+  indexer.make_index (reader);
 }
 
 /* Struct used to sort TUs by their abbreviation table offset.  */
@@ -7143,7 +6925,8 @@ struct tu_abbrev_offset
    dwarf2_per_objfile->per_bfd->type_unit_groups.  */
 
 static void
-build_type_psymtabs (dwarf2_per_objfile *per_objfile)
+build_type_psymtabs (dwarf2_per_objfile *per_objfile,
+                    cooked_index_storage *storage)
 {
   struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
   abbrev_table_up abbrev_table;
@@ -7212,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)
-       build_type_psymtabs_reader (&reader, reader.info_ptr,
-                                   reader.comp_unit_die);
+       build_type_psymtabs_reader (&reader, storage);
     }
 }
 
@@ -7238,36 +7020,11 @@ print_tu_stats (dwarf2_per_objfile *per_objfile)
                           tu_stats->nr_all_type_units_reallocs);
 }
 
-/* Traversal function for build_type_psymtabs.  */
-
-static int
-build_type_psymtab_dependencies (void **slot, void *info)
+struct skeleton_data
 {
-  dwarf2_per_objfile *per_objfile = (dwarf2_per_objfile *) info;
-  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
-  struct type_unit_group *tu_group = (struct type_unit_group *) *slot;
-  dwarf2_psymtab *pst = tu_group->v.psymtab;
-  int len = (tu_group->tus == nullptr) ? 0 : tu_group->tus->size ();
-  int i;
-
-  gdb_assert (len > 0);
-  gdb_assert (tu_group->type_unit_group_p ());
-
-  pst->number_of_dependencies = len;
-  pst->dependencies = per_bfd->partial_symtabs->allocate_dependencies (len);
-  for (i = 0; i < len; ++i)
-    {
-      struct signatured_type *iter = tu_group->tus->at (i);
-      gdb_assert (iter->is_debug_types);
-      pst->dependencies[i] = iter->v.psymtab;
-      iter->type_unit_group = tu_group;
-    }
-
-  delete tu_group->tus;
-  tu_group->tus = nullptr;
-
-  return 1;
-}
+  dwarf2_per_objfile *per_objfile;
+  cooked_index_storage *storage;
+};
 
 /* Traversal function for process_skeletonless_type_unit.
    Read a TU in a DWO file and build partial symbols for it.  */
@@ -7276,15 +7033,16 @@ static int
 process_skeletonless_type_unit (void **slot, void *info)
 {
   struct dwo_unit *dwo_unit = (struct dwo_unit *) *slot;
-  dwarf2_per_objfile *per_objfile = (dwarf2_per_objfile *) info;
+  skeleton_data *data = (skeleton_data *) info;
 
   /* If this TU doesn't exist in the global table, add it and read it in.  */
 
-  if (per_objfile->per_bfd->signatured_types == NULL)
-    per_objfile->per_bfd->signatured_types = allocate_signatured_type_table ();
+  if (data->per_objfile->per_bfd->signatured_types == NULL)
+    data->per_objfile->per_bfd->signatured_types
+      = allocate_signatured_type_table ();
 
   signatured_type find_entry (dwo_unit->signature);
-  slot = htab_find_slot (per_objfile->per_bfd->signatured_types.get (),
+  slot = htab_find_slot (data->per_objfile->per_bfd->signatured_types.get (),
                         &find_entry, INSERT);
   /* If we've already seen this type there's nothing to do.  What's happening
      is we're doing our own version of comdat-folding here.  */
@@ -7294,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
-    = add_type_unit (per_objfile, dwo_unit->signature, slot);
-  fill_in_sig_entry_from_dwo_entry (per_objfile, entry, dwo_unit);
+    = add_type_unit (data->per_objfile, dwo_unit->signature, slot);
+  fill_in_sig_entry_from_dwo_entry (data->per_objfile, entry, dwo_unit);
   *slot = entry;
 
   /* This does the job that build_type_psymtabs would have done.  */
-  cutu_reader reader (entry, per_objfile, nullptr, nullptr, false);
+  cutu_reader reader (entry, data->per_objfile, nullptr, nullptr, false);
   if (!reader.dummy_p)
-    build_type_psymtabs_reader (&reader, reader.info_ptr,
-                               reader.comp_unit_die);
+    build_type_psymtabs_reader (&reader, data->storage);
 
   return 1;
 }
@@ -7326,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
-process_skeletonless_type_units (dwarf2_per_objfile *per_objfile)
+process_skeletonless_type_units (dwarf2_per_objfile *per_objfile,
+                                cooked_index_storage *storage)
 {
+  skeleton_data data { per_objfile, storage };
+
   /* Skeletonless TUs in DWP files without .gdb_index is not supported yet.  */
   if (get_dwp_file (per_objfile) == NULL
       && per_objfile->per_bfd->dwo_files != NULL)
     {
       htab_traverse_noresize (per_objfile->per_bfd->dwo_files.get (),
                              process_dwo_file_for_skeletonless_type_units,
-                             per_objfile);
-    }
-}
-
-/* Compute the 'user' field for each psymtab in DWARF2_PER_OBJFILE.  */
-
-static void
-set_partial_user (dwarf2_per_objfile *per_objfile)
-{
-  for (const auto &per_cu : per_objfile->per_bfd->all_comp_units)
-    {
-      dwarf2_psymtab *pst = per_cu->v.psymtab;
-
-      if (pst == NULL)
-       continue;
-
-      for (int j = 0; j < pst->number_of_dependencies; ++j)
-       {
-         /* Set the 'user' field only if it is not already set.  */
-         if (pst->dependencies[j]->user == NULL)
-           pst->dependencies[j]->user = pst;
-       }
+                             &data);
     }
 }
 
@@ -7371,95 +7110,107 @@ dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile)
   dwarf_read_debug_printf ("Building psymtabs of objfile %s ...",
                           objfile_name (objfile));
 
-  scoped_restore restore_reading_psyms
-    = make_scoped_restore (&per_bfd->reading_partial_symbols, true);
-
-  per_bfd->info.read (objfile);
-
-  /* Any cached compilation units will be linked by the per-objfile
-     read_in_chain.  Make sure to free them when we're done.  */
-  free_cached_comp_units freer (per_objfile);
+  per_bfd->map_info_sections (objfile);
 
+  cooked_index_storage index_storage;
   create_all_comp_units (per_objfile);
-  build_type_psymtabs (per_objfile);
+  build_type_psymtabs (per_objfile, &index_storage);
+  std::vector<std::unique_ptr<cooked_index>> indexes;
 
-  /* Create a temporary address map on a temporary obstack.  We later
-     copy this to the final obstack.  */
-  auto_obstack temp_obstack;
+  per_bfd->quick_file_names_table
+    = create_quick_file_names_table (per_bfd->all_comp_units.size ());
+  if (!per_bfd->debug_aranges.empty ())
+    read_addrmap_from_aranges (per_objfile, &per_bfd->debug_aranges,
+                              index_storage.get_addrmap ());
 
-  scoped_restore save_psymtabs_addrmap
-    = make_scoped_restore (&per_bfd->partial_symtabs->psymtabs_addrmap,
-                          addrmap_create_mutable (&temp_obstack));
+  {
+    /* Ensure that complaints are handled correctly.  */
+    complaint_interceptor complaint_handler;
+
+    using iter_type = decltype (per_bfd->all_comp_units.begin ());
+
+    /* Each thread returns a pair holding a cooked index, and a vector
+       of errors that should be printed.  The latter is done because
+       GDB's I/O system is not thread-safe.  run_on_main_thread could be
+       used, but that would mean the messages are printed after the
+       prompt, which looks weird.  */
+    using result_type = std::pair<std::unique_ptr<cooked_index>,
+                                 std::vector<gdb_exception>>;
+    std::vector<result_type> results
+      = gdb::parallel_for_each (1, per_bfd->all_comp_units.begin (),
+                               per_bfd->all_comp_units.end (),
+                               [=] (iter_type iter, iter_type end)
+      {
+       std::vector<gdb_exception> errors;
+       cooked_index_storage thread_storage;
+       for (; iter != end; ++iter)
+         {
+           dwarf2_per_cu_data *per_cu = iter->get ();
+           try
+             {
+               process_psymtab_comp_unit (per_cu, per_objfile,
+                                          &thread_storage);
+             }
+           catch (gdb_exception &except)
+             {
+               errors.push_back (std::move (except));
+             }
+         }
+       return result_type (thread_storage.release (), std::move (errors));
+      });
 
-  for (const auto &per_cu : per_bfd->all_comp_units)
-    {
-      if (per_cu->v.psymtab != NULL)
-       /* In case a forward DW_TAG_imported_unit has read the CU already.  */
-       continue;
-      process_psymtab_comp_unit (per_cu.get (), per_objfile, false,
-                                language_minimal);
-    }
+    /* Only show a given exception a single time.  */
+    std::unordered_set<gdb_exception> seen_exceptions;
+    for (auto &one_result : results)
+      {
+       indexes.push_back (std::move (one_result.first));
+       for (auto &one_exc : one_result.second)
+         if (seen_exceptions.insert (one_exc).second)
+           exception_print (gdb_stderr, one_exc);
+      }
+  }
 
   /* This has to wait until we read the CUs, we need the list of DWOs.  */
-  process_skeletonless_type_units (per_objfile);
-
-  /* Now that all TUs have been processed we can fill in the dependencies.  */
-  if (per_bfd->type_unit_groups != NULL)
-    {
-      htab_traverse_noresize (per_bfd->type_unit_groups.get (),
-                             build_type_psymtab_dependencies, per_objfile);
-    }
+  process_skeletonless_type_units (per_objfile, &index_storage);
 
   if (dwarf_read_debug > 0)
     print_tu_stats (per_objfile);
 
-  set_partial_user (per_objfile);
-
-  per_bfd->partial_symtabs->psymtabs_addrmap
-    = addrmap_create_fixed (per_bfd->partial_symtabs->psymtabs_addrmap,
-                           per_bfd->partial_symtabs->obstack ());
-  /* At this point we want to keep the address map.  */
-  save_psymtabs_addrmap.release ();
+  indexes.push_back (index_storage.release ());
+  /* Remove any NULL entries.  This might happen if parallel-for
+     decides to throttle the number of threads that were used.  */
+  indexes.erase
+    (std::remove_if (indexes.begin (),
+                    indexes.end (),
+                    [] (const std::unique_ptr<cooked_index> &entry)
+                    {
+                      return entry == nullptr;
+                    }),
+     indexes.end ());
+  indexes.shrink_to_fit ();
+  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));
 }
 
-/* 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)
+read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
+                             struct dwarf2_section_info *section,
+                             struct dwarf2_section_info *abbrev_section,
+                             unsigned int is_dwz,
+                             htab_up &types_htab,
+                             rcuh_kind section_kind)
 {
-  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,
-                             struct dwarf2_section_info *abbrev_section,
-                             unsigned int is_dwz,
-                             htab_up &types_htab,
-                             rcuh_kind section_kind)
-{
-  const gdb_byte *info_ptr;
-  struct objfile *objfile = per_objfile->objfile;
+  const gdb_byte *info_ptr;
+  struct objfile *objfile = per_objfile->objfile;
 
   dwarf_read_debug_printf ("Reading %s for %s",
                           section->get_name (),
@@ -7532,612 +7283,18 @@ create_all_comp_units (dwarf2_per_objfile *per_objfile)
 
   dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd);
   if (dwz != NULL)
-    read_comp_units_from_section (per_objfile, &dwz->info, &dwz->abbrev, 1,
-                                 types_htab, rcuh_kind::COMPILE);
-
-  per_objfile->per_bfd->signatured_types = std::move (types_htab);
-}
-
-/* Process all loaded DIEs for compilation unit CU, starting at
-   FIRST_DIE.  The caller should pass SET_ADDRMAP == 1 if the compilation
-   unit DIE did not have PC info (DW_AT_low_pc and DW_AT_high_pc, or
-   DW_AT_ranges).  See the comments of add_partial_subprogram on how
-   SET_ADDRMAP is used and how *LOWPC and *HIGHPC are updated.  */
-
-static void
-scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
-                     CORE_ADDR *highpc, int set_addrmap,
-                     struct dwarf2_cu *cu)
-{
-  struct partial_die_info *pdi;
-
-  /* Now, march along the PDI's, descending into ones which have
-     interesting children but skipping the children of the other ones,
-     until we reach the end of the compilation unit.  */
-
-  pdi = first_die;
-
-  while (pdi != NULL)
-    {
-      pdi->fixup (cu);
-
-      /* Anonymous namespaces or modules have no name but have interesting
-        children, so we need to look at them.  Ditto for anonymous
-        enums.  */
-
-      if (pdi->raw_name != NULL || pdi->tag == DW_TAG_namespace
-         || pdi->tag == DW_TAG_module || pdi->tag == DW_TAG_enumeration_type
-         || pdi->tag == DW_TAG_imported_unit
-         || pdi->tag == DW_TAG_inlined_subroutine)
-       {
-         switch (pdi->tag)
-           {
-           case DW_TAG_subprogram:
-           case DW_TAG_inlined_subroutine:
-             add_partial_subprogram (pdi, lowpc, highpc, set_addrmap, cu);
-             if (cu->per_cu->lang == language_cplus)
-               scan_partial_symbols (pdi->die_child, lowpc, highpc,
-                                     set_addrmap, cu);
-             break;
-           case DW_TAG_constant:
-           case DW_TAG_variable:
-           case DW_TAG_typedef:
-           case DW_TAG_union_type:
-             if (!pdi->is_declaration
-                 || (pdi->tag == DW_TAG_variable && pdi->is_external))
-               {
-                 add_partial_symbol (pdi, cu);
-               }
-             break;
-           case DW_TAG_class_type:
-           case DW_TAG_interface_type:
-           case DW_TAG_structure_type:
-             if (!pdi->is_declaration)
-               {
-                 add_partial_symbol (pdi, cu);
-               }
-             if ((cu->per_cu->lang == language_rust
-                  || cu->per_cu->lang == language_cplus)
-                 && pdi->has_children)
-               scan_partial_symbols (pdi->die_child, lowpc, highpc,
-                                     set_addrmap, cu);
-             break;
-           case DW_TAG_enumeration_type:
-             if (!pdi->is_declaration)
-               add_partial_enumeration (pdi, cu);
-             break;
-           case DW_TAG_base_type:
-           case DW_TAG_subrange_type:
-             /* File scope base type definitions are added to the partial
-                symbol table.  */
-             add_partial_symbol (pdi, cu);
-             break;
-           case DW_TAG_namespace:
-             add_partial_namespace (pdi, lowpc, highpc, set_addrmap, cu);
-             break;
-           case DW_TAG_module:
-             if (!pdi->is_declaration)
-               add_partial_module (pdi, lowpc, highpc, set_addrmap, cu);
-             break;
-           case DW_TAG_imported_unit:
-             {
-               struct dwarf2_per_cu_data *per_cu;
-
-               /* For now we don't handle imported units in type units.  */
-               if (cu->per_cu->is_debug_types)
-                 {
-                   error (_("Dwarf Error: DW_TAG_imported_unit is not"
-                            " supported in type units [in module %s]"),
-                          objfile_name (cu->per_objfile->objfile));
-                 }
-
-               per_cu = dwarf2_find_containing_comp_unit
-                          (pdi->d.sect_off, pdi->is_dwz, cu->per_objfile);
-
-               /* Go read the partial unit, if needed.  */
-               if (per_cu->v.psymtab == NULL)
-                 process_psymtab_comp_unit (per_cu, cu->per_objfile, true,
-                                            cu->per_cu->lang);
-
-               if (pdi->die_parent == nullptr
-                   && per_cu->unit_type == DW_UT_compile
-                   && per_cu->lang == language_cplus)
-                 /* Regard import as hint.  See corresponding code in
-                    process_imported_unit_die.  */
-                 break;
-
-               cu->per_cu->imported_symtabs_push (per_cu);
-             }
-             break;
-           case DW_TAG_imported_declaration:
-             add_partial_symbol (pdi, cu);
-             break;
-           default:
-             break;
-           }
-       }
-
-      /* If the die has a sibling, skip to the sibling.  */
-
-      pdi = pdi->die_sibling;
-    }
-}
-
-/* Functions used to compute the fully scoped name of a partial DIE.
-
-   Normally, this is simple.  For C++, the parent DIE's fully scoped
-   name is concatenated with "::" and the partial DIE's name.
-   Enumerators are an exception; they use the scope of their parent
-   enumeration type, i.e. the name of the enumeration type is not
-   prepended to the enumerator.
-
-   There are two complexities.  One is DW_AT_specification; in this
-   case "parent" means the parent of the target of the specification,
-   instead of the direct parent of the DIE.  The other is compilers
-   which do not emit DW_TAG_namespace; in this case we try to guess
-   the fully qualified name of structure types from their members'
-   linkage names.  This must be done using the DIE's children rather
-   than the children of any DW_AT_specification target.  We only need
-   to do this for structures at the top level, i.e. if the target of
-   any DW_AT_specification (if any; otherwise the DIE itself) does not
-   have a parent.  */
-
-/* Compute the scope prefix associated with PDI's parent, in
-   compilation unit CU.  The result will be allocated on CU's
-   comp_unit_obstack, or a copy of the already allocated PDI->NAME
-   field.  NULL is returned if no prefix is necessary.  */
-static const char *
-partial_die_parent_scope (struct partial_die_info *pdi,
-                         struct dwarf2_cu *cu)
-{
-  const char *grandparent_scope;
-  struct partial_die_info *parent, *real_pdi;
-
-  /* We need to look at our parent DIE; if we have a DW_AT_specification,
-     then this means the parent of the specification DIE.  */
-
-  real_pdi = pdi;
-  while (real_pdi->has_specification)
-    {
-      auto res = find_partial_die (real_pdi->spec_offset,
-                                  real_pdi->spec_is_dwz, cu);
-      real_pdi = res.pdi;
-      cu = res.cu;
-    }
-
-  parent = real_pdi->die_parent;
-  if (parent == NULL)
-    return NULL;
-
-  if (parent->scope_set)
-    return parent->scope;
-
-  parent->fixup (cu);
-
-  grandparent_scope = partial_die_parent_scope (parent, cu);
-
-  /* GCC 4.0 and 4.1 had a bug (PR c++/28460) where they generated bogus
-     DW_TAG_namespace DIEs with a name of "::" for the global namespace.
-     Work around this problem here.  */
-  if (cu->per_cu->lang == language_cplus
-      && parent->tag == DW_TAG_namespace
-      && strcmp (parent->name (cu), "::") == 0
-      && grandparent_scope == NULL)
-    {
-      parent->scope = NULL;
-      parent->scope_set = 1;
-      return NULL;
-    }
-
-  /* Nested subroutines in Fortran get a prefix.  */
-  if (pdi->tag == DW_TAG_enumerator)
-    /* Enumerators should not get the name of the enumeration as a prefix.  */
-    parent->scope = grandparent_scope;
-  else if (parent->tag == DW_TAG_namespace
-      || parent->tag == DW_TAG_module
-      || parent->tag == DW_TAG_structure_type
-      || parent->tag == DW_TAG_class_type
-      || parent->tag == DW_TAG_interface_type
-      || parent->tag == DW_TAG_union_type
-      || parent->tag == DW_TAG_enumeration_type
-      || (cu->per_cu->lang == language_fortran
-         && parent->tag == DW_TAG_subprogram
-         && pdi->tag == DW_TAG_subprogram))
-    {
-      if (grandparent_scope == NULL)
-       parent->scope = parent->name (cu);
-      else
-       parent->scope = typename_concat (&cu->comp_unit_obstack,
-                                        grandparent_scope,
-                                        parent->name (cu), 0, cu);
-    }
-  else
-    {
-      /* FIXME drow/2004-04-01: What should we be doing with
-        function-local names?  For partial symbols, we should probably be
-        ignoring them.  */
-      complaint (_("unhandled containing DIE tag %s for DIE at %s"),
-                dwarf_tag_name (parent->tag),
-                sect_offset_str (pdi->sect_off));
-      parent->scope = grandparent_scope;
-    }
-
-  parent->scope_set = 1;
-  return parent->scope;
-}
-
-/* Return the fully scoped name associated with PDI, from compilation unit
-   CU.  The result will be allocated with malloc.  */
-
-static gdb::unique_xmalloc_ptr<char>
-partial_die_full_name (struct partial_die_info *pdi,
-                      struct dwarf2_cu *cu)
-{
-  const char *parent_scope;
-
-  /* If this is a template instantiation, we can not work out the
-     template arguments from partial DIEs.  So, unfortunately, we have
-     to go through the full DIEs.  At least any work we do building
-     types here will be reused if full symbols are loaded later.  */
-  if (pdi->has_template_arguments)
-    {
-      pdi->fixup (cu);
-
-      if (pdi->name (cu) != NULL && strchr (pdi->name (cu), '<') == NULL)
-       {
-         struct die_info *die;
-         struct attribute attr;
-         struct dwarf2_cu *ref_cu = cu;
-
-         /* DW_FORM_ref_addr is using section offset.  */
-         attr.name = (enum dwarf_attribute) 0;
-         attr.form = DW_FORM_ref_addr;
-         attr.u.unsnd = to_underlying (pdi->sect_off);
-         die = follow_die_ref (NULL, &attr, &ref_cu);
-
-         return make_unique_xstrdup (dwarf2_full_name (NULL, die, ref_cu));
-       }
-    }
-
-  parent_scope = partial_die_parent_scope (pdi, cu);
-  if (parent_scope == NULL)
-    return NULL;
-  else
-    return gdb::unique_xmalloc_ptr<char> (typename_concat (NULL, parent_scope,
-                                                          pdi->name (cu),
-                                                          0, cu));
-}
-
-static void
-add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
-{
-  dwarf2_per_objfile *per_objfile = cu->per_objfile;
-  struct objfile *objfile = per_objfile->objfile;
-  struct gdbarch *gdbarch = objfile->arch ();
-  CORE_ADDR addr = 0;
-  const char *actual_name = NULL;
-  CORE_ADDR baseaddr;
-
-  baseaddr = objfile->text_section_offset ();
-
-  gdb::unique_xmalloc_ptr<char> built_actual_name
-    = partial_die_full_name (pdi, cu);
-  if (built_actual_name != NULL)
-    actual_name = built_actual_name.get ();
-
-  if (actual_name == NULL)
-    actual_name = pdi->name (cu);
-
-  partial_symbol psymbol;
-  memset (&psymbol, 0, sizeof (psymbol));
-  psymbol.ginfo.set_language (cu->per_cu->lang,
-                             &objfile->objfile_obstack);
-  psymbol.ginfo.set_section_index (-1);
-
-  /* The code below indicates that the psymbol should be installed by
-     setting this.  */
-  gdb::optional<psymbol_placement> where;
-
-  switch (pdi->tag)
-    {
-    case DW_TAG_inlined_subroutine:
-    case DW_TAG_subprogram:
-      addr = (gdbarch_adjust_dwarf2_addr (gdbarch, pdi->lowpc + baseaddr)
-             - baseaddr);
-      if (pdi->is_external
-         || cu->per_cu->lang == language_ada
-         || (cu->per_cu->lang == language_fortran
-             && pdi->die_parent != NULL
-             && pdi->die_parent->tag == DW_TAG_subprogram))
-       {
-         /* Normally, only "external" DIEs are part of the global scope.
-            But in Ada and Fortran, we want to be able to access nested
-            procedures globally.  So all Ada and Fortran subprograms are
-            stored in the global scope.  */
-         where = psymbol_placement::GLOBAL;
-       }
-      else
-       where = psymbol_placement::STATIC;
-
-      psymbol.domain = VAR_DOMAIN;
-      psymbol.aclass = LOC_BLOCK;
-      psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
-      psymbol.ginfo.value.address = addr;
-
-      if (pdi->main_subprogram && actual_name != NULL)
-       set_objfile_main_name (objfile, actual_name, cu->per_cu->lang);
-      break;
-    case DW_TAG_constant:
-      psymbol.domain = VAR_DOMAIN;
-      psymbol.aclass = LOC_STATIC;
-      where = (pdi->is_external
-              ? psymbol_placement::GLOBAL
-              : psymbol_placement::STATIC);
-      break;
-    case DW_TAG_variable:
-      if (pdi->d.locdesc)
-       addr = decode_locdesc (pdi->d.locdesc, cu);
-
-      if (pdi->d.locdesc
-         && addr == 0
-         && !per_objfile->per_bfd->has_section_at_zero)
-       {
-         /* A global or static variable may also have been stripped
-            out by the linker if unused, in which case its address
-            will be nullified; do not add such variables into partial
-            symbol table then.  */
-       }
-      else if (pdi->is_external)
-       {
-         /* Global Variable.
-            Don't enter into the minimal symbol tables as there is
-            a minimal symbol table entry from the ELF symbols already.
-            Enter into partial symbol table if it has a location
-            descriptor or a type.
-            If the location descriptor is missing, new_symbol will create
-            a LOC_UNRESOLVED symbol, the address of the variable will then
-            be determined from the minimal symbol table whenever the variable
-            is referenced.
-            The address for the partial symbol table entry is not
-            used by GDB, but it comes in handy for debugging partial symbol
-            table building.  */
-
-         if (pdi->d.locdesc || pdi->has_type)
-           {
-             psymbol.domain = VAR_DOMAIN;
-             psymbol.aclass = LOC_STATIC;
-             psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
-             psymbol.ginfo.value.address = addr;
-             where = psymbol_placement::GLOBAL;
-           }
-       }
-      else
-       {
-         int has_loc = pdi->d.locdesc != NULL;
-
-         /* Static Variable.  Skip symbols whose value we cannot know (those
-            without location descriptors or constant values).  */
-         if (!has_loc && !pdi->has_const_value)
-           return;
-
-         psymbol.domain = VAR_DOMAIN;
-         psymbol.aclass = LOC_STATIC;
-         psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
-         if (has_loc)
-           psymbol.ginfo.value.address = addr;
-         where = psymbol_placement::STATIC;
-       }
-      break;
-    case DW_TAG_array_type:
-    case DW_TAG_typedef:
-    case DW_TAG_base_type:
-    case DW_TAG_subrange_type:
-      psymbol.domain = VAR_DOMAIN;
-      psymbol.aclass = LOC_TYPEDEF;
-      where = psymbol_placement::STATIC;
-      break;
-    case DW_TAG_imported_declaration:
-    case DW_TAG_namespace:
-      psymbol.domain = VAR_DOMAIN;
-      psymbol.aclass = LOC_TYPEDEF;
-      where = psymbol_placement::GLOBAL;
-      break;
-    case DW_TAG_module:
-      /* With Fortran 77 there might be a "BLOCK DATA" module
-        available without any name.  If so, we skip the module as it
-        doesn't bring any value.  */
-      if (actual_name != nullptr)
-       {
-         psymbol.domain = MODULE_DOMAIN;
-         psymbol.aclass = LOC_TYPEDEF;
-         where = psymbol_placement::GLOBAL;
-       }
-      break;
-    case DW_TAG_class_type:
-    case DW_TAG_interface_type:
-    case DW_TAG_structure_type:
-    case DW_TAG_union_type:
-    case DW_TAG_enumeration_type:
-      /* Skip external references.  The DWARF standard says in the section
-        about "Structure, Union, and Class Type Entries": "An incomplete
-        structure, union or class type is represented by a structure,
-        union or class entry that does not have a byte size attribute
-        and that has a DW_AT_declaration attribute."  */
-      if (!pdi->has_byte_size && pdi->is_declaration)
-       return;
-
-      /* NOTE: carlton/2003-10-07: See comment in new_symbol about
-        static vs. global.  */
-      psymbol.domain = STRUCT_DOMAIN;
-      psymbol.aclass = LOC_TYPEDEF;
-      where = (cu->per_cu->lang == language_cplus
-              ? psymbol_placement::GLOBAL
-              : psymbol_placement::STATIC);
-      break;
-    case DW_TAG_enumerator:
-      psymbol.domain = VAR_DOMAIN;
-      psymbol.aclass = LOC_CONST;
-      where = (cu->per_cu->lang == language_cplus
-              ? psymbol_placement::GLOBAL
-              : psymbol_placement::STATIC);
-      break;
-    default:
-      break;
-    }
-
-  if (where.has_value ())
-    {
-      if (built_actual_name != nullptr)
-       actual_name = objfile->intern (actual_name);
-      if (pdi->linkage_name == nullptr
-         || cu->per_cu->lang == language_ada)
-       psymbol.ginfo.set_linkage_name (actual_name);
-      else
-       {
-         psymbol.ginfo.set_demangled_name (actual_name,
-                                           &objfile->objfile_obstack);
-         psymbol.ginfo.set_linkage_name (pdi->linkage_name);
-       }
-      cu->per_cu->v.psymtab->add_psymbol
-       (psymbol, *where, per_objfile->per_bfd->partial_symtabs.get (),
-        objfile);
-    }
-}
-
-/* Read a partial die corresponding to a namespace; also, add a symbol
-   corresponding to that namespace to the symbol table.  NAMESPACE is
-   the name of the enclosing namespace.  */
-
-static void
-add_partial_namespace (struct partial_die_info *pdi,
-                      CORE_ADDR *lowpc, CORE_ADDR *highpc,
-                      int set_addrmap, struct dwarf2_cu *cu)
-{
-  /* Add a symbol for the namespace.  */
-
-  add_partial_symbol (pdi, cu);
-
-  /* Now scan partial symbols in that namespace.  */
-
-  if (pdi->has_children)
-    scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu);
-}
-
-/* Read a partial die corresponding to a Fortran module.  */
-
-static void
-add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
-                   CORE_ADDR *highpc, int set_addrmap, struct dwarf2_cu *cu)
-{
-  /* Add a symbol for the namespace.  */
-
-  add_partial_symbol (pdi, cu);
-
-  /* Now scan partial symbols in that module.  */
-
-  if (pdi->has_children)
-    scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu);
-}
-
-/* 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_pc_info || (!pdi->is_external && pdi->may_be_inlined))
-       {
-         if (!pdi->is_declaration)
-           /* Ignore subprogram DIEs that do not have a name, they are
-              illegal.  Do not emit a complaint at this point, we will
-              do so when we convert this psymtab into a symtab.  */
-           if (pdi->name (cu))
-             add_partial_symbol (pdi, cu);
-       }
-    }
-
-  if (! pdi->has_children)
-    return;
-
-  if (cu->per_cu->lang == language_ada
-      || cu->per_cu->lang == language_fortran)
     {
-      pdi = pdi->die_child;
-      while (pdi != NULL)
-       {
-         pdi->fixup (cu);
-         if (pdi->tag == DW_TAG_subprogram
-             || pdi->tag == DW_TAG_inlined_subroutine
-             || pdi->tag == DW_TAG_lexical_block)
-           add_partial_subprogram (pdi, lowpc, highpc, set_addrmap, cu);
-         pdi = pdi->die_sibling;
-       }
+      /* Pre-read the sections we'll need to construct an index.  */
+      struct objfile *objfile = per_objfile->objfile;
+      dwz->abbrev.read (objfile);
+      dwz->info.read (objfile);
+      dwz->str.read (objfile);
+      dwz->line.read (objfile);
+      read_comp_units_from_section (per_objfile, &dwz->info, &dwz->abbrev, 1,
+                                   types_htab, rcuh_kind::COMPILE);
     }
-}
-
-/* Read a partial die corresponding to an enumeration type.  */
-
-static void
-add_partial_enumeration (struct partial_die_info *enum_pdi,
-                        struct dwarf2_cu *cu)
-{
-  struct partial_die_info *pdi;
-
-  if (enum_pdi->name (cu) != NULL)
-    add_partial_symbol (enum_pdi, cu);
 
-  pdi = enum_pdi->die_child;
-  while (pdi)
-    {
-      if (pdi->tag != DW_TAG_enumerator || pdi->raw_name == NULL)
-       complaint (_("malformed enumerator DIE ignored"));
-      else
-       add_partial_symbol (pdi, cu);
-      pdi = pdi->die_sibling;
-    }
+  per_objfile->per_bfd->signatured_types = std::move (types_htab);
 }
 
 /* Return the initial uleb128 in the die at INFO_PTR.  */
@@ -8205,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
-   ABBREV.  Returns a pointer to this DIE's sibling, skipping any
-   children.  */
+   ABBREV.
+   
+   If DO_SKIP_CHILDREN is true, or if the DIE has no children, this
+   returns a pointer to this DIE's sibling, skipping any children.
+   Otherwise, returns a pointer to the DIE's first child.  */
 
 static const gdb_byte *
 skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
-             const struct abbrev_info *abbrev)
+             const struct abbrev_info *abbrev, bool do_skip_children)
 {
   unsigned int bytes_read;
   struct attribute attr;
@@ -8220,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;
 
+  if (do_skip_children && abbrev->sibling_offset != (unsigned short) -1)
+    {
+      /* We only handle DW_FORM_ref4 here.  */
+      const gdb_byte *sibling_data = info_ptr + abbrev->sibling_offset;
+      unsigned int offset = read_4_bytes (abfd, sibling_data);
+      const gdb_byte *sibling_ptr
+       = buffer + to_underlying (cu->header.sect_off) + offset;
+      if (sibling_ptr >= info_ptr && sibling_ptr < reader->buffer_end)
+       return sibling_ptr;
+      /* Fall through to the slow way.  */
+    }
+  else if (abbrev->size_if_constant != 0)
+    {
+      info_ptr += abbrev->size_if_constant;
+      if (do_skip_children && abbrev->has_children)
+       return skip_children (reader, info_ptr);
+      return info_ptr;
+    }
+
   for (i = 0; i < abbrev->num_attrs; i++)
     {
       /* The only abbrev we care about is DW_AT_sibling.  */
-      if (abbrev->attrs[i].name == DW_AT_sibling)
+      if (do_skip_children && abbrev->attrs[i].name == DW_AT_sibling)
        {
          read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
          if (attr.form == DW_FORM_ref_addr)
@@ -8340,77 +7519,26 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
        }
     }
 
-  if (abbrev->has_children)
+  if (do_skip_children && abbrev->has_children)
     return skip_children (reader, info_ptr);
   else
     return info_ptr;
 }
+\f
+/* Reading in full CUs.  */
 
-/* Locate ORIG_PDI's sibling.
-   INFO_PTR should point to the start of the next DIE after ORIG_PDI.  */
+/* Add PER_CU to the queue.  */
 
-static const gdb_byte *
-locate_pdi_sibling (const struct die_reader_specs *reader,
-                   struct partial_die_info *orig_pdi,
-                   const gdb_byte *info_ptr)
+static void
+queue_comp_unit (dwarf2_per_cu_data *per_cu,
+                dwarf2_per_objfile *per_objfile,
+                enum language pretend_language)
 {
-  /* Do we know the sibling already?  */
+  per_cu->queued = 1;
 
-  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.  */
-
-/* Add PER_CU to the queue.  */
-
-static void
-queue_comp_unit (dwarf2_per_cu_data *per_cu,
-                dwarf2_per_objfile *per_objfile,
-                enum language pretend_language)
-{
-  per_cu->queued = 1;
-
-  gdb_assert (per_objfile->per_bfd->queue.has_value ());
-  per_cu->per_bfd->queue->emplace (per_cu, per_objfile, pretend_language);
-}
+  gdb_assert (per_objfile->per_bfd->queue.has_value ());
+  per_cu->per_bfd->queue->emplace (per_cu, per_objfile, pretend_language);
+}
 
 /* If PER_CU is not yet expanded of queued for expansion, add it to the queue.
 
@@ -8443,18 +7571,6 @@ maybe_queue_comp_unit (struct dwarf2_cu *dependent_cu,
                       dwarf2_per_objfile *per_objfile,
                       enum language pretend_language)
 {
-  /* We may arrive here during partial symbol reading, if we need full
-     DIEs to process an unusual case (e.g. template arguments).  Do
-     not queue PER_CU, just tell our caller to load its DIEs.  */
-  if (per_cu->per_bfd->reading_partial_symbols)
-    {
-      dwarf2_cu *cu = per_objfile->get_cu (per_cu);
-
-      if (cu == NULL || cu->dies == NULL)
-       return 1;
-      return 0;
-    }
-
   /* Mark the dependence relation so that we don't flush PER_CU
      too early.  */
   if (dependent_cu != NULL)
@@ -8559,39 +7675,6 @@ process_queue (dwarf2_per_objfile *per_objfile)
                           objfile_name (per_objfile->objfile));
 }
 
-/* Read in full symbols for PST, and anything it depends on.  */
-
-void
-dwarf2_psymtab::expand_psymtab (struct objfile *objfile)
-{
-  gdb_assert (!readin_p (objfile));
-
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-  free_cached_comp_units freer (per_objfile);
-  expand_dependencies (objfile);
-
-  dw2_do_instantiate_symtab (per_cu_data, per_objfile, false);
-  gdb_assert (get_compunit_symtab (objfile) != nullptr);
-}
-
-/* See psympriv.h.  */
-
-bool
-dwarf2_psymtab::readin_p (struct objfile *objfile) const
-{
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-  return per_objfile->symtab_set_p (per_cu_data);
-}
-
-/* See psympriv.h.  */
-
-compunit_symtab *
-dwarf2_psymtab::get_compunit_symtab (struct objfile *objfile) const
-{
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-  return per_objfile->get_symtab (per_cu_data);
-}
-
 /* Trivial hash function for die_info: the hash value of a DIE
    is its offset in .debug_info for this objfile.  */
 
@@ -8774,7 +7857,7 @@ fixup_go_packaging (struct dwarf2_cu *cu)
          struct symbol *sym = list->symbol[i];
 
          if (sym->language () == language_go
-             && SYMBOL_CLASS (sym) == LOC_BLOCK)
+             && sym->aclass () == LOC_BLOCK)
            {
              gdb::unique_xmalloc_ptr<char> this_package_name
                (go_symbol_package_name (sym));
@@ -8811,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().  */
-      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 ());
     }
@@ -8933,9 +8016,9 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
 
 #define RUST_ENUM_PREFIX "RUST$ENCODED$ENUM$"
   if (type->num_fields () == 1
-      && startswith (TYPE_FIELD_NAME (type, 0), RUST_ENUM_PREFIX))
+      && startswith (type->field (0).name (), RUST_ENUM_PREFIX))
     {
-      const char *name = TYPE_FIELD_NAME (type, 0) + strlen (RUST_ENUM_PREFIX);
+      const char *name = type->field (0).name () + strlen (RUST_ENUM_PREFIX);
 
       /* Decode the field name to find the offset of the
         discriminant.  */
@@ -8948,18 +8031,18 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
          name = tail;
          if (*name != '$'
              || index >= field_type->num_fields ()
-             || (TYPE_FIELD_LOC_KIND (field_type, index)
+             || (field_type->field (index).loc_kind ()
                  != FIELD_LOC_KIND_BITPOS))
            {
              complaint (_("Could not parse Rust enum encoding string \"%s\""
                           "[in module %s]"),
-                        TYPE_FIELD_NAME (type, 0),
+                        type->field (0).name (),
                         objfile_name (objfile));
              return;
            }
          ++name;
 
-         bit_offset += TYPE_FIELD_BITPOS (field_type, index);
+         bit_offset += field_type->field (index).loc_bitpos ();
          field_type = field_type->field (index).type ();
        }
 
@@ -8975,17 +8058,17 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
       /* Put the discriminant at index 0.  */
       type->field (0).set_type (field_type);
       TYPE_FIELD_ARTIFICIAL (type, 0) = 1;
-      TYPE_FIELD_NAME (type, 0) = "<<discriminant>>";
-      SET_FIELD_BITPOS (type->field (0), bit_offset);
+      type->field (0).set_name ("<<discriminant>>");
+      type->field (0).set_loc_bitpos (bit_offset);
 
       /* The order of fields doesn't really matter, so put the real
         field at index 1 and the data-less field at index 2.  */
       type->field (1) = saved_field;
-      TYPE_FIELD_NAME (type, 1)
-       = rust_last_path_segment (type->field (1).type ()->name ());
+      type->field (1).set_name
+       (rust_last_path_segment (type->field (1).type ()->name ()));
       type->field (1).type ()->set_name
        (rust_fully_qualify (&objfile->objfile_obstack, type->name (),
-                            TYPE_FIELD_NAME (type, 1)));
+                            type->field (1).name ()));
 
       const char *dataless_name
        = rust_fully_qualify (&objfile->objfile_obstack, type->name (),
@@ -8995,8 +8078,8 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
       type->field (2).set_type (dataless_type);
       /* NAME points into the original discriminant name, which
         already has the correct lifetime.  */
-      TYPE_FIELD_NAME (type, 2) = name;
-      SET_FIELD_BITPOS (type->field (2), 0);
+      type->field (2).set_name (name);
+      type->field (2).set_loc_bitpos (0);
 
       /* Indicate that this is a variant type.  */
       static discriminant_range ranges[1] = { { 0, 0 } };
@@ -9004,7 +8087,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
     }
   /* A union with a single anonymous field is probably an old-style
      univariant enum.  */
-  else if (type->num_fields () == 1 && streq (TYPE_FIELD_NAME (type, 0), ""))
+  else if (type->num_fields () == 1 && streq (type->field (0).name (), ""))
     {
       /* Smash this type to be a structure type.  We have to do this
         because the type has already been recorded.  */
@@ -9013,7 +8096,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
       struct type *field_type = type->field (0).type ();
       const char *variant_name
        = rust_last_path_segment (field_type->name ());
-      TYPE_FIELD_NAME (type, 0) = variant_name;
+      type->field (0).set_name (variant_name);
       field_type->set_name
        (rust_fully_qualify (&objfile->objfile_obstack,
                             type->name (), variant_name));
@@ -9037,7 +8120,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
              /* Could be data-less variant, so keep going.  */
              disr_type = nullptr;
            }
-         else if (strcmp (TYPE_FIELD_NAME (disr_type, 0),
+         else if (strcmp (disr_type->field (0).name (),
                           "RUST$ENUM$DISR") != 0)
            {
              /* Not a Rust enum.  */
@@ -9072,7 +8155,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
       /* Install the discriminant at index 0 in the union.  */
       type->field (0) = *disr_field;
       TYPE_FIELD_ARTIFICIAL (type, 0) = 1;
-      TYPE_FIELD_NAME (type, 0) = "<<discriminant>>";
+      type->field (0).set_name ("<<discriminant>>");
 
       /* We need a way to find the correct discriminant given a
         variant name.  For convenience we build a map here.  */
@@ -9080,11 +8163,11 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
       std::unordered_map<std::string, ULONGEST> discriminant_map;
       for (int i = 0; i < enum_type->num_fields (); ++i)
        {
-         if (TYPE_FIELD_LOC_KIND (enum_type, i) == FIELD_LOC_KIND_ENUMVAL)
+         if (enum_type->field (i).loc_kind () == FIELD_LOC_KIND_ENUMVAL)
            {
              const char *name
-               = rust_last_path_segment (TYPE_FIELD_NAME (enum_type, i));
-             discriminant_map[name] = TYPE_FIELD_ENUMVAL (enum_type, i);
+               = rust_last_path_segment (enum_type->field (i).name ());
+             discriminant_map[name] = enum_type->field (i).loc_enumval ();
            }
        }
 
@@ -9122,7 +8205,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
              sub_type->set_num_fields (sub_type->num_fields () - 1);
              sub_type->set_fields (sub_type->fields () + 1);
            }
-         TYPE_FIELD_NAME (type, i) = variant_name;
+         type->field (i).set_name (variant_name);
          sub_type->set_name
            (rust_fully_qualify (&objfile->objfile_obstack,
                                 type->name (), variant_name));
@@ -9351,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);
-  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
@@ -9360,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);
 
-  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)
     {
@@ -9372,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
-           && 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
@@ -9388,12 +8471,12 @@ process_full_comp_unit (dwarf2_cu *cu, enum language pretend_language)
         options - this waits on GCC PR other/32998 (-frecord-gcc-switches).
         */
       if (cu->has_loclist && gcc_4_minor >= 5)
-       cust->locations_valid = 1;
+       cust->set_locations_valid (true);
 
       if (gcc_4_minor >= 5)
-       cust->epilogue_unwind_valid = 1;
+       cust->set_epilogue_unwind_valid (true);
 
-      cust->call_site_htab = cu->call_site_htab;
+      cust->set_call_site_htab (cu->call_site_htab);
     }
 
   per_objfile->set_symtab (cu->per_cu, cust);
@@ -9457,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
-               && 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
@@ -9495,7 +8578,8 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
       bool is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz);
       dwarf2_per_objfile *per_objfile = cu->per_objfile;
       dwarf2_per_cu_data *per_cu
-       = dwarf2_find_containing_comp_unit (sect_off, is_dwz, per_objfile);
+       = dwarf2_find_containing_comp_unit (sect_off, is_dwz,
+                                           per_objfile->per_bfd);
 
       /* We're importing a C++ compilation unit with tag DW_TAG_compile_unit
         into another compilation unit, at root level.  Regard this as a hint,
@@ -9588,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_namelist:
       process_structure_scope (die, cu);
       break;
     case DW_TAG_enumeration_type:
@@ -9615,6 +8700,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       /* FALLTHROUGH */
     case DW_TAG_base_type:
     case DW_TAG_subrange_type:
+    case DW_TAG_generic_subrange:
     case DW_TAG_typedef:
       /* Add a typedef symbol for the type definition, if it has a
         DW_AT_name.  */
@@ -9928,7 +9014,7 @@ dwarf2_compute_name (const char *name,
                      else if (bytes != NULL)
                        {
                          v = allocate_value (type);
-                         memcpy (value_contents_writeable (v), bytes,
+                         memcpy (value_contents_writeable (v).data (), bytes,
                                  TYPE_LENGTH (type));
                        }
                      else
@@ -10057,9 +9143,8 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
             to look up their definition from their declaration so
             the only disadvantage remains the minimal symbol variant
             `long name(params)' does not have the proper inferior type.  */
-         demangled.reset (gdb_demangle (mangled,
-                                        (DMGL_PARAMS | DMGL_ANSI
-                                         | DMGL_RET_DROP)));
+         demangled = gdb_demangle (mangled, (DMGL_PARAMS | DMGL_ANSI
+                                             | DMGL_RET_DROP));
        }
       if (demangled)
        canon = demangled.get ();
@@ -10369,38 +9454,25 @@ producer_is_gcc_lt_4_3 (struct dwarf2_cu *cu)
   return cu->producer_is_gcc_lt_4_3;
 }
 
-static file_and_directory
+static file_and_directory &
 find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu)
 {
-  file_and_directory res;
+  if (cu->per_cu->fnd != nullptr)
+    return *cu->per_cu->fnd;
 
   /* Find the filename.  Do not use dwarf2_name here, since the filename
      is not a source language identifier.  */
-  res.name = dwarf2_string_attr (die, DW_AT_name, cu);
-  res.comp_dir = dwarf2_string_attr (die, DW_AT_comp_dir, cu);
+  file_and_directory res (dwarf2_string_attr (die, DW_AT_name, cu),
+                         dwarf2_string_attr (die, DW_AT_comp_dir, cu));
 
-  if (res.comp_dir == NULL
-      && producer_is_gcc_lt_4_3 (cu) && res.name != NULL
-      && IS_ABSOLUTE_PATH (res.name))
-    {
-      res.comp_dir_storage = ldirname (res.name);
-      if (!res.comp_dir_storage.empty ())
-       res.comp_dir = res.comp_dir_storage.c_str ();
-    }
-  if (res.comp_dir != NULL)
-    {
-      /* Irix 6.2 native cc prepends <machine>.: to the compilation
-        directory, get rid of it.  */
-      const char *cp = strchr (res.comp_dir, ':');
-
-      if (cp && cp != res.comp_dir && cp[-1] == '.' && cp[1] == '/')
-       res.comp_dir = cp + 1;
-    }
-
-  if (res.name == NULL)
-    res.name = "<unknown>";
+  if (res.get_comp_dir () == nullptr
+      && producer_is_gcc_lt_4_3 (cu)
+      && res.get_name () != nullptr
+      && IS_ABSOLUTE_PATH (res.get_name ()))
+    res.set_comp_dir (ldirname (res.get_name ()));
 
-  return res;
+  cu->per_cu->fnd.reset (new file_and_directory (std::move (res)));
+  return *cu->per_cu->fnd;
 }
 
 /* Handle DW_AT_stmt_list for a compilation unit.
@@ -10410,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,
-                       const char *comp_dir, CORE_ADDR lowpc) /* ARI: editCase function */
+                       CORE_ADDR lowpc) /* ARI: editCase function */
 {
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
   struct attribute *attr;
@@ -10498,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);
-  dwarf_decode_lines (cu->line_header, comp_dir, cu, NULL, lowpc,
-                     decode_mapping);
-
+  dwarf_decode_lines (cu->line_header, cu, lowpc, decode_mapping);
 }
 
 /* Process DW_TAG_compile_unit or DW_TAG_partial_unit.  */
@@ -10528,9 +9598,10 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
     lowpc = highpc;
   lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
 
-  file_and_directory fnd = find_file_and_directory (die, cu);
+  file_and_directory &fnd = find_file_and_directory (die, cu);
 
-  cu->start_symtab (fnd.name, fnd.comp_dir, 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
@@ -10538,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
-     for DW_AT_decl_file.  */
-  handle_DW_AT_stmt_list (die, cu, fnd.comp_dir, 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)
@@ -10618,15 +9694,15 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
   if (lh == NULL)
     {
       if (first_time)
-       start_symtab ("", NULL, 0);
+       start_compunit_symtab ("", NULL, 0);
       else
        {
          gdb_assert (tug_unshare->symtabs == NULL);
          gdb_assert (m_builder == nullptr);
          struct compunit_symtab *cust = tug_unshare->compunit_symtab;
          m_builder.reset (new struct buildsym_compunit
-                          (COMPUNIT_OBJFILE (cust), "",
-                           COMPUNIT_DIRNAME (cust),
+                          (cust->objfile (), "",
+                           cust->dirname (),
                            compunit_language (cust),
                            0, cust));
          list_in_scope = get_builder ()->get_file_symbols ();
@@ -10639,7 +9715,7 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
 
   if (first_time)
     {
-      struct compunit_symtab *cust = start_symtab ("", NULL, 0);
+      struct compunit_symtab *cust = start_compunit_symtab ("", NULL, 0);
 
       /* Note: We don't assign tu_group->compunit_symtab yet because we're
         still initializing it, and our caller (a few levels up)
@@ -10647,7 +9723,7 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
         time.  */
 
       tug_unshare->symtabs
-       = XOBNEWVEC (&COMPUNIT_OBJFILE (cust)->objfile_obstack,
+       = XOBNEWVEC (&cust->objfile ()->objfile_obstack,
                     struct symtab *, line_header->file_names_size ());
 
       auto &file_names = line_header->file_names ();
@@ -10677,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
-                      (COMPUNIT_OBJFILE (cust), "",
-                       COMPUNIT_DIRNAME (cust),
+                      (cust->objfile (), "",
+                       cust->dirname (),
                        compunit_language (cust),
                        0, cust));
       list_in_scope = get_builder ()->get_file_symbols ();
@@ -12016,10 +11092,10 @@ try_open_dwop_file (dwarf2_per_objfile *per_objfile,
   gdb::unique_xmalloc_ptr<char> search_path_holder;
   if (search_cwd)
     {
-      if (*debug_file_directory != '\0')
+      if (!debug_file_directory.empty ())
        {
          search_path_holder.reset (concat (".", dirname_separator_string,
-                                           debug_file_directory,
+                                           debug_file_directory.c_str (),
                                            (char *) NULL));
          search_path = search_path_holder.get ();
        }
@@ -12027,7 +11103,7 @@ try_open_dwop_file (dwarf2_per_objfile *per_objfile,
        search_path = ".";
     }
   else
-    search_path = debug_file_directory;
+    search_path = debug_file_directory.c_str ();
 
   /* Add the path for the executable binary to the list of search paths.  */
   std::string objfile_dir = ldirname (objfile_name (per_objfile->objfile));
@@ -12098,7 +11174,7 @@ open_dwo_file (dwarf2_per_objfile *per_objfile,
   /* That didn't work, try debug-file-directory, which, despite its name,
      is a list of paths.  */
 
-  if (*debug_file_directory == '\0')
+  if (debug_file_directory.empty ())
     return NULL;
 
   return try_open_dwop_file (per_objfile, file_name,
@@ -12109,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
-dwarf2_locate_dwo_sections (bfd *abfd, asection *sectp,
-                           dwo_sections *dwo_sections)
+dwarf2_locate_dwo_sections (struct objfile *objfile, bfd *abfd,
+                           asection *sectp, dwo_sections *dwo_sections)
 {
   const struct dwop_section_names *names = &dwop_section_names;
 
+  struct dwarf2_section_info *dw_sect = nullptr;
+
   if (names->abbrev_dwo.matches (sectp->name))
-    {
-      dwo_sections->abbrev.s.section = sectp;
-      dwo_sections->abbrev.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->abbrev;
   else if (names->info_dwo.matches (sectp->name))
-    {
-      dwo_sections->info.s.section = sectp;
-      dwo_sections->info.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->info;
   else if (names->line_dwo.matches (sectp->name))
-    {
-      dwo_sections->line.s.section = sectp;
-      dwo_sections->line.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->line;
   else if (names->loc_dwo.matches (sectp->name))
-    {
-      dwo_sections->loc.s.section = sectp;
-      dwo_sections->loc.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->loc;
   else if (names->loclists_dwo.matches (sectp->name))
-    {
-      dwo_sections->loclists.s.section = sectp;
-      dwo_sections->loclists.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->loclists;
   else if (names->macinfo_dwo.matches (sectp->name))
-    {
-      dwo_sections->macinfo.s.section = sectp;
-      dwo_sections->macinfo.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->macinfo;
   else if (names->macro_dwo.matches (sectp->name))
-    {
-      dwo_sections->macro.s.section = sectp;
-      dwo_sections->macro.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->macro;
   else if (names->rnglists_dwo.matches (sectp->name))
-    {
-      dwo_sections->rnglists.s.section = sectp;
-      dwo_sections->rnglists.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->rnglists;
   else if (names->str_dwo.matches (sectp->name))
-    {
-      dwo_sections->str.s.section = sectp;
-      dwo_sections->str.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->str;
   else if (names->str_offsets_dwo.matches (sectp->name))
-    {
-      dwo_sections->str_offsets.s.section = sectp;
-      dwo_sections->str_offsets.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwo_sections->str_offsets;
   else if (names->types_dwo.matches (sectp->name))
     {
       struct dwarf2_section_info type_section;
 
       memset (&type_section, 0, sizeof (type_section));
-      type_section.s.section = sectp;
-      type_section.size = bfd_section_size (sectp);
       dwo_sections->types.push_back (type_section);
+      dw_sect = &dwo_sections->types.back ();
+    }
+
+  if (dw_sect != nullptr)
+    {
+      dw_sect->s.section = sectp;
+      dw_sect->size = bfd_section_size (sectp);
+      dw_sect->read (objfile);
     }
 }
 
@@ -12199,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))
-    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);
@@ -12227,8 +11281,8 @@ open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name,
    we are interested in.  */
 
 static void
-dwarf2_locate_common_dwp_sections (bfd *abfd, asection *sectp,
-                                  dwp_file *dwp_file)
+dwarf2_locate_common_dwp_sections (struct objfile *objfile, bfd *abfd,
+                                  asection *sectp, dwp_file *dwp_file)
 {
   const struct dwop_section_names *names = &dwop_section_names;
   unsigned int elf_section_nr = elf_section_data (sectp)->this_idx;
@@ -12239,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.  */
+  struct dwarf2_section_info *dw_sect = nullptr;
   if (names->str_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.str.s.section = sectp;
-      dwp_file->sections.str.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.str;
   else if (names->cu_index.matches (sectp->name))
-    {
-      dwp_file->sections.cu_index.s.section = sectp;
-      dwp_file->sections.cu_index.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.cu_index;
   else if (names->tu_index.matches (sectp->name))
+    dw_sect = &dwp_file->sections.tu_index;
+
+  if (dw_sect != nullptr)
     {
-      dwp_file->sections.tu_index.s.section = sectp;
-      dwp_file->sections.tu_index.size = bfd_section_size (sectp);
+      dw_sect->s.section = sectp;
+      dw_sect->size = bfd_section_size (sectp);
+      dw_sect->read (objfile);
     }
 }
 
@@ -12262,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
-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;
@@ -12274,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.  */
+  struct dwarf2_section_info *dw_sect = nullptr;
   if (names->abbrev_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.abbrev.s.section = sectp;
-      dwp_file->sections.abbrev.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.abbrev;
   else if (names->info_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.info.s.section = sectp;
-      dwp_file->sections.info.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.info;
   else if (names->line_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.line.s.section = sectp;
-      dwp_file->sections.line.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.line;
   else if (names->loc_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.loc.s.section = sectp;
-      dwp_file->sections.loc.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.loc;
   else if (names->macinfo_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.macinfo.s.section = sectp;
-      dwp_file->sections.macinfo.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.macinfo;
   else if (names->macro_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.macro.s.section = sectp;
-      dwp_file->sections.macro.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.macro;
   else if (names->str_offsets_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.str_offsets.s.section = sectp;
-      dwp_file->sections.str_offsets.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.str_offsets;
   else if (names->types_dwo.matches (sectp->name))
+    dw_sect = &dwp_file->sections.types;
+
+  if (dw_sect != nullptr)
     {
-      dwp_file->sections.types.s.section = sectp;
-      dwp_file->sections.types.size = bfd_section_size (sectp);
+      dw_sect->s.section = sectp;
+      dw_sect->size = bfd_section_size (sectp);
+      dw_sect->read (objfile);
     }
 }
 
@@ -12322,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
-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;
@@ -12334,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.  */
+  struct dwarf2_section_info *dw_sect = nullptr;
   if (names->abbrev_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.abbrev.s.section = sectp;
-      dwp_file->sections.abbrev.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.abbrev;
   else if (names->info_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.info.s.section = sectp;
-      dwp_file->sections.info.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.info;
   else if (names->line_dwo.matches (sectp->name))
-   {
-     dwp_file->sections.line.s.section = sectp;
-     dwp_file->sections.line.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.line;
   else if (names->loclists_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.loclists.s.section = sectp;
-      dwp_file->sections.loclists.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.loclists;
   else if (names->macro_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.macro.s.section = sectp;
-      dwp_file->sections.macro.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.macro;
   else if (names->rnglists_dwo.matches (sectp->name))
-    {
-      dwp_file->sections.rnglists.s.section = sectp;
-      dwp_file->sections.rnglists.size = bfd_section_size (sectp);
-    }
+    dw_sect = &dwp_file->sections.rnglists;
   else if (names->str_offsets_dwo.matches (sectp->name))
+    dw_sect = &dwp_file->sections.str_offsets;
+
+  if (dw_sect != nullptr)
     {
-      dwp_file->sections.str_offsets.s.section = sectp;
-      dwp_file->sections.str_offsets.size = bfd_section_size (sectp);
+      dw_sect->s.section = sectp;
+      dw_sect->size = bfd_section_size (sectp);
+      dw_sect->read (objfile);
     }
 }
 
@@ -12427,7 +11453,7 @@ open_dwp_file (dwarf2_per_objfile *per_objfile, const char *file_name)
      [IWBN if the dwp file name was recorded in the executable, akin to
      .gnu_debuglink, but that doesn't exist yet.]
      Strip the directory from FILE_NAME and search again.  */
-  if (*debug_file_directory != '\0')
+  if (!debug_file_directory.empty ())
     {
       /* Don't implicitly search the current directory here.
         If the user wants to search "." to handle this case,
@@ -12494,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))
-    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);
@@ -12524,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)
-       dwarf2_locate_v2_dwp_sections (dwp_file->dbfd.get (), sec,
+       dwarf2_locate_v2_dwp_sections (objfile, dwp_file->dbfd.get (), sec,
                                       dwp_file.get ());
       else
-       dwarf2_locate_v5_dwp_sections (dwp_file->dbfd.get (), sec,
+       dwarf2_locate_v5_dwp_sections (objfile, dwp_file->dbfd.get (), sec,
                                       dwp_file.get ());
     }
 
@@ -12978,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.  */
-  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);
@@ -13151,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.  */
-  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
@@ -13213,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);
 }
 
+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
@@ -13223,7 +12254,6 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
   struct gdbarch *gdbarch = objfile->arch ();
   CORE_ADDR pc, baseaddr;
   struct attribute *attr;
-  struct call_site *call_site, call_site_local;
   void **slot;
   int nparams;
   struct die_info *child_die;
@@ -13246,12 +12276,14 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
     }
   pc = attr->as_address () + baseaddr;
   pc = gdbarch_adjust_dwarf2_addr (gdbarch, pc);
+  pc -= baseaddr;
 
   if (cu->call_site_htab == NULL)
-    cu->call_site_htab = htab_create_alloc_ex (16, core_addr_hash, core_addr_eq,
-                                              NULL, &objfile->objfile_obstack,
+    cu->call_site_htab = htab_create_alloc_ex (16, call_site::hash,
+                                              call_site::eq, NULL,
+                                              &objfile->objfile_obstack,
                                               hashtab_obstack_allocate, NULL);
-  call_site_local.pc = pc;
+  struct call_site call_site_local (pc, nullptr, nullptr);
   slot = htab_find_slot (cu->call_site_htab, &call_site_local, INSERT);
   if (*slot != NULL)
     {
@@ -13281,14 +12313,16 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
       nparams++;
     }
 
-  call_site
-    = ((struct call_site *)
-       obstack_alloc (&objfile->objfile_obstack,
-                     sizeof (*call_site)
-                     + (sizeof (*call_site->parameter) * (nparams - 1))));
+  struct call_site *call_site
+    = new (XOBNEWVAR (&objfile->objfile_obstack,
+                     struct call_site,
+                     sizeof (*call_site) + sizeof (call_site->parameter[0]) * nparams))
+    struct call_site (pc, cu->per_cu, per_objfile);
   *slot = call_site;
-  memset (call_site, 0, sizeof (*call_site) - sizeof (*call_site->parameter));
-  call_site->pc = pc;
+
+  /* We never call the destructor of call_site, so we must ensure it is
+     trivially destructible.  */
+  gdb_static_assert(std::is_trivially_destructible<struct call_site>::value);
 
   if (dwarf2_flag_true_p (die, DW_AT_call_tail_call, cu)
       || dwarf2_flag_true_p (die, DW_AT_GNU_tail_call, cu))
@@ -13349,7 +12383,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
       /* This was a pre-DWARF-5 GNU extension alias for DW_AT_call_origin.  */
       attr = dwarf2_attr (die, DW_AT_abstract_origin, cu);
     }
-  SET_FIELD_DWARF_BLOCK (call_site->target, NULL);
+
+  call_site->target.set_loc_dwarf_block (nullptr);
   if (!attr || (attr->form_is_block () && attr->as_block ()->size == 0))
     /* Keep NULL DWARF_BLOCK.  */;
   else if (attr->form_is_block ())
@@ -13363,7 +12398,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
       dlbaton->per_objfile = per_objfile;
       dlbaton->per_cu = cu->per_cu;
 
-      SET_FIELD_DWARF_BLOCK (call_site->target, dlbaton);
+      call_site->target.set_loc_dwarf_block (dlbaton);
     }
   else if (attr->form_is_ref ())
     {
@@ -13372,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);
+
+      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;
@@ -13385,22 +12424,36 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
                         "physname, for referencing DIE %s [in module %s]"),
                       sect_offset_str (die->sect_off), objfile_name (objfile));
          else
-           SET_FIELD_PHYSNAME (call_site->target, target_physname);
+           call_site->target.set_loc_physname (target_physname);
+       }
+      else if (ranges_attr != nullptr && ranges_attr->form_is_unsigned ())
+       {
+         ULONGEST ranges_offset = (ranges_attr->as_unsigned ()
+                                   + target_cu->gnu_ranges_base);
+         std::vector<CORE_ADDR> addresses;
+         dwarf2_ranges_read_low_addrs (ranges_offset, target_cu,
+                                       target_die->tag, addresses);
+         CORE_ADDR *saved = XOBNEWVAR (&objfile->objfile_obstack, CORE_ADDR,
+                                       addresses.size ());
+         std::copy (addresses.begin (), addresses.end (), saved);
+         call_site->target.set_loc_array (addresses.size (), saved);
        }
       else
        {
          CORE_ADDR lowpc;
 
          /* DW_AT_entry_pc should be preferred.  */
-         if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu, NULL)
+         if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu,
+                                   nullptr, nullptr)
              <= PC_BOUNDS_INVALID)
            complaint (_("DW_AT_call_target target DIE has invalid "
                         "low pc, for referencing DIE %s [in module %s]"),
                       sect_offset_str (die->sect_off), objfile_name (objfile));
          else
            {
-             lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
-             SET_FIELD_PHYSADDR (call_site->target, lowpc);
+             lowpc = (gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr)
+                      - baseaddr);
+             call_site->target.set_loc_physaddr (lowpc);
            }
        }
     }
@@ -13409,9 +12462,6 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
                 "block nor reference, for DIE %s [in module %s]"),
               sect_offset_str (die->sect_off), objfile_name (objfile));
 
-  call_site->per_cu = cu->per_cu;
-  call_site->per_objfile = per_objfile;
-
   for (child_die = die->child;
        child_die && child_die->tag;
        child_die = child_die->sibling)
@@ -13615,7 +12665,6 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
   /* Base address selection entry.  */
   gdb::optional<CORE_ADDR> base;
   const gdb_byte *buffer;
-  CORE_ADDR baseaddr;
   bool overflow = false;
   ULONGEST addr_index;
   struct dwarf2_section_info *rnglists_section;
@@ -13632,8 +12681,6 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
     }
   buffer = rnglists_section->buffer + offset;
 
-  baseaddr = objfile->text_section_offset ();
-
   while (1)
     {
       /* Initialize it due to a false compiler warning.  */
@@ -13775,7 +12822,7 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
 
       /* A not-uncommon case of bad debug info.
         Don't pollute the addrmap with bad data.  */
-      if (range_beginning + baseaddr == 0
+      if (range_beginning == 0
          && !per_objfile->per_bfd->has_section_at_zero)
        {
          complaint (_(".debug_rnglists entry has start address of zero"
@@ -13817,7 +12864,6 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu, dwarf_tag tag,
   gdb::optional<CORE_ADDR> base;
   unsigned int dummy;
   const gdb_byte *buffer;
-  CORE_ADDR baseaddr;
 
   if (cu_header->version >= 5)
     return dwarf2_rnglists_process (offset, cu, tag, callback);
@@ -13833,8 +12879,6 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu, dwarf_tag tag,
     }
   buffer = per_objfile->per_bfd->ranges.buffer + offset;
 
-  baseaddr = objfile->text_section_offset ();
-
   while (1)
     {
       CORE_ADDR range_beginning, range_end;
@@ -13885,7 +12929,7 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu, dwarf_tag tag,
 
       /* A not-uncommon case of bad debug info.
         Don't pollute the addrmap with bad data.  */
-      if (range_beginning + baseaddr == 0
+      if (range_beginning == 0
          && !per_objfile->per_bfd->has_section_at_zero)
        {
          complaint (_(".debug_ranges entry has start address of zero"
@@ -13901,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.
-   If RANGES_PST is not NULL we should set up the `psymtabs_addrmap'.  */
+   TAG is passed to dwarf2_ranges_process.  If MAP is not NULL, then
+   ranges in MAP are set, using DATUM as the value.  */
 
 static int
 dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
                    CORE_ADDR *high_return, struct dwarf2_cu *cu,
-                   dwarf2_psymtab *ranges_pst, dwarf_tag tag)
+                   addrmap *map, void *datum, dwarf_tag tag)
 {
   struct objfile *objfile = cu->per_objfile->objfile;
-  dwarf2_per_bfd *per_bfd = cu->per_objfile->per_bfd;
   struct gdbarch *gdbarch = objfile->arch ();
   const CORE_ADDR baseaddr = objfile->text_section_offset ();
   int low_set = 0;
@@ -13920,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)
     {
-      if (ranges_pst != NULL)
+      if (map != nullptr)
        {
          CORE_ADDR lowpc;
          CORE_ADDR highpc;
@@ -13931,8 +12975,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
          highpc = (gdbarch_adjust_dwarf2_addr (gdbarch,
                                                range_end + baseaddr)
                    - baseaddr);
-         addrmap_set_empty (per_bfd->partial_symtabs->psymtabs_addrmap,
-                            lowpc, highpc - 1, ranges_pst);
+         addrmap_set_empty (map, lowpc, highpc - 1, datum);
        }
 
       /* FIXME: This is recording everything as a low-high
@@ -13968,6 +13011,20 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
   return 1;
 }
 
+/* Process ranges and fill in a vector of the low PC values only.  */
+
+static void
+dwarf2_ranges_read_low_addrs (unsigned offset, struct dwarf2_cu *cu,
+                             dwarf_tag tag,
+                             std::vector<CORE_ADDR> &result)
+{
+  dwarf2_ranges_process (offset, cu, tag,
+                        [&] (CORE_ADDR start, CORE_ADDR end)
+    {
+      result.push_back (start);
+    });
+}
+
 /* Get low and high pc attributes from a die.  See enum pc_bounds_kind
    definition for the return value.  *LOWPC and *HIGHPC are set iff
    neither PC_BOUNDS_NOT_PRESENT nor PC_BOUNDS_INVALID are returned.  */
@@ -13975,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,
-                     dwarf2_psymtab *pst)
+                     addrmap *map, void *datum)
 {
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
   struct attribute *attr;
@@ -14018,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.  */
-         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;
@@ -14062,7 +13119,8 @@ dwarf2_get_subprogram_pc_bounds (struct die_info *die,
   CORE_ADDR low, high;
   struct die_info *child = die->child;
 
-  if (dwarf2_get_pc_bounds (die, &low, &high, cu, NULL) >= PC_BOUNDS_RANGES)
+  if (dwarf2_get_pc_bounds (die, &low, &high, cu, nullptr, nullptr)
+      >= PC_BOUNDS_RANGES)
     {
       *lowpc = std::min (*lowpc, low);
       *highpc = std::max (*highpc, high);
@@ -14099,7 +13157,8 @@ get_scope_pc_bounds (struct die_info *die,
   CORE_ADDR best_high = (CORE_ADDR) 0;
   CORE_ADDR current_low, current_high;
 
-  if (dwarf2_get_pc_bounds (die, &current_low, &current_high, cu, NULL)
+  if (dwarf2_get_pc_bounds (die, &current_low, &current_high, cu,
+                           nullptr, nullptr)
       >= PC_BOUNDS_RANGES)
     {
       best_low = current_low;
@@ -14227,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_gcc_11 = major == 11;
     }
   else if (producer_is_icc (cu->producer, &major, &minor))
     {
@@ -14312,14 +13372,14 @@ dwarf2_access_attribute (struct die_info *die, struct dwarf2_cu *cu)
     }
 }
 
-/* Look for DW_AT_data_member_location.  Set *OFFSET to the byte
-   offset.  If the attribute was not found return 0, otherwise return
-   1.  If it was found but could not properly be handled, set *OFFSET
-   to 0.  */
+/* Look for DW_AT_data_member_location or DW_AT_data_bit_offset.  Set
+   *OFFSET to the byte offset.  If the attribute was not found return
+   0, otherwise return 1.  If it was found but could not properly be
+   handled, set *OFFSET to 0.  */
 
 static int
-handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu,
-                            LONGEST *offset)
+handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
+                       LONGEST *offset)
 {
   struct attribute *attr;
 
@@ -14343,15 +13403,25 @@ handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu,
 
       return 1;
     }
+  else
+    {
+      attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
+      if (attr != nullptr)
+       {
+         *offset = attr->constant_value (0);
+         return 1;
+       }
+    }
 
   return 0;
 }
 
-/* Look for DW_AT_data_member_location and store the results in FIELD.  */
+/* Look for DW_AT_data_member_location or DW_AT_data_bit_offset and
+   store the results in FIELD.  */
 
 static void
-handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu,
-                            struct field *field)
+handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
+                       struct field *field)
 {
   struct attribute *attr;
 
@@ -14361,7 +13431,20 @@ handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu,
       if (attr->form_is_constant ())
        {
          LONGEST offset = attr->constant_value (0);
-         SET_FIELD_BITPOS (*field, offset * bits_per_byte);
+
+         /* 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 ())
        dwarf2_complex_location_expr_complaint ();
@@ -14370,7 +13453,7 @@ handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu,
          bool handled;
          CORE_ADDR offset = decode_locdesc (attr->as_block (), cu, &handled);
          if (handled)
-           SET_FIELD_BITPOS (*field, offset * bits_per_byte);
+           field->set_loc_bitpos (offset * bits_per_byte);
          else
            {
              dwarf2_per_objfile *per_objfile = cu->per_objfile;
@@ -14387,12 +13470,18 @@ handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu,
              dlbaton->per_objfile = per_objfile;
              dlbaton->per_cu = cu->per_cu;
 
-             SET_FIELD_DWARF_BLOCK (*field, dlbaton);
+             field->set_loc_dwarf_block (dlbaton);
            }
        }
       else
        dwarf2_complex_location_expr_complaint ();
     }
+  else
+    {
+      attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
+      if (attr != nullptr)
+       field->set_loc_bitpos (attr->constant_value (0));
+    }
 }
 
 /* Add an aggregate field to the field list.  */
@@ -14433,14 +13522,27 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
 
   fp = &new_field->field;
 
-  if (die->tag == DW_TAG_member && ! die_is_declaration (die, cu))
-    {
+  if ((die->tag == DW_TAG_member || die->tag == DW_TAG_namelist_item)
+      && !die_is_declaration (die, cu))
+    {
+      if (die->tag == DW_TAG_namelist_item)
+        {
+         /* Typically, DW_TAG_namelist_item are references to namelist items.
+            If so, follow that reference.  */
+         struct attribute *attr1 = dwarf2_attr (die, DW_AT_namelist_item, cu);
+         struct die_info *item_die = nullptr;
+         struct dwarf2_cu *item_cu = cu;
+          if (attr1->form_is_ref ())
+           item_die = follow_die_ref (die, attr1, &item_cu);
+         if (item_die != nullptr)
+           die = item_die;
+        }
       /* Data member other than a C++ static data member.  */
 
       /* Get type of field.  */
       fp->set_type (die_type (die, cu));
 
-      SET_FIELD_BITPOS (*fp, 0);
+      fp->set_loc_bitpos (0);
 
       /* Get bit size of field (zero if none).  */
       attr = dwarf2_attr (die, DW_AT_bit_size, cu);
@@ -14454,7 +13556,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
        }
 
       /* Get bit offset of field.  */
-      handle_data_member_location (die, cu, fp);
+      handle_member_location (die, cu, fp);
       attr = dwarf2_attr (die, DW_AT_bit_offset, cu);
       if (attr != nullptr && attr->form_is_constant ())
        {
@@ -14465,8 +13567,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
                 anonymous object to the MSB of the field.  We don't
                 have to do anything special since we don't need to
                 know the size of the anonymous object.  */
-             SET_FIELD_BITPOS (*fp, (FIELD_BITPOS (*fp)
-                                     + attr->constant_value (0)));
+             fp->set_loc_bitpos (fp->loc_bitpos () + attr->constant_value (0));
            }
          else
            {
@@ -14495,16 +13596,11 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
                     bit field.  */
                  anonymous_size = TYPE_LENGTH (fp->type ());
                }
-             SET_FIELD_BITPOS (*fp,
-                               (FIELD_BITPOS (*fp)
-                                + anonymous_size * bits_per_byte
-                                - bit_offset - FIELD_BITSIZE (*fp)));
+             fp->set_loc_bitpos (fp->loc_bitpos ()
+                                 + anonymous_size * bits_per_byte
+                                 - bit_offset - FIELD_BITSIZE (*fp));
            }
        }
-      attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
-      if (attr != NULL)
-       SET_FIELD_BITPOS (*fp, (FIELD_BITPOS (*fp)
-                               + attr->constant_value (0)));
 
       /* Get name of field.  */
       fieldname = dwarf2_name (die, cu);
@@ -14513,7 +13609,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
 
       /* The name is already allocated along with this objfile, so we don't
         need to duplicate it for the type.  */
-      fp->name = fieldname;
+      fp->set_name (fieldname);
 
       /* Change accessibility for artificial fields (e.g. virtual table
         pointer or virtual base class pointer) to private.  */
@@ -14558,17 +13654,17 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
 
       /* The name is already allocated along with this objfile, so we don't
         need to duplicate it for the type.  */
-      SET_FIELD_PHYSNAME (*fp, physname ? physname : "");
+      fp->set_loc_physname (physname ? physname : "");
       fp->set_type (die_type (die, cu));
-      FIELD_NAME (*fp) = fieldname;
+      fp->set_name (fieldname);
     }
   else if (die->tag == DW_TAG_inheritance)
     {
       /* C++ base class field.  */
-      handle_data_member_location (die, cu, fp);
+      handle_member_location (die, cu, fp);
       FIELD_BITSIZE (*fp) = 0;
       fp->set_type (die_type (die, cu));
-      FIELD_NAME (*fp) = fp->type ()->name ();
+      fp->set_name (fp->type ()->name ());
     }
   else
     gdb_assert_not_reached ("missing case in dwarf2_add_field");
@@ -14811,7 +13907,7 @@ add_variant_property (struct field_info *fip, struct type *type,
     offset_map[fip->fields[i].offset] = i;
 
   struct objfile *objfile = cu->per_objfile->objfile;
-  gdb::array_view<variant_part> parts
+  gdb::array_view<const variant_part> parts
     = create_variant_parts (&objfile->objfile_obstack, offset_map, fip,
                            fip->variant_parts);
 
@@ -15203,10 +14299,10 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
     return;
 
   /* Check for __pfn and __delta members.  */
-  if (TYPE_FIELD_NAME (type, 0) == NULL
-      || strcmp (TYPE_FIELD_NAME (type, 0), "__pfn") != 0
-      || TYPE_FIELD_NAME (type, 1) == NULL
-      || strcmp (TYPE_FIELD_NAME (type, 1), "__delta") != 0)
+  if (type->field (0).name () == NULL
+      || strcmp (type->field (0).name (), "__pfn") != 0
+      || type->field (1).name () == NULL
+      || strcmp (type->field (1).name (), "__delta") != 0)
     return;
 
   /* Find the type of the method.  */
@@ -15297,10 +14393,10 @@ quirk_ada_thick_pointer_struct (struct die_info *die, struct dwarf2_cu *cu,
     return;
 
   /* Check for P_ARRAY and P_BOUNDS members.  */
-  if (TYPE_FIELD_NAME (type, 0) == NULL
-      || strcmp (TYPE_FIELD_NAME (type, 0), "P_ARRAY") != 0
-      || TYPE_FIELD_NAME (type, 1) == NULL
-      || strcmp (TYPE_FIELD_NAME (type, 1), "P_BOUNDS") != 0)
+  if (type->field (0).name () == NULL
+      || strcmp (type->field (0).name (), "P_ARRAY") != 0
+      || type->field (1).name () == NULL
+      || strcmp (type->field (1).name (), "P_BOUNDS") != 0)
     return;
 
   /* Make sure we're looking at a pointer to an array.  */
@@ -15498,6 +14594,10 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
     {
       type->set_code (TYPE_CODE_UNION);
     }
+  else if (die->tag == DW_TAG_namelist)
+    {
+      type->set_code (TYPE_CODE_NAMELIST);
+    }
   else
     {
       type->set_code (TYPE_CODE_STRUCT);
@@ -15700,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
-      || 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
@@ -15743,8 +14844,10 @@ handle_struct_member_die (struct die_info *child_die, struct type *type,
     handle_variant (child_die, type, fi, template_args, cu);
 }
 
-/* Finish creating a structure or union type, including filling in
-   its members and creating a symbol for it.  */
+/* Finish creating a structure or union type, including filling in its
+   members and creating a symbol for it. This function also handles Fortran
+   namelist variables, their items or members and creating a symbol for
+   them.  */
 
 static void
 process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
@@ -15813,7 +14916,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
                       i >= TYPE_N_BASECLASSES (t);
                       --i)
                    {
-                     const char *fieldname = TYPE_FIELD_NAME (t, i);
+                     const char *fieldname = t->field (i).name ();
 
                      if (is_vtable_name (fieldname, cu))
                        {
@@ -15846,7 +14949,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
                   i >= TYPE_N_BASECLASSES (type);
                   --i)
                {
-                 if (strcmp (TYPE_FIELD_NAME (type, i), "__vfp") == 0)
+                 if (strcmp (type->field (i).name (), "__vfp") == 0)
                    {
                      set_type_vptr_fieldno (type, i);
                      set_type_vptr_basetype (type, type);
@@ -16017,8 +15120,8 @@ update_enumeration_type_from_children (struct die_info *die,
 
       fields.emplace_back ();
       struct field &field = fields.back ();
-      FIELD_NAME (field) = dwarf2_physname (name, child_die, cu);
-      SET_FIELD_ENUMVAL (field, value);
+      field.set_name (dwarf2_physname (name, child_die, cu));
+      field.set_loc_enumval (value);
     }
 
   if (!fields.empty ())
@@ -16292,7 +15395,7 @@ recognize_bound_expression (struct die_info *die, enum dwarf_attribute name,
   else
     return false;
 
-  SET_FIELD_BITPOS (*field, 8 * offset);
+  field->set_loc_bitpos (8 * offset);
   if (size != TYPE_LENGTH (field->type ()))
     FIELD_BITSIZE (*field) = 8 * size;
 
@@ -16391,9 +15494,9 @@ quirk_ada_thick_pointer (struct die_info *die, struct dwarf2_cu *cu,
 
       /* Set the name of each field in the bounds.  */
       xsnprintf (name, sizeof (name), "LB%d", i / 2);
-      FIELD_NAME (range_fields[i]) = objfile->intern (name);
+      range_fields[i].set_name (objfile->intern (name));
       xsnprintf (name, sizeof (name), "UB%d", i / 2);
-      FIELD_NAME (range_fields[i + 1]) = objfile->intern (name);
+      range_fields[i + 1].set_name (objfile->intern (name));
     }
 
   struct type *bounds = alloc_type (objfile);
@@ -16407,7 +15510,7 @@ quirk_ada_thick_pointer (struct die_info *die, struct dwarf2_cu *cu,
          bounds->num_fields () * sizeof (struct field));
 
   int last_fieldno = range_fields.size () - 1;
-  int bounds_size = (TYPE_FIELD_BITPOS (bounds, last_fieldno) / 8
+  int bounds_size = (bounds->field (last_fieldno).loc_bitpos () / 8
                     + TYPE_LENGTH (bounds->field (last_fieldno).type ()));
   TYPE_LENGTH (bounds) = align_up (bounds_size, max_align);
 
@@ -16435,12 +15538,12 @@ quirk_ada_thick_pointer (struct die_info *die, struct dwarf2_cu *cu,
   /* The names are chosen to coincide with what the compiler does with
      -fgnat-encodings=all, which the Ada code in gdb already
      understands.  */
-  TYPE_FIELD_NAME (result, 0) = "P_ARRAY";
+  result->field (0).set_name ("P_ARRAY");
   result->field (0).set_type (lookup_pointer_type (type));
 
-  TYPE_FIELD_NAME (result, 1) = "P_BOUNDS";
+  result->field (1).set_name ("P_BOUNDS");
   result->field (1).set_type (lookup_pointer_type (bounds));
-  SET_FIELD_BITPOS (result->field (1), 8 * bounds_offset);
+  result->field (1).set_loc_bitpos (8 * bounds_offset);
 
   result->set_name (type->name ());
   TYPE_LENGTH (result) = (TYPE_LENGTH (result->field (0).type ())
@@ -16514,7 +15617,8 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
   child_die = die->child;
   while (child_die && child_die->tag)
     {
-      if (child_die->tag == DW_TAG_subrange_type)
+      if (child_die->tag == DW_TAG_subrange_type
+         || child_die->tag == DW_TAG_generic_subrange)
        {
          struct type *child_type = read_type_die (child_die, cu);
 
@@ -16748,7 +15852,7 @@ mark_common_block_symbol_computed (struct symbol *sym,
   gdb_assert (ptr - baton->data == baton->size);
 
   SYMBOL_LOCATION_BATON (sym) = baton;
-  SYMBOL_ACLASS_INDEX (sym) = dwarf2_locexpr_index;
+  sym->set_aclass_index (dwarf2_locexpr_index);
 }
 
 /* Create appropriate locally-scoped variables for all the
@@ -16847,7 +15951,7 @@ read_common_block (struct die_info *die, struct dwarf2_cu *cu)
        }
 
       sym = new_symbol (die, objfile_type (objfile)->builtin_void, cu);
-      SYMBOL_VALUE_COMMON_BLOCK (sym) = common_block;
+      sym->set_value_common_block (common_block);
     }
 }
 
@@ -17306,7 +16410,7 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
          /* Pass 0 as the default as we know this attribute is constant
             and the default value will not be returned.  */
          LONGEST sz = len->constant_value (0);
-         prop_type = cu->per_objfile->int_type (sz, true);
+         prop_type = objfile_int_type (objfile, sz, true);
        }
       else
        {
@@ -18133,16 +17237,7 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
        break;
       case DW_ATE_UTF:
        {
-         if (bits == 16)
-           type = builtin_type (arch)->builtin_char16;
-         else if (bits == 32)
-           type = builtin_type (arch)->builtin_char32;
-         else
-           {
-             complaint (_("unsupported DW_ATE_UTF bit size: '%d'"),
-                        bits);
-             type = dwarf2_init_integer_type (cu, objfile, bits, 1, name);
-           }
+         type = init_character_type (objfile, bits, 1, name);
          return set_die_type (die, type, cu);
        }
        break;
@@ -18162,7 +17257,9 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
        break;
     }
 
-  if (name && strcmp (name, "char") == 0)
+  if (type->code () == TYPE_CODE_INT
+      && name != nullptr
+      && strcmp (name, "char") == 0)
     type->set_has_no_signedness (true);
 
   maybe_set_alignment (cu, die, type);
@@ -18238,7 +17335,22 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
       baton->locexpr.per_cu = cu->per_cu;
       baton->locexpr.per_objfile = per_objfile;
 
-      struct dwarf_block *block = attr->as_block ();
+      struct dwarf_block *block;
+      if (attr->form == DW_FORM_data16)
+       {
+         size_t data_size = 16;
+         block = XOBNEW (obstack, struct dwarf_block);
+         block->size = (data_size
+                        + 2 /* Extra bytes for DW_OP and arg.  */);
+         gdb_byte *data = XOBNEWVEC (obstack, gdb_byte, block->size);
+         data[0] = DW_OP_implicit_value;
+         data[1] = data_size;
+         memcpy (&data[2], attr->as_block ()->data, data_size);
+         block->data = data;
+       }
+      else
+       block = attr->as_block ();
+
       baton->locexpr.size = block->size;
       baton->locexpr.data = block->data;
       switch (attr->name)
@@ -18265,6 +17377,9 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
       if (target_attr == NULL)
        target_attr = dwarf2_attr (target_die, DW_AT_data_member_location,
                                   target_cu);
+      if (target_attr == nullptr)
+       target_attr = dwarf2_attr (target_die, DW_AT_data_bit_offset,
+                                  target_cu);
       if (target_attr == NULL)
        {
          const char *name = var_decl_name (target_die, target_cu);
@@ -18308,11 +17423,11 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
              }
            break;
          case DW_AT_data_member_location:
+         case DW_AT_data_bit_offset:
            {
              LONGEST offset;
 
-             if (!handle_data_member_location (target_die, target_cu,
-                                               &offset))
+             if (!handle_member_location (target_die, target_cu, &offset))
                return 0;
 
              baton = XOBNEW (obstack, struct dwarf2_property_baton);
@@ -18327,42 +17442,34 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
     }
   else if (attr->form_is_constant ())
     prop->set_const_val (attr->constant_value (0));
-  else
+  else if (attr->form_is_section_offset ())
     {
-      dwarf2_invalid_attrib_class_complaint (dwarf_form_name (attr->form),
-                                            dwarf2_name (die, cu));
-      return 0;
+      switch (attr->name)
+       {
+       case DW_AT_string_length:
+         baton = XOBNEW (obstack, struct dwarf2_property_baton);
+         baton->property_type = default_type;
+         fill_in_loclist_baton (cu, &baton->loclist, attr);
+         prop->set_loclist (baton);
+         gdb_assert (prop->baton () != NULL);
+         break;
+       default:
+         goto invalid;
+       }
     }
+  else
+    goto invalid;
 
   return 1;
+
+ invalid:
+  dwarf2_invalid_attrib_class_complaint (dwarf_form_name (attr->form),
+                                        dwarf2_name (die, cu));
+  return 0;
 }
 
 /* See read.h.  */
 
-struct type *
-dwarf2_per_objfile::int_type (int size_in_bytes, bool unsigned_p) const
-{
-  struct type *int_type;
-
-  /* Helper macro to examine the various builtin types.  */
-#define TRY_TYPE(F)                                                    \
-  int_type = (unsigned_p                                               \
-             ? objfile_type (objfile)->builtin_unsigned_ ## F          \
-             : objfile_type (objfile)->builtin_ ## F);                 \
-  if (int_type != NULL && TYPE_LENGTH (int_type) == size_in_bytes)     \
-    return int_type
-
-  TRY_TYPE (char);
-  TRY_TYPE (short);
-  TRY_TYPE (int);
-  TRY_TYPE (long);
-  TRY_TYPE (long_long);
-
-#undef TRY_TYPE
-
-  gdb_assert_not_reached ("unable to find suitable integer type");
-}
-
 /* Read the DW_AT_type attribute for a sub-range.  If this attribute is not
    present (which is valid) then compute the default type based on the
    compilation units address size.  */
@@ -18684,11 +17791,11 @@ read_die_and_siblings (const struct die_reader_specs *reader,
 
   if (dwarf_die_debug)
     {
-      fprintf_unfiltered (gdb_stdlog,
-                         "Read die from %s@0x%x of %s:\n",
-                         reader->die_section->get_name (),
-                         (unsigned) (info_ptr - reader->die_section->buffer),
-                         bfd_get_filename (reader->abfd));
+      gdb_printf (gdb_stdlog,
+                 "Read die from %s@0x%x of %s:\n",
+                 reader->die_section->get_name (),
+                 (unsigned) (info_ptr - reader->die_section->buffer),
+                 bfd_get_filename (reader->abfd));
       dump_die (die, dwarf_die_debug);
     }
 
@@ -18790,11 +17897,11 @@ read_full_die (const struct die_reader_specs *reader,
 
   if (dwarf_die_debug)
     {
-      fprintf_unfiltered (gdb_stdlog,
-                         "Read die from %s@0x%x of %s:\n",
-                         reader->die_section->get_name (),
-                         (unsigned) (info_ptr - reader->die_section->buffer),
-                         bfd_get_filename (reader->abfd));
+      gdb_printf (gdb_stdlog,
+                 "Read die from %s@0x%x of %s:\n",
+                 reader->die_section->get_name (),
+                 (unsigned) (info_ptr - reader->die_section->buffer),
+                 bfd_get_filename (reader->abfd));
       dump_die (*diep, dwarf_die_debug);
     }
 
@@ -18802,827 +17909,841 @@ read_full_die (const struct die_reader_specs *reader,
 }
 \f
 
-/* Returns nonzero if TAG represents a type that we might generate a partial
-   symbol for.  */
-
-static int
-is_type_tag_for_partial (int tag, enum language lang)
+void
+cooked_indexer::check_bounds (cutu_reader *reader)
 {
-  switch (tag)
+  if (reader->cu->per_cu->addresses_seen)
+    return;
+
+  dwarf2_cu *cu = reader->cu;
+
+  CORE_ADDR best_lowpc = 0, best_highpc = 0;
+  /* Possibly set the default values of LOWPC and HIGHPC from
+     `DW_AT_ranges'.  */
+  dwarf2_find_base_address (reader->comp_unit_die, cu);
+  enum pc_bounds_kind cu_bounds_kind
+    = dwarf2_get_pc_bounds (reader->comp_unit_die, &best_lowpc, &best_highpc,
+                           cu, m_index_storage->get_addrmap (), cu->per_cu);
+  if (cu_bounds_kind == PC_BOUNDS_HIGH_LOW && best_lowpc < best_highpc)
     {
-#if 0
-    /* Some types that would be reasonable to generate partial symbols for,
-       that we don't at present.  Note that normally this does not
-       matter, mainly because C compilers don't give names to these
-       types, but instead emit DW_TAG_typedef.  */
-    case DW_TAG_file_type:
-    case DW_TAG_ptr_to_member_type:
-    case DW_TAG_set_type:
-    case DW_TAG_string_type:
-    case DW_TAG_subroutine_type:
-#endif
+      struct objfile *objfile = cu->per_objfile->objfile;
+      CORE_ADDR baseaddr = objfile->text_section_offset ();
+      struct gdbarch *gdbarch = objfile->arch ();
+      CORE_ADDR low
+       = (gdbarch_adjust_dwarf2_addr (gdbarch, best_lowpc + baseaddr)
+          - baseaddr);
+      CORE_ADDR high
+       = (gdbarch_adjust_dwarf2_addr (gdbarch, best_highpc + baseaddr)
+          - baseaddr - 1);
+      /* Store the contiguous range if it is not empty; it can be
+        empty for CUs with no code.  */
+      addrmap_set_empty (m_index_storage->get_addrmap (), low, high,
+                        cu->per_cu);
 
-      /* GNAT may emit an array with a name, but no typedef, so we
-        need to make a symbol in this case.  */
-    case DW_TAG_array_type:
-      return lang == language_ada;
+      cu->per_cu->addresses_seen = true;
+    }
+}
 
-    case DW_TAG_base_type:
+/* Helper function that returns true if TAG can have a linkage
+   name.  */
+
+static bool
+tag_can_have_linkage_name (enum dwarf_tag tag)
+{
+  switch (tag)
+    {
+      /* We include types here because an anonymous C++ type might
+        have a name for linkage purposes.  */
     case DW_TAG_class_type:
-    case DW_TAG_interface_type:
-    case DW_TAG_enumeration_type:
     case DW_TAG_structure_type:
-    case DW_TAG_subrange_type:
-    case DW_TAG_typedef:
     case DW_TAG_union_type:
-      return 1;
+    case DW_TAG_variable:
+    case DW_TAG_subprogram:
+      return true;
+
     default:
-      return 0;
+      return false;
     }
 }
 
-/* Load all DIEs that are interesting for partial symbols into memory.  */
-
-static struct partial_die_info *
-load_partial_dies (const struct die_reader_specs *reader,
-                  const gdb_byte *info_ptr, int building_psymtab)
+cutu_reader *
+cooked_indexer::ensure_cu_exists (cutu_reader *reader,
+                                 dwarf2_per_objfile *per_objfile,
+                                 sect_offset sect_off, bool is_dwz,
+                                 bool for_scanning)
 {
-  struct dwarf2_cu *cu = reader->cu;
-  struct objfile *objfile = cu->per_objfile->objfile;
-  struct partial_die_info *parent_die, *last_die, *first_die = NULL;
-  unsigned int bytes_read;
-  unsigned int load_all = 0;
-  int nesting_level = 1;
-
-  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)
-{
-}
+  if (result->dummy_p || !result->comp_unit_die->has_children)
+    return nullptr;
 
-/* See class definition.  */
+  if (for_scanning)
+    check_bounds (result);
 
-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;
-    }
-
-  return raw_name;
+  return result;
 }
 
-/* Read a minimal amount of information into the minimal die structure.
-   INFO_PTR should point just after the initial uleb128 of a DIE.  */
-
 const gdb_byte *
-partial_die_info::read (const struct die_reader_specs *reader,
-                       const struct abbrev_info &abbrev, const gdb_byte *info_ptr)
-{
-  struct dwarf2_cu *cu = reader->cu;
-  dwarf2_per_objfile *per_objfile = cu->per_objfile;
-  unsigned int i;
-  int has_low_pc_attr = 0;
-  int has_high_pc_attr = 0;
-  int high_pc_relative = 0;
-
-  for (i = 0; i < abbrev.num_attrs; ++i)
+cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
+                                cutu_reader *reader,
+                                const gdb_byte *watermark_ptr,
+                                const gdb_byte *info_ptr,
+                                const abbrev_info *abbrev,
+                                const char **name,
+                                const char **linkage_name,
+                                cooked_index_flag *flags,
+                                sect_offset *sibling_offset,
+                                const cooked_index_entry **parent_entry,
+                                CORE_ADDR *maybe_defer,
+                                bool for_specification)
+{
+  bool origin_is_dwz = false;
+  bool is_declaration = false;
+  sect_offset origin_offset {};
+
+  gdb::optional<CORE_ADDR> low_pc;
+  gdb::optional<CORE_ADDR> high_pc;
+  bool high_pc_relative = false;
+
+  for (int i = 0; i < abbrev->num_attrs; ++i)
     {
       attribute attr;
-      info_ptr = read_attribute (reader, &attr, &abbrev.attrs[i], info_ptr);
-      /* String and address offsets that need to do the reprocessing have
-        already been read at this point, so there is no need to wait until
-        the loop terminates to do the reprocessing.  */
+      info_ptr = read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
       if (attr.requires_reprocessing_p ())
-       read_attribute_reprocess (reader, &attr, tag);
+       read_attribute_reprocess (reader, &attr, abbrev->tag);
+
       /* Store the data if it is of an attribute we want to keep in a
         partial symbol table.  */
       switch (attr.name)
        {
        case DW_AT_name:
-         switch (tag)
+         switch (abbrev->tag)
            {
            case DW_TAG_compile_unit:
            case DW_TAG_partial_unit:
            case DW_TAG_type_unit:
              /* Compilation units have a DW_AT_name that is a filename, not
                 a source language identifier.  */
-           case DW_TAG_enumeration_type:
-           case DW_TAG_enumerator:
-             /* These tags always have simple identifiers already; no need
-                to canonicalize them.  */
-             canonical_name = 1;
-             raw_name = attr.as_string ();
              break;
+
            default:
-             canonical_name = 0;
-             raw_name = attr.as_string ();
+             if (*name == nullptr)
+               *name = attr.as_string ();
              break;
            }
          break;
+
        case DW_AT_linkage_name:
        case DW_AT_MIPS_linkage_name:
          /* Note that both forms of linkage name might appear.  We
             assume they will be the same, and we only store the last
             one we see.  */
-         linkage_name = attr.as_string ();
-         break;
-       case DW_AT_low_pc:
-         has_low_pc_attr = 1;
-         lowpc = attr.as_address ();
-         break;
-       case DW_AT_high_pc:
-         has_high_pc_attr = 1;
-         highpc = attr.as_address ();
-         if (cu->header.version >= 4 && attr.form_is_constant ())
-               high_pc_relative = 1;
-         break;
-       case DW_AT_location:
-         /* Support the .debug_loc offsets.  */
-         if (attr.form_is_block ())
-           {
-             d.locdesc = attr.as_block ();
-           }
-         else if (attr.form_is_section_offset ())
-           {
-             dwarf2_complex_location_expr_complaint ();
-           }
-         else
-           {
-             dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
-                                                    "partial symbol information");
-           }
+         if (*linkage_name == nullptr)
+           *linkage_name = attr.as_string ();
          break;
-       case DW_AT_external:
-         is_external = attr.as_boolean ();
+
+       case DW_AT_main_subprogram:
+         if (attr.as_boolean ())
+           *flags |= IS_MAIN;
          break;
+
        case DW_AT_declaration:
          is_declaration = attr.as_boolean ();
          break;
-       case DW_AT_type:
-         has_type = 1;
+
+       case DW_AT_sibling:
+         if (sibling_offset != nullptr)
+           *sibling_offset = attr.get_ref_die_offset ();
          break;
-       case DW_AT_abstract_origin:
+
        case DW_AT_specification:
+       case DW_AT_abstract_origin:
        case DW_AT_extension:
-         has_specification = 1;
-         spec_offset = attr.get_ref_die_offset ();
-         spec_is_dwz = (attr.form == DW_FORM_GNU_ref_alt
-                                  || cu->per_cu->is_dwz);
+         origin_offset = attr.get_ref_die_offset ();
+         origin_is_dwz = attr.form == DW_FORM_GNU_ref_alt;
          break;
-       case DW_AT_sibling:
-         /* Ignore absolute siblings, they might point outside of
-            the current compile unit.  */
-         if (attr.form == DW_FORM_ref_addr)
-           complaint (_("ignoring absolute DW_AT_sibling"));
-         else
-           {
-             const gdb_byte *buffer = reader->buffer;
-             sect_offset off = attr.get_ref_die_offset ();
-             const gdb_byte *sibling_ptr = buffer + to_underlying (off);
 
-             if (sibling_ptr < info_ptr)
-               complaint (_("DW_AT_sibling points backwards"));
-             else if (sibling_ptr > reader->buffer_end)
-               reader->die_section->overflow_complaint ();
-             else
-               sibling = sibling_ptr;
-           }
-         break;
-       case DW_AT_byte_size:
-         has_byte_size = 1;
+       case DW_AT_external:
+         if (attr.as_boolean ())
+           *flags &= ~IS_STATIC;
          break;
-       case DW_AT_const_value:
-         has_const_value = 1;
+
+       case DW_AT_enum_class:
+         if (attr.as_boolean ())
+           *flags |= IS_ENUM_CLASS;
          break;
-       case DW_AT_calling_convention:
-         /* DWARF doesn't provide a way to identify a program's source-level
-            entry point.  DW_AT_calling_convention attributes are only meant
-            to describe functions' calling conventions.
-
-            However, because it's a necessary piece of information in
-            Fortran, and before DWARF 4 DW_CC_program was the only
-            piece of debugging information whose definition refers to
-            a 'main program' at all, several compilers marked Fortran
-            main programs with DW_CC_program --- even when those
-            functions use the standard calling conventions.
-
-            Although DWARF now specifies a way to provide this
-            information, we support this practice for backward
-            compatibility.  */
-         if (attr.constant_value (0) == DW_CC_program
-             && cu->per_cu->lang == language_fortran)
-           main_subprogram = 1;
+
+       case DW_AT_low_pc:
+         low_pc = attr.as_address ();
          break;
-       case DW_AT_inline:
-         {
-           LONGEST value = attr.constant_value (-1);
-           if (value == DW_INL_inlined
-               || value == DW_INL_declared_inlined)
-             may_be_inlined = 1;
-         }
+
+       case DW_AT_high_pc:
+         high_pc = attr.as_address ();
+         if (reader->cu->header.version >= 4 && attr.form_is_constant ())
+           high_pc_relative = true;
          break;
 
-       case DW_AT_import:
-         if (tag == DW_TAG_imported_unit)
+       case DW_AT_location:
+         if (!scanning_per_cu->addresses_seen && attr.form_is_block ())
            {
-             d.sect_off = attr.get_ref_die_offset ();
-             is_dwz = (attr.form == DW_FORM_GNU_ref_alt
-                                 || cu->per_cu->is_dwz);
+             struct dwarf_block *locdesc = attr.as_block ();
+             CORE_ADDR addr = decode_locdesc (locdesc, reader->cu);
+             if (addr != 0
+                 || reader->cu->per_objfile->per_bfd->has_section_at_zero)
+               {
+                 low_pc = addr;
+                 /* For variables, we don't want to try decoding the
+                    type just to find the size -- for gdb's purposes
+                    we only need the address of a variable.  */
+                 high_pc = addr + 1;
+                 high_pc_relative = false;
+               }
            }
          break;
 
-       case DW_AT_main_subprogram:
-         main_subprogram = attr.as_boolean ();
-         break;
-
        case DW_AT_ranges:
-         {
-           /* 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.  */
-           if (tag != DW_TAG_compile_unit)
-             ranges_offset += cu->gnu_ranges_base;
-
-           if (dwarf2_ranges_read (ranges_offset, &lowpc, &highpc, cu,
-                                   nullptr, tag))
-             has_pc_info = 1;
-         }
+         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;
+       }
+    }
 
-       default:
-         break;
+  /* We don't want to examine declarations, but if we found a
+     declaration when handling DW_AT_specification or the like, then
+     that is ok.  Similarly, we allow an external variable without a
+     location; those are resolved via minimal symbols.  */
+  if (is_declaration && !for_specification
+      && (abbrev->tag != DW_TAG_variable
+         || (*flags & IS_STATIC) != 0))
+    {
+      *linkage_name = nullptr;
+      *name = nullptr;
+    }
+  else if ((*name == nullptr
+           || (*linkage_name == nullptr
+               && tag_can_have_linkage_name (abbrev->tag))
+           || (*parent_entry == nullptr && m_language != language_c))
+          && origin_offset != sect_offset (0))
+    {
+      cutu_reader *new_reader
+       = ensure_cu_exists (reader, reader->cu->per_objfile, origin_offset,
+                           origin_is_dwz, false);
+      if (new_reader != nullptr)
+       {
+         const gdb_byte *new_info_ptr = (new_reader->buffer
+                                         + to_underlying (origin_offset));
+
+         if (new_reader->cu == reader->cu
+             && new_info_ptr > watermark_ptr
+             && maybe_defer != nullptr
+             && *parent_entry == nullptr)
+           *maybe_defer = form_addr (origin_offset, origin_is_dwz);
+         else if (*parent_entry == nullptr)
+           {
+             CORE_ADDR lookup = form_addr (origin_offset, origin_is_dwz);
+             *parent_entry
+               = (cooked_index_entry *) addrmap_find (m_die_range_map,
+                                                      lookup);
+           }
+
+         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);
        }
     }
 
-  /* 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;
+  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);
+       }
+    }
+
+  /* Did not find DW_AT_import.  */
+  if (sect_off == sect_offset (0))
+    return info_ptr;
+
+  dwarf2_per_objfile *per_objfile = reader->cu->per_objfile;
+  cutu_reader *new_reader = ensure_cu_exists (reader, per_objfile, sect_off,
+                                             is_dwz, true);
+  if (new_reader != nullptr)
+    {
+      index_dies (new_reader, new_reader->info_ptr, nullptr, false);
+
+      reader->cu->add_dependence (new_reader->cu->per_cu);
+    }
+
+  return info_ptr;
+}
+
+const gdb_byte *
+cooked_indexer::recurse (cutu_reader *reader,
+                        const gdb_byte *info_ptr,
+                        const cooked_index_entry *parent_entry,
+                        bool fully)
+{
+  info_ptr = index_dies (reader, info_ptr, parent_entry, fully);
+
+  if (parent_entry != nullptr)
+    {
+      CORE_ADDR start = form_addr (parent_entry->die_offset,
+                                  reader->cu->per_cu->is_dwz);
+      CORE_ADDR end = form_addr (sect_offset (info_ptr - 1 - reader->buffer),
+                                reader->cu->per_cu->is_dwz);
+      addrmap_set_empty (m_die_range_map, start, end, (void *) parent_entry);
+    }
+
+  return info_ptr;
+}
+
+const gdb_byte *
+cooked_indexer::index_dies (cutu_reader *reader,
+                           const gdb_byte *info_ptr,
+                           const cooked_index_entry *parent_entry,
+                           bool fully)
+{
+  const gdb_byte *end_ptr = info_ptr + reader->cu->header.get_length ();
+
+  while (info_ptr < end_ptr)
+    {
+      sect_offset this_die = (sect_offset) (info_ptr - reader->buffer);
+      unsigned int bytes_read;
+      const abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr,
+                                                  &bytes_read);
+      info_ptr += bytes_read;
+      if (abbrev == nullptr)
+       break;
+
+      if (abbrev->tag == DW_TAG_imported_unit)
+       {
+         info_ptr = index_imported_unit (reader, info_ptr, abbrev);
+         continue;
+       }
+
+      if (!abbrev->interesting)
+       {
+         info_ptr = skip_one_die (reader, info_ptr, abbrev, !fully);
+         if (fully && abbrev->has_children)
+           info_ptr = index_dies (reader, info_ptr, parent_entry, fully);
+         continue;
+       }
+
+      const char *name = nullptr;
+      const char *linkage_name = nullptr;
+      CORE_ADDR defer = 0;
+      cooked_index_flag flags = IS_STATIC;
+      sect_offset sibling {};
+      const cooked_index_entry *this_parent_entry = parent_entry;
+      info_ptr = scan_attributes (reader->cu->per_cu, reader, info_ptr,
+                                 info_ptr, abbrev, &name, &linkage_name,
+                                 &flags, &sibling, &this_parent_entry,
+                                 &defer, false);
+
+      if (abbrev->tag == DW_TAG_namespace
+         && m_language == language_cplus
+         && strcmp (name, "::") == 0)
+       {
+         /* GCC 4.0 and 4.1 had a bug (PR c++/28460) where they
+            generated bogus DW_TAG_namespace DIEs with a name of "::"
+            for the global namespace.  Work around this problem
+            here.  */
+         name = nullptr;
+       }
+
+      const cooked_index_entry *this_entry = nullptr;
+      if (name != nullptr)
+       {
+         if (defer != 0)
+           m_deferred_entries.push_back ({
+               this_die, name, defer, abbrev->tag, flags
+             });
+         else
+           this_entry = m_index_storage->add (this_die, abbrev->tag, flags,
+                                              name, this_parent_entry,
+                                              m_per_cu);
+       }
+
+      if (linkage_name != nullptr)
+       {
+         /* We only want this to be "main" if it has a linkage name
+            but not an ordinary name.  */
+         if (name != nullptr)
+           flags = flags & ~IS_MAIN;
+         m_index_storage->add (this_die, abbrev->tag, flags | IS_LINKAGE,
+                               linkage_name, nullptr, m_per_cu);
+       }
+
+      if (abbrev->has_children)
+       {
+         switch (abbrev->tag)
+           {
+           case DW_TAG_class_type:
+           case DW_TAG_interface_type:
+           case DW_TAG_structure_type:
+           case DW_TAG_union_type:
+             if (m_language != language_c && this_entry != nullptr)
+               {
+                 info_ptr = recurse (reader, info_ptr, this_entry, fully);
+                 continue;
+               }
+             break;
+
+           case DW_TAG_enumeration_type:
+             /* We need to recurse even for an anonymous enumeration.
+                Which scope we record as the parent scope depends on
+                whether we're reading an "enum class".  If so, we use
+                the enum itself as the parent, yielding names like
+                "enum_class::enumerator"; otherwise we inject the
+                names into our own parent scope.  */
+             info_ptr = recurse (reader, info_ptr,
+                                 ((flags & IS_ENUM_CLASS) == 0)
+                                 ? parent_entry
+                                 : this_entry,
+                                 fully);
+             continue;
 
-  if (high_pc_relative)
-    highpc += lowpc;
+           case DW_TAG_module:
+             if (this_entry == nullptr)
+               break;
+             /* FALLTHROUGH */
+           case DW_TAG_namespace:
+             /* We don't check THIS_ENTRY for a namespace, to handle
+                the ancient G++ workaround pointed out above.  */
+             info_ptr = recurse (reader, info_ptr, this_entry, fully);
+             continue;
 
-  if (has_low_pc_attr && has_high_pc_attr)
-    {
-      /* When using the GNU linker, .gnu.linkonce. sections are used to
-        eliminate duplicate copies of functions and vtables and such.
-        The linker will arbitrarily choose one and discard the others.
-        The AT_*_pc values for such functions refer to local labels in
-        these sections.  If the section from that file was discarded, the
-        labels are not in the output, so the relocs get a value of 0.
-        If this is a discarded function, mark the pc bounds as invalid,
-        so that GDB will ignore it.  */
-      if (lowpc == 0 && !per_objfile->per_bfd->has_section_at_zero)
-       {
-         struct objfile *objfile = per_objfile->objfile;
-         struct gdbarch *gdbarch = objfile->arch ();
+           case DW_TAG_subprogram:
+             if ((m_language == language_fortran
+                  || m_language == language_ada)
+                 && this_entry != nullptr)
+               {
+                 info_ptr = recurse (reader, info_ptr, this_entry, true);
+                 continue;
+               }
+             break;
+           }
 
-         complaint (_("DW_AT_low_pc %s is zero "
-                      "for DIE at %s [in module %s]"),
-                    paddress (gdbarch, lowpc),
-                    sect_offset_str (sect_off),
-                    objfile_name (objfile));
-       }
-      /* dwarf2_get_pc_bounds has also the strict low < high requirement.  */
-      else if (lowpc >= highpc)
-       {
-         struct objfile *objfile = per_objfile->objfile;
-         struct gdbarch *gdbarch = objfile->arch ();
+         if (sibling != sect_offset (0))
+           {
+             const gdb_byte *sibling_ptr
+               = reader->buffer + to_underlying (sibling);
 
-         complaint (_("DW_AT_low_pc %s is not < DW_AT_high_pc %s "
-                      "for DIE at %s [in module %s]"),
-                    paddress (gdbarch, lowpc),
-                    paddress (gdbarch, highpc),
-                    sect_offset_str (sect_off),
-                    objfile_name (objfile));
+             if (sibling_ptr < info_ptr)
+               complaint (_("DW_AT_sibling points backwards"));
+             else if (sibling_ptr > reader->buffer_end)
+               reader->die_section->overflow_complaint ();
+             else
+               info_ptr = sibling_ptr;
+           }
+         else
+           info_ptr = skip_children (reader, info_ptr);
        }
-      else
-       has_pc_info = 1;
     }
 
   return info_ptr;
 }
 
-/* Find a cached partial DIE at OFFSET in CU.  */
-
-struct partial_die_info *
-dwarf2_cu::find_partial_die (sect_offset sect_off)
+void
+cooked_indexer::make_index (cutu_reader *reader)
 {
-  struct partial_die_info *lookup_die = NULL;
-  struct partial_die_info part_die (sect_off);
-
-  lookup_die = ((struct partial_die_info *)
-               htab_find_with_hash (partial_dies, &part_die,
-                                    to_underlying (sect_off)));
+  check_bounds (reader);
+  find_file_and_directory (reader->comp_unit_die, reader->cu);
+  if (!reader->comp_unit_die->has_children)
+    return;
+  index_dies (reader, reader->info_ptr, nullptr, false);
 
-  return lookup_die;
+  for (const auto &entry : m_deferred_entries)
+    {
+      CORE_ADDR key = form_addr (entry.die_offset, m_per_cu->is_dwz);
+      cooked_index_entry *parent
+       = (cooked_index_entry *) addrmap_find (m_die_range_map, key);
+      m_index_storage->add (entry.die_offset, entry.tag, entry.flags,
+                           entry.name, parent, m_per_cu);
+    }
 }
 
-/* Find a partial DIE at OFFSET, which may or may not be in CU,
-   except in the case of .debug_types DIEs which do not reference
-   outside their CU (they do however referencing other types via
-   DW_FORM_ref_sig8).  */
+/* An implementation of quick_symbol_functions for the cooked DWARF
+   index.  */
 
-static const struct cu_partial_die_info
-find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu)
+struct cooked_index_functions : public dwarf2_base_index_functions
 {
-  dwarf2_per_objfile *per_objfile = cu->per_objfile;
-  struct objfile *objfile = per_objfile->objfile;
-  struct partial_die_info *pd = NULL;
+  struct compunit_symtab *find_pc_sect_compunit_symtab
+    (struct objfile *objfile, struct bound_minimal_symbol msymbol,
+     CORE_ADDR pc, struct obj_section *section, int warn_if_readin) override;
 
-  if (offset_in_dwz == cu->per_cu->is_dwz
-      && cu->header.offset_in_cu_p (sect_off))
-    {
-      pd = cu->find_partial_die (sect_off);
-      if (pd != NULL)
-       return { cu, pd };
-      /* We missed recording what we needed.
-        Load all dies and try again.  */
-    }
-  else
-    {
-      /* TUs don't reference other CUs/TUs (except via type signatures).  */
-      if (cu->per_cu->is_debug_types)
-       {
-         error (_("Dwarf Error: Type Unit at offset %s contains"
-                  " external reference to offset %s [in module %s].\n"),
-                sect_offset_str (cu->header.sect_off), sect_offset_str (sect_off),
-                bfd_get_filename (objfile->obfd));
-       }
-      dwarf2_per_cu_data *per_cu
-       = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
-                                           per_objfile);
+  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;
+  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
-           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.
 
@@ -19846,7 +18967,7 @@ read_attribute_reprocess (const struct die_reader_specs *reader,
          break;
        }
       default:
-       gdb_assert_not_reached (_("Unexpected DWARF form."));
+       gdb_assert_not_reached ("Unexpected DWARF form.");
     }
 }
 
@@ -20171,6 +19292,18 @@ read_indirect_string (dwarf2_per_objfile *per_objfile, bfd *abfd,
 
 /* See read.h.  */
 
+const char *
+dwarf2_per_objfile::read_line_string (const gdb_byte *buf,
+                                     unsigned int offset_size)
+{
+  bfd *abfd = objfile->obfd;
+  ULONGEST str_offset = read_offset (abfd, buf, offset_size);
+
+  return per_bfd->line_str.read_string (objfile, str_offset, "DW_FORM_line_strp");
+}
+
+/* See read.h.  */
+
 const char *
 dwarf2_per_objfile::read_line_string (const gdb_byte *buf,
                                      const struct comp_unit_head *cu_header,
@@ -20602,30 +19735,28 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu)
 }
 
 /* Subroutine of dwarf_decode_lines to simplify it.
-   Return the file name of the psymtab for the given file_entry.
-   COMP_DIR is the compilation directory (DW_AT_comp_dir) or NULL if unknown.
+   Return the file name for the given file_entry.
+   CU_INFO describes the CU's DW_AT_name and DW_AT_comp_dir.
    If space for the result is malloc'd, *NAME_HOLDER will be set.
-   Returns NULL if FILE_INDEX should be ignored, i.e., it is pst->filename.  */
+   Returns NULL if FILE_INDEX should be ignored, i.e., it is
+   equivalent to CU_INFO.  */
 
 static const char *
-psymtab_include_file_name (const struct line_header *lh, const file_entry &fe,
-                          const dwarf2_psymtab *pst,
-                          const char *comp_dir,
+compute_include_file_name (const struct line_header *lh, const file_entry &fe,
+                          const file_and_directory &cu_info,
                           gdb::unique_xmalloc_ptr<char> *name_holder)
 {
   const char *include_name = fe.name;
   const char *include_name_to_compare = include_name;
-  const char *pst_filename;
-  int file_is_pst;
 
   const char *dir_name = fe.include_dir (lh);
 
   gdb::unique_xmalloc_ptr<char> hold_compare;
   if (!IS_ABSOLUTE_PATH (include_name)
-      && (dir_name != NULL || comp_dir != NULL))
+      && (dir_name != nullptr || cu_info.get_comp_dir () != nullptr))
     {
-      /* Avoid creating a duplicate psymtab for PST.
-        We do this by comparing INCLUDE_NAME and PST_FILENAME.
+      /* Avoid creating a duplicate name for CU_INFO.
+        We do this by comparing INCLUDE_NAME and CU_INFO.
         Before we do the comparison, however, we need to account
         for DIR_NAME and COMP_DIR.
         First prepend dir_name (if non-NULL).  If we still don't
@@ -20652,27 +19783,26 @@ psymtab_include_file_name (const struct line_header *lh, const file_entry &fe,
          include_name = name_holder->get ();
          include_name_to_compare = include_name;
        }
-      if (!IS_ABSOLUTE_PATH (include_name) && comp_dir != NULL)
+      if (!IS_ABSOLUTE_PATH (include_name)
+         && cu_info.get_comp_dir () != nullptr)
        {
-         hold_compare.reset (concat (comp_dir, SLASH_STRING,
+         hold_compare.reset (concat (cu_info.get_comp_dir (), SLASH_STRING,
                                      include_name, (char *) NULL));
          include_name_to_compare = hold_compare.get ();
        }
     }
 
-  pst_filename = pst->filename;
   gdb::unique_xmalloc_ptr<char> copied_name;
-  if (!IS_ABSOLUTE_PATH (pst_filename) && pst->dirname != NULL)
+  const char *cu_filename = cu_info.get_name ();
+  if (!IS_ABSOLUTE_PATH (cu_filename) && cu_info.get_comp_dir () != nullptr)
     {
-      copied_name.reset (concat (pst->dirname, SLASH_STRING,
-                                pst_filename, (char *) NULL));
-      pst_filename = copied_name.get ();
+      copied_name.reset (concat (cu_info.get_comp_dir (), SLASH_STRING,
+                                cu_filename, (char *) NULL));
+      cu_filename = copied_name.get ();
     }
 
-  file_is_pst = FILENAME_CMP (include_name_to_compare, pst_filename) == 0;
-
-  if (file_is_pst)
-    return NULL;
+  if (FILENAME_CMP (include_name_to_compare, cu_filename) == 0)
+    return nullptr;
   return include_name;
 }
 
@@ -20683,8 +19813,7 @@ class lnp_state_machine
 public:
   /* Initialize a machine state for the start of a line number
      program.  */
-  lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch, line_header *lh,
-                    bool record_lines_p);
+  lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch, line_header *lh);
 
   file_entry *current_file ()
   {
@@ -20735,7 +19864,7 @@ public:
   /* Handle DW_LNS_negate_stmt.  */
   void handle_negate_stmt ()
   {
-    m_is_stmt = !m_is_stmt;
+    m_flags ^= LEF_IS_STMT;
   }
 
   /* Handle DW_LNS_const_add_pc.  */
@@ -20753,6 +19882,7 @@ public:
   {
     record_line (false);
     m_discriminator = 0;
+    m_flags &= ~LEF_PROLOGUE_END;
   }
 
   /* Handle DW_LNE_end_sequence.  */
@@ -20761,6 +19891,12 @@ public:
     m_currently_recording_lines = true;
   }
 
+  /* Handle DW_LNS_set_prologue_end.  */
+  void handle_set_prologue_end ()
+  {
+    m_flags |= LEF_PROLOGUE_END;
+  }
+
 private:
   /* Advance the line by LINE_DELTA.  */
   void advance_line (int line_delta)
@@ -20775,11 +19911,6 @@ private:
 
   gdbarch *m_gdbarch;
 
-  /* True if we're recording lines.
-     Otherwise we're building partial symtabs and are just interested in
-     finding include files mentioned by the line number program.  */
-  bool m_record_lines_p;
-
   /* The line number header.  */
   line_header *m_line_header;
 
@@ -20794,7 +19925,7 @@ private:
   /* These are initialized in the constructor.  */
 
   CORE_ADDR m_address;
-  bool m_is_stmt;
+  linetable_entry_flags m_flags;
   unsigned int m_discriminator;
 
   /* Additional bits of state we need to track.  */
@@ -20809,9 +19940,9 @@ private:
   CORE_ADDR m_last_address;
 
   /* Set to true when a previous line at the same address (using
-     m_last_address) had m_is_stmt true.  This is reset to false when a
-     line entry at a new address (m_address different to m_last_address) is
-     processed.  */
+     m_last_address) had LEF_IS_STMT set in m_flags.  This is reset to false
+     when a line entry at a new address (m_address different to
+     m_last_address) is processed.  */
   bool m_stmt_at_address = false;
 
   /* When true, record the lines we decode.  */
@@ -20852,6 +19983,7 @@ lnp_state_machine::handle_special_opcode (unsigned char op_code)
   advance_line (line_delta);
   record_line (false);
   m_discriminator = 0;
+  m_flags &= ~LEF_PROLOGUE_END;
 }
 
 void
@@ -20862,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 ();
-  else if (m_record_lines_p)
+  else
     {
       const char *dir = fe->include_dir (m_line_header);
 
@@ -20941,21 +20073,22 @@ dwarf_record_line_p (struct dwarf2_cu *cu,
 
 static void
 dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
-                    unsigned int line, CORE_ADDR address, bool is_stmt,
+                    unsigned int line, CORE_ADDR address,
+                    linetable_entry_flags flags,
                     struct dwarf2_cu *cu)
 {
   CORE_ADDR addr = gdbarch_addr_bits_remove (gdbarch, address);
 
   if (dwarf_line_debug)
     {
-      fprintf_unfiltered (gdb_stdlog,
-                         "Recording line %u, file %s, address %s\n",
-                         line, lbasename (subfile->name),
-                         paddress (gdbarch, address));
+      gdb_printf (gdb_stdlog,
+                 "Recording line %u, file %s, address %s\n",
+                 line, lbasename (subfile->name),
+                 paddress (gdbarch, address));
     }
 
   if (cu != nullptr)
-    cu->get_builder ()->record_line (subfile, line, addr, is_stmt);
+    cu->get_builder ()->record_line (subfile, line, addr, flags);
 }
 
 /* Subroutine of dwarf_decode_lines_1 to simplify it.
@@ -20972,13 +20105,13 @@ dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile,
 
   if (dwarf_line_debug)
     {
-      fprintf_unfiltered (gdb_stdlog,
-                         "Finishing current line, file %s, address %s\n",
-                         lbasename (subfile->name),
-                         paddress (gdbarch, address));
+      gdb_printf (gdb_stdlog,
+                 "Finishing current line, file %s, address %s\n",
+                 lbasename (subfile->name),
+                 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
@@ -20986,13 +20119,15 @@ lnp_state_machine::record_line (bool end_sequence)
 {
   if (dwarf_line_debug)
     {
-      fprintf_unfiltered (gdb_stdlog,
-                         "Processing actual line %u: file %u,"
-                         " address %s, is_stmt %u, discrim %u%s\n",
-                         m_line, m_file,
-                         paddress (m_gdbarch, m_address),
-                         m_is_stmt, m_discriminator,
-                         (end_sequence ? "\t(end sequence)" : ""));
+      gdb_printf (gdb_stdlog,
+                 "Processing actual line %u: file %u,"
+                 " address %s, is_stmt %u, prologue_end %u, discrim %u%s\n",
+                 m_line, m_file,
+                 paddress (m_gdbarch, m_address),
+                 (m_flags & LEF_IS_STMT) != 0,
+                 (m_flags & LEF_PROLOGUE_END) != 0,
+                 m_discriminator,
+                 (end_sequence ? "\t(end sequence)" : ""));
     }
 
   file_entry *fe = current_file ();
@@ -21004,73 +20139,71 @@ lnp_state_machine::record_line (bool end_sequence)
      previous version of the code.  */
   else if (m_op_index == 0 || end_sequence)
     {
-      fe->included_p = true;
-      if (m_record_lines_p)
-       {
-         /* When we switch files we insert an end maker in the first file,
-            switch to the second file and add a new line entry.  The
-            problem is that the end marker inserted in the first file will
-            discard any previous line entries at the same address.  If the
-            line entries in the first file are marked as is-stmt, while
-            the new line in the second file is non-stmt, then this means
-            the end marker will discard is-stmt lines so we can have a
-            non-stmt line.  This means that there are less addresses at
-            which the user can insert a breakpoint.
-
-            To improve this we track the last address in m_last_address,
-            and whether we have seen an is-stmt at this address.  Then
-            when switching files, if we have seen a stmt at the current
-            address, and we are switching to create a non-stmt line, then
-            discard the new line.  */
-         bool file_changed
-           = m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
-         bool ignore_this_line
-          = ((file_changed && !end_sequence && m_last_address == m_address
-              && !m_is_stmt && m_stmt_at_address)
-             || (!end_sequence && m_line == 0));
-
-         if ((file_changed && !ignore_this_line) || end_sequence)
-           {
-             dwarf_finish_line (m_gdbarch, m_last_subfile, m_address,
-                                m_currently_recording_lines ? m_cu : nullptr);
-           }
-
-         if (!end_sequence && !ignore_this_line)
+      /* When we switch files we insert an end maker in the first file,
+        switch to the second file and add a new line entry.  The
+        problem is that the end marker inserted in the first file will
+        discard any previous line entries at the same address.  If the
+        line entries in the first file are marked as is-stmt, while
+        the new line in the second file is non-stmt, then this means
+        the end marker will discard is-stmt lines so we can have a
+        non-stmt line.  This means that there are less addresses at
+        which the user can insert a breakpoint.
+
+        To improve this we track the last address in m_last_address,
+        and whether we have seen an is-stmt at this address.  Then
+        when switching files, if we have seen a stmt at the current
+        address, and we are switching to create a non-stmt line, then
+        discard the new line.  */
+      bool file_changed
+       = m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
+      bool ignore_this_line
+       = ((file_changed && !end_sequence && m_last_address == m_address
+           && ((m_flags & LEF_IS_STMT) == 0)
+           && m_stmt_at_address)
+          || (!end_sequence && m_line == 0));
+
+      if ((file_changed && !ignore_this_line) || end_sequence)
+       {
+         dwarf_finish_line (m_gdbarch, m_last_subfile, m_address,
+                            m_currently_recording_lines ? m_cu : nullptr);
+       }
+
+      if (!end_sequence && !ignore_this_line)
+       {
+         linetable_entry_flags lte_flags = m_flags;
+         if (producer_is_codewarrior (m_cu))
+           lte_flags |= LEF_IS_STMT;
+
+         if (dwarf_record_line_p (m_cu, m_line, m_last_line,
+                                  m_line_has_non_zero_discriminator,
+                                  m_last_subfile))
            {
-             bool is_stmt = producer_is_codewarrior (m_cu) || m_is_stmt;
-
-             if (dwarf_record_line_p (m_cu, m_line, m_last_line,
-                                      m_line_has_non_zero_discriminator,
-                                      m_last_subfile))
-               {
-                 buildsym_compunit *builder = m_cu->get_builder ();
-                 dwarf_record_line_1 (m_gdbarch,
-                                      builder->get_current_subfile (),
-                                      m_line, m_address, is_stmt,
-                                      m_currently_recording_lines ? m_cu : nullptr);
-               }
-             m_last_subfile = m_cu->get_builder ()->get_current_subfile ();
-             m_last_line = m_line;
+             buildsym_compunit *builder = m_cu->get_builder ();
+             dwarf_record_line_1 (m_gdbarch,
+                                  builder->get_current_subfile (),
+                                  m_line, m_address, lte_flags,
+                                  m_currently_recording_lines ? m_cu : nullptr);
            }
+         m_last_subfile = m_cu->get_builder ()->get_current_subfile ();
+         m_last_line = m_line;
        }
     }
 
-  /* Track whether we have seen any m_is_stmt true at m_address in case we
+  /* Track whether we have seen any IS_STMT true at m_address in case we
      have multiple line table entries all at m_address.  */
   if (m_last_address != m_address)
     {
       m_stmt_at_address = false;
       m_last_address = m_address;
     }
-  m_stmt_at_address |= m_is_stmt;
+  m_stmt_at_address |= (m_flags & LEF_IS_STMT) != 0;
 }
 
 lnp_state_machine::lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch,
-                                     line_header *lh, bool record_lines_p)
+                                     line_header *lh)
 {
   m_cu = cu;
   m_gdbarch = arch;
-  m_record_lines_p = record_lines_p;
   m_line_header = lh;
 
   m_currently_recording_lines = true;
@@ -21080,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);
-  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;
@@ -21115,13 +20250,11 @@ lnp_state_machine::check_line_address (struct dwarf2_cu *cu,
 }
 
 /* Subroutine of dwarf_decode_lines to simplify it.
-   Process the line number information in LH.
-   If DECODE_FOR_PST_P is non-zero, all we do is process the line number
-   program in order to set included_p for every referenced header.  */
+   Process the line number information in LH.  */
 
 static void
 dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
-                     const int decode_for_pst_p, CORE_ADDR lowpc)
+                     CORE_ADDR lowpc)
 {
   const gdb_byte *line_ptr, *extended_end;
   const gdb_byte *line_end;
@@ -21131,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 ();
-  /* 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 ();
 
@@ -21146,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.  */
-      lnp_state_machine state_machine (cu, gdbarch, lh, record_lines_p);
+      lnp_state_machine state_machine (cu, gdbarch, lh);
       bool end_sequence = false;
 
-      if (record_lines_p)
-       {
-         /* Start a subfile for the current file of the state
-            machine.  */
-         const file_entry *fe = state_machine.current_file ();
+      /* Start a subfile for the current file of the state
+        machine.  */
+      const file_entry *fe = state_machine.current_file ();
 
-         if (fe != NULL)
-           dwarf2_start_subfile (cu, fe->name, fe->include_dir (lh));
-       }
+      if (fe != NULL)
+       dwarf2_start_subfile (cu, fe->name, fe->include_dir (lh));
 
       /* Decode the table.  */
       while (line_ptr < line_end && !end_sequence)
@@ -21308,6 +20434,9 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
                state_machine.handle_fixed_advance_pc (addr_adj);
              }
              break;
+           case DW_LNS_set_prologue_end:
+             state_machine.handle_set_prologue_end ();
+             break;
            default:
              {
                /* Unknown standard opcode, ignore it.  */
@@ -21335,23 +20464,15 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
    structure and CU.  The actual information extracted and the type
    of structures created from the LNP depends on the value of PST.
 
-   1. If PST is NULL, then this procedure uses the data from the program
-      to create all necessary symbol tables, and their linetables.
-
-   2. If PST is not NULL, this procedure reads the program to determine
-      the list of files included by the unit represented by PST, and
-      builds all the associated partial symbol tables.
-
-   COMP_DIR is the compilation directory (DW_AT_comp_dir) or NULL if unknown.
+   FND holds the CU file name and directory, if known.
    It is used for relative paths in the line table.
-   NOTE: When processing partial symtabs (pst != NULL),
-   comp_dir == pst->dirname.
 
-   NOTE: It is important that psymtabs have the same file name (via strcmp)
-   as the corresponding symtab.  Since COMP_DIR is not used in the name of the
-   symtab we don't use it in the name of the psymtabs we create.
-   E.g. expand_line_sal requires this when finding psymtabs to expand.
-   A good testcase for this is mb-inline.exp.
+   NOTE: It is important that psymtabs have the same file name (via
+   strcmp) as the corresponding symtab.  Since the directory is not
+   used in the name of the symtab we don't use it in the name of the
+   psymtabs we create.  E.g. expand_line_sal requires this when
+   finding psymtabs to expand.  A good testcase for this is
+   mb-inline.exp.
 
    LOWPC is the lowest address in CU (or 0 if not known).
 
@@ -21360,53 +20481,28 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
    table is read in.  */
 
 static void
-dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
-                   struct dwarf2_cu *cu, dwarf2_psymtab *pst,
+dwarf_decode_lines (struct line_header *lh, struct dwarf2_cu *cu,
                    CORE_ADDR lowpc, int decode_mapping)
 {
-  struct objfile *objfile = cu->per_objfile->objfile;
-  const int decode_for_pst_p = (pst != NULL);
-
   if (decode_mapping)
-    dwarf_decode_lines_1 (lh, cu, decode_for_pst_p, lowpc);
+    dwarf_decode_lines_1 (lh, cu, lowpc);
 
-  if (decode_for_pst_p)
-    {
-      /* Now that we're done scanning the Line Header Program, we can
-        create the psymtab of each included file.  */
-      for (auto &file_entry : lh->file_names ())
-       if (file_entry.included_p)
-         {
-           gdb::unique_xmalloc_ptr<char> name_holder;
-           const char *include_name =
-             psymtab_include_file_name (lh, file_entry, pst,
-                                        comp_dir, &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;
     }
 }
 
@@ -21476,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)
     {
-      SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
+      sym->set_aclass_index (LOC_OPTIMIZED_OUT);
       return;
     }
 
@@ -21499,19 +20595,16 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
          unsigned int dummy;
 
          if (block->data[0] == DW_OP_addr)
-           SET_SYMBOL_VALUE_ADDRESS
-             (sym, cu->header.read_address (objfile->obfd,
-                                            block->data + 1,
-                                            &dummy));
+           sym->set_value_address
+             (cu->header.read_address (objfile->obfd, block->data + 1,
+                                       &dummy));
          else
-           SET_SYMBOL_VALUE_ADDRESS
-             (sym, read_addr_index_from_leb128 (cu, block->data + 1,
-                                                &dummy));
-         SYMBOL_ACLASS_INDEX (sym) = LOC_STATIC;
+           sym->set_value_address
+             (read_addr_index_from_leb128 (cu, block->data + 1, &dummy));
+         sym->set_aclass_index (LOC_STATIC);
          fixup_symbol_section (sym, objfile);
-         SET_SYMBOL_VALUE_ADDRESS
-           (sym,
-            SYMBOL_VALUE_ADDRESS (sym)
+         sym->set_value_address
+           (sym->value_address ()
             + objfile->section_offsets[sym->section_index ()]);
          return;
        }
@@ -21585,19 +20678,24 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
          sym->set_linkage_name (linkagename);
        }
 
+      /* Handle DW_AT_artificial.  */
+      attr = dwarf2_attr (die, DW_AT_artificial, cu);
+      if (attr != nullptr)
+       sym->artificial = attr->as_boolean ();
+
       /* Default assumptions.
         Use the passed type or decode it from the die.  */
-      SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
-      SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
+      sym->set_domain (VAR_DOMAIN);
+      sym->set_aclass_index (LOC_OPTIMIZED_OUT);
       if (type != NULL)
-       SYMBOL_TYPE (sym) = type;
+       sym->set_type (type);
       else
-       SYMBOL_TYPE (sym) = die_type (die, cu);
+       sym->set_type (die_type (die, cu));
       attr = dwarf2_attr (die,
                          inlined_func ? DW_AT_call_line : DW_AT_decl_line,
                          cu);
       if (attr != nullptr)
-       SYMBOL_LINE (sym) = attr->constant_value (0);
+       sym->set_line (attr->constant_value (0));
 
       attr = dwarf2_attr (die,
                          inlined_func ? DW_AT_call_file : DW_AT_decl_file,
@@ -21629,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);
-             SET_SYMBOL_VALUE_ADDRESS (sym, addr);
-             SYMBOL_ACLASS_INDEX (sym) = LOC_LABEL;
+             sym->set_value_address (addr);
+             sym->set_aclass_index (LOC_LABEL);
            }
          else
-           SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
-         SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_core_addr;
-         SYMBOL_DOMAIN (sym) = LABEL_DOMAIN;
+           sym->set_aclass_index (LOC_OPTIMIZED_OUT);
+         sym->set_type (objfile_type (objfile)->builtin_core_addr);
+         sym->set_domain (LABEL_DOMAIN);
          add_symbol_to_list (sym, cu->list_in_scope);
          break;
        case DW_TAG_subprogram:
          /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
             finish_block.  */
-         SYMBOL_ACLASS_INDEX (sym) = LOC_BLOCK;
+         sym->set_aclass_index (LOC_BLOCK);
          attr2 = dwarf2_attr (die, DW_AT_external, cu);
          if ((attr2 != nullptr && attr2->as_boolean ())
              || cu->per_cu->lang == language_ada
@@ -21663,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.  */
-         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:
@@ -21676,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.  */
-         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
@@ -21714,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;
 
-             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,
@@ -21725,7 +20823,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
                }
              else if (attr2 != nullptr && attr2->as_boolean ())
                {
-                 if (SYMBOL_CLASS (sym) == LOC_STATIC
+                 if (sym->aclass () == LOC_STATIC
                      && (objfile->flags & OBJF_MAINLINE) == 0
                      && per_objfile->per_bfd->can_copy)
                    {
@@ -21783,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);
 
-                 SYMBOL_ACLASS_INDEX (sym) = LOC_UNRESOLVED;
+                 sym->set_aclass_index (LOC_UNRESOLVED);
                }
              else if (!die_is_declaration (die, cu))
                {
                  /* Use the default LOC_OPTIMIZED_OUT class.  */
-                 gdb_assert (SYMBOL_CLASS (sym) == LOC_OPTIMIZED_OUT);
+                 gdb_assert (sym->aclass () == LOC_OPTIMIZED_OUT);
                  if (!suppress_add)
                    list_to_add = cu->list_in_scope;
                }
@@ -21804,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)
-             SYMBOL_IS_ARGUMENT (sym) = 1;
+             sym->set_is_argument (1);
            attr = dwarf2_attr (die, DW_AT_location, cu);
            if (attr != nullptr)
              {
@@ -21833,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:
-         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
@@ -21864,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.  */
-                   if (SYMBOL_TYPE (sym)->name () == 0)
-                     SYMBOL_TYPE (sym)->set_name (sym->search_name ());
+                   if (sym->type ()->name () == 0)
+                     sym->type ()->set_name (sym->search_name ());
                  }
              }
          }
          break;
        case DW_TAG_typedef:
-         SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
-         SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
+         sym->set_aclass_index (LOC_TYPEDEF);
+         sym->set_domain (VAR_DOMAIN);
          list_to_add = cu->list_in_scope;
          break;
        case DW_TAG_array_type:
        case DW_TAG_base_type:
        case DW_TAG_subrange_type:
-         SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
-         SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
+       case DW_TAG_generic_subrange:
+         sym->set_aclass_index (LOC_TYPEDEF);
+         sym->set_domain (VAR_DOMAIN);
          list_to_add = cu->list_in_scope;
          break;
        case DW_TAG_enumerator:
@@ -21901,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:
-         SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
+         sym->set_aclass_index (LOC_TYPEDEF);
          list_to_add = cu->get_builder ()->get_global_symbols ();
          break;
        case DW_TAG_module:
-         SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
-         SYMBOL_DOMAIN (sym) = MODULE_DOMAIN;
+         sym->set_aclass_index (LOC_TYPEDEF);
+         sym->set_domain (MODULE_DOMAIN);
          list_to_add = cu->get_builder ()->get_global_symbols ();
          break;
        case DW_TAG_common_block:
-         SYMBOL_ACLASS_INDEX (sym) = LOC_COMMON_BLOCK;
-         SYMBOL_DOMAIN (sym) = COMMON_BLOCK_DOMAIN;
+         sym->set_aclass_index (LOC_COMMON_BLOCK);
+         sym->set_domain (COMMON_BLOCK_DOMAIN);
          add_symbol_to_list (sym, cu->list_in_scope);
          break;
        default:
@@ -22100,7 +21207,7 @@ dwarf2_const_value (const struct attribute *attr, struct symbol *sym,
   const gdb_byte *bytes;
   struct dwarf2_locexpr_baton *baton;
 
-  dwarf2_const_value_attr (attr, SYMBOL_TYPE (sym),
+  dwarf2_const_value_attr (attr, sym->type (),
                           sym->print_name (),
                           &objfile->objfile_obstack, cu,
                           &value, &bytes, &baton);
@@ -22108,17 +21215,17 @@ dwarf2_const_value (const struct attribute *attr, struct symbol *sym,
   if (baton != NULL)
     {
       SYMBOL_LOCATION_BATON (sym) = baton;
-      SYMBOL_ACLASS_INDEX (sym) = dwarf2_locexpr_index;
+      sym->set_aclass_index (dwarf2_locexpr_index);
     }
   else if (bytes != NULL)
-     {
-      SYMBOL_VALUE_BYTES (sym) = bytes;
-      SYMBOL_ACLASS_INDEX (sym) = LOC_CONST_BYTES;
+    {
+      sym->set_value_bytes (bytes);
+      sym->set_aclass_index (LOC_CONST_BYTES);
     }
   else
     {
-      SYMBOL_VALUE (sym) = value;
-      SYMBOL_ACLASS_INDEX (sym) = LOC_CONST;
+      sym->set_value_longest (value);
+      sym->set_aclass_index (LOC_CONST);
     }
 }
 
@@ -22244,7 +21351,8 @@ lookup_die_type (struct die_info *die, const struct attribute *attr,
       struct dwarf2_per_cu_data *per_cu;
       sect_offset sect_off = attr->get_ref_die_offset ();
 
-      per_cu = dwarf2_find_containing_comp_unit (sect_off, 1, per_objfile);
+      per_cu = dwarf2_find_containing_comp_unit (sect_off, 1,
+                                                per_objfile->per_bfd);
       this_type = get_die_type_at_offset (sect_off, per_cu, per_objfile);
     }
   else if (attr->form_is_ref ())
@@ -22370,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_generic_subrange:
     case DW_TAG_subrange_type:
       this_type = read_subrange_type (die, cu);
       break;
@@ -22771,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_namelist
       && die->tag != DW_TAG_union_type)
     return NULL;
 
@@ -22795,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_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
@@ -22868,85 +21979,82 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
 {
   unsigned int i;
 
-  print_spaces (indent, f);
-  fprintf_unfiltered (f, "Die: %s (abbrev %d, offset %s)\n",
-                     dwarf_tag_name (die->tag), die->abbrev,
-                     sect_offset_str (die->sect_off));
+  gdb_printf (f, "%*sDie: %s (abbrev %d, offset %s)\n",
+             indent, "",
+             dwarf_tag_name (die->tag), die->abbrev,
+             sect_offset_str (die->sect_off));
 
   if (die->parent != NULL)
-    {
-      print_spaces (indent, f);
-      fprintf_unfiltered (f, "  parent at offset: %s\n",
-                         sect_offset_str (die->parent->sect_off));
-    }
+    gdb_printf (f, "%*s  parent at offset: %s\n",
+               indent, "",
+               sect_offset_str (die->parent->sect_off));
 
-  print_spaces (indent, f);
-  fprintf_unfiltered (f, "  has children: %s\n",
-          dwarf_bool_name (die->child != NULL));
+  gdb_printf (f, "%*s  has children: %s\n",
+             indent, "",
+             dwarf_bool_name (die->child != NULL));
 
-  print_spaces (indent, f);
-  fprintf_unfiltered (f, "  attributes:\n");
+  gdb_printf (f, "%*s  attributes:\n", indent, "");
 
   for (i = 0; i < die->num_attrs; ++i)
     {
-      print_spaces (indent, f);
-      fprintf_unfiltered (f, "    %s (%s) ",
-              dwarf_attr_name (die->attrs[i].name),
-              dwarf_form_name (die->attrs[i].form));
+      gdb_printf (f, "%*s    %s (%s) ",
+                 indent, "",
+                 dwarf_attr_name (die->attrs[i].name),
+                 dwarf_form_name (die->attrs[i].form));
 
       switch (die->attrs[i].form)
        {
        case DW_FORM_addr:
        case DW_FORM_addrx:
        case DW_FORM_GNU_addr_index:
-         fprintf_unfiltered (f, "address: ");
-         fputs_filtered (hex_string (die->attrs[i].as_address ()), f);
+         gdb_printf (f, "address: ");
+         gdb_puts (hex_string (die->attrs[i].as_address ()), f);
          break;
        case DW_FORM_block2:
        case DW_FORM_block4:
        case DW_FORM_block:
        case DW_FORM_block1:
-         fprintf_unfiltered (f, "block: size %s",
-                             pulongest (die->attrs[i].as_block ()->size));
+         gdb_printf (f, "block: size %s",
+                     pulongest (die->attrs[i].as_block ()->size));
          break;
        case DW_FORM_exprloc:
-         fprintf_unfiltered (f, "expression: size %s",
-                             pulongest (die->attrs[i].as_block ()->size));
+         gdb_printf (f, "expression: size %s",
+                     pulongest (die->attrs[i].as_block ()->size));
          break;
        case DW_FORM_data16:
-         fprintf_unfiltered (f, "constant of 16 bytes");
+         gdb_printf (f, "constant of 16 bytes");
          break;
        case DW_FORM_ref_addr:
-         fprintf_unfiltered (f, "ref address: ");
-         fputs_filtered (hex_string (die->attrs[i].as_unsigned ()), f);
+         gdb_printf (f, "ref address: ");
+         gdb_puts (hex_string (die->attrs[i].as_unsigned ()), f);
          break;
        case DW_FORM_GNU_ref_alt:
-         fprintf_unfiltered (f, "alt ref address: ");
-         fputs_filtered (hex_string (die->attrs[i].as_unsigned ()), f);
+         gdb_printf (f, "alt ref address: ");
+         gdb_puts (hex_string (die->attrs[i].as_unsigned ()), f);
          break;
        case DW_FORM_ref1:
        case DW_FORM_ref2:
        case DW_FORM_ref4:
        case DW_FORM_ref8:
        case DW_FORM_ref_udata:
-         fprintf_unfiltered (f, "constant ref: 0x%lx (adjusted)",
-                             (long) (die->attrs[i].as_unsigned ()));
+         gdb_printf (f, "constant ref: 0x%lx (adjusted)",
+                     (long) (die->attrs[i].as_unsigned ()));
          break;
        case DW_FORM_data1:
        case DW_FORM_data2:
        case DW_FORM_data4:
        case DW_FORM_data8:
        case DW_FORM_udata:
-         fprintf_unfiltered (f, "constant: %s",
-                             pulongest (die->attrs[i].as_unsigned ()));
+         gdb_printf (f, "constant: %s",
+                     pulongest (die->attrs[i].as_unsigned ()));
          break;
        case DW_FORM_sec_offset:
-         fprintf_unfiltered (f, "section offset: %s",
-                             pulongest (die->attrs[i].as_unsigned ()));
+         gdb_printf (f, "section offset: %s",
+                     pulongest (die->attrs[i].as_unsigned ()));
          break;
        case DW_FORM_ref_sig8:
-         fprintf_unfiltered (f, "signature: %s",
-                             hex_string (die->attrs[i].as_signature ()));
+         gdb_printf (f, "signature: %s",
+                     hex_string (die->attrs[i].as_signature ()));
          break;
        case DW_FORM_string:
        case DW_FORM_strp:
@@ -22954,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:
-         fprintf_unfiltered (f, "string: \"%s\" (%s canonicalized)",
-                             die->attrs[i].as_string ()
-                             ? die->attrs[i].as_string () : "",
-                             die->attrs[i].canonical_string_p () ? "is" : "not");
+         gdb_printf (f, "string: \"%s\" (%s canonicalized)",
+                     die->attrs[i].as_string ()
+                     ? die->attrs[i].as_string () : "",
+                     die->attrs[i].canonical_string_p () ? "is" : "not");
          break;
        case DW_FORM_flag:
          if (die->attrs[i].as_boolean ())
-           fprintf_unfiltered (f, "flag: TRUE");
+           gdb_printf (f, "flag: TRUE");
          else
-           fprintf_unfiltered (f, "flag: FALSE");
+           gdb_printf (f, "flag: FALSE");
          break;
        case DW_FORM_flag_present:
-         fprintf_unfiltered (f, "flag: TRUE");
+         gdb_printf (f, "flag: TRUE");
          break;
        case DW_FORM_indirect:
          /* The reader will have reduced the indirect form to
             the "base form" so this form should not occur.  */
-         fprintf_unfiltered (f,
-                             "unexpected attribute form: DW_FORM_indirect");
+         gdb_printf (f,
+                     "unexpected attribute form: DW_FORM_indirect");
          break;
        case DW_FORM_sdata:
        case DW_FORM_implicit_const:
-         fprintf_unfiltered (f, "constant: %s",
-                             plongest (die->attrs[i].as_signed ()));
+         gdb_printf (f, "constant: %s",
+                     plongest (die->attrs[i].as_signed ()));
          break;
        default:
-         fprintf_unfiltered (f, "unsupported attribute form: %d.",
-                  die->attrs[i].form);
+         gdb_printf (f, "unsupported attribute form: %d.",
+                     die->attrs[i].form);
          break;
        }
-      fprintf_unfiltered (f, "\n");
+      gdb_printf (f, "\n");
     }
 }
 
@@ -23008,17 +22116,16 @@ dump_die_1 (struct ui_file *f, int level, int max_level, struct die_info *die)
 
   if (die->child != NULL)
     {
-      print_spaces (indent, f);
-      fprintf_unfiltered (f, "  Children:");
+      gdb_printf (f, "%*s  Children:", indent, "");
       if (level + 1 < max_level)
        {
-         fprintf_unfiltered (f, "\n");
+         gdb_printf (f, "\n");
          dump_die_1 (f, level + 1, max_level, die->child);
        }
       else
        {
-         fprintf_unfiltered (f,
-                             " [not printed, max nesting level reached]\n");
+         gdb_printf (f,
+                     " [not printed, max nesting level reached]\n");
        }
     }
 
@@ -23110,7 +22217,7 @@ follow_die_offset (sect_offset sect_off, int offset_in_dwz,
       struct dwarf2_per_cu_data *per_cu;
 
       per_cu = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
-                                                per_objfile);
+                                                per_objfile->per_bfd);
 
       dwarf_read_debug_printf_v ("target CU offset: %s, "
                                 "target CU DIEs loaded: %d",
@@ -23133,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.  */
-      gdb_assert (per_objfile->per_bfd->reading_partial_symbols);
       load_full_comp_unit (cu->per_cu, per_objfile, cu, false,
                           language_minimal);
     }
@@ -23675,9 +22781,6 @@ load_full_type_unit (dwarf2_per_cu_data *per_cu,
 {
   struct signatured_type *sig_type;
 
-  /* Caller is responsible for ensuring type_unit_groups don't get here.  */
-  gdb_assert (! per_cu->type_unit_group_p ());
-
   /* We have the per_cu, but we need the signatured_type.
      Fortunately this is an easy translation.  */
   gdb_assert (per_cu->is_debug_types);
@@ -24097,7 +23200,7 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
 
   struct dwarf2_section_info *str_offsets_section;
   struct dwarf2_section_info *str_section;
-  ULONGEST str_offsets_base;
+  gdb::optional<ULONGEST> str_offsets_base;
 
   if (cu->dwo_unit != nullptr)
     {
@@ -24110,7 +23213,7 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
     {
       str_offsets_section = &per_objfile->per_bfd->str_offsets;
       str_section = &per_objfile->per_bfd->str;
-      str_offsets_base = *cu->str_offsets_base;
+      str_offsets_base = cu->str_offsets_base;
     }
 
   dwarf_decode_macros (per_objfile, builder, section, lh,
@@ -24214,9 +23317,9 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym,
        complaint (_("Location list used without "
                     "specifying the CU base address."));
 
-      SYMBOL_ACLASS_INDEX (sym) = (is_block
-                                  ? dwarf2_loclist_block_index
-                                  : dwarf2_loclist_index);
+      sym->set_aclass_index ((is_block
+                             ? dwarf2_loclist_block_index
+                             : dwarf2_loclist_index));
       SYMBOL_LOCATION_BATON (sym) = baton;
     }
   else
@@ -24246,9 +23349,9 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym,
          baton->size = 0;
        }
 
-      SYMBOL_ACLASS_INDEX (sym) = (is_block
-                                  ? dwarf2_locexpr_block_index
-                                  : dwarf2_locexpr_index);
+      sym->set_aclass_index ((is_block
+                             ? dwarf2_locexpr_block_index
+                             : dwarf2_locexpr_index));
       SYMBOL_LOCATION_BATON (sym) = baton;
     }
 }
@@ -24342,12 +23445,11 @@ dwarf2_find_containing_comp_unit
 static struct dwarf2_per_cu_data *
 dwarf2_find_containing_comp_unit (sect_offset sect_off,
                                  unsigned int offset_in_dwz,
-                                 dwarf2_per_objfile *per_objfile)
+                                 dwarf2_per_bfd *per_bfd)
 {
   int low = dwarf2_find_containing_comp_unit
-    (sect_off, offset_in_dwz, per_objfile->per_bfd->all_comp_units);
-  dwarf2_per_cu_data *this_cu
-    = per_objfile->per_bfd->all_comp_units[low].get ();
+    (sect_off, offset_in_dwz, per_bfd->all_comp_units);
+  dwarf2_per_cu_data *this_cu = per_bfd->all_comp_units[low].get ();
 
   if (this_cu->is_dwz != offset_in_dwz || this_cu->sect_off > sect_off)
     {
@@ -24355,15 +23457,15 @@ dwarf2_find_containing_comp_unit (sect_offset sect_off,
        error (_("Dwarf Error: could not find partial DIE containing "
               "offset %s [in module %s]"),
               sect_offset_str (sect_off),
-              bfd_get_filename (per_objfile->objfile->obfd));
+              bfd_get_filename (per_bfd->obfd));
 
-      gdb_assert (per_objfile->per_bfd->all_comp_units[low-1]->sect_off
+      gdb_assert (per_bfd->all_comp_units[low-1]->sect_off
                  <= sect_off);
-      return per_objfile->per_bfd->all_comp_units[low - 1].get ();
+      return per_bfd->all_comp_units[low - 1].get ();
     }
   else
     {
-      if (low == per_objfile->per_bfd->all_comp_units.size () - 1
+      if (low == per_bfd->all_comp_units.size () - 1
          && sect_off >= this_cu->sect_off + this_cu->length)
        error (_("invalid dwarf2 offset %s"), sect_offset_str (sect_off));
       gdb_assert (sect_off < this_cu->sect_off + this_cu->length);
@@ -24656,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);
     }
 
+  /* 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)
     {
@@ -24717,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);
 }
 
-/* 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;
 
@@ -24750,26 +23835,24 @@ static void
 show_check_physname (struct ui_file *file, int from_tty,
                     struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file,
-                   _("Whether to check \"physname\" is %s.\n"),
-                   value);
+  gdb_printf (file,
+             _("Whether to check \"physname\" is %s.\n"),
+             value);
 }
 
 void _initialize_dwarf2_read ();
 void
 _initialize_dwarf2_read ()
 {
-  add_basic_prefix_cmd ("dwarf", class_maintenance, _("\
+  add_setshow_prefix_cmd ("dwarf", class_maintenance,
+                         _("\
 Set DWARF specific variables.\n\
 Configure DWARF variables such as the cache size."),
-                       &set_dwarf_cmdlist,
-                       0/*allow-unknown*/, &maintenance_set_cmdlist);
-
-  add_show_prefix_cmd ("dwarf", class_maintenance, _("\
+                         _("\
 Show DWARF specific variables.\n\
 Show DWARF variables such as the cache size."),
-                      &show_dwarf_cmdlist,
-                      0/*allow-unknown*/, &maintenance_show_cmdlist);
+                         &set_dwarf_cmdlist, &show_dwarf_cmdlist,
+                         &maintenance_set_cmdlist, &maintenance_show_cmdlist);
 
   add_setshow_zinteger_cmd ("max-cache-age", class_obscure,
                            &dwarf_max_cache_age, _("\