dwarf2read: Silence -Wenum-compare-switch warning
[binutils-gdb.git] / gdb / dwarf2read.c
index 8a6684883cd7ba1936ab93c73f4dd239112c08e6..fcd5e995366235cf31a6e3cb6888b339da00fb7c 100644 (file)
 #include "filestuff.h"
 #include "build-id.h"
 #include "namespace.h"
-
+#include "common/gdb_unlinker.h"
+#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);
@@ -174,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;
@@ -217,82 +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 macinfo;
-  struct dwarf2_section_info macro;
-  struct dwarf2_section_info str;
-  struct dwarf2_section_info ranges;
-  struct dwarf2_section_info addr;
-  struct dwarf2_section_info frame;
-  struct dwarf2_section_info eh_frame;
-  struct dwarf2_section_info gdb_index;
-
-  VEC (dwarf2_section_info_def) *types;
+  /* 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);
+
+  ~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
@@ -301,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;
@@ -332,15 +527,20 @@ static const struct dwarf2_debug_sections dwarf2_elf_names =
   { ".debug_abbrev", ".zdebug_abbrev" },
   { ".debug_line", ".zdebug_line" },
   { ".debug_loc", ".zdebug_loc" },
+  { ".debug_loclists", ".zdebug_loclists" },
   { ".debug_macinfo", ".zdebug_macinfo" },
   { ".debug_macro", ".zdebug_macro" },
   { ".debug_str", ".zdebug_str" },
+  { ".debug_line_str", ".zdebug_line_str" },
   { ".debug_ranges", ".zdebug_ranges" },
+  { ".debug_rnglists", ".zdebug_rnglists" },
   { ".debug_types", ".zdebug_types" },
   { ".debug_addr", ".zdebug_addr" },
   { ".debug_frame", ".zdebug_frame" },
   { ".eh_frame", NULL },
   { ".gdb_index", ".zgdb_index" },
+  { ".debug_names", ".zdebug_names" },
+  { ".debug_aranges", ".zdebug_aranges" },
   23
 };
 
@@ -352,6 +552,7 @@ static const struct dwop_section_names
   struct dwarf2_section_names info_dwo;
   struct dwarf2_section_names line_dwo;
   struct dwarf2_section_names loc_dwo;
+  struct dwarf2_section_names loclists_dwo;
   struct dwarf2_section_names macinfo_dwo;
   struct dwarf2_section_names macro_dwo;
   struct dwarf2_section_names str_dwo;
@@ -366,6 +567,7 @@ dwop_section_names =
   { ".debug_info.dwo", ".zdebug_info.dwo" },
   { ".debug_line.dwo", ".zdebug_line.dwo" },
   { ".debug_loc.dwo", ".zdebug_loc.dwo" },
+  { ".debug_loclists.dwo", ".zdebug_loclists.dwo" },
   { ".debug_macinfo.dwo", ".zdebug_macinfo.dwo" },
   { ".debug_macro.dwo", ".zdebug_macro.dwo" },
   { ".debug_str.dwo", ".zdebug_str.dwo" },
@@ -385,7 +587,7 @@ struct comp_unit_head
   short version;
   unsigned char addr_size;
   unsigned char signed_addr_p;
-  sect_offset abbrev_offset;
+  sect_offset abbrev_sect_off;
 
   /* Size of file offsets; either 4 or 8.  */
   unsigned int offset_size;
@@ -393,13 +595,22 @@ struct comp_unit_head
   /* Size of the length field; either 4 or 12.  */
   unsigned int initial_length_size;
 
+  enum dwarf_unit_type unit_type;
+
   /* Offset to the first byte of this compilation unit header in the
      .debug_info section, for resolving relative reference dies.  */
-  sect_offset offset;
+  sect_offset sect_off;
 
   /* Offset to first die in this cu from the start of the cu.
      This will be the first byte following the compilation unit header.  */
-  cu_offset first_die_offset;
+  cu_offset first_die_cu_offset;
+
+  /* 64-bit signature of this type unit - it is valid only for
+     UNIT_TYPE DW_UT_type.  */
+  ULONGEST signature;
+
+  /* For types, offset in the type's DIE of the type defined by this TU.  */
+  cu_offset type_cu_offset_in_tu;
 };
 
 /* Type used for delaying computation of method physnames.
@@ -496,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.  */
@@ -548,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
@@ -568,9 +785,12 @@ struct dwarf2_per_cu_data
      initial_length_size.
      If the DIE refers to a DWO file, this is always of the original die,
      not the DWO file.  */
-  sect_offset offset;
+  sect_offset sect_off;
   unsigned int length;
 
+  /* DWARF standard version this data has been read from (such as 4 or 5).  */
+  short dwarf_version;
+
   /* Flag indicating this compilation unit will be read in before
      any of the current compilation units are processed.  */
   unsigned int queued : 1;
@@ -704,7 +924,7 @@ struct stmt_list_hash
   struct dwo_unit *dwo_unit;
 
   /* Offset in .debug_line or .debug_line.dwo.  */
-  sect_offset line_offset;
+  sect_offset line_sect_off;
 };
 
 /* Each element of dwarf2_per_objfile->type_unit_groups is a pointer to
@@ -755,6 +975,7 @@ struct dwo_sections
   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;
@@ -779,8 +1000,8 @@ struct dwo_unit
   /* The section this CU/TU lives in, in the DWO file.  */
   struct dwarf2_section_info *section;
 
-  /* Same as dwarf2_per_cu_data:{offset,length} but in the DWO section.  */
-  sect_offset offset;
+  /* Same as dwarf2_per_cu_data:{sect_off,length} but in the DWO section.  */
+  sect_offset sect_off;
   unsigned int length;
 
   /* For types, offset in the type's DIE of the type defined by this TU.  */
@@ -827,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.  */
@@ -987,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;
@@ -1029,16 +1250,46 @@ typedef void (die_reader_func_ftype) (const struct die_reader_specs *reader,
                                      int has_children,
                                      void *data);
 
+/* A 1-based directory index.  This is a strong typedef to prevent
+   accidentally using a directory index as a 0-based index into an
+   array/vector.  */
+enum class dir_index : unsigned int {};
+
+/* Likewise, a 1-based file name index.  */
+enum class file_name_index : unsigned int {};
+
 struct file_entry
 {
-  const char *name;
-  unsigned int dir_index;
-  unsigned int mod_time;
-  unsigned int length;
-  /* Non-zero if referenced by the Line Number Program.  */
-  int included_p;
+  file_entry () = default;
+
+  file_entry (const char *name_, dir_index d_index_,
+             unsigned int mod_time_, unsigned int length_)
+    : name (name_),
+      d_index (d_index_),
+      mod_time (mod_time_),
+      length (length_)
+  {}
+
+  /* Return the include directory at D_INDEX stored in LH.  Returns
+     NULL if D_INDEX is out of bounds.  */
+  const char *include_dir (const line_header *lh) const;
+
+  /* The file name.  Note this is an observing pointer.  The memory is
+     owned by debug_line_buffer.  */
+  const char *name {};
+
+  /* The directory index (1-based).  */
+  dir_index d_index {};
+
+  unsigned int mod_time {};
+
+  unsigned int length {};
+
+  /* True if referenced by the Line Number Program.  */
+  bool included_p {};
+
   /* The associated symbol table, if any.  */
-  struct symtab *symtab;
+  struct symtab *symtab {};
 };
 
 /* The line number information for a compilation unit (found in the
@@ -1046,52 +1297,99 @@ struct file_entry
    which contains the following information.  */
 struct line_header
 {
+  line_header ()
+    : offset_in_dwz {}
+  {}
+
+  /* Add an entry to the include directory table.  */
+  void add_include_dir (const char *include_dir);
+
+  /* Add an entry to the file name table.  */
+  void add_file_name (const char *name, dir_index d_index,
+                     unsigned int mod_time, unsigned int length);
+
+  /* Return the include dir at INDEX (1-based).  Returns NULL if INDEX
+     is out of bounds.  */
+  const char *include_dir_at (dir_index index) const
+  {
+    /* Convert directory index number (1-based) to vector index
+       (0-based).  */
+    size_t vec_index = to_underlying (index) - 1;
+
+    if (vec_index >= include_dirs.size ())
+      return NULL;
+    return include_dirs[vec_index];
+  }
+
+  /* Return the file name at INDEX (1-based).  Returns NULL if INDEX
+     is out of bounds.  */
+  file_entry *file_name_at (file_name_index index)
+  {
+    /* Convert file name index number (1-based) to vector index
+       (0-based).  */
+    size_t vec_index = to_underlying (index) - 1;
+
+    if (vec_index >= file_names.size ())
+      return NULL;
+    return &file_names[vec_index];
+  }
+
+  /* Const version of the above.  */
+  const file_entry *file_name_at (unsigned int index) const
+  {
+    if (index >= file_names.size ())
+      return NULL;
+    return &file_names[index];
+  }
+
   /* Offset of line number information in .debug_line section.  */
-  sect_offset offset;
+  sect_offset sect_off {};
 
   /* OFFSET is for struct dwz_file associated with dwarf2_per_objfile.  */
-  unsigned offset_in_dwz : 1;
-
-  unsigned int total_length;
-  unsigned short version;
-  unsigned int header_length;
-  unsigned char minimum_instruction_length;
-  unsigned char maximum_ops_per_instruction;
-  unsigned char default_is_stmt;
-  int line_base;
-  unsigned char line_range;
-  unsigned char opcode_base;
+  unsigned offset_in_dwz : 1; /* Can't initialize bitfields in-class.  */
+
+  unsigned int total_length {};
+  unsigned short version {};
+  unsigned int header_length {};
+  unsigned char minimum_instruction_length {};
+  unsigned char maximum_ops_per_instruction {};
+  unsigned char default_is_stmt {};
+  int line_base {};
+  unsigned char line_range {};
+  unsigned char opcode_base {};
 
   /* standard_opcode_lengths[i] is the number of operands for the
      standard opcode whose value is i.  This means that
      standard_opcode_lengths[0] is unused, and the last meaningful
      element is standard_opcode_lengths[opcode_base - 1].  */
-  unsigned char *standard_opcode_lengths;
+  std::unique_ptr<unsigned char[]> standard_opcode_lengths;
 
-  /* The include_directories table.  NOTE!  These strings are not
-     allocated with xmalloc; instead, they are pointers into
-     debug_line_buffer.  If you try to free them, `free' will get
-     indigestion.  */
-  unsigned int num_include_dirs, include_dirs_size;
-  const char **include_dirs;
+  /* The include_directories table.  Note these are observing
+     pointers.  The memory is owned by debug_line_buffer.  */
+  std::vector<const char *> include_dirs;
 
-  /* The file_names table.  NOTE!  These strings are not allocated
-     with xmalloc; instead, they are pointers into debug_line_buffer.
-     Don't try to free them directly.  */
-  unsigned int num_file_names, file_names_size;
-  struct file_entry *file_names;
+  /* The file_names table.  */
+  std::vector<file_entry> file_names;
 
   /* The start and end of the statement program following this
      header.  These point into dwarf2_per_objfile->line_buffer.  */
-  const gdb_byte *statement_program_start, *statement_program_end;
+  const gdb_byte *statement_program_start {}, *statement_program_end {};
 };
 
+typedef std::unique_ptr<line_header> line_header_up;
+
+const char *
+file_entry::include_dir (const line_header *lh) const
+{
+  return lh->include_dir_at (d_index);
+}
+
 /* When we construct a partial symbol table entry we only
    need this much information.  */
 struct partial_die_info
   {
     /* Offset of this DIE.  */
-    sect_offset offset;
+    sect_offset sect_off;
 
     /* DWARF-2 tag for this DIE.  */
     ENUM_BITFIELD(dwarf_tag) tag : 16;
@@ -1149,7 +1447,7 @@ struct partial_die_info
       /* The location description associated with this DIE, if any.  */
       struct dwarf_block *locdesc;
       /* The offset of an import, for DW_TAG_imported_unit.  */
-      sect_offset offset;
+      sect_offset sect_off;
     } d;
 
     /* If HAS_PC_INFO, the PC range associated with this DIE.  */
@@ -1187,6 +1485,9 @@ struct attr_abbrev
   {
     ENUM_BITFIELD(dwarf_attribute) name : 16;
     ENUM_BITFIELD(dwarf_form) form : 16;
+
+    /* It is valid only if FORM is DW_FORM_implicit_const.  */
+    LONGEST implicit_const;
   };
 
 /* Size of abbrev_table.abbrev_hash_table.  */
@@ -1198,7 +1499,7 @@ struct abbrev_table
 {
   /* Where the abbrev table came from.
      This is used as a sanity check when the table is used.  */
-  sect_offset offset;
+  sect_offset sect_off;
 
   /* Storage for the abbrev table.  */
   struct obstack abbrev_obstack;
@@ -1253,7 +1554,7 @@ struct die_info
     unsigned int abbrev;
 
     /* Offset in .debug_info or .debug_types section.  */
-    sect_offset offset;
+    sect_offset sect_off;
 
     /* The dies in a compilation unit form an n-ary tree.  PARENT
        points to this die's parent; CHILD points to the first child of
@@ -1323,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
@@ -1346,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.  */
@@ -1360,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
@@ -1397,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 *,
@@ -1506,9 +1811,14 @@ static const char *read_indirect_string (bfd *, const gdb_byte *,
                                         const struct comp_unit_head *,
                                         unsigned int *);
 
-static const char *read_indirect_string_from_dwz (struct dwz_file *, LONGEST);
+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 ULONGEST read_unsigned_leb128 (bfd *, const gdb_byte *, unsigned int *);
+static const char *read_indirect_string_from_dwz (struct dwz_file *, LONGEST);
 
 static LONGEST read_signed_leb128 (bfd *, const gdb_byte *, unsigned int *);
 
@@ -1538,10 +1848,8 @@ static int die_is_declaration (struct die_info *, struct dwarf2_cu *cu);
 static struct die_info *die_specification (struct die_info *die,
                                           struct dwarf2_cu **);
 
-static void free_line_header (struct line_header *lh);
-
-static struct line_header *dwarf_decode_line_header (unsigned int offset,
-                                                    struct dwarf2_cu *cu);
+static line_header_up dwarf_decode_line_header (sect_offset sect_off,
+                                               struct dwarf2_cu *cu);
 
 static void dwarf_decode_lines (struct line_header *, const char *,
                                struct dwarf2_cu *, struct partial_symtab *,
@@ -1606,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 *);
 
@@ -1720,7 +2030,7 @@ static const char *dwarf_attr_name (unsigned int);
 
 static const char *dwarf_form_name (unsigned int);
 
-static char *dwarf_bool_name (unsigned int);
+static const char *dwarf_bool_name (unsigned int);
 
 static const char *dwarf_type_encoding_name (unsigned int);
 
@@ -1805,7 +2115,7 @@ static hashval_t partial_die_hash (const void *item);
 static int partial_die_eq (const void *item_lhs, const void *item_rhs);
 
 static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit
-  (sect_offset offset, unsigned int offset_in_dwz, struct objfile *objfile);
+  (sect_offset sect_off, unsigned int offset_in_dwz, struct objfile *objfile);
 
 static void init_one_comp_unit (struct dwarf2_cu *cu,
                                struct dwarf2_per_cu_data *per_cu);
@@ -1857,18 +2167,39 @@ static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu,
 
 static void process_queue (void);
 
-static void find_file_and_directory (struct die_info *die,
-                                    struct dwarf2_cu *cu,
-                                    const char **name, const char **comp_dir);
+/* The return type of find_file_and_directory.  Note, the enclosed
+   string pointers are only valid while this object is valid.  */
+
+struct file_and_directory
+{
+  /* The filename.  This is never NULL.  */
+  const char *name;
+
+  /* The compilation directory.  NULL if not known.  If we needed to
+     compute a new string, this points to COMP_DIR_STORAGE, otherwise,
+     points directly to the DW_AT_comp_dir string attribute owned by
+     the obstack that owns the DIE.  */
+  const char *comp_dir;
+
+  /* If we needed to build a new string for comp_dir, this is what
+     owns the storage.  */
+  std::string comp_dir_storage;
+};
+
+static file_and_directory find_file_and_directory (struct die_info *die,
+                                                  struct dwarf2_cu *cu);
 
 static char *file_full_name (int file, struct line_header *lh,
                             const char *comp_dir);
 
+/* Expected enum dwarf_unit_type for read_comp_unit_head.  */
+enum class rcuh_kind { COMPILE, TYPE };
+
 static const gdb_byte *read_and_check_comp_unit_head
   (struct comp_unit_head *header,
    struct dwarf2_section_info *section,
    struct dwarf2_section_info *abbrev_section, const gdb_byte *info_ptr,
-   int is_debug_types_section);
+   rcuh_kind section_kind);
 
 static void init_cutu_and_read_dies
   (struct dwarf2_per_cu_data *this_cu, struct abbrev_table *abbrev_table,
@@ -1976,7 +2307,7 @@ dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2)
 static hashval_t
 line_header_hash (const struct line_header *ofs)
 {
-  return ofs->offset.sect_off ^ ofs->offset_in_dwz;
+  return to_underlying (ofs->sect_off) ^ ofs->offset_in_dwz;
 }
 
 /* Hash function for htab_create_alloc_ex for line_header_hash.  */
@@ -1997,31 +2328,11 @@ line_header_eq_voidp (const void *item_lhs, const void *item_rhs)
   const struct line_header *ofs_lhs = (const struct line_header *) item_lhs;
   const struct line_header *ofs_rhs = (const struct line_header *) item_rhs;
 
-  return (ofs_lhs->offset.sect_off == ofs_rhs->offset.sect_off
+  return (ofs_lhs->sect_off == ofs_rhs->sect_off
          && ofs_lhs->offset_in_dwz == ofs_rhs->offset_in_dwz);
 }
 
 \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) (V)
-#endif /* WORDS_BIGENDIAN */
 
 /* Read the given attribute value as an address, taking the attribute's
    form into account.  */
@@ -2054,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.
@@ -2065,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)
@@ -2073,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
@@ -2185,80 +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))
+    {
+      this->info.s.section = sectp;
+      this->info.size = bfd_get_section_size (sectp);
+    }
+  else if (section_is_p (sectp->name, &names.abbrev))
+    {
+      this->abbrev.s.section = sectp;
+      this->abbrev.size = bfd_get_section_size (sectp);
+    }
+  else if (section_is_p (sectp->name, &names.line))
+    {
+      this->line.s.section = sectp;
+      this->line.size = bfd_get_section_size (sectp);
+    }
+  else if (section_is_p (sectp->name, &names.loc))
     {
-      dwarf2_per_objfile->info.s.section = sectp;
-      dwarf2_per_objfile->info.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->abbrev))
+  else if (section_is_p (sectp->name, &names.loclists))
     {
-      dwarf2_per_objfile->abbrev.s.section = sectp;
-      dwarf2_per_objfile->abbrev.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->line))
+  else if (section_is_p (sectp->name, &names.macinfo))
     {
-      dwarf2_per_objfile->line.s.section = sectp;
-      dwarf2_per_objfile->line.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->loc))
+  else if (section_is_p (sectp->name, &names.macro))
     {
-      dwarf2_per_objfile->loc.s.section = sectp;
-      dwarf2_per_objfile->loc.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->macinfo))
+  else if (section_is_p (sectp->name, &names.str))
     {
-      dwarf2_per_objfile->macinfo.s.section = sectp;
-      dwarf2_per_objfile->macinfo.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->macro))
+  else if (section_is_p (sectp->name, &names.line_str))
     {
-      dwarf2_per_objfile->macro.s.section = sectp;
-      dwarf2_per_objfile->macro.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->str))
+  else if (section_is_p (sectp->name, &names.addr))
     {
-      dwarf2_per_objfile->str.s.section = sectp;
-      dwarf2_per_objfile->str.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->addr))
+  else if (section_is_p (sectp->name, &names.frame))
     {
-      dwarf2_per_objfile->addr.s.section = sectp;
-      dwarf2_per_objfile->addr.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->frame))
+  else if (section_is_p (sectp->name, &names.eh_frame))
     {
-      dwarf2_per_objfile->frame.s.section = sectp;
-      dwarf2_per_objfile->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->eh_frame))
+  else if (section_is_p (sectp->name, &names.ranges))
     {
-      dwarf2_per_objfile->eh_frame.s.section = sectp;
-      dwarf2_per_objfile->eh_frame.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->ranges))
+  else if (section_is_p (sectp->name, &names.rnglists))
     {
-      dwarf2_per_objfile->ranges.s.section = sectp;
-      dwarf2_per_objfile->ranges.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;
 
@@ -2266,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))
+    {
+      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))
     {
-      dwarf2_per_objfile->gdb_index.s.section = sectp;
-      dwarf2_per_objfile->gdb_index.size = bfd_get_section_size (sectp);
+      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,
@@ -2470,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
@@ -2479,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;
@@ -2491,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)
@@ -2500,24 +2879,21 @@ 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));
-      char *rel;
-
-      make_cleanup (xfree, abs);
-      abs = ldirname (abs);
-      make_cleanup (xfree, abs);
+      gdb::unique_xmalloc_ptr<char> abs
+       = gdb_realpath (objfile_name (dwarf2_per_objfile->objfile));
 
-      rel = concat (abs, SLASH_STRING, filename, (char *) NULL);
-      make_cleanup (xfree, rel);
-      filename = rel;
+      abs_storage = ldirname (abs.get ()) + SLASH_STRING + filename;
+      filename = abs_storage.c_str ();
     }
 
   /* First try the file name given in the section.  If that doesn't
@@ -2542,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;
@@ -2605,7 +2979,7 @@ hash_stmt_list_entry (const struct stmt_list_hash *stmt_list_hash)
 
   if (stmt_list_hash->dwo_unit != NULL)
     v += (uintptr_t) stmt_list_hash->dwo_unit->dwo_file;
-  v += stmt_list_hash->line_offset.sect_off;
+  v += to_underlying (stmt_list_hash->line_sect_off);
   return v;
 }
 
@@ -2621,7 +2995,7 @@ eq_stmt_list_entry (const struct stmt_list_hash *lhs,
       && lhs->dwo_unit->dwo_file != rhs->dwo_unit->dwo_file)
     return 0;
 
-  return lhs->line_offset.sect_off == rhs->line_offset.sect_off;
+  return lhs->line_sect_off == rhs->line_sect_off;
 }
 
 /* Hash function for a quick_file_names.  */
@@ -2747,7 +3121,7 @@ dw2_instantiate_symtab (struct dwarf2_per_cu_data *per_cu)
   if (!per_cu->v.quick->compunit_symtab)
     {
       struct cleanup *back_to = make_cleanup (free_cached_comp_units, NULL);
-      increment_reading_symtab ();
+      scoped_restore decrementer = increment_reading_symtab ();
       dw2_do_instantiate_symtab (per_cu);
       process_cu_includes ();
       do_cleanups (back_to);
@@ -2794,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.  */
 
@@ -2808,24 +3205,15 @@ create_cus_from_index_list (struct objfile *objfile,
 
   for (i = 0; i < n_elements; i += 2)
     {
-      struct dwarf2_per_cu_data *the_cu;
-      ULONGEST offset, length;
-
       gdb_static_assert (sizeof (ULONGEST) >= 8);
-      offset = extract_unsigned_integer (cu_list, 8, BFD_ENDIAN_LITTLE);
-      length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE);
+
+      sect_offset sect_off
+       = (sect_offset) extract_unsigned_integer (cu_list, 8, BFD_ENDIAN_LITTLE);
+      ULONGEST length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE);
       cu_list += 2 * 8;
 
-      the_cu = OBSTACK_ZALLOC (&objfile->objfile_obstack,
-                              struct dwarf2_per_cu_data);
-      the_cu->offset.sect_off = offset;
-      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);
     }
 }
 
@@ -2877,23 +3265,26 @@ create_signatured_type_table_from_index (struct objfile *objfile,
   for (i = 0; i < elements; i += 3)
     {
       struct signatured_type *sig_type;
-      ULONGEST offset, type_offset_in_tu, signature;
+      ULONGEST signature;
       void **slot;
+      cu_offset type_offset_in_tu;
 
       gdb_static_assert (sizeof (ULONGEST) >= 8);
-      offset = extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE);
-      type_offset_in_tu = extract_unsigned_integer (bytes + 8, 8,
-                                                   BFD_ENDIAN_LITTLE);
+      sect_offset sect_off
+       = (sect_offset) extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE);
+      type_offset_in_tu
+       = (cu_offset) extract_unsigned_integer (bytes + 8, 8,
+                                               BFD_ENDIAN_LITTLE);
       signature = extract_unsigned_integer (bytes + 16, 8, BFD_ENDIAN_LITTLE);
       bytes += 3 * 8;
 
       sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
                                 struct signatured_type);
       sig_type->signature = signature;
-      sig_type->type_offset_in_tu.cu_off = type_offset_in_tu;
+      sig_type->type_offset_in_tu = type_offset_in_tu;
       sig_type->per_cu.is_debug_types = 1;
       sig_type->per_cu.section = section;
-      sig_type->per_cu.offset.sect_off = offset;
+      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,
@@ -2908,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.  */
 
@@ -2916,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));
 
@@ -2963,12 +3411,170 @@ 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
+/* Read the address map data from DWARF-5 .debug_aranges, and use it to
+   populate the objfile's psymtabs_addrmap.  */
+
+static void
+create_addrmap_from_aranges (struct objfile *objfile,
+                            struct dwarf2_section_info *section)
+{
+  bfd *abfd = objfile->obfd;
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  const CORE_ADDR baseaddr = ANOFFSET (objfile->section_offsets,
+                                      SECT_OFF_TEXT (objfile));
+
+  auto_obstack temp_obstack;
+  addrmap *mutable_map = addrmap_create_mutable (&temp_obstack);
+
+  std::unordered_map<sect_offset,
+                    dwarf2_per_cu_data *,
+                    gdb::hash_enum<sect_offset>>
+    debug_info_offset_to_per_cu;
+  for (int cui = 0; cui < dwarf2_per_objfile->n_comp_units; ++cui)
+    {
+      dwarf2_per_cu_data *per_cu = dw2_get_cutu (cui);
+      const auto insertpair
+       = debug_info_offset_to_per_cu.emplace (per_cu->sect_off, per_cu);
+      if (!insertpair.second)
+       {
+         warning (_("Section .debug_aranges in %s has duplicate "
+                    "debug_info_offset %u, ignoring .debug_aranges."),
+                  objfile_name (objfile), to_underlying (per_cu->sect_off));
+         return;
+       }
+    }
+
+  dwarf2_read_section (objfile, section);
+
+  const bfd_endian dwarf5_byte_order = gdbarch_byte_order (gdbarch);
+
+  const gdb_byte *addr = section->buffer;
+
+  while (addr < section->buffer + section->size)
+    {
+      const gdb_byte *const entry_addr = addr;
+      unsigned int bytes_read;
+
+      const LONGEST entry_length = read_initial_length (abfd, addr,
+                                                       &bytes_read);
+      addr += bytes_read;
+
+      const gdb_byte *const entry_end = addr + entry_length;
+      const bool dwarf5_is_dwarf64 = bytes_read != 4;
+      const uint8_t offset_size = dwarf5_is_dwarf64 ? 8 : 4;
+      if (addr + entry_length > section->buffer + section->size)
+       {
+         warning (_("Section .debug_aranges in %s entry at offset %zu "
+                    "length %s exceeds section length %s, "
+                    "ignoring .debug_aranges."),
+                  objfile_name (objfile), entry_addr - section->buffer,
+                  plongest (bytes_read + entry_length),
+                  pulongest (section->size));
+         return;
+       }
+
+      /* The version number.  */
+      const uint16_t version = read_2_bytes (abfd, addr);
+      addr += 2;
+      if (version != 2)
+       {
+         warning (_("Section .debug_aranges in %s entry at offset %zu "
+                    "has unsupported version %d, ignoring .debug_aranges."),
+                  objfile_name (objfile), entry_addr - section->buffer,
+                  version);
+         return;
+       }
+
+      const uint64_t debug_info_offset
+       = extract_unsigned_integer (addr, offset_size, dwarf5_byte_order);
+      addr += offset_size;
+      const auto per_cu_it
+       = debug_info_offset_to_per_cu.find (sect_offset (debug_info_offset));
+      if (per_cu_it == debug_info_offset_to_per_cu.cend ())
+       {
+         warning (_("Section .debug_aranges in %s entry at offset %zu "
+                    "debug_info_offset %s does not exists, "
+                    "ignoring .debug_aranges."),
+                  objfile_name (objfile), entry_addr - section->buffer,
+                  pulongest (debug_info_offset));
+         return;
+       }
+      dwarf2_per_cu_data *const per_cu = per_cu_it->second;
+
+      const uint8_t address_size = *addr++;
+      if (address_size < 1 || address_size > 8)
+       {
+         warning (_("Section .debug_aranges in %s entry at offset %zu "
+                    "address_size %u is invalid, ignoring .debug_aranges."),
+                  objfile_name (objfile), entry_addr - section->buffer,
+                  address_size);
+         return;
+       }
+
+      const uint8_t segment_selector_size = *addr++;
+      if (segment_selector_size != 0)
+       {
+         warning (_("Section .debug_aranges in %s entry at offset %zu "
+                    "segment_selector_size %u is not supported, "
+                    "ignoring .debug_aranges."),
+                  objfile_name (objfile), entry_addr - section->buffer,
+                  segment_selector_size);
+         return;
+       }
+
+      /* Must pad to an alignment boundary that is twice the address
+         size.  It is undocumented by the DWARF standard but GCC does
+         use it.  */
+      for (size_t padding = ((-(addr - section->buffer))
+                            & (2 * address_size - 1));
+           padding > 0; padding--)
+       if (*addr++ != 0)
+         {
+           warning (_("Section .debug_aranges in %s entry at offset %zu "
+                      "padding is not zero, ignoring .debug_aranges."),
+                    objfile_name (objfile), entry_addr - section->buffer);
+           return;
+         }
+
+      for (;;)
+       {
+         if (addr + 2 * address_size > entry_end)
+           {
+             warning (_("Section .debug_aranges in %s entry at offset %zu "
+                        "address list is not properly terminated, "
+                        "ignoring .debug_aranges."),
+                      objfile_name (objfile), entry_addr - section->buffer);
+             return;
+           }
+         ULONGEST start = extract_unsigned_integer (addr, address_size,
+                                                    dwarf5_byte_order);
+         addr += address_size;
+         ULONGEST length = extract_unsigned_integer (addr, address_size,
+                                                     dwarf5_byte_order);
+         addr += address_size;
+         if (start == 0 && length == 0)
+           break;
+         if (start == 0 && !dwarf2_per_objfile->has_section_at_zero)
+           {
+             /* Symbol was eliminated due to a COMDAT group.  */
+             continue;
+           }
+         ULONGEST end = start + length;
+         start = gdbarch_adjust_dwarf2_addr (gdbarch, start + baseaddr);
+         end = gdbarch_adjust_dwarf2_addr (gdbarch, end + baseaddr);
+         addrmap_set_empty (mutable_map, start, end - 1, per_cu);
+       }
+    }
+
+  objfile->psymtabs_addrmap = addrmap_create_fixed (mutable_map,
+                                                   &objfile->objfile_obstack);
+}
+
+/* The hash function for strings in the mapped index.  This is the same as
+   SYMBOL_HASH_NEXT, but we keep a separate copy to maintain control over the
+   implementation.  This is necessary because the hash function is tied to the
    format of the mapped index file.  The hash values do not have to match with
    SYMBOL_HASH_NEXT.
    
@@ -2993,17 +3599,18 @@ mapped_index_string_hash (int index_version, const void *p)
 
 /* 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.  */
+   constant pool and return true.  If NAME cannot be found, return
+   false.  */
 
-static int
+static bool
 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 *);
 
+  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)
@@ -3013,13 +3620,10 @@ find_slot_in_mapped_hash (struct mapped_index *index, const char *name,
 
       if (strchr (name, '(') != NULL)
        {
-         char *without_params = cp_remove_params (name);
+         without_params = cp_remove_params (name);
 
          if (without_params != NULL)
-           {
-             make_cleanup (xfree, without_params);
-             name = without_params;
-           }
+           name = without_params.get ();
        }
     }
 
@@ -3031,31 +3635,27 @@ find_slot_in_mapped_hash (struct mapped_index *index, const char *name,
                                    ? 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);
     }
 }
 
@@ -3166,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
@@ -3202,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
@@ -3249,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;
@@ -3283,13 +3886,10 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
   struct dwarf2_per_cu_data *this_cu = cu->per_cu;  
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct dwarf2_per_cu_data *lh_cu;
-  struct line_header *lh;
   struct attribute *attr;
   int i;
-  const char *name, *comp_dir;
   void **slot;
   struct quick_file_names *qfn;
-  unsigned int line_offset;
 
   gdb_assert (! this_cu->is_debug_types);
 
@@ -3302,21 +3902,22 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
     }
 
   lh_cu = this_cu;
-  lh = NULL;
   slot = NULL;
-  line_offset = 0;
+
+  line_header_up lh;
+  sect_offset line_offset {};
 
   attr = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, cu);
   if (attr)
     {
       struct quick_file_names find_entry;
 
-      line_offset = DW_UNSND (attr);
+      line_offset = (sect_offset) DW_UNSND (attr);
 
       /* We may have already read in this line header (TU line header sharing).
         If we have we're done.  */
       find_entry.hash.dwo_unit = cu->dwo_unit;
-      find_entry.hash.line_offset.sect_off = line_offset;
+      find_entry.hash.line_sect_off = line_offset;
       slot = htab_find_slot (dwarf2_per_objfile->quick_file_names_table,
                             &find_entry, INSERT);
       if (*slot != NULL)
@@ -3335,21 +3936,19 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
 
   qfn = XOBNEW (&objfile->objfile_obstack, struct quick_file_names);
   qfn->hash.dwo_unit = cu->dwo_unit;
-  qfn->hash.line_offset.sect_off = line_offset;
+  qfn->hash.line_sect_off = line_offset;
   gdb_assert (slot != NULL);
   *slot = qfn;
 
-  find_file_and_directory (comp_unit_die, cu, &name, &comp_dir);
+  file_and_directory fnd = find_file_and_directory (comp_unit_die, cu);
 
-  qfn->num_file_names = lh->num_file_names;
+  qfn->num_file_names = lh->file_names.size ();
   qfn->file_names =
-    XOBNEWVEC (&objfile->objfile_obstack, const char *, lh->num_file_names);
-  for (i = 0; i < lh->num_file_names; ++i)
-    qfn->file_names[i] = file_full_name (i + 1, lhcomp_dir);
+    XOBNEWVEC (&objfile->objfile_obstack, const char *, lh->file_names.size ());
+  for (i = 0; i < lh->file_names.size (); ++i)
+    qfn->file_names[i] = file_full_name (i + 1, lh.get (), fnd.comp_dir);
   qfn->real_names = NULL;
 
-  free_line_header (lh);
-
   lh_cu->v.quick->file_names = qfn;
 }
 
@@ -3389,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];
 }
@@ -3445,8 +4044,7 @@ static int
 dw2_map_expand_apply (struct objfile *objfile,
                      struct dwarf2_per_cu_data *per_cu,
                      const char *name, const char *real_path,
-                     int (*callback) (struct symtab *, void *),
-                     void *data)
+                     gdb::function_view<bool (symtab *)> callback)
 {
   struct compunit_symtab *last_made = objfile->compunit_symtabs;
 
@@ -3458,17 +4056,16 @@ dw2_map_expand_apply (struct objfile *objfile,
      all of them.  */
   dw2_instantiate_symtab (per_cu);
 
-  return iterate_over_some_symtabs (name, real_path, callback, data,
-                                   objfile->compunit_symtabs, last_made);
+  return iterate_over_some_symtabs (name, real_path, objfile->compunit_symtabs,
+                                   last_made, callback);
 }
 
 /* Implementation of the map_symtabs_matching_filename method.  */
 
-static int
-dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
-                                  const char *real_path,
-                                  int (*callback) (struct symtab *, void *),
-                                  void *data)
+static bool
+dw2_map_symtabs_matching_filename
+  (struct objfile *objfile, const char *name, const char *real_path,
+   gdb::function_view<bool (symtab *)> callback)
 {
   int i;
   const char *name_basename = lbasename (name);
@@ -3500,8 +4097,8 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
          if (compare_filenames_for_search (this_name, name))
            {
              if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
-                                       callback, data))
-               return 1;
+                                       callback))
+               return true;
              continue;
            }
 
@@ -3515,8 +4112,8 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
          if (compare_filenames_for_search (this_real_name, name))
            {
              if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
-                                       callback, data))
-               return 1;
+                                       callback))
+               return true;
              continue;
            }
 
@@ -3528,15 +4125,15 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
                  && FILENAME_CMP (real_path, this_real_name) == 0)
                {
                  if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
-                                           callback, data))
-                   return 1;
+                                           callback))
+                   return true;
                  continue;
                }
            }
        }
     }
 
-  return 0;
+  return false;
 }
 
 /* Struct used to manage iterating over all CUs looking for a symbol.  */
@@ -3689,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.  */
@@ -3715,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.  */
@@ -3863,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
@@ -3871,351 +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,
-   expand_symtabs_file_matcher_ftype *file_matcher,
-   expand_symtabs_symbol_matcher_ftype *symbol_matcher,
-   expand_symtabs_exp_notify_ftype *expansion_notify,
-   enum search_domain kind,
-   void *data)
-{
-  int i;
-  offset_type iter;
-  struct mapped_index *index;
+/* Symbol name matcher for .gdb_index names.
 
-  dw2_setup (objfile);
+   Symbol names in .gdb_index have a few particularities:
 
-  /* index_table is NULL if OBJF_READNOW.  */
-  if (!dwarf2_per_objfile->index_table)
-    return;
-  index = dwarf2_per_objfile->index_table;
+   - There's no indication of which is the language of each symbol.
 
-  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));
+     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.
 
-      /* The rule is CUs specify all the files, including those used by
-        any TU, so there's no need to scan TUs here.  */
+   - 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.
 
-      for (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;
+     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
+{
+public:
+  /* Prepares the vector of comparison functions for LOOKUP_NAME.  */
+  gdb_index_symbol_name_matcher (const lookup_name_info &lookup_name);
 
-         QUIT;
+  /* Walk all the matcher routines and match SYMBOL_NAME against them.
+     Returns true if any matcher matches.  */
+  bool matches (const char *symbol_name);
 
-         per_cu->v.quick->mark = 0;
+private:
+  /* A reference to the lookup name we're matching against.  */
+  const lookup_name_info &m_lookup_name;
 
-         /* We only need to look at symtabs not already expanded.  */
-         if (per_cu->v.quick->compunit_symtab)
-           continue;
+  /* A vector holding all the different symbol name matchers, for all
+     languages.  */
+  std::vector<symbol_name_matcher_ftype *> m_symbol_name_matcher_funcs;
+};
 
-         file_data = dw2_get_file_names (per_cu);
-         if (file_data == NULL)
-           continue;
+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);
 
