diff --git a/gdb/dwarf2/read-debug-names.c b/gdb/dwarf2/read-debug-names.c
index c6b70550f81..1e53c246b91 100644
--- a/gdb/dwarf2/read-debug-names.c
+++ b/gdb/dwarf2/read-debug-names.c
@@ -20,6 +20,7 @@
 #include "defs.h"
 #include "read-debug-names.h"
 #include "dwarf2/aranges.h"
+#include "dwarf2/cooked-index.h"
 
 #include "complaints.h"
 #include "cp-support.h"
@@ -28,22 +29,62 @@
 #include "read.h"
 #include "stringify.h"
 
-/* A description of the mapped .debug_names.
-   Uninitialized map has CU_COUNT 0.  */
+/* This is just like cooked_index_functions, but overrides a single
+   method so the test suite can distinguish the .debug_names case from
+   the ordinary case.  */
+struct dwarf2_debug_names_index : public cooked_index_functions
+{
+  /* This dumps minimal information about .debug_names.  It is called
+     via "mt print objfiles".  The gdb.dwarf2/gdb-index.exp testcase
+     uses this to verify that .debug_names has been loaded.  */
+  void dump (struct objfile *objfile) override
+  {
+    gdb_printf (".debug_names: exists\n");
+    /* This could call the superclass method if that's useful.  */
+  }
+};
+
+/* This is like a cooked index, but as it has been ingested from
+   .debug_names, it can't be used to write out an index.  */
+class debug_names_index : public cooked_index
+{
+public:
+
+  using cooked_index::cooked_index;
+
+  cooked_index *index_for_writing () override
+  { return nullptr; }
+
+  quick_symbol_functions_up make_quick_functions () const override
+  { return quick_symbol_functions_up (new dwarf2_debug_names_index); }
+};
+
+/* A description of the mapped .debug_names.  */
 
