This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] DWARF-5: .debug_names index consumer


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=927aa2e778dce440f4de5de8fc37ead1683a804e

commit 927aa2e778dce440f4de5de8fc37ead1683a804e
Author: Jan Kratochvil <jan.kratochvil@redhat.com>
Date:   Fri Dec 8 22:44:12 2017 +0000

    DWARF-5: .debug_names index consumer
    
    Some testcases needed to be updated as they were missing
    .debug_aranges.  While that does not matter for no-index (as GDB
    builds the mapping internally during dwarf2_build_psymtabs_hard) and
    neither for .gdb_index (as GDB uses that internally built mapping
    which it stores into .gdb_index) it does matter for .debug_names as
    that simply assumes existing .debug_aranges from GCC.
    
    gdb/ChangeLog:
    2017-12-08  Jan Kratochvil  <jan.kratochvil@redhat.com>
    	    Pedro Alves  <palves@redhat.com>
    
    	* defs.h (elf_sym_fns_debug_names): New declaration.
    	* dwarf2read.c: Include "hash_enum.h".
    	(mapped_debug_names): New.
    	(struct dwarf2_per_objfile): Add debug_names, debug_aranges and
    	debug_names_table.
    	(dwarf2_elf_names): Add ".debug_names" and ".debug_aranges".
    	(struct dwz_file): Add debug_names.
    	(dwarf2_per_objfile::locate_sections): Handle debug_names and
    	debug_aranges.
    	(locate_dwz_sections): Handle debug_names.
    	(create_signatured_type_table_from_debug_names)
    	(create_addrmap_from_aranges): New.
    	(dwarf2_read_index): Update function comment.
    	(dwarf5_augmentation): Moved up.
    	(read_debug_names_from_section, create_cus_from_debug_names_list)
    	(create_cus_from_debug_names, dwarf2_read_debug_names): New.
    	(dwarf5_djb_hash): Moved up.
    	(dw2_debug_names_iterator): New.
    	(read_indirect_string_at_offset): New declaration.
    	(mapped_debug_names::namei_to_name)
    	(dw2_debug_names_iterator::find_vec_in_debug_names)
    	(dw2_debug_names_iterator::next, dw2_debug_names_lookup_symbol)
    	(dw2_debug_names_dump, dw2_debug_names_expand_symtabs_for_function)
    	(dw2_debug_names_expand_symtabs_matching, dwarf2_debug_names_functions):
    	New.
    	(dwarf2_initialize_objfile): Return also elf_sym_fns_debug_names.
    	(debug_names::djb_hash): Rename it to dwarf5_djb_hash.
    	(debug_names::build): Update djb_hash caller.
    	(write_debug_names): Move out and rename augmentation to
    	dwarf5_augmentation.
    	* elfread.c (elf_sym_fns_debug_names): New.
    	* psymtab.h (dwarf2_debug_names_functions): New declaration.
    	* symfile.h (struct dwarf2_debug_sections): Add debug_names and
    	debug_aranges.
    	* xcoffread.c (dwarf2_xcoff_names): Add debug_names and debug_aranges.
    
    gdb/testsuite/ChangeLog:
    2017-12-08  Jan Kratochvil  <jan.kratochvil@redhat.com>
    	    Pedro Alves  <palves@redhat.com>
    
    	* gdb.base/maint.exp (check for .gdb_index): Check also for
    	.debug_names.
    	* gdb.dlang/watch-loc.c (.debug_aranges): New.
    	* gdb.dwarf2/dw2-case-insensitive-debug.S: Likewise.
    	* gdb.dwarf2/gdb-index.exp (check if index present, .gdb_index used)
    	(.gdb_index used after symbol reloading): Support also .debug_names.
    	* gdb.mi/dw2-ref-missing-frame-func.c (.debug_aranges): New.

Diff:
---
 gdb/ChangeLog                                      |   39 +
 gdb/defs.h                                         |    1 +
 gdb/dwarf2read.c                                   | 1502 +++++++++++++++++---
 gdb/elfread.c                                      |   17 +
 gdb/psymtab.h                                      |    1 +
 gdb/symfile.h                                      |    2 +
 gdb/testsuite/ChangeLog                            |   11 +
 gdb/testsuite/gdb.base/maint.exp                   |    9 +-
 gdb/testsuite/gdb.dlang/watch-loc.c                |   20 +
 .../gdb.dwarf2/dw2-case-insensitive-debug.S        |   18 +
 gdb/testsuite/gdb.dwarf2/gdb-index.exp             |   19 +-
 gdb/testsuite/gdb.mi/dw2-ref-missing-frame-func.c  |   21 +
 gdb/xcoffread.c                                    |    2 +
 13 files changed, 1445 insertions(+), 217 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 09cafd0..ee2f1c4 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,42 @@
+2017-12-08  Jan Kratochvil  <jan.kratochvil@redhat.com>
+	    Pedro Alves  <palves@redhat.com>
+
+	* defs.h (elf_sym_fns_debug_names): New declaration.
+	* dwarf2read.c: Include "hash_enum.h".
+	(mapped_debug_names): New.
+	(struct dwarf2_per_objfile): Add debug_names, debug_aranges and
+	debug_names_table.
+	(dwarf2_elf_names): Add ".debug_names" and ".debug_aranges".
+	(struct dwz_file): Add debug_names.
+	(dwarf2_per_objfile::locate_sections): Handle debug_names and
+	debug_aranges.
+	(locate_dwz_sections): Handle debug_names.
+	(create_signatured_type_table_from_debug_names)
+	(create_addrmap_from_aranges): New.
+	(dwarf2_read_index): Update function comment.
+	(dwarf5_augmentation): Moved up.
+	(read_debug_names_from_section, create_cus_from_debug_names_list)
+	(create_cus_from_debug_names, dwarf2_read_debug_names): New.
+	(dwarf5_djb_hash): Moved up.
+	(dw2_debug_names_iterator): New.
+	(read_indirect_string_at_offset): New declaration.
+	(mapped_debug_names::namei_to_name)
+	(dw2_debug_names_iterator::find_vec_in_debug_names)
+	(dw2_debug_names_iterator::next, dw2_debug_names_lookup_symbol)
+	(dw2_debug_names_dump, dw2_debug_names_expand_symtabs_for_function)
+	(dw2_debug_names_expand_symtabs_matching, dwarf2_debug_names_functions):
+	New.
+	(dwarf2_initialize_objfile): Return also elf_sym_fns_debug_names.
+	(debug_names::djb_hash): Rename it to dwarf5_djb_hash.
+	(debug_names::build): Update djb_hash caller.
+	(write_debug_names): Move out and rename augmentation to
+	dwarf5_augmentation.
+	* elfread.c (elf_sym_fns_debug_names): New.
+	* psymtab.h (dwarf2_debug_names_functions): New declaration.
+	* symfile.h (struct dwarf2_debug_sections): Add debug_names and
+	debug_aranges.
+	* xcoffread.c (dwarf2_xcoff_names): Add debug_names and debug_aranges.
+
 2017-12-08  Pedro Alves  <palves@redhat.com>
 
 	* common/hash_enum.h: New file.
diff --git a/gdb/defs.h b/gdb/defs.h
index a873a55..c2e145e 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -683,6 +683,7 @@ extern void initialize_inferiors (void);
 
 extern const struct sym_fns elf_sym_fns_lazy_psyms;
 extern const struct sym_fns elf_sym_fns_gdb_index;
+extern const struct sym_fns elf_sym_fns_debug_names;
 
 /* * Special block numbers */
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 80d4857..ca2b04d 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -74,6 +74,7 @@
 #include "common/gdb_optional.h"
 #include "common/underlying.h"
 #include "common/byte-vector.h"
+#include "common/hash_enum.h"
 #include "filename-seen-cache.h"
 #include "producer.h"
 #include <fcntl.h>
@@ -282,6 +283,44 @@ struct mapped_index
     find_name_components_bounds (const lookup_name_info &ln_no_params) const;
 };
 
+/* A description of the mapped .debug_names.
+   Uninitialized map has CU_COUNT 0.  */
+struct mapped_debug_names
+{
+  bfd_endian dwarf5_byte_order;
+  bool dwarf5_is_dwarf64;
+  bool augmentation_is_gdb;
+  uint8_t offset_size;
+  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;
+
+  struct index_val
+  {
+    ULONGEST dwarf_tag;
+    struct attr
+    {
+      /* Attribute name DW_IDX_*.  */
+      ULONGEST dw_idx;
+
+      /* Attribute form DW_FORM_*.  */
+      ULONGEST form;
+
+      /* Value if FORM is DW_FORM_implicit_const.  */
+      LONGEST implicit_const;
+    };
+    std::vector<attr> attr_vec;
+  };
+
+  std::unordered_map<ULONGEST, index_val> abbrev_map;
+
+  const char *namei_to_name (uint32_t namei) const;
+};
+
 typedef struct dwarf2_per_cu_data *dwarf2_per_cu_ptr;
 DEF_VEC_P (dwarf2_per_cu_ptr);
 