-         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;
-           }
+  matchers.push_back (default_symbol_name_matcher);
 
-         for (j = 0; j < file_data->num_file_names; ++j)
-           {
-             const char *this_real_name;
+  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)
+       {
+         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);
+       }
+    }
+}
 
-             if (file_matcher (file_data->file_names[j], data, 0))
-               {
-                 per_cu->v.quick->mark = 1;
-                 break;
-               }
+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;
 
-             /* 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]),
-                                   data, 1))
-               continue;
+  return false;
+}
 
-             this_real_name = dw2_get_real_path (objfile, file_data, j);
-             if (file_matcher (this_real_name, data, 0))
-               {
-                 per_cu->v.quick->mark = 1;
-                 break;
-               }
-           }
+/* 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.  */
 
-         slot = htab_find_slot (per_cu->v.quick->mark
-                                ? visited_found.get ()
-                                : visited_not_found.get (),
-                                file_data, INSERT);
-         *slot = file_data;
-       }
-    }
+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.
 
-  for (iter = 0; iter < index->symbol_table_slots; ++iter)
-    {
-      offset_type idx = 2 * iter;
-      const char *name;
-      offset_type *vec, vec_len, vec_idx;
-      int global_seen = 0;
+     Some examples of this operation:
 
-      QUIT;
+       SEARCH_NAME  => "+1" RESULT
 
-      if (index->symbol_table[idx] == 0 && index->symbol_table[idx + 1] == 0)
-       continue;
+       "abc"              => "abd"
+       "ab\xff"           => "ac"
+       "\xff" "a" "\xff"  => "\xff" "b"
+       "\xff"             => ""
+       "\xff\xff"         => ""
+       ""                 => ""
 
-      name = index->constant_pool + MAYBE_SWAP (index->symbol_table[idx]);
+     Then, with these symbols for example:
 
-      if (! (*symbol_matcher) (name, data))
-       continue;
+      func
+      func1
+      fund
 
-      /* 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);
+     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".
 
-         /* Work around gold/15646.  */
-         if (attrs_valid)
-           {
-             if (!is_static && global_seen)
-               continue;
-             if (!is_static)
-               global_seen = 1;
-           }
+     And with:
 
-         /* 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;
-               }
-           }
+      funcÿ     (Latin1 'ÿ' [0xff])
+      funcÿ1
+      fund
 
-         /* 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;
-           }
+     completing "funcÿ" looks for symbols between "funcÿ" and "fund"
+     (exclusive), which finds "funcÿ" and "funcÿ1", but not "fund".
 
-         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);
+     And with:
 
-             dw2_instantiate_symtab (per_cu);
+      Ã¿Ã¿        (Latin1 'ÿ' [0xff])
+      Ã¿Ã¿1
 
-             if (expansion_notify != NULL
-                 && symtab_was_null
-                 && per_cu->v.quick->compunit_symtab != NULL)
-               {
-                 expansion_notify (per_cu->v.quick->compunit_symtab,
-                                   data);
-               }
-           }
-       }
-    }
+     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;
 }
 
-/* A helper for dw2_find_pc_sect_compunit_symtab which finds the most specific
-   symtab.  */
+/* See declaration.  */
 
-static struct compunit_symtab *
-recursively_find_pc_sect_compunit_symtab (struct compunit_symtab *cust,
-                                         CORE_ADDR pc)
+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
 {
-  int i;
+  auto *name_cmp
+    = this->name_components_casing == case_sensitive_on ? strcmp : strcasecmp;
 
-  if (COMPUNIT_BLOCKVECTOR (cust) != NULL
-      && blockvector_contains_pc (COMPUNIT_BLOCKVECTOR (cust), pc))
-    return cust;
+  const char *cplus
+    = lookup_name_without_params.cplus ().lookup_name ().c_str ();
 
-  if (cust->includes == NULL)
-    return NULL;
+  /* 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;
+    };
 
-  for (i = 0; cust->includes[i]; ++i)
+  /* Comparison function object for upper_bound that matches against a
+     given symbol name.  */
+  auto lookup_compare_upper = [&] (const char *name,
+                                  const name_component &elem)
     {
-      struct compunit_symtab *s = cust->includes[i];
+      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;
+    };
 
-      s = recursively_find_pc_sect_compunit_symtab (s, pc);
-      if (s != NULL)
-       return s;
-    }
+  auto begin = this->name_components.begin ();
+  auto end = this->name_components.end ();
 
-  return NULL;
+  /* 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);
+    } ();
+
+  /* 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);
+    } ();
+
+  return {lower, upper};
 }
 
-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)
+/* See declaration.  */
+
+void
+mapped_index_base::build_name_components ()
 {
-  struct dwarf2_per_cu_data *data;
-  struct compunit_symtab *result;
+  if (!this->name_components.empty ())
+    return;
 
-  dw2_setup (objfile);
+  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;
 
-  if (!objfile->psymtabs_addrmap)
-    return NULL;
+      const char *name = this->symbol_name_at (idx);
 
-  data = (struct dwarf2_per_cu_data *) addrmap_find (objfile->psymtabs_addrmap,
-                                                    pc);
-  if (!data)
-    return NULL;
+      /* 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});
+    }
 
-  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));
+  /* Sort name_components elements by name.  */
+  auto name_comp_compare = [&] (const name_component &left,
+                               const name_component &right)
+    {
+      const char *left_qualified = this->symbol_name_at (left.idx);
+      const char *right_qualified = this->symbol_name_at (right.idx);
 
-  result
-    = recursively_find_pc_sect_compunit_symtab (dw2_instantiate_symtab (data),
-                                               pc);
-  gdb_assert (result != NULL);
-  return result;
+      const char *left_name = left_qualified + left.name_offset;
+      const char *right_name = right_qualified + right.name_offset;
+
+      return name_cmp (left_name, right_name) < 0;
+    };
+
+  std::sort (this->name_components.begin (),
+            this->name_components.end (),
+            name_comp_compare);
 }
 
+/* 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.  */
+
 static void
-dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
-                         void *data, int need_fullname)
+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)
 {
-  int i;
-  htab_up visited (htab_create_alloc (10, htab_hash_pointer, htab_eq_pointer,
-                                     NULL, xcalloc, xfree));
-
-  dw2_setup (objfile);
+  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);
 
-  /* 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.  */
+  /* Build the symbol name component sorted vector, if we haven't
+     yet.  */
+  index.build_name_components ();
 
-  for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
-    {
-      struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
+  auto bounds = index.find_name_components_bounds (lookup_name_without_params);
 
-      if (per_cu->v.quick->compunit_symtab)
-       {
-         void **slot = htab_find_slot (visited.get (),
-                                       per_cu->v.quick->file_names,
-                                       INSERT);
+  /* Now for each symbol name in range, check to see if we have a name
+     match, and if so, call the MATCH_CALLBACK callback.  */
 
-         *slot = per_cu->v.quick->file_names;
-       }
-    }
+  /* 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));
 
-  for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+  for (; bounds.first != bounds.second; ++bounds.first)
     {
-      int j;
-      struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
-      struct quick_file_names *file_data;
-      void **slot;
+      const char *qualified = index.symbol_name_at (bounds.first->idx);
 
-      /* We only need to look at symtabs not already expanded.  */
-      if (per_cu->v.quick->compunit_symtab)
+      if (!lookup_name_matcher.matches (qualified)
+         || (symbol_matcher != NULL && !symbol_matcher (qualified)))
        continue;
 
-      file_data = dw2_get_file_names (per_cu);
-      if (file_data == NULL)
-       continue;
+      matches.push_back (bounds.first->idx);
+    }
 
-      slot = htab_find_slot (visited.get (), file_data, INSERT);
-      if (*slot)
-       {
-         /* Already visited.  */
+  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), "");
+}
+
+#if GDB_SELF_TEST
+
+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
+{
+public:
+  mock_mapped_index (gdb::array_view<const char *> symbols)
+    : m_symbol_table (symbols)
+  {}
+
+  DISABLE_COPY_AND_ASSIGN (mock_mapped_index);
+
+  /* Return the number of names in the symbol table.  */
+  virtual size_t symbol_name_count () const
+  {
+    return m_symbol_table.size ();
+  }
+
+  /* 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];
+  }
+
+private:
+  gdb::array_view<const char *> m_symbol_table;
+};
+
+/* Convenience function that converts a NULL pointer to a "<null>"
+   string, to pass to print routines.  */
+
+static const char *
+string_or_null (const char *str)
+{
+  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;
        }
-      *slot = file_data;
 
-      for (j = 0; j < file_data->num_file_names; ++j)
+      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);
+
+  /* index_table is NULL if OBJF_READNOW.  */
+  if (!dwarf2_per_objfile->index_table)
+    return;
+
+  dw_expand_symtabs_matching_file_matcher (file_matcher);
+
+  mapped_index &index = *dwarf2_per_objfile->index_table;
+
+  dw2_expand_symtabs_matching_symbol (index, lookup_name,
+                                     symbol_matcher,
+                                     kind, [&] (offset_type idx)
+    {
+      dw2_expand_marked_cus (index, idx, objfile, file_matcher,
+                            expansion_notify, kind);
+    });
+}
+
+/* A helper for dw2_find_pc_sect_compunit_symtab which finds the most specific
+   symtab.  */
+
+static struct compunit_symtab *
+recursively_find_pc_sect_compunit_symtab (struct compunit_symtab *cust,
+                                         CORE_ADDR pc)
+{
+  int i;
+
+  if (COMPUNIT_BLOCKVECTOR (cust) != NULL
+      && blockvector_contains_pc (COMPUNIT_BLOCKVECTOR (cust), pc))
+    return cust;
+
+  if (cust->includes == NULL)
+    return NULL;
+
+  for (i = 0; cust->includes[i]; ++i)
+    {
+      struct compunit_symtab *s = cust->includes[i];
+
+      s = recursively_find_pc_sect_compunit_symtab (s, pc);
+      if (s != NULL)
+       return s;
+    }
+
+  return NULL;
+}
+
+static struct compunit_symtab *
+dw2_find_pc_sect_compunit_symtab (struct objfile *objfile,
+                                 struct bound_minimal_symbol msymbol,
+                                 CORE_ADDR pc,
+                                 struct obj_section *section,
+                                 int warn_if_readin)
+{
+  struct dwarf2_per_cu_data *data;
+  struct compunit_symtab *result;
+
+  dw2_setup (objfile);
+
+  if (!objfile->psymtabs_addrmap)
+    return NULL;
+
+  data = (struct dwarf2_per_cu_data *) addrmap_find (objfile->psymtabs_addrmap,
+                                                    pc);
+  if (!data)
+    return NULL;
+
+  if (warn_if_readin && data->v.quick->compunit_symtab)
+    warning (_("(Internal error: pc %s in read in CU, but not in symtab.)"),
+            paddress (get_objfile_arch (objfile), pc));
+
+  result
+    = recursively_find_pc_sect_compunit_symtab (dw2_instantiate_symtab (data),
+                                               pc);
+  gdb_assert (result != NULL);
+  return result;
+}
+
+static void
+dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
+                         void *data, int need_fullname)
+{
+  dw2_setup (objfile);
+
+  if (!dwarf2_per_objfile->filenames_cache)
+    {
+      dwarf2_per_objfile->filenames_cache.emplace ();
+
+      htab_up visited (htab_create_alloc (10,
+                                         htab_hash_pointer, htab_eq_pointer,
+                                         NULL, xcalloc, xfree));
+
+      /* The rule is CUs specify all the files, including those used
+        by any TU, so there's no need to scan TUs here.  We can
+        ignore file names coming from already-expanded CUs.  */
+
+      for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+       {
+         struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
+
+         if (per_cu->v.quick->compunit_symtab)
+           {
+             void **slot = htab_find_slot (visited.get (),
+                                           per_cu->v.quick->file_names,
+                                           INSERT);
+
+             *slot = per_cu->v.quick->file_names;
+           }
+       }
+
+      for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+       {
+         struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+         struct quick_file_names *file_data;
+         void **slot;
+
+         /* We only need to look at symtabs not already expanded.  */
+         if (per_cu->v.quick->compunit_symtab)
+           continue;
+
+         file_data = dw2_get_file_names (per_cu);
+         if (file_data == NULL)
+           continue;
+
+         slot = htab_find_slot (visited.get (), file_data, INSERT);
+         if (*slot)
+           {
+             /* Already visited.  */
+             continue;
+           }
+         *slot = file_data;
+
+         for (int j = 0; j < file_data->num_file_names; ++j)
+           {
+             const char *filename = file_data->file_names[j];
+             dwarf2_per_objfile->filenames_cache->seen (filename);
+           }
+       }
+    }
+
+  dwarf2_per_objfile->filenames_cache->traverse ([&] (const char *filename)
+    {
+      gdb::unique_xmalloc_ptr<char> this_real_name;
+
+      if (need_fullname)
+       this_real_name = gdb_realpath (filename);
+      (*fun) (filename, this_real_name.get (), data);
+    });
+}
+
+static int
+dw2_has_symbols (struct objfile *objfile)
+{
+  return 1;
+}
+
+const struct quick_symbol_functions dwarf2_gdb_index_functions =
+{
+  dw2_has_symbols,
+  dw2_find_last_source_symtab,
+  dw2_forget_cached_source_info,
+  dw2_map_symtabs_matching_filename,
+  dw2_lookup_symbol,
+  dw2_print_stats,
+  dw2_dump,
+  dw2_relocate,
+  dw2_expand_symtabs_for_function,
+  dw2_expand_all_symtabs,
+  dw2_expand_symtabs_with_fullname,
+  dw2_map_matching_symbols,
+  dw2_expand_symtabs_matching,
+  dw2_find_pc_sect_compunit_symtab,
+  NULL,
+  dw2_map_symbol_filenames
+};
+
+/* DWARF-5 debug_names reader.  */
+
+/* DWARF-5 augmentation string for GDB's DW_IDX_GNU_* extension.  */
+static const gdb_byte dwarf5_augmentation[] = { 'G', 'D', 'B', 0 };
+
+/* A helper function that reads the .debug_names section in SECTION
+   and fills in MAP.  FILENAME is the name of the file containing the
+   section; it is used for error reporting.
+
+   Returns true if all went well, false otherwise.  */
+
+static bool
+read_debug_names_from_section (struct objfile *objfile,
+                              const char *filename,
+                              struct dwarf2_section_info *section,
+                              mapped_debug_names &map)
+{
+  if (dwarf2_section_empty_p (section))
+    return false;
+
+  /* Older elfutils strip versions could keep the section in the main
+     executable while splitting it for the separate debug info file.  */
+  if ((get_section_flags (section) & SEC_HAS_CONTENTS) == 0)
+    return false;
+
+  dwarf2_read_section (objfile, section);
+
+  map.dwarf5_byte_order = gdbarch_byte_order (get_objfile_arch (objfile));
+
+  const gdb_byte *addr = section->buffer;
+
+  bfd *const abfd = get_section_bfd_owner (section);
+
+  unsigned int bytes_read;
+  LONGEST length = read_initial_length (abfd, addr, &bytes_read);
+  addr += bytes_read;
+
+  map.dwarf5_is_dwarf64 = bytes_read != 4;
+  map.offset_size = map.dwarf5_is_dwarf64 ? 8 : 4;
+  if (bytes_read + length != section->size)
+    {
+      /* There may be multiple per-CU indices.  */
+      warning (_("Section .debug_names in %s length %s does not match "
+                "section length %s, ignoring .debug_names."),
+              filename, plongest (bytes_read + length),
+              pulongest (section->size));
+      return false;
+    }
+
+  /* The version number.  */
+  uint16_t version = read_2_bytes (abfd, addr);
+  addr += 2;
+  if (version != 5)
+    {
+      warning (_("Section .debug_names in %s has unsupported version %d, "
+                "ignoring .debug_names."),
+              filename, version);
+      return false;
+    }
+
+  /* Padding.  */
+  uint16_t padding = read_2_bytes (abfd, addr);
+  addr += 2;
+  if (padding != 0)
+    {
+      warning (_("Section .debug_names in %s has unsupported padding %d, "
+                "ignoring .debug_names."),
+              filename, padding);
+      return false;
+    }
+
+  /* comp_unit_count - The number of CUs in the CU list.  */
+  map.cu_count = read_4_bytes (abfd, addr);
+  addr += 4;
+
+  /* local_type_unit_count - The number of TUs in the local TU
+     list.  */
+  map.tu_count = read_4_bytes (abfd, addr);
+  addr += 4;
+
+  /* foreign_type_unit_count - The number of TUs in the foreign TU
+     list.  */
+  uint32_t foreign_tu_count = read_4_bytes (abfd, addr);
+  addr += 4;
+  if (foreign_tu_count != 0)
+    {
+      warning (_("Section .debug_names in %s has unsupported %lu foreign TUs, "
+                "ignoring .debug_names."),
+              filename, static_cast<unsigned long> (foreign_tu_count));
+      return false;
+    }
+
+  /* bucket_count - The number of hash buckets in the hash lookup
+     table.  */
+  map.bucket_count = read_4_bytes (abfd, addr);
+  addr += 4;
+
+  /* name_count - The number of unique names in the index.  */
+  map.name_count = read_4_bytes (abfd, addr);
+  addr += 4;
+
+  /* abbrev_table_size - The size in bytes of the abbreviations
+     table.  */
+  uint32_t abbrev_table_size = read_4_bytes (abfd, addr);
+  addr += 4;
+
+  /* augmentation_string_size - The size in bytes of the augmentation
+     string.  This value is rounded up to a multiple of 4.  */
+  uint32_t augmentation_string_size = read_4_bytes (abfd, addr);
+  addr += 4;
+  map.augmentation_is_gdb = ((augmentation_string_size
+                             == sizeof (dwarf5_augmentation))
+                            && memcmp (addr, dwarf5_augmentation,
+                                       sizeof (dwarf5_augmentation)) == 0);
+  augmentation_string_size += (-augmentation_string_size) & 3;
+  addr += augmentation_string_size;
+
+  /* List of CUs */
+  map.cu_table_reordered = addr;
+  addr += map.cu_count * map.offset_size;
+
+  /* List of Local TUs */
+  map.tu_table_reordered = addr;
+  addr += map.tu_count * map.offset_size;
+
+  /* Hash Lookup Table */
+  map.bucket_table_reordered = reinterpret_cast<const uint32_t *> (addr);
+  addr += map.bucket_count * 4;
+  map.hash_table_reordered = reinterpret_cast<const uint32_t *> (addr);
+  addr += map.name_count * 4;
+
+  /* Name Table */
+  map.name_table_string_offs_reordered = addr;
+  addr += map.name_count * map.offset_size;
+  map.name_table_entry_offs_reordered = addr;
+  addr += map.name_count * map.offset_size;
+
+  const gdb_byte *abbrev_table_start = addr;
+  for (;;)
+    {
+      unsigned int bytes_read;
+      const ULONGEST index_num = read_unsigned_leb128 (abfd, addr, &bytes_read);
+      addr += bytes_read;
+      if (index_num == 0)
+       break;
+
+      const auto insertpair
+       = map.abbrev_map.emplace (index_num, mapped_debug_names::index_val ());
+      if (!insertpair.second)
+       {
+         warning (_("Section .debug_names in %s has duplicate index %s, "
+                    "ignoring .debug_names."),
+                  filename, pulongest (index_num));
+         return false;
+       }
+      mapped_debug_names::index_val &indexval = insertpair.first->second;
+      indexval.dwarf_tag = read_unsigned_leb128 (abfd, addr, &bytes_read);
+      addr += bytes_read;
+
+      for (;;)
+       {
+         mapped_debug_names::index_val::attr attr;
+         attr.dw_idx = read_unsigned_leb128 (abfd, addr, &bytes_read);
+         addr += bytes_read;
+         attr.form = read_unsigned_leb128 (abfd, addr, &bytes_read);
+         addr += bytes_read;
+         if (attr.form == DW_FORM_implicit_const)
+           {
+             attr.implicit_const = read_signed_leb128 (abfd, addr,
+                                                       &bytes_read);
+             addr += bytes_read;
+           }
+         if (attr.dw_idx == 0 && attr.form == 0)
+           break;
+         indexval.attr_vec.push_back (std::move (attr));
+       }
+    }
+  if (addr != abbrev_table_start + abbrev_table_size)
+    {
+      warning (_("Section .debug_names in %s has abbreviation_table "
+                 "of size %zu vs. written as %u, ignoring .debug_names."),
+              filename, addr - abbrev_table_start, abbrev_table_size);
+      return false;
+    }
+  map.entry_pool = addr;
+
+  return true;
+}
+
+/* A helper for create_cus_from_debug_names that handles the MAP's CU
+   list.  */
+
+static void
+create_cus_from_debug_names_list (struct objfile *objfile,
+                                 const mapped_debug_names &map,
+                                 dwarf2_section_info &section,
+                                 bool is_dwz, int base_offset)
+{
+  sect_offset sect_off_prev;
+  for (uint32_t i = 0; i <= map.cu_count; ++i)
+    {
+      sect_offset sect_off_next;
+      if (i < map.cu_count)
+       {
+         sect_off_next
+           = (sect_offset) (extract_unsigned_integer
+                            (map.cu_table_reordered + i * map.offset_size,
+                             map.offset_size,
+                             map.dwarf5_byte_order));
+       }
+      else
+       sect_off_next = (sect_offset) section.size;
+      if (i >= 1)
+       {
+         const ULONGEST length = sect_off_next - sect_off_prev;
+         dwarf2_per_objfile->all_comp_units[base_offset + (i - 1)]
+           = create_cu_from_index_list (objfile, &section, is_dwz,
+                                        sect_off_prev, length);
+       }
+      sect_off_prev = sect_off_next;
+    }
+}
+
+/* Read the CU list from the mapped index, and use it to create all
+   the CU objects for this objfile.  */
+
+static void
+create_cus_from_debug_names (struct objfile *objfile,
+                            const mapped_debug_names &map,
+                            const mapped_debug_names &dwz_map)
+{
+
+  dwarf2_per_objfile->n_comp_units = map.cu_count + dwz_map.cu_count;
+  dwarf2_per_objfile->all_comp_units
+    = XOBNEWVEC (&objfile->objfile_obstack, struct dwarf2_per_cu_data *,
+                dwarf2_per_objfile->n_comp_units);
+
+  create_cus_from_debug_names_list (objfile, map, dwarf2_per_objfile->info,
+                                   false /* is_dwz */,
+                                   0 /* base_offset */);
+
+  if (dwz_map.cu_count == 0)
+    return;
+
+  dwz_file *dwz = dwarf2_get_dwz_file ();
+  create_cus_from_debug_names_list (objfile, dwz_map, dwz->info,
+                                   true /* is_dwz */,
+                                   map.cu_count /* base_offset */);
+}
+
+/* Read .debug_names.  If everything went ok, initialize the "quick"
+   elements of all the CUs and return true.  Otherwise, return false.  */
+
+static bool
+dwarf2_read_debug_names (struct objfile *objfile)
+{
+  mapped_debug_names local_map, dwz_map;
+
+  if (!read_debug_names_from_section (objfile, objfile_name (objfile),
+                                     &dwarf2_per_objfile->debug_names,
+                                     local_map))
+    return false;
+
+  /* Don't use the index if it's empty.  */
+  if (local_map.name_count == 0)
+    return false;
+
+  /* If there is a .dwz file, read it so we can get its CU list as
+     well.  */
+  dwz_file *dwz = dwarf2_get_dwz_file ();
+  if (dwz != NULL)
+    {
+      if (!read_debug_names_from_section (objfile,
+                                         bfd_get_filename (dwz->dwz_bfd),
+                                         &dwz->debug_names, dwz_map))
+       {
+         warning (_("could not read '.debug_names' section from %s; skipping"),
+                  bfd_get_filename (dwz->dwz_bfd));
+         return false;
+       }
+    }
+
+  create_cus_from_debug_names (objfile, local_map, dwz_map);
+
+  if (local_map.tu_count != 0)
+    {
+      /* We can only handle a single .debug_types when we have an
+        index.  */
+      if (VEC_length (dwarf2_section_info_def, dwarf2_per_objfile->types) != 1)
+       return false;
+
+      dwarf2_section_info *section = VEC_index (dwarf2_section_info_def,
+                                               dwarf2_per_objfile->types, 0);
+
+      create_signatured_type_table_from_debug_names
+       (objfile, local_map, section, &dwarf2_per_objfile->abbrev);
+    }
+
+  create_addrmap_from_aranges (objfile, &dwarf2_per_objfile->debug_aranges);
+
+  dwarf2_per_objfile->debug_names_table.reset (new mapped_debug_names);
+  *dwarf2_per_objfile->debug_names_table = std::move (local_map);
+  dwarf2_per_objfile->using_index = 1;
+  dwarf2_per_objfile->quick_file_names_table =
+    create_quick_file_names_table (dwarf2_per_objfile->n_comp_units);
+
+  return true;
+}
+
+/* Symbol name hashing function as specified by DWARF-5.  */
+
+static uint32_t
+dwarf5_djb_hash (const char *str_)
+{
+  const unsigned char *str = (const unsigned char *) str_;
+
+  /* Note: tolower here ignores UTF-8, which isn't fully compliant.
+     See http://dwarfstd.org/ShowIssue.php?issue=161027.1.  */
+
+  uint32_t hash = 5381;
+  while (int c = *str++)
+    hash = hash * 33 + tolower (c);
+  return hash;
+}
+
+/* Type used to manage iterating over all CUs looking for a symbol for
+   .debug_names.  */
+
+class dw2_debug_names_iterator
+{
+public:
+  /* If WANT_SPECIFIC_BLOCK is true, only look for symbols in block
+     BLOCK_INDEX.  Otherwise BLOCK_INDEX is ignored.  */
+  dw2_debug_names_iterator (const mapped_debug_names &map,
+                           bool want_specific_block,
+                           block_enum block_index, domain_enum domain,
+                           const char *name)
+    : m_map (map), m_want_specific_block (want_specific_block),
+      m_block_index (block_index), m_domain (domain),
+      m_addr (find_vec_in_debug_names (map, name))
+  {}
+
+  dw2_debug_names_iterator (const mapped_debug_names &map,
+                           search_domain search, uint32_t namei)
+    : m_map (map),
+      m_search (search),
+      m_addr (find_vec_in_debug_names (map, namei))
+  {}
+
+  /* Return the next matching CU or NULL if there are no more.  */
+  dwarf2_per_cu_data *next ();
+
+private:
+  static const gdb_byte *find_vec_in_debug_names (const mapped_debug_names &map,
+                                                 const char *name);
+  static const gdb_byte *find_vec_in_debug_names (const mapped_debug_names &map,
+                                                 uint32_t namei);
+
+  /* The internalized form of .debug_names.  */
+  const mapped_debug_names &m_map;
+
+  /* If true, only look for symbols that match BLOCK_INDEX.  */
+  const bool m_want_specific_block = false;
+
+  /* One of GLOBAL_BLOCK or STATIC_BLOCK.
+     Unused if !WANT_SPECIFIC_BLOCK - FIRST_LOCAL_BLOCK is an invalid
+     value.  */
+  const block_enum m_block_index = FIRST_LOCAL_BLOCK;
+
+  /* The kind of symbol we're looking for.  */
+  const domain_enum m_domain = UNDEF_DOMAIN;
+  const search_domain m_search = ALL_DOMAIN;
+
+  /* The list of CUs from the index entry of the symbol, or NULL if
+     not found.  */
+  const gdb_byte *m_addr;
+};
+
+const char *
+mapped_debug_names::namei_to_name (uint32_t namei) const
+{
+  const ULONGEST namei_string_offs
+    = extract_unsigned_integer ((name_table_string_offs_reordered
+                                + namei * offset_size),
+                               offset_size,
+                               dwarf5_byte_order);
+  return read_indirect_string_at_offset
+    (dwarf2_per_objfile->objfile->obfd, namei_string_offs);
+}
+
+/* Find a slot in .debug_names for the object named NAME.  If NAME is
+   found, return pointer to its pool data.  If NAME cannot be found,
+   return NULL.  */
+
+const gdb_byte *
+dw2_debug_names_iterator::find_vec_in_debug_names
+  (const mapped_debug_names &map, const char *name)
+{
+  int (*cmp) (const char *, const char *);
+
+  if (current_language->la_language == language_cplus
+      || current_language->la_language == language_fortran
+      || current_language->la_language == language_d)
+    {
+      /* NAME is already canonical.  Drop any qualifiers as
+        .debug_names does not contain any.  */
+
+      if (strchr (name, '(') != NULL)
+       {
+         gdb::unique_xmalloc_ptr<char> without_params
+           = cp_remove_params (name);
+
+         if (without_params != NULL)
+           {
+             name = without_params.get();
+           }
+       }
+    }
+
+  cmp = (case_sensitivity == case_sensitive_on ? strcmp : strcasecmp);
+
+  const uint32_t full_hash = dwarf5_djb_hash (name);
+  uint32_t namei
+    = extract_unsigned_integer (reinterpret_cast<const gdb_byte *>
+                               (map.bucket_table_reordered
+                                + (full_hash % map.bucket_count)), 4,
+                               map.dwarf5_byte_order);
+  if (namei == 0)
+    return NULL;
+  --namei;
+  if (namei >= map.name_count)
+    {
+      complaint (&symfile_complaints,
+                _("Wrong .debug_names with name index %u but name_count=%u "
+                  "[in module %s]"),
+                namei, map.name_count,
+                objfile_name (dwarf2_per_objfile->objfile));
+      return NULL;
+    }
+
+  for (;;)
+    {
+      const uint32_t namei_full_hash
+       = extract_unsigned_integer (reinterpret_cast<const gdb_byte *>
+                                   (map.hash_table_reordered + namei), 4,
+                                   map.dwarf5_byte_order);
+      if (full_hash % map.bucket_count != namei_full_hash % map.bucket_count)
+       return NULL;
+
+      if (full_hash == namei_full_hash)
+       {
+         const char *const namei_string = map.namei_to_name (namei);
+
+#if 0 /* An expensive sanity check.  */
+         if (namei_full_hash != dwarf5_djb_hash (namei_string))
+           {
+             complaint (&symfile_complaints,
+                        _("Wrong .debug_names hash for string at index %u "
+                          "[in module %s]"),
+                        namei, objfile_name (dwarf2_per_objfile->objfile));
+             return NULL;
+           }
+#endif
+
+         if (cmp (namei_string, name) == 0)
+           {
+             const ULONGEST namei_entry_offs
+               = extract_unsigned_integer ((map.name_table_entry_offs_reordered
+                                            + namei * map.offset_size),
+                                           map.offset_size, map.dwarf5_byte_order);
+             return map.entry_pool + namei_entry_offs;
+           }
+       }
+
+      ++namei;
+      if (namei >= map.name_count)
+       return NULL;
+    }
+}
+
+const gdb_byte *
+dw2_debug_names_iterator::find_vec_in_debug_names
+  (const mapped_debug_names &map, uint32_t namei)
+{
+  if (namei >= map.name_count)
+    {
+      complaint (&symfile_complaints,
+                _("Wrong .debug_names with name index %u but name_count=%u "
+                  "[in module %s]"),
+                namei, map.name_count,
+                objfile_name (dwarf2_per_objfile->objfile));
+      return NULL;
+    }
+
+  const ULONGEST namei_entry_offs
+    = extract_unsigned_integer ((map.name_table_entry_offs_reordered
+                                + namei * map.offset_size),
+                               map.offset_size, map.dwarf5_byte_order);
+  return map.entry_pool + namei_entry_offs;
+}
+
+/* See dw2_debug_names_iterator.  */
+
+dwarf2_per_cu_data *
+dw2_debug_names_iterator::next ()
+{
+  if (m_addr == NULL)
+    return NULL;
+
+  bfd *const abfd = dwarf2_per_objfile->objfile->obfd;
+
+ again:
+
+  unsigned int bytes_read;
+  const ULONGEST abbrev = read_unsigned_leb128 (abfd, m_addr, &bytes_read);
+  m_addr += bytes_read;
+  if (abbrev == 0)
+    return NULL;
+
+  const auto indexval_it = m_map.abbrev_map.find (abbrev);
+  if (indexval_it == m_map.abbrev_map.cend ())
+    {
+      complaint (&symfile_complaints,
+                _("Wrong .debug_names undefined abbrev code %s "
+                  "[in module %s]"),
+                pulongest (abbrev), objfile_name (dwarf2_per_objfile->objfile));
+      return NULL;
+    }
+  const mapped_debug_names::index_val &indexval = indexval_it->second;
+  bool have_is_static = false;
+  bool is_static;
+  dwarf2_per_cu_data *per_cu = NULL;
+  for (const mapped_debug_names::index_val::attr &attr : indexval.attr_vec)
+    {
+      ULONGEST ull;
+      switch (attr.form)
+       {
+       case DW_FORM_implicit_const:
+         ull = attr.implicit_const;
+         break;
+       case DW_FORM_flag_present:
+         ull = 1;
+         break;
+       case DW_FORM_udata:
+         ull = read_unsigned_leb128 (abfd, m_addr, &bytes_read);
+         m_addr += bytes_read;
+         break;
+       default:
+         complaint (&symfile_complaints,
+                    _("Unsupported .debug_names form %s [in module %s]"),
+                    dwarf_form_name (attr.form),
+                    objfile_name (dwarf2_per_objfile->objfile));
+         return NULL;
+       }
+      switch (attr.dw_idx)
+       {
+       case DW_IDX_compile_unit:
+         /* Don't crash on bad data.  */
+         if (ull >= dwarf2_per_objfile->n_comp_units)
+           {
+             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;
+       }
+    }
+
+  /* Skip if already read in.  */
+  if (per_cu->v.quick->compunit_symtab)
+    goto again;
+
+  /* Check static vs global.  */
+  if (have_is_static)
+    {
+      const bool want_static = m_block_index != GLOBAL_BLOCK;
+      if (m_want_specific_block && want_static != is_static)
+       goto again;
+    }
+
+  /* Match dw2_symtab_iter_next, symbol_kind
+     and debug_names::psymbol_tag.  */
+  switch (m_domain)
+    {
+    case VAR_DOMAIN:
+      switch (indexval.dwarf_tag)
        {
-         const char *this_real_name;
+       case DW_TAG_variable:
+       case DW_TAG_subprogram:
+       /* Some types are also in VAR_DOMAIN.  */
+       case DW_TAG_typedef:
+       case DW_TAG_structure_type:
+         break;
+       default:
+         goto again;
+       }
+      break;
+    case STRUCT_DOMAIN:
+      switch (indexval.dwarf_tag)
+       {
+       case DW_TAG_typedef:
+       case DW_TAG_structure_type:
+         break;
+       default:
+         goto again;
+       }
+      break;
+    case LABEL_DOMAIN:
+      switch (indexval.dwarf_tag)
+       {
+       case 0:
+       case DW_TAG_variable:
+         break;
+       default:
+         goto again;
+       }
+      break;
+    default:
+      break;
+    }
 
-         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);
+  /* 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;
     }
+
+  return per_cu;
 }
 
-static int
-dw2_has_symbols (struct objfile *objfile)
+static struct compunit_symtab *
+dw2_debug_names_lookup_symbol (struct objfile *objfile, int block_index_int,
+                              const char *name, domain_enum domain)
 {
-  return 1;
+  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)
+    {
+      /* index is NULL if OBJF_READNOW.  */
+      return NULL;
+    }
+  const auto &map = *mapp;
+
+  dw2_debug_names_iterator iter (map, true /* want_specific_block */,
+                                block_index, domain, name);
+
+  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);
+
+      sym = block_find_symbol (block, name, domain,
+                              block_find_non_opaque_type_preferred,
+                              &with_opaque);
+
+      /* 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 (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;
 }
 
-const struct quick_symbol_functions dwarf2_gdb_index_functions =
+/* This dumps minimal information about .debug_names.  It is called
+   via "mt print objfiles".  The gdb.dwarf2/gdb-index.exp testcase
+   uses this to verify that .debug_names has been loaded.  */
+
+static void
+dw2_debug_names_dump (struct objfile *objfile)
+{
+  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");
+}
+
+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
@@ -4243,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
@@ -4260,20 +6521,18 @@ 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
     {
       /* This isn't really ideal: all the data we allocate on the
         objfile's obstack is still uselessly kept around.  However,
         freeing it seems unsafe.  */
-      struct cleanup *cleanups = make_cleanup_discard_psymtabs (objfile);
-
+      psymtab_discarder psymtabs (objfile);
       dwarf2_build_psymtabs_hard (objfile);
-      discard_cleanups (cleanups);
+      psymtabs.keep ();
     }
   CATCH (except, RETURN_MASK_ERROR)
     {
@@ -4290,15 +6549,15 @@ get_cu_length (const struct comp_unit_head *header)
   return header->initial_length_size + header->length;
 }
 
-/* Return TRUE if OFFSET is within CU_HEADER.  */
+/* Return TRUE if SECT_OFF is within CU_HEADER.  */
 
