dwarf2read: Silence -Wenum-compare-switch warning
[binutils-gdb.git] / gdb / dwarf2read.c
index 0c9e275850fad139a89123b6e04d86dc6d72d4fb..fcd5e995366235cf31a6e3cb6888b339da00fb7c 100644 (file)
 #include "common/function-view.h"
 #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>
 #include <sys/types.h>
 #include <algorithm>
 #include <unordered_set>
 #include <unordered_map>
+#include "selftest.h"
+#include <cmath>
+#include <set>
+#include <forward_list>
 
 typedef struct symbol *symbolp;
 DEF_VEC_P (symbolp);
@@ -180,30 +187,180 @@ DEF_VEC_I (offset_type);
     GDB_INDEX_CU_SET_VALUE((cu_index), (value)); \
   } while (0)
 
+#if WORDS_BIGENDIAN
+
+/* Convert VALUE between big- and little-endian.  */
+
+static offset_type
+byte_swap (offset_type value)
+{
+  offset_type result;
+
+  result = (value & 0xff) << 24;
+  result |= (value & 0xff00) << 8;
+  result |= (value & 0xff0000) >> 8;
+  result |= (value & 0xff000000) >> 24;
+  return result;
+}
+
+#define MAYBE_SWAP(V)  byte_swap (V)
+
+#else
+#define MAYBE_SWAP(V) static_cast<offset_type> (V)
+#endif /* WORDS_BIGENDIAN */
+
+/* An index into a (C++) symbol name component in a symbol name as
+   recorded in the mapped_index's symbol table.  For each C++ symbol
+   in the symbol table, we record one entry for the start of each
+   component in the symbol in a table of name components, and then
+   sort the table, in order to be able to binary search symbol names,
+   ignoring leading namespaces, both completion and regular look up.
+   For example, for symbol "A::B::C", we'll have an entry that points
+   to "A::B::C", another that points to "B::C", and another for "C".
+   Note that function symbols in GDB index have no parameter
+   information, just the function/method names.  You can convert a
+   name_component to a "const char *" using the
+   'mapped_index::symbol_name_at(offset_type)' method.  */
+
+struct name_component
+{
+  /* Offset in the symbol name where the component starts.  Stored as
+     a (32-bit) offset instead of a pointer to save memory and improve
+     locality on 64-bit architectures.  */
+  offset_type name_offset;
+
+  /* The symbol's index in the symbol and constant pool tables of a
+     mapped_index.  */
+  offset_type idx;
+};
+
+/* Base class containing bits shared by both .gdb_index and
+   .debug_name indexes.  */
+
+struct mapped_index_base
+{
+  /* The name_component table (a sorted vector).  See name_component's
+     description above.  */
+  std::vector<name_component> name_components;
+
+  /* How NAME_COMPONENTS is sorted.  */
+  enum case_sensitivity name_components_casing;
+
+  /* Return the number of names in the symbol table.  */
+  virtual size_t symbol_name_count () const = 0;
+
+  /* Get the name of the symbol at IDX in the symbol table.  */
+  virtual const char *symbol_name_at (offset_type idx) const = 0;
+
+  /* Return whether the name at IDX in the symbol table should be
+     ignored.  */
+  virtual bool symbol_name_slot_invalid (offset_type idx) const
+  {
+    return false;
+  }
+
+  /* Build the symbol name component sorted vector, if we haven't
+     yet.  */
+  void build_name_components ();
+
+  /* Returns the lower (inclusive) and upper (exclusive) bounds of the
+     possible matches for LN_NO_PARAMS in the name component
+     vector.  */
+  std::pair<std::vector<name_component>::const_iterator,
+           std::vector<name_component>::const_iterator>
+    find_name_components_bounds (const lookup_name_info &ln_no_params) const;
+
+  /* Prevent deleting/destroying via a base class pointer.  */
+protected:
+  ~mapped_index_base() = default;
+};
+
 /* A description of the mapped index.  The file format is described in
    a comment by the code that writes the index.  */
-struct mapped_index
+struct mapped_index final : public mapped_index_base
 {
+  /* A slot/bucket in the symbol table hash.  */
+  struct symbol_table_slot
+  {
+    const offset_type name;
+    const offset_type vec;
+  };
+
   /* Index data format version.  */
   int version;
 
   /* The total length of the buffer.  */
   off_t total_size;
 
-  /* A pointer to the address table data.  */
-  const gdb_byte *address_table;
-
-  /* Size of the address table data in bytes.  */
-  offset_type address_table_size;
+  /* The address table data.  */
+  gdb::array_view<const gdb_byte> address_table;
 
   /* The symbol table, implemented as a hash table.  */
-  const offset_type *symbol_table;
-
-  /* Size in slots, each slot is 2 offset_types.  */
-  offset_type symbol_table_slots;
+  gdb::array_view<symbol_table_slot> symbol_table;
 
   /* A pointer to the constant pool.  */
   const char *constant_pool;
+
+  bool symbol_name_slot_invalid (offset_type idx) const override
+  {
+    const auto &bucket = this->symbol_table[idx];
+    return bucket.name == 0 && bucket.vec;
+  }
+
+  /* Convenience method to get at the name of the symbol at IDX in the
+     symbol table.  */
+  const char *symbol_name_at (offset_type idx) const override
+  { return this->constant_pool + MAYBE_SWAP (this->symbol_table[idx].name); }
+
+  size_t symbol_name_count () const override
+  { return this->symbol_table.size (); }
+};
+
+/* A description of the mapped .debug_names.
+   Uninitialized map has CU_COUNT 0.  */
+struct mapped_debug_names final : public mapped_index_base
+{
+  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;
+
+  /* Implementation of the mapped_index_base virtual interface, for
+     the name_components cache.  */
+
+  const char *symbol_name_at (offset_type idx) const override
+  { return namei_to_name (idx); }
+
+  size_t symbol_name_count () const override
+  { return this->name_count; }
 };
 
 typedef struct dwarf2_per_cu_data *dwarf2_per_cu_ptr;
@@ -223,85 +380,110 @@ struct tu_stats
 
 struct dwarf2_per_objfile
 {
-  struct dwarf2_section_info info;
-  struct dwarf2_section_info abbrev;
-  struct dwarf2_section_info line;
-  struct dwarf2_section_info loc;
-  struct dwarf2_section_info loclists;
-  struct dwarf2_section_info macinfo;
-  struct dwarf2_section_info macro;
-  struct dwarf2_section_info str;
-  struct dwarf2_section_info line_str;
-  struct dwarf2_section_info ranges;
-  struct dwarf2_section_info rnglists;
-  struct dwarf2_section_info addr;
-  struct dwarf2_section_info frame;
-  struct dwarf2_section_info eh_frame;
-  struct dwarf2_section_info gdb_index;
+  /* Construct a dwarf2_per_objfile for OBJFILE.  NAMES points to the
+     dwarf2 section names, or is NULL if the standard ELF names are
+     used.  */
+  dwarf2_per_objfile (struct objfile *objfile,
+                     const dwarf2_debug_sections *names);
 
-  VEC (dwarf2_section_info_def) *types;
+  ~dwarf2_per_objfile ();
+
+  DISABLE_COPY_AND_ASSIGN (dwarf2_per_objfile);
+
+  /* Free all cached compilation units.  */
+  void free_cached_comp_units ();
+private:
+  /* This function is mapped across the sections and remembers the
+     offset and size of each of the debugging sections we are
+     interested in.  */
+  void locate_sections (bfd *abfd, asection *sectp,
+                       const dwarf2_debug_sections &names);
+
+public:
+  dwarf2_section_info info {};
+  dwarf2_section_info abbrev {};
+  dwarf2_section_info line {};
+  dwarf2_section_info loc {};
+  dwarf2_section_info loclists {};
+  dwarf2_section_info macinfo {};
+  dwarf2_section_info macro {};
+  dwarf2_section_info str {};
+  dwarf2_section_info line_str {};
+  dwarf2_section_info ranges {};
+  dwarf2_section_info rnglists {};
+  dwarf2_section_info addr {};
+  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;
 
   /* Back link.  */
-  struct objfile *objfile;
+  struct objfile *objfile = NULL;
 
   /* Table of all the compilation units.  This is used to locate
      the target compilation unit of a particular reference.  */
-  struct dwarf2_per_cu_data **all_comp_units;
+  struct dwarf2_per_cu_data **all_comp_units = NULL;
 
   /* The number of compilation units in ALL_COMP_UNITS.  */
-  int n_comp_units;
+  int n_comp_units = 0;
 
   /* The number of .debug_types-related CUs.  */
-  int n_type_units;
+  int n_type_units = 0;
 
   /* The number of elements allocated in all_type_units.
      If there are skeleton-less TUs, we add them to all_type_units lazily.  */
-  int n_allocated_type_units;
+  int n_allocated_type_units = 0;
 
   /* The .debug_types-related CUs (TUs).
      This is stored in malloc space because we may realloc it.  */
-  struct signatured_type **all_type_units;
+  struct signatured_type **all_type_units = NULL;
 
   /* Table of struct type_unit_group objects.
      The hash key is the DW_AT_stmt_list value.  */
-  htab_t type_unit_groups;
+  htab_t type_unit_groups {};
 
   /* A table mapping .debug_types signatures to its signatured_type entry.
      This is NULL if the .debug_types section hasn't been read in yet.  */
-  htab_t signatured_types;
+  htab_t signatured_types {};
 
   /* Type unit statistics, to see how well the scaling improvements
      are doing.  */
-  struct tu_stats tu_stats;
+  struct tu_stats tu_stats {};
 
   /* A chain of compilation units that are currently read in, so that
      they can be freed later.  */
-  struct dwarf2_per_cu_data *read_in_chain;
+  dwarf2_per_cu_data *read_in_chain = NULL;
 
   /* A table mapping DW_AT_dwo_name values to struct dwo_file objects.
      This is NULL if the table hasn't been allocated yet.  */
-  htab_t dwo_files;
+  htab_t dwo_files {};
 
-  /* Non-zero if we've check for whether there is a DWP file.  */
-  int dwp_checked;
+  /* True if we've checked for whether there is a DWP file.  */
+  bool dwp_checked = false;
 
   /* The DWP file if there is one, or NULL.  */
-  struct dwp_file *dwp_file;
+  struct dwp_file *dwp_file = NULL;
 
   /* The shared '.dwz' file, if one exists.  This is used when the
      original data was compressed using 'dwz -m'.  */
-  struct dwz_file *dwz_file;
+  struct dwz_file *dwz_file = NULL;
 
-  /* A flag indicating wether this objfile has a section loaded at a
+  /* A flag indicating whether this objfile has a section loaded at a
      VMA of 0.  */
-  int has_section_at_zero;
+  bool has_section_at_zero = false;
 
   /* True if we are using the mapped index,
      or we are faking it for OBJF_READNOW's sake.  */
-  unsigned char using_index;
+  bool using_index = false;
 
   /* The mapped index, or NULL if .gdb_index is missing or not being used.  */
-  struct mapped_index *index_table;
+  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
@@ -310,22 +492,26 @@ struct dwarf2_per_objfile
      sorted all the TUs into "type unit groups", grouped by their
      DW_AT_stmt_list value.  Therefore the only sharing done here is with a
      CU and its associated TU group if there is one.  */
-  htab_t quick_file_names_table;
+  htab_t quick_file_names_table {};
 
   /* Set during partial symbol reading, to prevent queueing of full
      symbols.  */
-  int reading_partial_symbols;
+  bool reading_partial_symbols = false;
 
   /* Table mapping type DIEs to their struct type *.
      This is NULL if not allocated yet.
      The mapping is done via (CU/TU + DIE offset) -> type.  */
-  htab_t die_type_hash;
+  htab_t die_type_hash {};
 
   /* The CUs we recently read.  */
-  VEC (dwarf2_per_cu_ptr) *just_read_cus;
+  VEC (dwarf2_per_cu_ptr) *just_read_cus = NULL;
 
   /* Table containing line_header indexed by offset and offset_in_dwz.  */
-  htab_t line_header_hash;
+  htab_t line_header_hash {};
+
+  /* Table containing all filenames.  This is an optional because the
+     table is lazily constructed on first access.  */
+  gdb::optional<filename_seen_cache> filenames_cache;
 };
 
 static struct dwarf2_per_objfile *dwarf2_per_objfile;
@@ -353,6 +539,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
 };
 
@@ -519,6 +707,12 @@ struct dwarf2_cu
 
   /* Header data from the line table, during full symbol processing.  */
   struct line_header *line_header;
+  /* Non-NULL if LINE_HEADER is owned by this DWARF_CU.  Otherwise,
+     it's owned by dwarf2_per_objfile::line_header_hash.  If non-NULL,
+     this is the DW_TAG_compile_unit die for this CU.  We'll hold on
+     to the line header as long as this DIE is being processed.  See
+     process_die_scope.  */
+  die_info *line_header_die_owner;
 
   /* A list of methods which need to have physnames computed
      after all type information has been read.  */
@@ -571,7 +765,7 @@ struct dwarf2_cu
   unsigned int checked_producer : 1;
   unsigned int producer_is_gxx_lt_4_6 : 1;
   unsigned int producer_is_gcc_lt_4_3 : 1;
-  unsigned int producer_is_icc : 1;
+  unsigned int producer_is_icc_lt_14 : 1;
 
   /* When set, the file that we're processing is known to have
      debugging info for C++ namespaces.  GCC 3.3.x did not produce
@@ -854,12 +1048,11 @@ struct dwo_file
      sections (for lack of a better name).  */
   struct dwo_sections sections;
 
-  /* The CU in the file.
-     We only support one because having more than one requires hacking the
-     dwo_name of each to match, which is highly unlikely to happen.
-     Doing this means all TUs can share comp_dir: We also assume that
-     DW_AT_comp_dir across all TUs in a DWO file will be identical.  */
-  struct dwo_unit *cu;
+  /* The CUs in the file.
+     Each element is a struct dwo_unit. Multiple CUs per DWO are supported as
+     an extension to handle LLVM's Link Time Optimization output (where
+     multiple source files may be compiled into a single object/dwo pair). */
+  htab_t cus;
 
   /* Table of TUs in the file.
      Each element is a struct dwo_unit.  */
@@ -1014,6 +1207,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;
@@ -1430,10 +1624,10 @@ struct fnfieldlist
   struct nextfnfield *head;
 };
 
-struct typedef_field_list
+struct decl_field_list
 {
-  struct typedef_field field;
-  struct typedef_field_list *next;
+  struct decl_field field;
+  struct decl_field_list *next;
 };
 
 /* The routines that read and process dies for a C struct or C++ class
@@ -1453,10 +1647,6 @@ struct field_info
     /* Set if the accesibility of one of the fields is not public.  */
     int non_public_fields;
 
-    /* Member function fields array, entries are allocated in the order they
-       are encountered in the object file.  */
-    struct nextfnfield *fnfields;
-
     /* Member function fieldlist array, contains name of possibly overloaded
        member function, number of overloaded member functions and a pointer
        to the head of the member function field chain.  */
@@ -1467,8 +1657,13 @@ struct field_info
 
     /* typedefs defined inside this class.  TYPEDEF_FIELD_LIST contains head of
        a NULL terminated list of TYPEDEF_FIELD_LIST_COUNT elements.  */
-    struct typedef_field_list *typedef_field_list;
+    struct decl_field_list *typedef_field_list;
     unsigned typedef_field_list_count;
+
+    /* Nested types defined by this class and the number of elements in this
+       list.  */
+    struct decl_field_list *nested_types_list;
+    unsigned nested_types_list_count;
   };
 
 /* One item on the queue of compilation units to read in full symbols
@@ -1504,14 +1699,17 @@ static const char *get_section_name (const struct dwarf2_section_info *);
 
 static const char *get_section_file_name (const struct dwarf2_section_info *);
 
-static void dwarf2_locate_sections (bfd *, asection *, void *);
-
 static void dwarf2_find_base_address (struct die_info *die,
                                      struct dwarf2_cu *cu);
 
 static struct partial_symtab *create_partial_symtab
   (struct dwarf2_per_cu_data *per_cu, const char *name);
 
+static void build_type_psymtabs_reader (const struct die_reader_specs *reader,
+                                       const gdb_byte *info_ptr,
+                                       struct die_info *type_unit_die,
+                                       int has_children, void *data);
+
 static void dwarf2_build_psymtabs_hard (struct objfile *);
 
 static void scan_partial_symbols (struct partial_die_info *,
@@ -1617,6 +1815,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 *);
@@ -1713,6 +1914,8 @@ static void read_lexical_block_scope (struct die_info *, struct dwarf2_cu *);
 
 static void read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu);
 
+static void read_variable (struct die_info *die, struct dwarf2_cu *cu);
+
 static int dwarf2_ranges_read (unsigned, CORE_ADDR *, CORE_ADDR *,
                               struct dwarf2_cu *, struct partial_symtab *);
 
@@ -2130,26 +2333,6 @@ line_header_eq_voidp (const void *item_lhs, const void *item_rhs)
 }
 
 \f
-#if WORDS_BIGENDIAN
-
-/* Convert VALUE between big- and little-endian.  */
-static offset_type
-byte_swap (offset_type value)
-{
-  offset_type result;
-
-  result = (value & 0xff) << 24;
-  result |= (value & 0xff00) << 8;
-  result |= (value & 0xff0000) >> 8;
-  result |= (value & 0xff000000) >> 24;
-  return result;
-}
-
-#define MAYBE_SWAP(V)  byte_swap (V)
-
-#else
-#define MAYBE_SWAP(V) static_cast<offset_type> (V)
-#endif /* WORDS_BIGENDIAN */
 
 /* Read the given attribute value as an address, taking the attribute's
    form into account.  */
@@ -2182,7 +2365,55 @@ attr_value_as_address (struct attribute *attr)
 }
 
 /* The suffix for an index file.  */
-#define INDEX_SUFFIX ".gdb-index"
+#define INDEX4_SUFFIX ".gdb-index"
+#define INDEX5_SUFFIX ".debug_names"
+#define DEBUG_STR_SUFFIX ".debug_str"
+
+/* See declaration.  */
+
+dwarf2_per_objfile::dwarf2_per_objfile (struct objfile *objfile_,
+                                       const dwarf2_debug_sections *names)
+  : objfile (objfile_)
+{
+  if (names == NULL)
+    names = &dwarf2_elf_names;
+
+  bfd *obfd = objfile->obfd;
+
+  for (asection *sec = obfd->sections; sec != NULL; sec = sec->next)
+    locate_sections (obfd, sec, *names);
+}
+
+dwarf2_per_objfile::~dwarf2_per_objfile ()
+{
+  /* Cached DIE trees use xmalloc and the comp_unit_obstack.  */
+  free_cached_comp_units ();
+
+  if (quick_file_names_table)
+    htab_delete (quick_file_names_table);
+
+  if (line_header_hash)
+    htab_delete (line_header_hash);
+
+  /* Everything else should be on the objfile obstack.  */
+}
+
+/* See declaration.  */
+
+void
+dwarf2_per_objfile::free_cached_comp_units ()
+{
+  dwarf2_per_cu_data *per_cu = read_in_chain;
+  dwarf2_per_cu_data **last_chain = &read_in_chain;
+  while (per_cu != NULL)
+    {
+      dwarf2_per_cu_data *next_cu = per_cu->cu->read_in_chain;
+
+      free_heap_comp_unit (per_cu->cu);
+      *last_chain = next_cu;
+      per_cu = next_cu;
+    }
+}
 
 /* Try to locate the sections we need for DWARF 2 debugging
    information and return true if we have enough to do something.
@@ -2193,6 +2424,9 @@ int
 dwarf2_has_info (struct objfile *objfile,
                  const struct dwarf2_debug_sections *names)
 {
+  if (objfile->flags & OBJF_READNEVER)
+    return 0;
+
   dwarf2_per_objfile = ((struct dwarf2_per_objfile *)
                        objfile_data (objfile, dwarf2_objfile_data_key));
   if (!dwarf2_per_objfile)
@@ -2201,13 +2435,8 @@ dwarf2_has_info (struct objfile *objfile,
       struct dwarf2_per_objfile *data
        = XOBNEW (&objfile->objfile_obstack, struct dwarf2_per_objfile);
 
-      memset (data, 0, sizeof (*data));
-      set_objfile_data (objfile, dwarf2_objfile_data_key, data);
-      dwarf2_per_objfile = data;
-
-      bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections,
-                             (void *) names);
-      dwarf2_per_objfile->objfile = objfile;
+      dwarf2_per_objfile = new (data) struct dwarf2_per_objfile (objfile, names);
+      set_objfile_data (objfile, dwarf2_objfile_data_key, dwarf2_per_objfile);
     }
   return (!dwarf2_per_objfile->info.is_virtual
          && dwarf2_per_objfile->info.s.section != NULL
@@ -2313,95 +2542,88 @@ section_is_p (const char *section_name,
   return 0;
 }
 
-/* This function is mapped across the sections and remembers the
-   offset and size of each of the debugging sections we are interested
-   in.  */
+/* See declaration.  */
 
-static void
-dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
+void
+dwarf2_per_objfile::locate_sections (bfd *abfd, asection *sectp,
+                                    const dwarf2_debug_sections &names)
 {
-  const struct dwarf2_debug_sections *names;
   flagword aflag = bfd_get_section_flags (abfd, sectp);
 
-  if (vnames == NULL)
-    names = &dwarf2_elf_names;
-  else
-    names = (const struct dwarf2_debug_sections *) vnames;
-
   if ((aflag & SEC_HAS_CONTENTS) == 0)
     {
     }
-  else if (section_is_p (sectp->name, &names->info))
+  else if (section_is_p (sectp->name, &names.info))
     {
-      dwarf2_per_objfile->info.s.section = sectp;
-      dwarf2_per_objfile->info.size = bfd_get_section_size (sectp);
+      this->info.s.section = sectp;
+      this->info.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->abbrev))
+  else if (section_is_p (sectp->name, &names.abbrev))
     {
-      dwarf2_per_objfile->abbrev.s.section = sectp;
-      dwarf2_per_objfile->abbrev.size = bfd_get_section_size (sectp);
+      this->abbrev.s.section = sectp;
+      this->abbrev.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->line))
+  else if (section_is_p (sectp->name, &names.line))
     {
-      dwarf2_per_objfile->line.s.section = sectp;
-      dwarf2_per_objfile->line.size = bfd_get_section_size (sectp);
+      this->line.s.section = sectp;
+      this->line.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->loc))
+  else if (section_is_p (sectp->name, &names.loc))
     {
-      dwarf2_per_objfile->loc.s.section = sectp;
-      dwarf2_per_objfile->loc.size = bfd_get_section_size (sectp);
+      this->loc.s.section = sectp;
+      this->loc.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->loclists))
+  else if (section_is_p (sectp->name, &names.loclists))
     {
-      dwarf2_per_objfile->loclists.s.section = sectp;
-      dwarf2_per_objfile->loclists.size = bfd_get_section_size (sectp);
+      this->loclists.s.section = sectp;
+      this->loclists.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->macinfo))
+  else if (section_is_p (sectp->name, &names.macinfo))
     {
-      dwarf2_per_objfile->macinfo.s.section = sectp;
-      dwarf2_per_objfile->macinfo.size = bfd_get_section_size (sectp);
+      this->macinfo.s.section = sectp;
+      this->macinfo.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->macro))
+  else if (section_is_p (sectp->name, &names.macro))
     {
-      dwarf2_per_objfile->macro.s.section = sectp;
-      dwarf2_per_objfile->macro.size = bfd_get_section_size (sectp);
+      this->macro.s.section = sectp;
+      this->macro.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->str))
+  else if (section_is_p (sectp->name, &names.str))
     {
-      dwarf2_per_objfile->str.s.section = sectp;
-      dwarf2_per_objfile->str.size = bfd_get_section_size (sectp);
+      this->str.s.section = sectp;
+      this->str.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->line_str))
+  else if (section_is_p (sectp->name, &names.line_str))
     {
-      dwarf2_per_objfile->line_str.s.section = sectp;
-      dwarf2_per_objfile->line_str.size = bfd_get_section_size (sectp);
+      this->line_str.s.section = sectp;
+      this->line_str.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->addr))
+  else if (section_is_p (sectp->name, &names.addr))
     {
-      dwarf2_per_objfile->addr.s.section = sectp;
-      dwarf2_per_objfile->addr.size = bfd_get_section_size (sectp);
+      this->addr.s.section = sectp;
+      this->addr.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->frame))
+  else if (section_is_p (sectp->name, &names.frame))
     {
-      dwarf2_per_objfile->frame.s.section = sectp;
-      dwarf2_per_objfile->frame.size = bfd_get_section_size (sectp);
+      this->frame.s.section = sectp;
+      this->frame.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->eh_frame))
+  else if (section_is_p (sectp->name, &names.eh_frame))
     {
-      dwarf2_per_objfile->eh_frame.s.section = sectp;
-      dwarf2_per_objfile->eh_frame.size = bfd_get_section_size (sectp);
+      this->eh_frame.s.section = sectp;
+      this->eh_frame.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->ranges))
+  else if (section_is_p (sectp->name, &names.ranges))
     {
-      dwarf2_per_objfile->ranges.s.section = sectp;
-      dwarf2_per_objfile->ranges.size = bfd_get_section_size (sectp);
+      this->ranges.s.section = sectp;
+      this->ranges.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->rnglists))
+  else if (section_is_p (sectp->name, &names.rnglists))
     {
-      dwarf2_per_objfile->rnglists.s.section = sectp;
-      dwarf2_per_objfile->rnglists.size = bfd_get_section_size (sectp);
+      this->rnglists.s.section = sectp;
+      this->rnglists.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->types))
+  else if (section_is_p (sectp->name, &names.types))
     {
       struct dwarf2_section_info type_section;
 
@@ -2409,18 +2631,28 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
       type_section.s.section = sectp;
       type_section.size = bfd_get_section_size (sectp);
 
-      VEC_safe_push (dwarf2_section_info_def, dwarf2_per_objfile->types,
+      VEC_safe_push (dwarf2_section_info_def, this->types,
                     &type_section);
     }
-  else if (section_is_p (sectp->name, &names->gdb_index))
+  else if (section_is_p (sectp->name, &names.gdb_index))
+    {
+      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))
     {
-      dwarf2_per_objfile->gdb_index.s.section = sectp;
-      dwarf2_per_objfile->gdb_index.size = bfd_get_section_size (sectp);
+      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)
-    dwarf2_per_objfile->has_section_at_zero = 1;
+    this->has_section_at_zero = true;
 }
 
 /* A helper function that decides whether a section is empty,
@@ -2613,6 +2845,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
@@ -2622,8 +2859,6 @@ locate_dwz_sections (bfd *abfd, asection *sectp, void *arg)
 static struct dwz_file *
 dwarf2_get_dwz_file (void)
 {
-  char *data;
-  struct cleanup *cleanup;
   const char *filename;
   struct dwz_file *result;
   bfd_size_type buildid_len_arg;
@@ -2634,8 +2869,9 @@ dwarf2_get_dwz_file (void)
     return dwarf2_per_objfile->dwz_file;
 
   bfd_set_error (bfd_error_no_error);
-  data = bfd_get_alt_debug_link_info (dwarf2_per_objfile->objfile->obfd,
-                                     &buildid_len_arg, &buildid);
+  gdb::unique_xmalloc_ptr<char> data
+    (bfd_get_alt_debug_link_info (dwarf2_per_objfile->objfile->obfd,
+                                 &buildid_len_arg, &buildid));
   if (data == NULL)
     {
       if (bfd_get_error () == bfd_error_no_error)
@@ -2643,20 +2879,20 @@ dwarf2_get_dwz_file (void)
       error (_("could not read '.gnu_debugaltlink' section: %s"),
             bfd_errmsg (bfd_get_error ()));
     }
-  cleanup = make_cleanup (xfree, data);
-  make_cleanup (xfree, buildid);
+
+  gdb::unique_xmalloc_ptr<bfd_byte> buildid_holder (buildid);
 
   buildid_len = (size_t) buildid_len_arg;
 
-  filename = (const char *) data;
+  filename = data.get ();
 
   std::string abs_storage;
   if (!IS_ABSOLUTE_PATH (filename))
     {
-      char *abs = gdb_realpath (objfile_name (dwarf2_per_objfile->objfile));
+      gdb::unique_xmalloc_ptr<char> abs
+       = gdb_realpath (objfile_name (dwarf2_per_objfile->objfile));
 
-      make_cleanup (xfree, abs);
-      abs_storage = ldirname (abs) + SLASH_STRING + filename;
+      abs_storage = ldirname (abs.get ()) + SLASH_STRING + filename;
       filename = abs_storage.c_str ();
     }
 
@@ -2682,8 +2918,6 @@ dwarf2_get_dwz_file (void)
 
   bfd_map_over_sections (result->dwz_bfd, locate_dwz_sections, result);
 
-  do_cleanups (cleanup);
-
   gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, result->dwz_bfd);
   dwarf2_per_objfile->dwz_file = result;
   return result;
@@ -2934,6 +3168,29 @@ dw2_get_cu (int index)
   return dwarf2_per_objfile->all_comp_units[index];
 }
 
+/* Return a new dwarf2_per_cu_data allocated on OBJFILE's
+   objfile_obstack, and constructed with the specified field
+   values.  */
+
+static dwarf2_per_cu_data *
+create_cu_from_index_list (struct objfile *objfile,
+                          struct dwarf2_section_info *section,
+                          int is_dwz,
+                          sect_offset sect_off, ULONGEST length)
+{
+  dwarf2_per_cu_data *the_cu
+    = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+                     struct dwarf2_per_cu_data);
+  the_cu->sect_off = sect_off;
+  the_cu->length = length;
+  the_cu->objfile = objfile;
+  the_cu->section = section;
+  the_cu->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+                                   struct dwarf2_per_cu_quick_data);
+  the_cu->is_dwz = is_dwz;
+  return the_cu;
+}
+
 /* A helper for create_cus_from_index that handles a given list of
    CUs.  */
 
