Parallelize DWARF indexing
[binutils-gdb.git] / gdb / dwarf2 / read.c
index 259401fbbb70d2c761dcf9a9d8dcabbd48a55fac..fce465e4dab8ecb28084a0f8efc961fcb3dc9784 100644 (file)
 #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 +367,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)
@@ -791,7 +796,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 +806,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 +816,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,
@@ -1090,9 +1105,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 */
@@ -1104,9 +1119,9 @@ 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);
 
@@ -1297,7 +1312,8 @@ enum pc_bounds_kind
 static enum pc_bounds_kind dwarf2_get_pc_bounds (struct die_info *,
                                                 CORE_ADDR *, CORE_ADDR *,
                                                 struct dwarf2_cu *,
-                                                dwarf2_psymtab *);
+                                                addrmap *,
+                                                void *);
 
 static void get_scope_pc_bounds (struct die_info *,
                                 CORE_ADDR *, CORE_ADDR *,
@@ -1441,7 +1457,8 @@ static void dwarf2_symbol_mark_computed (const struct attribute *attr,
 
 static const gdb_byte *skip_one_die (const struct die_reader_specs *reader,
                                     const gdb_byte *info_ptr,
-                                    const struct abbrev_info *abbrev);
+                                    const struct abbrev_info *abbrev,
+                                    bool do_skip_children = true);
 
 static hashval_t partial_die_hash (const void *item);
 
@@ -2024,6 +2041,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.  */
 
@@ -2579,12 +2615,14 @@ create_addrmap_from_index (dwarf2_per_objfile *per_objfile,
                                                 &per_bfd->obstack);
 }
 
-/* Read the address map data from DWARF-5 .debug_aranges, and use it to
-   populate the psymtabs_addrmap.  */
+/* Read the address map data from DWARF-5 .debug_aranges, and use it
+   to populate given addrmap.  Returns true on success, false on
+   failure.  */
 
-static void
-create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
-                            struct dwarf2_section_info *section)
+static bool
+read_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
+                          struct dwarf2_section_info *section,
+                          addrmap *mutable_map)
 {
   struct objfile *objfile = per_objfile->objfile;
   bfd *abfd = objfile->obfd;
@@ -2592,9 +2630,6 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
   const CORE_ADDR baseaddr = objfile->text_section_offset ();
   dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
 
-  auto_obstack temp_obstack;
-  addrmap *mutable_map = addrmap_create_mutable (&temp_obstack);
-
   std::unordered_map<sect_offset,
                     dwarf2_per_cu_data *,
                     gdb::hash_enum<sect_offset>>
@@ -2603,8 +2638,9 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
     {
       /* A TU will not need aranges, and skipping them here is an easy
         way of ignoring .debug_types -- and possibly seeing a
-        duplicate section offset -- entirely.  */
-      if (per_cu->is_debug_types)
+        duplicate section offset -- entirely.  The same applies to
+        units coming from a dwz file.  */
+      if (per_cu->is_debug_types || per_cu->is_dwz)
        continue;
 
       const auto insertpair
@@ -2615,7 +2651,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
          warning (_("Section .debug_aranges in %s has duplicate "
                     "debug_info_offset %s, ignoring .debug_aranges."),
                   objfile_name (objfile), sect_offset_str (per_cu->sect_off));
-         return;
+         return false;
        }
     }
 
@@ -2646,7 +2682,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                   plongest (entry_addr - section->buffer),
                   plongest (bytes_read + entry_length),
                   pulongest (section->size));
-         return;
+         return false;
        }
 
       /* The version number.  */
@@ -2658,7 +2694,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                     "has unsupported version %d, ignoring .debug_aranges."),
                   objfile_name (objfile),
                   plongest (entry_addr - section->buffer), version);
-         return;
+         return false;
        }
 
       const uint64_t debug_info_offset
@@ -2674,7 +2710,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                   objfile_name (objfile),
                   plongest (entry_addr - section->buffer),
                   pulongest (debug_info_offset));
-         return;
+         return false;
        }
       dwarf2_per_cu_data *const per_cu = per_cu_it->second;
 
@@ -2685,7 +2721,7 @@ create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile,
                     "address_size %u is invalid, ignoring .debug_aranges."),
                   objfile_name (objfile),
                   plongest (entry_addr - section->buffer), address_size);
-         return;
+         return false;
        }
 
       const uint8_t segment_selector_size = *addr++;
@@ -2697,7 +2733,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
@@ -2718,7 +2754,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);
@@ -2740,10 +2776,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
@@ -3121,6 +3175,9 @@ dwarf2_base_index_functions::find_last_source_symtab (struct objfile *objfile)
 void
 dwarf2_per_cu_data::free_cached_file_names ()
 {
+  if (fnd != nullptr)
+    fnd->forget_fullname ();
+
   if (per_bfd == nullptr || !per_bfd->using_index || v.quick == nullptr)
     return;
 
@@ -3311,8 +3368,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.
@@ -3326,15 +3383,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
@@ -4344,6 +4401,27 @@ dw_expand_symtabs_matching_file_matcher
       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->v.quick->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->v.quick->mark = 1;
+             continue;
+           }
+       }
+
       quick_file_names *file_data = dw2_get_file_names (per_cu.get (),
                                                        per_objfile);
       if (file_data == NULL)
@@ -4538,6 +4616,24 @@ dwarf2_base_index_functions::map_symbol_filenames
       if (per_cu->is_debug_types || per_objfile->symtab_set_p (per_cu))
        continue;
 
+      if (per_cu->fnd != nullptr)
+       {
+         file_and_directory *fnd = per_cu->fnd.get ();
+
+         const char *filename = fnd->get_name ();
+         const char *key = filename;
+         const char *fullname = nullptr;
+
+         if (need_fullname)
+           {
+             fullname = fnd->get_fullname ();
+             key = fullname;
+           }
+
+         if (!filenames_cache.seen (key))
+           fun (filename, fullname);
+       }
+
       quick_file_names *file_data = dw2_get_file_names (per_cu, per_objfile);
       if (file_data == nullptr
          || qfn_cache.find (file_data) != qfn_cache.end ())