-struct mapped_debug_names final : public mapped_index_base
+struct mapped_debug_names_reader
 {
-  bfd_endian dwarf5_byte_order;
-  bool dwarf5_is_dwarf64;
-  bool augmentation_is_gdb;
-  uint8_t offset_size;
+  const gdb_byte *scan_one_entry (const char *name,
+				  const gdb_byte *entry,
+				  cooked_index_entry **result,
+				  std::optional<ULONGEST> &parent);
+  void scan_entries (uint32_t index, const char *name, const gdb_byte *entry);
+  void scan_all_names ();
+
+  dwarf2_per_objfile *per_objfile = nullptr;
+  bfd *abfd = nullptr;
+  bfd_endian dwarf5_byte_order {};
+  bool dwarf5_is_dwarf64 = false;
+  bool augmentation_is_gdb = false;
+  uint8_t offset_size = 0;
   uint32_t cu_count = 0;
-  uint32_t tu_count, bucket_count, name_count;
-  const gdb_byte *cu_table_reordered, *tu_table_reordered;
-  const uint32_t *bucket_table_reordered, *hash_table_reordered;
-  const gdb_byte *name_table_string_offs_reordered;
-  const gdb_byte *name_table_entry_offs_reordered;
-  const gdb_byte *entry_pool;
+  uint32_t tu_count = 0, bucket_count = 0, name_count = 0;
+  const gdb_byte *cu_table_reordered = nullptr;
+  const gdb_byte *tu_table_reordered = nullptr;
+  const uint32_t *bucket_table_reordered = nullptr;
+  const uint32_t *hash_table_reordered = nullptr;
+  const gdb_byte *name_table_string_offs_reordered = nullptr;
+  const gdb_byte *name_table_entry_offs_reordered = nullptr;
+  const gdb_byte *entry_pool = nullptr;
 
   struct index_val
   {
@@ -64,41 +105,250 @@ struct mapped_debug_names final : public mapped_index_base
 
   std::unordered_map<ULONGEST, index_val> abbrev_map;
 
-  const char *namei_to_name
-    (uint32_t namei, dwarf2_per_objfile *per_objfile) const;
+  std::unique_ptr<cooked_index_shard> shard;
+  std::vector<std::pair<cooked_index_entry *, ULONGEST>> needs_parent;
+  std::vector<std::vector<cooked_index_entry *>> all_entries;
+};
 
-  /* Implementation of the mapped_index_base virtual interface, for
-     the name_components cache.  */
+/* Scan a single entry from the entries table.  Set *RESULT and PARENT
+   (if needed) and return the updated pointer on success, or return
+   nullptr on error, or at the end of the table.  */
 
-  const char *symbol_name_at
-    (offset_type idx, dwarf2_per_objfile *per_objfile) const override
-  { return namei_to_name (idx, per_objfile); }
+const gdb_byte *
+mapped_debug_names_reader::scan_one_entry (const char *name,
+					   const gdb_byte *entry,
+					   cooked_index_entry **result,
+					   std::optional<ULONGEST> &parent)
+{
+  unsigned int bytes_read;
+  const ULONGEST abbrev = read_unsigned_leb128 (abfd, entry, &bytes_read);
+  entry += bytes_read;
+  if (abbrev == 0)
+    return nullptr;
 
-  size_t symbol_name_count () const override
-  { return this->name_count; }
+  const auto indexval_it = abbrev_map.find (abbrev);
+  if (indexval_it == abbrev_map.cend ())
+    {
+      complaint (_("Wrong .debug_names undefined abbrev code %s "
+		   "[in module %s]"),
+		 pulongest (abbrev), bfd_get_filename (abfd));
+      return nullptr;
+    }
 
-  quick_symbol_functions_up make_quick_functions () const override;
-};
+  const auto &indexval = indexval_it->second;
+  cooked_index_flag flags = 0;
+  sect_offset die_offset {};
+  enum language lang = language_unknown;
+  dwarf2_per_cu_data *per_cu = nullptr;
+  for (const auto &attr : indexval.attr_vec)
+    {
+      ULONGEST ull;
+      switch (attr.form)
+	{
+	case DW_FORM_implicit_const:
+	  ull = attr.implicit_const;
+	  break;
+	case DW_FORM_flag_present:
+	  ull = 1;
+	  break;
+	case DW_FORM_udata:
+	  ull = read_unsigned_leb128 (abfd, entry, &bytes_read);
+	  entry += bytes_read;
+	  break;
+	case DW_FORM_ref4:
+	  ull = read_4_bytes (abfd, entry);
+	  entry += 4;
+	  break;
+	case DW_FORM_ref8:
+	  ull = read_8_bytes (abfd, entry);
+	  entry += 8;
+	  break;
+	case DW_FORM_ref_sig8:
+	  ull = read_8_bytes (abfd, entry);
+	  entry += 8;
+	  break;
+	default:
+	  complaint (_("Unsupported .debug_names form %s [in module %s]"),
+		     dwarf_form_name (attr.form),
+		     bfd_get_filename (abfd));
+	  return nullptr;
+	}
+      switch (attr.dw_idx)
+	{
+	case DW_IDX_compile_unit:
+	  {
+	    /* Don't crash on bad data.  */
+	    if (ull >= per_objfile->per_bfd->all_comp_units.size ())
+	      {
+		complaint (_(".debug_names entry has bad CU index %s"
+			     " [in module %s]"),
+			   pulongest (ull),
+			   bfd_get_filename (abfd));
+		continue;
+	      }
+	  }
+	  per_cu = per_objfile->per_bfd->get_cu (ull);
+	  break;
+	case DW_IDX_type_unit:
+	  /* Don't crash on bad data.  */
+	  if (ull >= per_objfile->per_bfd->all_type_units.size ())
+	    {
+	      complaint (_(".debug_names entry has bad TU index %s"
+			   " [in module %s]"),
+			 pulongest (ull),
+			 bfd_get_filename (abfd));
+	      continue;
+	    }
+	  {
+	    int nr_cus = per_objfile->per_bfd->all_comp_units.size ();
+	    per_cu = per_objfile->per_bfd->get_cu (nr_cus + ull);
+	  }
+	  break;
+	case DW_IDX_die_offset:
+	  die_offset = sect_offset (ull);
+	  /* In a per-CU index (as opposed to a per-module index), index
+	     entries without CU attribute implicitly refer to the single CU.  */
+	  if (per_cu == NULL)
+	    per_cu = per_objfile->per_bfd->get_cu (0);
+	  break;
+	case DW_IDX_parent:
+	  parent = ull;
+	  break;
+	case DW_IDX_GNU_internal:
+	  if (augmentation_is_gdb && ull != 0)
+	    flags |= IS_STATIC;
+	  break;
+	case DW_IDX_GNU_main:
+	  if (augmentation_is_gdb && ull != 0)
+	    flags |= IS_MAIN;
+	  break;
+	case DW_IDX_GNU_language:
+	  if (augmentation_is_gdb)
+	    lang = dwarf_lang_to_enum_language (ull);
+	  break;
+	case DW_IDX_GNU_linkage_name:
+	  if (augmentation_is_gdb && ull != 0)
+	    flags |= IS_LINKAGE;
+	  break;
+	}
+    }
+
+  *result = shard->add (die_offset, (dwarf_tag) indexval.dwarf_tag, flags,
+			lang, name, nullptr, per_cu);
+  return entry;
+}
+
+/* Scan all the entries for NAME, at name slot INDEX.  */
+
+void
+mapped_debug_names_reader::scan_entries (uint32_t index,
+					 const char *name,
+					 const gdb_byte *entry)
+{
+  std::vector<cooked_index_entry *> these_entries;
+  
+  while (true)
+    {
+      std::optional<ULONGEST> parent;
+      cooked_index_entry *this_entry;
+      entry = scan_one_entry (name, entry, &this_entry, parent);
+
+      if (entry == nullptr)
+	break;
+
+      these_entries.push_back (this_entry);
+      if (parent.has_value ())
+	needs_parent.emplace_back (this_entry, *parent);
+    }
 
-struct dwarf2_debug_names_index : public dwarf2_base_index_functions
+  all_entries[index] = std::move (these_entries);
+}
+
+/* Scan the name table and create all the entries.  */
+
+void
+mapped_debug_names_reader::scan_all_names ()
 {
-  void dump (struct objfile *objfile) 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;
+  all_entries.resize (name_count);
+
+  /* In the first pass, create all the entries.  */
+  for (uint32_t i = 0; i < name_count; ++i)
+    {
+      const ULONGEST namei_string_offs
+	= extract_unsigned_integer ((name_table_string_offs_reordered
+				     + i * offset_size),
+				    offset_size, dwarf5_byte_order);
+      const char *name = read_indirect_string_at_offset (per_objfile,
+							 namei_string_offs);
+
+      const ULONGEST namei_entry_offs
+	= extract_unsigned_integer ((name_table_entry_offs_reordered
+				     + i * offset_size),
+				    offset_size, dwarf5_byte_order);
+      const gdb_byte *entry = entry_pool + namei_entry_offs;
+
+      scan_entries (i, name, entry);
+    }
+
+  /* Now update the parent pointers for all entries.  This has to be
+     done in a funny way because DWARF specifies the parent entry to
+     point to a name -- but we don't know which specific one.  */
+  for (auto [entry, parent_idx] : needs_parent)
+    {
+      /* Name entries are indexed from 1 in DWARF.  */
+      std::vector<cooked_index_entry *> &entries = all_entries[parent_idx - 1];
+      for (const auto &parent : entries)
+	if (parent->lang == entry->lang)
+	  {
+	    entry->parent_entry = parent;
+	    break;
+	  }
+    }
+}
+
+/* A reader for .debug_names.  */
+
+struct cooked_index_debug_names : public cooked_index_worker
+{
+  cooked_index_debug_names (dwarf2_per_objfile *per_objfile,
+			    mapped_debug_names_reader &&map)
+    : cooked_index_worker (per_objfile),
+      m_map (std::move (map))
+  { }
+
+  void do_reading () override;
+
+  mapped_debug_names_reader m_map;
 };
 