@@ -2955,17 +3212,8 @@ create_cus_from_index_list (struct objfile *objfile,
       ULONGEST length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE);
       cu_list += 2 * 8;
 
-      dwarf2_per_cu_data *the_cu
-       = OBSTACK_ZALLOC (&objfile->objfile_obstack,
-                         struct dwarf2_per_cu_data);
-      the_cu->sect_off = sect_off;
-      the_cu->length = length;
-      the_cu->objfile = objfile;
-      the_cu->section = section;
-      the_cu->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack,
-                                       struct dwarf2_per_cu_quick_data);
-      the_cu->is_dwz = is_dwz;
-      dwarf2_per_objfile->all_comp_units[base_offset + i / 2] = the_cu;
+      dwarf2_per_objfile->all_comp_units[base_offset + i / 2]
+       = create_cu_from_index_list (objfile, section, is_dwz, sect_off, length);
     }
 }
 
@@ -3051,6 +3299,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.  */
 
@@ -3059,17 +3366,15 @@ create_addrmap_from_index (struct objfile *objfile, struct mapped_index *index)
 {
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   const gdb_byte *iter, *end;
-  struct obstack temp_obstack;
   struct addrmap *mutable_map;
-  struct cleanup *cleanup;
   CORE_ADDR baseaddr;
 
-  obstack_init (&temp_obstack);
-  cleanup = make_cleanup_obstack_free (&temp_obstack);
+  auto_obstack temp_obstack;
+
   mutable_map = addrmap_create_mutable (&temp_obstack);
 
-  iter = index->address_table;
-  end = iter + index->address_table_size;
+  iter = index->address_table.data ();
+  end = iter + index->address_table.size ();
 
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
@@ -3106,99 +3411,251 @@ create_addrmap_from_index (struct objfile *objfile, struct mapped_index *index)
 
   objfile->psymtabs_addrmap = addrmap_create_fixed (mutable_map,
                                                    &objfile->objfile_obstack);
-  do_cleanups (cleanup);
 }
 
-/* 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
-   format of the mapped index file.  The hash values do not have to match with
-   SYMBOL_HASH_NEXT.
-   
-   Use INT_MAX for INDEX_VERSION if you generate the current index format.  */
+/* Read the address map data from DWARF-5 .debug_aranges, and use it to
+   populate the objfile's psymtabs_addrmap.  */
 
-static hashval_t
-mapped_index_string_hash (int index_version, const void *p)
+static void
+create_addrmap_from_aranges (struct objfile *objfile,
+                            struct dwarf2_section_info *section)
 {
-  const unsigned char *str = (const unsigned char *) p;
-  hashval_t r = 0;
-  unsigned char c;
+  bfd *abfd = objfile->obfd;
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  const CORE_ADDR baseaddr = ANOFFSET (objfile->section_offsets,
+                                      SECT_OFF_TEXT (objfile));
 
-  while ((c = *str++) != 0)
+  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)
     {
-      if (index_version >= 5)
-       c = tolower (c);
-      r = r * 67 + c - 113;
+      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;
+       }
     }
 
-  return r;
-}
+  dwarf2_read_section (objfile, section);
 
-/* Find a slot in the mapped index INDEX for the object named NAME.
-   If NAME is found, set *VEC_OUT to point to the CU vector in the
-   constant pool and return 1.  If NAME cannot be found, return 0.  */
+  const bfd_endian dwarf5_byte_order = gdbarch_byte_order (gdbarch);
 
-static int
-find_slot_in_mapped_hash (struct mapped_index *index, const char *name,
-                         offset_type **vec_out)
-{
-  struct cleanup *back_to = make_cleanup (null_cleanup, 0);
-  offset_type hash;
-  offset_type slot, step;
-  int (*cmp) (const char *, const char *);
+  const gdb_byte *addr = section->buffer;
 
-  if (current_language->la_language == language_cplus
-      || current_language->la_language == language_fortran
-      || current_language->la_language == language_d)
+  while (addr < section->buffer + section->size)
     {
-      /* NAME is already canonical.  Drop any qualifiers as .gdb_index does
-        not contain any.  */
+      const gdb_byte *const entry_addr = addr;
+      unsigned int bytes_read;
 
-      if (strchr (name, '(') != NULL)
+      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)
        {
-         char *without_params = cp_remove_params (name);
+         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;
+       }
 
-         if (without_params != NULL)
-           {
-             make_cleanup (xfree, without_params);
-             name = without_params;
-           }
+      /* 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;
        }
-    }
 
-  /* Index version 4 did not support case insensitive searches.  But the
-     indices for case insensitive languages are built in lowercase, therefore
-     simulate our NAME being searched is also lowercased.  */
+      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
+   format of the mapped index file.  The hash values do not have to match with
+   SYMBOL_HASH_NEXT.
+   
+   Use INT_MAX for INDEX_VERSION if you generate the current index format.  */
+
+static hashval_t
+mapped_index_string_hash (int index_version, const void *p)
+{
+  const unsigned char *str = (const unsigned char *) p;
+  hashval_t r = 0;
+  unsigned char c;
+
+  while ((c = *str++) != 0)
+    {
+      if (index_version >= 5)
+       c = tolower (c);
+      r = r * 67 + c - 113;
+    }
+
+  return r;
+}
+
+/* Find a slot in the mapped index INDEX for the object named NAME.
+   If NAME is found, set *VEC_OUT to point to the CU vector in the
+   constant pool and return true.  If NAME cannot be found, return
+   false.  */
+
+static bool
+find_slot_in_mapped_hash (struct mapped_index *index, const char *name,
+                         offset_type **vec_out)
+{
+  offset_type hash;
+  offset_type slot, step;
+  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 .gdb_index does
+        not contain any.  */
+
+      if (strchr (name, '(') != NULL)
+       {
+         without_params = cp_remove_params (name);
+
+         if (without_params != NULL)
+           name = without_params.get ();
+       }
+    }
+
+  /* Index version 4 did not support case insensitive searches.  But the
+     indices for case insensitive languages are built in lowercase, therefore
+     simulate our NAME being searched is also lowercased.  */
   hash = mapped_index_string_hash ((index->version == 4
                                     && case_sensitivity == case_sensitive_off
                                    ? 5 : index->version),
                                   name);
 
-  slot = hash & (index->symbol_table_slots - 1);
-  step = ((hash * 17) & (index->symbol_table_slots - 1)) | 1;
+  slot = hash & (index->symbol_table.size () - 1);
+  step = ((hash * 17) & (index->symbol_table.size () - 1)) | 1;
   cmp = (case_sensitivity == case_sensitive_on ? strcmp : strcasecmp);
 
   for (;;)
     {
-      /* Convert a slot number to an offset into the table.  */
-      offset_type i = 2 * slot;
       const char *str;
-      if (index->symbol_table[i] == 0 && index->symbol_table[i + 1] == 0)
-       {
-         do_cleanups (back_to);
-         return 0;
-       }
 
-      str = index->constant_pool + MAYBE_SWAP (index->symbol_table[i]);
+      const auto &bucket = index->symbol_table[slot];
+      if (bucket.name == 0 && bucket.vec == 0)
+       return false;
+
+      str = index->constant_pool + MAYBE_SWAP (bucket.name);
       if (!cmp (name, str))
        {
          *vec_out = (offset_type *) (index->constant_pool
-                                     + MAYBE_SWAP (index->symbol_table[i + 1]));
-         do_cleanups (back_to);
-         return 1;
+                                     + MAYBE_SWAP (bucket.vec));
+         return true;
        }
 
-      slot = (slot + step) & (index->symbol_table_slots - 1);
+      slot = (slot + step) & (index->symbol_table.size () - 1);
     }
 }
 
@@ -3309,24 +3766,26 @@ to use the section anyway."),
                          / 8);
   ++i;
 
-  map->address_table = addr + MAYBE_SWAP (metadata[i]);
-  map->address_table_size = (MAYBE_SWAP (metadata[i + 1])
-                            - MAYBE_SWAP (metadata[i]));
+  const gdb_byte *address_table = addr + MAYBE_SWAP (metadata[i]);
+  const gdb_byte *address_table_end = addr + MAYBE_SWAP (metadata[i + 1]);
+  map->address_table
+    = gdb::array_view<const gdb_byte> (address_table, address_table_end);
   ++i;
 
-  map->symbol_table = (offset_type *) (addr + MAYBE_SWAP (metadata[i]));
-  map->symbol_table_slots = ((MAYBE_SWAP (metadata[i + 1])
-                             - MAYBE_SWAP (metadata[i]))
-                            / (2 * sizeof (offset_type)));
-  ++i;
+  const gdb_byte *symbol_table = addr + MAYBE_SWAP (metadata[i]);
+  const gdb_byte *symbol_table_end = addr + MAYBE_SWAP (metadata[i + 1]);
+  map->symbol_table
+    = gdb::array_view<mapped_index::symbol_table_slot>
+       ((mapped_index::symbol_table_slot *) symbol_table,
+       (mapped_index::symbol_table_slot *) symbol_table_end);
 
+  ++i;
   map->constant_pool = (char *) (addr + MAYBE_SWAP (metadata[i]));
 
   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
@@ -3345,7 +3804,7 @@ dwarf2_read_index (struct objfile *objfile)
     return 0;
 
   /* Don't use the index if it's empty.  */
-  if (local_map.symbol_table_slots == 0)
+  if (local_map.symbol_table.empty ())
     return 0;
 
   /* If there is a .dwz file, read it so we can get its CU list as
@@ -3392,6 +3851,7 @@ dwarf2_read_index (struct objfile *objfile)
   create_addrmap_from_index (objfile, &local_map);
 
   map = XOBNEW (&objfile->objfile_obstack, struct mapped_index);
+  map = new (map) mapped_index ();
   *map = local_map;
 
   dwarf2_per_objfile->index_table = map;
@@ -3528,7 +3988,7 @@ dw2_get_real_path (struct objfile *objfile,
                                      qfn->num_file_names, const char *);
 
   if (qfn->real_names[index] == NULL)
-    qfn->real_names[index] = gdb_realpath (qfn->file_names[index]);
+    qfn->real_names[index] = gdb_realpath (qfn->file_names[index]).release ();
 
   return qfn->real_names[index];
 }
@@ -3826,6 +4286,8 @@ dw2_lookup_symbol (struct objfile *objfile, int block_index,
 
   dw2_setup (objfile);
 
+  lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
+
   index = dwarf2_per_objfile->index_table;
 
   /* index is NULL if OBJF_READNOW.  */
@@ -3852,10 +4314,10 @@ dw2_lookup_symbol (struct objfile *objfile, int block_index,
             information (but NAME might contain it).  */
 
          if (sym != NULL
-             && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0)
+             && SYMBOL_MATCHES_SEARCH_NAME (sym, lookup_name))
            return stab;
          if (with_opaque != NULL
-             && strcmp_iw (SYMBOL_SEARCH_NAME (with_opaque), name) == 0)
+             && SYMBOL_MATCHES_SEARCH_NAME (with_opaque, lookup_name))
            stab_best = stab;
 
          /* Keep looking through other CUs.  */
@@ -4000,7 +4462,7 @@ dw2_map_matching_symbols (struct objfile *objfile,
                          int global,
                          int (*callback) (struct block *,
                                           struct symbol *, void *),
-                         void *data, symbol_compare_ftype *match,
+                         void *data, symbol_name_match_type match,
                          symbol_compare_ftype *ordered_compare)
 {
   /* Currently unimplemented; used for Ada.  The function can be called if the
@@ -4008,349 +4470,2003 @@ dw2_map_matching_symbols (struct objfile *objfile,
      does not look for non-Ada symbols this function should just return.  */
 }
 