@@ -5334,12 +5430,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
@@ -5496,6 +5592,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
@@ -5561,6 +5659,13 @@ dwarf2_initialize_objfile (struct objfile *objfile)
       return;
     }
 
+  if (per_bfd->cooked_index_table != nullptr)
+    {
+      dwarf_read_debug_printf ("re-using cooked index table");
+      objfile->qf.push_front (make_cooked_index_funcs ());
+      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
@@ -6037,9 +6142,12 @@ fill_in_sig_entry_from_dwo_entry (dwarf2_per_objfile *per_objfile,
   else
       gdb_assert (sig_entry->v.psymtab == NULL);
   gdb_assert (sig_entry->signature == dwo_entry->signature);
-  gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0);
+  gdb_assert (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;
@@ -6117,7 +6225,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;
 }
@@ -6390,11 +6499,11 @@ read_cutu_die_from_dwo (dwarf2_cu *cu,
 
   if (dwarf_die_debug)
     {
-      fprintf_unfiltered (gdb_stdlog,
-                         "Read die from %s@0x%x of %s:\n",
-                         section->get_name (),
-                         (unsigned) (begin_info_ptr - section->buffer),
-                         bfd_get_filename (abfd));
+      gdb_printf (gdb_stdlog,
+                 "Read die from %s@0x%x of %s:\n",
+                 section->get_name (),
+                 (unsigned) (begin_info_ptr - section->buffer),
+                 bfd_get_filename (abfd));
       dump_die (comp_unit_die, dwarf_die_debug);
     }
 
@@ -6429,6 +6538,14 @@ lookup_dwo_id (struct dwarf2_cu *cu, struct die_info* comp_unit_die)
 static struct dwo_unit *
 lookup_dwo_unit (dwarf2_cu *cu, die_info *comp_unit_die, const char *dwo_name)
 {
+#if CXX_STD_THREAD
+  /* We need a lock here both to handle the DWO hash table, and BFD,
+     which is not thread-safe.  */
+  static std::mutex dwo_lock;
+
+  std::lock_guard<std::mutex> guard (dwo_lock);
+#endif
+
   dwarf2_per_cu_data *per_cu = cu->per_cu;
   struct dwo_unit *dwo_unit;
   const char *comp_dir;
@@ -6521,7 +6638,8 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
                          dwarf2_per_objfile *per_objfile,
                          struct abbrev_table *abbrev_table,
                          dwarf2_cu *existing_cu,
-                         bool skip_partial)
+                         bool skip_partial,
+                         abbrev_cache *cache)
   : die_reader_specs {},
     m_this_cu (this_cu)
 {
@@ -6537,9 +6655,9 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
   int rereading_dwo_cu = 0;
 
   if (dwarf_die_debug)
-    fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset %s\n",
-                       this_cu->is_debug_types ? "type" : "comp",
-                       sect_offset_str (this_cu->sect_off));
+    gdb_printf (gdb_stdlog, "Reading %s unit at offset %s\n",
+               this_cu->is_debug_types ? "type" : "comp",
+               sect_offset_str (this_cu->sect_off));
 
   /* If we're reading a TU directly from a DWO file, including a virtual DWO
      file (instead of going through the stub), short-circuit all of this.  */
@@ -6575,9 +6693,14 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
     }
   else
     {
-      /* If an existing_cu is provided, a dwarf2_cu must not exist for this_cu
-        in per_objfile yet.  */
-      gdb_assert (per_objfile->get_cu (this_cu) == nullptr);
+      /* If an existing_cu is provided, a dwarf2_cu must not exist for
+        this_cu in per_objfile yet.  Here, CACHE doubles as a flag to
+        let us know that the CU is being scanned using the parallel
+        indexer.  This assert is avoided in this case because (1) it
+        is irrelevant, and (2) the get_cu method is not
+        thread-safe.  */
+      gdb_assert (cache != nullptr
+                 || per_objfile->get_cu (this_cu) == nullptr);
       m_new_cu.reset (new dwarf2_cu (this_cu, per_objfile));
       cu = m_new_cu.get ();
     }
@@ -6645,10 +6768,16 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu,
     gdb_assert (cu->header.abbrev_sect_off == abbrev_table->sect_off);
   else
     {
-      abbrev_section->read (objfile);
-      m_abbrev_table_holder
-       = abbrev_table::read (abbrev_section, cu->header.abbrev_sect_off);
-      abbrev_table = m_abbrev_table_holder.get ();
+      if (cache != nullptr)
+       abbrev_table = cache->find (abbrev_section,
+                                   cu->header.abbrev_sect_off);
+      if (abbrev_table == nullptr)
+       {
+         abbrev_section->read (objfile);
+         m_abbrev_table_holder
+           = abbrev_table::read (abbrev_section, cu->header.abbrev_sect_off);
+         abbrev_table = m_abbrev_table_holder.get ();
+       }
     }
 
   /* Read the top level CU/TU die.  */
@@ -6752,9 +6881,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);
 
@@ -6961,6 +7090,238 @@ create_partial_symtab (dwarf2_per_cu_data *per_cu,
 
   return pst;
 }
+\f
+
+/* An instance of this is created when scanning DWARF to create a
+   cooked index.  */
+
+class cooked_index_storage
+{
+public:
+
+  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))
+  {
+  }
+
+  DISABLE_COPY_AND_ASSIGN (cooked_index_storage);
+
+  /* Return the current abbrev cache.  */
+  abbrev_cache *get_abbrev_cache ()
+  {
+    return &m_abbrev_cache;
+  }
+
+  /* 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);
+  }
+
+  /* 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;
+  }
+
+  /* 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);
+  }
+
+  /* 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);
+  }
+
+  /* Return the mutable addrmap that is currently being created.  */
+  addrmap *get_addrmap ()
+  {
+    return m_addrmap;
+  }
+
+private:
+
+  /* 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;
+  }
+
+  /* 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;
+  }
+
+  /* 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;
+};
+
+/* An instance of this is created to index a CU.  */
+
+class cooked_indexer
+{
+public:
+
+  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))
+  {
+  }
+
+  DISABLE_COPY_AND_ASSIGN (cooked_indexer);
+
+  /* Index the given CU.  */
+  void make_index (cutu_reader *reader);
+
+private:
+
+  /* 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;
+  }
+
+  /* A helper function to scan the PC bounds of READER and record them
+     in the storage's addrmap.  */
+  void check_bounds (cutu_reader *reader);
+
+  /* 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;
+  };
+
+  /* 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;
+};
+
+
 
 /* DIE reader function for process_psymtab_comp_unit.  */
 