@@ -334,6 +373,8 @@ public:
   dwarf2_section_info frame {};
   dwarf2_section_info eh_frame {};
   dwarf2_section_info gdb_index {};
+  dwarf2_section_info debug_names {};
+  dwarf2_section_info debug_aranges {};
 
   VEC (dwarf2_section_info_def) *types = NULL;
 
@@ -399,6 +440,9 @@ public:
   /* The mapped index, or NULL if .gdb_index is missing or not being used.  */
   mapped_index *index_table = NULL;
 
+  /* The mapped index, or NULL if .debug_names is missing or not being used.  */
+  std::unique_ptr<mapped_debug_names> debug_names_table;
+
   /* When using index_table, this keeps track of all quick_file_names entries.
      TUs typically share line table entries with a CU, so we maintain a
      separate table of all line table entries to support the sharing.
@@ -453,6 +497,8 @@ static const struct dwarf2_debug_sections dwarf2_elf_names =
   { ".debug_frame", ".zdebug_frame" },
   { ".eh_frame", NULL },
   { ".gdb_index", ".zgdb_index" },
+  { ".debug_names", ".zdebug_names" },
+  { ".debug_aranges", ".zdebug_aranges" },
   23
 };
 
@@ -1119,6 +1165,7 @@ struct dwz_file
   struct dwarf2_section_info line;
   struct dwarf2_section_info macro;
   struct dwarf2_section_info gdb_index;
+  struct dwarf2_section_info debug_names;
 
   /* The dwz's BFD.  */
   bfd *dwz_bfd;
@@ -1726,6 +1773,9 @@ static const char *read_indirect_line_string (bfd *, const gdb_byte *,
 					      const struct comp_unit_head *,
 					      unsigned int *);
 
+static const char *read_indirect_string_at_offset (bfd *abfd,
+						   LONGEST str_offset);
+
 static const char *read_indirect_string_from_dwz (struct dwz_file *, LONGEST);
 
 static LONGEST read_signed_leb128 (bfd *, const gdb_byte *, unsigned int *);
@@ -2547,6 +2597,16 @@ dwarf2_per_objfile::locate_sections (bfd *abfd, asection *sectp,
       this->gdb_index.s.section = sectp;
       this->gdb_index.size = bfd_get_section_size (sectp);
     }
+  else if (section_is_p (sectp->name, &names.debug_names))
+    {
+      this->debug_names.s.section = sectp;
+      this->debug_names.size = bfd_get_section_size (sectp);
+    }
+  else if (section_is_p (sectp->name, &names.debug_aranges))
+    {
+      this->debug_aranges.s.section = sectp;
+      this->debug_aranges.size = bfd_get_section_size (sectp);
+    }
 
   if ((bfd_get_section_flags (abfd, sectp) & (SEC_LOAD | SEC_ALLOC))
       && bfd_section_vma (abfd, sectp) == 0)
@@ -2743,6 +2803,11 @@ locate_dwz_sections (bfd *abfd, asection *sectp, void *arg)
       dwz_file->gdb_index.s.section = sectp;
       dwz_file->gdb_index.size = bfd_get_section_size (sectp);
     }
+  else if (section_is_p (sectp->name, &dwarf2_elf_names.debug_names))
+    {
+      dwz_file->debug_names.s.section = sectp;
+      dwz_file->debug_names.size = bfd_get_section_size (sectp);
+    }
 }
 
 /* Open the separate '.dwz' debug file, if needed.  Return NULL if
@@ -3192,6 +3257,65 @@ create_signatured_type_table_from_index (struct objfile *objfile,
   dwarf2_per_objfile->signatured_types = sig_types_hash;
 }
 
+/* Create the signatured type hash table from .debug_names.  */
+
+static void
+create_signatured_type_table_from_debug_names
+  (struct objfile *objfile,
+   const mapped_debug_names &map,
+   struct dwarf2_section_info *section,
+   struct dwarf2_section_info *abbrev_section)
+{
+  dwarf2_read_section (objfile, section);
+  dwarf2_read_section (objfile, abbrev_section);
+
+  dwarf2_per_objfile->n_type_units
+    = dwarf2_per_objfile->n_allocated_type_units
+    = map.tu_count;
+  dwarf2_per_objfile->all_type_units
+    = XNEWVEC (struct signatured_type *, dwarf2_per_objfile->n_type_units);
+
+  htab_t sig_types_hash = allocate_signatured_type_table (objfile);
+
+  for (uint32_t i = 0; i < map.tu_count; ++i)
+    {
+      struct signatured_type *sig_type;
+      ULONGEST signature;
+      void **slot;
+      cu_offset type_offset_in_tu;
+
+      sect_offset sect_off
+	= (sect_offset) (extract_unsigned_integer
+			 (map.tu_table_reordered + i * map.offset_size,
+			  map.offset_size,
+			  map.dwarf5_byte_order));
+
+      comp_unit_head cu_header;
+      read_and_check_comp_unit_head (&cu_header, section, abbrev_section,
+				     section->buffer + to_underlying (sect_off),
+				     rcuh_kind::TYPE);
+
+      sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+				 struct signatured_type);
+      sig_type->signature = cu_header.signature;
+      sig_type->type_offset_in_tu = cu_header.type_cu_offset_in_tu;
+      sig_type->per_cu.is_debug_types = 1;
+      sig_type->per_cu.section = section;
+      sig_type->per_cu.sect_off = sect_off;
+      sig_type->per_cu.objfile = objfile;
+      sig_type->per_cu.v.quick
+	= OBSTACK_ZALLOC (&objfile->objfile_obstack,
+			  struct dwarf2_per_cu_quick_data);
+
+      slot = htab_find_slot (sig_types_hash, sig_type, INSERT);
+      *slot = sig_type;
+
+      dwarf2_per_objfile->all_type_units[i] = sig_type;
+    }
+
+  dwarf2_per_objfile->signatured_types = sig_types_hash;
+}
+
 /* Read the address map data from the mapped index, and use it to
    populate the objfile's psymtabs_addrmap.  */
 
@@ -3247,6 +3371,165 @@ create_addrmap_from_index (struct objfile *objfile, struct mapped_index *index)
 						    &objfile->objfile_obstack);
 }
 