-static void
-dw2_expand_symtabs_matching
-  (struct objfile *objfile,
-   gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
-   gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
-   gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
-   enum search_domain kind)
+/* Symbol name matcher for .gdb_index names.
+
+   Symbol names in .gdb_index have a few particularities:
+
+   - There's no indication of which is the language of each symbol.
+
+     Since each language has its own symbol name matching algorithm,
+     and we don't know which language is the right one, we must match
+     each symbol against all languages.  This would be a potential
+     performance problem if it were not mitigated by the
+     mapped_index::name_components lookup table, which significantly
+     reduces the number of times we need to call into this matcher,
+     making it a non-issue.
+
+   - Symbol names in the index have no overload (parameter)
+     information.  I.e., in C++, "foo(int)" and "foo(long)" both
+     appear as "foo" in the index, for example.
+
+     This means that the lookup names passed to the symbol name
+     matcher functions must have no parameter information either
+     because (e.g.) symbol search name "foo" does not match
+     lookup-name "foo(int)" [while swapping search name for lookup
+     name would match].
+*/
+class gdb_index_symbol_name_matcher
 {
-  int i;
-  offset_type iter;
-  struct mapped_index *index;
+public:
+  /* Prepares the vector of comparison functions for LOOKUP_NAME.  */
+  gdb_index_symbol_name_matcher (const lookup_name_info &lookup_name);
 
-  dw2_setup (objfile);
+  /* Walk all the matcher routines and match SYMBOL_NAME against them.
+     Returns true if any matcher matches.  */
+  bool matches (const char *symbol_name);
 
-  /* index_table is NULL if OBJF_READNOW.  */
-  if (!dwarf2_per_objfile->index_table)
-    return;
-  index = dwarf2_per_objfile->index_table;
+private:
+  /* A reference to the lookup name we're matching against.  */
+  const lookup_name_info &m_lookup_name;
 
-  if (file_matcher != NULL)
-    {
-      htab_up visited_found (htab_create_alloc (10, htab_hash_pointer,
-                                               htab_eq_pointer,
-                                               NULL, xcalloc, xfree));
-      htab_up visited_not_found (htab_create_alloc (10, htab_hash_pointer,
-                                                   htab_eq_pointer,
-                                                   NULL, xcalloc, xfree));
+  /* A vector holding all the different symbol name matchers, for all
+     languages.  */
+  std::vector<symbol_name_matcher_ftype *> m_symbol_name_matcher_funcs;
+};
 
-      /* The rule is CUs specify all the files, including those used by
-        any TU, so there's no need to scan TUs here.  */
+gdb_index_symbol_name_matcher::gdb_index_symbol_name_matcher
+  (const lookup_name_info &lookup_name)
+    : m_lookup_name (lookup_name)
+{
+  /* Prepare the vector of comparison functions upfront, to avoid
+     doing the same work for each symbol.  Care is taken to avoid
+     matching with the same matcher more than once if/when multiple
+     languages use the same matcher function.  */
+  auto &matchers = m_symbol_name_matcher_funcs;
+  matchers.reserve (nr_languages);
+
+  matchers.push_back (default_symbol_name_matcher);
 
-      for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+  for (int i = 0; i < nr_languages; i++)
+    {
+      const language_defn *lang = language_def ((enum language) i);
+      if (lang->la_get_symbol_name_matcher != NULL)
        {
-         int j;
-         struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
-         struct quick_file_names *file_data;
-         void **slot;
+         symbol_name_matcher_ftype *name_matcher
+           = lang->la_get_symbol_name_matcher (m_lookup_name);
+
+         /* Don't insert the same comparison routine more than once.
+            Note that we do this linear walk instead of a cheaper
+            sorted insert, or use a std::set or something like that,
+            because relative order of function addresses is not
+            stable.  This is not a problem in practice because the
+            number of supported languages is low, and the cost here
+            is tiny compared to the number of searches we'll do
+            afterwards using this object.  */
+         if (std::find (matchers.begin (), matchers.end (), name_matcher)
+             == matchers.end ())
+           matchers.push_back (name_matcher);
+       }
+    }
+}
 
-         QUIT;
+bool
+gdb_index_symbol_name_matcher::matches (const char *symbol_name)
+{
+  for (auto matches_name : m_symbol_name_matcher_funcs)
+    if (matches_name (symbol_name, m_lookup_name, NULL))
+      return true;
 
-         per_cu->v.quick->mark = 0;
+  return false;
+}
 
-         /* We only need to look at symtabs not already expanded.  */
-         if (per_cu->v.quick->compunit_symtab)
-           continue;
+/* Starting from a search name, return the string that finds the upper
+   bound of all strings that start with SEARCH_NAME in a sorted name
+   list.  Returns the empty string to indicate that the upper bound is
+   the end of the list.  */
+
+static std::string
+make_sort_after_prefix_name (const char *search_name)
+{
+  /* When looking to complete "func", we find the upper bound of all
+     symbols that start with "func" by looking for where we'd insert
+     the closest string that would follow "func" in lexicographical
+     order.  Usually, that's "func"-with-last-character-incremented,
+     i.e. "fund".  Mind non-ASCII characters, though.  Usually those
+     will be UTF-8 multi-byte sequences, but we can't be certain.
+     Especially mind the 0xff character, which is a valid character in
+     non-UTF-8 source character sets (e.g. Latin1 'ÿ'), and we can't
+     rule out compilers allowing it in identifiers.  Note that
+     conveniently, strcmp/strcasecmp are specified to compare
+     characters interpreted as unsigned char.  So what we do is treat
+     the whole string as a base 256 number composed of a sequence of
+     base 256 "digits" and add 1 to it.  I.e., adding 1 to 0xff wraps
+     to 0, and carries 1 to the following more-significant position.
+     If the very first character in SEARCH_NAME ends up incremented
+     and carries/overflows, then the upper bound is the end of the
+     list.  The string after the empty string is also the empty
+     string.
+
+     Some examples of this operation:
+
+       SEARCH_NAME  => "+1" RESULT
+
+       "abc"              => "abd"
+       "ab\xff"           => "ac"
+       "\xff" "a" "\xff"  => "\xff" "b"
+       "\xff"             => ""
+       "\xff\xff"         => ""
+       ""                 => ""
+
+     Then, with these symbols for example:
+
+      func
+      func1
+      fund
+
+     completing "func" looks for symbols between "func" and
+     "func"-with-last-character-incremented, i.e. "fund" (exclusive),
+     which finds "func" and "func1", but not "fund".
+
+     And with:
+
+      funcÿ     (Latin1 'ÿ' [0xff])
+      funcÿ1
+      fund
+
+     completing "funcÿ" looks for symbols between "funcÿ" and "fund"
+     (exclusive), which finds "funcÿ" and "funcÿ1", but not "fund".
+
+     And with:
+
+      Ã¿Ã¿        (Latin1 'ÿ' [0xff])
+      Ã¿Ã¿1
+
+     completing "ÿ" or "ÿÿ" looks for symbols between between "ÿÿ" and
+     the end of the list.
+  */
+  std::string after = search_name;
+  while (!after.empty () && (unsigned char) after.back () == 0xff)
+    after.pop_back ();
+  if (!after.empty ())
+    after.back () = (unsigned char) after.back () + 1;
+  return after;
+}
+
+/* See declaration.  */
+
+std::pair<std::vector<name_component>::const_iterator,
+         std::vector<name_component>::const_iterator>
+mapped_index_base::find_name_components_bounds
+  (const lookup_name_info &lookup_name_without_params) const
+{
+  auto *name_cmp
+    = this->name_components_casing == case_sensitive_on ? strcmp : strcasecmp;
+
+  const char *cplus
+    = lookup_name_without_params.cplus ().lookup_name ().c_str ();
+
+  /* Comparison function object for lower_bound that matches against a
+     given symbol name.  */
+  auto lookup_compare_lower = [&] (const name_component &elem,
+                                  const char *name)
+    {
+      const char *elem_qualified = this->symbol_name_at (elem.idx);
+      const char *elem_name = elem_qualified + elem.name_offset;
+      return name_cmp (elem_name, name) < 0;
+    };
 
-         file_data = dw2_get_file_names (per_cu);
-         if (file_data == NULL)
-           continue;
+  /* Comparison function object for upper_bound that matches against a
+     given symbol name.  */
+  auto lookup_compare_upper = [&] (const char *name,
+                                  const name_component &elem)
+    {
+      const char *elem_qualified = this->symbol_name_at (elem.idx);
+      const char *elem_name = elem_qualified + elem.name_offset;
+      return name_cmp (name, elem_name) < 0;
+    };
 
-         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;
-           }
+  auto begin = this->name_components.begin ();
+  auto end = this->name_components.end ();
 
-         for (j = 0; j < file_data->num_file_names; ++j)
-           {
-             const char *this_real_name;
+  /* Find the lower bound.  */
+  auto lower = [&] ()
+    {
+      if (lookup_name_without_params.completion_mode () && cplus[0] == '\0')
+       return begin;
+      else
+       return std::lower_bound (begin, end, cplus, lookup_compare_lower);
+    } ();
 
-             if (file_matcher (file_data->file_names[j], false))
-               {
-                 per_cu->v.quick->mark = 1;
-                 break;
-               }
+  /* Find the upper bound.  */
+  auto upper = [&] ()
+    {
+      if (lookup_name_without_params.completion_mode ())
+       {
+         /* In completion mode, we want UPPER to point past all
+            symbols names that have the same prefix.  I.e., with
+            these symbols, and completing "func":
+
+             function        << lower bound
+             function1
+             other_function  << upper bound
+
+            We find the upper bound by looking for the insertion
+            point of "func"-with-last-character-incremented,
+            i.e. "fund".  */
+         std::string after = make_sort_after_prefix_name (cplus);
+         if (after.empty ())
+           return end;
+         return std::lower_bound (lower, end, after.c_str (),
+                                  lookup_compare_lower);
+       }
+      else
+       return std::upper_bound (lower, end, cplus, lookup_compare_upper);
+    } ();
 
-             /* 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;
+  return {lower, upper};
+}
 
-             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;
-               }
-           }
+/* See declaration.  */
 
-         slot = htab_find_slot (per_cu->v.quick->mark
-                                ? visited_found.get ()
-                                : visited_not_found.get (),
-                                file_data, INSERT);
-         *slot = file_data;
+void
+mapped_index_base::build_name_components ()
+{
+  if (!this->name_components.empty ())
+    return;
+
+  this->name_components_casing = case_sensitivity;
+  auto *name_cmp
+    = this->name_components_casing == case_sensitive_on ? strcmp : strcasecmp;
+
+  /* The code below only knows how to break apart components of C++
+     symbol names (and other languages that use '::' as
+     namespace/module separator).  If we add support for wild matching
+     to some language that uses some other operator (E.g., Ada, Go and
+     D use '.'), then we'll need to try splitting the symbol name
+     according to that language too.  Note that Ada does support wild
+     matching, but doesn't currently support .gdb_index.  */
+  auto count = this->symbol_name_count ();
+  for (offset_type idx = 0; idx < count; idx++)
+    {
+      if (this->symbol_name_slot_invalid (idx))
+       continue;
+
+      const char *name = this->symbol_name_at (idx);
+
+      /* Add each name component to the name component table.  */
+      unsigned int previous_len = 0;
+      for (unsigned int current_len = cp_find_first_component (name);
+          name[current_len] != '\0';
+          current_len += cp_find_first_component (name + current_len))
+       {
+         gdb_assert (name[current_len] == ':');
+         this->name_components.push_back ({previous_len, idx});
+         /* Skip the '::'.  */
+         current_len += 2;
+         previous_len = current_len;
        }
+      this->name_components.push_back ({previous_len, idx});
     }
 
-  for (iter = 0; iter < index->symbol_table_slots; ++iter)
+  /* Sort name_components elements by name.  */
+  auto name_comp_compare = [&] (const name_component &left,
+                               const name_component &right)
     {
-      offset_type idx = 2 * iter;
-      const char *name;
-      offset_type *vec, vec_len, vec_idx;
-      int global_seen = 0;
+      const char *left_qualified = this->symbol_name_at (left.idx);
+      const char *right_qualified = this->symbol_name_at (right.idx);
 
-      QUIT;
+      const char *left_name = left_qualified + left.name_offset;
+      const char *right_name = right_qualified + right.name_offset;
 
-      if (index->symbol_table[idx] == 0 && index->symbol_table[idx + 1] == 0)
-       continue;
+      return name_cmp (left_name, right_name) < 0;
+    };
 
-      name = index->constant_pool + MAYBE_SWAP (index->symbol_table[idx]);
+  std::sort (this->name_components.begin (),
+            this->name_components.end (),
+            name_comp_compare);
+}
 
-      if (!symbol_matcher (name))
-       continue;
+/* Helper for dw2_expand_symtabs_matching that works with a
+   mapped_index_base instead of the containing objfile.  This is split
+   to a separate function in order to be able to unit test the
+   name_components matching using a mock mapped_index_base.  For each
+   symbol name that matches, calls MATCH_CALLBACK, passing it the
+   symbol's index in the mapped_index_base symbol table.  */
 
-      /* The name was matched, now expand corresponding CUs that were
-        marked.  */
-      vec = (offset_type *) (index->constant_pool
-                            + MAYBE_SWAP (index->symbol_table[idx + 1]));
-      vec_len = MAYBE_SWAP (vec[0]);
-      for (vec_idx = 0; vec_idx < vec_len; ++vec_idx)
-       {
-         struct dwarf2_per_cu_data *per_cu;
-         offset_type cu_index_and_attrs = MAYBE_SWAP (vec[vec_idx + 1]);
-         /* This value is only valid for index versions >= 7.  */
-         int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
-         gdb_index_symbol_kind symbol_kind =
-           GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
-         int cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
-         /* Only check the symbol attributes if they're present.
-            Indices prior to version 7 don't record them,
-            and indices >= 7 may elide them for certain symbols
-            (gold does this).  */
-         int attrs_valid =
-           (index->version >= 7
-            && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
+static void
+dw2_expand_symtabs_matching_symbol
+  (mapped_index_base &index,
+   const lookup_name_info &lookup_name_in,
+   gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
+   enum search_domain kind,
+   gdb::function_view<void (offset_type)> match_callback)
+{
+  lookup_name_info lookup_name_without_params
+    = lookup_name_in.make_ignore_params ();
+  gdb_index_symbol_name_matcher lookup_name_matcher
+    (lookup_name_without_params);
 
-         /* Work around gold/15646.  */
-         if (attrs_valid)
-           {
-             if (!is_static && global_seen)
-               continue;
-             if (!is_static)
-               global_seen = 1;
-           }
+  /* Build the symbol name component sorted vector, if we haven't
+     yet.  */
+  index.build_name_components ();
 
-         /* Only check the symbol's kind if it has one.  */
-         if (attrs_valid)
-           {
-             switch (kind)
-               {
-               case VARIABLES_DOMAIN:
-                 if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE)
-                   continue;
-                 break;
-               case FUNCTIONS_DOMAIN:
-                 if (symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION)
-                   continue;
-                 break;
-               case TYPES_DOMAIN:
-                 if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
-                   continue;
-                 break;
-               default:
-                 break;
-               }
-           }
+  auto bounds = index.find_name_components_bounds (lookup_name_without_params);
 
-         /* Don't crash on bad data.  */
-         if (cu_index >= (dwarf2_per_objfile->n_comp_units
-                          + dwarf2_per_objfile->n_type_units))
-           {
-             complaint (&symfile_complaints,
-                        _(".gdb_index entry has bad CU index"
-                          " [in module %s]"), objfile_name (objfile));
-             continue;
-           }
+  /* Now for each symbol name in range, check to see if we have a name
+     match, and if so, call the MATCH_CALLBACK callback.  */
 
-         per_cu = dw2_get_cutu (cu_index);
-         if (file_matcher == NULL || per_cu->v.quick->mark)
-           {
-             int symtab_was_null =
-               (per_cu->v.quick->compunit_symtab == NULL);
+  /* The same symbol may appear more than once in the range though.
+     E.g., if we're looking for symbols that complete "w", and we have
+     a symbol named "w1::w2", we'll find the two name components for
+     that same symbol in the range.  To be sure we only call the
+     callback once per symbol, we first collect the symbol name
+     indexes that matched in a temporary vector and ignore
+     duplicates.  */
+  std::vector<offset_type> matches;
+  matches.reserve (std::distance (bounds.first, bounds.second));
 
-             dw2_instantiate_symtab (per_cu);
+  for (; bounds.first != bounds.second; ++bounds.first)
+    {
+      const char *qualified = index.symbol_name_at (bounds.first->idx);
 
-             if (expansion_notify != NULL
-                 && symtab_was_null
-                 && per_cu->v.quick->compunit_symtab != NULL)
-               {
-                 expansion_notify (per_cu->v.quick->compunit_symtab);
-               }
-           }
+      if (!lookup_name_matcher.matches (qualified)
+         || (symbol_matcher != NULL && !symbol_matcher (qualified)))
+       continue;
+
+      matches.push_back (bounds.first->idx);
+    }
+
+  std::sort (matches.begin (), matches.end ());
+
+  /* Finally call the callback, once per match.  */
+  ULONGEST prev = -1;
+  for (offset_type idx : matches)
+    {
+      if (prev != idx)
+       {
+         match_callback (idx);
+         prev = idx;
        }
     }
+
+  /* Above we use a type wider than idx's for 'prev', since 0 and
+     (offset_type)-1 are both possible values.  */
+  static_assert (sizeof (prev) > sizeof (offset_type), "");
 }
 
-/* A helper for dw2_find_pc_sect_compunit_symtab which finds the most specific
-   symtab.  */
+#if GDB_SELF_TEST
 
-static struct compunit_symtab *
-recursively_find_pc_sect_compunit_symtab (struct compunit_symtab *cust,
-                                         CORE_ADDR pc)
+namespace selftests { namespace dw2_expand_symtabs_matching {
+
+/* A mock .gdb_index/.debug_names-like name index table, enough to
+   exercise dw2_expand_symtabs_matching_symbol, which works with the
+   mapped_index_base interface.  Builds an index from the symbol list
+   passed as parameter to the constructor.  */
+class mock_mapped_index : public mapped_index_base
 {
-  int i;
+public:
+  mock_mapped_index (gdb::array_view<const char *> symbols)
+    : m_symbol_table (symbols)
+  {}
 
-  if (COMPUNIT_BLOCKVECTOR (cust) != NULL
-      && blockvector_contains_pc (COMPUNIT_BLOCKVECTOR (cust), pc))
-    return cust;
+  DISABLE_COPY_AND_ASSIGN (mock_mapped_index);
 
-  if (cust->includes == NULL)
-    return NULL;
+  /* Return the number of names in the symbol table.  */
+  virtual size_t symbol_name_count () const
+  {
+    return m_symbol_table.size ();
+  }
 
-  for (i = 0; cust->includes[i]; ++i)
-    {
-      struct compunit_symtab *s = cust->includes[i];
+  /* Get the name of the symbol at IDX in the symbol table.  */
+  virtual const char *symbol_name_at (offset_type idx) const
+  {
+    return m_symbol_table[idx];
+  }
 
-      s = recursively_find_pc_sect_compunit_symtab (s, pc);
-      if (s != NULL)
-       return s;
-    }
+private:
+  gdb::array_view<const char *> m_symbol_table;
+};
 
-  return NULL;
-}
+/* Convenience function that converts a NULL pointer to a "<null>"
+   string, to pass to print routines.  */
 
-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)
+static const char *
+string_or_null (const char *str)
 {
-  struct dwarf2_per_cu_data *data;
-  struct compunit_symtab *result;
+  return str != NULL ? str : "<null>";
+}
 
+/* Check if a lookup_name_info built from
+   NAME/MATCH_TYPE/COMPLETION_MODE matches the symbols in the mock
+   index.  EXPECTED_LIST is the list of expected matches, in expected
+   matching order.  If no match expected, then an empty list is
+   specified.  Returns true on success.  On failure prints a warning
+   indicating the file:line that failed, and returns false.  */
+
+static bool
+check_match (const char *file, int line,
+            mock_mapped_index &mock_index,
+            const char *name, symbol_name_match_type match_type,
+            bool completion_mode,
+            std::initializer_list<const char *> expected_list)
+{
+  lookup_name_info lookup_name (name, match_type, completion_mode);
+
+  bool matched = true;
+
+  auto mismatch = [&] (const char *expected_str,
+                      const char *got)
+  {
+    warning (_("%s:%d: match_type=%s, looking-for=\"%s\", "
+              "expected=\"%s\", got=\"%s\"\n"),
+            file, line,
+            (match_type == symbol_name_match_type::FULL
+             ? "FULL" : "WILD"),
+            name, string_or_null (expected_str), string_or_null (got));
+    matched = false;
+  };
+
+  auto expected_it = expected_list.begin ();
+  auto expected_end = expected_list.end ();
+
+  dw2_expand_symtabs_matching_symbol (mock_index, lookup_name,
+                                     NULL, ALL_DOMAIN,
+                                     [&] (offset_type idx)
+  {
+    const char *matched_name = mock_index.symbol_name_at (idx);
+    const char *expected_str
+      = expected_it == expected_end ? NULL : *expected_it++;
+
+    if (expected_str == NULL || strcmp (expected_str, matched_name) != 0)
+      mismatch (expected_str, matched_name);
+  });
+
+  const char *expected_str
+  = expected_it == expected_end ? NULL : *expected_it++;
+  if (expected_str != NULL)
+    mismatch (expected_str, NULL);
+
+  return matched;
+}
+
+/* The symbols added to the mock mapped_index for testing (in
+   canonical form).  */
+static const char *test_symbols[] = {
+  "function",
+  "std::bar",
+  "std::zfunction",
+  "std::zfunction2",
+  "w1::w2",
+  "ns::foo<char*>",
+  "ns::foo<int>",
+  "ns::foo<long>",
+  "ns2::tmpl<int>::foo2",
+  "(anonymous namespace)::A::B::C",
+
+  /* These are used to check that the increment-last-char in the
+     matching algorithm for completion doesn't match "t1_fund" when
+     completing "t1_func".  */
+  "t1_func",
+  "t1_func1",
+  "t1_fund",
+  "t1_fund1",
+
+  /* A UTF-8 name with multi-byte sequences to make sure that
+     cp-name-parser understands this as a single identifier ("função"
+     is "function" in PT).  */
+  u8"u8função",
+
+  /* \377 (0xff) is Latin1 'ÿ'.  */
+  "yfunc\377",
+
+  /* \377 (0xff) is Latin1 'ÿ'.  */
+  "\377",
+  "\377\377123",
+
+  /* A name with all sorts of complications.  Starts with "z" to make
+     it easier for the completion tests below.  */
+#define Z_SYM_NAME \
+  "z::std::tuple<(anonymous namespace)::ui*, std::bar<(anonymous namespace)::ui> >" \
+    "::tuple<(anonymous namespace)::ui*, " \
+    "std::default_delete<(anonymous namespace)::ui>, void>"
+
+  Z_SYM_NAME
+};
+
+/* Returns true if the mapped_index_base::find_name_component_bounds
+   method finds EXPECTED_SYMS in INDEX when looking for SEARCH_NAME,
+   in completion mode.  */
+
+static bool
+check_find_bounds_finds (mapped_index_base &index,
+                        const char *search_name,
+                        gdb::array_view<const char *> expected_syms)
+{
+  lookup_name_info lookup_name (search_name,
+                               symbol_name_match_type::FULL, true);
+
+  auto bounds = index.find_name_components_bounds (lookup_name);
+
+  size_t distance = std::distance (bounds.first, bounds.second);
+  if (distance != expected_syms.size ())
+    return false;
+
+  for (size_t exp_elem = 0; exp_elem < distance; exp_elem++)
+    {
+      auto nc_elem = bounds.first + exp_elem;
+      const char *qualified = index.symbol_name_at (nc_elem->idx);
+      if (strcmp (qualified, expected_syms[exp_elem]) != 0)
+       return false;
+    }
+
+  return true;
+}
+
+/* Test the lower-level mapped_index::find_name_component_bounds
+   method.  */
+
+static void
+test_mapped_index_find_name_component_bounds ()
+{
+  mock_mapped_index mock_index (test_symbols);
+
+  mock_index.build_name_components ();
+
+  /* Test the lower-level mapped_index::find_name_component_bounds
+     method in completion mode.  */
+  {
+    static const char *expected_syms[] = {
+      "t1_func",
+      "t1_func1",
+    };
+
+    SELF_CHECK (check_find_bounds_finds (mock_index,
+                                        "t1_func", expected_syms));
+  }
+
+  /* Check that the increment-last-char in the name matching algorithm
+     for completion doesn't get confused with Ansi1 'ÿ' / 0xff.  */
+  {
+    static const char *expected_syms1[] = {
+      "\377",
+      "\377\377123",
+    };
+    SELF_CHECK (check_find_bounds_finds (mock_index,
+                                        "\377", expected_syms1));
+
+    static const char *expected_syms2[] = {
+      "\377\377123",
+    };
+    SELF_CHECK (check_find_bounds_finds (mock_index,
+                                        "\377\377", expected_syms2));
+  }
+}
+
+/* Test dw2_expand_symtabs_matching_symbol.  */
+
+static void
+test_dw2_expand_symtabs_matching_symbol ()
+{
+  mock_mapped_index mock_index (test_symbols);
+
+  /* We let all tests run until the end even if some fails, for debug
+     convenience.  */
+  bool any_mismatch = false;
+
+  /* Create the expected symbols list (an initializer_list).  Needed
+     because lists have commas, and we need to pass them to CHECK,
+     which is a macro.  */
+#define EXPECT(...) { __VA_ARGS__ }
+
+  /* Wrapper for check_match that passes down the current
+     __FILE__/__LINE__.  */
+#define CHECK_MATCH(NAME, MATCH_TYPE, COMPLETION_MODE, EXPECTED_LIST)  \
+  any_mismatch |= !check_match (__FILE__, __LINE__,                    \
+                               mock_index,                             \
+                               NAME, MATCH_TYPE, COMPLETION_MODE,      \
+                               EXPECTED_LIST)
+
+  /* Identity checks.  */
+  for (const char *sym : test_symbols)
+    {
+      /* Should be able to match all existing symbols.  */
+      CHECK_MATCH (sym, symbol_name_match_type::FULL, false,
+                  EXPECT (sym));
+
+      /* Should be able to match all existing symbols with
+        parameters.  */
+      std::string with_params = std::string (sym) + "(int)";
+      CHECK_MATCH (with_params.c_str (), symbol_name_match_type::FULL, false,
+                  EXPECT (sym));
+
+      /* Should be able to match all existing symbols with
+        parameters and qualifiers.  */
+      with_params = std::string (sym) + " ( int ) const";
+      CHECK_MATCH (with_params.c_str (), symbol_name_match_type::FULL, false,
+                  EXPECT (sym));
+
+      /* This should really find sym, but cp-name-parser.y doesn't
+        know about lvalue/rvalue qualifiers yet.  */
+      with_params = std::string (sym) + " ( int ) &&";
+      CHECK_MATCH (with_params.c_str (), symbol_name_match_type::FULL, false,
+                  {});
+    }
+
+  /* Check that the name matching algorithm for completion doesn't get
+     confused with Latin1 'ÿ' / 0xff.  */
+  {
+    static const char str[] = "\377";
+    CHECK_MATCH (str, symbol_name_match_type::FULL, true,
+                EXPECT ("\377", "\377\377123"));
+  }
+
+  /* Check that the increment-last-char in the matching algorithm for
+     completion doesn't match "t1_fund" when completing "t1_func".  */
+  {
+    static const char str[] = "t1_func";
+    CHECK_MATCH (str, symbol_name_match_type::FULL, true,
+                EXPECT ("t1_func", "t1_func1"));
+  }
+
+  /* Check that completion mode works at each prefix of the expected
+     symbol name.  */
+  {
+    static const char str[] = "function(int)";
+    size_t len = strlen (str);
+    std::string lookup;
+
+    for (size_t i = 1; i < len; i++)
+      {
+       lookup.assign (str, i);
+       CHECK_MATCH (lookup.c_str (), symbol_name_match_type::FULL, true,
+                    EXPECT ("function"));
+      }
+  }
+
+  /* While "w" is a prefix of both components, the match function
+     should still only be called once.  */
+  {
+    CHECK_MATCH ("w", symbol_name_match_type::FULL, true,
+                EXPECT ("w1::w2"));
+    CHECK_MATCH ("w", symbol_name_match_type::WILD, true,
+                EXPECT ("w1::w2"));
+  }
+
+  /* Same, with a "complicated" symbol.  */
+  {
+    static const char str[] = Z_SYM_NAME;
+    size_t len = strlen (str);
+    std::string lookup;
+
+    for (size_t i = 1; i < len; i++)
+      {
+       lookup.assign (str, i);
+       CHECK_MATCH (lookup.c_str (), symbol_name_match_type::FULL, true,
+                    EXPECT (Z_SYM_NAME));
+      }
+  }
+
+  /* In FULL mode, an incomplete symbol doesn't match.  */
+  {
+    CHECK_MATCH ("std::zfunction(int", symbol_name_match_type::FULL, false,
+                {});
+  }
+
+  /* A complete symbol with parameters matches any overload, since the
+     index has no overload info.  */
+  {
+    CHECK_MATCH ("std::zfunction(int)", symbol_name_match_type::FULL, true,
+                EXPECT ("std::zfunction", "std::zfunction2"));
+    CHECK_MATCH ("zfunction(int)", symbol_name_match_type::WILD, true,
+                EXPECT ("std::zfunction", "std::zfunction2"));
+    CHECK_MATCH ("zfunc", symbol_name_match_type::WILD, true,
+                EXPECT ("std::zfunction", "std::zfunction2"));
+  }
+
+  /* Check that whitespace is ignored appropriately.  A symbol with a
+     template argument list. */
+  {
+    static const char expected[] = "ns::foo<int>";
+    CHECK_MATCH ("ns :: foo < int > ", symbol_name_match_type::FULL, false,
+                EXPECT (expected));
+    CHECK_MATCH ("foo < int > ", symbol_name_match_type::WILD, false,
+                EXPECT (expected));
+  }
+
+  /* Check that whitespace is ignored appropriately.  A symbol with a
+     template argument list that includes a pointer.  */
+  {
+    static const char expected[] = "ns::foo<char*>";
+    /* Try both completion and non-completion modes.  */
+    static const bool completion_mode[2] = {false, true};
+    for (size_t i = 0; i < 2; i++)
+      {
+       CHECK_MATCH ("ns :: foo < char * >", symbol_name_match_type::FULL,
+                    completion_mode[i], EXPECT (expected));
+       CHECK_MATCH ("foo < char * >", symbol_name_match_type::WILD,
+                    completion_mode[i], EXPECT (expected));
+
+       CHECK_MATCH ("ns :: foo < char * > (int)", symbol_name_match_type::FULL,
+                    completion_mode[i], EXPECT (expected));
+       CHECK_MATCH ("foo < char * > (int)", symbol_name_match_type::WILD,
+                    completion_mode[i], EXPECT (expected));
+      }
+  }
+
+  {
+    /* Check method qualifiers are ignored.  */
+    static const char expected[] = "ns::foo<char*>";
+    CHECK_MATCH ("ns :: foo < char * >  ( int ) const",
+                symbol_name_match_type::FULL, true, EXPECT (expected));
+    CHECK_MATCH ("ns :: foo < char * >  ( int ) &&",
+                symbol_name_match_type::FULL, true, EXPECT (expected));
+    CHECK_MATCH ("foo < char * >  ( int ) const",
+                symbol_name_match_type::WILD, true, EXPECT (expected));
+    CHECK_MATCH ("foo < char * >  ( int ) &&",
+                symbol_name_match_type::WILD, true, EXPECT (expected));
+  }
+
+  /* Test lookup names that don't match anything.  */
+  {
+    CHECK_MATCH ("bar2", symbol_name_match_type::WILD, false,
+                {});
+
+    CHECK_MATCH ("doesntexist", symbol_name_match_type::FULL, false,
+                {});
+  }
+
+  /* Some wild matching tests, exercising "(anonymous namespace)",
+     which should not be confused with a parameter list.  */
+  {
+    static const char *syms[] = {
+      "A::B::C",
+      "B::C",
+      "C",
+      "A :: B :: C ( int )",
+      "B :: C ( int )",
+      "C ( int )",
+    };
+
+    for (const char *s : syms)
+      {
+       CHECK_MATCH (s, symbol_name_match_type::WILD, false,
+                    EXPECT ("(anonymous namespace)::A::B::C"));
+      }
+  }
+
+  {
+    static const char expected[] = "ns2::tmpl<int>::foo2";
+    CHECK_MATCH ("tmp", symbol_name_match_type::WILD, true,
+                EXPECT (expected));
+    CHECK_MATCH ("tmpl<", symbol_name_match_type::WILD, true,
+                EXPECT (expected));
+  }
+
+  SELF_CHECK (!any_mismatch);
+
+#undef EXPECT
+#undef CHECK_MATCH
+}
+
+static void
+run_test ()
+{
+  test_mapped_index_find_name_component_bounds ();
+  test_dw2_expand_symtabs_matching_symbol ();
+}
+
+}} // namespace selftests::dw2_expand_symtabs_matching
+
+#endif /* GDB_SELF_TEST */
+
+/* If FILE_MATCHER is NULL or if PER_CU has
+   dwarf2_per_cu_quick_data::MARK set (see
+   dw_expand_symtabs_matching_file_matcher), expand the CU and call
+   EXPANSION_NOTIFY on it.  */
+
+static void
+dw2_expand_symtabs_matching_one
+  (struct dwarf2_per_cu_data *per_cu,
+   gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
+   gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify)
+{
+  if (file_matcher == NULL || per_cu->v.quick->mark)
+    {
+      bool symtab_was_null
+       = (per_cu->v.quick->compunit_symtab == NULL);
+
+      dw2_instantiate_symtab (per_cu);
+
+      if (expansion_notify != NULL
+         && symtab_was_null
+         && per_cu->v.quick->compunit_symtab != NULL)
+       expansion_notify (per_cu->v.quick->compunit_symtab);
+    }
+}
+
+/* Helper for dw2_expand_matching symtabs.  Called on each symbol
+   matched, to expand corresponding CUs that were marked.  IDX is the
+   index of the symbol name that matched.  */
+
+static void
+dw2_expand_marked_cus
+  (mapped_index &index, offset_type idx,
+   struct objfile *objfile,
+   gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
+   gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+   search_domain kind)
+{
+  offset_type *vec, vec_len, vec_idx;
+  bool global_seen = false;
+
+  vec = (offset_type *) (index.constant_pool
+                        + MAYBE_SWAP (index.symbol_table[idx].vec));
+  vec_len = MAYBE_SWAP (vec[0]);
+  for (vec_idx = 0; vec_idx < vec_len; ++vec_idx)
+    {
+      struct dwarf2_per_cu_data *per_cu;
+      offset_type cu_index_and_attrs = MAYBE_SWAP (vec[vec_idx + 1]);
+      /* This value is only valid for index versions >= 7.  */
+      int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
+      gdb_index_symbol_kind symbol_kind =
+       GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
+      int cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
+      /* Only check the symbol attributes if they're present.
+        Indices prior to version 7 don't record them,
+        and indices >= 7 may elide them for certain symbols
+        (gold does this).  */
+      int attrs_valid =
+       (index.version >= 7
+        && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
+
+      /* Work around gold/15646.  */
+      if (attrs_valid)
+       {
+         if (!is_static && global_seen)
+           continue;
+         if (!is_static)
+           global_seen = true;
+       }
+
+      /* Only check the symbol's kind if it has one.  */
+      if (attrs_valid)
+       {
+         switch (kind)
+           {
+           case VARIABLES_DOMAIN:
+             if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE)
+               continue;
+             break;
+           case FUNCTIONS_DOMAIN:
+             if (symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION)
+               continue;
+             break;
+           case TYPES_DOMAIN:
+             if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
+               continue;
+             break;
+           default:
+             break;
+           }
+       }
+
+      /* Don't crash on bad data.  */
+      if (cu_index >= (dwarf2_per_objfile->n_comp_units
+                      + dwarf2_per_objfile->n_type_units))
+       {
+         complaint (&symfile_complaints,
+                    _(".gdb_index entry has bad CU index"
+                      " [in module %s]"), objfile_name (objfile));
+         continue;
+       }
+
+      per_cu = dw2_get_cutu (cu_index);
+      dw2_expand_symtabs_matching_one (per_cu, file_matcher,
+                                      expansion_notify);
+    }
+}
+
+/* If FILE_MATCHER is non-NULL, set all the
+   dwarf2_per_cu_quick_data::MARK of the current DWARF2_PER_OBJFILE
+   that match FILE_MATCHER.  */
+
+static void
+dw_expand_symtabs_matching_file_matcher
+  (gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher)
+{
+  if (file_matcher == NULL)
+    return;
+
+  objfile *const objfile = dwarf2_per_objfile->objfile;
+
+  htab_up visited_found (htab_create_alloc (10, htab_hash_pointer,
+                                           htab_eq_pointer,
+                                           NULL, xcalloc, xfree));
+  htab_up visited_not_found (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.  */
+
+  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)
+{
   dw2_setup (objfile);
 
-  if (!objfile->psymtabs_addrmap)
-    return NULL;
+  /* 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;
+}
 
-  data = (struct dwarf2_per_cu_data *) addrmap_find (objfile->psymtabs_addrmap,
-                                                    pc);
-  if (!data)
+/* See dw2_debug_names_iterator.  */
+
+dwarf2_per_cu_data *
+dw2_debug_names_iterator::next ()
+{
+  if (m_addr == NULL)
     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));
+  bfd *const abfd = dwarf2_per_objfile->objfile->obfd;
 
-  result
-    = recursively_find_pc_sect_compunit_symtab (dw2_instantiate_symtab (data),
-                                               pc);
-  gdb_assert (result != NULL);
-  return result;
-}
+ again:
 
-static void
-dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
-                         void *data, int need_fullname)
-{
-  int i;
-  htab_up visited (htab_create_alloc (10, htab_hash_pointer, htab_eq_pointer,
-                                     NULL, xcalloc, xfree));
+  unsigned int bytes_read;
+  const ULONGEST abbrev = read_unsigned_leb128 (abfd, m_addr, &bytes_read);
+  m_addr += bytes_read;
+  if (abbrev == 0)
+    return NULL;
 
-  dw2_setup (objfile);
+  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)
+           {
+             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_type_unit:
+         /* Don't crash on bad data.  */
+         if (ull >= dwarf2_per_objfile->n_type_units)
+           {
+             complaint (&symfile_complaints,
+                        _(".debug_names entry has bad TU index %s"
+                          " [in module %s]"),
+                        pulongest (ull),
+                        objfile_name (dwarf2_per_objfile->objfile));
+             continue;
+           }
+         per_cu = dw2_get_cutu (dwarf2_per_objfile->n_comp_units + 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;
+       }
+    }
 