@@ -7008,8 +7369,11 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
 
   /* 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);
+  cu_bounds_kind
+    = dwarf2_get_pc_bounds (comp_unit_die, &best_lowpc,
+                           &best_highpc, cu,
+                           per_bfd->partial_symtabs->psymtabs_addrmap,
+                           pst);
   if (cu_bounds_kind == PC_BOUNDS_HIGH_LOW && best_lowpc < best_highpc)
     {
       CORE_ADDR low
@@ -7102,16 +7466,21 @@ 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)
+                          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);
+  if (!per_objfile->per_bfd->using_index)
+    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 == nullptr
+                      ? nullptr
+                      : storage->get_abbrev_cache ()));
 
   if (reader.comp_unit_die == nullptr)
     return;
@@ -7139,13 +7508,28 @@ 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);
+    build_type_psymtabs_reader (&reader, storage);
   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);
+    {
+      if (per_objfile->per_bfd->using_index)
+       {
+         bool nope = false;
+         if (this_cu->scanned.compare_exchange_strong (nope, true))
+           {
+             prepare_one_comp_unit (reader.cu, reader.comp_unit_die,
+                                    pretend_language);
+             gdb_assert (storage != nullptr);
+             cooked_indexer indexer (storage, this_cu,
+                                     reader.cu->per_cu->lang);
+             indexer.make_index (&reader);
+           }
+       }
+      else
+       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 ();
@@ -7154,9 +7538,8 @@ process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu,
 /* 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;
@@ -7167,6 +7550,8 @@ build_type_psymtabs_reader (const struct die_reader_specs *reader,
   struct partial_die_info *first_die;
   CORE_ADDR lowpc, highpc;
   dwarf2_psymtab *pst;
+  const gdb_byte *info_ptr = reader->info_ptr;
+  struct die_info *type_unit_die = reader->comp_unit_die;
 
   gdb_assert (per_cu->is_debug_types);
   sig_type = (struct signatured_type *) per_cu;
@@ -7182,16 +7567,26 @@ build_type_psymtabs_reader (const struct die_reader_specs *reader,
   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);
+  if (per_objfile->per_bfd->using_index)
+    {
+      gdb_assert (storage != nullptr);
+      cooked_indexer indexer (storage, per_cu, cu->per_cu->lang);
+      indexer.make_index (reader);
+    }
+  else
+    {
+      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);
+      lowpc = (CORE_ADDR) -1;
+      highpc = (CORE_ADDR) 0;
+      scan_partial_symbols (first_die, &lowpc, &highpc, 0, cu);
 
-  pst->end ();
+      pst->end ();
+    }
 }
 
 /* Struct used to sort TUs by their abbreviation table offset.  */
@@ -7230,7 +7625,8 @@ struct tu_abbrev_offset
    dwarf2_per_objfile->per_bfd->type_unit_groups.  */
 
 static void
-build_type_psymtabs (dwarf2_per_objfile *per_objfile)
+build_type_psymtabs (dwarf2_per_objfile *per_objfile,
+                    cooked_index_storage *storage)
 {
   struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
   abbrev_table_up abbrev_table;
@@ -7299,8 +7695,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);
     }
 }
 
@@ -7356,6 +7751,12 @@ build_type_psymtab_dependencies (void **slot, void *info)
   return 1;
 }
 
+struct skeleton_data
+{
+  dwarf2_per_objfile *per_objfile;
+  cooked_index_storage *storage;
+};
+
 /* Traversal function for process_skeletonless_type_unit.
    Read a TU in a DWO file and build partial symbols for it.  */
 
@@ -7363,15 +7764,16 @@ static int
 process_skeletonless_type_unit (void **slot, void *info)
 {
   struct dwo_unit *dwo_unit = (struct dwo_unit *) *slot;
-  dwarf2_per_objfile *per_objfile = (dwarf2_per_objfile *) info;
+  skeleton_data *data = (skeleton_data *) info;
 
   /* If this TU doesn't exist in the global table, add it and read it in.  */
 
-  if (per_objfile->per_bfd->signatured_types == NULL)
-    per_objfile->per_bfd->signatured_types = allocate_signatured_type_table ();
+  if (data->per_objfile->per_bfd->signatured_types == NULL)
+    data->per_objfile->per_bfd->signatured_types
+      = allocate_signatured_type_table ();
 
   signatured_type find_entry (dwo_unit->signature);
-  slot = htab_find_slot (per_objfile->per_bfd->signatured_types.get (),
+  slot = htab_find_slot (data->per_objfile->per_bfd->signatured_types.get (),
                         &find_entry, INSERT);
   /* If we've already seen this type there's nothing to do.  What's happening
      is we're doing our own version of comdat-folding here.  */
@@ -7381,15 +7783,14 @@ process_skeletonless_type_unit (void **slot, void *info)
   /* This does the job that create_all_comp_units would have done for
      this TU.  */
   signatured_type *entry
-    = add_type_unit (per_objfile, dwo_unit->signature, slot);
-  fill_in_sig_entry_from_dwo_entry (per_objfile, entry, dwo_unit);
+    = add_type_unit (data->per_objfile, dwo_unit->signature, slot);
+  fill_in_sig_entry_from_dwo_entry (data->per_objfile, entry, dwo_unit);
   *slot = entry;
 
   /* This does the job that build_type_psymtabs would have done.  */
-  cutu_reader reader (entry, per_objfile, nullptr, nullptr, false);
+  cutu_reader reader (entry, data->per_objfile, nullptr, nullptr, false);
   if (!reader.dummy_p)
-    build_type_psymtabs_reader (&reader, reader.info_ptr,
-                               reader.comp_unit_die);
+    build_type_psymtabs_reader (&reader, data->storage);
 
   return 1;
 }
@@ -7413,15 +7814,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);
+                             &data);
     }
 }
 