-static inline int
-offset_in_cu_p (const struct comp_unit_head *cu_header, sect_offset offset)
+static inline bool
+offset_in_cu_p (const comp_unit_head *cu_header, sect_offset sect_off)
 {
-  sect_offset bottom = { cu_header->offset.sect_off };
-  sect_offset top = { cu_header->offset.sect_off + get_cu_length (cu_header) };
+  sect_offset bottom = cu_header->sect_off;
+  sect_offset top = cu_header->sect_off + get_cu_length (cu_header);
 
-  return (offset.sect_off >= bottom.sect_off && offset.sect_off < top.sect_off);
+  return sect_off >= bottom && sect_off < top;
 }
 
 /* Find the base address of the compilation unit for range lists and
@@ -4333,15 +6592,20 @@ dwarf2_find_base_address (struct die_info *die, struct dwarf2_cu *cu)
 }
 
 /* Read in the comp unit header information from the debug_info at info_ptr.
+   Use rcuh_kind::COMPILE as the default type if not known by the caller.
    NOTE: This leaves members offset, first_die_offset to be filled in
    by the caller.  */
 
 static const gdb_byte *
 read_comp_unit_head (struct comp_unit_head *cu_header,
-                    const gdb_byte *info_ptr, bfd *abfd)
+                    const gdb_byte *info_ptr,
+                    struct dwarf2_section_info *section,
+                    rcuh_kind section_kind)
 {
   int signed_addr;
   unsigned int bytes_read;
+  const char *filename = get_section_file_name (section);
+  bfd *abfd = get_section_bfd_owner (section);
 
   cu_header->length = read_initial_length (abfd, info_ptr, &bytes_read);
   cu_header->initial_length_size = bytes_read;
@@ -4349,17 +6613,75 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
   info_ptr += bytes_read;
   cu_header->version = read_2_bytes (abfd, info_ptr);
   info_ptr += 2;
-  cu_header->abbrev_offset.sect_off = read_offset (abfd, info_ptr, cu_header,
-                                            &bytes_read);
+  if (cu_header->version < 5)
+    switch (section_kind)
+      {
+      case rcuh_kind::COMPILE:
+       cu_header->unit_type = DW_UT_compile;
+       break;
+      case rcuh_kind::TYPE:
+       cu_header->unit_type = DW_UT_type;
+       break;
+      default:
+       internal_error (__FILE__, __LINE__,
+                       _("read_comp_unit_head: invalid section_kind"));
+      }
+  else
+    {
+      cu_header->unit_type = static_cast<enum dwarf_unit_type>
+                                                (read_1_byte (abfd, info_ptr));
+      info_ptr += 1;
+      switch (cu_header->unit_type)
+       {
+       case DW_UT_compile:
+         if (section_kind != rcuh_kind::COMPILE)
+           error (_("Dwarf Error: wrong unit_type in compilation unit header "
+                  "(is DW_UT_compile, should be DW_UT_type) [in module %s]"),
+                  filename);
+         break;
+       case DW_UT_type:
+         section_kind = rcuh_kind::TYPE;
+         break;
+       default:
+         error (_("Dwarf Error: wrong unit_type in compilation unit header "
+                "(is %d, should be %d or %d) [in module %s]"),
+                cu_header->unit_type, DW_UT_compile, DW_UT_type, filename);
+       }
+
+      cu_header->addr_size = read_1_byte (abfd, info_ptr);
+      info_ptr += 1;
+    }
+  cu_header->abbrev_sect_off = (sect_offset) read_offset (abfd, info_ptr,
+                                                         cu_header,
+                                                         &bytes_read);
   info_ptr += bytes_read;
-  cu_header->addr_size = read_1_byte (abfd, info_ptr);
-  info_ptr += 1;
+  if (cu_header->version < 5)
+    {
+      cu_header->addr_size = read_1_byte (abfd, info_ptr);
+      info_ptr += 1;
+    }
   signed_addr = bfd_get_sign_extend_vma (abfd);
   if (signed_addr < 0)
     internal_error (__FILE__, __LINE__,
                    _("read_comp_unit_head: dwarf from non elf file"));
   cu_header->signed_addr_p = signed_addr;
 
+  if (section_kind == rcuh_kind::TYPE)
+    {
+      LONGEST type_offset;
+
+      cu_header->signature = read_8_bytes (abfd, info_ptr);
+      info_ptr += 8;
+
+      type_offset = read_offset (abfd, info_ptr, cu_header, &bytes_read);
+      info_ptr += bytes_read;
+      cu_header->type_cu_offset_in_tu = (cu_offset) type_offset;
+      if (to_underlying (cu_header->type_cu_offset_in_tu) != type_offset)
+       error (_("Dwarf Error: Too big type_offset in compilation unit "
+              "header (is %s) [in module %s]"), plongest (type_offset),
+              filename);
+    }
+
   return info_ptr;
 }
 
@@ -4390,25 +6712,26 @@ error_check_comp_unit_head (struct comp_unit_head *header,
 {
   const char *filename = get_section_file_name (section);
 
-  if (header->version != 2 && header->version != 3 && header->version != 4)
+  if (header->version < 2 || header->version > 5)
     error (_("Dwarf Error: wrong version in compilation unit header "
-          "(is %d, should be 2, 3, or 4) [in module %s]"), header->version,
+          "(is %d, should be 2, 3, 4 or 5) [in module %s]"), header->version,
           filename);
 
-  if (header->abbrev_offset.sect_off
+  if (to_underlying (header->abbrev_sect_off)
       >= dwarf2_section_size (dwarf2_per_objfile->objfile, abbrev_section))
-    error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header "
-          "(offset 0x%lx + 6) [in module %s]"),
-          (long) header->abbrev_offset.sect_off, (long) header->offset.sect_off,
+    error (_("Dwarf Error: bad offset (0x%x) in compilation unit header "
+          "(offset 0x%x + 6) [in module %s]"),
+          to_underlying (header->abbrev_sect_off),
+          to_underlying (header->sect_off),
           filename);
 
-  /* Cast to unsigned long to use 64-bit arithmetic when possible to
+  /* Cast to ULONGEST to use 64-bit arithmetic when possible to
      avoid potential 32-bit overflow.  */
-  if (((unsigned long) header->offset.sect_off + get_cu_length (header))
+  if (((ULONGEST) header->sect_off + get_cu_length (header))
       > section->size)
-    error (_("Dwarf Error: bad length (0x%lx) in compilation unit header "
-          "(offset 0x%lx + 0) [in module %s]"),
-          (long) header->length, (long) header->offset.sect_off,
+    error (_("Dwarf Error: bad length (0x%x) in compilation unit header "
+          "(offset 0x%x + 0) [in module %s]"),
+          header->length, to_underlying (header->sect_off),
           filename);
 }
 
@@ -4421,56 +6744,15 @@ read_and_check_comp_unit_head (struct comp_unit_head *header,
                               struct dwarf2_section_info *section,
                               struct dwarf2_section_info *abbrev_section,
                               const gdb_byte *info_ptr,
-                              int is_debug_types_section)
-{
-  const gdb_byte *beg_of_comp_unit = info_ptr;
-  bfd *abfd = get_section_bfd_owner (section);
-
-  header->offset.sect_off = beg_of_comp_unit - section->buffer;
-
-  info_ptr = read_comp_unit_head (header, info_ptr, abfd);
-
-  /* If we're reading a type unit, skip over the signature and
-     type_offset fields.  */
-  if (is_debug_types_section)
-    info_ptr += 8 /*signature*/ + header->offset_size;
-
-  header->first_die_offset.cu_off = info_ptr - beg_of_comp_unit;
-
-  error_check_comp_unit_head (header, section, abbrev_section);
-
-  return info_ptr;
-}
-
-/* Read in the types comp unit header information from .debug_types entry at
-   types_ptr.  The result is a pointer to one past the end of the header.  */
-
-static const gdb_byte *
-read_and_check_type_unit_head (struct comp_unit_head *header,
-                              struct dwarf2_section_info *section,
-                              struct dwarf2_section_info *abbrev_section,
-                              const gdb_byte *info_ptr,
-                              ULONGEST *signature,
-                              cu_offset *type_offset_in_tu)
+                              rcuh_kind section_kind)
 {
   const gdb_byte *beg_of_comp_unit = info_ptr;
-  bfd *abfd = get_section_bfd_owner (section);
 
-  header->offset.sect_off = beg_of_comp_unit - section->buffer;
+  header->sect_off = (sect_offset) (beg_of_comp_unit - section->buffer);
 
-  info_ptr = read_comp_unit_head (header, info_ptr, abfd);
+  info_ptr = read_comp_unit_head (header, info_ptr, section, section_kind);
 
-  /* If we're reading a type unit, skip over the signature and
-     type_offset fields.  */
-  if (signature != NULL)
-    *signature = read_8_bytes (abfd, info_ptr);
-  info_ptr += 8;
-  if (type_offset_in_tu != NULL)
-    type_offset_in_tu->cu_off = read_offset_1 (abfd, info_ptr,
-                                              header->offset_size);
-  info_ptr += header->offset_size;
-
-  header->first_die_offset.cu_off = info_ptr - beg_of_comp_unit;
+  header->first_die_cu_offset = (cu_offset) (info_ptr - beg_of_comp_unit);
 
   error_check_comp_unit_head (header, section, abbrev_section);
 
@@ -4481,20 +6763,28 @@ read_and_check_type_unit_head (struct comp_unit_head *header,
 
 static sect_offset
 read_abbrev_offset (struct dwarf2_section_info *section,
-                   sect_offset offset)
+                   sect_offset sect_off)
 {
   bfd *abfd = get_section_bfd_owner (section);
   const gdb_byte *info_ptr;
   unsigned int initial_length_size, offset_size;
-  sect_offset abbrev_offset;
+  uint16_t version;
 
   dwarf2_read_section (dwarf2_per_objfile->objfile, section);
-  info_ptr = section->buffer + offset.sect_off;
+  info_ptr = section->buffer + to_underlying (sect_off);
   read_initial_length (abfd, info_ptr, &initial_length_size);
   offset_size = initial_length_size == 4 ? 4 : 8;
-  info_ptr += initial_length_size + 2 /*version*/;
-  abbrev_offset.sect_off = read_offset_1 (abfd, info_ptr, offset_size);
-  return abbrev_offset;
+  info_ptr += initial_length_size;
+
+  version = read_2_bytes (abfd, info_ptr);
+  info_ptr += 2;
+  if (version >= 5)
+    {
+      /* Skip unit type and address size.  */
+      info_ptr += 2;
+    }
+
+  return (sect_offset) read_offset_1 (abfd, info_ptr, offset_size);
 }
 
 /* Allocate a new partial symtab for file named NAME and mark this new
@@ -4543,19 +6833,17 @@ dwarf2_build_include_psymtabs (struct dwarf2_cu *cu,
                               struct die_info *die,
                               struct partial_symtab *pst)
 {
-  struct line_header *lh = NULL;
+  line_header_up lh;
   struct attribute *attr;
 
   attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
   if (attr)
-    lh = dwarf_decode_line_header (DW_UNSND (attr), cu);
+    lh = dwarf_decode_line_header ((sect_offset) DW_UNSND (attr), cu);
   if (lh == NULL)
     return;  /* No linetable, so no includes.  */
 
   /* NOTE: pst->dirname is DW_AT_comp_dir (if present).  */
-  dwarf_decode_lines (lh, pst->dirname, cu, pst, pst->textlow, 1);
-
-  free_line_header (lh);
+  dwarf_decode_lines (lh.get (), pst->dirname, cu, pst, pst->textlow, 1);
 }
 
 static hashval_t
@@ -4605,167 +6893,177 @@ add_signatured_type_cu_to_table (void **slot, void *datum)
   return 1;
 }
 
-/* Create the hash table of all entries in the .debug_types
-   (or .debug_types.dwo) section(s).
-   If reading a DWO file, then DWO_FILE is a pointer to the DWO file object,
-   otherwise it is NULL.
-
-   The result is a pointer to the hash table or NULL if there are no types.
-
-   Note: This function processes DWO files only, not DWP files.  */
+/* A helper for create_debug_types_hash_table.  Read types from SECTION
+   and fill them into TYPES_HTAB.  It will process only type units,
+   therefore DW_UT_type.  */
 
-static htab_t
-create_debug_types_hash_table (struct dwo_file *dwo_file,
-                              VEC (dwarf2_section_info_def) *types)
+static void
+create_debug_type_hash_table (struct dwo_file *dwo_file,
+                             dwarf2_section_info *section, htab_t &types_htab,
+                             rcuh_kind section_kind)
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
-  htab_t types_htab = NULL;
-  int ix;
-  struct dwarf2_section_info *section;
   struct dwarf2_section_info *abbrev_section;
-
-  if (VEC_empty (dwarf2_section_info_def, types))
-    return NULL;
+  bfd *abfd;
+  const gdb_byte *info_ptr, *end_ptr;
 
   abbrev_section = (dwo_file != NULL
                    ? &dwo_file->sections.abbrev
                    : &dwarf2_per_objfile->abbrev);
 
   if (dwarf_read_debug)
-    fprintf_unfiltered (gdb_stdlog, "Reading .debug_types%s for %s:\n",
-                       dwo_file ? ".dwo" : "",
+    fprintf_unfiltered (gdb_stdlog, "Reading %s for %s:\n",
+                       get_section_name (section),
                        get_section_file_name (abbrev_section));
 
-  for (ix = 0;
-       VEC_iterate (dwarf2_section_info_def, types, ix, section);
-       ++ix)
-    {
-      bfd *abfd;
-      const gdb_byte *info_ptr, *end_ptr;
+  dwarf2_read_section (objfile, section);
+  info_ptr = section->buffer;
 
-      dwarf2_read_section (objfile, section);
-      info_ptr = section->buffer;
+  if (info_ptr == NULL)
+    return;
 
-      if (info_ptr == NULL)
-       continue;
+  /* We can't set abfd until now because the section may be empty or
+     not present, in which case the bfd is unknown.  */
+  abfd = get_section_bfd_owner (section);
 
-      /* We can't set abfd until now because the section may be empty or
-        not present, in which case the bfd is unknown.  */
-      abfd = get_section_bfd_owner (section);
+  /* We don't use init_cutu_and_read_dies_simple, or some such, here
+     because we don't need to read any dies: the signature is in the
+     header.  */
 
-      /* We don't use init_cutu_and_read_dies_simple, or some such, here
-        because we don't need to read any dies: the signature is in the
-        header.  */
+  end_ptr = info_ptr + section->size;
+  while (info_ptr < end_ptr)
+    {
+      struct signatured_type *sig_type;
+      struct dwo_unit *dwo_tu;
+      void **slot;
+      const gdb_byte *ptr = info_ptr;
+      struct comp_unit_head header;
+      unsigned int length;
 
-      end_ptr = info_ptr + section->size;
-      while (info_ptr < end_ptr)
-       {
-         sect_offset offset;
-         cu_offset type_offset_in_tu;
-         ULONGEST signature;
-         struct signatured_type *sig_type;
-         struct dwo_unit *dwo_tu;
-         void **slot;
-         const gdb_byte *ptr = info_ptr;
-         struct comp_unit_head header;
-         unsigned int length;
+      sect_offset sect_off = (sect_offset) (ptr - section->buffer);
 
-         offset.sect_off = ptr - section->buffer;
+      /* Initialize it due to a false compiler warning.  */
+      header.signature = -1;
+      header.type_cu_offset_in_tu = (cu_offset) -1;
 
-         /* We need to read the type's signature in order to build the hash
-            table, but we don't need anything else just yet.  */
+      /* We need to read the type's signature in order to build the hash
+        table, but we don't need anything else just yet.  */
 
-         ptr = read_and_check_type_unit_head (&header, section,
-                                              abbrev_section, ptr,
-                                              &signature, &type_offset_in_tu);
+      ptr = read_and_check_comp_unit_head (&header, section,
+                                          abbrev_section, ptr, section_kind);
 
-         length = get_cu_length (&header);
+      length = get_cu_length (&header);
 
-         /* Skip dummy type units.  */
-         if (ptr >= info_ptr + length
-             || peek_abbrev_code (abfd, ptr) == 0)
-           {
-             info_ptr += length;
-             continue;
-           }
+      /* Skip dummy type units.  */
+      if (ptr >= info_ptr + length
+         || peek_abbrev_code (abfd, ptr) == 0
+         || header.unit_type != DW_UT_type)
+       {
+         info_ptr += length;
+         continue;
+       }
 
-         if (types_htab == NULL)
-           {
-             if (dwo_file)
-               types_htab = allocate_dwo_unit_table (objfile);
-             else
-               types_htab = allocate_signatured_type_table (objfile);
-           }
+      if (types_htab == NULL)
+       {
+         if (dwo_file)
+           types_htab = allocate_dwo_unit_table (objfile);
+         else
+           types_htab = allocate_signatured_type_table (objfile);
+       }
+
+      if (dwo_file)
+       {
+         sig_type = NULL;
+         dwo_tu = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+                                  struct dwo_unit);
+         dwo_tu->dwo_file = dwo_file;
+         dwo_tu->signature = header.signature;
+         dwo_tu->type_offset_in_tu = header.type_cu_offset_in_tu;
+         dwo_tu->section = section;
+         dwo_tu->sect_off = sect_off;
+         dwo_tu->length = length;
+       }
+      else
+       {
+         /* N.B.: type_offset is not usable if this type uses a DWO file.
+            The real type_offset is in the DWO file.  */
+         dwo_tu = NULL;
+         sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+                                    struct signatured_type);
+         sig_type->signature = header.signature;
+         sig_type->type_offset_in_tu = header.type_cu_offset_in_tu;
+         sig_type->per_cu.objfile = objfile;
+         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.length = length;
+       }
+
+      slot = htab_find_slot (types_htab,
+                            dwo_file ? (void*) dwo_tu : (void *) sig_type,
+                            INSERT);
+      gdb_assert (slot != NULL);
+      if (*slot != NULL)
+       {
+         sect_offset dup_sect_off;
 
          if (dwo_file)
            {
-             sig_type = NULL;
-             dwo_tu = OBSTACK_ZALLOC (&objfile->objfile_obstack,
-                                      struct dwo_unit);
-             dwo_tu->dwo_file = dwo_file;
-             dwo_tu->signature = signature;
-             dwo_tu->type_offset_in_tu = type_offset_in_tu;
-             dwo_tu->section = section;
-             dwo_tu->offset = offset;
-             dwo_tu->length = length;
+             const struct dwo_unit *dup_tu
+               = (const struct dwo_unit *) *slot;
+
+             dup_sect_off = dup_tu->sect_off;
            }
          else
            {
-             /* N.B.: type_offset is not usable if this type uses a DWO file.
-                The real type_offset is in the DWO file.  */
-             dwo_tu = NULL;
-             sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
-                                        struct signatured_type);
-             sig_type->signature = signature;
-             sig_type->type_offset_in_tu = type_offset_in_tu;
-             sig_type->per_cu.objfile = objfile;
-             sig_type->per_cu.is_debug_types = 1;
-             sig_type->per_cu.section = section;
-             sig_type->per_cu.offset = offset;
-             sig_type->per_cu.length = length;
+             const struct signatured_type *dup_tu
+               = (const struct signatured_type *) *slot;
+
+             dup_sect_off = dup_tu->per_cu.sect_off;
            }
 
-         slot = htab_find_slot (types_htab,
-                                dwo_file ? (void*) dwo_tu : (void *) sig_type,
-                                INSERT);
-         gdb_assert (slot != NULL);
-         if (*slot != NULL)
-           {
-             sect_offset dup_offset;
+         complaint (&symfile_complaints,
+                    _("debug type 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 (header.signature));
+       }
+      *slot = dwo_file ? (void *) dwo_tu : (void *) sig_type;
 
-             if (dwo_file)
-               {
-                 const struct dwo_unit *dup_tu
-                   = (const struct dwo_unit *) *slot;
+      if (dwarf_read_debug > 1)
+       fprintf_unfiltered (gdb_stdlog, "  offset 0x%x, signature %s\n",
+                           to_underlying (sect_off),
+                           hex_string (header.signature));
 
-                 dup_offset = dup_tu->offset;
-               }
-             else
-               {
-                 const struct signatured_type *dup_tu
-                   = (const struct signatured_type *) *slot;
+      info_ptr += length;
+    }
+}
 
-                 dup_offset = dup_tu->per_cu.offset;
-               }
+/* Create the hash table of all entries in the .debug_types
+   (or .debug_types.dwo) section(s).
+   If reading a DWO file, then DWO_FILE is a pointer to the DWO file object,
+   otherwise it is NULL.
 
-             complaint (&symfile_complaints,
-                        _("debug type entry at offset 0x%x is duplicate to"
-                          " the entry at offset 0x%x, signature %s"),
-                        offset.sect_off, dup_offset.sect_off,
-                        hex_string (signature));
-           }
-         *slot = dwo_file ? (void *) dwo_tu : (void *) sig_type;
+   The result is a pointer to the hash table or NULL if there are no types.
 
-         if (dwarf_read_debug > 1)
-           fprintf_unfiltered (gdb_stdlog, "  offset 0x%x, signature %s\n",
-                               offset.sect_off,
-                               hex_string (signature));
+   Note: This function processes DWO files only, not DWP files.  */
 
-         info_ptr += length;
-       }
-    }
+static void
+create_debug_types_hash_table (struct dwo_file *dwo_file,
+                              VEC (dwarf2_section_info_def) *types,
+                              htab_t &types_htab)
+{
+  int ix;
+  struct dwarf2_section_info *section;
+
+  if (VEC_empty (dwarf2_section_info_def, types))
+    return;
 
-  return types_htab;
+  for (ix = 0;
+       VEC_iterate (dwarf2_section_info_def, types, ix, section);
+       ++ix)
+    create_debug_type_hash_table (dwo_file, section, types_htab,
+                                 rcuh_kind::TYPE);
 }
 
 /* Create the hash table of all entries in the .debug_types section,
@@ -4776,10 +7074,12 @@ create_debug_types_hash_table (struct dwo_file *dwo_file,
 static int
 create_all_type_units (struct objfile *objfile)
 {
-  htab_t types_htab;
+  htab_t types_htab = NULL;
   struct signatured_type **iter;
 
-  types_htab = create_debug_types_hash_table (NULL, dwarf2_per_objfile->types);
+  create_debug_type_hash_table (NULL, &dwarf2_per_objfile->info, types_htab,
+                               rcuh_kind::COMPILE);
+  create_debug_types_hash_table (NULL, dwarf2_per_objfile->types, types_htab);
   if (types_htab == NULL)
     {
       dwarf2_per_objfile->signatured_types = NULL;
@@ -4869,12 +7169,12 @@ fill_in_sig_entry_from_dwo_entry (struct objfile *objfile,
   else
       gdb_assert (sig_entry->per_cu.v.psymtab == NULL);
   gdb_assert (sig_entry->signature == dwo_entry->signature);
-  gdb_assert (sig_entry->type_offset_in_section.sect_off == 0);
+  gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0);
   gdb_assert (sig_entry->type_unit_group == NULL);
   gdb_assert (sig_entry->dwo_unit == NULL);
 
   sig_entry->per_cu.section = dwo_entry->section;
-  sig_entry->per_cu.offset = dwo_entry->offset;
+  sig_entry->per_cu.sect_off = dwo_entry->sect_off;
   sig_entry->per_cu.length = dwo_entry->length;
   sig_entry->per_cu.reading_dwo_directly = 1;
   sig_entry->per_cu.objfile = objfile;
@@ -5089,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;
@@ -5153,48 +7452,45 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data *this_cu,
   section = dwo_unit->section;
   dwarf2_read_section (objfile, section);
   abfd = get_section_bfd_owner (section);
-  begin_info_ptr = info_ptr = section->buffer + dwo_unit->offset.sect_off;
+  begin_info_ptr = info_ptr = (section->buffer
+                              + to_underlying (dwo_unit->sect_off));
   dwo_abbrev_section = &dwo_unit->dwo_file->sections.abbrev;
   init_cu_die_reader (result_reader, cu, section, dwo_unit->dwo_file);
 
   if (this_cu->is_debug_types)
     {
-      ULONGEST header_signature;
-      cu_offset type_offset_in_tu;
       struct signatured_type *sig_type = (struct signatured_type *) this_cu;
 
-      info_ptr = read_and_check_type_unit_head (&cu->header, section,
+      info_ptr = read_and_check_comp_unit_head (&cu->header, section,
                                                dwo_abbrev_section,
-                                               info_ptr,
-                                               &header_signature,
-                                               &type_offset_in_tu);
+                                               info_ptr, rcuh_kind::TYPE);
       /* This is not an assert because it can be caused by bad debug info.  */
-      if (sig_type->signature != header_signature)
+      if (sig_type->signature != cu->header.signature)
        {
          error (_("Dwarf Error: signature mismatch %s vs %s while reading"
                   " TU at offset 0x%x [in module %s]"),
                 hex_string (sig_type->signature),
-                hex_string (header_signature),
-                dwo_unit->offset.sect_off,
+                hex_string (cu->header.signature),
+                to_underlying (dwo_unit->sect_off),
                 bfd_get_filename (abfd));
        }
-      gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
+      gdb_assert (dwo_unit->sect_off == cu->header.sect_off);
       /* For DWOs coming from DWP files, we don't know the CU length
         nor the type's offset in the TU until now.  */
       dwo_unit->length = get_cu_length (&cu->header);
-      dwo_unit->type_offset_in_tu = type_offset_in_tu;
+      dwo_unit->type_offset_in_tu = cu->header.type_cu_offset_in_tu;
 
       /* Establish the type offset that can be used to lookup the type.
         For DWO files, we don't know it until now.  */
-      sig_type->type_offset_in_section.sect_off =
-       dwo_unit->offset.sect_off + dwo_unit->type_offset_in_tu.cu_off;
+      sig_type->type_offset_in_section
+       = dwo_unit->sect_off + to_underlying (dwo_unit->type_offset_in_tu);
     }
   else
     {
       info_ptr = read_and_check_comp_unit_head (&cu->header, section,
                                                dwo_abbrev_section,
-                                               info_ptr, 0);
-      gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
+                                               info_ptr, rcuh_kind::COMPILE);
+      gdb_assert (dwo_unit->sect_off == cu->header.sect_off);
       /* For DWOs coming from DWP files, we don't know the CU length
         until now.  */
       dwo_unit->length = get_cu_length (&cu->header);
@@ -5279,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;
@@ -5454,7 +7749,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
   if (dwarf_die_debug)
     fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset 0x%x\n",
                        this_cu->is_debug_types ? "type" : "comp",
-                       this_cu->offset.sect_off);
+                       to_underlying (this_cu->sect_off));
 
   if (use_existing_cu)
     gdb_assert (keep);
@@ -5476,7 +7771,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
   /* This is cheap if the section is already read in.  */
   dwarf2_read_section (objfile, section);
 
-  begin_info_ptr = info_ptr = section->buffer + this_cu->offset.sect_off;
+  begin_info_ptr = info_ptr = section->buffer + to_underlying (this_cu->sect_off);
 
   abbrev_section = get_abbrev_section_for_cu (this_cu);
 
@@ -5503,47 +7798,47 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
     }
 
   /* Get the header.  */
-  if (cu->header.first_die_offset.cu_off != 0 && ! rereading_dwo_cu)
+  if (to_underlying (cu->header.first_die_cu_offset) != 0 && !rereading_dwo_cu)
     {
       /* We already have the header, there's no need to read it in again.  */
-      info_ptr += cu->header.first_die_offset.cu_off;
+      info_ptr += to_underlying (cu->header.first_die_cu_offset);
     }
   else
     {
       if (this_cu->is_debug_types)
        {
-         ULONGEST signature;
-         cu_offset type_offset_in_tu;
-
-         info_ptr = read_and_check_type_unit_head (&cu->header, section,
+         info_ptr = read_and_check_comp_unit_head (&cu->header, section,
                                                    abbrev_section, info_ptr,
-                                                   &signature,
-                                                   &type_offset_in_tu);
+                                                   rcuh_kind::TYPE);
 
          /* Since per_cu is the first member of struct signatured_type,
             we can go from a pointer to one to a pointer to the other.  */
          sig_type = (struct signatured_type *) this_cu;
-         gdb_assert (sig_type->signature == signature);
-         gdb_assert (sig_type->type_offset_in_tu.cu_off
-                     == type_offset_in_tu.cu_off);
-         gdb_assert (this_cu->offset.sect_off == cu->header.offset.sect_off);
+         gdb_assert (sig_type->signature == cu->header.signature);
+         gdb_assert (sig_type->type_offset_in_tu
+                     == cu->header.type_cu_offset_in_tu);
+         gdb_assert (this_cu->sect_off == cu->header.sect_off);
 
          /* LENGTH has not been set yet for type units if we're
             using .gdb_index.  */
          this_cu->length = get_cu_length (&cu->header);
 
          /* Establish the type offset that can be used to lookup the type.  */
-         sig_type->type_offset_in_section.sect_off =
-           this_cu->offset.sect_off + sig_type->type_offset_in_tu.cu_off;
+         sig_type->type_offset_in_section =
+           this_cu->sect_off + to_underlying (sig_type->type_offset_in_tu);
+
+         this_cu->dwarf_version = cu->header.version;
        }
       else
        {
          info_ptr = read_and_check_comp_unit_head (&cu->header, section,
                                                    abbrev_section,
-                                                   info_ptr, 0);
+                                                   info_ptr,
+                                                   rcuh_kind::COMPILE);
 
-         gdb_assert (this_cu->offset.sect_off == cu->header.offset.sect_off);
+         gdb_assert (this_cu->sect_off == cu->header.sect_off);
          gdb_assert (this_cu->length == get_cu_length (&cu->header));
+         this_cu->dwarf_version = cu->header.version;
        }
     }
 
@@ -5563,8 +7858,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
   if (abbrev_table != NULL)
     {
       gdb_assert (cu->abbrev_table == NULL);
-      gdb_assert (cu->header.abbrev_offset.sect_off
-                 == abbrev_table->offset.sect_off);
+      gdb_assert (cu->header.abbrev_sect_off == abbrev_table->sect_off);
       cu->abbrev_table = abbrev_table;
     }
   else if (cu->abbrev_table == NULL)
@@ -5597,7 +7891,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
          complaint (&symfile_complaints,
                     _("compilation unit with DW_AT_GNU_dwo_name"
                       " has children (offset 0x%x) [in module %s]"),
-                    this_cu->offset.sect_off, bfd_get_filename (abfd));
+                    to_underlying (this_cu->sect_off), bfd_get_filename (abfd));
        }
       dwo_unit = lookup_dwo_unit (this_cu, comp_unit_die);
       if (dwo_unit != NULL)
@@ -5687,7 +7981,7 @@ init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
   if (dwarf_die_debug)
     fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset 0x%x\n",
                        this_cu->is_debug_types ? "type" : "comp",
-                       this_cu->offset.sect_off);
+                       to_underlying (this_cu->sect_off));
 
   gdb_assert (this_cu->cu == NULL);
 
@@ -5702,10 +7996,12 @@ init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
 
   cleanups = make_cleanup (free_stack_comp_unit, &cu);
 
-  begin_info_ptr = info_ptr = section->buffer + this_cu->offset.sect_off;
+  begin_info_ptr = info_ptr = section->buffer + to_underlying (this_cu->sect_off);
   info_ptr = read_and_check_comp_unit_head (&cu.header, section,
                                            abbrev_section, info_ptr,
-                                           this_cu->is_debug_types);
+                                           (this_cu->is_debug_types
+                                            ? rcuh_kind::TYPE
+                                            : rcuh_kind::COMPILE));
 
   this_cu->length = get_cu_length (&cu.header);
 
@@ -5813,7 +8109,7 @@ create_type_unit_group (struct dwarf2_cu *cu, sect_offset line_offset_struct)
     }
   else
     {
-      unsigned int line_offset = line_offset_struct.sect_off;
+      unsigned int line_offset = to_underlying (line_offset_struct);
       struct partial_symtab *pst;
       char *name;
 
@@ -5831,7 +8127,7 @@ create_type_unit_group (struct dwarf2_cu *cu, sect_offset line_offset_struct)
     }
 
   tu_group->hash.dwo_unit = cu->dwo_unit;
-  tu_group->hash.line_offset = line_offset_struct;
+  tu_group->hash.line_sect_off = line_offset_struct;
 
   return tu_group;
 }
@@ -5875,7 +8171,7 @@ get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list)
     }
 
   type_unit_group_for_lookup.hash.dwo_unit = cu->dwo_unit;
-  type_unit_group_for_lookup.hash.line_offset.sect_off = line_offset;
+  type_unit_group_for_lookup.hash.line_sect_off = (sect_offset) line_offset;
   slot = htab_find_slot (dwarf2_per_objfile->type_unit_groups,
                         &type_unit_group_for_lookup, INSERT);
   if (*slot != NULL)
@@ -5885,9 +8181,7 @@ get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list)
     }
   else
     {
-      sect_offset line_offset_struct;
-
-      line_offset_struct.sect_off = line_offset;
+      sect_offset line_offset_struct = (sect_offset) line_offset;
       tu_group = create_type_unit_group (cu, line_offset_struct);
       *slot = tu_group;
       ++tu_stats->nr_symtabs;
@@ -5910,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;
 
@@ -6062,7 +8356,7 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
                          "Psymtab for %s unit @0x%x: %s - %s"
                          ", %d global, %d static syms\n",
                          per_cu->is_debug_types ? "type" : "comp",
-                         per_cu->offset.sect_off,
+                         to_underlying (per_cu->sect_off),
                          paddress (gdbarch, pst->textlow),
                          paddress (gdbarch, pst->texthigh),
                          pst->n_global_syms, pst->n_static_syms);
@@ -6077,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
@@ -6087,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 ();
@@ -6160,8 +8457,8 @@ sort_tu_by_abbrev_offset (const void *ap, const void *bp)
     = (const struct tu_abbrev_offset * const*) ap;
   const struct tu_abbrev_offset * const *b
     = (const struct tu_abbrev_offset * const*) bp;
-  unsigned int aoff = (*a)->abbrev_offset.sect_off;
-  unsigned int boff = (*b)->abbrev_offset.sect_off;
+  sect_offset aoff = (*a)->abbrev_offset;
+  sect_offset boff = (*b)->abbrev_offset;
 
   return (aoff > boff) - (aoff < boff);
 }
@@ -6233,13 +8530,13 @@ build_type_psymtabs_1 (void)
       sorted_by_abbrev[i].sig_type = sig_type;
       sorted_by_abbrev[i].abbrev_offset =
        read_abbrev_offset (sig_type->per_cu.section,
-                           sig_type->per_cu.offset);
+                           sig_type->per_cu.sect_off);
     }
   cleanups = make_cleanup (xfree, sorted_by_abbrev);
   qsort (sorted_by_abbrev, dwarf2_per_objfile->n_type_units,
         sizeof (struct tu_abbrev_offset), sort_tu_by_abbrev_offset);
 
-  abbrev_offset.sect_off = ~(unsigned) 0;
+  abbrev_offset = (sect_offset) ~(unsigned) 0;
   abbrev_table = NULL;
   make_cleanup (abbrev_table_free_cleanup, &abbrev_table);
 
@@ -6249,7 +8546,7 @@ build_type_psymtabs_1 (void)
 
       /* Switch to the next abbrev table if necessary.  */
       if (abbrev_table == NULL
-         || tu->abbrev_offset.sect_off != abbrev_offset.sect_off)
+         || tu->abbrev_offset != abbrev_offset)
        {
          if (abbrev_table != NULL)
            {
@@ -6411,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
@@ -6452,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)
@@ -6476,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)
     {
@@ -6505,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);
 
@@ -6547,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",
@@ -6566,21 +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 offset;
 
-      offset.sect_off = info_ptr - section->buffer;
+      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));
-      this_cu->offset = offset;
-      this_cu->length = length + initial_length_size;
+      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 = cu_header.length + cu_header.initial_length_size;
       this_cu->is_dwz = is_dwz;
       this_cu->objfile = objfile;
       this_cu->section = section;
@@ -6613,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);
 
@@ -6715,7 +9016,7 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
                           objfile_name (cu->objfile));
                  }
 
-               per_cu = dwarf2_find_containing_comp_unit (pdi->d.offset,
+               per_cu = dwarf2_find_containing_comp_unit (pdi->d.sect_off,
                                                           pdi->is_dwz,
                                                           cu->objfile);
 
@@ -6828,7 +9129,7 @@ partial_die_parent_scope (struct partial_die_info *pdi,
         ignoring them.  */
       complaint (&symfile_complaints,
                 _("unhandled containing DIE tag %d for DIE at %d"),
-                parent->tag, pdi->offset.sect_off);
+                parent->tag, to_underlying (pdi->sect_off));
       parent->scope = grandparent_scope;
     }
 
@@ -6862,7 +9163,7 @@ partial_die_full_name (struct partial_die_info *pdi,
          /* DW_FORM_ref_addr is using section offset.  */
          attr.name = (enum dwarf_attribute) 0;
          attr.form = DW_FORM_ref_addr;
-         attr.u.unsnd = pdi->offset.sect_off;
+         attr.u.unsnd = to_underlying (pdi->sect_off);
          die = follow_die_ref (NULL, &attr, &ref_cu);
 
          return xstrdup (dwarf2_full_name (NULL, die, ref_cu));
@@ -6925,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;
@@ -7222,7 +9523,7 @@ peek_die_abbrev (const gdb_byte *info_ptr, unsigned int *bytes_read,
       error (_("Dwarf Error: Could not find abbrev number %d in %s"
               " at offset 0x%x [in module %s]"),
             abbrev_number, cu->per_cu->is_debug_types ? "TU" : "CU",
-            cu->header.offset.sect_off, bfd_get_filename (abfd));
+            to_underlying (cu->header.sect_off), bfd_get_filename (abfd));
     }
 
   return abbrev;
@@ -7278,8 +9579,8 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
                       _("ignoring absolute DW_AT_sibling"));
          else
            {
-             unsigned int off = dwarf2_get_ref_die_offset (&attr).sect_off;
-             const gdb_byte *sibling_ptr = buffer + off;
+             sect_offset off = dwarf2_get_ref_die_offset (&attr);
+             const gdb_byte *sibling_ptr = buffer + to_underlying (off);
 
              if (sibling_ptr < info_ptr)
                complaint (&symfile_complaints,
@@ -7316,6 +9617,7 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
          info_ptr += 1;
          break;
        case DW_FORM_flag_present:
+       case DW_FORM_implicit_const:
          break;
        case DW_FORM_data2:
        case DW_FORM_ref2:
@@ -7330,6 +9632,9 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
        case DW_FORM_ref_sig8:
          info_ptr += 8;
          break;
+       case DW_FORM_data16:
+         info_ptr += 16;
+         break;
        case DW_FORM_string:
          read_direct_string (abfd, info_ptr, &bytes_read);
          info_ptr += bytes_read;
@@ -7563,14 +9868,15 @@ process_queue (void)
 
              sprintf (buf, "TU %s at offset 0x%x",
                       hex_string (sig_type->signature),
-                      per_cu->offset.sect_off);
+                      to_underlying (per_cu->sect_off));
              /* There can be 100s of TUs.
                 Only print them in verbose mode.  */
              debug_print_threshold = 2;
            }
          else
            {
-             sprintf (buf, "CU at offset 0x%x", per_cu->offset.sect_off);
+             sprintf (buf, "CU at offset 0x%x",
+                      to_underlying (per_cu->sect_off));
              debug_print_threshold = 1;
            }
 