-  /* 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.  */
+  /* Skip if already read in.  */
+  if (per_cu->v.quick->compunit_symtab)
+    goto again;
 
-  for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+  /* Check static vs global.  */
+  if (have_is_static)
     {
-      struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
+      const bool want_static = m_block_index != GLOBAL_BLOCK;
+      if (m_want_specific_block && want_static != is_static)
+       goto again;
+    }
 
-      if (per_cu->v.quick->compunit_symtab)
+  /* 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)
        {
-         void **slot = htab_find_slot (visited.get (),
-                                       per_cu->v.quick->file_names,
-                                       INSERT);
+       case 0:
+       case DW_TAG_variable:
+         break;
+       default:
+         goto again;
+       }
+      break;
+    default:
+      break;
+    }
 
-         *slot = per_cu->v.quick->file_names;
+  /* 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;
+    default:
+      break;
     }
 
-  for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+  return per_cu;
+}
+
+static struct compunit_symtab *
+dw2_debug_names_lookup_symbol (struct objfile *objfile, int block_index_int,
+                              const char *name, domain_enum domain)
+{
+  const block_enum block_index = static_cast<block_enum> (block_index_int);
+  dw2_setup (objfile);
+
+  const auto &mapp = dwarf2_per_objfile->debug_names_table;
+  if (!mapp)
     {
-      int j;
-      struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
-      struct quick_file_names *file_data;
-      void **slot;
+      /* index is NULL if OBJF_READNOW.  */
+      return NULL;
+    }
+  const auto &map = *mapp;
 
-      /* We only need to look at symtabs not already expanded.  */
-      if (per_cu->v.quick->compunit_symtab)
-       continue;
+  dw2_debug_names_iterator iter (map, true /* want_specific_block */,
+                                block_index, domain, name);
 
-      file_data = dw2_get_file_names (per_cu);
-      if (file_data == NULL)
-       continue;
+  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);
 
-      slot = htab_find_slot (visited.get (), file_data, INSERT);
-      if (*slot)
-       {
-         /* Already visited.  */
-         continue;
-       }
-      *slot = file_data;
+      sym = block_find_symbol (block, name, domain,
+                              block_find_non_opaque_type_preferred,
+                              &with_opaque);
 
-      for (j = 0; j < file_data->num_file_names; ++j)
-       {
-         const char *this_real_name;
+      /* Some caution must be observed with overloaded functions and
+        methods, since the index will not contain any overload
+        information (but NAME might contain it).  */
 
-         if (need_fullname)
-           this_real_name = dw2_get_real_path (objfile, file_data, j);
-         else
-           this_real_name = NULL;
-         (*fun) (file_data->file_names[j], this_real_name, data);
-       }
+      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;
+
+      /* Keep looking through other CUs.  */
     }
+
+  return stab_best;
 }
 
-static int
-dw2_has_symbols (struct objfile *objfile)
+/* 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)
 {
-  return 1;
+  dw2_setup (objfile);
+  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");
 }
 
-const struct quick_symbol_functions dwarf2_gdb_index_functions =
+static void
+dw2_debug_names_expand_symtabs_for_function (struct objfile *objfile,
+                                            const char *func_name)
+{
+  dw2_setup (objfile);
+
+  /* dwarf2_per_objfile->debug_names_table is NULL if OBJF_READNOW.  */
+  if (dwarf2_per_objfile->debug_names_table)
+    {
+      const mapped_debug_names &map = *dwarf2_per_objfile->debug_names_table;
+
+      /* 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);
+
+      struct dwarf2_per_cu_data *per_cu;
+      while ((per_cu = iter.next ()) != NULL)
+       dw2_instantiate_symtab (per_cu);
+    }
+}
+
+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);
+
+  /* debug_names_table is NULL if OBJF_READNOW.  */
+  if (!dwarf2_per_objfile->debug_names_table)
+    return;
+
+  dw_expand_symtabs_matching_file_matcher (file_matcher);
+
+  mapped_debug_names &map = *dwarf2_per_objfile->debug_names_table;
+
+  dw2_expand_symtabs_matching_symbol (map, lookup_name,
+                                     symbol_matcher,
+                                     kind, [&] (offset_type namei)
+    {
+      /* The name was matched, now expand corresponding CUs that were
+        marked.  */
+      dw2_debug_names_iterator iter (map, kind, namei);
+
+      struct dwarf2_per_cu_data *per_cu;
+      while ((per_cu = iter.next ()) != NULL)
+       dw2_expand_symtabs_matching_one (per_cu, file_matcher,
+                                        expansion_notify);
+    });
+}
+
+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
 };
 
-/* Initialize for reading DWARF for this objfile.  Return 0 if this
-   file will use psymtabs, or 1 if using the GNU index.  */
+/* See symfile.h.  */
 
-int
-dwarf2_initialize_objfile (struct objfile *objfile)
+bool
+dwarf2_initialize_objfile (struct objfile *objfile, dw_index_kind *index_kind)
 {
   /* If we're about to read full symbols, don't bother with the
      indices.  In this case we also don't care if some other debug
@@ -4378,13 +6494,23 @@ dwarf2_initialize_objfile (struct objfile *objfile)
       /* Return 1 so that gdb sees the "quick" functions.  However,
         these functions will be no-ops because we will have expanded
         all symtabs.  */
-      return 1;
+      *index_kind = dw_index_kind::GDB_INDEX;
+      return true;
+    }
+
+  if (dwarf2_read_debug_names (objfile))
+    {
+      *index_kind = dw_index_kind::DEBUG_NAMES;
+      return true;
     }
 
   if (dwarf2_read_index (objfile))
-    return 1;
+    {
+      *index_kind = dw_index_kind::GDB_INDEX;
+      return true;
+    }
 
-  return 0;
+  return false;
 }
 
 \f
@@ -4395,10 +6521,9 @@ void
 dwarf2_build_psymtabs (struct objfile *objfile)
 {
 
-  if (objfile->global_psymbols.size == 0 && objfile->static_psymbols.size == 0)
-    {
-      init_psymbol_list (objfile, 1024);
-    }
+  if (objfile->global_psymbols.capacity () == 0
+      && objfile->static_psymbols.capacity () == 0)
+    init_psymbol_list (objfile, 1024);
 
   TRY
     {
@@ -4622,7 +6747,6 @@ read_and_check_comp_unit_head (struct comp_unit_head *header,
                               rcuh_kind section_kind)
 {
   const gdb_byte *beg_of_comp_unit = info_ptr;
-  bfd *abfd = get_section_bfd_owner (section);
 
   header->sect_off = (sect_offset) (beg_of_comp_unit - section->buffer);
 
@@ -5265,7 +7389,6 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data *this_cu,
   struct dwarf2_section_info *section;
   bfd *abfd;
   const gdb_byte *begin_info_ptr, *info_ptr;
-  ULONGEST signature; /* Or dwo_id.  */
   struct attribute *comp_dir, *stmt_list, *low_pc, *high_pc, *ranges;
   int i,num_extra_attrs;
   struct dwarf2_section_info *dwo_abbrev_section;
@@ -5452,7 +7575,6 @@ lookup_dwo_unit (struct dwarf2_per_cu_data *this_cu,
                 struct die_info *comp_unit_die)
 {
   struct dwarf2_cu *cu = this_cu->cu;
-  struct attribute *attr;
   ULONGEST signature;
   struct dwo_unit *dwo_unit;
   const char *comp_dir, *dwo_name;
@@ -6082,8 +8204,8 @@ create_partial_symtab (struct dwarf2_per_cu_data *per_cu, const char *name)
   struct partial_symtab *pst;
 
   pst = start_psymtab_common (objfile, name, 0,
-                             objfile->global_psymbols.next,
-                             objfile->static_psymbols.next);
+                             objfile->global_psymbols,
+                             objfile->static_psymbols);
 
   pst->psymtabs_addrmap_supported = 1;
 
@@ -6249,8 +8371,6 @@ process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu,
                           int want_partial_unit,
                           enum language pretend_language)
 {
-  struct process_psymtab_comp_unit_data info;
-
   /* If this compilation unit was already read in, free the
      cached copy in order to read it in again. This is
      necessary because we skipped some symbols when we first
@@ -6259,12 +8379,17 @@ process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu,
   if (this_cu->cu != NULL)
     free_one_cached_comp_unit (this_cu);
 
-  gdb_assert (! this_cu->is_debug_types);
-  info.want_partial_unit = want_partial_unit;
-  info.pretend_language = pretend_language;
-  init_cutu_and_read_dies (this_cu, NULL, 0, 0,
-                          process_psymtab_comp_unit_reader,
-                          &info);
+  if (this_cu->is_debug_types)
+    init_cutu_and_read_dies (this_cu, NULL, 0, 0, build_type_psymtabs_reader,
+                            NULL);
+  else
+    {
+      process_psymtab_comp_unit_data info;
+      info.want_partial_unit = want_partial_unit;
+      info.pretend_language = pretend_language;
+      init_cutu_and_read_dies (this_cu, NULL, 0, 0,
+                              process_psymtab_comp_unit_reader, &info);
+    }
 
   /* Age out any secondary CUs.  */
   age_cached_comp_units ();
@@ -6583,16 +8708,6 @@ process_skeletonless_type_units (struct objfile *objfile)
     }
 }
 
-/* A cleanup function that clears objfile's psymtabs_addrmap field.  */
-
-static void
-psymtabs_addrmap_cleanup (void *o)
-{
-  struct objfile *objfile = (struct objfile *) o;
-
-  objfile->psymtabs_addrmap = NULL;
-}
-
 /* Compute the 'user' field for each psymtab in OBJFILE.  */
 
 static void
@@ -6624,8 +8739,7 @@ set_partial_user (struct objfile *objfile)
 static void
 dwarf2_build_psymtabs_hard (struct objfile *objfile)
 {
-  struct cleanup *back_to, *addrmap_cleanup;
-  struct obstack temp_obstack;
+  struct cleanup *back_to;
   int i;
 
   if (dwarf_read_debug)
@@ -6648,10 +8762,11 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile)
 
   /* Create a temporary address map on a temporary obstack.  We later
      copy this to the final obstack.  */
-  obstack_init (&temp_obstack);
-  make_cleanup_obstack_free (&temp_obstack);
-  objfile->psymtabs_addrmap = addrmap_create_mutable (&temp_obstack);
-  addrmap_cleanup = make_cleanup (psymtabs_addrmap_cleanup, objfile);
+  auto_obstack temp_obstack;
+
+  scoped_restore save_psymtabs_addrmap
+    = make_scoped_restore (&objfile->psymtabs_addrmap,
+                          addrmap_create_mutable (&temp_obstack));
 
   for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
     {
@@ -6677,7 +8792,8 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile)
 
   objfile->psymtabs_addrmap = addrmap_create_fixed (objfile->psymtabs_addrmap,
                                                    &objfile->objfile_obstack);
-  discard_cleanups (addrmap_cleanup);
+  /* At this point we want to keep the address map.  */
+  save_psymtabs_addrmap.release ();
 
   do_cleanups (back_to);
 
@@ -6719,13 +8835,13 @@ load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu)
 static void
 read_comp_units_from_section (struct objfile *objfile,
                              struct dwarf2_section_info *section,
+                             struct dwarf2_section_info *abbrev_section,
                              unsigned int is_dwz,
                              int *n_allocated,
                              int *n_comp_units,
                              struct dwarf2_per_cu_data ***all_comp_units)
 {
   const gdb_byte *info_ptr;
-  bfd *abfd = get_section_bfd_owner (section);
 
   if (dwarf_read_debug)
     fprintf_unfiltered (gdb_stdlog, "Reading %s for %s\n",
@@ -6738,20 +8854,33 @@ read_comp_units_from_section (struct objfile *objfile,
 
   while (info_ptr < section->buffer + section->size)
     {
-      unsigned int length, initial_length_size;
       struct dwarf2_per_cu_data *this_cu;
 
       sect_offset sect_off = (sect_offset) (info_ptr - section->buffer);
 
-      /* Read just enough information to find out where the next
-        compilation unit is.  */
-      length = read_initial_length (abfd, info_ptr, &initial_length_size);
+      comp_unit_head cu_header;
+      read_and_check_comp_unit_head (&cu_header, section, abbrev_section,
+                                    info_ptr, rcuh_kind::COMPILE);
 
       /* Save the compilation unit for later lookup.  */
-      this_cu = XOBNEW (&objfile->objfile_obstack, struct dwarf2_per_cu_data);
-      memset (this_cu, 0, sizeof (*this_cu));
+      if (cu_header.unit_type != DW_UT_type)
+       {
+         this_cu = XOBNEW (&objfile->objfile_obstack,
+                           struct dwarf2_per_cu_data);
+         memset (this_cu, 0, sizeof (*this_cu));
+       }
+      else
+       {
+         auto sig_type = XOBNEW (&objfile->objfile_obstack,
+                                 struct signatured_type);
+         memset (sig_type, 0, sizeof (*sig_type));
+         sig_type->signature = cu_header.signature;
+         sig_type->type_offset_in_tu = cu_header.type_cu_offset_in_tu;
+         this_cu = &sig_type->per_cu;
+       }
+      this_cu->is_debug_types = (cu_header.unit_type == DW_UT_type);
       this_cu->sect_off = sect_off;
-      this_cu->length = length + initial_length_size;
+      this_cu->length = cu_header.length + cu_header.initial_length_size;
       this_cu->is_dwz = is_dwz;
       this_cu->objfile = objfile;
       this_cu->section = section;
@@ -6784,12 +8913,13 @@ create_all_comp_units (struct objfile *objfile)
   n_allocated = 10;
   all_comp_units = XNEWVEC (struct dwarf2_per_cu_data *, n_allocated);
 
-  read_comp_units_from_section (objfile, &dwarf2_per_objfile->info, 0,
+  read_comp_units_from_section (objfile, &dwarf2_per_objfile->info,
+                               &dwarf2_per_objfile->abbrev, 0,
                                &n_allocated, &n_comp_units, &all_comp_units);
 
   dwz = dwarf2_get_dwz_file ();
   if (dwz != NULL)
-    read_comp_units_from_section (objfile, &dwz->info, 1,
+    read_comp_units_from_section (objfile, &dwz->info, &dwz->abbrev, 1,
                                  &n_allocated, &n_comp_units,
                                  &all_comp_units);
 
@@ -7096,7 +9226,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
       break;
     case DW_TAG_constant:
       {
-        struct psymbol_allocation_list *list;
+       std::vector<partial_symbol *> *list;
 
        if (pdi->is_external)
          list = &objfile->global_psymbols;
@@ -7951,6 +10081,23 @@ free_delayed_list (void *ptr)
     }
 }
 
+/* Check whether [PHYSNAME, PHYSNAME+LEN) ends with a modifier like
+   "const" / "volatile".  If so, decrements LEN by the length of the
+   modifier and return true.  Otherwise return false.  */
+
+template<size_t N>
+static bool
+check_modifier (const char *physname, size_t &len, const char (&mod)[N])
+{
+  size_t mod_len = sizeof (mod) - 1;
+  if (len > mod_len && startswith (physname + (len - mod_len), mod))
+    {
+      len -= mod_len;
+      return true;
+    }
+  return false;
+}
+
 /* Compute the physnames of any methods on the CU's method list.
 
    The computation of method physnames is delayed in order to avoid the
@@ -7962,6 +10109,12 @@ compute_delayed_physnames (struct dwarf2_cu *cu)
 {
   int i;
   struct delayed_method_info *mi;
+
+  /* Only C++ delays computing physnames.  */
+  if (VEC_empty (delayed_method_info, cu->method_list))
+    return;
+  gdb_assert (cu->language == language_cplus);
+
   for (i = 0; VEC_iterate (delayed_method_info, cu->method_list, i, mi) ; ++i)
     {
       const char *physname;
@@ -7970,6 +10123,26 @@ compute_delayed_physnames (struct dwarf2_cu *cu)
       physname = dwarf2_physname (mi->name, mi->die, cu);
       TYPE_FN_FIELD_PHYSNAME (fn_flp->fn_fields, mi->index)
        = physname ? physname : "";
+
+      /* Since there's no tag to indicate whether a method is a
+        const/volatile overload, extract that information out of the
+        demangled name.  */
+      if (physname != NULL)
+       {
+         size_t len = strlen (physname);
+
+         while (1)
+           {
+             if (physname[len] == ')') /* shortcut */
+               break;
+             else if (check_modifier (physname, len, " const"))
+               TYPE_FN_FIELD_CONST (fn_flp->fn_fields, mi->index) = 1;
+             else if (check_modifier (physname, len, " volatile"))
+               TYPE_FN_FIELD_VOLATILE (fn_flp->fn_fields, mi->index) = 1;
+             else
+               break;
+           }
+       }
     }
 }
 
@@ -8205,7 +10378,7 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   CORE_ADDR lowpc, highpc;
   struct compunit_symtab *cust;
-  struct cleanup *back_to, *delayed_list_cleanup;
+  struct cleanup *delayed_list_cleanup;
   CORE_ADDR baseaddr;
   struct block *static_block;
   CORE_ADDR addr;
@@ -8213,7 +10386,7 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
   buildsym_init ();
-  back_to = make_cleanup (really_free_pendings, NULL);
+  scoped_free_pendings free_pending;
   delayed_list_cleanup = make_cleanup (free_delayed_list, cu);
 
   cu->list_in_scope = &file_symbols;
@@ -8295,8 +10468,6 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
 
   /* Push it for inclusion processing later.  */
   VEC_safe_push (dwarf2_per_cu_ptr, dwarf2_per_objfile->just_read_cus, per_cu);
-
-  do_cleanups (back_to);
 }
 
 /* Generate full symbol information for type unit PER_CU, whose DIEs have
@@ -8309,14 +10480,14 @@ process_full_type_unit (struct dwarf2_per_cu_data *per_cu,
   struct dwarf2_cu *cu = per_cu->cu;
   struct objfile *objfile = per_cu->objfile;
   struct compunit_symtab *cust;
-  struct cleanup *back_to, *delayed_list_cleanup;
+  struct cleanup *delayed_list_cleanup;
   struct signatured_type *sig_type;
 
   gdb_assert (per_cu->is_debug_types);
   sig_type = (struct signatured_type *) per_cu;
 
   buildsym_init ();
-  back_to = make_cleanup (really_free_pendings, NULL);
+  scoped_free_pendings free_pending;
   delayed_list_cleanup = make_cleanup (free_delayed_list, cu);
 
   cu->list_in_scope = &file_symbols;
@@ -8371,8 +10542,6 @@ process_full_type_unit (struct dwarf2_per_cu_data *per_cu,
       pst->compunit_symtab = cust;
       pst->readin = 1;
     }
-
-  do_cleanups (back_to);
 }
 
 /* Process an imported unit DIE.  */
@@ -8407,28 +10576,44 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
     }
 }
 
-/* Reset the in_process bit of a die.  */
-
-static void
-reset_die_in_process (void *arg)
+/* RAII object that represents a process_die scope: i.e.,
+   starts/finishes processing a DIE.  */
+class process_die_scope
 {
-  struct die_info *die = (struct die_info *) arg;
+public:
+  process_die_scope (die_info *die, dwarf2_cu *cu)
+    : m_die (die), m_cu (cu)
+  {
+    /* We should only be processing DIEs not already in process.  */
+    gdb_assert (!m_die->in_process);
+    m_die->in_process = true;
+  }
 
-  die->in_process = 0;
-}
+  ~process_die_scope ()
+  {
+    m_die->in_process = false;
+
+    /* If we're done processing the DIE for the CU that owns the line
+       header, we don't need the line header anymore.  */
+    if (m_cu->line_header_die_owner == m_die)
+      {
+       delete m_cu->line_header;
+       m_cu->line_header = NULL;
+       m_cu->line_header_die_owner = NULL;
+      }
+  }
+
+private:
+  die_info *m_die;
+  dwarf2_cu *m_cu;
+};
 
 /* Process a die and its children.  */
 
 static void
 process_die (struct die_info *die, struct dwarf2_cu *cu)
 {
-  struct cleanup *in_process;
-
-  /* We should only be processing those not already in process.  */
-  gdb_assert (!die->in_process);
-
-  die->in_process = 1;
-  in_process = make_cleanup (reset_die_in_process,die);
+  process_die_scope scope (die, cu);
 
   switch (die->tag)
     {
@@ -8515,12 +10700,14 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       process_imported_unit_die (die, cu);
       break;
 
+    case DW_TAG_variable:
+      read_variable (die, cu);
+      break;
+
     default:
       new_symbol (die, NULL, cu);
       break;
     }
-
-  do_cleanups (in_process);
 }
 \f
 /* DWARF name computation.  */
@@ -8584,6 +10771,38 @@ die_needs_namespace (struct die_info *die, struct dwarf2_cu *cu)
     }
 }
 
+/* Return the DIE's linkage name attribute, either DW_AT_linkage_name
+   or DW_AT_MIPS_linkage_name.  Returns NULL if the attribute is not
+   defined for the given DIE.  */
+
+static struct attribute *
+dw2_linkage_name_attr (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct attribute *attr;
+
+  attr = dwarf2_attr (die, DW_AT_linkage_name, cu);
+  if (attr == NULL)
+    attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu);
+
+  return attr;
+}
+
+/* Return the DIE's linkage name as a string, either DW_AT_linkage_name
+   or DW_AT_MIPS_linkage_name.  Returns NULL if the attribute is not
+   defined for the given DIE.  */
+
+static const char *
+dw2_linkage_name (struct die_info *die, struct dwarf2_cu *cu)
+{
+  const char *linkage_name;
+
+  linkage_name = dwarf2_string_attr (die, DW_AT_linkage_name, cu);
+  if (linkage_name == NULL)
+    linkage_name = dwarf2_string_attr (die, DW_AT_MIPS_linkage_name, cu);
+
+  return linkage_name;
+}
+
 /* Compute the fully qualified name of DIE in CU.  If PHYSNAME is nonzero,
    compute the physname for the object, which include a method's:
    - formal parameters (C++),
@@ -8623,11 +10842,8 @@ dwarf2_compute_name (const char *name,
         to be able to reference.  Ideally, we want the user to be able
         to reference this entity using either natural or linkage name,
         but we haven't started looking at this enhancement yet.  */
-      const char *linkage_name;
+      const char *linkage_name = dw2_linkage_name (die, cu);
 
-      linkage_name = dwarf2_string_attr (die, DW_AT_linkage_name, cu);
-      if (linkage_name == NULL)
-       linkage_name = dwarf2_string_attr (die, DW_AT_MIPS_linkage_name, cu);
       if (linkage_name != NULL)
        return linkage_name;
     }
@@ -8640,7 +10856,6 @@ dwarf2_compute_name (const char *name,
     {
       if (die_needs_namespace (die, cu))
        {
-         long length;
          const char *prefix;
          const char *canonical_name = NULL;
 
@@ -8858,7 +11073,6 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->objfile;
   const char *retval, *mangled = NULL, *canon = NULL;
-  struct cleanup *back_to;
   int need_copy = 1;
 
   /* In this case dwarf2_compute_name is just a shortcut not building anything
@@ -8866,11 +11080,7 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   if (!die_needs_namespace (die, cu))
     return dwarf2_compute_name (name, die, cu, 1);
 
-  back_to = make_cleanup (null_cleanup, NULL);
-
-  mangled = dwarf2_string_attr (die, DW_AT_linkage_name, cu);
-  if (mangled == NULL)
-    mangled = dwarf2_string_attr (die, DW_AT_MIPS_linkage_name, cu);
+  mangled = dw2_linkage_name (die, cu);
 
   /* rustc emits invalid values for DW_AT_linkage_name.  Ignore these.
      See https://github.com/rust-lang/rust/issues/32925.  */
@@ -8880,10 +11090,9 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
 
   /* DW_AT_linkage_name is missing in some cases - depend on what GDB
      has computed.  */
+  gdb::unique_xmalloc_ptr<char> demangled;
   if (mangled != NULL)
     {
-      char *demangled;
-
       /* Use DMGL_RET_DROP for C++ template functions to suppress their return
         type.  It is easier for GDB users to search for such functions as
         `name(params)' than `long name(params)'.  In such case the minimal
@@ -8898,18 +11107,15 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
          /* This is a lie, but we already lie to the caller new_symbol_full.
             new_symbol_full assumes we return the mangled name.
             This just undoes that lie until things are cleaned up.  */
-         demangled = NULL;
        }
       else
        {
-         demangled = gdb_demangle (mangled,
-                                   (DMGL_PARAMS | DMGL_ANSI | DMGL_RET_DROP));
+         demangled.reset (gdb_demangle (mangled,
+                                        (DMGL_PARAMS | DMGL_ANSI
+                                         | DMGL_RET_DROP)));
        }
       if (demangled)
-       {
-         make_cleanup (xfree, demangled);
-         canon = demangled;
-       }
+       canon = demangled.get ();
       else
        {
          canon = mangled;
@@ -8953,7 +11159,6 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
              obstack_copy0 (&objfile->per_bfd->storage_obstack,
                             retval, strlen (retval)));
 
-  do_cleanups (back_to);
   return retval;
 }
 
@@ -9050,8 +11255,7 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
   const char *import_alias;
   const char *imported_declaration = NULL;
   const char *import_prefix;
-  VEC (const_char_ptr) *excludes = NULL;
-  struct cleanup *cleanups;
+  std::vector<const char *> excludes;
 
   import_attr = dwarf2_attr (die, DW_AT_import, cu);
   if (import_attr == NULL)
@@ -9125,8 +11329,6 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
   else
     canonical_name = imported_name;
 
-  cleanups = make_cleanup (VEC_cleanup (const_char_ptr), &excludes);
-
   if (die->tag == DW_TAG_imported_module && cu->language == language_fortran)
     for (child_die = die->child; child_die && child_die->tag;
         child_die = sibling_die (child_die))
@@ -9166,7 +11368,7 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
            continue;
          }
 
-       VEC_safe_push (const_char_ptr, excludes, imported_name);
+       excludes.push_back (imported_name);
 
        process_die (child_die, cu);
       }
@@ -9179,8 +11381,19 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
                       excludes,
                       0,
                       &objfile->objfile_obstack);
+}
 
-  do_cleanups (cleanups);
+/* ICC<14 does not output the required DW_AT_declaration on incomplete
+   types, but gives them a size of zero.  Starting with version 14,
+   ICC is compatible with GCC.  */
+
+static int
+producer_is_icc_lt_14 (struct dwarf2_cu *cu)
+{
+  if (!cu->checked_producer)
+    check_producer (cu);
+
+  return cu->producer_is_icc_lt_14;
 }
 
 /* Check for possibly missing DW_AT_comp_dir with relative .debug_line
@@ -9243,7 +11456,6 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
   struct attribute *attr;
   struct line_header line_header_local;
   hashval_t line_header_local_hash;
-  unsigned u;
   void **slot;
   int decode_mapping;
 
@@ -9298,7 +11510,9 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
   line_header_up lh = dwarf_decode_line_header (line_offset, cu);
   if (lh == NULL)
     return;
-  cu->line_header = lh.get ();
+
+  cu->line_header = lh.release ();
+  cu->line_header_die_owner = die;
 
   if (dwarf2_per_objfile->line_header_hash == NULL)
     slot = NULL;
@@ -9314,6 +11528,7 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
       /* This newly decoded line number information unit will be owned
         by line_header_hash hash table.  */
       *slot = cu->line_header;