@@ -7461,15 +7865,12 @@ dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile)
   scoped_restore restore_reading_psyms
     = make_scoped_restore (&per_bfd->reading_partial_symbols, true);
 
-  per_bfd->info.read (objfile);
+  per_bfd->map_info_sections (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);
 
-  create_all_comp_units (per_objfile);
-  build_type_psymtabs (per_objfile);
-
   /* Create a temporary address map on a temporary obstack.  We later
      copy this to the final obstack.  */
   auto_obstack temp_obstack;
@@ -7478,20 +7879,91 @@ dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile)
     = make_scoped_restore (&per_bfd->partial_symtabs->psymtabs_addrmap,
                           addrmap_create_mutable (&temp_obstack));
 
-  for (const auto &per_cu : per_bfd->all_comp_units)
+  cooked_index_storage index_storage;
+  cooked_index_storage *index_storage_ptr
+    = per_bfd->using_index ? &index_storage : nullptr;
+  create_all_comp_units (per_objfile);
+  build_type_psymtabs (per_objfile, index_storage_ptr);
+  std::vector<std::unique_ptr<cooked_index>> indexes;
+  if (per_bfd->using_index)
     {
-      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);
+      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 ());
+
+      {
+       /* Ensure that complaints are handled correctly.  */
+       complaint_interceptor complaint_handler;
+
+       using iter_type = typeof (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,
+                                                                        false,
+                                                                        language_minimal,
+                                                                        &thread_storage);
+                                           }
+                                         catch (gdb_exception &except)
+                                           {
+                                             errors.push_back (std::move (except));
+                                           }
+                                       }
+                                     return result_type (thread_storage.release (),
+                                                         std::move (errors));
+                                   });
+
+       /* 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);
+             }
+         }
+      }
+    }
+  else
+    {
+      for (const auto &per_cu : per_bfd->all_comp_units)
+       {
+         if (!per_bfd->using_index && 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, nullptr);
+       }
     }
 
   /* This has to wait until we read the CUs, we need the list of DWOs.  */
-  process_skeletonless_type_units (per_objfile);
+  process_skeletonless_type_units (per_objfile, &index_storage);
 
   /* Now that all TUs have been processed we can fill in the dependencies.  */
-  if (per_bfd->type_unit_groups != NULL)
+  if (!per_bfd->using_index && per_bfd->type_unit_groups != NULL)
     {
       htab_traverse_noresize (per_bfd->type_unit_groups.get (),
                              build_type_psymtab_dependencies, per_objfile);
@@ -7500,14 +7972,39 @@ dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile)
   if (dwarf_read_debug > 0)
     print_tu_stats (per_objfile);
 
-  set_partial_user (per_objfile);
-
-  per_bfd->partial_symtabs->psymtabs_addrmap
-    = addrmap_create_fixed (per_bfd->partial_symtabs->psymtabs_addrmap,
-                           per_bfd->partial_symtabs->obstack ());
-  /* At this point we want to keep the address map.  */
-  save_psymtabs_addrmap.release ();
+  if (per_bfd->using_index)
+    {
+      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);
+    }
+  else
+    {
+      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 ();
+    }
   dwarf_read_debug_printf ("Done building psymtabs of %s",
                           objfile_name (objfile));
 }
@@ -7596,6 +8093,10 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
       this_cu->is_dwz = is_dwz;
       this_cu->section = section;
 
+      if (per_objfile->per_bfd->using_index)
+       this_cu->v.quick = OBSTACK_ZALLOC (&per_objfile->per_bfd->obstack,
+                                          struct dwarf2_per_cu_quick_data);
+
       info_ptr = info_ptr + this_cu->length;
       per_objfile->per_bfd->all_comp_units.push_back (std::move (this_cu));
     }
@@ -7619,8 +8120,16 @@ 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);
+    {
+      /* Pre-read the sections we'll need to construct an index.  */
+      struct objfile *objfile = per_objfile->objfile;
+      dwz->abbrev.read (objfile);
+      dwz->info.read (objfile);
+      dwz->str.read (objfile);
+      dwz->line.read (objfile);
+      read_comp_units_from_section (per_objfile, &dwz->info, &dwz->abbrev, 1,
+                                   types_htab, rcuh_kind::COMPILE);
+    }
 
   per_objfile->per_bfd->signatured_types = std::move (types_htab);
 }
@@ -7694,6 +8203,7 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
                add_partial_enumeration (pdi, cu);
              break;
            case DW_TAG_base_type:
+           case DW_TAG_generic_subrange:
            case DW_TAG_subrange_type:
              /* File scope base type definitions are added to the partial
                 symbol table.  */