-quick_symbol_functions_up
-mapped_debug_names::make_quick_functions () const
+void
+cooked_index_debug_names::do_reading ()
 {
-  return quick_symbol_functions_up (new dwarf2_debug_names_index);
+  complaint_interceptor complaint_handler;
+  std::vector<gdb_exception> exceptions;
+  try
+    {
+      m_map.scan_all_names ();
+    }
+  catch (const gdb_exception &exc)
+    {
+      exceptions.push_back (std::move (exc));
+    }
+
+  dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd;
+  per_bfd->quick_file_names_table
+    = create_quick_file_names_table (per_bfd->all_units.size ());
+  m_results.emplace_back (nullptr,
+			  complaint_handler.release (),
+			  std::move (exceptions));
+  std::vector<std::unique_ptr<cooked_index_shard>> indexes;
+  indexes.push_back (std::move (m_map.shard));
+  cooked_index *table
+    = (gdb::checked_static_cast<cooked_index *>
+       (per_bfd->index_table.get ()));
+  table->set_contents (std::move (indexes));
+
+  bfd_thread_cleanup ();
 }
 
 /* Check the signatured type hash table from .debug_names.  */
@@ -106,7 +356,7 @@ mapped_debug_names::make_quick_functions () const
 static bool
 check_signatured_type_table_from_debug_names
   (dwarf2_per_objfile *per_objfile,
-   const mapped_debug_names &map,
+   const mapped_debug_names_reader &map,
    struct dwarf2_section_info *section)
 {
   struct objfile *objfile = per_objfile->objfile;
@@ -143,28 +393,18 @@ check_signatured_type_table_from_debug_names
   return true;
 }
 
-/* Read the address map data from DWARF-5 .debug_aranges, and use it to
-   populate the index_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;
-
-  addrmap_mutable mutable_map;
-
-  section->read (per_objfile->objfile);
-  if (read_addrmap_from_aranges (per_objfile, section, &mutable_map))
-    per_bfd->index_addrmap
-      = new (&per_bfd->obstack) addrmap_fixed (&per_bfd->obstack,
-					       &mutable_map);
-}
-
 /* DWARF-5 debug_names reader.  */
 