+      cu->line_header_die_owner = NULL;
     }
   else
     {
@@ -9328,7 +11543,6 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
   dwarf_decode_lines (cu->line_header, comp_dir, cu, NULL, lowpc,
                      decode_mapping);
 
-  lh.release ();
 }
 
 /* Process DW_TAG_compile_unit or DW_TAG_partial_unit.  */
@@ -9466,7 +11680,8 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
       return;
     }
 
-  cu->line_header = lh.get ();
+  cu->line_header = lh.release ();
+  cu->line_header_die_owner = die;
 
   if (first_time)
     {
@@ -9477,21 +11692,23 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
         process_full_type_unit still needs to know if this is the first
         time.  */
 
-      tu_group->num_symtabs = lh->file_names.size ();
-      tu_group->symtabs = XNEWVEC (struct symtab *, lh->file_names.size ());
+      tu_group->num_symtabs = cu->line_header->file_names.size ();
+      tu_group->symtabs = XNEWVEC (struct symtab *,
+                                  cu->line_header->file_names.size ());
 
-      for (i = 0; i < lh->file_names.size (); ++i)
+      for (i = 0; i < cu->line_header->file_names.size (); ++i)
        {
-         file_entry &fe = lh->file_names[i];
+         file_entry &fe = cu->line_header->file_names[i];
 
-         dwarf2_start_subfile (fe.name, fe.include_dir (lh.get ()));
+         dwarf2_start_subfile (fe.name, fe.include_dir (cu->line_header));
 
          if (current_subfile->symtab == NULL)
            {
-             /* NOTE: start_subfile will recognize when it's been passed
-                a file it has already seen.  So we can't assume there's a
-                simple mapping from lh->file_names to subfiles, plus
-                lh->file_names may contain dups.  */
+             /* NOTE: start_subfile will recognize when it's been
+                passed a file it has already seen.  So we can't
+                assume there's a simple mapping from
+                cu->line_header->file_names to subfiles, plus
+                cu->line_header->file_names may contain dups.  */
              current_subfile->symtab
                = allocate_symtab (cust, current_subfile->name);
            }
@@ -9504,16 +11721,14 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
     {
       restart_symtab (tu_group->compunit_symtab, "", 0);
 
-      for (i = 0; i < lh->file_names.size (); ++i)
+      for (i = 0; i < cu->line_header->file_names.size (); ++i)
        {
-         struct file_entry *fe = &lh->file_names[i];
+         file_entry &fe = cu->line_header->file_names[i];
 
-         fe->symtab = tu_group->symtabs[i];
+         fe.symtab = tu_group->symtabs[i];
        }
     }
 
-  lh.release ();
-
   /* The main symtab is allocated last.  Type units don't have DW_AT_name
      so they don't have a "real" (so to speak) symtab anyway.
      There is later code that will assign the main symtab to all symbols
@@ -9704,72 +11919,75 @@ create_dwo_cu_reader (const struct die_reader_specs *reader,
                        hex_string (dwo_unit->signature));
 }
 
-/* Create the dwo_unit for the lone CU in DWO_FILE.
+/* Create the dwo_units for the CUs in a DWO_FILE.
    Note: This function processes DWO files only, not DWP files.  */
 
-static struct dwo_unit *
-create_dwo_cu (struct dwo_file *dwo_file)
+static void
+create_cus_hash_table (struct dwo_file &dwo_file, dwarf2_section_info &section,
+                      htab_t &cus_htab)
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
-  struct dwarf2_section_info *section = &dwo_file->sections.info;
   const gdb_byte *info_ptr, *end_ptr;
-  struct create_dwo_cu_data create_dwo_cu_data;
-  struct dwo_unit *dwo_unit;
 
-  dwarf2_read_section (objfile, section);
-  info_ptr = section->buffer;
+  dwarf2_read_section (objfile, &section);
+  info_ptr = section.buffer;
 
   if (info_ptr == NULL)
-    return NULL;
+    return;
 
   if (dwarf_read_debug)
     {
       fprintf_unfiltered (gdb_stdlog, "Reading %s for %s:\n",
-                         get_section_name (section),
-                         get_section_file_name (section));
+                         get_section_name (&section),
+                         get_section_file_name (&section));
     }
 
-  create_dwo_cu_data.dwo_file = dwo_file;
-  dwo_unit = NULL;
-
-  end_ptr = info_ptr + section->size;
+  end_ptr = info_ptr + section.size;
   while (info_ptr < end_ptr)
     {
       struct dwarf2_per_cu_data per_cu;
+      struct create_dwo_cu_data create_dwo_cu_data;
+      struct dwo_unit *dwo_unit;
+      void **slot;
+      sect_offset sect_off = (sect_offset) (info_ptr - section.buffer);
 
       memset (&create_dwo_cu_data.dwo_unit, 0,
              sizeof (create_dwo_cu_data.dwo_unit));
       memset (&per_cu, 0, sizeof (per_cu));
       per_cu.objfile = objfile;
       per_cu.is_debug_types = 0;
-      per_cu.sect_off = sect_offset (info_ptr - section->buffer);
-      per_cu.section = section;
+      per_cu.sect_off = sect_offset (info_ptr - section.buffer);
+      per_cu.section = &section;
+      create_dwo_cu_data.dwo_file = &dwo_file;
+
+      init_cutu_and_read_dies_no_follow (
+         &per_cu, &dwo_file, create_dwo_cu_reader, &create_dwo_cu_data);
+      info_ptr += per_cu.length;
 
-      init_cutu_and_read_dies_no_follow (&per_cu, dwo_file,
-                                        create_dwo_cu_reader,
-                                        &create_dwo_cu_data);
+      // If the unit could not be parsed, skip it.
+      if (create_dwo_cu_data.dwo_unit.dwo_file == NULL)
+       continue;
+
+      if (cus_htab == NULL)
+       cus_htab = allocate_dwo_unit_table (objfile);
 
-      if (create_dwo_cu_data.dwo_unit.dwo_file != NULL)
+      dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
+      *dwo_unit = create_dwo_cu_data.dwo_unit;
+      slot = htab_find_slot (cus_htab, dwo_unit, INSERT);
+      gdb_assert (slot != NULL);
+      if (*slot != NULL)
        {
-         /* If we've already found one, complain.  We only support one
-            because having more than one requires hacking the dwo_name of
-            each to match, which is highly unlikely to happen.  */
-         if (dwo_unit != NULL)
-           {
-             complaint (&symfile_complaints,
-                        _("Multiple CUs in DWO file %s [in module %s]"),
-                        dwo_file->dwo_name, objfile_name (objfile));
-             break;
-           }
+         const struct dwo_unit *dup_cu = (const struct dwo_unit *)*slot;
+         sect_offset dup_sect_off = dup_cu->sect_off;
 
-         dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
-         *dwo_unit = create_dwo_cu_data.dwo_unit;
+         complaint (&symfile_complaints,
+                    _("debug cu entry at offset 0x%x is duplicate to"
+                      " the entry at offset 0x%x, signature %s"),
+                    to_underlying (sect_off), to_underlying (dup_sect_off),
+                    hex_string (dwo_unit->signature));
        }
-
-      info_ptr += per_cu.length;
+      *slot = (void *)dwo_unit;
     }
-
-  return dwo_unit;
 }
 
 /* DWP file .debug_{cu,tu}_index section format:
@@ -10161,8 +12379,6 @@ create_dwo_unit_in_dwp_v1 (struct dwp_file *dwp_file,
   struct dwo_unit *dwo_unit;
   struct virtual_v1_dwo_sections sections;
   void **dwo_file_slot;
-  char *virtual_dwo_name;
-  struct cleanup *cleanups;
   int i;
 
   gdb_assert (dwp_file->version == 1);
@@ -10189,7 +12405,6 @@ create_dwo_unit_in_dwp_v1 (struct dwp_file *dwp_file,
    + 1 /* trailing zero */)
 
   memset (&sections, 0, sizeof (sections));
-  cleanups = make_cleanup (null_cleanup, 0);
 
   for (i = 0; i < MAX_NR_V1_DWO_SECTIONS; ++i)
     {
@@ -10241,28 +12456,27 @@ create_dwo_unit_in_dwp_v1 (struct dwp_file *dwp_file,
      (fewer struct dwo_file objects to allocate).  Remember that for really
      large apps there can be on the order of 8K CUs and 200K TUs, or more.  */
 
-  virtual_dwo_name =
-    xstrprintf ("virtual-dwo/%d-%d-%d-%d",
-               get_section_id (&sections.abbrev),
-               get_section_id (&sections.line),
-               get_section_id (&sections.loc),
-               get_section_id (&sections.str_offsets));
-  make_cleanup (xfree, virtual_dwo_name);
+  std::string virtual_dwo_name =
+    string_printf ("virtual-dwo/%d-%d-%d-%d",
+                  get_section_id (&sections.abbrev),
+                  get_section_id (&sections.line),
+                  get_section_id (&sections.loc),
+                  get_section_id (&sections.str_offsets));
   /* Can we use an existing virtual DWO file?  */
-  dwo_file_slot = lookup_dwo_file_slot (virtual_dwo_name, comp_dir);
+  dwo_file_slot = lookup_dwo_file_slot (virtual_dwo_name.c_str (), comp_dir);
   /* Create one if necessary.  */
   if (*dwo_file_slot == NULL)
     {
       if (dwarf_read_debug)
        {
          fprintf_unfiltered (gdb_stdlog, "Creating virtual DWO: %s\n",
-                             virtual_dwo_name);
+                             virtual_dwo_name.c_str ());
        }
       dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_file);
       dwo_file->dwo_name
        = (const char *) obstack_copy0 (&objfile->objfile_obstack,
-                                       virtual_dwo_name,
-                                       strlen (virtual_dwo_name));
+                                       virtual_dwo_name.c_str (),
+                                       virtual_dwo_name.size ());
       dwo_file->comp_dir = comp_dir;
       dwo_file->sections.abbrev = sections.abbrev;
       dwo_file->sections.line = sections.line;
@@ -10286,11 +12500,10 @@ create_dwo_unit_in_dwp_v1 (struct dwp_file *dwp_file,
       if (dwarf_read_debug)
        {
          fprintf_unfiltered (gdb_stdlog, "Using existing virtual DWO: %s\n",
-                             virtual_dwo_name);
+                             virtual_dwo_name.c_str ());
        }
       dwo_file = (struct dwo_file *) *dwo_file_slot;
     }
-  do_cleanups (cleanups);
 
   dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
   dwo_unit->dwo_file = dwo_file;
@@ -10333,8 +12546,6 @@ create_dwp_v2_section (struct dwarf2_section_info *section,
   if (sectp == NULL
       || offset + size > bfd_get_section_size (sectp))
     {
-      bfd *abfd = sectp->owner;
-
       error (_("Dwarf Error: Bad DWP V2 section info, doesn't fit"
               " in section %s [in module %s]"),
             sectp ? bfd_section_name (abfd, sectp) : "<unknown>",
@@ -10366,8 +12577,6 @@ create_dwo_unit_in_dwp_v2 (struct dwp_file *dwp_file,
   struct dwo_unit *dwo_unit;
   struct virtual_v2_dwo_sections sections;
   void **dwo_file_slot;
-  char *virtual_dwo_name;
-  struct cleanup *cleanups;
   int i;
 
   gdb_assert (dwp_file->version == 2);
@@ -10383,7 +12592,6 @@ create_dwo_unit_in_dwp_v2 (struct dwp_file *dwp_file,
   /* Fetch the section offsets of this DWO unit.  */
 
   memset (&sections, 0, sizeof (sections));
-  cleanups = make_cleanup (null_cleanup, 0);
 
   for (i = 0; i < dwp_htab->nr_columns; ++i)
     {
@@ -10441,29 +12649,28 @@ create_dwo_unit_in_dwp_v2 (struct dwp_file *dwp_file,
      (fewer struct dwo_file objects to allocate).  Remember that for really
      large apps there can be on the order of 8K CUs and 200K TUs, or more.  */
 
-  virtual_dwo_name =
-    xstrprintf ("virtual-dwo/%ld-%ld-%ld-%ld",
-               (long) (sections.abbrev_size ? sections.abbrev_offset : 0),
-               (long) (sections.line_size ? sections.line_offset : 0),
-               (long) (sections.loc_size ? sections.loc_offset : 0),
-               (long) (sections.str_offsets_size
-                       ? sections.str_offsets_offset : 0));
-  make_cleanup (xfree, virtual_dwo_name);
+  std::string virtual_dwo_name =
+    string_printf ("virtual-dwo/%ld-%ld-%ld-%ld",
+                  (long) (sections.abbrev_size ? sections.abbrev_offset : 0),
+                  (long) (sections.line_size ? sections.line_offset : 0),
+                  (long) (sections.loc_size ? sections.loc_offset : 0),
+                  (long) (sections.str_offsets_size
+                          ? sections.str_offsets_offset : 0));
   /* Can we use an existing virtual DWO file?  */
-  dwo_file_slot = lookup_dwo_file_slot (virtual_dwo_name, comp_dir);
+  dwo_file_slot = lookup_dwo_file_slot (virtual_dwo_name.c_str (), comp_dir);
   /* Create one if necessary.  */
   if (*dwo_file_slot == NULL)
     {
       if (dwarf_read_debug)
        {
          fprintf_unfiltered (gdb_stdlog, "Creating virtual DWO: %s\n",
-                             virtual_dwo_name);
+                             virtual_dwo_name.c_str ());
        }
       dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_file);
       dwo_file->dwo_name
        = (const char *) obstack_copy0 (&objfile->objfile_obstack,
-                                       virtual_dwo_name,
-                                       strlen (virtual_dwo_name));
+                                       virtual_dwo_name.c_str (),
+                                       virtual_dwo_name.size ());
       dwo_file->comp_dir = comp_dir;
       dwo_file->sections.abbrev =
        create_dwp_v2_section (&dwp_file->sections.abbrev,
@@ -10500,11 +12707,10 @@ create_dwo_unit_in_dwp_v2 (struct dwp_file *dwp_file,
       if (dwarf_read_debug)
        {
          fprintf_unfiltered (gdb_stdlog, "Using existing virtual DWO: %s\n",
-                             virtual_dwo_name);
+                             virtual_dwo_name.c_str ());
        }
       dwo_file = (struct dwo_file *) *dwo_file_slot;
     }
-  do_cleanups (cleanups);
 
   dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
   dwo_unit->dwo_file = dwo_file;
@@ -10774,7 +12980,7 @@ open_and_init_dwo_file (struct dwarf2_per_cu_data *per_cu,
   bfd_map_over_sections (dwo_file->dbfd, dwarf2_locate_dwo_sections,
                         &dwo_file->sections);
 
-  dwo_file->cu = create_dwo_cu (dwo_file);
+  create_cus_hash_table (*dwo_file, dwo_file->sections.info, dwo_file->cus);
 
   create_debug_types_hash_table (dwo_file, dwo_file->sections.types,
                                 dwo_file->tus);
@@ -11014,7 +13220,8 @@ open_and_init_dwp_file (void)
   dwp_file->tus = create_dwp_hash_table (dwp_file, 1);
 
   /* The DWP file version is stored in the hash table.  Oh well.  */
-  if (dwp_file->cus->version != dwp_file->tus->version)
+  if (dwp_file->cus && dwp_file->tus
+      && dwp_file->cus->version != dwp_file->tus->version)
     {
       /* Technically speaking, we should try to limp along, but this is
         pretty bizarre.  We use pulongest here because that's the established
@@ -11024,7 +13231,13 @@ open_and_init_dwp_file (void)
             pulongest (dwp_file->cus->version),
             pulongest (dwp_file->tus->version), dwp_name.c_str ());
     }
-  dwp_file->version = dwp_file->cus->version;
+
+  if (dwp_file->cus)
+    dwp_file->version = dwp_file->cus->version;
+  else if (dwp_file->tus)
+    dwp_file->version = dwp_file->tus->version;
+  else
+    dwp_file->version = 2;
 
   if (dwp_file->version == 2)
     bfd_map_over_sections (dwp_file->dbfd, dwarf2_locate_v2_dwp_sections,
@@ -11141,10 +13354,14 @@ lookup_dwo_cutu (struct dwarf2_per_cu_data *this_unit,
              dwo_cutu
                = (struct dwo_unit *) htab_find (dwo_file->tus, &find_dwo_cutu);
            }
-         else if (!is_debug_types && dwo_file->cu)
+         else if (!is_debug_types && dwo_file->cus)
            {
-             if (signature == dwo_file->cu->signature)
-               dwo_cutu = dwo_file->cu;
+             struct dwo_unit find_dwo_cutu;
+
+             memset (&find_dwo_cutu, 0, sizeof (find_dwo_cutu));
+             find_dwo_cutu.signature = signature;
+             dwo_cutu = (struct dwo_unit *)htab_find (dwo_file->cus,
+                                                      &find_dwo_cutu);
            }
 
          if (dwo_cutu != NULL)
@@ -11175,21 +13392,18 @@ lookup_dwo_cutu (struct dwarf2_per_cu_data *this_unit,
   {
     /* Print the name of the DWP file if we looked there, helps the user
        better diagnose the problem.  */
-    char *dwp_text = NULL;
-    struct cleanup *cleanups;
+    std::string dwp_text;
 
     if (dwp_file != NULL)
-      dwp_text = xstrprintf (" [in DWP file %s]", lbasename (dwp_file->name));
-    cleanups = make_cleanup (xfree, dwp_text);
+      dwp_text = string_printf (" [in DWP file %s]",
+                               lbasename (dwp_file->name));
 
     warning (_("Could not find DWO %s %s(%s)%s referenced by %s at offset 0x%x"
               " [in module %s]"),
             kind, dwo_name, hex_string (signature),
-            dwp_text != NULL ? dwp_text : "",
+            dwp_text.c_str (),
             this_unit->is_debug_types ? "TU" : "CU",
             to_underlying (this_unit->sect_off), objfile_name (objfile));
-
-    do_cleanups (cleanups);
   }
   return NULL;
 }
@@ -11312,17 +13526,6 @@ free_dwo_files (htab_t dwo_files, struct objfile *objfile)
 \f
 /* Read in various DIEs.  */
 
-/* qsort helper for inherit_abstract_dies.  */
-
-static int
-unsigned_int_compar (const void *ap, const void *bp)
-{
-  unsigned int a = *(unsigned int *) ap;
-  unsigned int b = *(unsigned int *) bp;
-
-  return (a > b) - (b > a);
-}
-
 /* DW_AT_abstract_origin inherits whole DIEs (not just their attributes).
    Inherit only the children of the DW_AT_abstract_origin DIE not being
    already referenced by DW_AT_abstract_origin from the children of the
@@ -11332,15 +13535,11 @@ static void
 inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct die_info *child_die;
-  unsigned die_children_count;
-  /* CU offsets which were referenced by children of the current DIE.  */
-  sect_offset *offsets;
-  sect_offset *offsets_end, *offsetp;
+  sect_offset *offsetp;
   /* Parent of DIE - referenced by DW_AT_abstract_origin.  */
   struct die_info *origin_die;
   /* Iterator of the ORIGIN_DIE children.  */
   struct die_info *origin_child_die;
-  struct cleanup *cleanups;
   struct attribute *attr;
   struct dwarf2_cu *origin_cu;
   struct pending **origin_previous_list_in_scope;
@@ -11368,17 +13567,8 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
               to_underlying (die->sect_off),
               to_underlying (origin_die->sect_off));
 
-  child_die = die->child;
-  die_children_count = 0;
-  while (child_die && child_die->tag)
-    {
-      child_die = sibling_die (child_die);
-      die_children_count++;
-    }
-  offsets = XNEWVEC (sect_offset, die_children_count);
-  cleanups = make_cleanup (xfree, offsets);
+  std::vector<sect_offset> offsets;
 
-  offsets_end = offsets;
   for (child_die = die->child;
        child_die && child_die->tag;
        child_die = sibling_die (child_die))
@@ -11431,19 +13621,19 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
                       to_underlying (child_die->sect_off),
                       to_underlying (child_origin_die->sect_off));
          else
-           *offsets_end++ = child_origin_die->sect_off;
+           offsets.push_back (child_origin_die->sect_off);
        }
     }
-  qsort (offsets, offsets_end - offsets, sizeof (*offsets),
-        unsigned_int_compar);
-  for (offsetp = offsets + 1; offsetp < offsets_end; offsetp++)
+  std::sort (offsets.begin (), offsets.end ());
+  sect_offset *offsets_end = offsets.data () + offsets.size ();
+  for (offsetp = offsets.data () + 1; offsetp < offsets_end; offsetp++)
     if (offsetp[-1] == *offsetp)
       complaint (&symfile_complaints,
                 _("Multiple children of DIE 0x%x refer "
                   "to DIE 0x%x as their abstract origin"),
                 to_underlying (die->sect_off), to_underlying (*offsetp));
 
-  offsetp = offsets;
+  offsetp = offsets.data ();
   origin_child_die = origin_die->child;
   while (origin_child_die && origin_child_die->tag)
     {
@@ -11464,8 +13654,6 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
       origin_child_die = sibling_die (origin_child_die);
     }
   origin_cu->list_in_scope = origin_previous_list_in_scope;
-
-  do_cleanups (cleanups);
 }
 
 static void
@@ -11482,7 +13670,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
   CORE_ADDR baseaddr;
   struct block *block;
   int inlined_func = (die->tag == DW_TAG_inlined_subroutine);
-  VEC (symbolp) *template_args = NULL;
+  std::vector<struct symbol *> template_args;
   struct template_symbol *templ_func = NULL;
 
   if (inlined_func)
@@ -11537,7 +13725,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
          || child_die->tag == DW_TAG_template_value_param)
        {
          templ_func = allocate_template_symbol (objfile);
-         templ_func->base.is_cplus_template_function = 1;
+         templ_func->subclass = SYMBOL_TEMPLATE;
          break;
        }
     }
@@ -11575,7 +13763,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
              struct symbol *arg = new_symbol (child_die, NULL, cu);
 
              if (arg != NULL)
-               VEC_safe_push (symbolp, template_args, arg);
+               template_args.push_back (arg);
            }
          else
            process_die (child_die, cu);
@@ -11630,18 +13818,17 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
   gdbarch_make_symbol_special (gdbarch, newobj->name, objfile);
 
   /* Attach template arguments to function.  */
-  if (! VEC_empty (symbolp, template_args))
+  if (!template_args.empty ())
     {
       gdb_assert (templ_func != NULL);
 
-      templ_func->n_template_arguments = VEC_length (symbolp, template_args);
+      templ_func->n_template_arguments = template_args.size ();
       templ_func->template_arguments
         = XOBNEWVEC (&objfile->objfile_obstack, struct symbol *,
                     templ_func->n_template_arguments);
       memcpy (templ_func->template_arguments,
-             VEC_address (symbolp, template_args),
+             template_args.data (),
              (templ_func->n_template_arguments * sizeof (struct symbol *)));
-      VEC_free (symbolp, template_args);
     }
 
   /* In C++, we can have functions nested inside functions (e.g., when
@@ -11894,13 +14081,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
          const char *target_physname;
 
          /* Prefer the mangled name; otherwise compute the demangled one.  */
-         target_physname = dwarf2_string_attr (target_die,
-                                               DW_AT_linkage_name,
-                                               target_cu);
-         if (target_physname == NULL)
-           target_physname = dwarf2_string_attr (target_die,
-                                                DW_AT_MIPS_linkage_name,
-                                                target_cu);
+         target_physname = dw2_linkage_name (target_die, target_cu);
          if (target_physname == NULL)
            target_physname = dwarf2_physname (NULL, target_die, target_cu);
          if (target_physname == NULL)
@@ -12058,6 +14239,57 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
     }
 }
 
+/* Helper function for read_variable.  If DIE represents a virtual
+   table, then return the type of the concrete object that is
+   associated with the virtual table.  Otherwise, return NULL.  */
+
+static struct type *
+rust_containing_type (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct attribute *attr = dwarf2_attr (die, DW_AT_type, cu);
+  if (attr == NULL)
+    return NULL;
+
+  /* Find the type DIE.  */
+  struct die_info *type_die = NULL;
+  struct dwarf2_cu *type_cu = cu;
+
+  if (attr_form_is_ref (attr))
+    type_die = follow_die_ref (die, attr, &type_cu);
+  if (type_die == NULL)
+    return NULL;
+
+  if (dwarf2_attr (type_die, DW_AT_containing_type, type_cu) == NULL)
+    return NULL;
+  return die_containing_type (type_die, type_cu);
+}
+
+/* Read a variable (DW_TAG_variable) DIE and create a new symbol.  */
+
+static void
+read_variable (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct rust_vtable_symbol *storage = NULL;
+
+  if (cu->language == language_rust)
+    {
+      struct type *containing_type = rust_containing_type (die, cu);
+
+      if (containing_type != NULL)
+       {
+         struct objfile *objfile = cu->objfile;
+
+         storage = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+                                   struct rust_vtable_symbol);
+         initialize_objfile_symbol (storage);
+         storage->concrete_type = containing_type;
+         storage->subclass = SYMBOL_RUST_VTABLE;
+       }
+    }
+
+  new_symbol_full (die, NULL, cu, storage);
+}
+
 /* Call CALLBACK from DW_AT_ranges attribute value OFFSET
    reading .debug_rnglists.
    Callback's type should be:
@@ -12071,18 +14303,11 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
                         Callback &&callback)
 {
   struct objfile *objfile = cu->objfile;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
-  struct comp_unit_head *cu_header = &cu->header;
   bfd *obfd = objfile->obfd;
-  unsigned int addr_size = cu_header->addr_size;
-  CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
   /* Base address selection entry.  */
   CORE_ADDR base;
   int found_base;
-  unsigned int dummy;
   const gdb_byte *buffer;
-  CORE_ADDR low = 0;
-  CORE_ADDR high = 0;
   CORE_ADDR baseaddr;
   bool overflow = false;
 