@@ -7725,7 +8235,7 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
                /* 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);
+                                            cu->per_cu->lang, nullptr);
 
                if (pdi->die_parent == nullptr
                    && per_cu->unit_type == DW_UT_compile
@@ -7950,7 +8460,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
       psymbol.domain = VAR_DOMAIN;
       psymbol.aclass = LOC_BLOCK;
       psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
-      psymbol.ginfo.value.address = addr;
+      psymbol.ginfo.set_value_address (addr);
 
       if (pdi->main_subprogram && actual_name != NULL)
        set_objfile_main_name (objfile, actual_name, cu->per_cu->lang);
@@ -7995,7 +8505,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
              psymbol.domain = VAR_DOMAIN;
              psymbol.aclass = LOC_STATIC;
              psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
-             psymbol.ginfo.value.address = addr;
+             psymbol.ginfo.set_value_address (addr);
              where = psymbol_placement::GLOBAL;
            }
        }
@@ -8012,7 +8522,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
          psymbol.aclass = LOC_STATIC;
          psymbol.ginfo.set_section_index (SECT_OFF_TEXT (objfile));
          if (has_loc)
-           psymbol.ginfo.value.address = addr;
+           psymbol.ginfo.set_value_address (addr);
          where = psymbol_placement::STATIC;
        }
       break;
@@ -8020,6 +8530,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
     case DW_TAG_typedef:
     case DW_TAG_base_type:
     case DW_TAG_subrange_type:
+    case DW_TAG_generic_subrange:
       psymbol.domain = VAR_DOMAIN;
       psymbol.aclass = LOC_TYPEDEF;
       where = psymbol_placement::STATIC;
@@ -8127,9 +8638,9 @@ add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
     scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu);
 }
 
-static int
-dwarf2_ranges_read (unsigned, CORE_ADDR *, CORE_ADDR *, struct dwarf2_cu *,
-                   dwarf2_psymtab *, dwarf_tag);
+static int dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
+                              CORE_ADDR *high_return, struct dwarf2_cu *cu,
+                              addrmap *map, void *datum, dwarf_tag tag);
 
 /* Read a partial die corresponding to a subprogram or an inlined
    subprogram and create a partial symbol for that subprogram.
@@ -8183,6 +8694,9 @@ add_partial_subprogram (struct partial_die_info *pdi,
       if (pdi->has_range_info
          && dwarf2_ranges_read (pdi->ranges_offset, &pdi->lowpc, &pdi->highpc,
                                 cu,
+                                (set_addrmap
+                                 ? cu->per_objfile->per_bfd->partial_symtabs->psymtabs_addrmap
+                                 : nullptr),
                                 set_addrmap ? cu->per_cu->v.psymtab : nullptr,
                                 pdi->tag))
        {
@@ -8310,12 +8824,15 @@ skip_children (const struct die_reader_specs *reader, const gdb_byte *info_ptr)
 /* Scan the debug information for CU starting at INFO_PTR in buffer BUFFER.
    INFO_PTR should point just after the initial uleb128 of a DIE, and the
    abbrev corresponding to that skipped uleb128 should be passed in
-   ABBREV.  Returns a pointer to this DIE's sibling, skipping any
-   children.  */
+   ABBREV.
+   
+   If DO_SKIP_CHILDREN is true, or if the DIE has no children, this
+   returns a pointer to this DIE's sibling, skipping any children.
+   Otherwise, returns a pointer to the DIE's first child.  */
 
 static const gdb_byte *
 skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
-             const struct abbrev_info *abbrev)
+             const struct abbrev_info *abbrev, bool do_skip_children)
 {
   unsigned int bytes_read;
   struct attribute attr;
@@ -8325,10 +8842,29 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
   const gdb_byte *buffer_end = reader->buffer_end;
   unsigned int form, i;
 
+  if (do_skip_children && abbrev->sibling_offset != (unsigned short) -1)
+    {
+      /* We only handle DW_FORM_ref4 here.  */
+      const gdb_byte *sibling_data = info_ptr + abbrev->sibling_offset;
+      unsigned int offset = read_4_bytes (abfd, sibling_data);
+      const gdb_byte *sibling_ptr
+       = buffer + to_underlying (cu->header.sect_off) + offset;
+      if (sibling_ptr >= info_ptr && sibling_ptr < reader->buffer_end)
+       return sibling_ptr;
+      /* Fall through to the slow way.  */
+    }
+  else if (abbrev->size_if_constant != 0)
+    {
+      info_ptr += abbrev->size_if_constant;
+      if (do_skip_children && abbrev->has_children)
+       return skip_children (reader, info_ptr);
+      return info_ptr;
+    }
+
   for (i = 0; i < abbrev->num_attrs; i++)
     {
       /* The only abbrev we care about is DW_AT_sibling.  */
-      if (abbrev->attrs[i].name == DW_AT_sibling)
+      if (do_skip_children && abbrev->attrs[i].name == DW_AT_sibling)
        {
          read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
          if (attr.form == DW_FORM_ref_addr)
@@ -8445,7 +8981,7 @@ 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;
@@ -8918,7 +9454,7 @@ fixup_go_packaging (struct dwarf2_cu *cu)
         e.g., "main" finds the "main" module and not C's main().  */
       sym->set_domain (STRUCT_DOMAIN);
       sym->set_aclass_index (LOC_TYPEDEF);
-      SYMBOL_TYPE (sym) = type;
+      sym->set_type (type);
 
       add_symbol_to_list (sym, cu->get_builder ()->get_global_symbols ());
     }
@@ -9456,7 +9992,8 @@ process_full_comp_unit (dwarf2_cu *cu, enum language pretend_language)
   get_scope_pc_bounds (cu->dies, &lowpc, &highpc, cu);
 
   addr = gdbarch_adjust_dwarf2_addr (gdbarch, highpc + baseaddr);
-  static_block = cu->get_builder ()->end_symtab_get_static_block (addr, 0, 1);
+  static_block
+    = cu->get_builder ()->end_compunit_symtab_get_static_block (addr, 0, 1);
 
   /* If the comp unit has DW_AT_ranges, it may have discontiguous ranges.
      Also, DW_AT_ranges may record ranges not belonging to any child DIEs
@@ -9465,9 +10002,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)
     {
@@ -9694,6 +10230,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
     case DW_TAG_interface_type:
     case DW_TAG_structure_type:
     case DW_TAG_union_type:
+    case DW_TAG_namelist:
       process_structure_scope (die, cu);
       break;
     case DW_TAG_enumeration_type:
@@ -9721,6 +10258,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.  */
@@ -10622,7 +11160,8 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
 
   file_and_directory &fnd = find_file_and_directory (die, cu);
 
-  cu->start_symtab (fnd.get_name (), fnd.intern_comp_dir (objfile), lowpc);
+  cu->start_compunit_symtab (fnd.get_name (), fnd.intern_comp_dir (objfile),
+                            lowpc);
 
   gdb_assert (per_objfile->sym_cu == nullptr);
   scoped_restore restore_sym_cu
@@ -10715,7 +11254,7 @@ 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);
@@ -10736,7 +11275,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)
@@ -12206,69 +12745,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);
     }
 }
 
@@ -12296,8 +12813,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);
@@ -12324,8 +12841,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;
@@ -12336,20 +12853,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);
     }
 }
 