@@ -7680,7 +9986,7 @@ die_hash (const void *item)
 {
   const struct die_info *die = (const struct die_info *) item;
 
-  return die->offset.sect_off;
+  return to_underlying (die->sect_off);
 }
 
 /* Trivial comparison function for die_info structures: two DIEs
@@ -7692,7 +9998,7 @@ die_eq (const void *item_lhs, const void *item_rhs)
   const struct die_info *die_lhs = (const struct die_info *) item_lhs;
   const struct die_info *die_rhs = (const struct die_info *) item_rhs;
 
-  return die_lhs->offset.sect_off == die_rhs->offset.sect_off;
+  return die_lhs->sect_off == die_rhs->sect_off;
 }
 
 /* die_reader_func for load_full_comp_unit.
@@ -7775,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
@@ -7786,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;
@@ -7794,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;
+           }
+       }
     }
 }
 
@@ -8029,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;
@@ -8037,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;
@@ -8119,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
@@ -8133,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;
@@ -8195,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.  */
@@ -8217,13 +10562,10 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
   attr = dwarf2_attr (die, DW_AT_import, cu);
   if (attr != NULL)
     {
-      struct dwarf2_per_cu_data *per_cu;
-      sect_offset offset;
-      int is_dwz;
-
-      offset = dwarf2_get_ref_die_offset (attr);
-      is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz);
-      per_cu = dwarf2_find_containing_comp_unit (offset, is_dwz, cu->objfile);
+      sect_offset sect_off = dwarf2_get_ref_die_offset (attr);
+      bool is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz);
+      dwarf2_per_cu_data *per_cu
+       = dwarf2_find_containing_comp_unit (sect_off, is_dwz, cu->objfile);
 
       /* If necessary, add it to the queue and load its DIEs.  */
       if (maybe_queue_comp_unit (cu, per_cu, cu->language))
@@ -8234,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)
     {
@@ -8277,6 +10635,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
     case DW_TAG_catch_block:
       read_lexical_block_scope (die, cu);
       break;
+    case DW_TAG_call_site:
     case DW_TAG_GNU_call_site:
       read_call_site_scope (die, cu);
       break;
@@ -8299,6 +10658,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
     case DW_TAG_pointer_type:
     case DW_TAG_ptr_to_member_type:
     case DW_TAG_reference_type:
+    case DW_TAG_rvalue_reference_type:
     case DW_TAG_string_type:
       break;
 
@@ -8340,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.  */
@@ -8409,15 +10771,36 @@ die_needs_namespace (struct die_info *die, struct dwarf2_cu *cu)
     }
 }
 
-/* Retrieve the last character from a mem_file.  */
+/* 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 void
-do_ui_file_peek_last (void *object, const char *buffer, long length)
+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)
 {
-  char *last_char_p = (char *) object;
+  const char *linkage_name;
 
-  if (length > 0)
-    *last_char_p = buffer[length - 1];
+  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,
@@ -8459,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;
     }
@@ -8476,23 +10856,22 @@ dwarf2_compute_name (const char *name,
     {
       if (die_needs_namespace (die, cu))
        {
-         long length;
          const char *prefix;
-         struct ui_file *buf;
          const char *canonical_name = NULL;
 
+         string_file buf;
+
          prefix = determine_prefix (die, cu);
-         buf = mem_fileopen ();
          if (*prefix != '\0')
            {
              char *prefixed_name = typename_concat (NULL, prefix, name,
                                                     physname, cu);
 
-             fputs_unfiltered (prefixed_name, buf);
+             buf.puts (prefixed_name);
              xfree (prefixed_name);
            }
          else
-           fputs_unfiltered (name, buf);
+           buf.puts (name);
 
          /* Template parameters may be specified in the DIE's DW_AT_name, or
             as children with DW_TAG_template_type_param or
@@ -8537,25 +10916,25 @@ dwarf2_compute_name (const char *name,
 
                  if (first)
                    {
-                     fputs_unfiltered ("<", buf);
+                     buf.puts ("<");
                      first = 0;
                    }
                  else
-                   fputs_unfiltered (", ", buf);
+                   buf.puts (", ");
 
                  attr = dwarf2_attr (child, DW_AT_type, cu);
                  if (attr == NULL)
                    {
                      complaint (&symfile_complaints,
                                 _("template parameter missing DW_AT_type"));
-                     fputs_unfiltered ("UNKNOWN_TYPE", buf);
+                     buf.puts ("UNKNOWN_TYPE");
                      continue;
                    }
                  type = die_type (child, cu);
 
                  if (child->tag == DW_TAG_template_type_param)
                    {
-                     c_print_type (type, "", buf, -1, 0, &type_print_raw_options);
+                     c_print_type (type, "", &buf, -1, 0, &type_print_raw_options);
                      continue;
                    }
 
@@ -8565,7 +10944,7 @@ dwarf2_compute_name (const char *name,
                      complaint (&symfile_complaints,
                                 _("template parameter missing "
                                   "DW_AT_const_value"));
-                     fputs_unfiltered ("UNKNOWN_VALUE", buf);
+                     buf.puts ("UNKNOWN_VALUE");
                      continue;
                    }
 
@@ -8576,7 +10955,7 @@ dwarf2_compute_name (const char *name,
                  if (TYPE_NOSIGN (type))
                    /* GDB prints characters as NUMBER 'CHAR'.  If that's
                       changed, this can use value_print instead.  */
-                   c_printchar (value, type, buf);
+                   c_printchar (value, type, &buf);
                  else
                    {
                      struct value_print_options opts;
@@ -8599,7 +10978,7 @@ dwarf2_compute_name (const char *name,
                         the radix.  */
                      get_formatted_print_options (&opts, 'd');
                      opts.raw = 1;
-                     value_print (v, buf, &opts);
+                     value_print (v, &buf, &opts);
                      release_value (v);
                      value_free (v);
                    }
@@ -8611,12 +10990,10 @@ dwarf2_compute_name (const char *name,
                {
                  /* Close the argument list, with a space if necessary
                     (nested templates).  */
-                 char last_char = '\0';
-                 ui_file_put (buf, do_ui_file_peek_last, &last_char);
-                 if (last_char == '>')
-                   fputs_unfiltered (" >", buf);
+                 if (!buf.empty () && buf.string ().back () == '>')
+                   buf.puts (" >");
                  else
-                   fputs_unfiltered (">", buf);
+                   buf.puts (">");
                }
            }
 
@@ -8628,7 +11005,7 @@ dwarf2_compute_name (const char *name,
            {
              struct type *type = read_type_die (die, cu);
 
-             c_type_print_args (type, buf, 1, cu->language,
+             c_type_print_args (type, &buf, 1, cu->language,
                                 &type_print_raw_options);
 
              if (cu->language == language_cplus)
@@ -8643,12 +11020,11 @@ dwarf2_compute_name (const char *name,
                      && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_PTR
                      && TYPE_CONST (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type,
                                                                        0))))
-                   fputs_unfiltered (" const", buf);
+                   buf.puts (" const");
                }
            }
 
-         std::string intermediate_name = ui_file_as_string (buf);
-         ui_file_delete (buf);
+         const std::string &intermediate_name = buf.string ();
 
          if (cu->language == language_cplus)
            canonical_name
@@ -8697,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
@@ -8705,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.  */
@@ -8719,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
@@ -8737,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;
@@ -8769,7 +11136,7 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
          complaint (&symfile_complaints,
                     _("Computed physname <%s> does not match demangled <%s> "
                       "(from linkage <%s>) - DIE at 0x%x [in module %s]"),
-                    physname, canon, mangled, die->offset.sect_off,
+                    physname, canon, mangled, to_underlying (die->sect_off),
                     objfile_name (objfile));
 
          /* Prefer DW_AT_linkage_name (in the CANON form) - when it
@@ -8792,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;
 }
 
@@ -8833,16 +11199,16 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
        {
          complaint (&symfile_complaints,
                     _("DIE at 0x%x has too many recursively imported "
-                      "declarations"), d->offset.sect_off);
+                      "declarations"), to_underlying (d->sect_off));
          return 0;
        }
 
       if (attr != NULL)
        {
          struct type *type;
-         sect_offset offset = dwarf2_get_ref_die_offset (attr);
+         sect_offset sect_off = dwarf2_get_ref_die_offset (attr);
 
-         type = get_die_type_at_offset (offset, cu->per_cu);
+         type = get_die_type_at_offset (sect_off, cu->per_cu);
          if (type != NULL && TYPE_CODE (type) == TYPE_CODE_NAMESPACE)
            {
              /* This declaration is a global namespace alias.  Add
@@ -8889,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)
@@ -8964,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))
@@ -8980,7 +11343,7 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
            complaint (&symfile_complaints,
                       _("child DW_TAG_imported_declaration expected "
                         "- DIE at 0x%x [in module %s]"),
-                      child_die->offset.sect_off, objfile_name (objfile));
+                      to_underlying (child_die->sect_off), objfile_name (objfile));
            continue;
          }
 
@@ -9001,11 +11364,11 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
            complaint (&symfile_complaints,
                       _("child DW_TAG_imported_declaration has unknown "
                         "imported name - DIE at 0x%x [in module %s]"),
-                      child_die->offset.sect_off, objfile_name (objfile));
+                      to_underlying (child_die->sect_off), objfile_name (objfile));
            continue;
          }
 
-       VEC_safe_push (const_char_ptr, excludes, imported_name);
+       excludes.push_back (imported_name);
 
        process_die (child_die, cu);
       }
@@ -9018,19 +11381,19 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
                       excludes,
                       0,
                       &objfile->objfile_obstack);
-
-  do_cleanups (cleanups);
 }
 
-/* Cleanup function for handle_DW_AT_stmt_list.  */
+/* 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 void
-free_cu_line_header (void *arg)
+static int
+producer_is_icc_lt_14 (struct dwarf2_cu *cu)
 {
-  struct dwarf2_cu *cu = (struct dwarf2_cu *) arg;
+  if (!cu->checked_producer)
+    check_producer (cu);
 
-  free_line_header (cu->line_header);
-  cu->line_header = NULL;
+  return cu->producer_is_icc_lt_14;
 }
 
 /* Check for possibly missing DW_AT_comp_dir with relative .debug_line
@@ -9046,37 +11409,38 @@ producer_is_gcc_lt_4_3 (struct dwarf2_cu *cu)
   return cu->producer_is_gcc_lt_4_3;
 }
 
-static void
-find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu,
-                        const char **name, const char **comp_dir)
+static file_and_directory
+find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu)
 {
+  file_and_directory res;
+
   /* Find the filename.  Do not use dwarf2_name here, since the filename
      is not a source language identifier.  */
-  *name = dwarf2_string_attr (die, DW_AT_name, cu);
-  *comp_dir = dwarf2_string_attr (die, DW_AT_comp_dir, cu);
+  res.name = dwarf2_string_attr (die, DW_AT_name, cu);
+  res.comp_dir = dwarf2_string_attr (die, DW_AT_comp_dir, cu);
 
-  if (*comp_dir == NULL
-      && producer_is_gcc_lt_4_3 (cu) && *name != NULL
-      && IS_ABSOLUTE_PATH (*name))
+  if (res.comp_dir == NULL
+      && producer_is_gcc_lt_4_3 (cu) && res.name != NULL
+      && IS_ABSOLUTE_PATH (res.name))
     {
-      char *d = ldirname (*name);
-
-      *comp_dir = d;
-      if (d != NULL)
-       make_cleanup (xfree, d);
+      res.comp_dir_storage = ldirname (res.name);
+      if (!res.comp_dir_storage.empty ())
+       res.comp_dir = res.comp_dir_storage.c_str ();
     }
-  if (*comp_dir != NULL)
+  if (res.comp_dir != NULL)
     {
       /* Irix 6.2 native cc prepends <machine>.: to the compilation
         directory, get rid of it.  */
-      const char *cp = strchr (*comp_dir, ':');
+      const char *cp = strchr (res.comp_dir, ':');
 
-      if (cp && cp != *comp_dir && cp[-1] == '.' && cp[1] == '/')
-       *comp_dir = cp + 1;
+      if (cp && cp != res.comp_dir && cp[-1] == '.' && cp[1] == '/')
+       res.comp_dir = cp + 1;
     }
 
-  if (*name == NULL)
-    *name = "<unknown>";
+  if (res.name == NULL)
+    res.name = "<unknown>";
+
+  return res;
 }
 
 /* Handle DW_AT_stmt_list for a compilation unit.
@@ -9090,10 +11454,8 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct attribute *attr;
-  unsigned int line_offset;
   struct line_header line_header_local;
   hashval_t line_header_local_hash;
-  unsigned u;
   void **slot;
   int decode_mapping;
 
@@ -9103,7 +11465,7 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
   if (attr == NULL)
     return;
 
-  line_offset = DW_UNSND (attr);
+  sect_offset line_offset = (sect_offset) DW_UNSND (attr);
 
   /* The line header hash table is only created if needed (it exists to
      prevent redundant reading of the line table for partial_units).
@@ -9123,7 +11485,7 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
                                dummy_obstack_deallocate);
     }
 
-  line_header_local.offset.sect_off = line_offset;
+  line_header_local.sect_off = line_offset;
   line_header_local.offset_in_dwz = cu->per_cu->is_dwz;
   line_header_local_hash = line_header_hash (&line_header_local);
   if (dwarf2_per_objfile->line_header_hash != NULL)
@@ -9145,10 +11507,13 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
 
   /* dwarf_decode_line_header does not yet provide sufficient information.
      We always have to call also dwarf_decode_lines for it.  */
-  cu->line_header = dwarf_decode_line_header (line_offset, cu);
-  if (cu->line_header == NULL)
+  line_header_up lh = dwarf_decode_line_header (line_offset, cu);
+  if (lh == NULL)
     return;
 
+  cu->line_header = lh.release ();
+  cu->line_header_die_owner = die;
+
   if (dwarf2_per_objfile->line_header_hash == NULL)
     slot = NULL;
   else
@@ -9163,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
     {
@@ -9172,11 +11538,11 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
         number information unit.  And if we're not using line_header_hash
         then this is what we want as well.  */
       gdb_assert (die->tag != DW_TAG_partial_unit);
-      make_cleanup (free_cu_line_header, cu);
     }
   decode_mapping = (die->tag != DW_TAG_partial_unit);
   dwarf_decode_lines (cu->line_header, comp_dir, cu, NULL, lowpc,
                      decode_mapping);
+
 }
 
 /* Process DW_TAG_compile_unit or DW_TAG_partial_unit.  */
@@ -9186,12 +11552,9 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
-  struct cleanup *back_to = make_cleanup (null_cleanup, 0);
   CORE_ADDR lowpc = ((CORE_ADDR) -1);
   CORE_ADDR highpc = ((CORE_ADDR) 0);
   struct attribute *attr;
-  const char *name = NULL;
-  const char *comp_dir = NULL;
   struct die_info *child_die;
   CORE_ADDR baseaddr;
 
@@ -9205,7 +11568,7 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
     lowpc = highpc;
   lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
 
-  find_file_and_directory (die, cu, &name, &comp_dir);
+  file_and_directory fnd = find_file_and_directory (die, cu);
 
   prepare_one_comp_unit (cu, die, cu->language);
 
@@ -9219,12 +11582,12 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
   if (cu->producer && strstr (cu->producer, "GNU Go ") != NULL)
     set_cu_language (DW_LANG_Go, cu);
 
-  dwarf2_start_symtab (cu, name, comp_dir, lowpc);
+  dwarf2_start_symtab (cu, fnd.name, fnd.comp_dir, lowpc);
 
   /* Decode line number information if present.  We do this before
      processing child DIEs, so that the line header table is available
      for DW_AT_decl_file.  */
-  handle_DW_AT_stmt_list (die, cu, comp_dir, lowpc);
+  handle_DW_AT_stmt_list (die, cu, fnd.comp_dir, lowpc);
 
   /* Process all dies in compilation unit.  */
   if (die->child != NULL)
@@ -9241,12 +11604,14 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
      refers to information in the line number info statement program
      header, so we can only read it if we've read the header
      successfully.  */
-  attr = dwarf2_attr (die, DW_AT_GNU_macros, cu);
+  attr = dwarf2_attr (die, DW_AT_macros, cu);
+  if (attr == NULL)
+    attr = dwarf2_attr (die, DW_AT_GNU_macros, cu);
   if (attr && cu->line_header)
     {
       if (dwarf2_attr (die, DW_AT_macro_info, cu))
        complaint (&symfile_complaints,
-                  _("CU refers to both DW_AT_GNU_macros and DW_AT_macro_info"));
+                  _("CU refers to both DW_AT_macros and DW_AT_macro_info"));
 
       dwarf_decode_macros (cu, DW_UNSND (attr), 1);
     }
@@ -9260,8 +11625,6 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
          dwarf_decode_macros (cu, macro_offset, 0);
        }
     }
-
-  do_cleanups (back_to);
 }
 
 /* TU version of handle_DW_AT_stmt_list for read_type_unit_scope.
@@ -9276,9 +11639,8 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
   struct dwarf2_per_cu_data *per_cu = cu->per_cu;
   struct type_unit_group *tu_group;
   int first_time;
-  struct line_header *lh;
   struct attribute *attr;
-  unsigned int i, line_offset;
+  unsigned int i;
   struct signatured_type *sig_type;
 
   gdb_assert (per_cu->is_debug_types);
@@ -9300,10 +11662,10 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
 
   /* We have to handle the case of both a missing DW_AT_stmt_list or bad
      debug info.  */
-  lh = NULL;
+  line_header_up lh;
   if (attr != NULL)
     {
-      line_offset = DW_UNSND (attr);
+      sect_offset line_offset = (sect_offset) DW_UNSND (attr);
       lh = dwarf_decode_line_header (line_offset, cu);
     }
   if (lh == NULL)
@@ -9318,8 +11680,8 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
       return;
     }
 
-  cu->line_header = lh;
-  make_cleanup (free_cu_line_header, cu);
+  cu->line_header = lh.release ();
+  cu->line_header_die_owner = die;
 
   if (first_time)
     {
@@ -9330,41 +11692,40 @@ 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->num_file_names;
-      tu_group->symtabs = XNEWVEC (struct symtab *, lh->num_file_names);
+      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->num_file_names; ++i)
+      for (i = 0; i < cu->line_header->file_names.size (); ++i)
        {
-         const char *dir = NULL;
-         struct file_entry *fe = &lh->file_names[i];
+         file_entry &fe = cu->line_header->file_names[i];
 
-         if (fe->dir_index && lh->include_dirs != NULL)
-           dir = lh->include_dirs[fe->dir_index - 1];
-         dwarf2_start_subfile (fe->name, dir);
+         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);
            }
 
-         fe->symtab = current_subfile->symtab;
-         tu_group->symtabs[i] = fe->symtab;
+         fe.symtab = current_subfile->symtab;
+         tu_group->symtabs[i] = fe.symtab;
        }
     }
   else
     {
       restart_symtab (tu_group->compunit_symtab, "", 0);
 
-      for (i = 0; i < lh->num_file_names; ++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];
        }
     }
 
@@ -9529,7 +11890,7 @@ create_dwo_cu_reader (const struct die_reader_specs *reader,
                      void *datap)
 {
   struct dwarf2_cu *cu = reader->cu;
-  sect_offset offset = cu->per_cu->offset;
+  sect_offset sect_off = cu->per_cu->sect_off;
   struct dwarf2_section_info *section = cu->per_cu->section;
   struct create_dwo_cu_data *data = (struct create_dwo_cu_data *) datap;
   struct dwo_file *dwo_file = data->dwo_file;
@@ -9542,87 +11903,91 @@ create_dwo_cu_reader (const struct die_reader_specs *reader,
       complaint (&symfile_complaints,
                 _("Dwarf Error: debug entry at offset 0x%x is missing"
                   " its dwo_id [in module %s]"),
-                offset.sect_off, dwo_file->dwo_name);
+                to_underlying (sect_off), dwo_file->dwo_name);
       return;
     }
 
   dwo_unit->dwo_file = dwo_file;
   dwo_unit->signature = DW_UNSND (attr);
   dwo_unit->section = section;
-  dwo_unit->offset = offset;
+  dwo_unit->sect_off = sect_off;
   dwo_unit->length = cu->per_cu->length;
 
   if (dwarf_read_debug)
     fprintf_unfiltered (gdb_stdlog, "  offset 0x%x, dwo_id %s\n",
-                       offset.sect_off, hex_string (dwo_unit->signature));
+                       to_underlying (sect_off),
+                       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.offset.sect_off = 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:
@@ -10014,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);
@@ -10042,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)
     {
@@ -10094,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;
@@ -10139,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;
@@ -10186,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>",
@@ -10219,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);
@@ -10236,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)
     {
@@ -10294,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,
@@ -10353,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;
@@ -10627,10 +12980,10 @@ 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);
 
-  dwo_file->tus = create_debug_types_hash_table (dwo_file,
-                                                dwo_file->sections.types);
+  create_debug_types_hash_table (dwo_file, dwo_file->sections.types,
+                                dwo_file->tus);
 
   discard_cleanups (cleanups);
 
@@ -10814,49 +13167,44 @@ open_and_init_dwp_file (void)
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct dwp_file *dwp_file;
-  char *dwp_name;
-  struct cleanup *cleanups = make_cleanup (null_cleanup, 0);
 
   /* Try to find first .dwp for the binary file before any symbolic links
      resolving.  */
 
   /* If the objfile is a debug file, find the name of the real binary
      file and get the name of dwp file from there.  */
+  std::string dwp_name;
   if (objfile->separate_debug_objfile_backlink != NULL)
     {
       struct objfile *backlink = objfile->separate_debug_objfile_backlink;
       const char *backlink_basename = lbasename (backlink->original_name);
-      char *debug_dirname = ldirname (objfile->original_name);
 
-      make_cleanup (xfree, debug_dirname);
-      dwp_name = xstrprintf ("%s%s%s.dwp", debug_dirname,
-                            SLASH_STRING, backlink_basename);
+      dwp_name = ldirname (objfile->original_name) + SLASH_STRING + backlink_basename;
     }
   else
-    dwp_name = xstrprintf ("%s.dwp", objfile->original_name);
-  make_cleanup (xfree, dwp_name);
+    dwp_name = objfile->original_name;
 
-  gdb_bfd_ref_ptr dbfd (open_dwp_file (dwp_name));
+  dwp_name += ".dwp";
+
+  gdb_bfd_ref_ptr dbfd (open_dwp_file (dwp_name.c_str ()));
   if (dbfd == NULL
       && strcmp (objfile->original_name, objfile_name (objfile)) != 0)
     {
       /* Try to find .dwp for the binary file after gdb_realpath resolving.  */
-      dwp_name = xstrprintf ("%s.dwp", objfile_name (objfile));
-      make_cleanup (xfree, dwp_name);
-      dbfd = open_dwp_file (dwp_name);
+      dwp_name = objfile_name (objfile);
+      dwp_name += ".dwp";
+      dbfd = open_dwp_file (dwp_name.c_str ());
     }
 
   if (dbfd == NULL)
     {
       if (dwarf_read_debug)
-       fprintf_unfiltered (gdb_stdlog, "DWP file not found: %s\n", dwp_name);
-      do_cleanups (cleanups);
+       fprintf_unfiltered (gdb_stdlog, "DWP file not found: %s\n", dwp_name.c_str ());
       return NULL;
     }
   dwp_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwp_file);
   dwp_file->name = bfd_get_filename (dbfd.get ());
   dwp_file->dbfd = dbfd.release ();
-  do_cleanups (cleanups);
 
   /* +1: section 0 is unused */
   dwp_file->num_sections = bfd_count_sections (dwp_file->dbfd) + 1;
@@ -10872,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
@@ -10880,9 +13229,15 @@ open_and_init_dwp_file (void)
       error (_("Dwarf Error: DWP file CU version %s doesn't match"
               " TU version %s [in DWP file %s]"),
             pulongest (dwp_file->cus->version),
-            pulongest (dwp_file->tus->version), dwp_name);
+            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,
@@ -10999,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)
@@ -11033,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",
-            this_unit->offset.sect_off, objfile_name (objfile));
-
-    do_cleanups (cleanups);
+            to_underlying (this_unit->sect_off), objfile_name (objfile));
   }
   return NULL;
 }
@@ -11170,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
@@ -11190,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;
@@ -11223,19 +13564,11 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
           && origin_die->tag == DW_TAG_subprogram))
     complaint (&symfile_complaints,
               _("DIE 0x%x and its abstract origin 0x%x have different tags"),
-              die->offset.sect_off, origin_die->offset.sect_off);
+              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))
@@ -11244,11 +13577,12 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
       struct dwarf2_cu *child_origin_cu;
 
       /* We are trying to process concrete instance entries:
-        DW_TAG_GNU_call_site DIEs indeed have a DW_AT_abstract_origin tag, but
+        DW_TAG_call_site DIEs indeed have a DW_AT_abstract_origin tag, but
         it's not relevant to our analysis here. i.e. detecting DIEs that are
         present in the abstract instance but not referenced in the concrete
         one.  */
-      if (child_die->tag == DW_TAG_GNU_call_site)
+      if (child_die->tag == DW_TAG_call_site
+          || child_die->tag == DW_TAG_GNU_call_site)
        continue;
 
       /* For each CHILD_DIE, find the corresponding child of
@@ -11277,36 +13611,38 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
                   && child_origin_die->tag == DW_TAG_subprogram))
            complaint (&symfile_complaints,
                       _("Child DIE 0x%x and its abstract origin 0x%x have "
-                        "different tags"), child_die->offset.sect_off,
-                      child_origin_die->offset.sect_off);
+                        "different tags"),
+                      to_underlying (child_die->sect_off),
+                      to_underlying (child_origin_die->sect_off));
          if (child_origin_die->parent != origin_die)
            complaint (&symfile_complaints,
                       _("Child DIE 0x%x and its abstract origin 0x%x have "
-                        "different parents"), child_die->offset.sect_off,
-                      child_origin_die->offset.sect_off);
+                        "different parents"),
+                      to_underlying (child_die->sect_off),
+                      to_underlying (child_origin_die->sect_off));
          else
-           *offsets_end++ = child_origin_die->offset;
+           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++)
-    if (offsetp[-1].sect_off == offsetp->sect_off)
+  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"),
-                die->offset.sect_off, offsetp->sect_off);
+                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)
     {
       /* Is ORIGIN_CHILD_DIE referenced by any of the DIE children?  */
       while (offsetp < offsets_end
-            && offsetp->sect_off < origin_child_die->offset.sect_off)
+            && *offsetp < origin_child_die->sect_off)
        offsetp++;
       if (offsetp >= offsets_end
-         || offsetp->sect_off > origin_child_die->offset.sect_off)
+         || *offsetp > origin_child_die->sect_off)
        {
          /* Found that ORIGIN_CHILD_DIE is really not referenced.
             Check whether we're already processing ORIGIN_CHILD_DIE.
@@ -11318,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
@@ -11336,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)
@@ -11363,7 +13697,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
     {
       complaint (&symfile_complaints,
                 _("missing name for subprogram DIE at %d"),
-                die->offset.sect_off);
+                to_underlying (die->sect_off));
       return;
     }
 
@@ -11376,7 +13710,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
        complaint (&symfile_complaints,
                   _("cannot get low and high bounds "
                     "for subprogram DIE at %d"),
-                  die->offset.sect_off);
+                  to_underlying (die->sect_off));
       return;
     }
 
@@ -11391,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;
        }
     }
@@ -11429,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);
@@ -11484,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
@@ -11583,7 +13916,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
   local_using_directives = newobj->local_using_directives;
 }
 
-/* Read in DW_TAG_GNU_call_site and insert it to CU->call_site_htab.  */
+/* Read in DW_TAG_call_site and insert it to CU->call_site_htab.  */
 
 static void
 read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
@@ -11599,13 +13932,19 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
 
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
-  attr = dwarf2_attr (die, DW_AT_low_pc, cu);
+  attr = dwarf2_attr (die, DW_AT_call_return_pc, cu);
+  if (attr == NULL)
+    {
+      /* This was a pre-DWARF-5 GNU extension alias
+        for DW_AT_call_return_pc.  */
+      attr = dwarf2_attr (die, DW_AT_low_pc, cu);
+    }
   if (!attr)
     {
       complaint (&symfile_complaints,
-                _("missing DW_AT_low_pc for DW_TAG_GNU_call_site "
+                _("missing DW_AT_call_return_pc for DW_TAG_call_site "
                   "DIE 0x%x [in module %s]"),
-                die->offset.sect_off, objfile_name (objfile));
+                to_underlying (die->sect_off), objfile_name (objfile));
       return;
     }
   pc = attr_value_as_address (attr) + baseaddr;
@@ -11620,9 +13959,9 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
   if (*slot != NULL)
     {
       complaint (&symfile_complaints,
-                _("Duplicate PC %s for DW_TAG_GNU_call_site "
+                _("Duplicate PC %s for DW_TAG_call_site "
                   "DIE 0x%x [in module %s]"),
-                paddress (gdbarch, pc), die->offset.sect_off,
+                paddress (gdbarch, pc), to_underlying (die->sect_off),
                 objfile_name (objfile));
       return;
     }
@@ -11633,12 +13972,13 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
   for (child_die = die->child; child_die && child_die->tag;
        child_die = sibling_die (child_die))
     {
-      if (child_die->tag != DW_TAG_GNU_call_site_parameter)
+      if (child_die->tag != DW_TAG_call_site_parameter
+          && child_die->tag != DW_TAG_GNU_call_site_parameter)
        {
          complaint (&symfile_complaints,
-                    _("Tag %d is not DW_TAG_GNU_call_site_parameter in "
-                      "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
-                    child_die->tag, child_die->offset.sect_off,
+                    _("Tag %d is not DW_TAG_call_site_parameter in "
+                      "DW_TAG_call_site child DIE 0x%x [in module %s]"),
+                    child_die->tag, to_underlying (child_die->sect_off),
                     objfile_name (objfile));
          continue;
        }
@@ -11655,7 +13995,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
   memset (call_site, 0, sizeof (*call_site) - sizeof (*call_site->parameter));
   call_site->pc = pc;
 
-  if (dwarf2_flag_true_p (die, DW_AT_GNU_tail_call, cu))
+  if (dwarf2_flag_true_p (die, DW_AT_call_tail_call, cu)
+      || dwarf2_flag_true_p (die, DW_AT_GNU_tail_call, cu))
     {
       struct die_info *func_die;
 
@@ -11665,10 +14006,12 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
           && func_die->tag != DW_TAG_subroutine_type;
           func_die = func_die->parent);
 
-      /* DW_AT_GNU_all_call_sites is a superset
-        of DW_AT_GNU_all_tail_call_sites.  */
+      /* DW_AT_call_all_calls is a superset
+        of DW_AT_call_all_tail_calls.  */
       if (func_die
+          && !dwarf2_flag_true_p (func_die, DW_AT_call_all_calls, cu)
           && !dwarf2_flag_true_p (func_die, DW_AT_GNU_all_call_sites, cu)
+         && !dwarf2_flag_true_p (func_die, DW_AT_call_all_tail_calls, cu)
          && !dwarf2_flag_true_p (func_die, DW_AT_GNU_all_tail_call_sites, cu))
        {
          /* TYPE_TAIL_CALL_LIST is not interesting in functions where it is
@@ -11696,15 +14039,22 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
            }
          else
            complaint (&symfile_complaints,
-                      _("Cannot find function owning DW_TAG_GNU_call_site "
+                      _("Cannot find function owning DW_TAG_call_site "
                         "DIE 0x%x [in module %s]"),
-                      die->offset.sect_off, objfile_name (objfile));
+                      to_underlying (die->sect_off), objfile_name (objfile));
        }
     }
 
-  attr = dwarf2_attr (die, DW_AT_GNU_call_site_target, cu);
+  attr = dwarf2_attr (die, DW_AT_call_target, cu);
+  if (attr == NULL)
+    attr = dwarf2_attr (die, DW_AT_GNU_call_site_target, cu);
+  if (attr == NULL)
+    attr = dwarf2_attr (die, DW_AT_call_origin, cu);
   if (attr == NULL)
-    attr = dwarf2_attr (die, DW_AT_abstract_origin, cu);
+    {
+      /* This was a pre-DWARF-5 GNU extension alias for DW_AT_call_origin.  */
+      attr = dwarf2_attr (die, DW_AT_abstract_origin, cu);
+    }
   SET_FIELD_DWARF_BLOCK (call_site->target, NULL);
   if (!attr || (attr_form_is_block (attr) && DW_BLOCK (attr)->size == 0))
     /* Keep NULL DWARF_BLOCK.  */;
@@ -11731,20 +14081,14 @@ 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)
            complaint (&symfile_complaints,
-                      _("DW_AT_GNU_call_site_target target DIE has invalid "
+                      _("DW_AT_call_target target DIE has invalid "
                         "physname, for referencing DIE 0x%x [in module %s]"),
-                      die->offset.sect_off, objfile_name (objfile));
+                      to_underlying (die->sect_off), objfile_name (objfile));
          else
            SET_FIELD_PHYSNAME (call_site->target, target_physname);
        }
@@ -11756,9 +14100,9 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
          if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu, NULL)
              <= PC_BOUNDS_INVALID)
            complaint (&symfile_complaints,
-                      _("DW_AT_GNU_call_site_target target DIE has invalid "
+                      _("DW_AT_call_target target DIE has invalid "
                         "low pc, for referencing DIE 0x%x [in module %s]"),
-                      die->offset.sect_off, objfile_name (objfile));
+                      to_underlying (die->sect_off), objfile_name (objfile));
          else
            {
              lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
@@ -11768,9 +14112,9 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
     }
   else
     complaint (&symfile_complaints,
-              _("DW_TAG_GNU_call_site DW_AT_GNU_call_site_target is neither "
+              _("DW_TAG_call_site DW_AT_call_target is neither "
                 "block nor reference, for DIE 0x%x [in module %s]"),
-              die->offset.sect_off, objfile_name (objfile));
+              to_underlying (die->sect_off), objfile_name (objfile));
 
   call_site->per_cu = cu->per_cu;
 
@@ -11781,7 +14125,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
       struct call_site_parameter *parameter;
       struct attribute *loc, *origin;
 
-      if (child_die->tag != DW_TAG_GNU_call_site_parameter)
+      if (child_die->tag != DW_TAG_call_site_parameter
+          && child_die->tag != DW_TAG_GNU_call_site_parameter)
        {
          /* Already printed the complaint above.  */
          continue;
@@ -11792,37 +14137,43 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
 
       /* DW_AT_location specifies the register number or DW_AT_abstract_origin
         specifies DW_TAG_formal_parameter.  Value of the data assumed for the
-        register is contained in DW_AT_GNU_call_site_value.  */
+        register is contained in DW_AT_call_value.  */
 
       loc = dwarf2_attr (child_die, DW_AT_location, cu);
-      origin = dwarf2_attr (child_die, DW_AT_abstract_origin, cu);
+      origin = dwarf2_attr (child_die, DW_AT_call_parameter, cu);
+      if (origin == NULL)
+       {
+         /* This was a pre-DWARF-5 GNU extension alias
+            for DW_AT_call_parameter.  */
+         origin = dwarf2_attr (child_die, DW_AT_abstract_origin, cu);
+       }
       if (loc == NULL && origin != NULL && attr_form_is_ref (origin))
        {
-         sect_offset offset;
-
          parameter->kind = CALL_SITE_PARAMETER_PARAM_OFFSET;
-         offset = dwarf2_get_ref_die_offset (origin);
-         if (!offset_in_cu_p (&cu->header, offset))
+
+         sect_offset sect_off
+           = (sect_offset) dwarf2_get_ref_die_offset (origin);
+         if (!offset_in_cu_p (&cu->header, sect_off))
            {
              /* As DW_OP_GNU_parameter_ref uses CU-relative offset this
                 binding can be done only inside one CU.  Such referenced DIE
                 therefore cannot be even moved to DW_TAG_partial_unit.  */
              complaint (&symfile_complaints,
-                        _("DW_AT_abstract_origin offset is not in CU for "
-                          "DW_TAG_GNU_call_site child DIE 0x%x "
-                          "[in module %s]"),
-                        child_die->offset.sect_off, objfile_name (objfile));
+                        _("DW_AT_call_parameter offset is not in CU for "
+                          "DW_TAG_call_site child DIE 0x%x [in module %s]"),
+                        to_underlying (child_die->sect_off),
+                        objfile_name (objfile));
              continue;
            }
-         parameter->u.param_offset.cu_off = (offset.sect_off
-                                             - cu->header.offset.sect_off);
+         parameter->u.param_cu_off
+           = (cu_offset) (sect_off - cu->header.sect_off);
        }
       else if (loc == NULL || origin != NULL || !attr_form_is_block (loc))
        {
          complaint (&symfile_complaints,
                     _("No DW_FORM_block* DW_AT_location for "
-                      "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
-                    child_die->offset.sect_off, objfile_name (objfile));
+                      "DW_TAG_call_site child DIE 0x%x [in module %s]"),
+                    to_underlying (child_die->sect_off), objfile_name (objfile));
          continue;
        }
       else
@@ -11840,20 +14191,24 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
              complaint (&symfile_complaints,
                         _("Only single DW_OP_reg or DW_OP_fbreg is supported "
                           "for DW_FORM_block* DW_AT_location is supported for "
-                          "DW_TAG_GNU_call_site child DIE 0x%x "
+                          "DW_TAG_call_site child DIE 0x%x "
                           "[in module %s]"),
-                        child_die->offset.sect_off, objfile_name (objfile));
+                        to_underlying (child_die->sect_off),
+                        objfile_name (objfile));
              continue;
            }
        }
 
-      attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_value, cu);
+      attr = dwarf2_attr (child_die, DW_AT_call_value, cu);
+      if (attr == NULL)
+       attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_value, cu);
       if (!attr_form_is_block (attr))
        {
          complaint (&symfile_complaints,
-                    _("No DW_FORM_block* DW_AT_GNU_call_site_value for "
-                      "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
-                    child_die->offset.sect_off, objfile_name (objfile));
+                    _("No DW_FORM_block* DW_AT_call_value for "
+                      "DW_TAG_call_site child DIE 0x%x [in module %s]"),
+                    to_underlying (child_die->sect_off),
+                    objfile_name (objfile));
          continue;
        }
       parameter->value = DW_BLOCK (attr)->data;
@@ -11864,14 +14219,17 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
       parameter->data_value_size = 0;
       call_site->parameter_count++;
 