@@ -12244,7 +14469,6 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu,
                       Callback &&callback)
 {
   struct objfile *objfile = cu->objfile;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct comp_unit_head *cu_header = &cu->header;
   bfd *obfd = objfile->obfd;
   unsigned int addr_size = cu_header->addr_size;
@@ -12618,7 +14842,6 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
   attr = dwarf2_attr (die, DW_AT_ranges, cu);
   if (attr)
     {
-      bfd *obfd = objfile->obfd;
       /* DW_AT_ranges_base does not apply to DIEs from the DWO skeleton.
         We take advantage of the fact that DW_AT_ranges does not appear
         in DW_TAG_compile_unit of DWO files.  */
@@ -12683,8 +14906,8 @@ check_producer (struct dwarf2_cu *cu)
       cu->producer_is_gxx_lt_4_6 = major < 4 || (major == 4 && minor < 6);
       cu->producer_is_gcc_lt_4_3 = major < 4 || (major == 4 && minor < 3);
     }
-  else if (startswith (cu->producer, "Intel(R) C"))
-    cu->producer_is_icc = 1;
+  else if (producer_is_icc (cu->producer, &major, &minor))
+    cu->producer_is_icc_lt_14 = major < 14;
   else
     {
       /* For other non-GCC compilers, expect their behavior is DWARF version
@@ -12962,33 +15185,81 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
     }
 }
 
-/* Add a typedef defined in the scope of the FIP's class.  */
+/* Can the type given by DIE define another type?  */
+
+static bool
+type_can_define_types (const struct die_info *die)
+{
+  switch (die->tag)
+    {
+    case DW_TAG_typedef:
+    case DW_TAG_class_type:
+    case DW_TAG_structure_type:
+    case DW_TAG_union_type:
+    case DW_TAG_enumeration_type:
+      return true;
+
+    default:
+      return false;
+    }
+}
+
+/* Add a type definition defined in the scope of the FIP's class.  */
 
 static void
-dwarf2_add_typedef (struct field_info *fip, struct die_info *die,
-                   struct dwarf2_cu *cu)
+dwarf2_add_type_defn (struct field_info *fip, struct die_info *die,
+                     struct dwarf2_cu *cu)
 {
-  struct typedef_field_list *new_field;
-  struct typedef_field *fp;
+  struct decl_field_list *new_field;
+  struct decl_field *fp;
 
   /* Allocate a new field list entry and link it in.  */
-  new_field = XCNEW (struct typedef_field_list);
+  new_field = XCNEW (struct decl_field_list);
   make_cleanup (xfree, new_field);
 
-  gdb_assert (die->tag == DW_TAG_typedef);
+  gdb_assert (type_can_define_types (die));
 
   fp = &new_field->field;
 
-  /* Get name of field.  */
+  /* Get name of field.  NULL is okay here, meaning an anonymous type.  */
   fp->name = dwarf2_name (die, cu);
-  if (fp->name == NULL)
-    return;
-
   fp->type = read_type_die (die, cu);
 
-  new_field->next = fip->typedef_field_list;
-  fip->typedef_field_list = new_field;
-  fip->typedef_field_list_count++;
+  /* Save accessibility.  */
+  enum dwarf_access_attribute accessibility;
+  struct attribute *attr = dwarf2_attr (die, DW_AT_accessibility, cu);
+  if (attr != NULL)
+    accessibility = (enum dwarf_access_attribute) DW_UNSND (attr);
+  else
+    accessibility = dwarf2_default_access_attribute (die, cu);
+  switch (accessibility)
+    {
+    case DW_ACCESS_public:
+      /* The assumed value if neither private nor protected.  */
+      break;
+    case DW_ACCESS_private:
+      fp->is_private = 1;
+      break;
+    case DW_ACCESS_protected:
+      fp->is_protected = 1;
+      break;
+    default:
+      complaint (&symfile_complaints,
+                _("Unhandled DW_AT_accessibility value (%x)"), accessibility);
+    }
+
+  if (die->tag == DW_TAG_typedef)
+    {
+      new_field->next = fip->typedef_field_list;
+      fip->typedef_field_list = new_field;
+      fip->typedef_field_list_count++;
+    }
+  else
+    {
+      new_field->next = fip->nested_types_list;
+      fip->nested_types_list = new_field;
+      fip->nested_types_list_count++;
+    }
 }
 
 /* Create the vector of fields, and attach it to the type.  */
@@ -13371,7 +15642,6 @@ static int
 is_vtable_name (const char *name, struct dwarf2_cu *cu)
 {
   static const char vptr[] = "_vptr";
-  static const char vtable[] = "vtable";
 
   /* Look for the C++ form of the vtable.  */
   if (startswith (name, vptr) && is_cplus_marker (name[sizeof (vptr) - 1]))
@@ -13425,17 +15695,6 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
   smash_to_methodptr_type (type, new_type);
 }
 
-/* Return non-zero if the CU's PRODUCER string matches the Intel C/C++ compiler
-   (icc).  */
-
-static int
-producer_is_icc (struct dwarf2_cu *cu)
-{
-  if (!cu->checked_producer)
-    check_producer (cu);
-
-  return cu->producer_is_icc;
-}
 
 /* Called when we find the DIE that starts a structure or union scope
    (definition) to create a type for the structure or union.  Fill in
@@ -13541,10 +15800,10 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
       TYPE_LENGTH (type) = 0;
     }
 
-  if (producer_is_icc (cu) && (TYPE_LENGTH (type) == 0))
+  if (producer_is_icc_lt_14 (cu) && (TYPE_LENGTH (type) == 0))
     {
-      /* ICC does not output the required DW_AT_declaration
-        on incomplete types, but gives them a size of zero.  */
+      /* ICC<14 does not output the required DW_AT_declaration on
+        incomplete types, but gives them a size of zero.  */
       TYPE_STUB (type) = 1;
     }
   else
@@ -13586,7 +15845,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
   if (die->child != NULL && ! die_is_declaration (die, cu))
     {
       struct field_info fi;
-      VEC (symbolp) *template_args = NULL;
+      std::vector<struct symbol *> template_args;
       struct cleanup *back_to = make_cleanup (null_cleanup, 0);
 
       memset (&fi, 0, sizeof (struct field_info));
@@ -13623,35 +15882,33 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
              /* C++ base class field.  */
              dwarf2_add_field (&fi, child_die, cu);
            }
-         else if (child_die->tag == DW_TAG_typedef)
-           dwarf2_add_typedef (&fi, child_die, cu);
+         else if (type_can_define_types (child_die))
+           dwarf2_add_type_defn (&fi, child_die, cu);
          else if (child_die->tag == DW_TAG_template_type_param
                   || child_die->tag == DW_TAG_template_value_param)
            {
              struct symbol *arg = new_symbol (child_die, NULL, cu);
 
              if (arg != NULL)
-               VEC_safe_push (symbolp, template_args, arg);
+               template_args.push_back (arg);
            }
 
          child_die = sibling_die (child_die);
        }
 
       /* Attach template arguments to type.  */
-      if (! VEC_empty (symbolp, template_args))
+      if (!template_args.empty ())
        {
          ALLOCATE_CPLUS_STRUCT_TYPE (type);
-         TYPE_N_TEMPLATE_ARGUMENTS (type)
-           = VEC_length (symbolp, template_args);
+         TYPE_N_TEMPLATE_ARGUMENTS (type) = template_args.size ();
          TYPE_TEMPLATE_ARGUMENTS (type)
            = XOBNEWVEC (&objfile->objfile_obstack,
                         struct symbol *,
                         TYPE_N_TEMPLATE_ARGUMENTS (type));
          memcpy (TYPE_TEMPLATE_ARGUMENTS (type),
-                 VEC_address (symbolp, template_args),
+                 template_args.data (),
                  (TYPE_N_TEMPLATE_ARGUMENTS (type)
                   * sizeof (struct symbol *)));
-         VEC_free (symbolp, template_args);
        }
 
       /* Attach fields and member functions to the type.  */
@@ -13733,14 +15990,14 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
 
          ALLOCATE_CPLUS_STRUCT_TYPE (type);
          TYPE_TYPEDEF_FIELD_ARRAY (type)
-           = ((struct typedef_field *)
+           = ((struct decl_field *)
               TYPE_ALLOC (type, sizeof (TYPE_TYPEDEF_FIELD (type, 0)) * i));
          TYPE_TYPEDEF_FIELD_COUNT (type) = i;
 
          /* Reverse the list order to keep the debug info elements order.  */
          while (--i >= 0)
            {
-             struct typedef_field *dest, *src;
+             struct decl_field *dest, *src;
 
              dest = &TYPE_TYPEDEF_FIELD (type, i);
              src = &fi.typedef_field_list->field;
@@ -13749,6 +16006,30 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
            }
        }
 
+      /* Copy fi.nested_types_list linked list elements content into the
+        allocated array TYPE_NESTED_TYPES_ARRAY (type).  */
+      if (fi.nested_types_list != NULL && cu->language != language_ada)
+       {
+         int i = fi.nested_types_list_count;
+
+         ALLOCATE_CPLUS_STRUCT_TYPE (type);
+         TYPE_NESTED_TYPES_ARRAY (type)
+           = ((struct decl_field *)
+              TYPE_ALLOC (type, sizeof (struct decl_field) * i));
+         TYPE_NESTED_TYPES_COUNT (type) = i;
+
+         /* Reverse the list order to keep the debug info elements order.  */
+         while (--i >= 0)
+           {
+             struct decl_field *dest, *src;
+
+             dest = &TYPE_NESTED_TYPES_FIELD (type, i);
+             src = &fi.nested_types_list->field;
+             fi.nested_types_list = fi.nested_types_list->next;
+             *dest = *src;
+           }
+       }
+
       do_cleanups (back_to);
     }
 
@@ -13795,15 +16076,12 @@ update_enumeration_type_from_children (struct die_info *die,
                                       struct type *type,
                                       struct dwarf2_cu *cu)
 {
-  struct obstack obstack;
   struct die_info *child_die;
   int unsigned_enum = 1;
   int flag_enum = 1;
   ULONGEST mask = 0;
-  struct cleanup *old_chain;
 
-  obstack_init (&obstack);
-  old_chain = make_cleanup_obstack_free (&obstack);
+  auto_obstack obstack;
 
   for (child_die = die->child;
        child_die != NULL && child_die->tag;
@@ -13848,8 +16126,6 @@ update_enumeration_type_from_children (struct die_info *die,
     TYPE_UNSIGNED (type) = 1;
   if (flag_enum)
     TYPE_FLAG_ENUM (type) = 1;
-
-  do_cleanups (old_chain);
 }
 
 /* Given a DW_AT_enumeration_type die, set its type.  We do not
@@ -14034,10 +16310,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
   struct die_info *child_die;
   struct type *type;
   struct type *element_type, *range_type, *index_type;
-  struct type **range_types = NULL;
   struct attribute *attr;
-  int ndim = 0;
-  struct cleanup *back_to;
   const char *name;
   unsigned int bit_stride = 0;
 
@@ -14067,7 +16340,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
       return set_die_type (die, type, cu);
     }
 
-  back_to = make_cleanup (null_cleanup, NULL);
+  std::vector<struct type *> range_types;
   child_die = die->child;
   while (child_die && child_die->tag)
     {
@@ -14079,15 +16352,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
             {
              /* The range type was succesfully read.  Save it for the
                  array type creation.  */
-              if ((ndim % DW_FIELD_ALLOC_CHUNK) == 0)
-                {
-                  range_types = (struct type **)
-                    xrealloc (range_types, (ndim + DW_FIELD_ALLOC_CHUNK)
-                              * sizeof (struct type *));
-                  if (ndim == 0)
-                    make_cleanup (free_current_contents, &range_types);
-               }
-             range_types[ndim++] = child_type;
+             range_types.push_back (child_type);
             }
        }
       child_die = sibling_die (child_die);
@@ -14102,12 +16367,13 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
     {
       int i = 0;
 
-      while (i < ndim)
+      while (i < range_types.size ())
        type = create_array_type_with_stride (NULL, type, range_types[i++],
                                              bit_stride);
     }
   else
     {
+      size_t ndim = range_types.size ();
       while (ndim-- > 0)
        type = create_array_type_with_stride (NULL, type, range_types[ndim],
                                              bit_stride);
@@ -14147,8 +16413,6 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
   /* set_die_type should be already done.  */
   set_descriptive_type (type, die, cu);
 
-  do_cleanups (back_to);
-
   return type;
 }
 
@@ -14446,9 +16710,10 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu)
        {
          const char *previous_prefix = determine_prefix (die, cu);
 
+         std::vector<const char *> excludes;
          add_using_directive (using_directives (cu->language),
                               previous_prefix, TYPE_NAME (type), NULL,
-                              NULL, NULL, 0, &objfile->objfile_obstack);
+                              NULL, excludes, 0, &objfile->objfile_obstack);
        }
     }
 
@@ -15044,7 +17309,7 @@ dwarf2_init_float_type (struct objfile *objfile, int bits, const char *name,
   if (format)
     type = init_float_type (objfile, bits, name, format);
   else
-    type = init_type (objfile, TYPE_CODE_ERROR, bits / TARGET_CHAR_BIT, name);
+    type = init_type (objfile, TYPE_CODE_ERROR, bits, name);
 
   return type;
 }
@@ -15082,7 +17347,7 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
     {
       case DW_ATE_address:
        /* Turn DW_ATE_address into a void * pointer.  */
-       type = init_type (objfile, TYPE_CODE_VOID, 1, NULL);
+       type = init_type (objfile, TYPE_CODE_VOID, TARGET_CHAR_BIT, NULL);
        type = init_pointer_type (objfile, bits, name, type);
        break;
       case DW_ATE_boolean:
@@ -15148,8 +17413,7 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
       default:
        complaint (&symfile_complaints, _("unsupported DW_AT_encoding: '%s'"),
                   dwarf_type_encoding_name (encoding));
-       type = init_type (objfile, TYPE_CODE_ERROR,
-                         bits / TARGET_CHAR_BIT, name);
+       type = init_type (objfile, TYPE_CODE_ERROR, bits, name);
        break;
     }
 
@@ -17556,7 +19820,9 @@ dwarf2_string_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *c
   if (attr != NULL)
     {
       if (attr->form == DW_FORM_strp || attr->form == DW_FORM_line_strp
-         || attr->form == DW_FORM_string || attr->form == DW_FORM_GNU_strp_alt)
+         || attr->form == DW_FORM_string
+         || attr->form == DW_FORM_GNU_str_index
+         || attr->form == DW_FORM_GNU_strp_alt)
        str = DW_STRING (attr);
       else
         complaint (&symfile_complaints,
@@ -17691,7 +19957,6 @@ read_formatted_entries (bfd *abfd, const gdb_byte **bufp,
   ULONGEST data_count, datai;
   const gdb_byte *buf = *bufp;
   const gdb_byte *format_header_data;
-  int i;
   unsigned int bytes_read;
 
   format_count = read_1_byte (abfd, buf);
@@ -18807,7 +21072,7 @@ dwarf2_start_symtab (struct dwarf2_cu *cu,
                     const char *name, const char *comp_dir, CORE_ADDR low_pc)
 {
   struct compunit_symtab *cust
-    = start_symtab (cu->objfile, name, comp_dir, low_pc);
+    = start_symtab (cu->objfile, name, comp_dir, low_pc, cu->language);
 
   record_debugformat ("DWARF 2");
   record_producer (cu->producer);
@@ -19026,8 +21291,7 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
             variables with missing type entries.  Change the
             misleading `void' type to something sensible.  */
          if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_VOID)
-           SYMBOL_TYPE (sym)
-             = objfile_type (objfile)->nodebug_data_symbol;
+           SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_int;
 
          attr = dwarf2_attr (die, DW_AT_const_value, cu);
          /* In the case of DW_TAG_member, we should only be called for
@@ -19409,6 +21673,7 @@ dwarf2_const_value_attr (const struct attribute *attr, struct type *type,
       break;
 
     case DW_FORM_sdata:
+    case DW_FORM_implicit_const:
       *value = DW_SND (attr);
       break;
 
@@ -19768,12 +22033,8 @@ guess_full_die_structure_name (struct die_info *die, struct dwarf2_cu *cu)
     {
       if (child->tag == DW_TAG_subprogram)
        {
-         const char *linkage_name;
+         const char *linkage_name = dw2_linkage_name (child, cu);
 
-         linkage_name = dwarf2_string_attr (child, DW_AT_linkage_name, cu);
-         if (linkage_name == NULL)
-           linkage_name = dwarf2_string_attr (child, DW_AT_MIPS_linkage_name,
-                                              cu);
          if (linkage_name != NULL)
            {
              char *actual_name
@@ -19828,9 +22089,7 @@ anonymous_struct_prefix (struct die_info *die, struct dwarf2_cu *cu)
   if (dwarf2_string_attr (die, DW_AT_name, cu) != NULL)
     return NULL;
 
-  attr = dwarf2_attr (die, DW_AT_linkage_name, cu);
-  if (attr == NULL)
-    attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu);
+  attr = dw2_linkage_name_attr (die, cu);
   if (attr == NULL || DW_STRING (attr) == NULL)
     return NULL;
 
@@ -20156,10 +22415,7 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu)
        {
          char *demangled = NULL;
 
-         attr = dwarf2_attr (die, DW_AT_linkage_name, cu);
-         if (attr == NULL)
-           attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu);
-
+         attr = dw2_linkage_name_attr (die, cu);
          if (attr == NULL || DW_STRING (attr) == NULL)
            return NULL;
 
@@ -20402,6 +22658,10 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
          fprintf_unfiltered (f, 
                              "unexpected attribute form: DW_FORM_indirect");
          break;
+       case DW_FORM_implicit_const:
+         fprintf_unfiltered (f, "constant: %s",
+                             plongest (DW_SND (&die->attrs[i])));
+         break;
        default:
          fprintf_unfiltered (f, "unsupported attribute form: %d.",
                   die->attrs[i].form);
@@ -20493,7 +22753,7 @@ dwarf2_get_ref_die_offset (const struct attribute *attr)
 static LONGEST
 dwarf2_get_attr_constant_value (const struct attribute *attr, int default_value)
 {
-  if (attr->form == DW_FORM_sdata)
+  if (attr->form == DW_FORM_sdata || attr->form == DW_FORM_implicit_const)
     return DW_SND (attr);
   else if (attr->form == DW_FORM_udata
            || attr->form == DW_FORM_data1
@@ -20828,6 +23088,7 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
       break;
 
     case DW_FORM_sdata:
+    case DW_FORM_implicit_const:
       type = die_type (die, cu);
       result = write_constant_as_bytes (obstack, byte_order,
                                        type, DW_SND (attr), len);
@@ -21520,20 +23781,6 @@ macro_start_file (int file, int line,
   return current_file;
 }
 
-
-/* Copy the LEN characters at BUF to a xmalloc'ed block of memory,
-   followed by a null byte.  */
-static char *
-copy_string (const char *buf, int len)
-{
-  char *s = (char *) xmalloc (len + 1);
-
-  memcpy (s, buf, len);
-  s[len] = '\0';
-  return s;
-}
-
-
 static const char *
 consume_improper_spaces (const char *p, const char *body)
 {
@@ -21593,7 +23840,7 @@ parse_macro_definition (struct macro_source_file *file, int line,
     {
       /* It's an object-like macro.  */
       int name_len = p - body;
-      char *name = copy_string (body, name_len);
+      char *name = savestring (body, name_len);
       const char *replacement;
 
       if (*p == ' ')
@@ -21611,7 +23858,7 @@ parse_macro_definition (struct macro_source_file *file, int line,
   else if (*p == '(')
     {
       /* It's a function-like macro.  */
-      char *name = copy_string (body, p - body);
+      char *name = savestring (body, p - body);
       int argc = 0;
       int argv_size = 1;
       char **argv = XNEWVEC (char *, argv_size);
@@ -21640,7 +23887,7 @@ parse_macro_definition (struct macro_source_file *file, int line,
                   argv = XRESIZEVEC (char *, argv, argv_size);
                 }
 
-              argv[argc++] = copy_string (arg_start, p - arg_start);
+              argv[argc++] = savestring (arg_start, p - arg_start);
             }
 
           p = consume_improper_spaces (p, body);
@@ -21764,9 +24011,11 @@ skip_form_bytes (bfd *abfd, const gdb_byte *bytes, const gdb_byte *buffer_end,
        }
       break;
 
+    case DW_FORM_implicit_const:
+      break;
+
     default:
       {
-      complain:
        complaint (&symfile_complaints,
                   _("invalid form 0x%x in `%s'"),
                   form, get_section_name (section));
@@ -21930,6 +24179,8 @@ dwarf_decode_macro_bytes (bfd *abfd,
 
       /* Note that we rely on the fact that the corresponding GNU and
         DWARF constants are the same.  */
+      DIAGNOSTIC_PUSH
+      DIAGNOSTIC_IGNORE_SWITCH_DIFFERENT_ENUM_TYPES
       switch (macinfo_type)
        {
          /* A zero macinfo type indicates the end of the macro
@@ -22154,6 +24405,7 @@ dwarf_decode_macro_bytes (bfd *abfd,
            return;
          break;
         }
+      DIAGNOSTIC_POP
     } while (macinfo_type != 0);
 }
 
@@ -22169,7 +24421,6 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
   enum dwarf_macro_record_type macinfo_type;
   unsigned int offset_size = cu->header.offset_size;
   const gdb_byte *opcode_definitions[256];
-  struct cleanup *cleanup;
   void **slot;
   struct dwarf2_section_info *section;
   const char *section_name;
@@ -22247,6 +24498,8 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
 
       /* Note that we rely on the fact that the corresponding GNU and
         DWARF constants are the same.  */
+      DIAGNOSTIC_PUSH
+      DIAGNOSTIC_IGNORE_SWITCH_DIFFERENT_ENUM_TYPES
       switch (macinfo_type)
         {
           /* A zero macinfo type indicates the end of the macro
@@ -22327,6 +24580,7 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
            return;
          break;
        }
+      DIAGNOSTIC_POP
     } while (macinfo_type != 0 && current_file == NULL);
 
   /* Second pass: Process all entries.
@@ -22405,6 +24659,7 @@ attr_form_is_constant (const struct attribute *attr)
     case DW_FORM_data2:
     case DW_FORM_data4:
     case DW_FORM_data8:
+    case DW_FORM_implicit_const:
       return 1;
     default:
       return 0;
@@ -22751,30 +25006,16 @@ free_stack_comp_unit (void *data)
   cu->per_cu->cu = NULL;
   cu->per_cu = NULL;
 
-  obstack_free (&cu->comp_unit_obstack, NULL);
-  cu->partial_dies = NULL;
-}
-
-/* Free all cached compilation units.  */
-
-static void
-free_cached_comp_units (void *data)
-{
-  struct dwarf2_per_cu_data *per_cu, **last_chain;
-
-  per_cu = dwarf2_per_objfile->read_in_chain;
-  last_chain = &dwarf2_per_objfile->read_in_chain;
-  while (per_cu != NULL)
-    {
-      struct dwarf2_per_cu_data *next_cu;
-
-      next_cu = per_cu->cu->read_in_chain;
+  obstack_free (&cu->comp_unit_obstack, NULL);
+  cu->partial_dies = NULL;
+}
 
-      free_heap_comp_unit (per_cu->cu);
-      *last_chain = next_cu;
+/* Free all cached compilation units.  */
 
-      per_cu = next_cu;
-    }
+static void
+free_cached_comp_units (void *data)
+{
+  dwarf2_per_objfile->free_cached_comp_units ();
 }
 
 /* Increase the age counter on each cached compilation unit, and free
@@ -22856,16 +25097,7 @@ dwarf2_free_objfile (struct objfile *objfile)
   if (dwarf2_per_objfile == NULL)
     return;
 
-  /* Cached DIE trees use xmalloc and the comp_unit_obstack.  */
-  free_cached_comp_units (NULL);
-
-  if (dwarf2_per_objfile->quick_file_names_table)
-    htab_delete (dwarf2_per_objfile->quick_file_names_table);
-
-  if (dwarf2_per_objfile->line_header_hash)
-    htab_delete (dwarf2_per_objfile->line_header_hash);
-
-  /* Everything else should be on the objfile obstack.  */
+  dwarf2_per_objfile->~dwarf2_per_objfile ();
 }
 
 /* A set of CU "per_cu" pointer, DIE offset, and GDB type pointer.
@@ -23149,14 +25381,14 @@ static struct cmd_list_element *set_dwarf_cmdlist;
 static struct cmd_list_element *show_dwarf_cmdlist;
 
 static void
-set_dwarf_cmd (char *args, int from_tty)
+set_dwarf_cmd (const char *args, int from_tty)
 {
   help_list (set_dwarf_cmdlist, "maintenance set dwarf ", all_commands,
             gdb_stdout);
 }
 
 static void
-show_dwarf_cmd (char *args, int from_tty)
+show_dwarf_cmd (const char *args, int from_tty)
 {
   cmd_show_list (show_dwarf_cmdlist, from_tty, "");
 }
@@ -23190,6 +25422,9 @@ dwarf2_per_objfile_free (struct objfile *objfile, void *d)
 
   if (data->dwz_file && data->dwz_file->dwz_bfd)
     gdb_bfd_unref (data->dwz_file->dwz_bfd);
+
+  if (data->index_table != NULL)
+    data->index_table->~mapped_index ();
 }
 
 \f
@@ -23207,40 +25442,54 @@ file_write (FILE *file, const void *data, size_t size)
 
 /* Write the contents of VEC to FILE, with error checking.  */
 
-template<class Elem>
+template<typename Elem, typename Alloc>
 static void
-file_write (FILE *file, const std::vector<Elem> &vec)
+file_write (FILE *file, const std::vector<Elem, Alloc> &vec)
 {
-  file_write (file, vec.data (), vec.size() * sizeof (vec[0]));
+  file_write (file, vec.data (), vec.size () * sizeof (vec[0]));
 }
 
 /* In-memory buffer to prepare data to be written later to a file.  */
 class data_buf
 {
 public:
-  /* Add SIZE bytes at the end of the buffer.  Returns a pointer to
-     the start of the new block.  */
-  gdb_byte *append_space (size_t size)
-  {
-    m_vec.resize (m_vec.size () + size);
-    return &*m_vec.end () - size;
-  }
-
   /* Copy DATA to the end of the buffer.  */
   template<typename T>
   void append_data (const T &data)
   {
     std::copy (reinterpret_cast<const gdb_byte *> (&data),
               reinterpret_cast<const gdb_byte *> (&data + 1),
-              append_space (sizeof (data)));
+              grow (sizeof (data)));
   }
 
-  /* Copy CSTR (a null-terminated string) to the end of the buffer.
-     The terminating null is appended too.  */
+  /* Copy CSTR (a zero-terminated string) to the end of buffer.  The
+     terminating zero is appended too.  */
   void append_cstr0 (const char *cstr)
   {
     const size_t size = strlen (cstr) + 1;
-    std::copy (cstr, cstr + size, append_space (size));
+    std::copy (cstr, cstr + size, grow (size));
+  }
+
+  /* Store INPUT as ULEB128 to the end of buffer.  */
+  void append_unsigned_leb128 (ULONGEST input)
+  {
+    for (;;)
+      {
+       gdb_byte output = input & 0x7f;
+       input >>= 7;
+       if (input)
+         output |= 0x80;
+       append_data (output);
+       if (input == 0)
+         break;
+      }
+  }
+
+  /* Accept a host-format integer in VAL and append it to the buffer
+     as a target-format integer which is LEN bytes long.  */
+  void append_uint (size_t len, bfd_endian byte_order, ULONGEST val)
+  {
+    ::store_unsigned_integer (grow (len), len, byte_order, val);
   }
 
   /* Return the size of the buffer.  */
@@ -23249,6 +25498,12 @@ public:
     return m_vec.size ();
   }
 
+  /* Return true iff the buffer is empty.  */
+  bool empty () const
+  {
+    return m_vec.empty ();
+  }
+
   /* Write the buffer to FILE.  */
   void file_write (FILE *file) const
   {
@@ -23256,7 +25511,15 @@ public:
   }
 
 private:
-  std::vector<gdb_byte> m_vec;
+  /* Grow SIZE bytes at the end of the buffer.  Returns a pointer to
+     the start of the new block.  */
+  gdb_byte *grow (size_t size)
+  {
+    m_vec.resize (m_vec.size () + size);
+    return &*m_vec.end () - size;
+  }
+
+  gdb::byte_vector m_vec;
 };
 
 /* An entry in the symbol table.  */
@@ -23280,7 +25543,7 @@ struct mapped_symtab
   }
 
   offset_type n_elements = 0;
-  std::vector<std::unique_ptr<symtab_index_entry>> data;
+  std::vector<symtab_index_entry> data;
 };
 
 /* Find a slot in SYMTAB for the symbol NAME.  Returns a reference to
@@ -23289,7 +25552,7 @@ struct mapped_symtab
    Function is used only during write_hash_table so no index format backward
    compatibility is needed.  */
 