@@ -12359,7 +12875,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;
@@ -12371,45 +12888,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);
     }
 }
 
@@ -12419,7 +12920,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;
@@ -12431,40 +12933,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);
     }
 }
 
@@ -12591,7 +13080,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);
@@ -12621,10 +13110,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 ());
     }
 
@@ -13075,7 +13564,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);
@@ -13248,7 +13737,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
@@ -13310,6 +13799,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
@@ -13473,6 +13967,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;
@@ -13488,12 +13986,25 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
          else
            call_site->target.set_loc_physname (target_physname);
        }
+      else if (ranges_attr != nullptr && ranges_attr->form_is_unsigned ())
+       {
+         ULONGEST ranges_offset = (ranges_attr->as_unsigned ()
+                                   + target_cu->gnu_ranges_base);
+         std::vector<CORE_ADDR> addresses;
+         dwarf2_ranges_read_low_addrs (ranges_offset, target_cu,
+                                       target_die->tag, addresses);
+         CORE_ADDR *saved = XOBNEWVAR (&objfile->objfile_obstack, CORE_ADDR,
+                                       addresses.size ());
+         std::copy (addresses.begin (), addresses.end (), saved);
+         call_site->target.set_loc_array (addresses.size (), saved);
+       }
       else
        {
          CORE_ADDR lowpc;
 
          /* DW_AT_entry_pc should be preferred.  */
-         if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu, NULL)
+         if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu,
+                                   nullptr, nullptr)
              <= PC_BOUNDS_INVALID)
            complaint (_("DW_AT_call_target target DIE has invalid "
                         "low pc, for referencing DIE %s [in module %s]"),
@@ -13994,15 +14505,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;
@@ -14013,7 +14524,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;
@@ -14024,8 +14535,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
@@ -14061,6 +14571,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.  */
@@ -14068,7 +14592,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;
@@ -14111,8 +14635,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;
@@ -14155,7 +14679,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);
@@ -14192,7 +14717,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;
@@ -14556,8 +15082,21 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
 
   fp = &new_field->field;
 
-  if (die->tag == DW_TAG_member && ! die_is_declaration (die, cu))
-    {
+  if ((die->tag == DW_TAG_member || die->tag == DW_TAG_namelist_item)
+      && !die_is_declaration (die, cu))
+    {
+      if (die->tag == DW_TAG_namelist_item)
+        {
+         /* Typically, DW_TAG_namelist_item are references to namelist items.
+            If so, follow that reference.  */
+         struct attribute *attr1 = dwarf2_attr (die, DW_AT_namelist_item, cu);
+         struct die_info *item_die = nullptr;
+         struct dwarf2_cu *item_cu = cu;
+          if (attr1->form_is_ref ())
+           item_die = follow_die_ref (die, attr1, &item_cu);
+         if (item_die != nullptr)
+           die = item_die;
+        }
       /* Data member other than a C++ static data member.  */
 
       /* Get type of field.  */
@@ -15615,6 +16154,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);
@@ -15817,7 +16360,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
@@ -15860,8 +16404,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)
@@ -16631,7 +17177,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);
 
@@ -16964,7 +17511,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);
     }
 }
 
@@ -18804,11 +19351,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);
     }
 
@@ -18910,11 +19457,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);
     }
 
@@ -18922,6 +19469,841 @@ read_full_die (const struct die_reader_specs *reader,
 }
 \f
 