-      attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_data_value, cu);
+      attr = dwarf2_attr (child_die, DW_AT_call_data_value, cu);
+      if (attr == NULL)
+       attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_data_value, cu);
       if (attr)
        {
          if (!attr_form_is_block (attr))
            complaint (&symfile_complaints,
-                      _("No DW_FORM_block* DW_AT_GNU_call_site_data_value for "
-                        "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
-                      child_die->offset.sect_off, objfile_name (objfile));
+                      _("No DW_FORM_block* DW_AT_call_data_value for "
+                        "DW_TAG_call_site child DIE 0x%x [in module %s]"),
+                      to_underlying (child_die->sect_off),
+                      objfile_name (objfile));
          else
            {
              parameter->data_value = DW_BLOCK (attr)->data;
@@ -11881,17 +14239,236 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
     }
 }
 
-/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
-   Return 1 if the attributes are present and valid, otherwise, return 0.
-   If RANGES_PST is not NULL we should setup `objfile->psymtabs_addrmap'.  */
+/* 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:
+    void (CORE_ADDR range_beginning, CORE_ADDR range_end)
+   Return true if the attributes are present and valid, otherwise,
+   return false.  */
+
+template <typename Callback>
+static bool
+dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
+                        Callback &&callback)
+{
+  struct objfile *objfile = cu->objfile;
+  bfd *obfd = objfile->obfd;
+  /* Base address selection entry.  */
+  CORE_ADDR base;
+  int found_base;
+  const gdb_byte *buffer;
+  CORE_ADDR baseaddr;
+  bool overflow = false;
+
+  found_base = cu->base_known;
+  base = cu->base_address;
+
+  dwarf2_read_section (objfile, &dwarf2_per_objfile->rnglists);
+  if (offset >= dwarf2_per_objfile->rnglists.size)
+    {
+      complaint (&symfile_complaints,
+                _("Offset %d out of bounds for DW_AT_ranges attribute"),
+                offset);
+      return false;
+    }
+  buffer = dwarf2_per_objfile->rnglists.buffer + offset;
+
+  baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+  while (1)
+    {
+      /* Initialize it due to a false compiler warning.  */
+      CORE_ADDR range_beginning = 0, range_end = 0;
+      const gdb_byte *buf_end = (dwarf2_per_objfile->rnglists.buffer
+                                + dwarf2_per_objfile->rnglists.size);
+      unsigned int bytes_read;
+
+      if (buffer == buf_end)
+       {
+         overflow = true;
+         break;
+       }
+      const auto rlet = static_cast<enum dwarf_range_list_entry>(*buffer++);
+      switch (rlet)
+       {
+       case DW_RLE_end_of_list:
+         break;
+       case DW_RLE_base_address:
+         if (buffer + cu->header.addr_size > buf_end)
+           {
+             overflow = true;
+             break;
+           }
+         base = read_address (obfd, buffer, cu, &bytes_read);
+         found_base = 1;
+         buffer += bytes_read;
+         break;
+       case DW_RLE_start_length:
+         if (buffer + cu->header.addr_size > buf_end)
+           {
+             overflow = true;
+             break;
+           }
+         range_beginning = read_address (obfd, buffer, cu, &bytes_read);
+         buffer += bytes_read;
+         range_end = (range_beginning
+                      + read_unsigned_leb128 (obfd, buffer, &bytes_read));
+         buffer += bytes_read;
+         if (buffer > buf_end)
+           {
+             overflow = true;
+             break;
+           }
+         break;
+       case DW_RLE_offset_pair:
+         range_beginning = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+         buffer += bytes_read;
+         if (buffer > buf_end)
+           {
+             overflow = true;
+             break;
+           }
+         range_end = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+         buffer += bytes_read;
+         if (buffer > buf_end)
+           {
+             overflow = true;
+             break;
+           }
+         break;
+       case DW_RLE_start_end:
+         if (buffer + 2 * cu->header.addr_size > buf_end)
+           {
+             overflow = true;
+             break;
+           }
+         range_beginning = read_address (obfd, buffer, cu, &bytes_read);
+         buffer += bytes_read;
+         range_end = read_address (obfd, buffer, cu, &bytes_read);
+         buffer += bytes_read;
+         break;
+       default:
+         complaint (&symfile_complaints,
+                    _("Invalid .debug_rnglists data (no base address)"));
+         return false;
+       }
+      if (rlet == DW_RLE_end_of_list || overflow)
+       break;
+      if (rlet == DW_RLE_base_address)
+       continue;
+
+      if (!found_base)
+       {
+         /* We have no valid base address for the ranges
+            data.  */
+         complaint (&symfile_complaints,
+                    _("Invalid .debug_rnglists data (no base address)"));
+         return false;
+       }
+
+      if (range_beginning > range_end)
+       {
+         /* Inverted range entries are invalid.  */
+         complaint (&symfile_complaints,
+                    _("Invalid .debug_rnglists data (inverted range)"));
+         return false;
+       }
+
+      /* Empty range entries have no effect.  */
+      if (range_beginning == range_end)
+       continue;
+
+      range_beginning += base;
+      range_end += base;
+
+      /* A not-uncommon case of bad debug info.
+        Don't pollute the addrmap with bad data.  */
+      if (range_beginning + baseaddr == 0
+         && !dwarf2_per_objfile->has_section_at_zero)
+       {
+         complaint (&symfile_complaints,
+                    _(".debug_rnglists entry has start address of zero"
+                      " [in module %s]"), objfile_name (objfile));
+         continue;
+       }
+
+      callback (range_beginning, range_end);
+    }
+
+  if (overflow)
+    {
+      complaint (&symfile_complaints,
+                _("Offset %d is not terminated "
+                  "for DW_AT_ranges attribute"),
+                offset);
+      return false;
+    }
+
+  return true;
+}
 
+/* Call CALLBACK from DW_AT_ranges attribute value OFFSET reading .debug_ranges.
+   Callback's type should be:
+    void (CORE_ADDR range_beginning, CORE_ADDR range_end)
+   Return 1 if the attributes are present and valid, otherwise, return 0.  */
+
+template <typename Callback>
 static int
-dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
-                   CORE_ADDR *high_return, struct dwarf2_cu *cu,
-                   struct partial_symtab *ranges_pst)
+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;
@@ -11901,11 +14478,11 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
   int found_base;
   unsigned int dummy;
   const gdb_byte *buffer;
-  int low_set;
-  CORE_ADDR low = 0;
-  CORE_ADDR high = 0;
   CORE_ADDR baseaddr;
 
+  if (cu_header->version >= 5)
+    return dwarf2_rnglists_process (offset, cu, callback);
+
   found_base = cu->base_known;
   base = cu->base_address;
 
@@ -11919,8 +14496,6 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
     }
   buffer = dwarf2_per_objfile->ranges.buffer + offset;
 
-  low_set = 0;
-
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
   while (1)
@@ -11985,6 +14560,33 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
          continue;
        }
 
+      callback (range_beginning, range_end);
+    }
+
+  return 1;
+}
+
+/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
+   Return 1 if the attributes are present and valid, otherwise, return 0.
+   If RANGES_PST is not NULL we should setup `objfile->psymtabs_addrmap'.  */
+
+static int
+dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
+                   CORE_ADDR *high_return, struct dwarf2_cu *cu,
+                   struct partial_symtab *ranges_pst)
+{
+  struct objfile *objfile = cu->objfile;
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  const CORE_ADDR baseaddr = ANOFFSET (objfile->section_offsets,
+                                      SECT_OFF_TEXT (objfile));
+  int low_set = 0;
+  CORE_ADDR low = 0;
+  CORE_ADDR high = 0;
+  int retval;
+
+  retval = dwarf2_ranges_process (offset, cu,
+    [&] (CORE_ADDR range_beginning, CORE_ADDR range_end)
+    {
       if (ranges_pst != NULL)
        {
          CORE_ADDR lowpc;
@@ -12015,7 +14617,9 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
          if (range_end > high)
            high = range_end;
        }
-    }
+    });
+  if (!retval)
+    return 0;
 
   if (! low_set)
     /* If the first entry is an end-of-list marker, the range
@@ -12238,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.  */
@@ -12267,79 +14870,15 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
       CORE_ADDR base = cu->base_address;
       int base_known = cu->base_known;
 
-      dwarf2_read_section (objfile, &dwarf2_per_objfile->ranges);
-      if (offset >= dwarf2_per_objfile->ranges.size)
-        {
-          complaint (&symfile_complaints,
-                     _("Offset %lu out of bounds for DW_AT_ranges attribute"),
-                     offset);
-          return;
-        }
-      buffer = dwarf2_per_objfile->ranges.buffer + offset;
-
-      for (;;)
-        {
-          unsigned int bytes_read;
-          CORE_ADDR start, end;
-
-          start = read_address (obfd, buffer, cu, &bytes_read);
-          buffer += bytes_read;
-          end = read_address (obfd, buffer, cu, &bytes_read);
-          buffer += bytes_read;
-
-          /* Did we find the end of the range list?  */
-          if (start == 0 && end == 0)
-            break;
-
-          /* Did we find a base address selection entry?  */
-          else if ((start & base_select_mask) == base_select_mask)
-            {
-              base = end;
-              base_known = 1;
-            }
-
-          /* We found an ordinary address range.  */
-          else
-            {
-              if (!base_known)
-                {
-                  complaint (&symfile_complaints,
-                            _("Invalid .debug_ranges data "
-                              "(no base address)"));
-                  return;
-                }
-
-             if (start > end)
-               {
-                 /* Inverted range entries are invalid.  */
-                 complaint (&symfile_complaints,
-                            _("Invalid .debug_ranges data "
-                              "(inverted range)"));
-                 return;
-               }
-
-             /* Empty range entries have no effect.  */
-             if (start == end)
-               continue;
-
-             start += base + baseaddr;
-             end += base + baseaddr;
-
-             /* A not-uncommon case of bad debug info.
-                Don't pollute the addrmap with bad data.  */
-             if (start == 0 && !dwarf2_per_objfile->has_section_at_zero)
-               {
-                 complaint (&symfile_complaints,
-                            _(".debug_ranges entry has start address of zero"
-                              " [in module %s]"), objfile_name (objfile));
-                 continue;
-               }
-
-             start = gdbarch_adjust_dwarf2_addr (gdbarch, start);
-             end = gdbarch_adjust_dwarf2_addr (gdbarch, end);
-              record_block_range (block, start, end - 1);
-            }
-        }
+      dwarf2_ranges_process (offset, cu,
+       [&] (CORE_ADDR start, CORE_ADDR end)
+       {
+         start += baseaddr;
+         end += baseaddr;
+         start = gdbarch_adjust_dwarf2_addr (gdbarch, start);
+         end = gdbarch_adjust_dwarf2_addr (gdbarch, end);
+         record_block_range (block, start, end - 1);
+       });
     }
 }
 
@@ -12367,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
@@ -12646,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.  */
@@ -12981,7 +15568,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
                  complaint (&symfile_complaints,
                             _("cannot determine context for virtual member "
                               "function \"%s\" (offset %d)"),
-                            fieldname, die->offset.sect_off);
+                            fieldname, to_underlying (die->sect_off));
                }
              else
                {
@@ -13009,7 +15596,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
          complaint (&symfile_complaints,
                     _("Member function \"%s\" (offset %d) is virtual "
                       "but the vtable offset is not specified"),
-                    fieldname, die->offset.sect_off);
+                    fieldname, to_underlying (die->sect_off));
          ALLOCATE_CPLUS_STRUCT_TYPE (type);
          TYPE_CPLUS_DYNAMIC (type) = 1;
        }
@@ -13055,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]))
@@ -13106,21 +15692,10 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
   smash_to_method_type (new_type, self_type, TYPE_TARGET_TYPE (pfn_type),
                        TYPE_FIELDS (pfn_type), TYPE_NFIELDS (pfn_type),
                        TYPE_VARARGS (pfn_type));
-  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;
+  smash_to_methodptr_type (type, new_type);
 }
 
+
 /* 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
    the type's name and general properties; the members will not be
@@ -13225,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
@@ -13270,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));
@@ -13307,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.  */
@@ -13417,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;
@@ -13433,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);
     }
 
@@ -13479,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;
@@ -13532,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
@@ -13699,8 +16291,8 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
       struct signatured_type *sig_type;
 
       sig_type = (struct signatured_type *) cu->per_cu;
-      gdb_assert (sig_type->type_offset_in_section.sect_off != 0);
-      if (sig_type->type_offset_in_section.sect_off != die->offset.sect_off)
+      gdb_assert (to_underlying (sig_type->type_offset_in_section) != 0);
+      if (sig_type->type_offset_in_section != die->sect_off)
        return;
     }
 
@@ -13718,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;
 
@@ -13751,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)
     {
@@ -13763,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);
@@ -13786,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);
@@ -13831,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;
 }
 
@@ -13940,7 +16520,7 @@ mark_common_block_symbol_computed (struct symbol *sym,
   baton->data = ptr;
 
   *ptr++ = DW_OP_call4;
-  cu_off = common_die->offset.sect_off - cu->per_cu->offset.sect_off;
+  cu_off = common_die->sect_off - cu->per_cu->sect_off;
   store_unsigned_integer (ptr, 4, byte_order, cu_off);
   ptr += 4;
 
@@ -14043,7 +16623,7 @@ read_common_block (struct die_info *die, struct dwarf2_cu *cu)
                             _("Variable in common block has "
                               "DW_AT_data_member_location "
                               "- DIE at 0x%x [in module %s]"),
-                            child_die->offset.sect_off,
+                            to_underlying (child_die->sect_off),
                             objfile_name (cu->objfile));
 
                  if (attr_form_is_section_offset (member_loc))
@@ -14130,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);
        }
     }
 
@@ -14163,7 +16744,7 @@ read_module_type (struct die_info *die, struct dwarf2_cu *cu)
   if (!module_name)
     complaint (&symfile_complaints,
               _("DW_TAG_module has no name, offset 0x%x"),
-               die->offset.sect_off);
+               to_underlying (die->sect_off));
   type = init_type (objfile, TYPE_CODE_MODULE, 0, module_name);
 
   /* determine_prefix uses TYPE_TAG_NAME.  */
@@ -14323,16 +16904,19 @@ read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu)
   return set_die_type (die, type, cu);
 }
 
-/* Extract all information from a DW_TAG_reference_type DIE and add to
+/* Extract all information from a DW_TAG_{rvalue_,}reference_type DIE and add to
    the user defined type vector.  */
 
 static struct type *
-read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu)
+read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu,
+                          enum type_code refcode)
 {
   struct comp_unit_head *cu_header = &cu->header;
   struct type *type, *target_type;
   struct attribute *attr;
 
+  gdb_assert (refcode == TYPE_CODE_REF || refcode == TYPE_CODE_RVALUE_REF);
+
   target_type = die_type (die, cu);
 
   /* The die_type call above may have already set the type for this DIE.  */
@@ -14340,7 +16924,7 @@ read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu)
   if (type)
     return type;
 
-  type = lookup_reference_type (target_type);
+  type = lookup_reference_type (target_type, refcode);
   attr = dwarf2_attr (die, DW_AT_byte_size, cu);
   if (attr)
     {
@@ -14703,7 +17287,7 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu)
       complaint (&symfile_complaints,
                 _("Self-referential DW_TAG_typedef "
                   "- DIE at 0x%x [in module %s]"),
-                die->offset.sect_off, objfile_name (objfile));
+                to_underlying (die->sect_off), objfile_name (objfile));
       TYPE_TARGET_TYPE (this_type) = NULL;
     }
   return this_type;
@@ -14725,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;
 }
@@ -14763,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:
@@ -14808,16 +17392,28 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
          type = init_integer_type (objfile, bits, 1, name);
        break;
       case DW_ATE_UTF:
-       /* We just treat this as an integer and then recognize the
-          type by name elsewhere.  */
-       type = init_integer_type (objfile, bits, 0, name);
+       {
+         gdbarch *arch = get_objfile_arch (objfile);
+
+         if (bits == 16)
+           type = builtin_type (arch)->builtin_char16;
+         else if (bits == 32)
+           type = builtin_type (arch)->builtin_char32;
+         else
+           {
+             complaint (&symfile_complaints,
+                        _("unsupported DW_ATE_UTF bit size: '%d'"),
+                        bits);
+             type = init_integer_type (objfile, bits, 1, name);
+           }
+         return set_die_type (die, type, cu);
+       }
        break;
 
       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;
     }
 
@@ -14997,7 +17593,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
   else if (!low_default_is_valid)
     complaint (&symfile_complaints, _("Missing DW_AT_lower_bound "
                                      "- DIE at 0x%x [in module %s]"),
-              die->offset.sect_off, objfile_name (cu->objfile));
+              to_underlying (die->sect_off), objfile_name (cu->objfile));
 
   attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
   if (!attr_to_dynamic_prop (attr, die, cu, &high))
@@ -15219,13 +17815,12 @@ read_full_die_1 (const struct die_reader_specs *reader,
                 int *has_children, int num_extra_attrs)
 {
   unsigned int abbrev_number, bytes_read, i;
-  sect_offset offset;
   struct abbrev_info *abbrev;
   struct die_info *die;
   struct dwarf2_cu *cu = reader->cu;
   bfd *abfd = reader->abfd;
 
-  offset.sect_off = info_ptr - reader->buffer;
+  sect_offset sect_off = (sect_offset) (info_ptr - reader->buffer);
   abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
   info_ptr += bytes_read;
   if (!abbrev_number)
@@ -15242,7 +17837,7 @@ read_full_die_1 (const struct die_reader_specs *reader,
           bfd_get_filename (abfd));
 
   die = dwarf_alloc_die (cu, abbrev->num_attrs + num_extra_attrs);
-  die->offset = offset;
+  die->sect_off = sect_off;
   die->tag = abbrev->tag;
   die->abbrev = abbrev_number;
 
@@ -15347,7 +17942,7 @@ abbrev_table_lookup_abbrev (const struct abbrev_table *abbrev_table,
 
 static struct abbrev_table *
 abbrev_table_read_table (struct dwarf2_section_info *section,
-                        sect_offset offset)
+                        sect_offset sect_off)
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   bfd *abfd = get_section_bfd_owner (section);
@@ -15360,7 +17955,7 @@ abbrev_table_read_table (struct dwarf2_section_info *section,
   unsigned int allocated_attrs;
 
   abbrev_table = XNEW (struct abbrev_table);
-  abbrev_table->offset = offset;
+  abbrev_table->sect_off = sect_off;
   obstack_init (&abbrev_table->abbrev_obstack);
   abbrev_table->abbrevs =
     XOBNEWVEC (&abbrev_table->abbrev_obstack, struct abbrev_info *,
@@ -15369,7 +17964,7 @@ abbrev_table_read_table (struct dwarf2_section_info *section,
          ABBREV_HASH_SIZE * sizeof (struct abbrev_info *));
 
   dwarf2_read_section (objfile, section);
-  abbrev_ptr = section->buffer + offset.sect_off;
+  abbrev_ptr = section->buffer + to_underlying (sect_off);
   abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
   abbrev_ptr += bytes_read;
 
@@ -15390,12 +17985,29 @@ abbrev_table_read_table (struct dwarf2_section_info *section,
       abbrev_ptr += 1;
 
       /* now read in declarations */
-      abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
-      abbrev_ptr += bytes_read;
-      abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
-      abbrev_ptr += bytes_read;
-      while (abbrev_name)
+      for (;;)
        {
+         LONGEST implicit_const;
+
+         abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+         abbrev_ptr += bytes_read;
+         abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+         abbrev_ptr += bytes_read;
+         if (abbrev_form == DW_FORM_implicit_const)
+           {
+             implicit_const = read_signed_leb128 (abfd, abbrev_ptr,
+                                                  &bytes_read);
+             abbrev_ptr += bytes_read;
+           }
+         else
+           {
+             /* Initialize it due to a false compiler warning.  */
+             implicit_const = -1;
+           }
+
+         if (abbrev_name == 0)
+           break;
+
          if (cur_abbrev->num_attrs == allocated_attrs)
            {
              allocated_attrs += ATTR_ALLOC_CHUNK;
@@ -15405,12 +18017,10 @@ abbrev_table_read_table (struct dwarf2_section_info *section,
 
          cur_attrs[cur_abbrev->num_attrs].name
            = (enum dwarf_attribute) abbrev_name;
-         cur_attrs[cur_abbrev->num_attrs++].form
+         cur_attrs[cur_abbrev->num_attrs].form
            = (enum dwarf_form) abbrev_form;
-         abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
-         abbrev_ptr += bytes_read;
-         abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
-         abbrev_ptr += bytes_read;
+         cur_attrs[cur_abbrev->num_attrs].implicit_const = implicit_const;
+         ++cur_abbrev->num_attrs;
        }
 
       cur_abbrev->attrs =
@@ -15471,7 +18081,7 @@ dwarf2_read_abbrevs (struct dwarf2_cu *cu,
                     struct dwarf2_section_info *abbrev_section)
 {
   cu->abbrev_table =
-    abbrev_table_read_table (abbrev_section, cu->header.abbrev_offset);
+    abbrev_table_read_table (abbrev_section, cu->header.abbrev_sect_off);
 }
 
 /* Release the memory used by the abbrev table for a compilation unit.  */
@@ -15673,7 +18283,7 @@ load_partial_dies (const struct die_reader_specs *reader,
        complaint (&symfile_complaints,
                   _("DW_TAG_typedef has childen - GCC PR debug/47510 bug "
                     "- DIE at 0x%x [in module %s]"),
-                  part_die->offset.sect_off, objfile_name (objfile));
+                  to_underlying (part_die->sect_off), objfile_name (objfile));
 
       /* If we're at the second level, and we're an enumerator, and
         our parent has no specification (meaning possibly lives in a
@@ -15746,7 +18356,8 @@ load_partial_dies (const struct die_reader_specs *reader,
          void **slot;
 
          slot = htab_find_slot_with_hash (cu->partial_dies, part_die,
-                                          part_die->offset.sect_off, INSERT);
+                                          to_underlying (part_die->sect_off),
+                                          INSERT);
          *slot = part_die;
        }
 
@@ -15813,7 +18424,7 @@ read_partial_die (const struct die_reader_specs *reader,
 
   memset (part_die, 0, sizeof (struct partial_die_info));
 
-  part_die->offset.sect_off = info_ptr - buffer;
+  part_die->sect_off = (sect_offset) (info_ptr - buffer);
 
   info_ptr += abbrev_len;
 
@@ -15912,8 +18523,8 @@ read_partial_die (const struct die_reader_specs *reader,
                       _("ignoring absolute DW_AT_sibling"));
          else
            {
-             unsigned int off = dwarf2_get_ref_die_offset (&attr).sect_off;
-             const gdb_byte *sibling_ptr = buffer + off;
+             sect_offset off = dwarf2_get_ref_die_offset (&attr);
+             const gdb_byte *sibling_ptr = buffer + to_underlying (off);
 
              if (sibling_ptr < info_ptr)
                complaint (&symfile_complaints,
@@ -15958,7 +18569,7 @@ read_partial_die (const struct die_reader_specs *reader,
        case DW_AT_import:
          if (part_die->tag == DW_TAG_imported_unit)
            {
-             part_die->d.offset = dwarf2_get_ref_die_offset (&attr);
+             part_die->d.sect_off = dwarf2_get_ref_die_offset (&attr);
              part_die->is_dwz = (attr.form == DW_FORM_GNU_ref_alt
                                  || cu->per_cu->is_dwz);
            }
@@ -15994,7 +18605,7 @@ read_partial_die (const struct die_reader_specs *reader,
                     _("DW_AT_low_pc %s is zero "
                       "for DIE at 0x%x [in module %s]"),
                     paddress (gdbarch, part_die->lowpc),
-                    part_die->offset.sect_off, objfile_name (objfile));
+                    to_underlying (part_die->sect_off), objfile_name (objfile));
        }
       /* dwarf2_get_pc_bounds has also the strict low < high requirement.  */
       else if (part_die->lowpc >= part_die->highpc)
@@ -16006,7 +18617,8 @@ read_partial_die (const struct die_reader_specs *reader,
                       "for DIE at 0x%x [in module %s]"),
                     paddress (gdbarch, part_die->lowpc),
                     paddress (gdbarch, part_die->highpc),
-                    part_die->offset.sect_off, objfile_name (objfile));
+                    to_underlying (part_die->sect_off),
+                    objfile_name (objfile));
        }
       else
        part_die->has_pc_info = 1;
@@ -16018,15 +18630,15 @@ read_partial_die (const struct die_reader_specs *reader,
 /* Find a cached partial DIE at OFFSET in CU.  */
 
 static struct partial_die_info *
-find_partial_die_in_comp_unit (sect_offset offset, struct dwarf2_cu *cu)
+find_partial_die_in_comp_unit (sect_offset sect_off, struct dwarf2_cu *cu)
 {
   struct partial_die_info *lookup_die = NULL;
   struct partial_die_info part_die;
 
-  part_die.offset = offset;
+  part_die.sect_off = sect_off;
   lookup_die = ((struct partial_die_info *)
                htab_find_with_hash (cu->partial_dies, &part_die,
-                                    offset.sect_off));
+                                    to_underlying (sect_off)));
 
   return lookup_die;
 }
@@ -16037,16 +18649,16 @@ find_partial_die_in_comp_unit (sect_offset offset, struct dwarf2_cu *cu)
    DW_FORM_ref_sig8).  */
 
 static struct partial_die_info *
-find_partial_die (sect_offset offset, int offset_in_dwz, struct dwarf2_cu *cu)
+find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->objfile;
   struct dwarf2_per_cu_data *per_cu = NULL;
   struct partial_die_info *pd = NULL;
 
   if (offset_in_dwz == cu->per_cu->is_dwz
-      && offset_in_cu_p (&cu->header, offset))
+      && offset_in_cu_p (&cu->header, sect_off))
     {
-      pd = find_partial_die_in_comp_unit (offset, cu);
+      pd = find_partial_die_in_comp_unit (sect_off, cu);
       if (pd != NULL)
        return pd;
       /* We missed recording what we needed.
@@ -16058,19 +18670,19 @@ find_partial_die (sect_offset offset, int offset_in_dwz, struct dwarf2_cu *cu)
       /* TUs don't reference other CUs/TUs (except via type signatures).  */
       if (cu->per_cu->is_debug_types)
        {
-         error (_("Dwarf Error: Type Unit at offset 0x%lx contains"
-                  " external reference to offset 0x%lx [in module %s].\n"),
-                (long) cu->header.offset.sect_off, (long) offset.sect_off,
+         error (_("Dwarf Error: Type Unit at offset 0x%x contains"
+                  " external reference to offset 0x%x [in module %s].\n"),
+                to_underlying (cu->header.sect_off), to_underlying (sect_off),
                 bfd_get_filename (objfile->obfd));
        }
-      per_cu = dwarf2_find_containing_comp_unit (offset, offset_in_dwz,
+      per_cu = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
                                                 objfile);
 
       if (per_cu->cu == NULL || per_cu->cu->partial_dies == NULL)
        load_partial_comp_unit (per_cu);
 
       per_cu->cu->last_used = 0;
-      pd = find_partial_die_in_comp_unit (offset, per_cu->cu);
+      pd = find_partial_die_in_comp_unit (sect_off, per_cu->cu);
     }
 
   /* If we didn't find it, and not all dies have been loaded,
@@ -16088,14 +18700,14 @@ find_partial_die (sect_offset offset, int offset_in_dwz, struct dwarf2_cu *cu)
         set.  */
       load_partial_comp_unit (per_cu);
 
-      pd = find_partial_die_in_comp_unit (offset, per_cu->cu);
+      pd = find_partial_die_in_comp_unit (sect_off, per_cu->cu);
     }
 
   if (pd == NULL)
     internal_error (__FILE__, __LINE__,
                    _("could not find partial DIE 0x%x "
                      "in cache [from module %s]\n"),
-                   offset.sect_off, bfd_get_filename (objfile->obfd));
+                   to_underlying (sect_off), bfd_get_filename (objfile->obfd));
   return pd;
 }
 
@@ -16244,7 +18856,7 @@ fixup_partial_die (struct partial_die_info *part_die,
 static const gdb_byte *
 read_attribute_value (const struct die_reader_specs *reader,
                      struct attribute *attr, unsigned form,
-                     const gdb_byte *info_ptr)
+                     LONGEST implicit_const, const gdb_byte *info_ptr)
 {
   struct dwarf2_cu *cu = reader->cu;
   struct objfile *objfile = cu->objfile;
@@ -16302,6 +18914,13 @@ read_attribute_value (const struct die_reader_specs *reader,
       DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
       info_ptr += 8;
       break;
+    case DW_FORM_data16:
+      blk = dwarf_alloc_block (cu);
+      blk->size = 16;
+      blk->data = read_n_bytes (abfd, info_ptr, 16);
+      info_ptr += 16;
+      DW_BLOCK (attr) = blk;
+      break;
     case DW_FORM_sec_offset:
       DW_UNSND (attr) = read_offset (abfd, info_ptr, &cu->header, &bytes_read);
       info_ptr += bytes_read;
@@ -16321,6 +18940,16 @@ read_attribute_value (const struct die_reader_specs *reader,
          break;
        }
       /* FALLTHROUGH */
+    case DW_FORM_line_strp:
+      if (!cu->per_cu->is_dwz)
+       {
+         DW_STRING (attr) = read_indirect_line_string (abfd, info_ptr,
+                                                       cu_header, &bytes_read);
+         DW_STRING_IS_CANONICAL (attr) = 0;
+         info_ptr += bytes_read;
+         break;
+       }
+      /* FALLTHROUGH */
     case DW_FORM_GNU_strp_alt:
       {
        struct dwz_file *dwz = dwarf2_get_dwz_file ();
@@ -16369,22 +18998,22 @@ read_attribute_value (const struct die_reader_specs *reader,
       info_ptr += bytes_read;
       break;
     case DW_FORM_ref1:
-      DW_UNSND (attr) = (cu->header.offset.sect_off
+      DW_UNSND (attr) = (to_underlying (cu->header.sect_off)
                         + read_1_byte (abfd, info_ptr));
       info_ptr += 1;
       break;
     case DW_FORM_ref2:
-      DW_UNSND (attr) = (cu->header.offset.sect_off
+      DW_UNSND (attr) = (to_underlying (cu->header.sect_off)
                         + read_2_bytes (abfd, info_ptr));
       info_ptr += 2;
       break;
     case DW_FORM_ref4:
-      DW_UNSND (attr) = (cu->header.offset.sect_off
+      DW_UNSND (attr) = (to_underlying (cu->header.sect_off)
                         + read_4_bytes (abfd, info_ptr));
       info_ptr += 4;
       break;
     case DW_FORM_ref8:
-      DW_UNSND (attr) = (cu->header.offset.sect_off
+      DW_UNSND (attr) = (to_underlying (cu->header.sect_off)
                         + read_8_bytes (abfd, info_ptr));
       info_ptr += 8;
       break;
@@ -16393,14 +19022,23 @@ read_attribute_value (const struct die_reader_specs *reader,
       info_ptr += 8;
       break;
     case DW_FORM_ref_udata:
-      DW_UNSND (attr) = (cu->header.offset.sect_off
+      DW_UNSND (attr) = (to_underlying (cu->header.sect_off)
                         + read_unsigned_leb128 (abfd, info_ptr, &bytes_read));
       info_ptr += bytes_read;
       break;
     case DW_FORM_indirect:
       form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
       info_ptr += bytes_read;
-      info_ptr = read_attribute_value (reader, attr, form, info_ptr);
+      if (form == DW_FORM_implicit_const)
+       {
+         implicit_const = read_signed_leb128 (abfd, info_ptr, &bytes_read);
+         info_ptr += bytes_read;
+       }
+      info_ptr = read_attribute_value (reader, attr, form, implicit_const,
+                                      info_ptr);
+      break;
+    case DW_FORM_implicit_const:
+      DW_SND (attr) = implicit_const;
       break;
     case DW_FORM_GNU_addr_index:
       if (reader->dwo_file == NULL)
@@ -16470,7 +19108,8 @@ read_attribute (const struct die_reader_specs *reader,
                const gdb_byte *info_ptr)
 {
   attr->name = abbrev->name;
-  return read_attribute_value (reader, attr, abbrev->form, info_ptr);
+  return read_attribute_value (reader, attr, abbrev->form,
+                              abbrev->implicit_const, info_ptr);
 }
 
 /* Read dwarf information from a buffer.  */
@@ -16723,21 +19362,47 @@ read_direct_string (bfd *abfd, const gdb_byte *buf,
   return (const char *) buf;
 }
 
+/* Return pointer to string at section SECT offset STR_OFFSET with error
+   reporting strings FORM_NAME and SECT_NAME.  */
+
 static const char *
-read_indirect_string_at_offset (bfd *abfd, LONGEST str_offset)
-{
-  dwarf2_read_section (dwarf2_per_objfile->objfile, &dwarf2_per_objfile->str);
-  if (dwarf2_per_objfile->str.buffer == NULL)
-    error (_("DW_FORM_strp used without .debug_str section [in module %s]"),
-          bfd_get_filename (abfd));
-  if (str_offset >= dwarf2_per_objfile->str.size)
-    error (_("DW_FORM_strp pointing outside of "
-            ".debug_str section [in module %s]"),
-          bfd_get_filename (abfd));
+read_indirect_string_at_offset_from (bfd *abfd, LONGEST str_offset,
+                                    struct dwarf2_section_info *sect,
+                                    const char *form_name,
+                                    const char *sect_name)
+{
+  dwarf2_read_section (dwarf2_per_objfile->objfile, sect);
+  if (sect->buffer == NULL)
+    error (_("%s used without %s section [in module %s]"),
+          form_name, sect_name, bfd_get_filename (abfd));
+  if (str_offset >= sect->size)
+    error (_("%s pointing outside of %s section [in module %s]"),
+          form_name, sect_name, bfd_get_filename (abfd));
   gdb_assert (HOST_CHAR_BIT == 8);
-  if (dwarf2_per_objfile->str.buffer[str_offset] == '\0')
+  if (sect->buffer[str_offset] == '\0')
     return NULL;
-  return (const char *) (dwarf2_per_objfile->str.buffer + str_offset);
+  return (const char *) (sect->buffer + str_offset);
+}
+
+/* Return pointer to string at .debug_str offset STR_OFFSET.  */
+
+static const char *
+read_indirect_string_at_offset (bfd *abfd, LONGEST str_offset)
+{
+  return read_indirect_string_at_offset_from (abfd, str_offset,
+                                             &dwarf2_per_objfile->str,
+                                             "DW_FORM_strp", ".debug_str");
+}
+
+/* Return pointer to string at .debug_line_str offset STR_OFFSET.  */
+
+static const char *
+read_indirect_line_string_at_offset (bfd *abfd, LONGEST str_offset)
+{
+  return read_indirect_string_at_offset_from (abfd, str_offset,
+                                             &dwarf2_per_objfile->line_str,
+                                             "DW_FORM_line_strp",
+                                             ".debug_line_str");
 }
 
 /* Read a string at offset STR_OFFSET in the .debug_str section from
@@ -16764,6 +19429,10 @@ read_indirect_string_from_dwz (struct dwz_file *dwz, LONGEST str_offset)
   return (const char *) (dwz->str.buffer + str_offset);
 }
 
+/* Return pointer to string at .debug_str offset as read from BUF.
+   BUF is assumed to be in a compilation unit described by CU_HEADER.
+   Return *BYTES_READ_PTR count of bytes read from BUF.  */
+
 static const char *
 read_indirect_string (bfd *abfd, const gdb_byte *buf,
                      const struct comp_unit_head *cu_header,
@@ -16774,9 +19443,23 @@ read_indirect_string (bfd *abfd, const gdb_byte *buf,
   return read_indirect_string_at_offset (abfd, str_offset);
 }
 
-static ULONGEST
+/* Return pointer to string at .debug_line_str offset as read from BUF.
+   BUF is assumed to be in a compilation unit described by CU_HEADER.
+   Return *BYTES_READ_PTR count of bytes read from BUF.  */
+
+static const char *
+read_indirect_line_string (bfd *abfd, const gdb_byte *buf,
+                          const struct comp_unit_head *cu_header,
+                          unsigned int *bytes_read_ptr)
+{
+  LONGEST str_offset = read_offset (abfd, buf, cu_header, bytes_read_ptr);
+
+  return read_indirect_line_string_at_offset (abfd, str_offset);
+}
+
+ULONGEST
 read_unsigned_leb128 (bfd *abfd, const gdb_byte *buf,
-                     unsigned int *bytes_read_ptr)
+                         unsigned int *bytes_read_ptr)
 {
   ULONGEST result;
   unsigned int num_read;
@@ -16978,16 +19661,16 @@ read_str_index (const struct die_reader_specs *reader, ULONGEST str_index)
   dwarf2_read_section (objfile, str_offsets_section);
   if (str_section->buffer == NULL)
     error (_("%s used without .debug_str.dwo section"
-            " in CU at offset 0x%lx [in module %s]"),
-          form_name, (long) cu->header.offset.sect_off, objf_name);
+            " in CU at offset 0x%x [in module %s]"),
+          form_name, to_underlying (cu->header.sect_off), objf_name);
   if (str_offsets_section->buffer == NULL)
     error (_("%s used without .debug_str_offsets.dwo section"
-            " in CU at offset 0x%lx [in module %s]"),
-          form_name, (long) cu->header.offset.sect_off, objf_name);
+            " in CU at offset 0x%x [in module %s]"),
+          form_name, to_underlying (cu->header.sect_off), objf_name);
   if (str_index * cu->header.offset_size >= str_offsets_section->size)
     error (_("%s pointing outside of .debug_str_offsets.dwo"
-            " section in CU at offset 0x%lx [in module %s]"),
-          form_name, (long) cu->header.offset.sect_off, objf_name);
+            " section in CU at offset 0x%x [in module %s]"),
+          form_name, to_underlying (cu->header.sect_off), objf_name);
   info_ptr = (str_offsets_section->buffer
              + str_index * cu->header.offset_size);
   if (cu->header.offset_size == 4)
@@ -16996,8 +19679,8 @@ read_str_index (const struct die_reader_specs *reader, ULONGEST str_index)
     str_offset = bfd_get_64 (abfd, info_ptr);
   if (str_offset >= str_section->size)
     error (_("Offset from %s pointing outside of"
-            " .debug_str.dwo section in CU at offset 0x%lx [in module %s]"),
-          form_name, (long) cu->header.offset.sect_off, objf_name);
+            " .debug_str.dwo section in CU at offset 0x%x [in module %s]"),
+          form_name, to_underlying (cu->header.sect_off), objf_name);
   return (const char *) (str_section->buffer + str_offset);
 }
 
@@ -17136,14 +19819,16 @@ 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_string
+      if (attr->form == DW_FORM_strp || attr->form == DW_FORM_line_strp
+         || 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,
                   _("string type expected for attribute %s for "
                     "DIE at 0x%x in module %s"),
-                  dwarf_attr_name (name), die->offset.sect_off,
+                  dwarf_attr_name (name), to_underlying (die->sect_off),
                   objfile_name (cu->objfile));
     }
 
@@ -17197,28 +19882,6 @@ die_specification (struct die_info *die, struct dwarf2_cu **spec_cu)
     return follow_die_ref (die, spec_attr, spec_cu);
 }
 
-/* Free the line_header structure *LH, and any arrays and strings it
-   refers to.
-   NOTE: This is also used as a "cleanup" function.  */
-
-static void
-free_line_header (struct line_header *lh)
-{
-  if (lh->standard_opcode_lengths)
-    xfree (lh->standard_opcode_lengths);
-
-  /* Remember that all the lh->file_names[i].name pointers are
-     pointers into debug_line_buffer, and don't need to be freed.  */
-  if (lh->file_names)
-    xfree (lh->file_names);
-
-  /* Similarly for the include directory names.  */
-  if (lh->include_dirs)
-    xfree (lh->include_dirs);
-
-  xfree (lh);
-}
-
 /* Stub for free_line_header to match void * callback types.  */
 
 static void
@@ -17226,69 +19889,30 @@ free_line_header_voidp (void *arg)
 {
   struct line_header *lh = (struct line_header *) arg;
 
-  free_line_header (lh);
+  delete lh;
 }
 
-/* Add an entry to LH's include directory table.  */
-
-static void
-add_include_dir (struct line_header *lh, const char *include_dir)
+void
+line_header::add_include_dir (const char *include_dir)
 {
   if (dwarf_line_debug >= 2)
-    fprintf_unfiltered (gdb_stdlog, "Adding dir %u: %s\n",
-                       lh->num_include_dirs + 1, include_dir);
-
-  /* Grow the array if necessary.  */
-  if (lh->include_dirs_size == 0)
-    {
-      lh->include_dirs_size = 1; /* for testing */
-      lh->include_dirs = XNEWVEC (const char *, lh->include_dirs_size);
-    }
-  else if (lh->num_include_dirs >= lh->include_dirs_size)
-    {
-      lh->include_dirs_size *= 2;
-      lh->include_dirs = XRESIZEVEC (const char *, lh->include_dirs,
-                                    lh->include_dirs_size);
-    }
+    fprintf_unfiltered (gdb_stdlog, "Adding dir %zu: %s\n",
+                       include_dirs.size () + 1, include_dir);
 
-  lh->include_dirs[lh->num_include_dirs++] = include_dir;
+  include_dirs.push_back (include_dir);
 }
 
-/* Add an entry to LH's file name table.  */
-
-static void
-add_file_name (struct line_header *lh,
-               const char *name,
-               unsigned int dir_index,
-               unsigned int mod_time,
-               unsigned int length)
+void
+line_header::add_file_name (const char *name,
+                           dir_index d_index,
+                           unsigned int mod_time,
+                           unsigned int length)
 {
-  struct file_entry *fe;
-
   if (dwarf_line_debug >= 2)
     fprintf_unfiltered (gdb_stdlog, "Adding file %u: %s\n",
-                       lh->num_file_names + 1, name);
-
-  /* Grow the array if necessary.  */
-  if (lh->file_names_size == 0)
-    {
-      lh->file_names_size = 1; /* for testing */
-      lh->file_names = XNEWVEC (struct file_entry, lh->file_names_size);
-    }
-  else if (lh->num_file_names >= lh->file_names_size)
-    {
-      lh->file_names_size *= 2;
-      lh->file_names
-       = XRESIZEVEC (struct file_entry, lh->file_names, lh->file_names_size);
-    }
+                       (unsigned) file_names.size () + 1, name);
 
-  fe = &lh->file_names[lh->num_file_names++];
-  fe->name = name;
-  fe->dir_index = dir_index;
-  fe->mod_time = mod_time;
-  fe->length = length;
-  fe->included_p = 0;
-  fe->symtab = NULL;
+  file_names.emplace_back (name, d_index, mod_time, length);
 }
 
 /* A convenience function to find the proper .debug_line section for a CU.  */