-static std::unique_ptr<symtab_index_entry> &
+static symtab_index_entry &
 find_slot (struct mapped_symtab *symtab, const char *name)
 {
   offset_type index, step, hash = mapped_index_string_hash (INT_MAX, name);
@@ -23299,7 +25562,8 @@ find_slot (struct mapped_symtab *symtab, const char *name)
 
   for (;;)
     {
-      if (!symtab->data[index] || !strcmp (name, symtab->data[index]->name))
+      if (symtab->data[index].name == NULL
+         || strcmp (name, symtab->data[index].name) == 0)
        return symtab->data[index];
       index = (index + step) & (symtab->data.size () - 1);
     }
@@ -23316,9 +25580,9 @@ hash_expand (struct mapped_symtab *symtab)
   symtab->data.resize (old_entries.size () * 2);
 
   for (auto &it : old_entries)
-    if (it != NULL)
+    if (it.name != NULL)
       {
-       auto &ref = find_slot (symtab, it->name);
+       auto &ref = find_slot (symtab, it.name);
        ref = std::move (it);
       }
 }
@@ -23338,11 +25602,10 @@ add_index_entry (struct mapped_symtab *symtab, const char *name,
   if (4 * symtab->n_elements / 3 >= symtab->data.size ())
     hash_expand (symtab);
 
-  std::unique_ptr<symtab_index_entry> &slot = find_slot (symtab, name);
-  if (slot == NULL)
+  symtab_index_entry &slot = find_slot (symtab, name);
+  if (slot.name == NULL)
     {
-      slot.reset (new symtab_index_entry ());
-      slot->name = name;
+      slot.name = name;
       /* index_offset is set later.  */
     }
 
@@ -23358,7 +25621,7 @@ add_index_entry (struct mapped_symtab *symtab, const char *name,
      the last entry pushed), but a symbol could have multiple kinds in one CU.
      To keep things simple we don't worry about the duplication here and
      sort and uniqufy the list after we've processed all symbols.  */
-  slot->cu_indices.push_back (cu_index_and_attrs);
+  slot.cu_indices.push_back (cu_index_and_attrs);
 }
 
 /* Sort and remove duplicates of all symbols' cu_indices lists.  */