+void
+cooked_indexer::check_bounds (cutu_reader *reader)
+{
+  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)
+    {
+      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);
+
+      cu->per_cu->addresses_seen = true;
+    }
+}
+
+/* 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_structure_type:
+    case DW_TAG_union_type:
+    case DW_TAG_variable:
+    case DW_TAG_subprogram:
+      return true;
+
+    default:
+      return false;
+    }
+}
+
+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)
+{
+  /* 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;
+
+  dwarf2_per_cu_data *per_cu
+    = dwarf2_find_containing_comp_unit (sect_off, is_dwz,
+                                       per_objfile->per_bfd);
+
+  /* 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)
+    {
+      bool nope = false;
+      if (!per_cu->scanned.compare_exchange_strong (nope, true))
+       return nullptr;
+    }
+  if (per_cu == m_per_cu)
+    return reader;
+
+  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 ());
+
+      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));
+    }
+
+  if (result->dummy_p || !result->comp_unit_die->has_children)
+    return nullptr;
+
+  if (for_scanning)
+    check_bounds (result);
+
+  return result;
+}
+
+const gdb_byte *
+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);
+      if (attr.requires_reprocessing_p ())
+       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 (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.  */
+             break;
+
+           default:
+             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.  */
+         if (*linkage_name == nullptr)
+           *linkage_name = attr.as_string ();
+         break;
+
+       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_sibling:
+         if (sibling_offset != nullptr)
+           *sibling_offset = attr.get_ref_die_offset ();
+         break;
+
+       case DW_AT_specification:
+       case DW_AT_abstract_origin:
+       case DW_AT_extension:
+         origin_offset = attr.get_ref_die_offset ();
+         origin_is_dwz = attr.form == DW_FORM_GNU_ref_alt;
+         break;
+
+       case DW_AT_external:
+         if (attr.as_boolean ())
+           *flags &= ~IS_STATIC;
+         break;
+
+       case DW_AT_enum_class:
+         if (attr.as_boolean ())
+           *flags |= IS_ENUM_CLASS;
+         break;
+
+       case DW_AT_low_pc:
+         low_pc = attr.as_address ();
+         break;
+
+       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_location:
+         if (!scanning_per_cu->addresses_seen && attr.form_is_block ())
+           {
+             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_ranges:
+         if (!scanning_per_cu->addresses_seen)
+           {
+             /* Offset in the .debug_ranges or .debug_rnglist section
+                (depending on DWARF version).  */
+             ULONGEST ranges_offset = attr.as_unsigned ();
+
+             /* See dwarf2_cu::gnu_ranges_base's doc for why we might
+                want to add this value.  */
+             ranges_offset += reader->cu->gnu_ranges_base;
+
+             CORE_ADDR lowpc, highpc;
+             dwarf2_ranges_read (ranges_offset, &lowpc, &highpc, reader->cu,
+                                 m_index_storage->get_addrmap (),
+                                 scanning_per_cu, abbrev->tag);
+           }
+         break;
+       }
+    }
+
+  /* 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);
+       }
+    }
+
+  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;
+
+           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;
+
+           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;
+           }
+
+         if (sibling != sect_offset (0))
+           {
+             const gdb_byte *sibling_ptr
+               = reader->buffer + to_underlying (sibling);
+
+             if (sibling_ptr < info_ptr)
+               complaint (_("DW_AT_sibling points backwards"));
+             else if (sibling_ptr > reader->buffer_end)
+               reader->die_section->overflow_complaint ();
+             else
+               info_ptr = sibling_ptr;
+           }
+         else
+           info_ptr = skip_children (reader, info_ptr);
+       }
+    }
+
+  return info_ptr;
+}
+
+void
+cooked_indexer::make_index (cutu_reader *reader)
+{
+  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);
+
+  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);
+    }
+}
+
+/* An implementation of quick_symbol_functions for the cooked DWARF
+   index.  */
+
+struct cooked_index_functions : public dwarf2_base_index_functions
+{
+  struct compunit_symtab *find_pc_sect_compunit_symtab
+    (struct objfile *objfile, struct bound_minimal_symbol msymbol,
+     CORE_ADDR pc, struct obj_section *section, int warn_if_readin) override;
+
+  struct compunit_symtab *find_compunit_symtab_by_address
+    (struct objfile *objfile, CORE_ADDR address) override;
+
+  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;
+
+  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;
+
+  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);
+  }
+};
+
+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;
+
+  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;
+
+  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));
+
+  compunit_symtab *result = (recursively_find_pc_sect_compunit_symtab
+                            (dw2_instantiate_symtab (per_cu, per_objfile,
+                                                     false),
+                             pc));
+  gdb_assert (result != nullptr);
+  return result;
+}
+
+struct compunit_symtab *
+cooked_index_functions::find_compunit_symtab_by_address
+     (struct objfile *objfile, CORE_ADDR address)
+{
+  if (objfile->sect_index_data == -1)
+    return nullptr;
+
+  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+  if (per_objfile->per_bfd->cooked_index_table == nullptr)
+    return nullptr;
+
+  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;
+
+  return dw2_instantiate_symtab (per_cu, per_objfile, false);
+}
+
+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 (const cooked_index_entry *entry
+        : per_objfile->per_bfd->cooked_index_table->all_entries ())
+    {
+      if (entry->parent_entry != nullptr)
+       continue;
+
+      if (!entry->matches (search_flags)
+         || !entry->matches (domain))
+       continue;
+
+      if (name_match (entry->canonical, lookup_name, nullptr))
+       dw2_instantiate_symtab (entry->per_cu, per_objfile, false);
+    }
+}
+
+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)
+{
+  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
+  if (per_objfile->per_bfd->cooked_index_table == nullptr)
+    return true;
+
+  dw_expand_symtabs_matching_file_matcher (per_objfile, file_matcher);
+
+  /* This invariant is documented in quick-functions.h.  */
+  gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr);
+  if (lookup_name == nullptr)
+    {
+      for (dwarf2_per_cu_data *per_cu
+            : all_comp_units_range (per_objfile->per_bfd))
+       {
+         QUIT;
+
+         if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
+                                               file_matcher,
+                                               expansion_notify))
+           return false;
+       }
+      return true;
+    }
+
+  lookup_name_info lookup_name_without_params
+    = lookup_name->make_ignore_params ();
+  bool completing = lookup_name->completion_mode ();
+
+  /* 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
+  };
+
+  for (enum language lang : unique_styles)
+    {
+      std::vector<gdb::string_view> name_vec
+       = lookup_name_without_params.split_name (lang);
+
+      for (const cooked_index_entry *entry
+          : per_objfile->per_bfd->cooked_index_table->find (name_vec.back (),
+                                                            completing))
+       {
+         /* No need to consider symbols from expanded CUs.  */
+         if (per_objfile->symtab_set_p (entry->per_cu))
+           continue;
+
+         /* If file-matching was done, we don't need to consider
+            symbols from unmarked CUs.  */
+         if (file_matcher != nullptr && !entry->per_cu->v.quick->mark)
+           continue;
+
+         /* See if the symbol matches the type filter.  */
+         if (!entry->matches (search_flags)
+             || !entry->matches (domain)
+             || !entry->matches (kind))
+           continue;
+
+         /* 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
+           {
+             auto_obstack temp_storage;
+             const char *full_name = entry->full_name (&temp_storage);
+             if (!symbol_matcher (full_name))
+               continue;
+           }
+
+         if (!dw2_expand_symtabs_matching_one (entry->per_cu, per_objfile,
+                                               file_matcher,
+                                               expansion_notify))
+           return false;
+       }
+    }
+
+  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
+
 /* Returns nonzero if TAG represents a type that we might generate a partial
    symbol for.  */
 
@@ -18953,6 +20335,7 @@ is_type_tag_for_partial (int tag, enum language lang)
     case DW_TAG_enumeration_type:
     case DW_TAG_structure_type:
     case DW_TAG_subrange_type:
+    case DW_TAG_generic_subrange:
     case DW_TAG_typedef:
     case DW_TAG_union_type:
       return 1;
@@ -19086,6 +20469,7 @@ load_partial_dies (const struct die_reader_specs *reader,
          && ((pdi.tag == DW_TAG_typedef && !pdi.has_children)
              || pdi.tag == DW_TAG_base_type
              || pdi.tag == DW_TAG_array_type
+             || pdi.tag == DW_TAG_generic_subrange
              || pdi.tag == DW_TAG_subrange_type))
        {
          if (building_psymtab && pdi.raw_name != NULL)
@@ -20862,7 +22246,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.  */
@@ -20880,6 +22264,7 @@ public:
   {
     record_line (false);
     m_discriminator = 0;
+    m_flags &= ~LEF_PROLOGUE_END;
   }
 
   /* Handle DW_LNE_end_sequence.  */
@@ -20888,6 +22273,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)
@@ -20921,7 +22312,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.  */
@@ -20936,9 +22327,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.  */
@@ -20979,6 +22370,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
@@ -21068,21 +22460,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.
@@ -21099,13 +22492,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
@@ -21113,13 +22506,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 ();
@@ -21153,7 +22548,8 @@ lnp_state_machine::record_line (bool end_sequence)
            = 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)