+/* Read the address map data from DWARF-5 .debug_aranges, and use it to
+   populate the objfile's psymtabs_addrmap.  */
+
+static void
+create_addrmap_from_aranges (struct objfile *objfile,
+			     struct dwarf2_section_info *section)
+{
+  bfd *abfd = objfile->obfd;
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  const CORE_ADDR baseaddr = ANOFFSET (objfile->section_offsets,
+				       SECT_OFF_TEXT (objfile));
+
+  auto_obstack temp_obstack;
+  addrmap *mutable_map = addrmap_create_mutable (&temp_obstack);
+
+  std::unordered_map<sect_offset,
+		     dwarf2_per_cu_data *,
+		     gdb::hash_enum<sect_offset>>
+    debug_info_offset_to_per_cu;
+  for (int cui = 0; cui < dwarf2_per_objfile->n_comp_units; ++cui)
+    {
+      dwarf2_per_cu_data *per_cu = dw2_get_cutu (cui);
+      const auto insertpair
+	= debug_info_offset_to_per_cu.emplace (per_cu->sect_off, per_cu);
+      if (!insertpair.second)
+	{
+	  warning (_("Section .debug_aranges in %s has duplicate "
+		     "debug_info_offset %u, ignoring .debug_aranges."),
+		   objfile_name (objfile), to_underlying (per_cu->sect_off));
+	  return;
+	}
+    }
+
+  dwarf2_read_section (objfile, section);
+
+  const bfd_endian dwarf5_byte_order = gdbarch_byte_order (gdbarch);
+
+  const gdb_byte *addr = section->buffer;
+
+  while (addr < section->buffer + section->size)
+    {
+      const gdb_byte *const entry_addr = addr;
+      unsigned int bytes_read;
+
+      const LONGEST entry_length = read_initial_length (abfd, addr,
+							&bytes_read);
+      addr += bytes_read;
+
+      const gdb_byte *const entry_end = addr + entry_length;
+      const bool dwarf5_is_dwarf64 = bytes_read != 4;
+      const uint8_t offset_size = dwarf5_is_dwarf64 ? 8 : 4;
+      if (addr + entry_length > section->buffer + section->size)
+	{
+	  warning (_("Section .debug_aranges in %s entry at offset %zu "
+	             "length %s exceeds section length %s, "
+		     "ignoring .debug_aranges."),
+		   objfile_name (objfile), entry_addr - section->buffer,
+		   plongest (bytes_read + entry_length),
+		   pulongest (section->size));
+	  return;
+	}
+
+      /* The version number.  */
+      const uint16_t version = read_2_bytes (abfd, addr);
+      addr += 2;
+      if (version != 2)
+	{
+	  warning (_("Section .debug_aranges in %s entry at offset %zu "
+		     "has unsupported version %d, ignoring .debug_aranges."),
+		   objfile_name (objfile), entry_addr - section->buffer,
+		   version);
+	  return;
+	}
+
+      const uint64_t debug_info_offset
+	= extract_unsigned_integer (addr, offset_size, dwarf5_byte_order);
+      addr += offset_size;
+      const auto per_cu_it
+	= debug_info_offset_to_per_cu.find (sect_offset (debug_info_offset));
+      if (per_cu_it == debug_info_offset_to_per_cu.cend ())
+	{
+	  warning (_("Section .debug_aranges in %s entry at offset %zu "
+		     "debug_info_offset %s does not exists, "
+		     "ignoring .debug_aranges."),
+		   objfile_name (objfile), entry_addr - section->buffer,
+		   pulongest (debug_info_offset));
+	  return;
+	}
+      dwarf2_per_cu_data *const per_cu = per_cu_it->second;
+
+      const uint8_t address_size = *addr++;
+      if (address_size < 1 || address_size > 8)
+	{
+	  warning (_("Section .debug_aranges in %s entry at offset %zu "
+		     "address_size %u is invalid, ignoring .debug_aranges."),
+		   objfile_name (objfile), entry_addr - section->buffer,
+		   address_size);
+	  return;
+	}
+
+      const uint8_t segment_selector_size = *addr++;
+      if (segment_selector_size != 0)
+	{
+	  warning (_("Section .debug_aranges in %s entry at offset %zu "
+		     "segment_selector_size %u is not supported, "
+		     "ignoring .debug_aranges."),
+		   objfile_name (objfile), entry_addr - section->buffer,
+		   segment_selector_size);
+	  return;
+	}
+
+      /* Must pad to an alignment boundary that is twice the address
+         size.  It is undocumented by the DWARF standard but GCC does
+         use it.  */
+      for (size_t padding = ((-(addr - section->buffer))
+			     & (2 * address_size - 1));
+           padding > 0; padding--)
+	if (*addr++ != 0)
+	  {
+	    warning (_("Section .debug_aranges in %s entry at offset %zu "
+		       "padding is not zero, ignoring .debug_aranges."),
+		     objfile_name (objfile), entry_addr - section->buffer);
+	    return;
+	  }
+
+      for (;;)
+	{
+	  if (addr + 2 * address_size > entry_end)
+	    {
+	      warning (_("Section .debug_aranges in %s entry at offset %zu "
+			 "address list is not properly terminated, "
+			 "ignoring .debug_aranges."),
+		       objfile_name (objfile), entry_addr - section->buffer);
+	      return;
+	    }
+	  ULONGEST start = extract_unsigned_integer (addr, address_size,
+						     dwarf5_byte_order);
+	  addr += address_size;
+	  ULONGEST length = extract_unsigned_integer (addr, address_size,
+						      dwarf5_byte_order);
+	  addr += address_size;
+	  if (start == 0 && length == 0)
+	    break;
+	  if (start == 0 && !dwarf2_per_objfile->has_section_at_zero)
+	    {
+	      /* Symbol was eliminated due to a COMDAT group.  */
+	      continue;
+	    }
+	  ULONGEST end = start + length;
+	  start = gdbarch_adjust_dwarf2_addr (gdbarch, start + baseaddr);
+	  end = gdbarch_adjust_dwarf2_addr (gdbarch, end + baseaddr);
+	  addrmap_set_empty (mutable_map, start, end - 1, per_cu);
+	}
+    }
+
+  objfile->psymtabs_addrmap = addrmap_create_fixed (mutable_map,
+						    &objfile->objfile_obstack);
+}
+
 /* The hash function for strings in the mapped index.  This is the same as
    SYMBOL_HASH_NEXT, but we keep a separate copy to maintain control over the
    implementation.  This is necessary because the hash function is tied to the
@@ -3457,8 +3740,7 @@ to use the section anyway."),
   return 1;
 }
 
-
-/* Read the index file.  If everything went ok, initialize the "quick"
+/* Read .gdb_index.  If everything went ok, initialize the "quick"
    elements of all the CUs and return 1.  Otherwise, return 0.  */
 
 static int
@@ -5083,248 +5365,1069 @@ dw_expand_symtabs_matching_file_matcher
   /* The rule is CUs specify all the files, including those used by
      any TU, so there's no need to scan TUs here.  */
 