@@ -17314,6 +19938,134 @@ get_debug_line_section (struct dwarf2_cu *cu)
   return section;
 }
 
+/* Read directory or file name entry format, starting with byte of
+   format count entries, ULEB128 pairs of entry formats, ULEB128 of
+   entries count and the entries themselves in the described entry
+   format.  */
+
+static void
+read_formatted_entries (bfd *abfd, const gdb_byte **bufp,
+                       struct line_header *lh,
+                       const struct comp_unit_head *cu_header,
+                       void (*callback) (struct line_header *lh,
+                                         const char *name,
+                                         dir_index d_index,
+                                         unsigned int mod_time,
+                                         unsigned int length))
+{
+  gdb_byte format_count, formati;
+  ULONGEST data_count, datai;
+  const gdb_byte *buf = *bufp;
+  const gdb_byte *format_header_data;
+  unsigned int bytes_read;
+
+  format_count = read_1_byte (abfd, buf);
+  buf += 1;
+  format_header_data = buf;
+  for (formati = 0; formati < format_count; formati++)
+    {
+      read_unsigned_leb128 (abfd, buf, &bytes_read);
+      buf += bytes_read;
+      read_unsigned_leb128 (abfd, buf, &bytes_read);
+      buf += bytes_read;
+    }
+
+  data_count = read_unsigned_leb128 (abfd, buf, &bytes_read);
+  buf += bytes_read;
+  for (datai = 0; datai < data_count; datai++)
+    {
+      const gdb_byte *format = format_header_data;
+      struct file_entry fe;
+
+      for (formati = 0; formati < format_count; formati++)
+       {
+         ULONGEST content_type = read_unsigned_leb128 (abfd, format, &bytes_read);
+         format += bytes_read;
+
+         ULONGEST form  = read_unsigned_leb128 (abfd, format, &bytes_read);
+         format += bytes_read;
+
+         gdb::optional<const char *> string;
+         gdb::optional<unsigned int> uint;
+
+         switch (form)
+           {
+           case DW_FORM_string:
+             string.emplace (read_direct_string (abfd, buf, &bytes_read));
+             buf += bytes_read;
+             break;
+
+           case DW_FORM_line_strp:
+             string.emplace (read_indirect_line_string (abfd, buf,
+                                                        cu_header,
+                                                        &bytes_read));
+             buf += bytes_read;
+             break;
+
+           case DW_FORM_data1:
+             uint.emplace (read_1_byte (abfd, buf));
+             buf += 1;
+             break;
+
+           case DW_FORM_data2:
+             uint.emplace (read_2_bytes (abfd, buf));
+             buf += 2;
+             break;
+
+           case DW_FORM_data4:
+             uint.emplace (read_4_bytes (abfd, buf));
+             buf += 4;
+             break;
+
+           case DW_FORM_data8:
+             uint.emplace (read_8_bytes (abfd, buf));
+             buf += 8;
+             break;
+
+           case DW_FORM_udata:
+             uint.emplace (read_unsigned_leb128 (abfd, buf, &bytes_read));
+             buf += bytes_read;
+             break;
+
+           case DW_FORM_block:
+             /* It is valid only for DW_LNCT_timestamp which is ignored by
+                current GDB.  */
+             break;
+           }
+
+         switch (content_type)
+           {
+           case DW_LNCT_path:
+             if (string.has_value ())
+               fe.name = *string;
+             break;
+           case DW_LNCT_directory_index:
+             if (uint.has_value ())
+               fe.d_index = (dir_index) *uint;
+             break;
+           case DW_LNCT_timestamp:
+             if (uint.has_value ())
+               fe.mod_time = *uint;
+             break;
+           case DW_LNCT_size:
+             if (uint.has_value ())
+               fe.length = *uint;
+             break;
+           case DW_LNCT_MD5:
+             break;
+           default:
+             complaint (&symfile_complaints,
+                        _("Unknown format content type %s"),
+                        pulongest (content_type));
+           }
+       }
+
+      callback (lh, fe.name, fe.d_index, fe.mod_time, fe.length);
+    }
+
+  *bufp = buf;
+}
+
 /* Read the statement program header starting at OFFSET in
    .debug_line, or .debug_line.dwo.  Return a pointer
    to a struct line_header, allocated using xmalloc.
@@ -17324,11 +20076,9 @@ get_debug_line_section (struct dwarf2_cu *cu)
    the returned object point into the dwarf line section buffer,
    and must not be freed.  */
 
-static struct line_header *
-dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
+static line_header_up
+dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu)
 {
-  struct cleanup *back_to;
-  struct line_header *lh;
   const gdb_byte *line_ptr;
   unsigned int bytes_read, offset_size;
   int i;
@@ -17353,21 +20103,18 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
 
   /* Make sure that at least there's room for the total_length field.
      That could be 12 bytes long, but we're just going to fudge that.  */
-  if (offset + 4 >= section->size)
+  if (to_underlying (sect_off) + 4 >= section->size)
     {
       dwarf2_statement_list_fits_in_line_number_section_complaint ();
       return 0;
     }
 
-  lh = XNEW (struct line_header);
-  memset (lh, 0, sizeof (*lh));
-  back_to = make_cleanup ((make_cleanup_ftype *) free_line_header,
-                          (void *) lh);
+  line_header_up lh (new line_header ());
 
-  lh->offset.sect_off = offset;
+  lh->sect_off = sect_off;
   lh->offset_in_dwz = cu->per_cu->is_dwz;
 
-  line_ptr = section->buffer + offset;
+  line_ptr = section->buffer + to_underlying (sect_off);
 
   /* Read in the header.  */
   lh->total_length =
@@ -17377,13 +20124,12 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
   if (line_ptr + lh->total_length > (section->buffer + section->size))
     {
       dwarf2_statement_list_fits_in_line_number_section_complaint ();
-      do_cleanups (back_to);
       return 0;
     }
   lh->statement_program_end = line_ptr + lh->total_length;
   lh->version = read_2_bytes (abfd, line_ptr);
   line_ptr += 2;
-  if (lh->version > 4)
+  if (lh->version > 5)
     {
       /* This is a version we don't understand.  The format could have
         changed in ways we don't handle properly so just punt.  */
@@ -17391,6 +20137,25 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
                 _("unsupported version in .debug_line section"));
       return NULL;
     }
+  if (lh->version >= 5)
+    {
+      gdb_byte segment_selector_size;
+
+      /* Skip address size.  */
+      read_1_byte (abfd, line_ptr);
+      line_ptr += 1;
+
+      segment_selector_size = read_1_byte (abfd, line_ptr);
+      line_ptr += 1;
+      if (segment_selector_size != 0)
+       {
+         complaint (&symfile_complaints,
+                    _("unsupported segment selector size %u "
+                      "in .debug_line section"),
+                    segment_selector_size);
+         return NULL;
+       }
+    }
   lh->header_length = read_offset_1 (abfd, line_ptr, offset_size);
   line_ptr += offset_size;
   lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
@@ -17419,7 +20184,7 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
   line_ptr += 1;
   lh->opcode_base = read_1_byte (abfd, line_ptr);
   line_ptr += 1;
-  lh->standard_opcode_lengths = XNEWVEC (unsigned char, lh->opcode_base);
+  lh->standard_opcode_lengths.reset (new unsigned char[lh->opcode_base]);
 
   lh->standard_opcode_lengths[0] = 1;  /* This should never be used anyway.  */
   for (i = 1; i < lh->opcode_base; ++i)
@@ -17428,30 +20193,54 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
       line_ptr += 1;
     }
 
-  /* Read directory table.  */
-  while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
+  if (lh->version >= 5)
     {
-      line_ptr += bytes_read;
-      add_include_dir (lh, cur_dir);
+      /* Read directory table.  */
+      read_formatted_entries (abfd, &line_ptr, lh.get (), &cu->header,
+                             [] (struct line_header *lh, const char *name,
+                                 dir_index d_index, unsigned int mod_time,
+                                 unsigned int length)
+       {
+         lh->add_include_dir (name);
+       });
+
+      /* Read file name table.  */
+      read_formatted_entries (abfd, &line_ptr, lh.get (), &cu->header,
+                             [] (struct line_header *lh, const char *name,
+                                 dir_index d_index, unsigned int mod_time,
+                                 unsigned int length)
+       {
+         lh->add_file_name (name, d_index, mod_time, length);
+       });
     }
-  line_ptr += bytes_read;
-
-  /* Read file name table.  */
-  while ((cur_file = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
+  else
     {
-      unsigned int dir_index, mod_time, length;
-
-      line_ptr += bytes_read;
-      dir_index = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-      line_ptr += bytes_read;
-      mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-      line_ptr += bytes_read;
-      length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+      /* Read directory table.  */
+      while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
+       {
+         line_ptr += bytes_read;
+         lh->add_include_dir (cur_dir);
+       }
       line_ptr += bytes_read;
 
-      add_file_name (lh, cur_file, dir_index, mod_time, length);
+      /* Read file name table.  */
+      while ((cur_file = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
+       {
+         unsigned int mod_time, length;
+         dir_index d_index;
+
+         line_ptr += bytes_read;
+         d_index = (dir_index) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+         line_ptr += bytes_read;
+         mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+         line_ptr += bytes_read;
+         length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+         line_ptr += bytes_read;
+
+         lh->add_file_name (cur_file, d_index, mod_time, length);
+       }
+      line_ptr += bytes_read;
     }
-  line_ptr += bytes_read;
   lh->statement_program_start = line_ptr;
 
   if (line_ptr > (section->buffer + section->size))
@@ -17459,7 +20248,6 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
               _("line number info header doesn't "
                 "fit in `.debug_line' section"));
 
-  discard_cleanups (back_to);
   return lh;
 }
 
@@ -17477,16 +20265,14 @@ psymtab_include_file_name (const struct line_header *lh, int file_index,
                           const struct partial_symtab *pst,
                           const char *comp_dir)
 {
-  const struct file_entry fe = lh->file_names [file_index];
+  const file_entry &fe = lh->file_names[file_index];
   const char *include_name = fe.name;
   const char *include_name_to_compare = include_name;
-  const char *dir_name = NULL;
   const char *pst_filename;
   char *copied_name = NULL;
   int file_is_pst;
 
-  if (fe.dir_index && lh->include_dirs != NULL)
-    dir_name = lh->include_dirs[fe.dir_index - 1];
+  const char *dir_name = fe.include_dir (lh);
 
   if (!IS_ABSOLUTE_PATH (include_name)
       && (dir_name != NULL || comp_dir != NULL))
@@ -17551,51 +20337,203 @@ psymtab_include_file_name (const struct line_header *lh, int file_index,
 
 /* State machine to track the state of the line number program.  */
 
-typedef struct
+class lnp_state_machine
 {
-  /* These are part of the standard DWARF line number state machine.  */
+public:
+  /* Initialize a machine state for the start of a line number
+     program.  */
+  lnp_state_machine (gdbarch *arch, line_header *lh, bool record_lines_p);
+
+  file_entry *current_file ()
+  {
+    /* lh->file_names is 0-based, but the file name numbers in the
+       statement program are 1-based.  */
+    return m_line_header->file_name_at (m_file);
+  }
+
+  /* Record the line in the state machine.  END_SEQUENCE is true if
+     we're processing the end of a sequence.  */
+  void record_line (bool end_sequence);
+
+  /* Check address and if invalid nop-out the rest of the lines in this
+     sequence.  */
+  void check_line_address (struct dwarf2_cu *cu,
+                          const gdb_byte *line_ptr,
+                          CORE_ADDR lowpc, CORE_ADDR address);
+
+  void handle_set_discriminator (unsigned int discriminator)
+  {
+    m_discriminator = discriminator;
+    m_line_has_non_zero_discriminator |= discriminator != 0;
+  }
+
+  /* Handle DW_LNE_set_address.  */
+  void handle_set_address (CORE_ADDR baseaddr, CORE_ADDR address)
+  {
+    m_op_index = 0;
+    address += baseaddr;
+    m_address = gdbarch_adjust_dwarf2_line (m_gdbarch, address, false);
+  }
+
+  /* Handle DW_LNS_advance_pc.  */
+  void handle_advance_pc (CORE_ADDR adjust);
+
+  /* Handle a special opcode.  */
+  void handle_special_opcode (unsigned char op_code);
+
+  /* Handle DW_LNS_advance_line.  */
+  void handle_advance_line (int line_delta)
+  {
+    advance_line (line_delta);
+  }
+
+  /* Handle DW_LNS_set_file.  */
+  void handle_set_file (file_name_index file);
+
+  /* Handle DW_LNS_negate_stmt.  */
+  void handle_negate_stmt ()
+  {
+    m_is_stmt = !m_is_stmt;
+  }
+
+  /* Handle DW_LNS_const_add_pc.  */
+  void handle_const_add_pc ();
+
+  /* Handle DW_LNS_fixed_advance_pc.  */
+  void handle_fixed_advance_pc (CORE_ADDR addr_adj)
+  {
+    m_address += gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
+    m_op_index = 0;
+  }
+
+  /* Handle DW_LNS_copy.  */
+  void handle_copy ()
+  {
+    record_line (false);
+    m_discriminator = 0;
+  }
+
+  /* Handle DW_LNE_end_sequence.  */
+  void handle_end_sequence ()
+  {
+    m_record_line_callback = ::record_line;
+  }
+
+private:
+  /* Advance the line by LINE_DELTA.  */
+  void advance_line (int line_delta)
+  {
+    m_line += line_delta;
+
+    if (line_delta != 0)
+      m_line_has_non_zero_discriminator = m_discriminator != 0;
+  }
 
-  unsigned char op_index;
-  unsigned int file;
-  unsigned int line;
-  CORE_ADDR address;
-  int is_stmt;
-  unsigned int discriminator;
+  gdbarch *m_gdbarch;
+
+  /* True if we're recording lines.
+     Otherwise we're building partial symtabs and are just interested in
+     finding include files mentioned by the line number program.  */
+  bool m_record_lines_p;
+
+  /* The line number header.  */
+  line_header *m_line_header;
+
+  /* These are part of the standard DWARF line number state machine,
+     and initialized according to the DWARF spec.  */
+
+  unsigned char m_op_index = 0;
+  /* The line table index (1-based) of the current file.  */
+  file_name_index m_file = (file_name_index) 1;
+  unsigned int m_line = 1;
+
+  /* These are initialized in the constructor.  */
+
+  CORE_ADDR m_address;
+  bool m_is_stmt;
+  unsigned int m_discriminator;
 
   /* Additional bits of state we need to track.  */
 
   /* The last file that we called dwarf2_start_subfile for.
      This is only used for TLLs.  */
-  unsigned int last_file;
+  unsigned int m_last_file = 0;
   /* The last file a line number was recorded for.  */
-  struct subfile *last_subfile;
+  struct subfile *m_last_subfile = NULL;
 
   /* The function to call to record a line.  */
-  record_line_ftype *record_line;
+  record_line_ftype *m_record_line_callback = NULL;
 
   /* The last line number that was recorded, used to coalesce
      consecutive entries for the same line.  This can happen, for
      example, when discriminators are present.  PR 17276.  */
-  unsigned int last_line;
-  int line_has_non_zero_discriminator;
-} lnp_state_machine;
+  unsigned int m_last_line = 0;
+  bool m_line_has_non_zero_discriminator = false;
+};
 
-/* There's a lot of static state to pass to dwarf_record_line.
-   This keeps it all together.  */
+void
+lnp_state_machine::handle_advance_pc (CORE_ADDR adjust)
+{
+  CORE_ADDR addr_adj = (((m_op_index + adjust)
+                        / m_line_header->maximum_ops_per_instruction)
+                       * m_line_header->minimum_instruction_length);
+  m_address += gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
+  m_op_index = ((m_op_index + adjust)
+               % m_line_header->maximum_ops_per_instruction);
+}
 
-typedef struct
+void
+lnp_state_machine::handle_special_opcode (unsigned char op_code)
 {
-  /* The gdbarch.  */
-  struct gdbarch *gdbarch;
+  unsigned char adj_opcode = op_code - m_line_header->opcode_base;
+  CORE_ADDR addr_adj = (((m_op_index
+                         + (adj_opcode / m_line_header->line_range))
+                        / m_line_header->maximum_ops_per_instruction)
+                       * m_line_header->minimum_instruction_length);
+  m_address += gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
+  m_op_index = ((m_op_index + (adj_opcode / m_line_header->line_range))
+               % m_line_header->maximum_ops_per_instruction);
 
-  /* The line number header.  */
-  struct line_header *line_header;
+  int line_delta = (m_line_header->line_base
+                   + (adj_opcode % m_line_header->line_range));
+  advance_line (line_delta);
+  record_line (false);
+  m_discriminator = 0;
+}
 
-  /* Non-zero if we're recording lines.
-     Otherwise we're building partial symtabs and are just interested in
-     finding include files mentioned by the line number program.  */
-  int record_lines_p;
-} lnp_reader_state;
+void
+lnp_state_machine::handle_set_file (file_name_index file)
+{
+  m_file = file;
+
+  const file_entry *fe = current_file ();
+  if (fe == NULL)
+    dwarf2_debug_line_missing_file_complaint ();
+  else if (m_record_lines_p)
+    {
+      const char *dir = fe->include_dir (m_line_header);
+
+      m_last_subfile = current_subfile;
+      m_line_has_non_zero_discriminator = m_discriminator != 0;
+      dwarf2_start_subfile (fe->name, dir);
+    }
+}
+
+void
+lnp_state_machine::handle_const_add_pc ()
+{
+  CORE_ADDR adjust
+    = (255 - m_line_header->opcode_base) / m_line_header->line_range;
+
+  CORE_ADDR addr_adj
+    = (((m_op_index + adjust)
+       / m_line_header->maximum_ops_per_instruction)
+       * m_line_header->minimum_instruction_length);
+
+  m_address += gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
+  m_op_index = ((m_op_index + adjust)
+               % m_line_header->maximum_ops_per_instruction);
+}
 
 /* Ignore this record_line request.  */
 
@@ -17696,102 +20634,76 @@ dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile,
   dwarf_record_line_1 (gdbarch, subfile, 0, address, p_record_line);
 }
 
-/* Record the line in STATE.
-   END_SEQUENCE is non-zero if we're processing the end of a sequence.  */
-
-static void
-dwarf_record_line (lnp_reader_state *reader, lnp_state_machine *state,
-                  int end_sequence)
+void
+lnp_state_machine::record_line (bool end_sequence)
 {
-  const struct line_header *lh = reader->line_header;
-  unsigned int file, line, discriminator;
-  int is_stmt;
-
-  file = state->file;
-  line = state->line;
-  is_stmt = state->is_stmt;
-  discriminator = state->discriminator;
-
   if (dwarf_line_debug)
     {
       fprintf_unfiltered (gdb_stdlog,
                          "Processing actual line %u: file %u,"
                          " address %s, is_stmt %u, discrim %u\n",
-                         line, file,
-                         paddress (reader->gdbarch, state->address),
-                         is_stmt, discriminator);
+                         m_line, to_underlying (m_file),
+                         paddress (m_gdbarch, m_address),
+                         m_is_stmt, m_discriminator);
     }
 
-  if (file == 0 || file - 1 >= lh->num_file_names)
+  file_entry *fe = current_file ();
+
+  if (fe == NULL)
     dwarf2_debug_line_missing_file_complaint ();
   /* For now we ignore lines not starting on an instruction boundary.
      But not when processing end_sequence for compatibility with the
      previous version of the code.  */
-  else if (state->op_index == 0 || end_sequence)
+  else if (m_op_index == 0 || end_sequence)
     {
-      lh->file_names[file - 1].included_p = 1;
-      if (reader->record_lines_p && is_stmt)
+      fe->included_p = 1;
+      if (m_record_lines_p && m_is_stmt)
        {
-         if (state->last_subfile != current_subfile || end_sequence)
+         if (m_last_subfile != current_subfile || end_sequence)
            {
-             dwarf_finish_line (reader->gdbarch, state->last_subfile,
-                                state->address, state->record_line);
+             dwarf_finish_line (m_gdbarch, m_last_subfile,
+                                m_address, m_record_line_callback);
            }
 
          if (!end_sequence)
            {
-             if (dwarf_record_line_p (line, state->last_line,
-                                      state->line_has_non_zero_discriminator,
-                                      state->last_subfile))
+             if (dwarf_record_line_p (m_line, m_last_line,
+                                      m_line_has_non_zero_discriminator,
+                                      m_last_subfile))
                {
-                 dwarf_record_line_1 (reader->gdbarch, current_subfile,
-                                      line, state->address,
-                                      state->record_line);
+                 dwarf_record_line_1 (m_gdbarch, current_subfile,
+                                      m_line, m_address,
+                                      m_record_line_callback);
                }
-             state->last_subfile = current_subfile;
-             state->last_line = line;
+             m_last_subfile = current_subfile;
+             m_last_line = m_line;
            }
        }
     }
 }
 
-/* Initialize STATE for the start of a line number program.  */
-
-static void
-init_lnp_state_machine (lnp_state_machine *state,
-                       const lnp_reader_state *reader)
+lnp_state_machine::lnp_state_machine (gdbarch *arch, line_header *lh,
+                                     bool record_lines_p)
 {
-  memset (state, 0, sizeof (*state));
-
-  /* Just starting, there is no "last file".  */
-  state->last_file = 0;
-  state->last_subfile = NULL;
+  m_gdbarch = arch;
+  m_record_lines_p = record_lines_p;
+  m_line_header = lh;
 
-  state->record_line = record_line;
+  m_record_line_callback = ::record_line;
 
-  state->last_line = 0;
-  state->line_has_non_zero_discriminator = 0;
-
-  /* Initialize these according to the DWARF spec.  */
-  state->op_index = 0;
-  state->file = 1;
-  state->line = 1;
   /* Call `gdbarch_adjust_dwarf2_line' on the initial 0 address as if there
      was a line entry for it so that the backend has a chance to adjust it
      and also record it in case it needs it.  This is currently used by MIPS
      code, cf. `mips_adjust_dwarf2_line'.  */
-  state->address = gdbarch_adjust_dwarf2_line (reader->gdbarch, 0, 0);
-  state->is_stmt = reader->line_header->default_is_stmt;
-  state->discriminator = 0;
+  m_address = gdbarch_adjust_dwarf2_line (arch, 0, 0);
+  m_is_stmt = lh->default_is_stmt;
+  m_discriminator = 0;
 }
 
-/* Check address and if invalid nop-out the rest of the lines in this
-   sequence.  */
-
-static void
-check_line_address (struct dwarf2_cu *cu, lnp_state_machine *state,
-                   const gdb_byte *line_ptr,
-                   CORE_ADDR lowpc, CORE_ADDR address)
+void
+lnp_state_machine::check_line_address (struct dwarf2_cu *cu,
+                                      const gdb_byte *line_ptr,
+                                      CORE_ADDR lowpc, CORE_ADDR address)
 {
   /* If address < lowpc then it's not a usable value, it's outside the
      pc range of the CU.  However, we restrict the test to only address
@@ -17809,9 +20721,9 @@ check_line_address (struct dwarf2_cu *cu, lnp_state_machine *state,
       complaint (&symfile_complaints,
                 _(".debug_line address at offset 0x%lx is 0 [in module %s]"),
                 line_offset, objfile_name (objfile));
-      state->record_line = noop_record_line;
-      /* Note: sm.record_line is left as noop_record_line
-        until we see DW_LNE_end_sequence.  */
+      m_record_line_callback = noop_record_line;
+      /* Note: record_line_callback is left as noop_record_line until
+        we see DW_LNE_end_sequence.  */
     }
 }
 
@@ -17832,44 +20744,32 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
   struct objfile *objfile = cu->objfile;
   bfd *abfd = objfile->obfd;
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
-  /* Non-zero if we're recording line info (as opposed to building partial
-     symtabs).  */
-  int record_lines_p = !decode_for_pst_p;
-  /* A collection of things we need to pass to dwarf_record_line.  */
-  lnp_reader_state reader_state;
+  /* True if we're recording line info (as opposed to building partial
+     symtabs and just interested in finding include files mentioned by
+     the line number program).  */
+  bool record_lines_p = !decode_for_pst_p;
 
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
   line_ptr = lh->statement_program_start;
   line_end = lh->statement_program_end;
 
-  reader_state.gdbarch = gdbarch;
-  reader_state.line_header = lh;
-  reader_state.record_lines_p = record_lines_p;
-
   /* Read the statement sequences until there's nothing left.  */
   while (line_ptr < line_end)
     {
-      /* The DWARF line number program state machine.  */
-      lnp_state_machine state_machine;
-      int end_sequence = 0;
-
-      /* Reset the state machine at the start of each sequence.  */
-      init_lnp_state_machine (&state_machine, &reader_state);
+      /* The DWARF line number program state machine.  Reset the state
+        machine at the start of each sequence.  */
+      lnp_state_machine state_machine (gdbarch, lh, record_lines_p);
+      bool end_sequence = false;
 
-      if (record_lines_p && lh->num_file_names >= state_machine.file)
+      if (record_lines_p)
        {
-          /* Start a subfile for the current file of the state machine.  */
-         /* lh->include_dirs and lh->file_names are 0-based, but the
-            directory and file name numbers in the statement program
-            are 1-based.  */
-          struct file_entry *fe = &lh->file_names[state_machine.file - 1];
-          const char *dir = NULL;
+         /* Start a subfile for the current file of the state
+            machine.  */
+         const file_entry *fe = state_machine.current_file ();
 
-          if (fe->dir_index && lh->include_dirs != NULL)
-            dir = lh->include_dirs[fe->dir_index - 1];
-
-         dwarf2_start_subfile (fe->name, dir);
+         if (fe != NULL)
+           dwarf2_start_subfile (fe->name, fe->include_dir (lh));
        }
 
       /* Decode the table.  */
@@ -17881,28 +20781,7 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
          if (op_code >= lh->opcode_base)
            {
              /* Special opcode.  */
-             unsigned char adj_opcode;
-             CORE_ADDR addr_adj;
-             int line_delta;
-
-             adj_opcode = op_code - lh->opcode_base;
-             addr_adj = (((state_machine.op_index
-                           + (adj_opcode / lh->line_range))
-                          / lh->maximum_ops_per_instruction)
-                         * lh->minimum_instruction_length);
-             state_machine.address
-               += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
-             state_machine.op_index = ((state_machine.op_index
-                                        + (adj_opcode / lh->line_range))
-                                       % lh->maximum_ops_per_instruction);
-             line_delta = lh->line_base + (adj_opcode % lh->line_range);
-             state_machine.line += line_delta;
-             if (line_delta != 0)
-               state_machine.line_has_non_zero_discriminator
-                 = state_machine.discriminator != 0;
-
-             dwarf_record_line (&reader_state, &state_machine, 0);
-             state_machine.discriminator = 0;
+             state_machine.handle_special_opcode (op_code);
            }
          else switch (op_code)
            {
@@ -17916,32 +20795,30 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
              switch (extended_op)
                {
                case DW_LNE_end_sequence:
-                 state_machine.record_line = record_line;
-                 end_sequence = 1;
+                 state_machine.handle_end_sequence ();
+                 end_sequence = true;
                  break;
                case DW_LNE_set_address:
                  {
                    CORE_ADDR address
                      = read_address (abfd, line_ptr, cu, &bytes_read);
-
                    line_ptr += bytes_read;
-                   check_line_address (cu, &state_machine, line_ptr,
-                                       lowpc, address);
-                   state_machine.op_index = 0;
-                   address += baseaddr;
-                   state_machine.address
-                     = gdbarch_adjust_dwarf2_line (gdbarch, address, 0);
+
+                   state_machine.check_line_address (cu, line_ptr,
+                                                     lowpc, address);
+                   state_machine.handle_set_address (baseaddr, address);
                  }
                  break;
                case DW_LNE_define_file:
                   {
                     const char *cur_file;
-                    unsigned int dir_index, mod_time, length;
+                   unsigned int mod_time, length;
+                   dir_index dindex;
 
                     cur_file = read_direct_string (abfd, line_ptr,
                                                   &bytes_read);
                     line_ptr += bytes_read;
-                    dir_index =
+                    dindex = (dir_index)
                       read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
                     line_ptr += bytes_read;
                     mod_time =
@@ -17950,20 +20827,23 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
                     length =
                       read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
                     line_ptr += bytes_read;
-                    add_file_name (lh, cur_file, dir_index, mod_time, length);
+                    lh->add_file_name (cur_file, dindex, mod_time, length);
                   }
                  break;
                case DW_LNE_set_discriminator:
-                 /* The discriminator is not interesting to the debugger;
-                    just ignore it.  We still need to check its value though:
-                    if there are consecutive entries for the same
-                    (non-prologue) line we want to coalesce them.
-                    PR 17276.  */
-                 state_machine.discriminator
-                   = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-                 state_machine.line_has_non_zero_discriminator
-                   |= state_machine.discriminator != 0;
-                 line_ptr += bytes_read;
+                 {
+                   /* The discriminator is not interesting to the
+                      debugger; just ignore it.  We still need to
+                      check its value though:
+                      if there are consecutive entries for the same
+                      (non-prologue) line we want to coalesce them.
+                      PR 17276.  */
+                   unsigned int discr
+                     = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                   line_ptr += bytes_read;
+
+                   state_machine.handle_set_discriminator (discr);
+                 }
                  break;
                default:
                  complaint (&symfile_complaints,
@@ -17981,64 +20861,34 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
                }
              break;
            case DW_LNS_copy:
-             dwarf_record_line (&reader_state, &state_machine, 0);
-             state_machine.discriminator = 0;
+             state_machine.handle_copy ();
              break;
            case DW_LNS_advance_pc:
              {
                CORE_ADDR adjust
                  = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-               CORE_ADDR addr_adj;
-
-               addr_adj = (((state_machine.op_index + adjust)
-                            / lh->maximum_ops_per_instruction)
-                           * lh->minimum_instruction_length);
-               state_machine.address
-                 += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
-               state_machine.op_index = ((state_machine.op_index + adjust)
-                                         % lh->maximum_ops_per_instruction);
                line_ptr += bytes_read;
+
+               state_machine.handle_advance_pc (adjust);
              }
              break;
            case DW_LNS_advance_line:
              {
                int line_delta
                  = read_signed_leb128 (abfd, line_ptr, &bytes_read);
-
-               state_machine.line += line_delta;
-               if (line_delta != 0)
-                 state_machine.line_has_non_zero_discriminator
-                   = state_machine.discriminator != 0;
                line_ptr += bytes_read;
+
+               state_machine.handle_advance_line (line_delta);
              }
              break;
            case DW_LNS_set_file:
              {
-               /* The arrays lh->include_dirs and lh->file_names are
-                  0-based, but the directory and file name numbers in
-                  the statement program are 1-based.  */
-               struct file_entry *fe;
-               const char *dir = NULL;
-
-               state_machine.file = read_unsigned_leb128 (abfd, line_ptr,
-                                                          &bytes_read);
+               file_name_index file
+                 = (file_name_index) read_unsigned_leb128 (abfd, line_ptr,
+                                                           &bytes_read);
                line_ptr += bytes_read;
-               if (state_machine.file == 0
-                   || state_machine.file - 1 >= lh->num_file_names)
-                 dwarf2_debug_line_missing_file_complaint ();
-               else
-                 {
-                   fe = &lh->file_names[state_machine.file - 1];
-                   if (fe->dir_index && lh->include_dirs != NULL)
-                     dir = lh->include_dirs[fe->dir_index - 1];
-                   if (record_lines_p)
-                     {
-                       state_machine.last_subfile = current_subfile;
-                       state_machine.line_has_non_zero_discriminator
-                         = state_machine.discriminator != 0;
-                       dwarf2_start_subfile (fe->name, dir);
-                     }
-                 }
+
+               state_machine.handle_set_file (file);
              }
              break;
            case DW_LNS_set_column:
@@ -18046,7 +20896,7 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
              line_ptr += bytes_read;
              break;
            case DW_LNS_negate_stmt:
-             state_machine.is_stmt = (!state_machine.is_stmt);
+             state_machine.handle_negate_stmt ();
              break;
            case DW_LNS_set_basic_block:
              break;
@@ -18056,28 +20906,14 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
               instruction length since special opcode 255 would have
               scaled the increment.  */
            case DW_LNS_const_add_pc:
-             {
-               CORE_ADDR adjust = (255 - lh->opcode_base) / lh->line_range;
-               CORE_ADDR addr_adj;
-
-               addr_adj = (((state_machine.op_index + adjust)
-                            / lh->maximum_ops_per_instruction)
-                           * lh->minimum_instruction_length);
-               state_machine.address
-                 += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
-               state_machine.op_index = ((state_machine.op_index + adjust)
-                                         % lh->maximum_ops_per_instruction);
-             }
+             state_machine.handle_const_add_pc ();
              break;
            case DW_LNS_fixed_advance_pc:
              {
-               CORE_ADDR addr_adj;
-
-               addr_adj = read_2_bytes (abfd, line_ptr);
-               state_machine.address
-                 += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
-               state_machine.op_index = 0;
+               CORE_ADDR addr_adj = read_2_bytes (abfd, line_ptr);
                line_ptr += 2;
+
+               state_machine.handle_fixed_advance_pc (addr_adj);
              }
              break;
            default:
@@ -18099,7 +20935,7 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
 
       /* We got a DW_LNE_end_sequence (or we ran off the end of the buffer,
         in which case we still finish recording the last line).  */
-      dwarf_record_line (&reader_state, &state_machine, 1);
+      state_machine.record_line (true);
     }
 }
 
@@ -18148,7 +20984,7 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
 
       /* Now that we're done scanning the Line Header Program, we can
          create the psymtab of each included file.  */
-      for (file_index = 0; file_index < lh->num_file_names; file_index++)
+      for (file_index = 0; file_index < lh->file_names.size (); file_index++)
         if (lh->file_names[file_index].included_p == 1)
           {
            const char *include_name =
@@ -18165,22 +21001,18 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
       struct compunit_symtab *cust = buildsym_compunit_symtab ();
       int i;
 
-      for (i = 0; i < lh->num_file_names; i++)
+      for (i = 0; i < lh->file_names.size (); i++)
        {
-         const char *dir = NULL;
-         struct file_entry *fe;
+         file_entry &fe = lh->file_names[i];
 
-         fe = &lh->file_names[i];
-         if (fe->dir_index && lh->include_dirs != NULL)
-           dir = lh->include_dirs[fe->dir_index - 1];
-         dwarf2_start_subfile (fe->name, dir);
+         dwarf2_start_subfile (fe.name, fe.include_dir (lh));
 
          if (current_subfile->symtab == NULL)
            {
              current_subfile->symtab
                = allocate_symtab (cust, current_subfile->name);
            }
-         fe->symtab = current_subfile->symtab;
+         fe.symtab = current_subfile->symtab;
        }
     }
 }