+              && ((m_flags & LEF_IS_STMT) == 0)
+              && m_stmt_at_address)
              || (!end_sequence && m_line == 0));
 
          if ((file_changed && !ignore_this_line) || end_sequence)
@@ -21164,7 +22560,9 @@ lnp_state_machine::record_line (bool end_sequence)
 
          if (!end_sequence && !ignore_this_line)
            {
-             bool is_stmt = producer_is_codewarrior (m_cu) || m_is_stmt;
+             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,
@@ -21173,7 +22571,7 @@ lnp_state_machine::record_line (bool end_sequence)
                  buildsym_compunit *builder = m_cu->get_builder ();
                  dwarf_record_line_1 (m_gdbarch,
                                       builder->get_current_subfile (),
-                                      m_line, m_address, is_stmt,
+                                      m_line, m_address, lte_flags,
                                       m_currently_recording_lines ? m_cu : nullptr);
                }
              m_last_subfile = m_cu->get_builder ()->get_current_subfile ();
@@ -21182,14 +22580,14 @@ lnp_state_machine::record_line (bool end_sequence)
        }
     }
 
-  /* 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,
@@ -21207,7 +22605,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;
@@ -21435,6 +22835,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.  */
@@ -21624,19 +23027,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));
+           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;
        }
@@ -21720,14 +23120,14 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
       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,
@@ -21759,12 +23159,12 @@ 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);
+             sym->set_value_address (addr);
              sym->set_aclass_index (LOC_LABEL);
            }
          else
            sym->set_aclass_index (LOC_OPTIMIZED_OUT);
-         SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_core_addr;
+         sym->set_type (objfile_type (objfile)->builtin_core_addr);
          sym->set_domain (LABEL_DOMAIN);
          add_symbol_to_list (sym, cu->list_in_scope);
          break;
@@ -21794,7 +23194,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
          /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
             finish_block.  */
          sym->set_aclass_index (LOC_BLOCK);
-         SYMBOL_INLINED (sym) = 1;
+         sym->set_is_inlined (1);
          list_to_add = cu->list_in_scope;
          break;
        case DW_TAG_template_value_param:
@@ -21806,8 +23206,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
@@ -21845,7 +23245,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
                attr2 = NULL;
 
              if (sym->aclass () == LOC_STATIC
-                 && SYMBOL_VALUE_ADDRESS (sym) == 0
+                 && sym->value_address () == 0
                  && !per_objfile->per_bfd->has_section_at_zero)
                {
                  /* When a static variable is eliminated by the linker,
@@ -21963,9 +23363,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:
-         sym->set_aclass_index (LOC_TYPEDEF);
-         sym->set_domain (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
@@ -21994,8 +23402,8 @@ 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 ());
                  }
              }
          }
@@ -22008,6 +23416,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
        case DW_TAG_array_type:
        case DW_TAG_base_type:
        case DW_TAG_subrange_type:
+       case DW_TAG_generic_subrange:
          sym->set_aclass_index (LOC_TYPEDEF);
          sym->set_domain (VAR_DOMAIN);
          list_to_add = cu->list_in_scope;
@@ -22230,7 +23639,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);
@@ -22241,13 +23650,13 @@ dwarf2_const_value (const struct attribute *attr, struct symbol *sym,
       sym->set_aclass_index (dwarf2_locexpr_index);
     }
   else if (bytes != NULL)
-     {
-      SYMBOL_VALUE_BYTES (sym) = bytes;
+    {
+      sym->set_value_bytes (bytes);
       sym->set_aclass_index (LOC_CONST_BYTES);
     }
   else
     {
-      SYMBOL_VALUE (sym) = value;
+      sym->set_value_longest (value);
       sym->set_aclass_index (LOC_CONST);
     }
 }
@@ -22501,6 +23910,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;
@@ -22902,6 +24312,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;
 
@@ -22926,6 +24337,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
@@ -22999,82 +24411,82 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
 {
   unsigned int i;
 
-  fprintf_unfiltered (f, "%*sDie: %s (abbrev %d, offset %s)\n",
-                     indent, "",
-                     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)
-    fprintf_unfiltered (f, "%*s  parent at offset: %s\n",
-                       indent, "",
-                       sect_offset_str (die->parent->sect_off));
+    gdb_printf (f, "%*s  parent at offset: %s\n",
+               indent, "",
+               sect_offset_str (die->parent->sect_off));
 
-  fprintf_unfiltered (f, "%*s  has children: %s\n",
-                     indent, "",
-                     dwarf_bool_name (die->child != NULL));
+  gdb_printf (f, "%*s  has children: %s\n",
+             indent, "",
+             dwarf_bool_name (die->child != NULL));
 
-  fprintf_unfiltered (f, "%*s  attributes:\n", indent, "");
+  gdb_printf (f, "%*s  attributes:\n", indent, "");
 
   for (i = 0; i < die->num_attrs; ++i)
     {
-      fprintf_unfiltered (f, "%*s    %s (%s) ",
-                         indent, "",
-                         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:
@@ -23082,37 +24494,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");
     }
 }
 
@@ -23136,16 +24548,16 @@ dump_die_1 (struct ui_file *f, int level, int max_level, struct die_info *die)
 
   if (die->child != NULL)
     {
-      fprintf_unfiltered (f, "%*s  Children:", indent, "");
+      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");
        }
     }
 
@@ -24782,6 +26194,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)
     {
@@ -24876,9 +26297,9 @@ static void
 show_check_physname (struct ui_file *file, int from_tty,
                     struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file,
-                   _("Whether to check \"physname\" is %s.\n"),
-                   value);
+  gdb_printf (file,
+             _("Whether to check \"physname\" is %s.\n"),
+             value);
 }
 
 void _initialize_dwarf2_read ();