@@ -23366,11 +25629,11 @@ add_index_entry (struct mapped_symtab *symtab, const char *name,
 static void
 uniquify_cu_indices (struct mapped_symtab *symtab)
 {
-  for (const auto &entry : symtab->data)
+  for (auto &entry : symtab->data)
     {
-      if (entry && !entry->cu_indices.empty ())
+      if (entry.name != NULL && !entry.cu_indices.empty ())
        {
-         auto &cu_indices = entry->cu_indices;
+         auto &cu_indices = entry.cu_indices;
          std::sort (cu_indices.begin (), cu_indices.end ());
          auto from = std::unique (cu_indices.begin (), cu_indices.end ());
          cu_indices.erase (from, cu_indices.end ());
@@ -23393,6 +25656,13 @@ public:
     return strcmp (m_cstr, other.m_cstr) == 0;
   }
 
+  /* Return the underlying C string.  Note, the returned string is
+     only a reference with lifetime of this object.  */
+  const char *c_str () const
+  {
+    return m_cstr;
+  }
+
 private:
   friend class c_str_view_hasher;
   const char *const m_cstr;
@@ -23436,35 +25706,46 @@ write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool)
 
     /* We add all the index vectors to the constant pool first, to
        ensure alignment is ok.  */
-    for (const std::unique_ptr<symtab_index_entry> &it : symtab->data)
+    for (symtab_index_entry &entry : symtab->data)
       {
-       if (it == NULL)
-         continue;
-       gdb_assert (it->index_offset == 0);
-       const auto insertpair
-         = symbol_hash_table.emplace (it->cu_indices, cpool.size ());
-       it->index_offset = insertpair.first->second;
-       if (!insertpair.second)
+       if (entry.name == NULL)
          continue;
-       cpool.append_data (MAYBE_SWAP (it->cu_indices.size ()));
-       for (const auto iter : it->cu_indices)
-         cpool.append_data (MAYBE_SWAP (iter));
+       gdb_assert (entry.index_offset == 0);
+
+       /* Finding before inserting is faster than always trying to
+          insert, because inserting always allocates a node, does the
+          lookup, and then destroys the new node if another node
+          already had the same key.  C++17 try_emplace will avoid
+          this.  */
+       const auto found
+         = symbol_hash_table.find (entry.cu_indices);
+       if (found != symbol_hash_table.end ())
+         {
+           entry.index_offset = found->second;
+           continue;
+         }
+
+       symbol_hash_table.emplace (entry.cu_indices, cpool.size ());
+       entry.index_offset = cpool.size ();
+       cpool.append_data (MAYBE_SWAP (entry.cu_indices.size ()));
+       for (const auto index : entry.cu_indices)
+         cpool.append_data (MAYBE_SWAP (index));
       }
   }
 
   /* Now write out the hash table.  */
   std::unordered_map<c_str_view, offset_type, c_str_view_hasher> str_table;
-  for (const auto &it : symtab->data)
+  for (const auto &entry : symtab->data)
     {
       offset_type str_off, vec_off;
 
-      if (it != NULL)
+      if (entry.name != NULL)
        {
-         const auto insertpair = str_table.emplace (it->name, cpool.size ());
+         const auto insertpair = str_table.emplace (entry.name, cpool.size ());
          if (insertpair.second)
-           cpool.append_cstr0 (it->name);
+           cpool.append_cstr0 (entry.name);
          str_off = insertpair.first->second;
-         vec_off = it->index_offset;
+         vec_off = entry.index_offset;
        }
       else
        {
@@ -23512,10 +25793,8 @@ add_address_entry (struct objfile *objfile, data_buf &addr_vec,
 
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
-  store_unsigned_integer (addr_vec.append_space (8), 8, BFD_ENDIAN_LITTLE,
-                         start - baseaddr);
-  store_unsigned_integer (addr_vec.append_space (8), 8, BFD_ENDIAN_LITTLE,
-                         end - baseaddr);
+  addr_vec.append_uint (8, BFD_ENDIAN_LITTLE, start - baseaddr);
+  addr_vec.append_uint (8, BFD_ENDIAN_LITTLE, end - baseaddr);
   addr_vec.append_data (MAYBE_SWAP (cu_index));
 }
 
@@ -23613,163 +25892,773 @@ symbol_kind (struct partial_symbol *psym)
     default:
       return GDB_INDEX_SYMBOL_KIND_OTHER;
     }
-}
+}
+
+/* Add a list of partial symbols to SYMTAB.  */
+
+static void
+write_psymbols (struct mapped_symtab *symtab,
+               std::unordered_set<partial_symbol *> &psyms_seen,
+               struct partial_symbol **psymp,
+               int count,
+               offset_type cu_index,
+               int is_static)
+{
+  for (; count-- > 0; ++psymp)
+    {
+      struct partial_symbol *psym = *psymp;
+
+      if (SYMBOL_LANGUAGE (psym) == language_ada)
+       error (_("Ada is not currently supported by the index"));
+
+      /* Only add a given psymbol once.  */
+      if (psyms_seen.insert (psym).second)
+       {
+         gdb_index_symbol_kind kind = symbol_kind (psym);
+
+         add_index_entry (symtab, SYMBOL_SEARCH_NAME (psym),
+                          is_static, kind, cu_index);
+       }
+    }
+}
+
+/* A helper struct used when iterating over debug_types.  */
+struct signatured_type_index_data
+{
+  signatured_type_index_data (data_buf &types_list_,
+                              std::unordered_set<partial_symbol *> &psyms_seen_)
+    : types_list (types_list_), psyms_seen (psyms_seen_)
+  {}
+
+  struct objfile *objfile;
+  struct mapped_symtab *symtab;
+  data_buf &types_list;
+  std::unordered_set<partial_symbol *> &psyms_seen;
+  int cu_index;
+};
+
+/* A helper function that writes a single signatured_type to an
+   obstack.  */
+
+static int
+write_one_signatured_type (void **slot, void *d)
+{
+  struct signatured_type_index_data *info
+    = (struct signatured_type_index_data *) d;
+  struct signatured_type *entry = (struct signatured_type *) *slot;
+  struct partial_symtab *psymtab = entry->per_cu.v.psymtab;
+
+  write_psymbols (info->symtab,
+                 info->psyms_seen,
+                 &info->objfile->global_psymbols[psymtab->globals_offset],
+                 psymtab->n_global_syms, info->cu_index,
+                 0);
+  write_psymbols (info->symtab,
+                 info->psyms_seen,
+                 &info->objfile->static_psymbols[psymtab->statics_offset],
+                 psymtab->n_static_syms, info->cu_index,
+                 1);
+
+  info->types_list.append_uint (8, BFD_ENDIAN_LITTLE,
+                               to_underlying (entry->per_cu.sect_off));
+  info->types_list.append_uint (8, BFD_ENDIAN_LITTLE,
+                               to_underlying (entry->type_offset_in_tu));
+  info->types_list.append_uint (8, BFD_ENDIAN_LITTLE, entry->signature);
+
+  ++info->cu_index;
+
+  return 1;
+}
+
+/* Recurse into all "included" dependencies and count their symbols as
+   if they appeared in this psymtab.  */
+
+static void
+recursively_count_psymbols (struct partial_symtab *psymtab,
+                           size_t &psyms_seen)
+{
+  for (int i = 0; i < psymtab->number_of_dependencies; ++i)
+    if (psymtab->dependencies[i]->user != NULL)
+      recursively_count_psymbols (psymtab->dependencies[i],
+                                 psyms_seen);
+
+  psyms_seen += psymtab->n_global_syms;
+  psyms_seen += psymtab->n_static_syms;
+}
+
+/* Recurse into all "included" dependencies and write their symbols as
+   if they appeared in this psymtab.  */
+
+static void
+recursively_write_psymbols (struct objfile *objfile,
+                           struct partial_symtab *psymtab,
+                           struct mapped_symtab *symtab,
+                           std::unordered_set<partial_symbol *> &psyms_seen,
+                           offset_type cu_index)
+{
+  int i;
+
+  for (i = 0; i < psymtab->number_of_dependencies; ++i)
+    if (psymtab->dependencies[i]->user != NULL)
+      recursively_write_psymbols (objfile, psymtab->dependencies[i],
+                                 symtab, psyms_seen, cu_index);
+
+  write_psymbols (symtab,
+                 psyms_seen,
+                 &objfile->global_psymbols[psymtab->globals_offset],
+                 psymtab->n_global_syms, cu_index,
+                 0);
+  write_psymbols (symtab,
+                 psyms_seen,
+                 &objfile->static_psymbols[psymtab->statics_offset],
+                 psymtab->n_static_syms, cu_index,
+                 1);
+}
+
+/* DWARF-5 .debug_names builder.  */
+class debug_names
+{
+public:
+  debug_names (bool is_dwarf64, bfd_endian dwarf5_byte_order)
+    : m_dwarf5_byte_order (dwarf5_byte_order),
+      m_dwarf32 (dwarf5_byte_order),
+      m_dwarf64 (dwarf5_byte_order),
+      m_dwarf (is_dwarf64
+              ? static_cast<dwarf &> (m_dwarf64)
+              : static_cast<dwarf &> (m_dwarf32)),
+      m_name_table_string_offs (m_dwarf.name_table_string_offs),
+      m_name_table_entry_offs (m_dwarf.name_table_entry_offs)
+  {}
+
+  int dwarf5_offset_size () const
+  {
+    const bool dwarf5_is_dwarf64 = &m_dwarf == &m_dwarf64;
+    return dwarf5_is_dwarf64 ? 8 : 4;
+  }
+
+  /* Is this symbol from DW_TAG_compile_unit or DW_TAG_type_unit?  */
+  enum class unit_kind { cu, tu };
+
+  /* Insert one symbol.  */
+  void insert (const partial_symbol *psym, int cu_index, bool is_static,
+              unit_kind kind)
+  {
+    const int dwarf_tag = psymbol_tag (psym);
+    if (dwarf_tag == 0)
+      return;
+    const char *const name = SYMBOL_SEARCH_NAME (psym);
+    const auto insertpair
+      = m_name_to_value_set.emplace (c_str_view (name),
+                                    std::set<symbol_value> ());
+    std::set<symbol_value> &value_set = insertpair.first->second;
+    value_set.emplace (symbol_value (dwarf_tag, cu_index, is_static, kind));
+  }
+
+  /* Build all the tables.  All symbols must be already inserted.
+     This function does not call file_write, caller has to do it
+     afterwards.  */
+  void build ()
+  {
+    /* Verify the build method has not be called twice.  */
+    gdb_assert (m_abbrev_table.empty ());
+    const size_t name_count = m_name_to_value_set.size ();
+    m_bucket_table.resize
+      (std::pow (2, std::ceil (std::log2 (name_count * 4 / 3))));
+    m_hash_table.reserve (name_count);
+    m_name_table_string_offs.reserve (name_count);
+    m_name_table_entry_offs.reserve (name_count);
+
+    /* Map each hash of symbol to its name and value.  */
+    struct hash_it_pair
+    {
+      uint32_t hash;
+      decltype (m_name_to_value_set)::const_iterator it;
+    };
+    std::vector<std::forward_list<hash_it_pair>> bucket_hash;
+    bucket_hash.resize (m_bucket_table.size ());
+    for (decltype (m_name_to_value_set)::const_iterator it
+          = m_name_to_value_set.cbegin ();
+        it != m_name_to_value_set.cend ();
+        ++it)
+      {
+       const char *const name = it->first.c_str ();
+       const uint32_t hash = dwarf5_djb_hash (name);
+       hash_it_pair hashitpair;
+       hashitpair.hash = hash;
+       hashitpair.it = it;
+       auto &slot = bucket_hash[hash % bucket_hash.size()];
+       slot.push_front (std::move (hashitpair));
+      }
+    for (size_t bucket_ix = 0; bucket_ix < bucket_hash.size (); ++bucket_ix)
+      {
+       const std::forward_list<hash_it_pair> &hashitlist
+         = bucket_hash[bucket_ix];
+       if (hashitlist.empty ())
+         continue;
+       uint32_t &bucket_slot = m_bucket_table[bucket_ix];
+       /* The hashes array is indexed starting at 1.  */
+       store_unsigned_integer (reinterpret_cast<gdb_byte *> (&bucket_slot),
+                               sizeof (bucket_slot), m_dwarf5_byte_order,
+                               m_hash_table.size () + 1);
+       for (const hash_it_pair &hashitpair : hashitlist)
+         {
+           m_hash_table.push_back (0);
+           store_unsigned_integer (reinterpret_cast<gdb_byte *>
+                                                       (&m_hash_table.back ()),
+                                   sizeof (m_hash_table.back ()),
+                                   m_dwarf5_byte_order, hashitpair.hash);
+           const c_str_view &name = hashitpair.it->first;
+           const std::set<symbol_value> &value_set = hashitpair.it->second;
+           m_name_table_string_offs.push_back_reorder
+             (m_debugstrlookup.lookup (name.c_str ()));
+           m_name_table_entry_offs.push_back_reorder (m_entry_pool.size ());
+           gdb_assert (!value_set.empty ());
+           for (const symbol_value &value : value_set)
+             {
+               int &idx = m_indexkey_to_idx[index_key (value.dwarf_tag,
+                                                       value.is_static,
+                                                       value.kind)];
+               if (idx == 0)
+                 {
+                   idx = m_idx_next++;
+                   m_abbrev_table.append_unsigned_leb128 (idx);
+                   m_abbrev_table.append_unsigned_leb128 (value.dwarf_tag);
+                   m_abbrev_table.append_unsigned_leb128
+                             (value.kind == unit_kind::cu ? DW_IDX_compile_unit
+                                                          : DW_IDX_type_unit);
+                   m_abbrev_table.append_unsigned_leb128 (DW_FORM_udata);
+                   m_abbrev_table.append_unsigned_leb128 (value.is_static
+                                                          ? DW_IDX_GNU_internal
+                                                          : DW_IDX_GNU_external);
+                   m_abbrev_table.append_unsigned_leb128 (DW_FORM_flag_present);
+
+                   /* Terminate attributes list.  */
+                   m_abbrev_table.append_unsigned_leb128 (0);
+                   m_abbrev_table.append_unsigned_leb128 (0);
+                 }
+
+               m_entry_pool.append_unsigned_leb128 (idx);
+               m_entry_pool.append_unsigned_leb128 (value.cu_index);
+             }
+
+           /* Terminate the list of CUs.  */
+           m_entry_pool.append_unsigned_leb128 (0);
+         }
+      }
+    gdb_assert (m_hash_table.size () == name_count);
+
+    /* Terminate tags list.  */
+    m_abbrev_table.append_unsigned_leb128 (0);
+  }
+
+  /* Return .debug_names bucket count.  This must be called only after
+     calling the build method.  */
+  uint32_t bucket_count () const
+  {
+    /* Verify the build method has been already called.  */
+    gdb_assert (!m_abbrev_table.empty ());
+    const uint32_t retval = m_bucket_table.size ();
+
+    /* Check for overflow.  */
+    gdb_assert (retval == m_bucket_table.size ());
+    return retval;
+  }
+
+  /* Return .debug_names names count.  This must be called only after
+     calling the build method.  */
+  uint32_t name_count () const
+  {
+    /* Verify the build method has been already called.  */
+    gdb_assert (!m_abbrev_table.empty ());
+    const uint32_t retval = m_hash_table.size ();
+
+    /* Check for overflow.  */
+    gdb_assert (retval == m_hash_table.size ());
+    return retval;
+  }
+
+  /* Return number of bytes of .debug_names abbreviation table.  This
+     must be called only after calling the build method.  */
+  uint32_t abbrev_table_bytes () const
+  {
+    gdb_assert (!m_abbrev_table.empty ());
+    return m_abbrev_table.size ();
+  }
+
+  /* Recurse into all "included" dependencies and store their symbols
+     as if they appeared in this psymtab.  */
+  void recursively_write_psymbols
+    (struct objfile *objfile,
+     struct partial_symtab *psymtab,
+     std::unordered_set<partial_symbol *> &psyms_seen,
+     int cu_index)
+  {
+    for (int i = 0; i < psymtab->number_of_dependencies; ++i)
+      if (psymtab->dependencies[i]->user != NULL)
+       recursively_write_psymbols (objfile, psymtab->dependencies[i],
+                                   psyms_seen, cu_index);
+
+    write_psymbols (psyms_seen,
+                   &objfile->global_psymbols[psymtab->globals_offset],
+                   psymtab->n_global_syms, cu_index, false, unit_kind::cu);
+    write_psymbols (psyms_seen,
+                   &objfile->static_psymbols[psymtab->statics_offset],
+                   psymtab->n_static_syms, cu_index, true, unit_kind::cu);
+  }
+
+  /* Return number of bytes the .debug_names section will have.  This
+     must be called only after calling the build method.  */
+  size_t bytes () const
+  {
+    /* Verify the build method has been already called.  */
+    gdb_assert (!m_abbrev_table.empty ());
+    size_t expected_bytes = 0;
+    expected_bytes += m_bucket_table.size () * sizeof (m_bucket_table[0]);
+    expected_bytes += m_hash_table.size () * sizeof (m_hash_table[0]);
+    expected_bytes += m_name_table_string_offs.bytes ();
+    expected_bytes += m_name_table_entry_offs.bytes ();
+    expected_bytes += m_abbrev_table.size ();
+    expected_bytes += m_entry_pool.size ();
+    return expected_bytes;
+  }
+
+  /* Write .debug_names to FILE_NAMES and .debug_str addition to
+     FILE_STR.  This must be called only after calling the build
+     method.  */
+  void file_write (FILE *file_names, FILE *file_str) const
+  {
+    /* Verify the build method has been already called.  */
+    gdb_assert (!m_abbrev_table.empty ());
+    ::file_write (file_names, m_bucket_table);
+    ::file_write (file_names, m_hash_table);
+    m_name_table_string_offs.file_write (file_names);
+    m_name_table_entry_offs.file_write (file_names);
+    m_abbrev_table.file_write (file_names);
+    m_entry_pool.file_write (file_names);
+    m_debugstrlookup.file_write (file_str);
+  }
+
+  /* A helper user data for write_one_signatured_type.  */
+  class write_one_signatured_type_data
+  {
+  public:
+    write_one_signatured_type_data (debug_names &nametable_,
+                                    signatured_type_index_data &&info_)
+    : nametable (nametable_), info (std::move (info_))
+    {}
+    debug_names &nametable;
+    struct signatured_type_index_data info;
+  };
+
+  /* A helper function to pass write_one_signatured_type to
+     htab_traverse_noresize.  */
+  static int
+  write_one_signatured_type (void **slot, void *d)
+  {
+    write_one_signatured_type_data *data = (write_one_signatured_type_data *) d;
+    struct signatured_type_index_data *info = &data->info;
+    struct signatured_type *entry = (struct signatured_type *) *slot;
+
+    data->nametable.write_one_signatured_type (entry, info);
+
+    return 1;
+  }
+
+private:
+
+  /* Storage for symbol names mapping them to their .debug_str section
+     offsets.  */
+  class debug_str_lookup
+  {
+  public:
+
+    /* Object costructor to be called for current DWARF2_PER_OBJFILE.
+       All .debug_str section strings are automatically stored.  */
+    debug_str_lookup ()
+      : m_abfd (dwarf2_per_objfile->objfile->obfd)
+    {
+      dwarf2_read_section (dwarf2_per_objfile->objfile,
+                          &dwarf2_per_objfile->str);
+      if (dwarf2_per_objfile->str.buffer == NULL)
+       return;
+      for (const gdb_byte *data = dwarf2_per_objfile->str.buffer;
+          data < (dwarf2_per_objfile->str.buffer
+                  + dwarf2_per_objfile->str.size);)
+       {
+         const char *const s = reinterpret_cast<const char *> (data);
+         const auto insertpair
+           = m_str_table.emplace (c_str_view (s),
+                                  data - dwarf2_per_objfile->str.buffer);
+         if (!insertpair.second)
+           complaint (&symfile_complaints,
+                      _("Duplicate string \"%s\" in "
+                        ".debug_str section [in module %s]"),
+                      s, bfd_get_filename (m_abfd));
+         data += strlen (s) + 1;
+       }
+    }
+
+    /* Return offset of symbol name S in the .debug_str section.  Add
+       such symbol to the section's end if it does not exist there
+       yet.  */
+    size_t lookup (const char *s)
+    {
+      const auto it = m_str_table.find (c_str_view (s));
+      if (it != m_str_table.end ())
+       return it->second;
+      const size_t offset = (dwarf2_per_objfile->str.size
+                            + m_str_add_buf.size ());
+      m_str_table.emplace (c_str_view (s), offset);
+      m_str_add_buf.append_cstr0 (s);
+      return offset;
+    }
+
+    /* Append the end of the .debug_str section to FILE.  */
+    void file_write (FILE *file) const
+    {
+      m_str_add_buf.file_write (file);
+    }
+
+  private:
+    std::unordered_map<c_str_view, size_t, c_str_view_hasher> m_str_table;
+    bfd *const m_abfd;
+
+    /* Data to add at the end of .debug_str for new needed symbol names.  */
+    data_buf m_str_add_buf;
+  };
+
+  /* Container to map used DWARF tags to their .debug_names abbreviation
+     tags.  */
+  class index_key
+  {
+  public:
+    index_key (int dwarf_tag_, bool is_static_, unit_kind kind_)
+      : dwarf_tag (dwarf_tag_), is_static (is_static_), kind (kind_)
+    {
+    }
+
+    bool
+    operator== (const index_key &other) const
+    {
+      return (dwarf_tag == other.dwarf_tag && is_static == other.is_static
+             && kind == other.kind);
+    }
+
+    const int dwarf_tag;
+    const bool is_static;
+    const unit_kind kind;
+  };
+
+  /* Provide std::unordered_map::hasher for index_key.  */
+  class index_key_hasher
+  {
+  public:
+    size_t
+    operator () (const index_key &key) const
+    {
+      return (std::hash<int>() (key.dwarf_tag) << 1) | key.is_static;
+    }
+  };
+
+  /* Parameters of one symbol entry.  */
+  class symbol_value
+  {
+  public:
+    const int dwarf_tag, cu_index;
+    const bool is_static;
+    const unit_kind kind;
+
+    symbol_value (int dwarf_tag_, int cu_index_, bool is_static_,
+                 unit_kind kind_)
+      : dwarf_tag (dwarf_tag_), cu_index (cu_index_), is_static (is_static_),
+        kind (kind_)
+    {}
+
+    bool
+    operator< (const symbol_value &other) const
+    {
+#define X(n) \
+  do \
+    { \
+      if (n < other.n) \
+       return true; \
+      if (n > other.n) \
+       return false; \
+    } \
+  while (0)
+      X (dwarf_tag);
+      X (is_static);
+      X (kind);
+      X (cu_index);
+#undef X
+      return false;
+    }
+  };
 
-/* Add a list of partial symbols to SYMTAB.  */
+  /* Abstract base class to unify DWARF-32 and DWARF-64 name table
+     output.  */
+  class offset_vec
+  {
+  protected:
+    const bfd_endian dwarf5_byte_order;
+  public:
+    explicit offset_vec (bfd_endian dwarf5_byte_order_)
+      : dwarf5_byte_order (dwarf5_byte_order_)
+    {}
 
-static void
-write_psymbols (struct mapped_symtab *symtab,
-               std::unordered_set<partial_symbol *> &psyms_seen,
-               struct partial_symbol **psymp,
-               int count,
-               offset_type cu_index,
-               int is_static)
-{
-  for (; count-- > 0; ++psymp)
+    /* Call std::vector::reserve for NELEM elements.  */
+    virtual void reserve (size_t nelem) = 0;
+
+    /* Call std::vector::push_back with store_unsigned_integer byte
+       reordering for ELEM.  */
+    virtual void push_back_reorder (size_t elem) = 0;
+
+    /* Return expected output size in bytes.  */
+    virtual size_t bytes () const = 0;
+
+    /* Write name table to FILE.  */
+    virtual void file_write (FILE *file) const = 0;
+  };
+
+  /* Template to unify DWARF-32 and DWARF-64 output.  */
+  template<typename OffsetSize>
+  class offset_vec_tmpl : public offset_vec
+  {
+  public:
+    explicit offset_vec_tmpl (bfd_endian dwarf5_byte_order_)
+      : offset_vec (dwarf5_byte_order_)
+    {}
+
+    /* Implement offset_vec::reserve.  */
+    void reserve (size_t nelem) override
     {
-      struct partial_symbol *psym = *psymp;
+      m_vec.reserve (nelem);
+    }
 
-      if (SYMBOL_LANGUAGE (psym) == language_ada)
-       error (_("Ada is not currently supported by the index"));
+    /* Implement offset_vec::push_back_reorder.  */
+    void push_back_reorder (size_t elem) override
+    {
+      m_vec.push_back (elem);
+      /* Check for overflow.  */
+      gdb_assert (m_vec.back () == elem);
+      store_unsigned_integer (reinterpret_cast<gdb_byte *> (&m_vec.back ()),
+                             sizeof (m_vec.back ()), dwarf5_byte_order, elem);
+    }
 
-      /* Only add a given psymbol once.  */
-      if (psyms_seen.insert (psym).second)
-       {
-         gdb_index_symbol_kind kind = symbol_kind (psym);
+    /* Implement offset_vec::bytes.  */
+    size_t bytes () const override
+    {
+      return m_vec.size () * sizeof (m_vec[0]);
+    }
 
-         add_index_entry (symtab, SYMBOL_SEARCH_NAME (psym),
-                          is_static, kind, cu_index);
-       }
+    /* Implement offset_vec::file_write.  */
+    void file_write (FILE *file) const override
+    {
+      ::file_write (file, m_vec);
     }
-}
 
-/* A helper struct used when iterating over debug_types.  */
-struct signatured_type_index_data
-{
-  signatured_type_index_data (data_buf &types_list_,
-                              std::unordered_set<partial_symbol *> &psyms_seen_)
-    : types_list (types_list_), psyms_seen (psyms_seen_)
-  {}
+  private:
+    std::vector<OffsetSize> m_vec;
+  };
 
-  struct objfile *objfile;
-  struct mapped_symtab *symtab;
-  data_buf &types_list;
-  std::unordered_set<partial_symbol *> &psyms_seen;
-  int cu_index;
-};
+  /* Base class to unify DWARF-32 and DWARF-64 .debug_names output
+     respecting name table width.  */
+  class dwarf
+  {
+  public:
+    offset_vec &name_table_string_offs, &name_table_entry_offs;
 
-/* A helper function that writes a single signatured_type to an
-   obstack.  */
+    dwarf (offset_vec &name_table_string_offs_,
+          offset_vec &name_table_entry_offs_)
+      : name_table_string_offs (name_table_string_offs_),
+       name_table_entry_offs (name_table_entry_offs_)
+    {
+    }
+  };
 
-static int
-write_one_signatured_type (void **slot, void *d)
-{
-  struct signatured_type_index_data *info
-    = (struct signatured_type_index_data *) d;
-  struct signatured_type *entry = (struct signatured_type *) *slot;
-  struct partial_symtab *psymtab = entry->per_cu.v.psymtab;
+  /* Template to unify DWARF-32 and DWARF-64 .debug_names output
+     respecting name table width.  */
+  template<typename OffsetSize>
+  class dwarf_tmpl : public dwarf
+  {
+  public:
+    explicit dwarf_tmpl (bfd_endian dwarf5_byte_order_)
+      : dwarf (m_name_table_string_offs, m_name_table_entry_offs),
+       m_name_table_string_offs (dwarf5_byte_order_),
+       m_name_table_entry_offs (dwarf5_byte_order_)
+    {}
+
+  private:
+    offset_vec_tmpl<OffsetSize> m_name_table_string_offs;
+    offset_vec_tmpl<OffsetSize> m_name_table_entry_offs;
+  };
 
-  write_psymbols (info->symtab,
-                 info->psyms_seen,
-                 info->objfile->global_psymbols.list
-                 + psymtab->globals_offset,
-                 psymtab->n_global_syms, info->cu_index,
-                 0);
-  write_psymbols (info->symtab,
-                 info->psyms_seen,
-                 info->objfile->static_psymbols.list
-                 + psymtab->statics_offset,
-                 psymtab->n_static_syms, info->cu_index,
-                 1);
+  /* Try to reconstruct original DWARF tag for given partial_symbol.
+     This function is not DWARF-5 compliant but it is sufficient for
+     GDB as a DWARF-5 index consumer.  */
+  static int psymbol_tag (const struct partial_symbol *psym)
+  {
+    domain_enum domain = PSYMBOL_DOMAIN (psym);
+    enum address_class aclass = PSYMBOL_CLASS (psym);
 
-  store_unsigned_integer (info->types_list.append_space (8), 8,
-                         BFD_ENDIAN_LITTLE,
-                         to_underlying (entry->per_cu.sect_off));
-  store_unsigned_integer (info->types_list.append_space (8), 8,
-                         BFD_ENDIAN_LITTLE,
-                         to_underlying (entry->type_offset_in_tu));
-  store_unsigned_integer (info->types_list.append_space (8), 8,
-                         BFD_ENDIAN_LITTLE, entry->signature);
+    switch (domain)
+      {
+      case VAR_DOMAIN:
+       switch (aclass)
+         {
+         case LOC_BLOCK:
+           return DW_TAG_subprogram;
+         case LOC_TYPEDEF:
+           return DW_TAG_typedef;
+         case LOC_COMPUTED:
+         case LOC_CONST_BYTES:
+         case LOC_OPTIMIZED_OUT:
+         case LOC_STATIC:
+           return DW_TAG_variable;
+         case LOC_CONST:
+           /* Note: It's currently impossible to recognize psyms as enum values
+              short of reading the type info.  For now punt.  */
+           return DW_TAG_variable;
+         default:
+           /* There are other LOC_FOO values that one might want to classify
+              as variables, but dwarf2read.c doesn't currently use them.  */
+           return DW_TAG_variable;
+         }
+      case STRUCT_DOMAIN:
+       return DW_TAG_structure_type;
+      default:
+       return 0;
+      }
+  }
 
-  ++info->cu_index;
+  /* Call insert for all partial symbols and mark them in PSYMS_SEEN.  */
+  void write_psymbols (std::unordered_set<partial_symbol *> &psyms_seen,
+                      struct partial_symbol **psymp, int count, int cu_index,
+                      bool is_static, unit_kind kind)
+  {
+    for (; count-- > 0; ++psymp)
+      {
+       struct partial_symbol *psym = *psymp;
 
-  return 1;
-}
+       if (SYMBOL_LANGUAGE (psym) == language_ada)
+         error (_("Ada is not currently supported by the index"));
 
-/* Recurse into all "included" dependencies and write their symbols as
-   if they appeared in this psymtab.  */
+       /* Only add a given psymbol once.  */
+       if (psyms_seen.insert (psym).second)
+         insert (psym, cu_index, is_static, kind);
+      }
+  }
 
-static void
-recursively_write_psymbols (struct objfile *objfile,
-                           struct partial_symtab *psymtab,
-                           struct mapped_symtab *symtab,
-                           std::unordered_set<partial_symbol *> &psyms_seen,
-                           offset_type cu_index)
-{
-  int i;
+  /* A helper function that writes a single signatured_type
+     to a debug_names.  */
+  void
+  write_one_signatured_type (struct signatured_type *entry,
+                            struct signatured_type_index_data *info)
+  {
+    struct partial_symtab *psymtab = entry->per_cu.v.psymtab;
 
-  for (i = 0; i < psymtab->number_of_dependencies; ++i)
-    if (psymtab->dependencies[i]->user != NULL)
-      recursively_write_psymbols (objfile, psymtab->dependencies[i],
-                                 symtab, psyms_seen, cu_index);
+    write_psymbols (info->psyms_seen,
+                   &info->objfile->global_psymbols[psymtab->globals_offset],
+                   psymtab->n_global_syms, info->cu_index, false,
+                   unit_kind::tu);
+    write_psymbols (info->psyms_seen,
+                   &info->objfile->static_psymbols[psymtab->statics_offset],
+                   psymtab->n_static_syms, info->cu_index, true,
+                   unit_kind::tu);
 
-  write_psymbols (symtab,
-                 psyms_seen,
-                 objfile->global_psymbols.list + psymtab->globals_offset,
-                 psymtab->n_global_syms, cu_index,
-                 0);
-  write_psymbols (symtab,
-                 psyms_seen,
-                 objfile->static_psymbols.list + psymtab->statics_offset,
-                 psymtab->n_static_syms, cu_index,
-                 1);
-}
+    info->types_list.append_uint (dwarf5_offset_size (), m_dwarf5_byte_order,
+                                 to_underlying (entry->per_cu.sect_off));
 
-/* Closes FILE on scope exit.  */
-struct file_closer
-{
-  explicit file_closer (FILE *file)
-    : m_file (file)
-  {}
+    ++info->cu_index;
+  }
 
-  ~file_closer ()
-  { fclose (m_file); }
+  /* Store value of each symbol.  */
+  std::unordered_map<c_str_view, std::set<symbol_value>, c_str_view_hasher>
+    m_name_to_value_set;
 
-private:
-  FILE *m_file;
+  /* Tables of DWARF-5 .debug_names.  They are in object file byte
+     order.  */
+  std::vector<uint32_t> m_bucket_table;
+  std::vector<uint32_t> m_hash_table;
+
+  const bfd_endian m_dwarf5_byte_order;
+  dwarf_tmpl<uint32_t> m_dwarf32;
+  dwarf_tmpl<uint64_t> m_dwarf64;
+  dwarf &m_dwarf;
+  offset_vec &m_name_table_string_offs, &m_name_table_entry_offs;
+  debug_str_lookup m_debugstrlookup;
+
+  /* Map each used .debug_names abbreviation tag parameter to its
+     index value.  */
+  std::unordered_map<index_key, int, index_key_hasher> m_indexkey_to_idx;
+
+  /* Next unused .debug_names abbreviation tag for
+     m_indexkey_to_idx.  */
+  int m_idx_next = 1;
+
+  /* .debug_names abbreviation table.  */
+  data_buf m_abbrev_table;
+
+  /* .debug_names entry pool.  */
+  data_buf m_entry_pool;
 };
 
-/* Create an index file for OBJFILE in the directory DIR.  */
+/* Return iff any of the needed offsets does not fit into 32-bit
+   .debug_names section.  */
 
-static void
-write_psymtabs_to_index (struct objfile *objfile, const char *dir)
+static bool
+check_dwarf64_offsets ()
 {
-  if (dwarf2_per_objfile->using_index)
-    error (_("Cannot use an index to create the index"));
+  for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+    {
+      const dwarf2_per_cu_data &per_cu = *dwarf2_per_objfile->all_comp_units[i];
 
-  if (VEC_length (dwarf2_section_info_def, dwarf2_per_objfile->types) > 1)
-    error (_("Cannot make an index when the file has multiple .debug_types sections"));
+      if (to_underlying (per_cu.sect_off) >= (static_cast<uint64_t> (1) << 32))
+       return true;
+    }
+  for (int i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
+    {
+      const signatured_type &sigtype = *dwarf2_per_objfile->all_type_units[i];
+      const dwarf2_per_cu_data &per_cu = sigtype.per_cu;
 
-  if (!objfile->psymtabs || !objfile->psymtabs_addrmap)
-    return;
+      if (to_underlying (per_cu.sect_off) >= (static_cast<uint64_t> (1) << 32))
+       return true;
+    }
+  return false;
+}
 
-  struct stat st;
-  if (stat (objfile_name (objfile), &st) < 0)
-    perror_with_name (objfile_name (objfile));
+/* The psyms_seen set is potentially going to be largish (~40k
+   elements when indexing a -g3 build of GDB itself).  Estimate the
+   number of elements in order to avoid too many rehashes, which
+   require rebuilding buckets and thus many trips to
+   malloc/free.  */
 
-  std::string filename (std::string (dir) + SLASH_STRING
-                       + lbasename (objfile_name (objfile)) + INDEX_SUFFIX);
+static size_t
+psyms_seen_size ()
+{
+  size_t psyms_count = 0;
+  for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+    {
+      struct dwarf2_per_cu_data *per_cu
+       = dwarf2_per_objfile->all_comp_units[i];
+      struct partial_symtab *psymtab = per_cu->v.psymtab;
 
-  FILE *out_file = gdb_fopen_cloexec (filename.c_str (), "wb");
-  if (!out_file)
-    error (_("Can't open `%s' for writing"), filename.c_str ());
+      if (psymtab != NULL && psymtab->user == NULL)
+       recursively_count_psymbols (psymtab, psyms_count);
+    }
+  /* Generating an index for gdb itself shows a ratio of
+     TOTAL_SEEN_SYMS/UNIQUE_SYMS or ~5.  4 seems like a good bet.  */
+  return psyms_count / 4;
+}
 
-  file_closer close_out_file (out_file);
-  gdb::unlinker unlink_file (filename.c_str ());
+/* Write new .gdb_index section for OBJFILE into OUT_FILE.
+   Return how many bytes were expected to be written into OUT_FILE.  */
 
+static size_t
+write_gdbindex (struct objfile *objfile, FILE *out_file)
+{
   mapped_symtab symtab;
   data_buf cu_list;
-  std::unordered_set<partial_symbol *> psyms_seen;
 
   /* While we're scanning CU's create a table that maps a psymtab pointer
      (which is what addrmap records) to its index (which is what is recorded
@@ -23781,6 +26670,8 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
   /* The CU list is already sorted, so we don't need to do additional
      work here.  Also, the debug_types entries do not appear in
      all_comp_units, but only in their own hash table.  */
+
+  std::unordered_set<partial_symbol *> psyms_seen (psyms_seen_size ());
   for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
     {
       struct dwarf2_per_cu_data *per_cu
@@ -23800,11 +26691,9 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
       const auto insertpair = cu_index_htab.emplace (psymtab, i);
       gdb_assert (insertpair.second);
 
-      store_unsigned_integer (cu_list.append_space (8), 8,
-                             BFD_ENDIAN_LITTLE,
-                             to_underlying (per_cu->sect_off));
-      store_unsigned_integer (cu_list.append_space (8), 8,
-                             BFD_ENDIAN_LITTLE, per_cu->length);
+      cu_list.append_uint (8, BFD_ENDIAN_LITTLE,
+                          to_underlying (per_cu->sect_off));
+      cu_list.append_uint (8, BFD_ENDIAN_LITTLE, per_cu->length);
     }
 
   /* Dump the address map.  */
@@ -23868,22 +26757,237 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
   symtab_vec.file_write (out_file);
   constant_pool.file_write (out_file);
 
+  return total_len;
+}
+
+/* DWARF-5 augmentation string for GDB's DW_IDX_GNU_* extension.  */
+static const gdb_byte dwarf5_gdb_augmentation[] = { 'G', 'D', 'B', 0 };
+
+/* Write a new .debug_names section for OBJFILE into OUT_FILE, write
+   needed addition to .debug_str section to OUT_FILE_STR.  Return how
+   many bytes were expected to be written into OUT_FILE.  */
+
+static size_t
+write_debug_names (struct objfile *objfile, FILE *out_file, FILE *out_file_str)
+{
+  const bool dwarf5_is_dwarf64 = check_dwarf64_offsets ();
+  const enum bfd_endian dwarf5_byte_order
+    = gdbarch_byte_order (get_objfile_arch (objfile));
+
+  /* The CU list is already sorted, so we don't need to do additional
+     work here.  Also, the debug_types entries do not appear in
+     all_comp_units, but only in their own hash table.  */
+  data_buf cu_list;
+  debug_names nametable (dwarf5_is_dwarf64, dwarf5_byte_order);
+  std::unordered_set<partial_symbol *> psyms_seen (psyms_seen_size ());
+  for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+    {
+      const dwarf2_per_cu_data *per_cu = dwarf2_per_objfile->all_comp_units[i];
+      partial_symtab *psymtab = per_cu->v.psymtab;
+
+      /* CU of a shared file from 'dwz -m' may be unused by this main
+        file.  It may be referenced from a local scope but in such
+        case it does not need to be present in .debug_names.  */
+      if (psymtab == NULL)
+       continue;
+
+      if (psymtab->user == NULL)
+       nametable.recursively_write_psymbols (objfile, psymtab, psyms_seen, i);
+
+      cu_list.append_uint (nametable.dwarf5_offset_size (), dwarf5_byte_order,
+                          to_underlying (per_cu->sect_off));
+    }
+
+  /* Write out the .debug_type entries, if any.  */
+  data_buf types_cu_list;
+  if (dwarf2_per_objfile->signatured_types)
+    {
+      debug_names::write_one_signatured_type_data sig_data (nametable,
+                       signatured_type_index_data (types_cu_list, psyms_seen));
+
+      sig_data.info.objfile = objfile;
+      /* It is used only for gdb_index.  */
+      sig_data.info.symtab = nullptr;
+      sig_data.info.cu_index = 0;
+      htab_traverse_noresize (dwarf2_per_objfile->signatured_types,
+                             debug_names::write_one_signatured_type,
+                             &sig_data);
+    }
+
+  nametable.build ();
+
+  /* No addr_vec - DWARF-5 uses .debug_aranges generated by GCC.  */
+
+  const offset_type bytes_of_header
+    = ((dwarf5_is_dwarf64 ? 12 : 4)
+       + 2 + 2 + 7 * 4
+       + sizeof (dwarf5_gdb_augmentation));
+  size_t expected_bytes = 0;
+  expected_bytes += bytes_of_header;
+  expected_bytes += cu_list.size ();
+  expected_bytes += types_cu_list.size ();
+  expected_bytes += nametable.bytes ();
+  data_buf header;
+
+  if (!dwarf5_is_dwarf64)
+    {
+      const uint64_t size64 = expected_bytes - 4;
+      gdb_assert (size64 < 0xfffffff0);
+      header.append_uint (4, dwarf5_byte_order, size64);
+    }
+  else
+    {
+      header.append_uint (4, dwarf5_byte_order, 0xffffffff);
+      header.append_uint (8, dwarf5_byte_order, expected_bytes - 12);
+    }
+
+  /* The version number.  */
+  header.append_uint (2, dwarf5_byte_order, 5);
+
+  /* Padding.  */
+  header.append_uint (2, dwarf5_byte_order, 0);
+
+  /* comp_unit_count - The number of CUs in the CU list.  */
+  header.append_uint (4, dwarf5_byte_order, dwarf2_per_objfile->n_comp_units);
+
+  /* local_type_unit_count - The number of TUs in the local TU
+     list.  */
+  header.append_uint (4, dwarf5_byte_order, dwarf2_per_objfile->n_type_units);
+
+  /* foreign_type_unit_count - The number of TUs in the foreign TU
+     list.  */
+  header.append_uint (4, dwarf5_byte_order, 0);
+
+  /* bucket_count - The number of hash buckets in the hash lookup
+     table.  */
+  header.append_uint (4, dwarf5_byte_order, nametable.bucket_count ());
+
+  /* name_count - The number of unique names in the index.  */
+  header.append_uint (4, dwarf5_byte_order, nametable.name_count ());
+
+  /* abbrev_table_size - The size in bytes of the abbreviations
+     table.  */
+  header.append_uint (4, dwarf5_byte_order, nametable.abbrev_table_bytes ());
+
+  /* augmentation_string_size - The size in bytes of the augmentation
+     string.  This value is rounded up to a multiple of 4.  */
+  static_assert (sizeof (dwarf5_gdb_augmentation) % 4 == 0, "");
+  header.append_uint (4, dwarf5_byte_order, sizeof (dwarf5_gdb_augmentation));
+  header.append_data (dwarf5_gdb_augmentation);
+
+  gdb_assert (header.size () == bytes_of_header);
+
+  header.file_write (out_file);
+  cu_list.file_write (out_file);
+  types_cu_list.file_write (out_file);
+  nametable.file_write (out_file, out_file_str);
+
+  return expected_bytes;
+}
+
+/* Assert that FILE's size is EXPECTED_SIZE.  Assumes file's seek
+   position is at the end of the file.  */
+
+static void
+assert_file_size (FILE *file, const char *filename, size_t expected_size)
+{
+  const auto file_size = ftell (file);
+  if (file_size == -1)
+    error (_("Can't get `%s' size"), filename);
+  gdb_assert (file_size == expected_size);
+}
+
+/* Create an index file for OBJFILE in the directory DIR.  */
+
+static void
+write_psymtabs_to_index (struct objfile *objfile, const char *dir,
+                        dw_index_kind index_kind)
+{
+  if (dwarf2_per_objfile->using_index)
+    error (_("Cannot use an index to create the index"));
+
+  if (VEC_length (dwarf2_section_info_def, dwarf2_per_objfile->types) > 1)
+    error (_("Cannot make an index when the file has multiple .debug_types sections"));
+
+  if (!objfile->psymtabs || !objfile->psymtabs_addrmap)
+    return;
+
+  struct stat st;
+  if (stat (objfile_name (objfile), &st) < 0)
+    perror_with_name (objfile_name (objfile));
+
+  std::string filename (std::string (dir) + SLASH_STRING
+                       + lbasename (objfile_name (objfile))
+                       + (index_kind == dw_index_kind::DEBUG_NAMES
+                          ? INDEX5_SUFFIX : INDEX4_SUFFIX));
+
+  FILE *out_file = gdb_fopen_cloexec (filename.c_str (), "wb").release ();
+  if (!out_file)
+    error (_("Can't open `%s' for writing"), filename.c_str ());
+
+  /* Order matters here; we want FILE to be closed before FILENAME is
+     unlinked, because on MS-Windows one cannot delete a file that is
+     still open.  (Don't call anything here that might throw until
+     file_closer is created.)  */
+  gdb::unlinker unlink_file (filename.c_str ());
+  gdb_file_up close_out_file (out_file);
+
+  if (index_kind == dw_index_kind::DEBUG_NAMES)
+    {
+      std::string filename_str (std::string (dir) + SLASH_STRING
+                               + lbasename (objfile_name (objfile))
+                               + DEBUG_STR_SUFFIX);
+      FILE *out_file_str
+       = gdb_fopen_cloexec (filename_str.c_str (), "wb").release ();
+      if (!out_file_str)
+       error (_("Can't open `%s' for writing"), filename_str.c_str ());
+      gdb::unlinker unlink_file_str (filename_str.c_str ());
+      gdb_file_up close_out_file_str (out_file_str);
+
+      const size_t total_len
+       = write_debug_names (objfile, out_file, out_file_str);
+      assert_file_size (out_file, filename.c_str (), total_len);
+
+      /* We want to keep the file .debug_str file too.  */
+      unlink_file_str.keep ();
+    }
+  else
+    {
+      const size_t total_len
+       = write_gdbindex (objfile, out_file);
+      assert_file_size (out_file, filename.c_str (), total_len);
+    }
+
   /* We want to keep the file.  */
   unlink_file.keep ();
 }
 
 /* Implementation of the `save gdb-index' command.
    
-   Note that the file format used by this command is documented in the
-   GDB manual.  Any changes here must be documented there.  */
+   Note that the .gdb_index file format used by this command is
+   documented in the GDB manual.  Any changes here must be documented
+   there.  */
 
 static void
-save_gdb_index_command (char *arg, int from_tty)
+save_gdb_index_command (const char *arg, int from_tty)
 {
   struct objfile *objfile;
+  const char dwarf5space[] = "-dwarf-5 ";
+  dw_index_kind index_kind = dw_index_kind::GDB_INDEX;
+
+  if (!arg)
+    arg = "";
+
+  arg = skip_spaces (arg);
+  if (strncmp (arg, dwarf5space, strlen (dwarf5space)) == 0)
+    {
+      index_kind = dw_index_kind::DEBUG_NAMES;
+      arg += strlen (dwarf5space);
+      arg = skip_spaces (arg);
+    }
 
-  if (!arg || !*arg)
-    error (_("usage: save gdb-index DIRECTORY"));
+  if (!*arg)
+    error (_("usage: save gdb-index [-dwarf-5] DIRECTORY"));
 
   ALL_OBJFILES (objfile)
   {
@@ -23901,7 +27005,7 @@ save_gdb_index_command (char *arg, int from_tty)
 
        TRY
          {
-           write_psymtabs_to_index (objfile, arg);
+           write_psymtabs_to_index (objfile, arg, index_kind);
          }
        CATCH (except, RETURN_MASK_ERROR)
          {
@@ -23937,8 +27041,6 @@ show_check_physname (struct ui_file *file, int from_tty,
                    value);
 }
 
-void _initialize_dwarf2_read (void);
-
 void
 _initialize_dwarf2_read (void)
 {
@@ -24035,7 +27137,11 @@ Warning: This option must be enabled before gdb reads the file."),
   c = add_cmd ("gdb-index", class_files, save_gdb_index_command,
               _("\
 Save a gdb-index file.\n\
-Usage: save gdb-index DIRECTORY"),
+Usage: save gdb-index [-dwarf-5] DIRECTORY\n\
+\n\
+No options create one file with .gdb-index extension for pre-DWARF-5\n\
+compatible .gdb_index section.  With -dwarf-5 creates two files with\n\
+extension .debug_names and .debug_str for DWARF-5 .debug_names section."),
               &save_cmdlist);
   set_cmd_completer (c, filename_completer);
 
@@ -24048,4 +27154,9 @@ Usage: save gdb-index DIRECTORY"),
                                        &dwarf2_block_frame_base_locexpr_funcs);
   dwarf2_loclist_block_index = register_symbol_block_impl (LOC_BLOCK,
                                        &dwarf2_block_frame_base_loclist_funcs);
+
+#if GDB_SELF_TEST
+  selftests::register_test ("dw2_expand_symtabs_matching",
+                           selftests::dw2_expand_symtabs_matching::run_test);
+#endif
 }