@@ -18240,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);
@@ -18389,19 +21221,19 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
                          cu);
       if (attr)
        {
-         int file_index = DW_UNSND (attr);
+         file_name_index file_index = (file_name_index) DW_UNSND (attr);
+         struct file_entry *fe;
 
-         if (cu->line_header == NULL
-             || file_index > cu->line_header->num_file_names)
+         if (cu->line_header != NULL)
+           fe = cu->line_header->file_name_at (file_index);
+         else
+           fe = NULL;
+
+         if (fe == NULL)
            complaint (&symfile_complaints,
                       _("file index out of range"));
-         else if (file_index > 0)
-           {
-             struct file_entry *fe;
-
-             fe = &cu->line_header->file_names[file_index - 1];
-             symbol_set_symtab (sym, fe->symtab);
-           }
+         else
+           symbol_set_symtab (sym, fe->symtab);
        }
 
       switch (die->tag)
@@ -18459,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
@@ -18815,6 +21646,7 @@ dwarf2_const_value_attr (const struct attribute *attr, struct type *type,
     case DW_FORM_block4:
     case DW_FORM_block:
     case DW_FORM_exprloc:
+    case DW_FORM_data16:
       blk = DW_BLOCK (attr);
       if (TYPE_LENGTH (type) != blk->size)
        dwarf2_const_value_length_mismatch_complaint (name, blk->size,
@@ -18841,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;
 
@@ -18984,8 +21817,8 @@ build_error_marker_type (struct dwarf2_cu *cu, struct die_info *die)
 
   message = xstrprintf (_("<unknown type in %s, CU 0x%x, DIE 0x%x>"),
                        objfile_name (objfile),
-                       cu->header.offset.sect_off,
-                       die->offset.sect_off);
+                       to_underlying (cu->header.sect_off),
+                       to_underlying (die->sect_off));
   saved = (char *) obstack_copy0 (&objfile->objfile_obstack,
                                  message, strlen (message));
   xfree (message);
@@ -19014,16 +21847,16 @@ lookup_die_type (struct die_info *die, const struct attribute *attr,
   if (attr->form == DW_FORM_GNU_ref_alt)
     {
       struct dwarf2_per_cu_data *per_cu;
-      sect_offset offset = dwarf2_get_ref_die_offset (attr);
+      sect_offset sect_off = dwarf2_get_ref_die_offset (attr);
 
-      per_cu = dwarf2_find_containing_comp_unit (offset, 1, cu->objfile);
-      this_type = get_die_type_at_offset (offset, per_cu);
+      per_cu = dwarf2_find_containing_comp_unit (sect_off, 1, cu->objfile);
+      this_type = get_die_type_at_offset (sect_off, per_cu);
     }
   else if (attr_form_is_ref (attr))
     {
-      sect_offset offset = dwarf2_get_ref_die_offset (attr);
+      sect_offset sect_off = dwarf2_get_ref_die_offset (attr);
 
-      this_type = get_die_type_at_offset (offset, cu->per_cu);
+      this_type = get_die_type_at_offset (sect_off, cu->per_cu);
     }
   else if (attr->form == DW_FORM_ref_sig8)
     {
@@ -19036,7 +21869,7 @@ lookup_die_type (struct die_info *die, const struct attribute *attr,
       complaint (&symfile_complaints,
                 _("Dwarf Error: Bad type attribute %s in DIE"
                   " at 0x%x [in module %s]"),
-                dwarf_attr_name (attr->name), die->offset.sect_off,
+                dwarf_attr_name (attr->name), to_underlying (die->sect_off),
                 objfile_name (objfile));
       return build_error_marker_type (cu, die);
     }
@@ -19123,7 +21956,10 @@ read_type_die_1 (struct die_info *die, struct dwarf2_cu *cu)
       this_type = read_tag_ptr_to_member_type (die, cu);
       break;
     case DW_TAG_reference_type:
-      this_type = read_tag_reference_type (die, cu);
+      this_type = read_tag_reference_type (die, cu, TYPE_CODE_REF);
+      break;
+    case DW_TAG_rvalue_reference_type:
+      this_type = read_tag_reference_type (die, cu, TYPE_CODE_RVALUE_REF);
       break;
     case DW_TAG_const_type:
       this_type = read_tag_const_type (die, cu);
@@ -19197,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
@@ -19244,7 +22076,7 @@ guess_full_die_structure_name (struct die_info *die, struct dwarf2_cu *cu)
    prefix part in such case.  See
    http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47510.  */
 
-static char *
+static const char *
 anonymous_struct_prefix (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;
@@ -19257,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;
 
@@ -19297,7 +22127,7 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
   struct die_info *parent, *spec_die;
   struct dwarf2_cu *spec_cu;
   struct type *parent_type;
-  char *retval;
+  const char *retval;
 
   if (cu->language != language_cplus
       && cu->language != language_fortran && cu->language != language_d
@@ -19585,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;
 
@@ -19699,7 +22526,7 @@ dwarf_form_name (unsigned form)
   return name;
 }
 
-static char *
+static const char *
 dwarf_bool_name (unsigned mybool)
 {
   if (mybool)
@@ -19728,13 +22555,14 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
 
   print_spaces (indent, f);
   fprintf_unfiltered (f, "Die: %s (abbrev %d, offset 0x%x)\n",
-          dwarf_tag_name (die->tag), die->abbrev, die->offset.sect_off);
+                     dwarf_tag_name (die->tag), die->abbrev,
+                     to_underlying (die->sect_off));
 
   if (die->parent != NULL)
     {
       print_spaces (indent, f);
       fprintf_unfiltered (f, "  parent at offset: 0x%x\n",
-                         die->parent->offset.sect_off);
+                         to_underlying (die->parent->sect_off));
     }
 
   print_spaces (indent, f);
@@ -19769,6 +22597,9 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
          fprintf_unfiltered (f, "expression: size %s",
                              pulongest (DW_BLOCK (&die->attrs[i])->size));
          break;
+       case DW_FORM_data16:
+         fprintf_unfiltered (f, "constant of 16 bytes");
+         break;
        case DW_FORM_ref_addr:
          fprintf_unfiltered (f, "ref address: ");
          fputs_filtered (hex_string (DW_UNSND (&die->attrs[i])), f);
@@ -19804,6 +22635,7 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
          break;
        case DW_FORM_string:
        case DW_FORM_strp:
+       case DW_FORM_line_strp:
        case DW_FORM_GNU_str_index:
        case DW_FORM_GNU_strp_alt:
          fprintf_unfiltered (f, "string: \"%s\" (%s canonicalized)",
@@ -19826,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);
@@ -19889,7 +22725,8 @@ store_in_ref_table (struct die_info *die, struct dwarf2_cu *cu)
 {
   void **slot;
 
-  slot = htab_find_slot_with_hash (cu->die_hash, die, die->offset.sect_off,
+  slot = htab_find_slot_with_hash (cu->die_hash, die,
+                                  to_underlying (die->sect_off),
                                   INSERT);
 
   *slot = die;
@@ -19901,16 +22738,13 @@ store_in_ref_table (struct die_info *die, struct dwarf2_cu *cu)
 static sect_offset
 dwarf2_get_ref_die_offset (const struct attribute *attr)
 {
-  sect_offset retval = { DW_UNSND (attr) };
-
   if (attr_form_is_ref (attr))
-    return retval;
+    return (sect_offset) DW_UNSND (attr);
 
-  retval.sect_off = 0;
   complaint (&symfile_complaints,
             _("unsupported die ref attribute form: '%s'"),
             dwarf_form_name (attr->form));
-  return retval;
+  return {};
 }
 
 /* Return the constant value held by ATTR.  Return DEFAULT_VALUE if
@@ -19919,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
@@ -19929,6 +22763,7 @@ dwarf2_get_attr_constant_value (const struct attribute *attr, int default_value)
     return DW_UNSND (attr);
   else
     {
+      /* For DW_FORM_data16 see attr_form_is_constant.  */
       complaint (&symfile_complaints,
                 _("Attribute value is not a constant (%s)"),
                  dwarf_form_name (attr->form));
@@ -19966,7 +22801,7 @@ follow_die_ref_or_sig (struct die_info *src_die, const struct attribute *attr,
    Returns NULL if OFFSET is invalid.  */
 
 static struct die_info *
-follow_die_offset (sect_offset offset, int offset_in_dwz,
+follow_die_offset (sect_offset sect_off, int offset_in_dwz,
                   struct dwarf2_cu **ref_cu)
 {
   struct die_info temp_die;
@@ -19981,15 +22816,15 @@ follow_die_offset (sect_offset offset, int offset_in_dwz,
       /* .debug_types CUs cannot reference anything outside their CU.
         If they need to, they have to reference a signatured type via
         DW_FORM_ref_sig8.  */
-      if (! offset_in_cu_p (&cu->header, offset))
+      if (!offset_in_cu_p (&cu->header, sect_off))
        return NULL;
     }
   else if (offset_in_dwz != cu->per_cu->is_dwz
-          || ! offset_in_cu_p (&cu->header, offset))
+          || !offset_in_cu_p (&cu->header, sect_off))
     {
       struct dwarf2_per_cu_data *per_cu;
 
-      per_cu = dwarf2_find_containing_comp_unit (offset, offset_in_dwz,
+      per_cu = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
                                                 cu->objfile);
 
       /* If necessary, add it to the queue and load its DIEs.  */
@@ -20006,9 +22841,10 @@ follow_die_offset (sect_offset offset, int offset_in_dwz,
     }
 
   *ref_cu = target_cu;
-  temp_die.offset = offset;
+  temp_die.sect_off = sect_off;
   return (struct die_info *) htab_find_with_hash (target_cu->die_hash,
-                                                 &temp_die, offset.sect_off);
+                                                 &temp_die,
+                                                 to_underlying (sect_off));
 }
 
 /* Follow reference attribute ATTR of SRC_DIE.
@@ -20019,29 +22855,29 @@ static struct die_info *
 follow_die_ref (struct die_info *src_die, const struct attribute *attr,
                struct dwarf2_cu **ref_cu)
 {
-  sect_offset offset = dwarf2_get_ref_die_offset (attr);
+  sect_offset sect_off = dwarf2_get_ref_die_offset (attr);
   struct dwarf2_cu *cu = *ref_cu;
   struct die_info *die;
 
-  die = follow_die_offset (offset,
+  die = follow_die_offset (sect_off,
                           (attr->form == DW_FORM_GNU_ref_alt
                            || cu->per_cu->is_dwz),
                           ref_cu);
   if (!die)
     error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE "
           "at 0x%x [in module %s]"),
-          offset.sect_off, src_die->offset.sect_off,
+          to_underlying (sect_off), to_underlying (src_die->sect_off),
           objfile_name (cu->objfile));
 
   return die;
 }
 
-/* Return DWARF block referenced by DW_AT_location of DIE at OFFSET at PER_CU.
+/* Return DWARF block referenced by DW_AT_location of DIE at SECT_OFF at PER_CU.
    Returned value is intended for DW_OP_call*.  Returned
    dwarf2_locexpr_baton->data has lifetime of PER_CU->OBJFILE.  */
 
 struct dwarf2_locexpr_baton
-dwarf2_fetch_die_loc_sect_off (sect_offset offset,
+dwarf2_fetch_die_loc_sect_off (sect_offset sect_off,
                               struct dwarf2_per_cu_data *per_cu,
                               CORE_ADDR (*get_frame_pc) (void *baton),
                               void *baton)
@@ -20061,13 +22897,13 @@ dwarf2_fetch_die_loc_sect_off (sect_offset offset,
       /* We shouldn't get here for a dummy CU, but don't crash on the user.
         Instead just throw an error, not much else we can do.  */
       error (_("Dwarf Error: Dummy CU at 0x%x referenced in module %s"),
-            offset.sect_off, objfile_name (per_cu->objfile));
+            to_underlying (sect_off), objfile_name (per_cu->objfile));
     }
 
-  die = follow_die_offset (offset, per_cu->is_dwz, &cu);
+  die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
   if (!die)
     error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
-          offset.sect_off, objfile_name (per_cu->objfile));
+          to_underlying (sect_off), objfile_name (per_cu->objfile));
 
   attr = dwarf2_attr (die, DW_AT_location, cu);
   if (!attr)
@@ -20095,7 +22931,7 @@ dwarf2_fetch_die_loc_sect_off (sect_offset offset,
       if (!attr_form_is_block (attr))
        error (_("Dwarf Error: DIE at 0x%x referenced in module %s "
                 "is neither DW_FORM_block* nor DW_FORM_exprloc"),
-              offset.sect_off, objfile_name (per_cu->objfile));
+              to_underlying (sect_off), objfile_name (per_cu->objfile));
 
       retval.data = DW_BLOCK (attr)->data;
       retval.size = DW_BLOCK (attr)->size;
@@ -20116,9 +22952,9 @@ dwarf2_fetch_die_loc_cu_off (cu_offset offset_in_cu,
                             CORE_ADDR (*get_frame_pc) (void *baton),
                             void *baton)
 {
-  sect_offset offset = { per_cu->offset.sect_off + offset_in_cu.cu_off };
+  sect_offset sect_off = per_cu->sect_off + to_underlying (offset_in_cu);
 
-  return dwarf2_fetch_die_loc_sect_off (offset, per_cu, get_frame_pc, baton);
+  return dwarf2_fetch_die_loc_sect_off (sect_off, per_cu, get_frame_pc, baton);
 }
 
 /* Write a constant of a given type as target-ordered bytes into
@@ -20146,7 +22982,7 @@ write_constant_as_bytes (struct obstack *obstack,
    does not have a DW_AT_const_value, return NULL.  */
 
 const gdb_byte *
-dwarf2_fetch_constant_bytes (sect_offset offset,
+dwarf2_fetch_constant_bytes (sect_offset sect_off,
                             struct dwarf2_per_cu_data *per_cu,
                             struct obstack *obstack,
                             LONGEST *len)
@@ -20169,13 +23005,13 @@ dwarf2_fetch_constant_bytes (sect_offset offset,
       /* We shouldn't get here for a dummy CU, but don't crash on the user.
         Instead just throw an error, not much else we can do.  */
       error (_("Dwarf Error: Dummy CU at 0x%x referenced in module %s"),
-            offset.sect_off, objfile_name (per_cu->objfile));
+            to_underlying (sect_off), objfile_name (per_cu->objfile));
     }
 
-  die = follow_die_offset (offset, per_cu->is_dwz, &cu);
+  die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
   if (!die)
     error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
-          offset.sect_off, objfile_name (per_cu->objfile));
+          to_underlying (sect_off), objfile_name (per_cu->objfile));
 
 
   attr = dwarf2_attr (die, DW_AT_const_value, cu);
@@ -20212,6 +23048,7 @@ dwarf2_fetch_constant_bytes (sect_offset offset,
     case DW_FORM_block4:
     case DW_FORM_block:
     case DW_FORM_exprloc:
+    case DW_FORM_data16:
       result = DW_BLOCK (attr)->data;
       *len = DW_BLOCK (attr)->size;
       break;
@@ -20251,6 +23088,7 @@ dwarf2_fetch_constant_bytes (sect_offset offset,
       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);
@@ -20272,6 +23110,31 @@ dwarf2_fetch_constant_bytes (sect_offset offset,
   return result;
 }
 
+/* Return the type of the die at OFFSET in PER_CU.  Return NULL if no
+   valid type for this die is found.  */
+
+struct type *
+dwarf2_fetch_die_type_sect_off (sect_offset sect_off,
+                               struct dwarf2_per_cu_data *per_cu)
+{
+  struct dwarf2_cu *cu;
+  struct die_info *die;
+
+  dw2_setup (per_cu->objfile);
+
+  if (per_cu->cu == NULL)
+    load_cu (per_cu);
+  cu = per_cu->cu;
+  if (!cu)
+    return NULL;
+
+  die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
+  if (!die)
+    return NULL;
+
+  return die_type (die, cu);
+}
+
 /* Return the type of the DIE at DIE_OFFSET in the CU named by
    PER_CU.  */
 
@@ -20279,11 +23142,9 @@ struct type *
 dwarf2_get_die_type (cu_offset die_offset,
                     struct dwarf2_per_cu_data *per_cu)
 {
-  sect_offset die_offset_sect;
-
   dw2_setup (per_cu->objfile);
 
-  die_offset_sect.sect_off = per_cu->offset.sect_off + die_offset.cu_off;
+  sect_offset die_offset_sect = per_cu->sect_off + to_underlying (die_offset);
   return get_die_type_at_offset (die_offset_sect, per_cu);
 }
 
@@ -20311,10 +23172,10 @@ follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type,
 
   sig_cu = sig_type->per_cu.cu;
   gdb_assert (sig_cu != NULL);
-  gdb_assert (sig_type->type_offset_in_section.sect_off != 0);
-  temp_die.offset = sig_type->type_offset_in_section;
+  gdb_assert (to_underlying (sig_type->type_offset_in_section) != 0);
+  temp_die.sect_off = sig_type->type_offset_in_section;
   die = (struct die_info *) htab_find_with_hash (sig_cu->die_hash, &temp_die,
-                                                temp_die.offset.sect_off);
+                                                to_underlying (temp_die.sect_off));
   if (die)
     {
       /* For .gdb_index version 7 keep track of included TUs.
@@ -20357,7 +23218,7 @@ follow_die_sig (struct die_info *src_die, const struct attribute *attr,
     {
       error (_("Dwarf Error: Cannot find signatured DIE %s referenced"
                " from DIE at 0x%x [in module %s]"),
-             hex_string (signature), src_die->offset.sect_off,
+             hex_string (signature), to_underlying (src_die->sect_off),
             objfile_name ((*ref_cu)->objfile));
     }
 
@@ -20367,7 +23228,7 @@ follow_die_sig (struct die_info *src_die, const struct attribute *attr,
       dump_die_for_error (src_die);
       error (_("Dwarf Error: Problem reading signatured DIE %s referenced"
               " from DIE at 0x%x [in module %s]"),
-            hex_string (signature), src_die->offset.sect_off,
+            hex_string (signature), to_underlying (src_die->sect_off),
             objfile_name ((*ref_cu)->objfile));
     }
 
@@ -20394,7 +23255,7 @@ get_signatured_type (struct die_info *die, ULONGEST signature,
       complaint (&symfile_complaints,
                 _("Dwarf Error: Cannot find signatured DIE %s referenced"
                   " from DIE at 0x%x [in module %s]"),
-                hex_string (signature), die->offset.sect_off,
+                hex_string (signature), to_underlying (die->sect_off),
                 objfile_name (dwarf2_per_objfile->objfile));
       return build_error_marker_type (cu, die);
     }
@@ -20416,7 +23277,7 @@ get_signatured_type (struct die_info *die, ULONGEST signature,
          complaint (&symfile_complaints,
                     _("Dwarf Error: Cannot build signatured type %s"
                       " referenced from DIE at 0x%x [in module %s]"),
-                    hex_string (signature), die->offset.sect_off,
+                    hex_string (signature), to_underlying (die->sect_off),
                     objfile_name (dwarf2_per_objfile->objfile));
          type = build_error_marker_type (cu, die);
        }
@@ -20426,7 +23287,7 @@ get_signatured_type (struct die_info *die, ULONGEST signature,
       complaint (&symfile_complaints,
                 _("Dwarf Error: Problem reading signatured DIE %s referenced"
                   " from DIE at 0x%x [in module %s]"),
-                hex_string (signature), die->offset.sect_off,
+                hex_string (signature), to_underlying (die->sect_off),
                 objfile_name (dwarf2_per_objfile->objfile));
       type = build_error_marker_type (cu, die);
     }
@@ -20459,7 +23320,7 @@ get_DW_AT_signature_type (struct die_info *die, const struct attribute *attr,
       complaint (&symfile_complaints,
                 _("Dwarf Error: DW_AT_signature has bad form %s in DIE"
                   " at 0x%x [in module %s]"),
-                dwarf_form_name (attr->form), die->offset.sect_off,
+                dwarf_form_name (attr->form), to_underlying (die->sect_off),
                 objfile_name (dwarf2_per_objfile->objfile));
       return build_error_marker_type (cu, die);
     }
@@ -20840,15 +23701,17 @@ file_file_name (int file, struct line_header *lh)
 {
   /* Is the file number a valid index into the line header's file name
      table?  Remember that file numbers start with one, not zero.  */
-  if (1 <= file && file <= lh->num_file_names)
+  if (1 <= file && file <= lh->file_names.size ())
     {
-      struct file_entry *fe = &lh->file_names[file - 1];
+      const file_entry &fe = lh->file_names[file - 1];
 
-      if (IS_ABSOLUTE_PATH (fe->name) || fe->dir_index == 0
-         || lh->include_dirs == NULL)
-        return xstrdup (fe->name);
-      return concat (lh->include_dirs[fe->dir_index - 1], SLASH_STRING,
-                    fe->name, (char *) NULL);
+      if (!IS_ABSOLUTE_PATH (fe.name))
+       {
+         const char *dir = fe.include_dir (lh);
+         if (dir != NULL)
+           return concat (dir, SLASH_STRING, fe.name, (char *) NULL);
+       }
+      return xstrdup (fe.name);
     }
   else
     {
@@ -20877,7 +23740,7 @@ file_full_name (int file, struct line_header *lh, const char *comp_dir)
 {
   /* Is the file number a valid index into the line header's file name
      table?  Remember that file numbers start with one, not zero.  */
-  if (1 <= file && file <= lh->num_file_names)
+  if (1 <= file && file <= lh->file_names.size ())
     {
       char *relative = file_file_name (file, lh);
 
@@ -20918,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)
 {
@@ -20991,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 == ' ')
@@ -21009,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);
@@ -21038,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);
@@ -21120,6 +23969,10 @@ skip_form_bytes (bfd *abfd, const gdb_byte *bytes, const gdb_byte *buffer_end,
       bytes += 8;
       break;
 
+    case DW_FORM_data16:
+      bytes += 16;
+      break;
+
     case DW_FORM_string:
       read_direct_string (abfd, bytes, &bytes_read);
       bytes += bytes_read;
@@ -21158,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));
@@ -21233,7 +24088,7 @@ dwarf_parse_macro_header (const gdb_byte **opcode_definitions,
       unsigned int version, flags;
 
       version = read_2_bytes (abfd, mac_ptr);
-      if (version != 4)
+      if (version != 4 && version != 5)
        {
          complaint (&symfile_complaints,
                     _("unrecognized version `%d' in .debug_macro section"),
@@ -21276,7 +24131,7 @@ dwarf_parse_macro_header (const gdb_byte **opcode_definitions,
 }
 
 /* A helper for dwarf_decode_macros that handles the GNU extensions,
-   including DW_MACRO_GNU_transparent_include.  */
+   including DW_MACRO_import.  */
 
 static void
 dwarf_decode_macro_bytes (bfd *abfd,
@@ -21324,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
@@ -21331,12 +24188,12 @@ dwarf_decode_macro_bytes (bfd *abfd,
        case 0:
          break;
 
-        case DW_MACRO_GNU_define:
-        case DW_MACRO_GNU_undef:
-       case DW_MACRO_GNU_define_indirect:
-       case DW_MACRO_GNU_undef_indirect:
-       case DW_MACRO_GNU_define_indirect_alt:
-       case DW_MACRO_GNU_undef_indirect_alt:
+        case DW_MACRO_define:
+        case DW_MACRO_undef:
+       case DW_MACRO_define_strp:
+       case DW_MACRO_undef_strp:
+       case DW_MACRO_define_sup:
+       case DW_MACRO_undef_sup:
           {
             unsigned int bytes_read;
             int line;
@@ -21346,8 +24203,8 @@ dwarf_decode_macro_bytes (bfd *abfd,
            line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
            mac_ptr += bytes_read;
 
-           if (macinfo_type == DW_MACRO_GNU_define
-               || macinfo_type == DW_MACRO_GNU_undef)
+           if (macinfo_type == DW_MACRO_define
+               || macinfo_type == DW_MACRO_undef)
              {
                body = read_direct_string (abfd, mac_ptr, &bytes_read);
                mac_ptr += bytes_read;
@@ -21359,8 +24216,8 @@ dwarf_decode_macro_bytes (bfd *abfd,
                str_offset = read_offset_1 (abfd, mac_ptr, offset_size);
                mac_ptr += offset_size;
 
-               if (macinfo_type == DW_MACRO_GNU_define_indirect_alt
-                   || macinfo_type == DW_MACRO_GNU_undef_indirect_alt
+               if (macinfo_type == DW_MACRO_define_sup
+                   || macinfo_type == DW_MACRO_undef_sup
                    || section_is_dwz)
                  {
                    struct dwz_file *dwz = dwarf2_get_dwz_file ();
@@ -21371,9 +24228,9 @@ dwarf_decode_macro_bytes (bfd *abfd,
                  body = read_indirect_string_at_offset (abfd, str_offset);
              }
 
-           is_define = (macinfo_type == DW_MACRO_GNU_define
-                        || macinfo_type == DW_MACRO_GNU_define_indirect
-                        || macinfo_type == DW_MACRO_GNU_define_indirect_alt);
+           is_define = (macinfo_type == DW_MACRO_define
+                        || macinfo_type == DW_MACRO_define_strp
+                        || macinfo_type == DW_MACRO_define_sup);
             if (! current_file)
              {
                /* DWARF violation as no main source is present.  */
@@ -21396,15 +24253,15 @@ dwarf_decode_macro_bytes (bfd *abfd,
              parse_macro_definition (current_file, line, body);
            else
              {
-               gdb_assert (macinfo_type == DW_MACRO_GNU_undef
-                           || macinfo_type == DW_MACRO_GNU_undef_indirect
-                           || macinfo_type == DW_MACRO_GNU_undef_indirect_alt);
+               gdb_assert (macinfo_type == DW_MACRO_undef
+                           || macinfo_type == DW_MACRO_undef_strp
+                           || macinfo_type == DW_MACRO_undef_sup);
                macro_undef (current_file, line, body);
              }
           }
           break;
 
-        case DW_MACRO_GNU_start_file:
+        case DW_MACRO_start_file:
           {
             unsigned int bytes_read;
             int line, file;
@@ -21424,7 +24281,7 @@ dwarf_decode_macro_bytes (bfd *abfd,
 
            if (at_commandline)
              {
-               /* This DW_MACRO_GNU_start_file was executed in the
+               /* This DW_MACRO_start_file was executed in the
                   pass one.  */
                at_commandline = 0;
              }
@@ -21433,7 +24290,7 @@ dwarf_decode_macro_bytes (bfd *abfd,
           }
           break;
 
-        case DW_MACRO_GNU_end_file:
+        case DW_MACRO_end_file:
           if (! current_file)
            complaint (&symfile_complaints,
                       _("macro debug info has an unmatched "
@@ -21472,8 +24329,8 @@ dwarf_decode_macro_bytes (bfd *abfd,
             }
           break;
 
-       case DW_MACRO_GNU_transparent_include:
-       case DW_MACRO_GNU_transparent_include_alt:
+       case DW_MACRO_import:
+       case DW_MACRO_import_sup:
          {
            LONGEST offset;
            void **slot;
@@ -21486,7 +24343,7 @@ dwarf_decode_macro_bytes (bfd *abfd,
            offset = read_offset_1 (abfd, mac_ptr, offset_size);
            mac_ptr += offset_size;
 
-           if (macinfo_type == DW_MACRO_GNU_transparent_include_alt)
+           if (macinfo_type == DW_MACRO_import_sup)
              {
                struct dwz_file *dwz = dwarf2_get_dwz_file ();
 
@@ -21506,7 +24363,7 @@ dwarf_decode_macro_bytes (bfd *abfd,
                /* This has actually happened; see
                   http://sourceware.org/bugzilla/show_bug.cgi?id=13568.  */
                complaint (&symfile_complaints,
-                          _("recursive DW_MACRO_GNU_transparent_include in "
+                          _("recursive DW_MACRO_import in "
                             ".debug_macro section"));
              }
            else
@@ -21548,6 +24405,7 @@ dwarf_decode_macro_bytes (bfd *abfd,
            return;
          break;
         }
+      DIAGNOSTIC_POP
     } while (macinfo_type != 0);
 }
 
@@ -21563,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;
@@ -21641,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
@@ -21648,8 +24507,8 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
         case 0:
          break;
 
-       case DW_MACRO_GNU_define:
-       case DW_MACRO_GNU_undef:
+       case DW_MACRO_define:
+       case DW_MACRO_undef:
          /* Only skip the data by MAC_PTR.  */
          {
            unsigned int bytes_read;
@@ -21661,7 +24520,7 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
          }
          break;
 
-       case DW_MACRO_GNU_start_file:
+       case DW_MACRO_start_file:
          {
            unsigned int bytes_read;
            int line, file;
@@ -21675,14 +24534,14 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
          }
          break;
 
-       case DW_MACRO_GNU_end_file:
+       case DW_MACRO_end_file:
          /* No data to skip by MAC_PTR.  */
          break;
 
-       case DW_MACRO_GNU_define_indirect:
-       case DW_MACRO_GNU_undef_indirect:
-       case DW_MACRO_GNU_define_indirect_alt:
-       case DW_MACRO_GNU_undef_indirect_alt:
+       case DW_MACRO_define_strp:
+       case DW_MACRO_undef_strp:
+       case DW_MACRO_define_sup:
+       case DW_MACRO_undef_sup:
          {
            unsigned int bytes_read;
 
@@ -21692,10 +24551,10 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
          }
          break;
 
-       case DW_MACRO_GNU_transparent_include:
-       case DW_MACRO_GNU_transparent_include_alt:
+       case DW_MACRO_import:
+       case DW_MACRO_import_sup:
          /* Note that, according to the spec, a transparent include
-            chain cannot call DW_MACRO_GNU_start_file.  So, we can just
+            chain cannot call DW_MACRO_start_file.  So, we can just
             skip this opcode.  */
          mac_ptr += offset_size;
          break;
@@ -21721,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.
@@ -21783,7 +24643,10 @@ attr_form_is_section_offset (const struct attribute *attr)
    (lineptr, loclistptr, macptr or rangelistptr).  The DWARF spec says
    that, if an attribute's can be either a constant or one of the
    section offset classes, DW_FORM_data4 and DW_FORM_data8 should be
-   taken as section offsets, not constants.  */
+   taken as section offsets, not constants.
+
+   DW_FORM_data16 is not considered as dwarf2_get_attr_constant_value
+   cannot handle that.  */
 
 static int
 attr_form_is_constant (const struct attribute *attr)
@@ -21796,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;
@@ -21831,8 +24695,13 @@ static struct dwarf2_section_info *
 cu_debug_loc_section (struct dwarf2_cu *cu)
 {
   if (cu->dwo_unit)
-    return &cu->dwo_unit->dwo_file->sections.loc;
-  return &dwarf2_per_objfile->loc;
+    {
+      struct dwo_sections *sections = &cu->dwo_unit->dwo_file->sections;
+      
+      return cu->header.version >= 5 ? &sections->loclists : &sections->loc;
+    }
+  return (cu->header.version >= 5 ? &dwarf2_per_objfile->loclists
+                                 : &dwarf2_per_objfile->loc);
 }
 
 /* A helper function that fills in a dwarf2_loclist_baton.  */
@@ -21947,10 +24816,11 @@ per_cu_header_read_in (struct comp_unit_head *cu_headerp,
   if (per_cu->cu)
     return &per_cu->cu->header;
 
-  info_ptr = per_cu->section->buffer + per_cu->offset.sect_off;
+  info_ptr = per_cu->section->buffer + to_underlying (per_cu->sect_off);
 
   memset (cu_headerp, 0, sizeof (*cu_headerp));
-  read_comp_unit_head (cu_headerp, info_ptr, per_cu->objfile->obfd);
+  read_comp_unit_head (cu_headerp, info_ptr, per_cu->section,
+                      rcuh_kind::COMPILE);
 
   return cu_headerp;
 }
@@ -22010,11 +24880,19 @@ dwarf2_per_cu_text_offset (struct dwarf2_per_cu_data *per_cu)
   return ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 }
 
+/* Return DWARF version number of PER_CU.  */
+
+short
+dwarf2_version (struct dwarf2_per_cu_data *per_cu)
+{
+  return per_cu->dwarf_version;
+}
+
 /* Locate the .debug_info compilation unit from CU's objfile which contains
    the DIE at OFFSET.  Raises an error on failure.  */
 
 static struct dwarf2_per_cu_data *
-dwarf2_find_containing_comp_unit (sect_offset offset,
+dwarf2_find_containing_comp_unit (sect_offset sect_off,
                                  unsigned int offset_in_dwz,
                                  struct objfile *objfile)
 {
@@ -22030,35 +24908,34 @@ dwarf2_find_containing_comp_unit (sect_offset offset,
       int mid = low + (high - low) / 2;
 
       mid_cu = dwarf2_per_objfile->all_comp_units[mid];
-      cu_off = &mid_cu->offset;
+      cu_off = &mid_cu->sect_off;
       if (mid_cu->is_dwz > offset_in_dwz
-         || (mid_cu->is_dwz == offset_in_dwz
-             && cu_off->sect_off >= offset.sect_off))
+         || (mid_cu->is_dwz == offset_in_dwz && *cu_off >= sect_off))
        high = mid;
       else
        low = mid + 1;
     }
   gdb_assert (low == high);
   this_cu = dwarf2_per_objfile->all_comp_units[low];
-  cu_off = &this_cu->offset;
-  if (this_cu->is_dwz != offset_in_dwz || cu_off->sect_off > offset.sect_off)
+  cu_off = &this_cu->sect_off;
+  if (this_cu->is_dwz != offset_in_dwz || *cu_off > sect_off)
     {
       if (low == 0 || this_cu->is_dwz != offset_in_dwz)
        error (_("Dwarf Error: could not find partial DIE containing "
-              "offset 0x%lx [in module %s]"),
-              (long) offset.sect_off, bfd_get_filename (objfile->obfd));
+              "offset 0x%x [in module %s]"),
+              to_underlying (sect_off), bfd_get_filename (objfile->obfd));
 
-      gdb_assert (dwarf2_per_objfile->all_comp_units[low-1]->offset.sect_off
-                 <= offset.sect_off);
+      gdb_assert (dwarf2_per_objfile->all_comp_units[low-1]->sect_off
+                 <= sect_off);
       return dwarf2_per_objfile->all_comp_units[low-1];
     }
   else
     {
       this_cu = dwarf2_per_objfile->all_comp_units[low];
       if (low == dwarf2_per_objfile->n_comp_units - 1
-         && offset.sect_off >= this_cu->offset.sect_off + this_cu->length)
-       error (_("invalid dwarf2 offset %u"), offset.sect_off);
-      gdb_assert (offset.sect_off < this_cu->offset.sect_off + this_cu->length);
+         && sect_off >= this_cu->sect_off + this_cu->length)
+       error (_("invalid dwarf2 offset %u"), to_underlying (sect_off));
+      gdb_assert (sect_off < this_cu->sect_off + this_cu->length);
       return this_cu;
     }
 }
@@ -22138,21 +25015,7 @@ free_stack_comp_unit (void *data)
 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;
-
-      free_heap_comp_unit (per_cu->cu);
-      *last_chain = next_cu;
-
-      per_cu = next_cu;
-    }
+  dwarf2_per_objfile->free_cached_comp_units ();
 }
 
 /* Increase the age counter on each cached compilation unit, and free
@@ -22234,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.
@@ -22263,7 +25117,7 @@ dwarf2_free_objfile (struct objfile *objfile)
 struct dwarf2_per_cu_offset_and_type
 {
   const struct dwarf2_per_cu_data *per_cu;
-  sect_offset offset;
+  sect_offset sect_off;
   struct type *type;
 };
 
@@ -22275,7 +25129,7 @@ per_cu_offset_and_type_hash (const void *item)
   const struct dwarf2_per_cu_offset_and_type *ofs
     = (const struct dwarf2_per_cu_offset_and_type *) item;
 
-  return (uintptr_t) ofs->per_cu + ofs->offset.sect_off;
+  return (uintptr_t) ofs->per_cu + to_underlying (ofs->sect_off);
 }
 
 /* Equality function for a dwarf2_per_cu_offset_and_type.  */
@@ -22289,7 +25143,7 @@ per_cu_offset_and_type_eq (const void *item_lhs, const void *item_rhs)
     = (const struct dwarf2_per_cu_offset_and_type *) item_rhs;
 
   return (ofs_lhs->per_cu == ofs_rhs->per_cu
-         && ofs_lhs->offset.sect_off == ofs_rhs->offset.sect_off);
+         && ofs_lhs->sect_off == ofs_rhs->sect_off);
 }
 
 /* Set the type associated with DIE to TYPE.  Save it in CU's hash
@@ -22344,9 +25198,9 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
   else if (attr != NULL)
     {
       complaint (&symfile_complaints,
-                _("DW_AT_allocated has the wrong form (%s) at DIE 0x%x"),
-                (attr != NULL ? dwarf_form_name (attr->form) : "n/a"),
-                die->offset.sect_off);
+                _("DW_AT_allocated has the wrong form (%s) at DIE 0x%x"),
+                (attr != NULL ? dwarf_form_name (attr->form) : "n/a"),
+                to_underlying (die->sect_off));
     }
 
   /* Read DW_AT_associated and set in type.  */
@@ -22359,9 +25213,9 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
   else if (attr != NULL)
     {
       complaint (&symfile_complaints,
-                _("DW_AT_associated has the wrong form (%s) at DIE 0x%x"),
-                (attr != NULL ? dwarf_form_name (attr->form) : "n/a"),
-                die->offset.sect_off);
+                _("DW_AT_associated has the wrong form (%s) at DIE 0x%x"),
+                (attr != NULL ? dwarf_form_name (attr->form) : "n/a"),
+                to_underlying (die->sect_off));
     }
 
   /* Read DW_AT_data_location and set in type.  */
@@ -22382,25 +25236,25 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
     }
 
   ofs.per_cu = cu->per_cu;
-  ofs.offset = die->offset;
+  ofs.sect_off = die->sect_off;
   ofs.type = type;
   slot = (struct dwarf2_per_cu_offset_and_type **)
     htab_find_slot (dwarf2_per_objfile->die_type_hash, &ofs, INSERT);
   if (*slot)
     complaint (&symfile_complaints,
               _("A problem internal to GDB: DIE 0x%x has type already set"),
-              die->offset.sect_off);
+              to_underlying (die->sect_off));
   *slot = XOBNEW (&objfile->objfile_obstack,
                  struct dwarf2_per_cu_offset_and_type);
   **slot = ofs;
   return type;
 }
 
-/* Look up the type for the die at OFFSET in PER_CU in die_type_hash,
+/* Look up the type for the die at SECT_OFF in PER_CU in die_type_hash,
    or return NULL if the die does not have a saved type.  */
 
 static struct type *
-get_die_type_at_offset (sect_offset offset,
+get_die_type_at_offset (sect_offset sect_off,
                        struct dwarf2_per_cu_data *per_cu)
 {
   struct dwarf2_per_cu_offset_and_type *slot, ofs;
@@ -22409,7 +25263,7 @@ get_die_type_at_offset (sect_offset offset,
     return NULL;
 
   ofs.per_cu = per_cu;
-  ofs.offset = offset;
+  ofs.sect_off = sect_off;
   slot = ((struct dwarf2_per_cu_offset_and_type *)
          htab_find (dwarf2_per_objfile->die_type_hash, &ofs));
   if (slot)
@@ -22424,7 +25278,7 @@ get_die_type_at_offset (sect_offset offset,
 static struct type *
 get_die_type (struct die_info *die, struct dwarf2_cu *cu)
 {
-  return get_die_type_at_offset (die->offset, cu->per_cu);
+  return get_die_type_at_offset (die->sect_off, cu->per_cu);
 }
 
 /* Add a dependence relationship from CU to REF_PER_CU.  */
@@ -22506,7 +25360,7 @@ partial_die_hash (const void *item)
   const struct partial_die_info *part_die
     = (const struct partial_die_info *) item;
 
-  return part_die->offset.sect_off;
+  return to_underlying (part_die->sect_off);
 }
 
 /* Trivial comparison function for partial_die_info structures: two DIEs
@@ -22520,21 +25374,21 @@ partial_die_eq (const void *item_lhs, const void *item_rhs)
   const struct partial_die_info *part_die_rhs
     = (const struct partial_die_info *) item_rhs;
 
-  return part_die_lhs->offset.sect_off == part_die_rhs->offset.sect_off;
+  return part_die_lhs->sect_off == part_die_rhs->sect_off;
 }
 
 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, "");
 }
@@ -22568,74 +25422,105 @@ 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
 /* The "save gdb-index" command.  */
 
-/* The contents of the hash table we create when building the string
-   table.  */
-struct strtab_entry
-{
-  offset_type offset;
-  const char *str;
-};
-
-/* Hash function for a strtab_entry.
-
-   Function is used only during write_hash_table so no index format backward
-   compatibility is needed.  */
+/* Write SIZE bytes from the buffer pointed to by DATA to FILE, with
+   error checking.  */
 
-static hashval_t
-hash_strtab_entry (const void *e)
+static void
+file_write (FILE *file, const void *data, size_t size)
 {
-  const struct strtab_entry *entry = (const struct strtab_entry *) e;
-  return mapped_index_string_hash (INT_MAX, entry->str);
+  if (fwrite (data, 1, size, file) != size)
+    error (_("couldn't data write to file"));
 }
 
-/* Equality function for a strtab_entry.  */
+/* Write the contents of VEC to FILE, with error checking.  */
 
-static int
-eq_strtab_entry (const void *a, const void *b)
+template<typename Elem, typename Alloc>
+static void
+file_write (FILE *file, const std::vector<Elem, Alloc> &vec)
 {
-  const struct strtab_entry *ea = (const struct strtab_entry *) a;
-  const struct strtab_entry *eb = (const struct strtab_entry *) b;
-  return !strcmp (ea->str, eb->str);
+  file_write (file, vec.data (), vec.size () * sizeof (vec[0]));
 }
 
-/* Create a strtab_entry hash table.  */
-
-static htab_t
-create_strtab (void)
+/* In-memory buffer to prepare data to be written later to a file.  */
+class data_buf
 {
-  return htab_create_alloc (100, hash_strtab_entry, eq_strtab_entry,
-                           xfree, xcalloc, xfree);
-}
+public:
+  /* 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),
+              grow (sizeof (data)));
+  }
 
-/* Add a string to the constant pool.  Return the string's offset in
-   host order.  */
+  /* 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, grow (size));
+  }
 
-static offset_type
-add_string (htab_t table, struct obstack *cpool, const char *str)
-{
-  void **slot;
-  struct strtab_entry entry;
-  struct strtab_entry *result;
+  /* 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;
+      }
+  }
 
-  entry.str = str;
-  slot = htab_find_slot (table, &entry, INSERT);
-  if (*slot)
-    result = (struct strtab_entry *) *slot;
-  else
-    {
-      result = XNEW (struct strtab_entry);
-      result->offset = obstack_object_size (cpool);
-      result->str = str;
-      obstack_grow_str0 (cpool, str);
-      *slot = result;
-    }
-  return result->offset;
-}
+  /* 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.  */
+  size_t size () const
+  {
+    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
+  {
+    ::file_write (file, m_vec);
+  }
+
+private:
+  /* 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.  */
 struct symtab_index_entry
@@ -22646,107 +25531,41 @@ struct symtab_index_entry
   offset_type index_offset;
   /* A sorted vector of the indices of all the CUs that hold an object
      of this name.  */
-  VEC (offset_type) *cu_indices;
+  std::vector<offset_type> cu_indices;
 };
 
 /* The symbol table.  This is a power-of-2-sized hash table.  */
 struct mapped_symtab
 {
-  offset_type n_elements;
-  offset_type size;
-  struct symtab_index_entry **data;
-};
-
-/* Hash function for a symtab_index_entry.  */
-
-static hashval_t
-hash_symtab_entry (const void *e)
-{
-  const struct symtab_index_entry *entry
-    = (const struct symtab_index_entry *) e;
-  return iterative_hash (VEC_address (offset_type, entry->cu_indices),
-                        sizeof (offset_type) * VEC_length (offset_type,
-                                                           entry->cu_indices),
-                        0);
-}
-
-/* Equality function for a symtab_index_entry.  */
-
-static int
-eq_symtab_entry (const void *a, const void *b)
-{
-  const struct symtab_index_entry *ea = (const struct symtab_index_entry *) a;
-  const struct symtab_index_entry *eb = (const struct symtab_index_entry *) b;
-  int len = VEC_length (offset_type, ea->cu_indices);
-  if (len != VEC_length (offset_type, eb->cu_indices))
-    return 0;
-  return !memcmp (VEC_address (offset_type, ea->cu_indices),
-                 VEC_address (offset_type, eb->cu_indices),
-                 sizeof (offset_type) * len);
-}
-
-/* Destroy a symtab_index_entry.  */
-
-static void
-delete_symtab_entry (void *p)
-{
-  struct symtab_index_entry *entry = (struct symtab_index_entry *) p;
-  VEC_free (offset_type, entry->cu_indices);
-  xfree (entry);
-}
-
-/* Create a hash table holding symtab_index_entry objects.  */
-
-static htab_t
-create_symbol_hash_table (void)
-{
-  return htab_create_alloc (100, hash_symtab_entry, eq_symtab_entry,
-                           delete_symtab_entry, xcalloc, xfree);
-}
-
-/* Create a new mapped symtab object.  */
-
-static struct mapped_symtab *
-create_mapped_symtab (void)
-{
-  struct mapped_symtab *symtab = XNEW (struct mapped_symtab);
-  symtab->n_elements = 0;
-  symtab->size = 1024;
-  symtab->data = XCNEWVEC (struct symtab_index_entry *, symtab->size);
-  return symtab;
-}
-
-/* Destroy a mapped_symtab.  */
+  mapped_symtab ()
+  {
+    data.resize (1024);
+  }
 
-static void
-cleanup_mapped_symtab (void *p)
-{
-  struct mapped_symtab *symtab = (struct mapped_symtab *) p;
-  /* The contents of the array are freed when the other hash table is
-     destroyed.  */
-  xfree (symtab->data);
-  xfree (symtab);
-}
+  offset_type n_elements = 0;
+  std::vector<symtab_index_entry> data;
+};
 
-/* Find a slot in SYMTAB for the symbol NAME.  Returns a pointer to
+/* Find a slot in SYMTAB for the symbol NAME.  Returns a reference to
    the slot.
    
    Function is used only during write_hash_table so no index format backward
    compatibility is needed.  */
 
-static struct 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);
 
-  index = hash & (symtab->size - 1);
-  step = ((hash * 17) & (symtab->size - 1)) | 1;
+  index = hash & (symtab->data.size () - 1);
+  step = ((hash * 17) & (symtab->data.size () - 1)) | 1;
 
   for (;;)
     {
-      if (!symtab->data[index] || !strcmp (name, symtab->data[index]->name))
-       return &symtab->data[index];
-      index = (index + step) & (symtab->size - 1);
+      if (symtab->data[index].name == NULL
+         || strcmp (name, symtab->data[index].name) == 0)
+       return symtab->data[index];
+      index = (index + step) & (symtab->data.size () - 1);
     }
 }
 
@@ -22755,24 +25574,17 @@ find_slot (struct mapped_symtab *symtab, const char *name)
 static void
 hash_expand (struct mapped_symtab *symtab)
 {
-  offset_type old_size = symtab->size;
-  offset_type i;
-  struct symtab_index_entry **old_entries = symtab->data;
+  auto old_entries = std::move (symtab->data);
 
-  symtab->size *= 2;
-  symtab->data = XCNEWVEC (struct symtab_index_entry *, symtab->size);
+  symtab->data.clear ();
+  symtab->data.resize (old_entries.size () * 2);
 
-  for (i = 0; i < old_size; ++i)
-    {
-      if (old_entries[i])
-       {
-         struct symtab_index_entry **slot = find_slot (symtab,
-                                                       old_entries[i]->name);
-         *slot = old_entries[i];
-       }
-    }
-
-  xfree (old_entries);
+  for (auto &it : old_entries)
+    if (it.name != NULL)
+      {
+       auto &ref = find_slot (symtab, it.name);
+       ref = std::move (it);
+      }
 }
 
 /* Add an entry to SYMTAB.  NAME is the name of the symbol.
@@ -22784,20 +25596,17 @@ add_index_entry (struct mapped_symtab *symtab, const char *name,
                 int is_static, gdb_index_symbol_kind kind,
                 offset_type cu_index)
 {
-  struct symtab_index_entry **slot;
   offset_type cu_index_and_attrs;
 
   ++symtab->n_elements;
-  if (4 * symtab->n_elements / 3 >= symtab->size)
+  if (4 * symtab->n_elements / 3 >= symtab->data.size ())
     hash_expand (symtab);
 
-  slot = find_slot (symtab, name);
-  if (!*slot)
+  symtab_index_entry &slot = find_slot (symtab, name);
+  if (slot.name == NULL)
     {
-      *slot = XNEW (struct symtab_index_entry);
-      (*slot)->name = name;
+      slot.name = name;
       /* index_offset is set later.  */
-      (*slot)->cu_indices = NULL;
     }
 
   cu_index_and_attrs = 0;
@@ -22812,18 +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.  */
-  VEC_safe_push (offset_type, (*slot)->cu_indices, cu_index_and_attrs);
-}
-
-/* qsort helper routine for uniquify_cu_indices.  */
-
-static int
-offset_type_compare (const void *ap, const void *bp)
-{
-  offset_type a = *(offset_type *) ap;
-  offset_type b = *(offset_type *) bp;
-
-  return (a > b) - (b > a);
+  slot.cu_indices.push_back (cu_index_and_attrs);
 }
 
 /* Sort and remove duplicates of all symbols' cu_indices lists.  */
@@ -22831,112 +25629,123 @@ offset_type_compare (const void *ap, const void *bp)
 static void
 uniquify_cu_indices (struct mapped_symtab *symtab)
 {
-  int i;
-
-  for (i = 0; i < symtab->size; ++i)
+  for (auto &entry : symtab->data)
     {
-      struct symtab_index_entry *entry = symtab->data[i];
-
-      if (entry
-         && entry->cu_indices != NULL)
+      if (entry.name != NULL && !entry.cu_indices.empty ())
        {
-         unsigned int next_to_insert, next_to_check;
-         offset_type last_value;
-
-         qsort (VEC_address (offset_type, entry->cu_indices),
-                VEC_length (offset_type, entry->cu_indices),
-                sizeof (offset_type), offset_type_compare);
-
-         last_value = VEC_index (offset_type, entry->cu_indices, 0);
-         next_to_insert = 1;
-         for (next_to_check = 1;
-              next_to_check < VEC_length (offset_type, entry->cu_indices);
-              ++next_to_check)
-           {
-             if (VEC_index (offset_type, entry->cu_indices, next_to_check)
-                 != last_value)
-               {
-                 last_value = VEC_index (offset_type, entry->cu_indices,
-                                         next_to_check);
-                 VEC_replace (offset_type, entry->cu_indices, next_to_insert,
-                              last_value);
-                 ++next_to_insert;
-               }
-           }
-         VEC_truncate (offset_type, entry->cu_indices, next_to_insert);
+         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 ());
        }
     }
 }
 
-/* Add a vector of indices to the constant pool.  */
-
-static offset_type
-add_indices_to_cpool (htab_t symbol_hash_table, struct obstack *cpool,
-                     struct symtab_index_entry *entry)
+/* A form of 'const char *' suitable for container keys.  Only the
+   pointer is stored.  The strings themselves are compared, not the
+   pointers.  */
+class c_str_view
 {
-  void **slot;
+public:
+  c_str_view (const char *cstr)
+    : m_cstr (cstr)
+  {}
 
-  slot = htab_find_slot (symbol_hash_table, entry, INSERT);
-  if (!*slot)
-    {
-      offset_type len = VEC_length (offset_type, entry->cu_indices);
-      offset_type val = MAYBE_SWAP (len);
-      offset_type iter;
-      int i;
+  bool operator== (const c_str_view &other) const
+  {
+    return strcmp (m_cstr, other.m_cstr) == 0;
+  }
 
-      *slot = entry;
-      entry->index_offset = obstack_object_size (cpool);
+  /* 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;
+  }
 
-      obstack_grow (cpool, &val, sizeof (val));
-      for (i = 0;
-          VEC_iterate (offset_type, entry->cu_indices, i, iter);
-          ++i)
-       {
-         val = MAYBE_SWAP (iter);
-         obstack_grow (cpool, &val, sizeof (val));
-       }
-    }
-  else
-    {
-      struct symtab_index_entry *old_entry
-       = (struct symtab_index_entry *) *slot;
-      entry->index_offset = old_entry->index_offset;
-      entry = old_entry;
-    }
-  return entry->index_offset;
-}
+private:
+  friend class c_str_view_hasher;
+  const char *const m_cstr;
+};
 
-/* Write the mapped hash table SYMTAB to the obstack OUTPUT, with
-   constant pool entries going into the obstack CPOOL.  */
+/* A std::unordered_map::hasher for c_str_view that uses the right
+   hash function for strings in a mapped index.  */
+class c_str_view_hasher
+{
+public:
+  size_t operator () (const c_str_view &x) const
+  {
+    return mapped_index_string_hash (INT_MAX, x.m_cstr);
+  }
+};
 
-static void
-write_hash_table (struct mapped_symtab *symtab,
-                 struct obstack *output, struct obstack *cpool)
+/* A std::unordered_map::hasher for std::vector<>.  */
+template<typename T>
+class vector_hasher
 {
-  offset_type i;
-  htab_t symbol_hash_table;
-  htab_t str_table;
+public:
+  size_t operator () (const std::vector<T> &key) const
+  {
+    return iterative_hash (key.data (),
+                          sizeof (key.front ()) * key.size (), 0);
+  }
+};
 
-  symbol_hash_table = create_symbol_hash_table ();
-  str_table = create_strtab ();
+/* Write the mapped hash table SYMTAB to the data buffer OUTPUT, with
+   constant pool entries going into the data buffer CPOOL.  */
+
+static void
+write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool)
+{
+  {
+    /* Elements are sorted vectors of the indices of all the CUs that
+       hold an object of this name.  */
+    std::unordered_map<std::vector<offset_type>, offset_type,
+                      vector_hasher<offset_type>>
+      symbol_hash_table;
+
+    /* We add all the index vectors to the constant pool first, to
+       ensure alignment is ok.  */
+    for (symtab_index_entry &entry : symtab->data)
+      {
+       if (entry.name == NULL)
+         continue;
+       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;
+         }
 
-  /* We add all the index vectors to the constant pool first, to
-     ensure alignment is ok.  */
-  for (i = 0; i < symtab->size; ++i)
-    {
-      if (symtab->data[i])
-       add_indices_to_cpool (symbol_hash_table, cpool, symtab->data[i]);
-    }
+       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.  */
-  for (i = 0; i < symtab->size; ++i)
+  std::unordered_map<c_str_view, offset_type, c_str_view_hasher> str_table;
+  for (const auto &entry : symtab->data)
     {
       offset_type str_off, vec_off;
 
-      if (symtab->data[i])
+      if (entry.name != NULL)
        {
-         str_off = add_string (str_table, cpool, symtab->data[i]->name);
-         vec_off = symtab->data[i]->index_offset;
+         const auto insertpair = str_table.emplace (entry.name, cpool.size ());
+         if (insertpair.second)
+           cpool.append_cstr0 (entry.name);
+         str_off = insertpair.first->second;
+         vec_off = entry.index_offset;
        }
       else
        {
@@ -22946,50 +25755,23 @@ write_hash_table (struct mapped_symtab *symtab,
          vec_off = 0;
        }
 
-      str_off = MAYBE_SWAP (str_off);
-      vec_off = MAYBE_SWAP (vec_off);
-
-      obstack_grow (output, &str_off, sizeof (str_off));
-      obstack_grow (output, &vec_off, sizeof (vec_off));
+      output.append_data (MAYBE_SWAP (str_off));
+      output.append_data (MAYBE_SWAP (vec_off));
     }
-
-  htab_delete (str_table);
-  htab_delete (symbol_hash_table);
-}
-
-/* Struct to map psymtab to CU index in the index file.  */
-struct psymtab_cu_index_map
-{
-  struct partial_symtab *psymtab;
-  unsigned int cu_index;
-};
-
-static hashval_t
-hash_psymtab_cu_index (const void *item)
-{
-  const struct psymtab_cu_index_map *map
-    = (const struct psymtab_cu_index_map *) item;
-
-  return htab_hash_pointer (map->psymtab);
 }
 
-static int
-eq_psymtab_cu_index (const void *item_lhs, const void *item_rhs)
-{
-  const struct psymtab_cu_index_map *lhs
-    = (const struct psymtab_cu_index_map *) item_lhs;
-  const struct psymtab_cu_index_map *rhs
-    = (const struct psymtab_cu_index_map *) item_rhs;
-
-  return lhs->psymtab == rhs->psymtab;
-}
+typedef std::unordered_map<partial_symtab *, unsigned int> psym_index_map;
 
 /* Helper struct for building the address table.  */
 struct addrmap_index_data
 {
+  addrmap_index_data (data_buf &addr_vec_, psym_index_map &cu_index_htab_)
+    : addr_vec (addr_vec_), cu_index_htab (cu_index_htab_)
+  {}
+
   struct objfile *objfile;
-  struct obstack *addr_obstack;
-  htab_t cu_index_htab;
+  data_buf &addr_vec;
+  psym_index_map &cu_index_htab;
 
   /* Non-zero if the previous_* fields are valid.
      We can't write an entry until we see the next entry (since it is only then
@@ -23001,24 +25783,19 @@ struct addrmap_index_data
   CORE_ADDR previous_cu_start;
 };
 
-/* Write an address entry to OBSTACK.  */
+/* Write an address entry to ADDR_VEC.  */
 
 static void
-add_address_entry (struct objfile *objfile, struct obstack *obstack,
+add_address_entry (struct objfile *objfile, data_buf &addr_vec,
                   CORE_ADDR start, CORE_ADDR end, unsigned int cu_index)
 {
-  offset_type cu_index_to_write;
-  gdb_byte addr[8];
   CORE_ADDR baseaddr;
 
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
-  store_unsigned_integer (addr, 8, BFD_ENDIAN_LITTLE, start - baseaddr);
-  obstack_grow (obstack, addr, 8);
-  store_unsigned_integer (addr, 8, BFD_ENDIAN_LITTLE, end - baseaddr);
-  obstack_grow (obstack, addr, 8);
-  cu_index_to_write = MAYBE_SWAP (cu_index);
-  obstack_grow (obstack, &cu_index_to_write, sizeof (offset_type));
+  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));
 }
 
 /* Worker function for traversing an addrmap to build the address table.  */
@@ -23030,44 +25807,39 @@ add_address_entry_worker (void *datap, CORE_ADDR start_addr, void *obj)
   struct partial_symtab *pst = (struct partial_symtab *) obj;
 
   if (data->previous_valid)
-    add_address_entry (data->objfile, data->addr_obstack,
+    add_address_entry (data->objfile, data->addr_vec,
                       data->previous_cu_start, start_addr,
                       data->previous_cu_index);
 
   data->previous_cu_start = start_addr;
   if (pst != NULL)
     {
-      struct psymtab_cu_index_map find_map, *map;
-      find_map.psymtab = pst;
-      map = ((struct psymtab_cu_index_map *)
-            htab_find (data->cu_index_htab, &find_map));
-      gdb_assert (map != NULL);
-      data->previous_cu_index = map->cu_index;
+      const auto it = data->cu_index_htab.find (pst);
+      gdb_assert (it != data->cu_index_htab.cend ());
+      data->previous_cu_index = it->second;
       data->previous_valid = 1;
     }
   else
-      data->previous_valid = 0;
+    data->previous_valid = 0;
 
   return 0;
 }
 
-/* Write OBJFILE's address map to OBSTACK.
+/* Write OBJFILE's address map to ADDR_VEC.
    CU_INDEX_HTAB is used to map addrmap entries to their CU indices
    in the index file.  */
 
 static void
-write_address_map (struct objfile *objfile, struct obstack *obstack,
-                  htab_t cu_index_htab)
+write_address_map (struct objfile *objfile, data_buf &addr_vec,
+                  psym_index_map &cu_index_htab)
 {
-  struct addrmap_index_data addrmap_index_data;
+  struct addrmap_index_data addrmap_index_data (addr_vec, cu_index_htab);
 
   /* When writing the address table, we have to cope with the fact that
      the addrmap iterator only provides the start of a region; we have to
      wait until the next invocation to get the start of the next region.  */
 
   addrmap_index_data.objfile = objfile;
-  addrmap_index_data.addr_obstack = obstack;
-  addrmap_index_data.cu_index_htab = cu_index_htab;
   addrmap_index_data.previous_valid = 0;
 
   addrmap_foreach (objfile->psymtabs_addrmap, add_address_entry_worker,
@@ -23079,258 +25851,832 @@ write_address_map (struct objfile *objfile, struct obstack *obstack,
      doesn't work here.  To cope we pass 0xff...ff, this is a rare situation
      anyway.  */
   if (addrmap_index_data.previous_valid)
-    add_address_entry (objfile, obstack,
+    add_address_entry (objfile, addr_vec,
                       addrmap_index_data.previous_cu_start, (CORE_ADDR) -1,
                       addrmap_index_data.previous_cu_index);
 }
 
 /* Return the symbol kind of PSYM.  */
 
-static gdb_index_symbol_kind
-symbol_kind (struct partial_symbol *psym)
-{
-  domain_enum domain = PSYMBOL_DOMAIN (psym);
-  enum address_class aclass = PSYMBOL_CLASS (psym);
+static gdb_index_symbol_kind
+symbol_kind (struct partial_symbol *psym)
+{
+  domain_enum domain = PSYMBOL_DOMAIN (psym);
+  enum address_class aclass = PSYMBOL_CLASS (psym);
+
+  switch (domain)
+    {
+    case VAR_DOMAIN:
+      switch (aclass)
+       {
+       case LOC_BLOCK:
+         return GDB_INDEX_SYMBOL_KIND_FUNCTION;
+       case LOC_TYPEDEF:
+         return GDB_INDEX_SYMBOL_KIND_TYPE;
+       case LOC_COMPUTED:
+       case LOC_CONST_BYTES:
+       case LOC_OPTIMIZED_OUT:
+       case LOC_STATIC:
+         return GDB_INDEX_SYMBOL_KIND_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 GDB_INDEX_SYMBOL_KIND_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 GDB_INDEX_SYMBOL_KIND_OTHER;
+       }
+    case STRUCT_DOMAIN:
+      return GDB_INDEX_SYMBOL_KIND_TYPE;
+    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;
+    }
+  };
+
+  /* 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_)
+    {}
+
+    /* 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_)
+    {}
 
-  switch (domain)
+    /* Implement offset_vec::reserve.  */
+    void reserve (size_t nelem) override
     {
-    case VAR_DOMAIN:
-      switch (aclass)
-       {
-       case LOC_BLOCK:
-         return GDB_INDEX_SYMBOL_KIND_FUNCTION;
-       case LOC_TYPEDEF:
-         return GDB_INDEX_SYMBOL_KIND_TYPE;
-       case LOC_COMPUTED:
-       case LOC_CONST_BYTES:
-       case LOC_OPTIMIZED_OUT:
-       case LOC_STATIC:
-         return GDB_INDEX_SYMBOL_KIND_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 GDB_INDEX_SYMBOL_KIND_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 GDB_INDEX_SYMBOL_KIND_OTHER;
-       }
-    case STRUCT_DOMAIN:
-      return GDB_INDEX_SYMBOL_KIND_TYPE;
-    default:
-      return GDB_INDEX_SYMBOL_KIND_OTHER;
+      m_vec.reserve (nelem);
     }
-}
-
-/* Add a list of partial symbols to SYMTAB.  */
 
-static void
-write_psymbols (struct mapped_symtab *symtab,
-               htab_t psyms_seen,
-               struct partial_symbol **psymp,
-               int count,
-               offset_type cu_index,
-               int is_static)
-{
-  for (; count-- > 0; ++psymp)
+    /* Implement offset_vec::push_back_reorder.  */
+    void push_back_reorder (size_t elem) override
     {
-      struct partial_symbol *psym = *psymp;
-      void **slot;
-
-      if (SYMBOL_LANGUAGE (psym) == language_ada)
-       error (_("Ada is not currently supported by the index"));
+      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.  */
-      slot = htab_find_slot (psyms_seen, psym, INSERT);
-      if (!*slot)
-       {
-         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]);
+    }
 
-         *slot = psym;
-         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);
     }
-}
 
-/* Write the contents of an ("unfinished") obstack to FILE.  Throw an
-   exception if there is an error.  */
+  private:
+    std::vector<OffsetSize> m_vec;
+  };
 
-static void
-write_obstack (FILE *file, struct obstack *obstack)
-{
-  if (fwrite (obstack_base (obstack), 1, obstack_object_size (obstack),
-             file)
-      != obstack_object_size (obstack))
-    error (_("couldn't data write to file"));
-}
+  /* 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;
 
-/* Unlink a file if the argument is not NULL.  */
+    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 void
-unlink_if_set (void *p)
-{
-  char **filename = (char **) p;
-  if (*filename)
-    unlink (*filename);
-}
+  /* 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;
+  };
 
-/* A helper struct used when iterating over debug_types.  */
-struct signatured_type_index_data
-{
-  struct objfile *objfile;
-  struct mapped_symtab *symtab;
-  struct obstack *types_list;
-  htab_t psyms_seen;
-  int cu_index;
-};
+  /* 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);
 
-/* A helper function that writes a single signatured_type to an
-   obstack.  */
+    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;
+      }
+  }
 
-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;
-  gdb_byte val[8];
+  /* 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;
 
-  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);
+       if (SYMBOL_LANGUAGE (psym) == language_ada)
+         error (_("Ada is not currently supported by the index"));
 
-  store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE,
-                         entry->per_cu.offset.sect_off);
-  obstack_grow (info->types_list, val, 8);
-  store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE,
-                         entry->type_offset_in_tu.cu_off);
-  obstack_grow (info->types_list, val, 8);
-  store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->signature);
-  obstack_grow (info->types_list, val, 8);
+       /* Only add a given psymbol once.  */
+       if (psyms_seen.insert (psym).second)
+         insert (psym, cu_index, is_static, kind);
+      }
+  }
 
-  ++info->cu_index;
+  /* 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;
 
-  return 1;
-}
+    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);
 
-/* Recurse into all "included" dependencies and write their symbols as
-   if they appeared in this psymtab.  */
+    info->types_list.append_uint (dwarf5_offset_size (), m_dwarf5_byte_order,
+                                 to_underlying (entry->per_cu.sect_off));
 
-static void
-recursively_write_psymbols (struct objfile *objfile,
-                           struct partial_symtab *psymtab,
-                           struct mapped_symtab *symtab,
-                           htab_t psyms_seen,
-                           offset_type cu_index)
-{
-  int i;
+    ++info->cu_index;
+  }
 
-  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);
+  /* Store value of each symbol.  */
+  std::unordered_map<c_str_view, std::set<symbol_value>, c_str_view_hasher>
+    m_name_to_value_set;
 
-  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);
-}
+  /* 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;
 
-/* Create an index file for OBJFILE in the directory DIR.  */
+  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;
 