-  for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+  for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+    {
+      int j;
+      struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+      struct quick_file_names *file_data;
+      void **slot;
+
+      QUIT;
+
+      per_cu->v.quick->mark = 0;
+
+      /* We only need to look at symtabs not already expanded.  */
+      if (per_cu->v.quick->compunit_symtab)
+	continue;
+
+      file_data = dw2_get_file_names (per_cu);
+      if (file_data == NULL)
+	continue;
+
+      if (htab_find (visited_not_found.get (), file_data) != NULL)
+	continue;
+      else if (htab_find (visited_found.get (), file_data) != NULL)
+	{
+	  per_cu->v.quick->mark = 1;
+	  continue;
+	}
+
+      for (j = 0; j < file_data->num_file_names; ++j)
+	{
+	  const char *this_real_name;
+
+	  if (file_matcher (file_data->file_names[j], false))
+	    {
+	      per_cu->v.quick->mark = 1;
+	      break;
+	    }
+
+	  /* 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 (file_data->file_names[j]),
+				true))
+	    continue;
+
+	  this_real_name = dw2_get_real_path (objfile, file_data, j);
+	  if (file_matcher (this_real_name, false))
+	    {
+	      per_cu->v.quick->mark = 1;
+	      break;
+	    }
+	}
+
+      slot = htab_find_slot (per_cu->v.quick->mark
+			     ? visited_found.get ()
+			     : visited_not_found.get (),
+			     file_data, INSERT);
+      *slot = file_data;
+    }
+}
+
+static void
+dw2_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,
+   enum search_domain kind)
+{
+  int i;
+
+  dw2_setup (objfile);
+
+  /* index_table is NULL if OBJF_READNOW.  */
+  if (!dwarf2_per_objfile->index_table)
+    return;
+
+  dw_expand_symtabs_matching_file_matcher (file_matcher);
+
+  mapped_index &index = *dwarf2_per_objfile->index_table;
+
+  dw2_expand_symtabs_matching_symbol (index, lookup_name,
+				      symbol_matcher,
+				      kind, [&] (offset_type idx)
+    {
+      dw2_expand_marked_cus (index, idx, objfile, file_matcher,
+			     expansion_notify, kind);
+    });
+}
+
+/* A helper for dw2_find_pc_sect_compunit_symtab which finds the most specific
+   symtab.  */
+
+static struct compunit_symtab *
+recursively_find_pc_sect_compunit_symtab (struct compunit_symtab *cust,
+					  CORE_ADDR pc)
+{
+  int i;
+
+  if (COMPUNIT_BLOCKVECTOR (cust) != NULL
+      && blockvector_contains_pc (COMPUNIT_BLOCKVECTOR (cust), pc))
+    return cust;
+
+  if (cust->includes == NULL)
+    return NULL;
+
+  for (i = 0; cust->includes[i]; ++i)
+    {
+      struct compunit_symtab *s = cust->includes[i];
+
+      s = recursively_find_pc_sect_compunit_symtab (s, pc);
+      if (s != NULL)
+	return s;
+    }
+
+  return NULL;
+}
+
+static struct compunit_symtab *
+dw2_find_pc_sect_compunit_symtab (struct objfile *objfile,
+				  struct bound_minimal_symbol msymbol,
+				  CORE_ADDR pc,
+				  struct obj_section *section,
+				  int warn_if_readin)
+{
+  struct dwarf2_per_cu_data *data;
+  struct compunit_symtab *result;
+
+  dw2_setup (objfile);
+
+  if (!objfile->psymtabs_addrmap)
+    return NULL;
+
+  data = (struct dwarf2_per_cu_data *) addrmap_find (objfile->psymtabs_addrmap,
+						     pc);
+  if (!data)
+    return NULL;
+
+  if (warn_if_readin && data->v.quick->compunit_symtab)
+    warning (_("(Internal error: pc %s in read in CU, but not in symtab.)"),
+	     paddress (get_objfile_arch (objfile), pc));
+
+  result
+    = recursively_find_pc_sect_compunit_symtab (dw2_instantiate_symtab (data),
+						pc);
+  gdb_assert (result != NULL);
+  return result;
+}
+
+static void
+dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
+			  void *data, int need_fullname)
+{
+  dw2_setup (objfile);
+
+  if (!dwarf2_per_objfile->filenames_cache)
+    {
+      dwarf2_per_objfile->filenames_cache.emplace ();
+
+      htab_up visited (htab_create_alloc (10,
+					  htab_hash_pointer, htab_eq_pointer,
+					  NULL, xcalloc, xfree));
+
+      /* The rule is CUs specify all the files, including those used
+	 by any TU, so there's no need to scan TUs here.  We can
+	 ignore file names coming from already-expanded CUs.  */
+
+      for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+	{
+	  struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
+
+	  if (per_cu->v.quick->compunit_symtab)
+	    {
+	      void **slot = htab_find_slot (visited.get (),
+					    per_cu->v.quick->file_names,
+					    INSERT);
+
+	      *slot = per_cu->v.quick->file_names;
+	    }
+	}
+
+      for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+	{
+	  struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+	  struct quick_file_names *file_data;
+	  void **slot;
+
+	  /* We only need to look at symtabs not already expanded.  */
+	  if (per_cu->v.quick->compunit_symtab)
+	    continue;
+
+	  file_data = dw2_get_file_names (per_cu);
+	  if (file_data == NULL)
+	    continue;
+
+	  slot = htab_find_slot (visited.get (), file_data, INSERT);
+	  if (*slot)
+	    {
+	      /* Already visited.  */
+	      continue;
+	    }
+	  *slot = file_data;
+
+	  for (int j = 0; j < file_data->num_file_names; ++j)
+	    {
+	      const char *filename = file_data->file_names[j];
+	      dwarf2_per_objfile->filenames_cache->seen (filename);
+	    }
+	}
+    }
+
+  dwarf2_per_objfile->filenames_cache->traverse ([&] (const char *filename)
+    {
+      gdb::unique_xmalloc_ptr<char> this_real_name;
+
+      if (need_fullname)
+	this_real_name = gdb_realpath (filename);
+      (*fun) (filename, this_real_name.get (), data);
+    });
+}
+
+static int
+dw2_has_symbols (struct objfile *objfile)
+{
+  return 1;
+}
+
+const struct quick_symbol_functions dwarf2_gdb_index_functions =
+{
+  dw2_has_symbols,
+  dw2_find_last_source_symtab,
+  dw2_forget_cached_source_info,
+  dw2_map_symtabs_matching_filename,
+  dw2_lookup_symbol,
+  dw2_print_stats,
+  dw2_dump,
+  dw2_relocate,
+  dw2_expand_symtabs_for_function,
+  dw2_expand_all_symtabs,
+  dw2_expand_symtabs_with_fullname,
+  dw2_map_matching_symbols,
+  dw2_expand_symtabs_matching,
+  dw2_find_pc_sect_compunit_symtab,
+  NULL,
+  dw2_map_symbol_filenames
+};
+
+/* 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 };
+
+/* A helper function that reads the .debug_names section in SECTION
+   and fills in MAP.  FILENAME is the name of the file containing the
+   section; it is used for error reporting.
+
+   Returns true if all went well, false otherwise.  */
+
+static bool
+read_debug_names_from_section (struct objfile *objfile,
+			       const char *filename,
+			       struct dwarf2_section_info *section,
+			       mapped_debug_names &map)
+{
+  if (dwarf2_section_empty_p (section))
+    return false;
+
+  /* Older elfutils strip versions could keep the section in the main
+     executable while splitting it for the separate debug info file.  */
+  if ((get_section_flags (section) & SEC_HAS_CONTENTS) == 0)
+    return false;
+
+  dwarf2_read_section (objfile, section);
+
+  map.dwarf5_byte_order = gdbarch_byte_order (get_objfile_arch (objfile));
+
+  const gdb_byte *addr = section->buffer;
+
+  bfd *const abfd = get_section_bfd_owner (section);
+
+  unsigned int bytes_read;
+  LONGEST length = read_initial_length (abfd, addr, &bytes_read);
+  addr += bytes_read;
+
+  map.dwarf5_is_dwarf64 = bytes_read != 4;
+  map.offset_size = map.dwarf5_is_dwarf64 ? 8 : 4;
+  if (bytes_read + length != section->size)
+    {
+      /* There may be multiple per-CU indices.  */
+      warning (_("Section .debug_names in %s length %s does not match "
+		 "section length %s, ignoring .debug_names."),
+	       filename, plongest (bytes_read + length),
+	       pulongest (section->size));
+      return false;
+    }
+
+  /* The version number.  */
+  uint16_t version = read_2_bytes (abfd, addr);
+  addr += 2;
+  if (version != 5)
+    {
+      warning (_("Section .debug_names in %s has unsupported version %d, "
+		 "ignoring .debug_names."),
+	       filename, version);
+      return false;
+    }
+
+  /* Padding.  */
+  uint16_t padding = read_2_bytes (abfd, addr);
+  addr += 2;
+  if (padding != 0)
+    {
+      warning (_("Section .debug_names in %s has unsupported padding %d, "
+		 "ignoring .debug_names."),
+	       filename, padding);
+      return false;
+    }
+
+  /* comp_unit_count - The number of CUs in the CU list.  */
+  map.cu_count = read_4_bytes (abfd, addr);
+  addr += 4;
+
+  /* local_type_unit_count - The number of TUs in the local TU
+     list.  */
+  map.tu_count = read_4_bytes (abfd, addr);
+  addr += 4;
+
+  /* foreign_type_unit_count - The number of TUs in the foreign TU
+     list.  */
+  uint32_t foreign_tu_count = read_4_bytes (abfd, addr);
+  addr += 4;
+  if (foreign_tu_count != 0)
+    {
+      warning (_("Section .debug_names in %s has unsupported %lu foreign TUs, "
+		 "ignoring .debug_names."),
+	       filename, static_cast<unsigned long> (foreign_tu_count));
+      return false;
+    }
+
+  /* bucket_count - The number of hash buckets in the hash lookup
+     table.  */
+  map.bucket_count = read_4_bytes (abfd, addr);
+  addr += 4;
+
+  /* name_count - The number of unique names in the index.  */
+  map.name_count = read_4_bytes (abfd, addr);
+  addr += 4;
+
+  /* abbrev_table_size - The size in bytes of the abbreviations
+     table.  */
+  uint32_t abbrev_table_size = read_4_bytes (abfd, addr);
+  addr += 4;
+
+  /* augmentation_string_size - The size in bytes of the augmentation
+     string.  This value is rounded up to a multiple of 4.  */
+  uint32_t augmentation_string_size = read_4_bytes (abfd, addr);
+  addr += 4;
+  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;
+  addr += augmentation_string_size;
+
+  /* List of CUs */
+  map.cu_table_reordered = addr;
+  addr += map.cu_count * map.offset_size;
+
+  /* List of Local TUs */
+  map.tu_table_reordered = addr;
+  addr += map.tu_count * map.offset_size;
+
+  /* Hash Lookup Table */
+  map.bucket_table_reordered = reinterpret_cast<const uint32_t *> (addr);
+  addr += map.bucket_count * 4;
+  map.hash_table_reordered = reinterpret_cast<const uint32_t *> (addr);
+  addr += map.name_count * 4;
+
+  /* Name Table */
+  map.name_table_string_offs_reordered = addr;
+  addr += map.name_count * map.offset_size;
+  map.name_table_entry_offs_reordered = addr;
+  addr += map.name_count * map.offset_size;
+
+  const gdb_byte *abbrev_table_start = addr;
+  for (;;)
+    {
+      unsigned int bytes_read;
+      const ULONGEST index_num = read_unsigned_leb128 (abfd, addr, &bytes_read);
+      addr += bytes_read;
+      if (index_num == 0)
+	break;
+
+      const auto insertpair
+	= map.abbrev_map.emplace (index_num, mapped_debug_names::index_val ());
+      if (!insertpair.second)
+	{
+	  warning (_("Section .debug_names in %s has duplicate index %s, "
+		     "ignoring .debug_names."),
+		   filename, pulongest (index_num));
+	  return false;
+	}
+      mapped_debug_names::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;
+	  attr.dw_idx = read_unsigned_leb128 (abfd, addr, &bytes_read);
+	  addr += bytes_read;
+	  attr.form = read_unsigned_leb128 (abfd, addr, &bytes_read);
+	  addr += bytes_read;
+	  if (attr.form == DW_FORM_implicit_const)
+	    {
+	      attr.implicit_const = read_signed_leb128 (abfd, addr,
+							&bytes_read);
+	      addr += bytes_read;
+	    }
+	  if (attr.dw_idx == 0 && attr.form == 0)
+	    break;
+	  indexval.attr_vec.push_back (std::move (attr));
+	}
+    }
+  if (addr != abbrev_table_start + abbrev_table_size)
+    {
+      warning (_("Section .debug_names in %s has abbreviation_table "
+                 "of size %zu vs. written as %u, ignoring .debug_names."),
+	       filename, addr - abbrev_table_start, abbrev_table_size);
+      return false;
+    }
+  map.entry_pool = addr;
+
+  return true;
+}
+
+/* A helper for create_cus_from_debug_names that handles the MAP's CU
+   list.  */
+
+static void
+create_cus_from_debug_names_list (struct objfile *objfile,
+				  const mapped_debug_names &map,
+				  dwarf2_section_info &section,
+				  bool is_dwz, int base_offset)
+{
+  sect_offset sect_off_prev;
+  for (uint32_t i = 0; i <= map.cu_count; ++i)
+    {
+      sect_offset sect_off_next;
+      if (i < map.cu_count)
+	{
+	  sect_off_next
+	    = (sect_offset) (extract_unsigned_integer
+			     (map.cu_table_reordered + i * map.offset_size,
+			      map.offset_size,
+			      map.dwarf5_byte_order));
+	}
+      else
+	sect_off_next = (sect_offset) section.size;
+      if (i >= 1)
+	{
+	  const ULONGEST length = sect_off_next - sect_off_prev;
+	  dwarf2_per_objfile->all_comp_units[base_offset + (i - 1)]
+	    = create_cu_from_index_list (objfile, &section, is_dwz,
+					 sect_off_prev, length);
+	}
+      sect_off_prev = sect_off_next;
+    }
+}
+
+/* Read the CU list from the mapped index, and use it to create all
+   the CU objects for this objfile.  */
+
+static void
+create_cus_from_debug_names (struct objfile *objfile,
+			     const mapped_debug_names &map,
+			     const mapped_debug_names &dwz_map)
+{
+
+  dwarf2_per_objfile->n_comp_units = map.cu_count + dwz_map.cu_count;
+  dwarf2_per_objfile->all_comp_units
+    = XOBNEWVEC (&objfile->objfile_obstack, struct dwarf2_per_cu_data *,
+		 dwarf2_per_objfile->n_comp_units);
+
+  create_cus_from_debug_names_list (objfile, map, dwarf2_per_objfile->info,
+				    false /* is_dwz */,
+				    0 /* base_offset */);
+
+  if (dwz_map.cu_count == 0)
+    return;
+
+  dwz_file *dwz = dwarf2_get_dwz_file ();
+  create_cus_from_debug_names_list (objfile, dwz_map, dwz->info,
+				    true /* is_dwz */,
+				    map.cu_count /* base_offset */);
+}
+
+/* Read .debug_names.  If everything went ok, initialize the "quick"
+   elements of all the CUs and return true.  Otherwise, return false.  */
+
+static bool
+dwarf2_read_debug_names (struct objfile *objfile)
+{
+  mapped_debug_names local_map, dwz_map;
+
+  if (!read_debug_names_from_section (objfile, objfile_name (objfile),
+				      &dwarf2_per_objfile->debug_names,
+				      local_map))
+    return false;
+
+  /* Don't use the index if it's empty.  */
+  if (local_map.name_count == 0)
+    return false;
+
+  /* If there is a .dwz file, read it so we can get its CU list as
+     well.  */
+  dwz_file *dwz = dwarf2_get_dwz_file ();
+  if (dwz != NULL)
+    {
+      if (!read_debug_names_from_section (objfile,
+					  bfd_get_filename (dwz->dwz_bfd),
+					  &dwz->debug_names, dwz_map))
+	{
+	  warning (_("could not read '.debug_names' section from %s; skipping"),
+		   bfd_get_filename (dwz->dwz_bfd));
+	  return false;
+	}
+    }
+
+  create_cus_from_debug_names (objfile, local_map, dwz_map);
+
+  if (local_map.tu_count != 0)
+    {
+      /* We can only handle a single .debug_types when we have an
+	 index.  */
+      if (VEC_length (dwarf2_section_info_def, dwarf2_per_objfile->types) != 1)
+	return false;
+
+      dwarf2_section_info *section = VEC_index (dwarf2_section_info_def,
+						dwarf2_per_objfile->types, 0);
+
+      create_signatured_type_table_from_debug_names
+	(objfile, local_map, section, &dwarf2_per_objfile->abbrev);
+    }
+
+  create_addrmap_from_aranges (objfile, &dwarf2_per_objfile->debug_aranges);
+
+  dwarf2_per_objfile->debug_names_table.reset (new mapped_debug_names);
+  *dwarf2_per_objfile->debug_names_table = std::move (local_map);
+  dwarf2_per_objfile->using_index = 1;
+  dwarf2_per_objfile->quick_file_names_table =
+    create_quick_file_names_table (dwarf2_per_objfile->n_comp_units);
+
+  return true;
+}
+
+/* Symbol name hashing function as specified by DWARF-5.  */
+
+static uint32_t
+dwarf5_djb_hash (const char *str_)
+{
+  const unsigned char *str = (const unsigned char *) str_;
+
+  /* Note: tolower here ignores UTF-8, which isn't fully compliant.
+     See http://dwarfstd.org/ShowIssue.php?issue=161027.1.  */
+
+  uint32_t hash = 5381;
+  while (int c = *str++)
+    hash = hash * 33 + tolower (c);
+  return hash;
+}
+
+/* Type used to manage iterating over all CUs looking for a symbol for
+   .debug_names.  */
+
+class dw2_debug_names_iterator
+{
+public:
+  /* If WANT_SPECIFIC_BLOCK is true, only look for symbols in block
+     BLOCK_INDEX.  Otherwise BLOCK_INDEX is ignored.  */
+  dw2_debug_names_iterator (const mapped_debug_names &map,
+			    bool want_specific_block,
+			    block_enum block_index, domain_enum domain,
+			    const char *name)
+    : m_map (map), m_want_specific_block (want_specific_block),
+      m_block_index (block_index), m_domain (domain),
+      m_addr (find_vec_in_debug_names (map, name))
+  {}
+
+  dw2_debug_names_iterator (const mapped_debug_names &map,
+			    search_domain search, uint32_t namei)
+    : m_map (map),
+      m_search (search),
+      m_addr (find_vec_in_debug_names (map, namei))
+  {}
+
+  /* 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);
+  static const gdb_byte *find_vec_in_debug_names (const mapped_debug_names &map,
+						  uint32_t namei);
+
+  /* The internalized form of .debug_names.  */
+  const mapped_debug_names &m_map;
+
+  /* If true, only look for symbols that match BLOCK_INDEX.  */
+  const bool m_want_specific_block = false;
+
+  /* One of GLOBAL_BLOCK or STATIC_BLOCK.
+     Unused if !WANT_SPECIFIC_BLOCK - FIRST_LOCAL_BLOCK is an invalid
+     value.  */
+  const block_enum m_block_index = FIRST_LOCAL_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;
+};
+
+const char *
+mapped_debug_names::namei_to_name (uint32_t namei) 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
+    (dwarf2_per_objfile->objfile->obfd, 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)
+{
+  int (*cmp) (const char *, const char *);
+
+  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)
+	{
+	  gdb::unique_xmalloc_ptr<char> 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 (&symfile_complaints,
+		 _("Wrong .debug_names with name index %u but name_count=%u "
+		   "[in module %s]"),
+		 namei, map.name_count,
+		 objfile_name (dwarf2_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);
+
+#if 0 /* An expensive sanity check.  */
+	  if (namei_full_hash != dwarf5_djb_hash (namei_string))
+	    {
+	      complaint (&symfile_complaints,
+			 _("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)
+{
+  if (namei >= map.name_count)
+    {
+      complaint (&symfile_complaints,
+		 _("Wrong .debug_names with name index %u but name_count=%u "
+		   "[in module %s]"),
+		 namei, map.name_count,
+		 objfile_name (dwarf2_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;
+
+  bfd *const abfd = dwarf2_per_objfile->objfile->obfd;
+
+ 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 (&symfile_complaints,
+		 _("Wrong .debug_names undefined abbrev code %s "
+		   "[in module %s]"),
+		 pulongest (abbrev), objfile_name (dwarf2_per_objfile->objfile));
+      return NULL;
+    }
+  const mapped_debug_names::index_val &indexval = indexval_it->second;
+  bool have_is_static = false;
+  bool is_static;
+  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;
+	default:
+	  complaint (&symfile_complaints,
+		     _("Unsupported .debug_names form %s [in module %s]"),
+		     dwarf_form_name (attr.form),
+		     objfile_name (dwarf2_per_objfile->objfile));
+	  return NULL;
+	}
+      switch (attr.dw_idx)
+	{
+	case DW_IDX_compile_unit:
+	  /* Don't crash on bad data.  */
+	  if (ull >= (dwarf2_per_objfile->n_comp_units
+		      + dwarf2_per_objfile->n_type_units))
+	    {
+	      complaint (&symfile_complaints,
+			 _(".debug_names entry has bad CU index %s"
+			   " [in module %s]"),
+			 pulongest (ull),
+			 objfile_name (dwarf2_per_objfile->objfile));
+	      continue;
+	    }
+	  per_cu = dw2_get_cutu (ull);
+	  break;
+	case DW_IDX_GNU_internal:
+	  if (!m_map.augmentation_is_gdb)
+	    break;
+	  have_is_static = true;
+	  is_static = true;
+	  break;
+	case DW_IDX_GNU_external:
+	  if (!m_map.augmentation_is_gdb)
+	    break;
+	  have_is_static = true;
+	  is_static = false;
+	  break;
+	}
+    }
+
+  /* Skip if already read in.  */
+  if (per_cu->v.quick->compunit_symtab)
+    goto again;
+
+  /* Check static vs global.  */
+  if (have_is_static)
+    {
+      const bool want_static = m_block_index != GLOBAL_BLOCK;
+      if (m_want_specific_block && want_static != is_static)
+	goto again;
+    }
+
+  /* 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;
+    default:
+      break;
+    }
+
+  /* Match dw2_expand_symtabs_matching, symbol_kind and
+     debug_names::psymbol_tag.  */
+  switch (m_search)
     {
-      int j;
-      struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
-      struct quick_file_names *file_data;
-      void **slot;
-
-      QUIT;
-
-      per_cu->v.quick->mark = 0;
-
-      /* We only need to look at symtabs not already expanded.  */
-      if (per_cu->v.quick->compunit_symtab)
-	continue;
-
-      file_data = dw2_get_file_names (per_cu);
-      if (file_data == NULL)
-	continue;
-
-      if (htab_find (visited_not_found.get (), file_data) != NULL)
-	continue;
-      else if (htab_find (visited_found.get (), file_data) != NULL)
+    case VARIABLES_DOMAIN:
+      switch (indexval.dwarf_tag)
 	{
-	  per_cu->v.quick->mark = 1;
-	  continue;
+	case DW_TAG_variable:
+	  break;
+	default:
+	  goto again;
 	}
-
-      for (j = 0; j < file_data->num_file_names; ++j)
+      break;
+    case FUNCTIONS_DOMAIN:
+      switch (indexval.dwarf_tag)
 	{
-	  const char *this_real_name;
-
-	  if (file_matcher (file_data->file_names[j], false))
-	    {
-	      per_cu->v.quick->mark = 1;
-	      break;
-	    }
-
-	  /* 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 (file_data->file_names[j]),
-				true))
-	    continue;
-
-	  this_real_name = dw2_get_real_path (objfile, file_data, j);
-	  if (file_matcher (this_real_name, false))
-	    {
-	      per_cu->v.quick->mark = 1;
-	      break;
-	    }
+	case DW_TAG_subprogram:
+	  break;
+	default:
+	  goto again;
 	}
-
-      slot = htab_find_slot (per_cu->v.quick->mark
-			     ? visited_found.get ()
-			     : visited_not_found.get (),
-			     file_data, INSERT);
-      *slot = file_data;
+      break;
+    case TYPES_DOMAIN:
+      switch (indexval.dwarf_tag)
+	{
+	case DW_TAG_typedef:
+	case DW_TAG_structure_type:
+	  break;
+	default:
+	  goto again;
+	}
+      break;
+    default:
+      break;
     }
+
+  return per_cu;
 }
 
-static void
-dw2_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,
-   enum search_domain kind)
+static struct compunit_symtab *
+dw2_debug_names_lookup_symbol (struct objfile *objfile, int block_index_int,
+			       const char *name, domain_enum domain)
 {
-  int i;
-
+  const block_enum block_index = static_cast<block_enum> (block_index_int);
   dw2_setup (objfile);
 
-  /* index_table is NULL if OBJF_READNOW.  */
-  if (!dwarf2_per_objfile->index_table)
-    return;
-
-  dw_expand_symtabs_matching_file_matcher (file_matcher);
-
-  mapped_index &index = *dwarf2_per_objfile->index_table;
-
-  dw2_expand_symtabs_matching_symbol (index, lookup_name,
-				      symbol_matcher,
-				      kind, [&] (offset_type idx)
+  const auto &mapp = dwarf2_per_objfile->debug_names_table;
+  if (!mapp)
     {
-      dw2_expand_marked_cus (index, idx, objfile, file_matcher,
-			     expansion_notify, kind);
-    });
-}
+      /* index is NULL if OBJF_READNOW.  */
+      return NULL;
+    }
+  const auto &map = *mapp;
 
-/* A helper for dw2_find_pc_sect_compunit_symtab which finds the most specific
-   symtab.  */
+  dw2_debug_names_iterator iter (map, true /* want_specific_block */,
+				 block_index, domain, name);
 
-static struct compunit_symtab *
-recursively_find_pc_sect_compunit_symtab (struct compunit_symtab *cust,
-					  CORE_ADDR pc)
-{
-  int i;
+  struct compunit_symtab *stab_best = NULL;
+  struct dwarf2_per_cu_data *per_cu;
+  while ((per_cu = iter.next ()) != NULL)
+    {
+      struct symbol *sym, *with_opaque = NULL;
+      struct compunit_symtab *stab = dw2_instantiate_symtab (per_cu);
+      const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (stab);
+      struct block *block = BLOCKVECTOR_BLOCK (bv, block_index);
 
-  if (COMPUNIT_BLOCKVECTOR (cust) != NULL
-      && blockvector_contains_pc (COMPUNIT_BLOCKVECTOR (cust), pc))
-    return cust;
+      sym = block_find_symbol (block, name, domain,
+			       block_find_non_opaque_type_preferred,
+			       &with_opaque);
 
-  if (cust->includes == NULL)
-    return NULL;
+      /* Some caution must be observed with overloaded functions and
+	 methods, since the index will not contain any overload
+	 information (but NAME might contain it).  */
 
-  for (i = 0; cust->includes[i]; ++i)
-    {
-      struct compunit_symtab *s = cust->includes[i];
+      if (sym != NULL
+	  && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0)
+	return stab;
+      if (with_opaque != NULL
+	  && strcmp_iw (SYMBOL_SEARCH_NAME (with_opaque), name) == 0)
+	stab_best = stab;
 
-      s = recursively_find_pc_sect_compunit_symtab (s, pc);
-      if (s != NULL)
-	return s;
+      /* Keep looking through other CUs.  */
     }
 
-  return NULL;
+  return stab_best;
 }
 
-static struct compunit_symtab *
-dw2_find_pc_sect_compunit_symtab (struct objfile *objfile,
-				  struct bound_minimal_symbol msymbol,
-				  CORE_ADDR pc,
-				  struct obj_section *section,
-				  int warn_if_readin)
-{
-  struct dwarf2_per_cu_data *data;
-  struct compunit_symtab *result;
+/* 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.  */
 
+static void
+dw2_debug_names_dump (struct objfile *objfile)
+{
   dw2_setup (objfile);
-
-  if (!objfile->psymtabs_addrmap)
-    return NULL;
-
-  data = (struct dwarf2_per_cu_data *) addrmap_find (objfile->psymtabs_addrmap,
-						     pc);
-  if (!data)
-    return NULL;
-
-  if (warn_if_readin && data->v.quick->compunit_symtab)
-    warning (_("(Internal error: pc %s in read in CU, but not in symtab.)"),
-	     paddress (get_objfile_arch (objfile), pc));
-
-  result
-    = recursively_find_pc_sect_compunit_symtab (dw2_instantiate_symtab (data),
-						pc);
-  gdb_assert (result != NULL);
-  return result;
+  gdb_assert (dwarf2_per_objfile->using_index);
+  printf_filtered (".debug_names:");
+  if (dwarf2_per_objfile->debug_names_table)
+    printf_filtered (" exists\n");
+  else
+    printf_filtered (" faked for \"readnow\"\n");
+  printf_filtered ("\n");
 }
 
 static void
-dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
-			  void *data, int need_fullname)
+dw2_debug_names_expand_symtabs_for_function (struct objfile *objfile,
+					     const char *func_name)
 {
   dw2_setup (objfile);
 
-  if (!dwarf2_per_objfile->filenames_cache)
+  /* dwarf2_per_objfile->debug_names_table is NULL if OBJF_READNOW.  */
+  if (dwarf2_per_objfile->debug_names_table)
     {
-      dwarf2_per_objfile->filenames_cache.emplace ();
+      const mapped_debug_names &map = *dwarf2_per_objfile->debug_names_table;
 
-      htab_up visited (htab_create_alloc (10,
-					  htab_hash_pointer, htab_eq_pointer,
-					  NULL, xcalloc, xfree));
+      /* Note: It doesn't matter what we pass for block_index here.  */
+      dw2_debug_names_iterator iter (map, false /* want_specific_block */,
+				     GLOBAL_BLOCK, VAR_DOMAIN, func_name);
 
-      /* The rule is CUs specify all the files, including those used
-	 by any TU, so there's no need to scan TUs here.  We can
-	 ignore file names coming from already-expanded CUs.  */
+      struct dwarf2_per_cu_data *per_cu;
+      while ((per_cu = iter.next ()) != NULL)
+	dw2_instantiate_symtab (per_cu);
+    }
+}
 
-      for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
-	{
-	  struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
+static void
+dw2_debug_names_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,
+   enum search_domain kind)
+{
+  dw2_setup (objfile);
 
-	  if (per_cu->v.quick->compunit_symtab)
-	    {
-	      void **slot = htab_find_slot (visited.get (),
-					    per_cu->v.quick->file_names,
-					    INSERT);
+  /* debug_names_table is NULL if OBJF_READNOW.  */
+  if (!dwarf2_per_objfile->debug_names_table)
+    return;
 
-	      *slot = per_cu->v.quick->file_names;
-	    }
-	}
+  dw_expand_symtabs_matching_file_matcher (file_matcher);
 
-      for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
-	{
-	  struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
-	  struct quick_file_names *file_data;
-	  void **slot;
+  const mapped_debug_names &map = *dwarf2_per_objfile->debug_names_table;
 
-	  /* We only need to look at symtabs not already expanded.  */
-	  if (per_cu->v.quick->compunit_symtab)
-	    continue;
+  for (uint32_t namei = 0; namei < map.name_count; ++namei)
+    {
+      QUIT;
 
-	  file_data = dw2_get_file_names (per_cu);
-	  if (file_data == NULL)
-	    continue;
+      const char *const namei_string = map.namei_to_name (namei);
+      if (symbol_matcher != NULL && !symbol_matcher (namei_string))
+	continue;
 
-	  slot = htab_find_slot (visited.get (), file_data, INSERT);
-	  if (*slot)
-	    {
-	      /* Already visited.  */
-	      continue;
-	    }
-	  *slot = file_data;
+      /* The name was matched, now expand corresponding CUs that were
+	 marked.  */
+      dw2_debug_names_iterator iter (map, kind, namei);
 
-	  for (int j = 0; j < file_data->num_file_names; ++j)
-	    {
-	      const char *filename = file_data->file_names[j];
-	      dwarf2_per_objfile->filenames_cache->seen (filename);
-	    }
-	}
+      struct dwarf2_per_cu_data *per_cu;
+      while ((per_cu = iter.next ()) != NULL)
+	dw2_expand_symtabs_matching_one (per_cu, file_matcher,
+					 expansion_notify);
     }
-
-  dwarf2_per_objfile->filenames_cache->traverse ([&] (const char *filename)
-    {
-      gdb::unique_xmalloc_ptr<char> this_real_name;
-
-      if (need_fullname)
-	this_real_name = gdb_realpath (filename);
-      (*fun) (filename, this_real_name.get (), data);
-    });
-}
-
-static int
-dw2_has_symbols (struct objfile *objfile)
-{
-  return 1;
 }
 
-const struct quick_symbol_functions dwarf2_gdb_index_functions =
+const struct quick_symbol_functions dwarf2_debug_names_functions =
 {
   dw2_has_symbols,
   dw2_find_last_source_symtab,
   dw2_forget_cached_source_info,
   dw2_map_symtabs_matching_filename,
-  dw2_lookup_symbol,
+  dw2_debug_names_lookup_symbol,
   dw2_print_stats,
-  dw2_dump,
+  dw2_debug_names_dump,
   dw2_relocate,
-  dw2_expand_symtabs_for_function,
+  dw2_debug_names_expand_symtabs_for_function,
   dw2_expand_all_symtabs,
   dw2_expand_symtabs_with_fullname,
   dw2_map_matching_symbols,
-  dw2_expand_symtabs_matching,
+  dw2_debug_names_expand_symtabs_matching,
   dw2_find_pc_sect_compunit_symtab,
   NULL,
   dw2_map_symbol_filenames
@@ -5365,6 +6468,9 @@ dwarf2_initialize_objfile (struct objfile *objfile)
       return elf_sym_fns_gdb_index;
     }
 
+  if (dwarf2_read_debug_names (objfile))
+    return elf_sym_fns_debug_names;
+
   if (dwarf2_read_index (objfile))
     return elf_sym_fns_gdb_index;
 
@@ -24867,22 +25973,6 @@ recursively_write_psymbols (struct objfile *objfile,
 		  1);
 }
 
-/* Symbol name hashing function as specified by DWARF-5.  */
-
-static uint32_t
-dwarf5_djb_hash (const char *str_)
-{
-  const unsigned char *str = (const unsigned char *) str_;
-
-  /* Note: tolower here ignores UTF-8, which isn't fully compliant.
-     See http://dwarfstd.org/ShowIssue.php?issue=161027.1.  */
-
-  uint32_t hash = 5381;
-  while (int c = *str++)
-    hash = hash * 33 + tolower (c);
-  return hash;
-}
-
 /* DWARF-5 .debug_names builder.  */
 class debug_names
 {
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 904696f..31288a9 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -1403,6 +1403,23 @@ const struct sym_fns elf_sym_fns_gdb_index =
   &dwarf2_gdb_index_functions
 };
 
+/* The same as elf_sym_fns, but not registered and uses the
+   DWARF-specific .debug_names index rather than psymtab.  */
+const struct sym_fns elf_sym_fns_debug_names =
+{
+  elf_new_init,			/* init anything gbl to entire symab */
+  elf_symfile_init,		/* read initial info, setup for sym_red() */
+  elf_symfile_read,		/* read a symbol file into symtab */
+  NULL,				/* sym_read_psymbols */
+  elf_symfile_finish,		/* finished with file, cleanup */
+  default_symfile_offsets,	/* Translate ext. to int. relocatin */
+  elf_symfile_segments,		/* Get segment information from a file.  */
+  NULL,
+  default_symfile_relocate,	/* Relocate a debug section.  */
+  &elf_probe_fns,		/* sym_probe_fns */
+  &dwarf2_debug_names_functions
+};
+
 /* STT_GNU_IFUNC resolver vector to be installed to gnu_ifunc_fns_p.  */
 
 static const struct gnu_ifunc_fns elf_gnu_ifunc_fns =
diff --git a/gdb/psymtab.h b/gdb/psymtab.h
index f0c9ae7..17ceb22 100644
--- a/gdb/psymtab.h
+++ b/gdb/psymtab.h
@@ -33,6 +33,7 @@ extern struct bcache *psymbol_bcache_get_bcache (struct psymbol_bcache *);
 extern const struct quick_symbol_functions psym_functions;
 
 extern const struct quick_symbol_functions dwarf2_gdb_index_functions;
+extern const struct quick_symbol_functions dwarf2_debug_names_functions;
 
 /* Ensure that the partial symbols for OBJFILE have been loaded.  If
    VERBOSE is non-zero, then this will print a message when symbols
diff --git a/gdb/symfile.h b/gdb/symfile.h
index 194dccf..e903c60 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -582,6 +582,8 @@ struct dwarf2_debug_sections {
   struct dwarf2_section_names frame;
   struct dwarf2_section_names eh_frame;
   struct dwarf2_section_names gdb_index;
+  struct dwarf2_section_names debug_names;
+  struct dwarf2_section_names debug_aranges;
   /* This field has no meaning, but exists solely to catch changes to
      this structure which are not reflected in some instance.  */
   int sentinel;
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 53a2ca4..48bad29 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,14 @@
+2017-12-08  Jan Kratochvil  <jan.kratochvil@redhat.com>
+	    Pedro Alves  <palves@redhat.com>
+
+	* gdb.base/maint.exp (check for .gdb_index): Check also for
+	.debug_names.
+	* gdb.dlang/watch-loc.c (.debug_aranges): New.
+	* gdb.dwarf2/dw2-case-insensitive-debug.S: Likewise.
+	* gdb.dwarf2/gdb-index.exp (check if index present, .gdb_index used)
+	(.gdb_index used after symbol reloading): Support also .debug_names.
+	* gdb.mi/dw2-ref-missing-frame-func.c (.debug_aranges): New.
+
 2017-12-08  Yao Qi  <yao.qi@linaro.org>
 
 	* gdb.arch/aarch64-tagged-pointer.c (main): Update.
diff --git a/gdb/testsuite/gdb.base/maint.exp b/gdb/testsuite/gdb.base/maint.exp
index 782a21c..8d1a4d0 100644
--- a/gdb/testsuite/gdb.base/maint.exp
+++ b/gdb/testsuite/gdb.base/maint.exp
@@ -89,10 +89,13 @@ if ![runto_main] then {
         perror "tests suppressed"
 }
 
-# If we're using .gdb_index there will be no psymtabs.
+# If we're using .gdb_index or .debug_names there will be no psymtabs.
 set have_gdb_index 0
-gdb_test_multiple "maint info sections .gdb_index" "check for .gdb_index" {
-    -re ": .gdb_index.*$gdb_prompt $" {
+gdb_test_multiple "maint info sections .gdb_index .debug_names" "check for .gdb_index" {
+    -re ": \\.gdb_index .*\r\n$gdb_prompt $" {
+	set have_gdb_index 1
+    }
+    -re ": \\.debug_names .*\r\n$gdb_prompt $" {
 	set have_gdb_index 1
     }
     -re ".*$gdb_prompt $" {
diff --git a/gdb/testsuite/gdb.dlang/watch-loc.c b/gdb/testsuite/gdb.dlang/watch-loc.c
index 0ffc377..3b993db 100644
--- a/gdb/testsuite/gdb.dlang/watch-loc.c
+++ b/gdb/testsuite/gdb.dlang/watch-loc.c
@@ -34,3 +34,23 @@ main (void)
   return _Dmain ();
 }
 
+/* The .debug_names-based index support depends on .debug_aranges
+   generated by GCC.  (.gdb_index includes a gdb-generated map
+   instead.)  */
+asm (
+"	.pushsection	.debug_aranges,\"\",@progbits \n"
+"	.4byte	.Laranges_end - .Laranges_start \n"	// Length of Address Ranges Info
+".Laranges_start: \n"
+"	.2byte	0x2 \n"	// DWARF Version
+"	.4byte	0 \n" // .Ldebug_info0 - Offset of Compilation Unit Info
+"	.byte	4 \n"	// Size of Address
+"	.byte	0 \n"	// Size of Segment Descriptor
+"	.2byte	0 \n"	// Pad to 16 byte boundary
+"	.2byte	0 \n"
+"	.4byte	_Dmain \n"	// Address
+"	.4byte	0x1000 \n"	// Length
+"	.4byte	0 \n"
+"	.4byte	0 \n"
+".Laranges_end: \n"
+"	.popsection \n"
+);
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-case-insensitive-debug.S b/gdb/testsuite/gdb.dwarf2/dw2-case-insensitive-debug.S
index 3bbd725..ad19f81 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-case-insensitive-debug.S
+++ b/gdb/testsuite/gdb.dwarf2/dw2-case-insensitive-debug.S
@@ -57,6 +57,24 @@
 	.byte		0			/* End of children of CU */
 .Lcu1_end:
 
+	/* The .debug_names-based index support depends on
+	   .debug_aranges generated by GCC.  (.gdb_index includes a
+	   gdb-generated map instead.)	*/
+	.section	.debug_aranges,"",@progbits
+	.4byte	.Laranges_end - .Laranges_start	// Length of Address Ranges Info
+.Laranges_start:
+	.2byte	0x2	// DWARF Version
+	.4byte	0 // .Ldebug_info0 - Offset of Compilation Unit Info
+	.byte	PTRBITS / 8	// Size of Address
+	.byte	0	// Size of Segment Descriptor
+	.2byte	0	// Pad to 16 byte boundary
+	.2byte	0
+	PTRBYTE	cu_text_start	// Address
+	PTRBYTE	0x1000 // cu_text_end - cu_text_start	// Length
+	PTRBYTE	0
+	PTRBYTE	0
+.Laranges_end:
+
 /* Abbrev table */
 	.section .debug_abbrev
 .Labbrev1_begin:
diff --git a/gdb/testsuite/gdb.dwarf2/gdb-index.exp b/gdb/testsuite/gdb.dwarf2/gdb-index.exp
index c925b1e..c7ddbbf 100644
--- a/gdb/testsuite/gdb.dwarf2/gdb-index.exp
+++ b/gdb/testsuite/gdb.dwarf2/gdb-index.exp
@@ -58,7 +58,7 @@ proc add_gdb_index { program } {
     return ${program_with_index}
 }
 
-# Build a copy of the program with .gdb_index.
+# Build a copy of the program with an index (.gdb_index/.debug_names).
 # But only if the toolchain didn't already create one: gdb doesn't support
 # building an index from a program already using one.
 
@@ -67,6 +67,9 @@ gdb_test_multiple "mt print objfiles ${testfile}" $test {
     -re "gdb_index.*${gdb_prompt} $" {
 	set binfile_with_index $binfile
     }
+    -re "debug_names.*${gdb_prompt} $" {
+	set binfile_with_index $binfile
+    }
     -re "Psymtabs.*${gdb_prompt} $" {
 	set binfile_with_index [add_gdb_index $binfile]
 	if { ${binfile_with_index} == "" } {
@@ -75,16 +78,16 @@ gdb_test_multiple "mt print objfiles ${testfile}" $test {
     }
 }
 
-# Ok, we have a copy of $binfile with .gdb_index.
+# Ok, we have a copy of $binfile with an index.
 # Restart gdb and verify the index was used.
 
 clean_restart ${binfile_with_index}
 gdb_test "mt print objfiles ${testfile}" \
-    "gdb_index.*" \
-    ".gdb_index used"
+    "(gdb_index|debug_names).*" \
+    "index used"
 
-# Make gdb re-read symbols and see if .gdb_index still gets used.
-# symtab/15885
+# Make gdb re-read symbols and see if .gdb_index/.debug_names still
+# gets used.  symtab/15885
 
 # There is gdb_touch_execfile, but it doesn't handle remote hosts.
 # Is touch portable enough?
@@ -98,5 +101,5 @@ if ![runto_main] {
     return -1
 }
 gdb_test "mt print objfiles ${testfile}" \
-    "gdb_index.*" \
-    ".gdb_index used after symbol reloading"
+    "(gdb_index|debug_names).*" \
+    "index used after symbol reloading"
diff --git a/gdb/testsuite/gdb.mi/dw2-ref-missing-frame-func.c b/gdb/testsuite/gdb.mi/dw2-ref-missing-frame-func.c
index 0c2a153..785cf43 100644
--- a/gdb/testsuite/gdb.mi/dw2-ref-missing-frame-func.c
+++ b/gdb/testsuite/gdb.mi/dw2-ref-missing-frame-func.c
@@ -52,3 +52,24 @@ asm ("func_loopfb_end:");
 
 asm (".globl cu_text_end");
 asm ("cu_text_end:");
+
+/* The .debug_names-based index support depends on .debug_aranges
+   generated by GCC.  (.gdb_index includes a gdb-generated map
+   instead.)  */
+asm (
+"	.pushsection	.debug_aranges,\"\",@progbits \n"
+"	.4byte	.Laranges_end - .Laranges_start \n"	// Length of Address Ranges Info
+".Laranges_start: \n"
+"	.2byte	0x2 \n"	// DWARF Version
+"	.4byte	0 \n" // .Ldebug_info0 - Offset of Compilation Unit Info
+"	.byte	4 \n"	// Size of Address
+"	.byte	0 \n"	// Size of Segment Descriptor
+"	.2byte	0 \n"	// Pad to 16 byte boundary
+"	.2byte	0 \n"
+"	.4byte	cu_text_start \n"	// Address
+"	.4byte	cu_text_end - cu_text_start \n"	// Length
+"	.4byte	0 \n"
+"	.4byte	0 \n"
+".Laranges_end: \n"
+"	.popsection \n"
+);
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index b1c634c..142845b 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -174,6 +174,8 @@ static const struct dwarf2_debug_sections dwarf2_xcoff_names = {
   { ".dwframe", NULL },
   { NULL, NULL }, /* eh_frame */
   { NULL, NULL }, /* gdb_index */
+  { NULL, NULL }, /* debug_names */
+  { NULL, NULL }, /* debug_aranges */
   23
 };


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]