-/* DWARF-5 augmentation string for GDB's DW_IDX_GNU_* extension.  */
-static const gdb_byte dwarf5_augmentation[] = { 'G', 'D', 'B', 0 };
+/* The old, no-longer-supported GDB augmentation.  */
+static const gdb_byte old_gdb_augmentation[]
+     = { 'G', 'D', 'B', 0 };
+static_assert (sizeof (old_gdb_augmentation) % 4 == 0);
+
+/* DWARF-5 augmentation string for GDB's DW_IDX_GNU_* extension.  This
+   must have a size that is a multiple of 4.  */
+static const gdb_byte dwarf5_augmentation[]
+     = { 'G', 'D', 'B', '2', 0, 0, 0, 0 };
+static_assert (sizeof (dwarf5_augmentation) % 4 == 0);
 
 /* A helper function that reads the .debug_names section in SECTION
    and fills in MAP.  FILENAME is the name of the file containing the
@@ -173,11 +413,13 @@ static const gdb_byte dwarf5_augmentation[] = { 'G', 'D', 'B', 0 };
    Returns true if all went well, false otherwise.  */
 
 static bool
-read_debug_names_from_section (struct objfile *objfile,
+read_debug_names_from_section (dwarf2_per_objfile *per_objfile,
 			       const char *filename,
 			       struct dwarf2_section_info *section,
-			       mapped_debug_names &map)
+			       mapped_debug_names_reader &map)
 {
+  struct objfile *objfile = per_objfile->objfile;
+
   if (section->empty ())
     return false;
 
@@ -188,11 +430,13 @@ read_debug_names_from_section (struct objfile *objfile,
 
   section->read (objfile);
 
+  map.per_objfile = per_objfile;
   map.dwarf5_byte_order = gdbarch_byte_order (objfile->arch ());
 
   const gdb_byte *addr = section->buffer;
 
-  bfd *const abfd = section->get_bfd_owner ();
+  bfd *abfd = section->get_bfd_owner ();
+  map.abfd = abfd;
 
   unsigned int bytes_read;
   LONGEST length = read_initial_length (abfd, addr, &bytes_read);
@@ -271,11 +515,27 @@ read_debug_names_from_section (struct objfile *objfile,
      string.  This value is rounded up to a multiple of 4.  */
   uint32_t augmentation_string_size = read_4_bytes (abfd, addr);
   addr += 4;
+  augmentation_string_size += (-augmentation_string_size) & 3;
+
+  if (augmentation_string_size == sizeof (old_gdb_augmentation)
+      && memcmp (addr, old_gdb_augmentation,
+		 sizeof (old_gdb_augmentation)) == 0)
+    {
+      warning (_(".debug_names created by an old version of gdb; ignoring"));
+      return false;
+    }
+
   map.augmentation_is_gdb = ((augmentation_string_size
 			      == sizeof (dwarf5_augmentation))
 			     && memcmp (addr, dwarf5_augmentation,
 					sizeof (dwarf5_augmentation)) == 0);
-  augmentation_string_size += (-augmentation_string_size) & 3;
+
+  if (!map.augmentation_is_gdb)
+    {
+      warning (_(".debug_names not created by gdb; ignoring"));
+      return false;
+    }
+
   addr += augmentation_string_size;
 
   /* List of CUs */
@@ -308,7 +568,7 @@ read_debug_names_from_section (struct objfile *objfile,
 	break;
 
       const auto insertpair
-	= map.abbrev_map.emplace (index_num, mapped_debug_names::index_val ());
+	= map.abbrev_map.emplace (index_num, mapped_debug_names_reader::index_val ());
       if (!insertpair.second)
 	{
 	  warning (_("Section .debug_names in %s has duplicate index %s, "
@@ -316,13 +576,13 @@ read_debug_names_from_section (struct objfile *objfile,
 		   filename, pulongest (index_num));
 	  return false;
 	}
-      mapped_debug_names::index_val &indexval = insertpair.first->second;
+      mapped_debug_names_reader::index_val &indexval = insertpair.first->second;
       indexval.dwarf_tag = read_unsigned_leb128 (abfd, addr, &bytes_read);
       addr += bytes_read;
 
       for (;;)
 	{
-	  mapped_debug_names::index_val::attr attr;
+	  mapped_debug_names_reader::index_val::attr attr;
 	  attr.dw_idx = read_unsigned_leb128 (abfd, addr, &bytes_read);
 	  addr += bytes_read;
 	  attr.form = read_unsigned_leb128 (abfd, addr, &bytes_read);
@@ -356,9 +616,9 @@ read_debug_names_from_section (struct objfile *objfile,
 
 static bool
 check_cus_from_debug_names_list (dwarf2_per_bfd *per_bfd,
-				 const mapped_debug_names &map,
-				 dwarf2_section_info &section,
-				 bool is_dwz)
+				  const mapped_debug_names_reader &map,
+				  dwarf2_section_info &section,
+				  bool is_dwz)
 {
   int nr_cus = per_bfd->all_comp_units.size ();
 
@@ -420,8 +680,8 @@ check_cus_from_debug_names_list (dwarf2_per_bfd *per_bfd,
 
 static bool
 check_cus_from_debug_names (dwarf2_per_bfd *per_bfd,
-			    const mapped_debug_names &map,
-			    const mapped_debug_names &dwz_map)
+			     const mapped_debug_names_reader &map,
+			     const mapped_debug_names_reader &dwz_map)
 {
   if (!check_cus_from_debug_names_list (per_bfd, map, per_bfd->info,
 					false /* is_dwz */))
@@ -435,22 +695,23 @@ check_cus_from_debug_names (dwarf2_per_bfd *per_bfd,
 					  true /* is_dwz */);
 }
 
-/* See read-debug-names.h.  */
+/* This does all the work for dwarf2_read_debug_names, but putting it
+   into a separate function makes some cleanup a bit simpler.  */
 
-bool
-dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
+static bool
+do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
 {
-  auto map = std::make_unique<mapped_debug_names> ();
-  mapped_debug_names dwz_map;
+  mapped_debug_names_reader map;
+  mapped_debug_names_reader dwz_map;
   struct objfile *objfile = per_objfile->objfile;
   dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
 
-  if (!read_debug_names_from_section (objfile, objfile_name (objfile),
-				      &per_bfd->debug_names, *map))
+  if (!read_debug_names_from_section (per_objfile, objfile_name (objfile),
+				      &per_bfd->debug_names, map))
     return false;
 
   /* Don't use the index if it's empty.  */
-  if (map->name_count == 0)
+  if (map.name_count == 0)
     return false;
 
   /* If there is a .dwz file, read it so we can get its CU list as
@@ -458,7 +719,7 @@ dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
   dwz_file *dwz = dwarf2_get_dwz_file (per_bfd);
   if (dwz != NULL)
     {
-      if (!read_debug_names_from_section (objfile,
+      if (!read_debug_names_from_section (per_objfile,
 					  bfd_get_filename (dwz->dwz_bfd.get ()),
 					  &dwz->debug_names, dwz_map))
 	{
@@ -469,525 +730,53 @@ dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
     }
 
   create_all_units (per_objfile);
-  if (!check_cus_from_debug_names (per_bfd, *map, dwz_map))
-    {
-      per_bfd->all_units.clear ();
-      return false;
-    }
+  if (!check_cus_from_debug_names (per_bfd, map, dwz_map))
+    return false;
 
-  if (map->tu_count != 0)
+  if (map.tu_count != 0)
     {
       /* We can only handle a single .debug_types when we have an
 	 index.  */
       if (per_bfd->types.size () > 1)
-	{
-	  per_bfd->all_units.clear ();
-	  return false;
-	}
+	return false;
 
       dwarf2_section_info *section
 	= (per_bfd->types.size () == 1
 	   ? &per_bfd->types[0]
 	   : &per_bfd->info);
 
-      if (!check_signatured_type_table_from_debug_names
-	     (per_objfile, *map, section))
-	{
-	  per_bfd->all_units.clear ();
-	  return false;
-	}
-    }
-
-  create_addrmap_from_aranges (per_objfile, &per_bfd->debug_aranges);
-
-  per_bfd->index_table = std::move (map);
-  per_bfd->quick_file_names_table =
-    create_quick_file_names_table (per_bfd->all_units.size ());
-
-  return true;
-}
-
-/* Type used to manage iterating over all CUs looking for a symbol for
-   .debug_names.  */
-
-class dw2_debug_names_iterator
-{
-public:
-  dw2_debug_names_iterator (const mapped_debug_names &map,
-			    block_search_flags block_index,
-			    domain_enum domain,
-			    const char *name, dwarf2_per_objfile *per_objfile)
-    : m_map (map), m_block_index (block_index), m_domain (domain),
-      m_addr (find_vec_in_debug_names (map, name, per_objfile)),
-      m_per_objfile (per_objfile)
-  {}
-
-  dw2_debug_names_iterator (const mapped_debug_names &map,
-			    search_domain search, uint32_t namei,
-			    dwarf2_per_objfile *per_objfile,
-			    domain_enum domain = UNDEF_DOMAIN)
-    : m_map (map),
-      m_domain (domain),
-      m_search (search),
-      m_addr (find_vec_in_debug_names (map, namei, per_objfile)),
-      m_per_objfile (per_objfile)
-  {}
-
-  dw2_debug_names_iterator (const mapped_debug_names &map,
-			    block_search_flags block_index, domain_enum domain,
-			    uint32_t namei, dwarf2_per_objfile *per_objfile)
-    : m_map (map), m_block_index (block_index), m_domain (domain),
-      m_addr (find_vec_in_debug_names (map, namei, per_objfile)),
-      m_per_objfile (per_objfile)
-  {}
-
-  /* Return the next matching CU or NULL if there are no more.  */
-  dwarf2_per_cu_data *next ();
-
-private:
-  static const gdb_byte *find_vec_in_debug_names (const mapped_debug_names &map,
-						  const char *name,
-						  dwarf2_per_objfile *per_objfile);
-  static const gdb_byte *find_vec_in_debug_names (const mapped_debug_names &map,
-						  uint32_t namei,
-						  dwarf2_per_objfile *per_objfile);
-
-  /* The internalized form of .debug_names.  */
-  const mapped_debug_names &m_map;
-
-  /* Restrict the search to these blocks.  */
-  block_search_flags m_block_index = (SEARCH_GLOBAL_BLOCK
-				      | SEARCH_STATIC_BLOCK);
-
-  /* The kind of symbol we're looking for.  */
-  const domain_enum m_domain = UNDEF_DOMAIN;
-  const search_domain m_search = ALL_DOMAIN;
-
-  /* The list of CUs from the index entry of the symbol, or NULL if
-     not found.  */
-  const gdb_byte *m_addr;
-
-  dwarf2_per_objfile *m_per_objfile;
-};
-
-const char *
-mapped_debug_names::namei_to_name
-  (uint32_t namei, dwarf2_per_objfile *per_objfile) const
-{
-  const ULONGEST namei_string_offs
-    = extract_unsigned_integer ((name_table_string_offs_reordered
-				 + namei * offset_size),
-				offset_size,
-				dwarf5_byte_order);
-  return read_indirect_string_at_offset (per_objfile, namei_string_offs);
-}
-
-/* Find a slot in .debug_names for the object named NAME.  If NAME is
-   found, return pointer to its pool data.  If NAME cannot be found,
-   return NULL.  */
-
-const gdb_byte *
-dw2_debug_names_iterator::find_vec_in_debug_names
-  (const mapped_debug_names &map, const char *name,
-   dwarf2_per_objfile *per_objfile)
-{
-  int (*cmp) (const char *, const char *);
-
-  gdb::unique_xmalloc_ptr<char> without_params;
-  if (current_language->la_language == language_cplus
-      || current_language->la_language == language_fortran
-      || current_language->la_language == language_d)
-    {
-      /* NAME is already canonical.  Drop any qualifiers as
-	 .debug_names does not contain any.  */
-
-      if (strchr (name, '(') != NULL)
-	{
-	  without_params = cp_remove_params (name);
-	  if (without_params != NULL)
-	    name = without_params.get ();
-	}
-    }
-
-  cmp = (case_sensitivity == case_sensitive_on ? strcmp : strcasecmp);
-
-  const uint32_t full_hash = dwarf5_djb_hash (name);
-  uint32_t namei
-    = extract_unsigned_integer (reinterpret_cast<const gdb_byte *>
-				(map.bucket_table_reordered
-				 + (full_hash % map.bucket_count)), 4,
-				map.dwarf5_byte_order);
-  if (namei == 0)
-    return NULL;
-  --namei;
-  if (namei >= map.name_count)
-    {
-      complaint (_("Wrong .debug_names with name index %u but name_count=%u "
-		   "[in module %s]"),
-		 namei, map.name_count,
-		 objfile_name (per_objfile->objfile));
-      return NULL;
-    }
-
-  for (;;)
-    {
-      const uint32_t namei_full_hash
-	= extract_unsigned_integer (reinterpret_cast<const gdb_byte *>
-				    (map.hash_table_reordered + namei), 4,
-				    map.dwarf5_byte_order);
-      if (full_hash % map.bucket_count != namei_full_hash % map.bucket_count)
-	return NULL;
-
-      if (full_hash == namei_full_hash)
-	{
-	  const char *const namei_string = map.namei_to_name (namei, per_objfile);
-
-#if 0 /* An expensive sanity check.  */
-	  if (namei_full_hash != dwarf5_djb_hash (namei_string))
-	    {
-	      complaint (_("Wrong .debug_names hash for string at index %u "
-			   "[in module %s]"),
-			 namei, objfile_name (dwarf2_per_objfile->objfile));
-	      return NULL;
-	    }
-#endif
-
-	  if (cmp (namei_string, name) == 0)
-	    {
-	      const ULONGEST namei_entry_offs
-		= extract_unsigned_integer ((map.name_table_entry_offs_reordered
-					     + namei * map.offset_size),
-					    map.offset_size, map.dwarf5_byte_order);
-	      return map.entry_pool + namei_entry_offs;
-	    }
-	}
-
-      ++namei;
-      if (namei >= map.name_count)
-	return NULL;
-    }
-}
-
-const gdb_byte *
-dw2_debug_names_iterator::find_vec_in_debug_names
-  (const mapped_debug_names &map, uint32_t namei, dwarf2_per_objfile *per_objfile)
-{
-  if (namei >= map.name_count)
-    {
-      complaint (_("Wrong .debug_names with name index %u but name_count=%u "
-		   "[in module %s]"),
-		 namei, map.name_count,
-		 objfile_name (per_objfile->objfile));
-      return NULL;
-    }
-
-  const ULONGEST namei_entry_offs
-    = extract_unsigned_integer ((map.name_table_entry_offs_reordered
-				 + namei * map.offset_size),
-				map.offset_size, map.dwarf5_byte_order);
-  return map.entry_pool + namei_entry_offs;
-}
-
-/* See dw2_debug_names_iterator.  */
-
-dwarf2_per_cu_data *
-dw2_debug_names_iterator::next ()
-{
-  if (m_addr == NULL)
-    return NULL;
-
-  dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd;
-  struct objfile *objfile = m_per_objfile->objfile;
-  bfd *const abfd = objfile->obfd.get ();
-
- again:
-
-  unsigned int bytes_read;
-  const ULONGEST abbrev = read_unsigned_leb128 (abfd, m_addr, &bytes_read);
-  m_addr += bytes_read;
-  if (abbrev == 0)
-    return NULL;
-
-  const auto indexval_it = m_map.abbrev_map.find (abbrev);
-  if (indexval_it == m_map.abbrev_map.cend ())
-    {
-      complaint (_("Wrong .debug_names undefined abbrev code %s "
-		   "[in module %s]"),
-		 pulongest (abbrev), objfile_name (objfile));
-      return NULL;
-    }
-  const mapped_debug_names::index_val &indexval = indexval_it->second;
-  enum class symbol_linkage {
-    unknown,
-    static_,
-    extern_,
-  } symbol_linkage_ = symbol_linkage::unknown;
-  dwarf2_per_cu_data *per_cu = NULL;
-  for (const mapped_debug_names::index_val::attr &attr : indexval.attr_vec)
-    {
-      ULONGEST ull;
-      switch (attr.form)
-	{
-	case DW_FORM_implicit_const:
-	  ull = attr.implicit_const;
-	  break;
-	case DW_FORM_flag_present:
-	  ull = 1;
-	  break;
-	case DW_FORM_udata:
-	  ull = read_unsigned_leb128 (abfd, m_addr, &bytes_read);
-	  m_addr += bytes_read;
-	  break;
-	case DW_FORM_ref4:
-	  ull = read_4_bytes (abfd, m_addr);
-	  m_addr += 4;
-	  break;
-	case DW_FORM_ref8:
-	  ull = read_8_bytes (abfd, m_addr);
-	  m_addr += 8;
-	  break;
-	case DW_FORM_ref_sig8:
-	  ull = read_8_bytes (abfd, m_addr);
-	  m_addr += 8;
-	  break;
-	default:
-	  complaint (_("Unsupported .debug_names form %s [in module %s]"),
-		     dwarf_form_name (attr.form),
-		     objfile_name (objfile));
-	  return NULL;
-	}
-      switch (attr.dw_idx)
-	{
-	case DW_IDX_compile_unit:
-	  {
-	    /* Don't crash on bad data.  */
-	    if (ull >= per_bfd->all_comp_units.size ())
-	      {
-		complaint (_(".debug_names entry has bad CU index %s"
-			     " [in module %s]"),
-			   pulongest (ull),
-			   objfile_name (objfile));
-		continue;
-	      }
-	  }
-	  per_cu = per_bfd->get_index_cu (ull);
-	  break;
-	case DW_IDX_type_unit:
-	  /* Don't crash on bad data.  */
-	  if (ull >= per_bfd->all_type_units.size ())
-	    {
-	      complaint (_(".debug_names entry has bad TU index %s"
-			   " [in module %s]"),
-			 pulongest (ull),
-			 objfile_name (objfile));
-	      continue;
-	    }
-	  {
-	    per_cu = per_bfd->get_index_tu (ull);
-	  }
-	  break;
-	case DW_IDX_die_offset:
-	  /* In a per-CU index (as opposed to a per-module index), index
-	     entries without CU attribute implicitly refer to the single CU.  */
-	  if (per_cu == NULL)
-	    per_cu = per_bfd->get_index_cu (0);
-	  break;
-	case DW_IDX_GNU_internal:
-	  if (!m_map.augmentation_is_gdb)
-	    break;
-	  symbol_linkage_ = symbol_linkage::static_;
-	  break;
-	case DW_IDX_GNU_external:
-	  if (!m_map.augmentation_is_gdb)
-	    break;
-	  symbol_linkage_ = symbol_linkage::extern_;
-	  break;
-	}
+      if (!check_signatured_type_table_from_debug_names (per_objfile,
+							 map, section))
+	return false;
     }
 
-  /* Skip if we couldn't find a valid CU/TU index.  */
-  if (per_cu == nullptr)
-    goto again;
+  per_bfd->debug_aranges.read (per_objfile->objfile);
+  addrmap_mutable addrmap;
+  if (!read_addrmap_from_aranges (per_objfile, &per_bfd->debug_aranges,
+				  &addrmap))
+    return false;
 
-  /* Skip if already read in.  */
-  if (m_per_objfile->symtab_set_p (per_cu))
-    goto again;
+  map.shard = std::make_unique<cooked_index_shard> ();
+  map.shard->install_addrmap (&addrmap);
 
-  /* Check static vs global.  */
-  if (symbol_linkage_ != symbol_linkage::unknown)
-    {
-      if (symbol_linkage_ == symbol_linkage::static_)
-	{
-	  if ((m_block_index & SEARCH_STATIC_BLOCK) == 0)
-	    goto again;
-	}
-      else
-	{
-	  if ((m_block_index & SEARCH_GLOBAL_BLOCK) == 0)
-	    goto again;
-	}
-    }
+  cooked_index *idx
+    = new debug_names_index (per_objfile,
+			     (std::make_unique<cooked_index_debug_names>
+			      (per_objfile, std::move (map))));
+  per_bfd->index_table.reset (idx);
 
-  /* Match dw2_symtab_iter_next, symbol_kind
-     and debug_names::psymbol_tag.  */
-  switch (m_domain)
-    {
-    case VAR_DOMAIN:
-      switch (indexval.dwarf_tag)
-	{
-	case DW_TAG_variable:
-	case DW_TAG_subprogram:
-	/* Some types are also in VAR_DOMAIN.  */
-	case DW_TAG_typedef:
-	case DW_TAG_structure_type:
-	  break;
-	default:
-	  goto again;
-	}
-      break;
-    case STRUCT_DOMAIN:
-      switch (indexval.dwarf_tag)
-	{
-	case DW_TAG_typedef:
-	case DW_TAG_structure_type:
-	  break;
-	default:
-	  goto again;
-	}
-      break;
-    case LABEL_DOMAIN:
-      switch (indexval.dwarf_tag)
-	{
-	case 0:
-	case DW_TAG_variable:
-	  break;
-	default:
-	  goto again;
-	}
-      break;
-    case MODULE_DOMAIN:
-      switch (indexval.dwarf_tag)
-	{
-	case DW_TAG_module:
-	  break;
-	default:
-	  goto again;
-	}
-      break;
-    default:
-      break;
-    }
-
-  /* Match dw2_expand_symtabs_matching, symbol_kind and
-     debug_names::psymbol_tag.  */
-  switch (m_search)
-    {
-    case VARIABLES_DOMAIN:
-      switch (indexval.dwarf_tag)
-	{
-	case DW_TAG_variable:
-	  break;
-	default:
-	  goto again;
-	}
-      break;
-    case FUNCTIONS_DOMAIN:
-      switch (indexval.dwarf_tag)
-	{
-	case DW_TAG_subprogram:
-	  break;
-	default:
-	  goto again;
-	}
-      break;
-    case TYPES_DOMAIN:
-      switch (indexval.dwarf_tag)
-	{
-	case DW_TAG_typedef:
-	case DW_TAG_structure_type:
-	  break;
-	default:
-	  goto again;
-	}
-      break;
-    case MODULES_DOMAIN:
-      switch (indexval.dwarf_tag)
-	{
-	case DW_TAG_module:
-	  break;
-	default:
-	  goto again;
-	}
-    default:
-      break;
-    }
+  idx->start_reading ();
 
-  return per_cu;
+  return true;
 }
 
-/* This dumps minimal information about .debug_names.  It is called
-   via "mt print objfiles".  The gdb.dwarf2/gdb-index.exp testcase
-   uses this to verify that .debug_names has been loaded.  */
-
-void
-dwarf2_debug_names_index::dump (struct objfile *objfile)
-{
-  gdb_printf (".debug_names: exists\n");
-}
+/* See read-debug-names.h.  */
 
 bool
-dwarf2_debug_names_index::expand_symtabs_matching
-  (struct objfile *objfile,
-   gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
-   const lookup_name_info *lookup_name,
-   gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
-   gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
-   block_search_flags search_flags,
-   domain_enum domain,
-   enum search_domain kind)
+dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
 {
-  dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
-
-  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_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;
-    }
-
-  mapped_debug_names &map
-    = *(gdb::checked_static_cast<mapped_debug_names *>
-	(per_objfile->per_bfd->index_table.get ()));
-
-  bool result
-    = dw2_expand_symtabs_matching_symbol (map, *lookup_name,
-					  symbol_matcher,
-					  [&] (offset_type namei)
-    {
-      /* The name was matched, now expand corresponding CUs that were
-	 marked.  */
-      dw2_debug_names_iterator iter (map, kind, namei, per_objfile, domain);
-
-      struct dwarf2_per_cu_data *per_cu;
-      while ((per_cu = iter.next ()) != NULL)
-	if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile,
-					      file_matcher,
-					      expansion_notify))
-	  return false;
-      return true;
-    }, per_objfile);
-
+  bool result = do_dwarf2_read_debug_names (per_objfile);
+  if (!result)
+    per_objfile->per_bfd->all_units.clear ();
   return result;
 }