-static void
-write_psymtabs_to_index (struct objfile *objfile, const char *dir)
-{
-  struct cleanup *cleanup;
-  char *filename, *cleanup_filename;
-  struct obstack contents, addr_obstack, constant_pool, symtab_obstack;
-  struct obstack cu_list, types_cu_list;
-  int i;
-  FILE *out_file;
-  struct mapped_symtab *symtab;
-  offset_type val, size_of_contents, total_len;
-  struct stat st;
-  struct psymtab_cu_index_map *psymtab_cu_index_map;
+  /* 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;
 
-  if (dwarf2_per_objfile->using_index)
-    error (_("Cannot use an index to create the index"));
+  /* Next unused .debug_names abbreviation tag for
+     m_indexkey_to_idx.  */
+  int m_idx_next = 1;
 
-  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"));
+  /* .debug_names abbreviation table.  */
+  data_buf m_abbrev_table;
 
-  if (!objfile->psymtabs || !objfile->psymtabs_addrmap)
-    return;
+  /* .debug_names entry pool.  */
+  data_buf m_entry_pool;
+};
 
-  if (stat (objfile_name (objfile), &st) < 0)
-    perror_with_name (objfile_name (objfile));
+/* Return iff any of the needed offsets does not fit into 32-bit
+   .debug_names section.  */
 
-  filename = concat (dir, SLASH_STRING, lbasename (objfile_name (objfile)),
-                    INDEX_SUFFIX, (char *) NULL);
-  cleanup = make_cleanup (xfree, filename);
+static bool
+check_dwarf64_offsets ()
+{
+  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];
 
-  out_file = gdb_fopen_cloexec (filename, "wb");
-  if (!out_file)
-    error (_("Can't open `%s' for writing"), filename);
+      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;
 
-  cleanup_filename = filename;
-  make_cleanup (unlink_if_set, &cleanup_filename);
+      if (to_underlying (per_cu.sect_off) >= (static_cast<uint64_t> (1) << 32))
+       return true;
+    }
+  return false;
+}
 
-  symtab = create_mapped_symtab ();
-  make_cleanup (cleanup_mapped_symtab, symtab);
+/* 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.  */
 
-  obstack_init (&addr_obstack);
-  make_cleanup_obstack_free (&addr_obstack);
+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;
 
-  obstack_init (&cu_list);
-  make_cleanup_obstack_free (&cu_list);
+      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;
+}
 
-  obstack_init (&types_cu_list);
-  make_cleanup_obstack_free (&types_cu_list);
+/* Write new .gdb_index section for OBJFILE into OUT_FILE.
+   Return how many bytes were expected to be written into OUT_FILE.  */
 
-  htab_up psyms_seen (htab_create_alloc (100, htab_hash_pointer,
-                                        htab_eq_pointer,
-                                        NULL, xcalloc, xfree));
+static size_t
+write_gdbindex (struct objfile *objfile, FILE *out_file)
+{
+  mapped_symtab symtab;
+  data_buf cu_list;
 
   /* 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
      in the index file).  This will later be needed to write the address
      table.  */
-  htab_up cu_index_htab (htab_create_alloc (100,
-                                           hash_psymtab_cu_index,
-                                           eq_psymtab_cu_index,
-                                           NULL, xcalloc, xfree));
-  psymtab_cu_index_map = XNEWVEC (struct psymtab_cu_index_map,
-                                 dwarf2_per_objfile->n_comp_units);
-  make_cleanup (xfree, psymtab_cu_index_map);
+  psym_index_map cu_index_htab;
+  cu_index_htab.reserve (dwarf2_per_objfile->n_comp_units);
 
   /* 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.  */
-  for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+
+  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
        = dwarf2_per_objfile->all_comp_units[i];
       struct partial_symtab *psymtab = per_cu->v.psymtab;
-      gdb_byte val[8];
-      struct psymtab_cu_index_map *map;
-      void **slot;
 
       /* 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
@@ -23339,36 +26685,30 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
        continue;
 
       if (psymtab->user == NULL)
-       recursively_write_psymbols (objfile, psymtab, symtab,
-                                   psyms_seen.get (), i);
+       recursively_write_psymbols (objfile, psymtab, &symtab,
+                                   psyms_seen, i);
 
-      map = &psymtab_cu_index_map[i];
-      map->psymtab = psymtab;
-      map->cu_index = i;
-      slot = htab_find_slot (cu_index_htab.get (), map, INSERT);
-      gdb_assert (slot != NULL);
-      gdb_assert (*slot == NULL);
-      *slot = map;
+      const auto insertpair = cu_index_htab.emplace (psymtab, i);
+      gdb_assert (insertpair.second);
 
-      store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE,
-                             per_cu->offset.sect_off);
-      obstack_grow (&cu_list, val, 8);
-      store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, per_cu->length);
-      obstack_grow (&cu_list, val, 8);
+      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.  */
-  write_address_map (objfile, &addr_obstack, cu_index_htab.get ());
+  data_buf addr_vec;
+  write_address_map (objfile, addr_vec, cu_index_htab);
 
   /* Write out the .debug_type entries, if any.  */
+  data_buf types_cu_list;
   if (dwarf2_per_objfile->signatured_types)
     {
-      struct signatured_type_index_data sig_data;
+      signatured_type_index_data sig_data (types_cu_list,
+                                          psyms_seen);
 
       sig_data.objfile = objfile;
-      sig_data.symtab = symtab;
-      sig_data.types_list = &types_cu_list;
-      sig_data.psyms_seen = psyms_seen.get ();
+      sig_data.symtab = &symtab;
       sig_data.cu_index = dwarf2_per_objfile->n_comp_units;
       htab_traverse_noresize (dwarf2_per_objfile->signatured_types,
                              write_one_signatured_type, &sig_data);
@@ -23376,78 +26716,278 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
 
   /* Now that we've processed all symbols we can shrink their cu_indices
      lists.  */
-  uniquify_cu_indices (symtab);
+  uniquify_cu_indices (&symtab);
 
-  obstack_init (&constant_pool);
-  make_cleanup_obstack_free (&constant_pool);
-  obstack_init (&symtab_obstack);
-  make_cleanup_obstack_free (&symtab_obstack);
-  write_hash_table (symtab, &symtab_obstack, &constant_pool);
+  data_buf symtab_vec, constant_pool;
+  write_hash_table (&symtab, symtab_vec, constant_pool);
 
-  obstack_init (&contents);
-  make_cleanup_obstack_free (&contents);
-  size_of_contents = 6 * sizeof (offset_type);
-  total_len = size_of_contents;
+  data_buf contents;
+  const offset_type size_of_contents = 6 * sizeof (offset_type);
+  offset_type total_len = size_of_contents;
 
   /* The version number.  */
-  val = MAYBE_SWAP (8);
-  obstack_grow (&contents, &val, sizeof (val));
+  contents.append_data (MAYBE_SWAP (8));
 
   /* The offset of the CU list from the start of the file.  */
-  val = MAYBE_SWAP (total_len);
-  obstack_grow (&contents, &val, sizeof (val));
-  total_len += obstack_object_size (&cu_list);
+  contents.append_data (MAYBE_SWAP (total_len));
+  total_len += cu_list.size ();
 
   /* The offset of the types CU list from the start of the file.  */
-  val = MAYBE_SWAP (total_len);
-  obstack_grow (&contents, &val, sizeof (val));
-  total_len += obstack_object_size (&types_cu_list);
+  contents.append_data (MAYBE_SWAP (total_len));
+  total_len += types_cu_list.size ();
 
   /* The offset of the address table from the start of the file.  */
-  val = MAYBE_SWAP (total_len);
-  obstack_grow (&contents, &val, sizeof (val));
-  total_len += obstack_object_size (&addr_obstack);
+  contents.append_data (MAYBE_SWAP (total_len));
+  total_len += addr_vec.size ();
 
   /* The offset of the symbol table from the start of the file.  */
-  val = MAYBE_SWAP (total_len);
-  obstack_grow (&contents, &val, sizeof (val));
-  total_len += obstack_object_size (&symtab_obstack);
+  contents.append_data (MAYBE_SWAP (total_len));
+  total_len += symtab_vec.size ();
 
   /* The offset of the constant pool from the start of the file.  */
-  val = MAYBE_SWAP (total_len);
-  obstack_grow (&contents, &val, sizeof (val));
-  total_len += obstack_object_size (&constant_pool);
+  contents.append_data (MAYBE_SWAP (total_len));
+  total_len += constant_pool.size ();
+
+  gdb_assert (contents.size () == size_of_contents);
+
+  contents.file_write (out_file);
+  cu_list.file_write (out_file);
+  types_cu_list.file_write (out_file);
+  addr_vec.file_write (out_file);
+  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));
+    }
 
-  gdb_assert (obstack_object_size (&contents) == size_of_contents);
+  /* 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.  */
 
-  write_obstack (out_file, &contents);
-  write_obstack (out_file, &cu_list);
-  write_obstack (out_file, &types_cu_list);
-  write_obstack (out_file, &addr_obstack);
-  write_obstack (out_file, &symtab_obstack);
-  write_obstack (out_file, &constant_pool);
+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;
 
-  fclose (out_file);
+  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));
 
-  /* We want to keep the file, so we set cleanup_filename to NULL
-     here.  See unlink_if_set.  */
-  cleanup_filename = NULL;
+  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);
+    }
 
-  do_cleanups (cleanup);
+  /* 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)
   {
@@ -23465,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)
          {
@@ -23501,8 +27041,6 @@ show_check_physname (struct ui_file *file, int from_tty,
                    value);
 }
 
-void _initialize_dwarf2_read (void);
-
 void
 _initialize_dwarf2_read (void)
 {
@@ -23599,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);
 
@@ -23612,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
 }