Make init_type/arch_type take a size in bits
[deliverable/binutils-gdb.git] / gdb / dwarf2read.c
index e390b322978accacee4edf84cd82ea49eb79a116..7a59c1b4358276b0173eb965dc8b8051403d1c4f 100644 (file)
 #include "common/function-view.h"
 #include "common/gdb_optional.h"
 #include "common/underlying.h"
-
+#include "common/byte-vector.h"
+#include "filename-seen-cache.h"
+#include "producer.h"
 #include <fcntl.h>
 #include <sys/types.h>
 #include <algorithm>
+#include <unordered_set>
+#include <unordered_map>
 
 typedef struct symbol *symbolp;
 DEF_VEC_P (symbolp);
@@ -221,85 +225,105 @@ struct tu_stats
 
 struct dwarf2_per_objfile
 {
-  struct dwarf2_section_info info;
-  struct dwarf2_section_info abbrev;
-  struct dwarf2_section_info line;
-  struct dwarf2_section_info loc;
-  struct dwarf2_section_info loclists;
-  struct dwarf2_section_info macinfo;
-  struct dwarf2_section_info macro;
-  struct dwarf2_section_info str;
-  struct dwarf2_section_info line_str;
-  struct dwarf2_section_info ranges;
-  struct dwarf2_section_info rnglists;
-  struct dwarf2_section_info addr;
-  struct dwarf2_section_info frame;
-  struct dwarf2_section_info eh_frame;
-  struct dwarf2_section_info gdb_index;
+  /* Construct a dwarf2_per_objfile for OBJFILE.  NAMES points to the
+     dwarf2 section names, or is NULL if the standard ELF names are
+     used.  */
+  dwarf2_per_objfile (struct objfile *objfile,
+                     const dwarf2_debug_sections *names);
 
-  VEC (dwarf2_section_info_def) *types;
+  ~dwarf2_per_objfile ();
+
+  DISABLE_COPY_AND_ASSIGN (dwarf2_per_objfile);
+
+  /* Free all cached compilation units.  */
+  void free_cached_comp_units ();
+private:
+  /* This function is mapped across the sections and remembers the
+     offset and size of each of the debugging sections we are
+     interested in.  */
+  void locate_sections (bfd *abfd, asection *sectp,
+                       const dwarf2_debug_sections &names);
+
+public:
+  dwarf2_section_info info {};
+  dwarf2_section_info abbrev {};
+  dwarf2_section_info line {};
+  dwarf2_section_info loc {};
+  dwarf2_section_info loclists {};
+  dwarf2_section_info macinfo {};
+  dwarf2_section_info macro {};
+  dwarf2_section_info str {};
+  dwarf2_section_info line_str {};
+  dwarf2_section_info ranges {};
+  dwarf2_section_info rnglists {};
+  dwarf2_section_info addr {};
+  dwarf2_section_info frame {};
+  dwarf2_section_info eh_frame {};
+  dwarf2_section_info gdb_index {};
+
+  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;
 
   /* 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
@@ -308,22 +332,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;
@@ -517,6 +545,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.  */
@@ -569,7 +603,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
@@ -852,12 +886,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.  */
@@ -1451,10 +1484,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.  */
@@ -1502,14 +1531,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 *,
@@ -2146,7 +2178,7 @@ byte_swap (offset_type value)
 #define MAYBE_SWAP(V)  byte_swap (V)
 
 #else
-#define MAYBE_SWAP(V) (V)
+#define MAYBE_SWAP(V) static_cast<offset_type> (V)
 #endif /* WORDS_BIGENDIAN */
 
 /* Read the given attribute value as an address, taking the attribute's
@@ -2182,6 +2214,52 @@ attr_value_as_address (struct attribute *attr)
 /* The suffix for an index file.  */
 #define INDEX_SUFFIX ".gdb-index"
 
+/* 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.
    NAMES points to the dwarf2 section names, or is NULL if the standard
@@ -2199,13 +2277,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
@@ -2311,95 +2384,88 @@ section_is_p (const char *section_name,
   return 0;
 }
 
-/* This function is mapped across the sections and remembers the
-   offset and size of each of the debugging sections we are interested
-   in.  */
+/* See declaration.  */
 
-static void
-dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
+void
+dwarf2_per_objfile::locate_sections (bfd *abfd, asection *sectp,
+                                    const dwarf2_debug_sections &names)
 {
-  const struct dwarf2_debug_sections *names;
   flagword aflag = bfd_get_section_flags (abfd, sectp);
 
-  if (vnames == NULL)
-    names = &dwarf2_elf_names;
-  else
-    names = (const struct dwarf2_debug_sections *) vnames;
-
   if ((aflag & SEC_HAS_CONTENTS) == 0)
     {
     }
-  else if (section_is_p (sectp->name, &names->info))
+  else if (section_is_p (sectp->name, &names.info))
     {
-      dwarf2_per_objfile->info.s.section = sectp;
-      dwarf2_per_objfile->info.size = bfd_get_section_size (sectp);
+      this->info.s.section = sectp;
+      this->info.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->abbrev))
+  else if (section_is_p (sectp->name, &names.abbrev))
     {
-      dwarf2_per_objfile->abbrev.s.section = sectp;
-      dwarf2_per_objfile->abbrev.size = bfd_get_section_size (sectp);
+      this->abbrev.s.section = sectp;
+      this->abbrev.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->line))
+  else if (section_is_p (sectp->name, &names.line))
     {
-      dwarf2_per_objfile->line.s.section = sectp;
-      dwarf2_per_objfile->line.size = bfd_get_section_size (sectp);
+      this->line.s.section = sectp;
+      this->line.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->loc))
+  else if (section_is_p (sectp->name, &names.loc))
     {
-      dwarf2_per_objfile->loc.s.section = sectp;
-      dwarf2_per_objfile->loc.size = bfd_get_section_size (sectp);
+      this->loc.s.section = sectp;
+      this->loc.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->loclists))
+  else if (section_is_p (sectp->name, &names.loclists))
     {
-      dwarf2_per_objfile->loclists.s.section = sectp;
-      dwarf2_per_objfile->loclists.size = bfd_get_section_size (sectp);
+      this->loclists.s.section = sectp;
+      this->loclists.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->macinfo))
+  else if (section_is_p (sectp->name, &names.macinfo))
     {
-      dwarf2_per_objfile->macinfo.s.section = sectp;
-      dwarf2_per_objfile->macinfo.size = bfd_get_section_size (sectp);
+      this->macinfo.s.section = sectp;
+      this->macinfo.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->macro))
+  else if (section_is_p (sectp->name, &names.macro))
     {
-      dwarf2_per_objfile->macro.s.section = sectp;
-      dwarf2_per_objfile->macro.size = bfd_get_section_size (sectp);
+      this->macro.s.section = sectp;
+      this->macro.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->str))
+  else if (section_is_p (sectp->name, &names.str))
     {
-      dwarf2_per_objfile->str.s.section = sectp;
-      dwarf2_per_objfile->str.size = bfd_get_section_size (sectp);
+      this->str.s.section = sectp;
+      this->str.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->line_str))
+  else if (section_is_p (sectp->name, &names.line_str))
     {
-      dwarf2_per_objfile->line_str.s.section = sectp;
-      dwarf2_per_objfile->line_str.size = bfd_get_section_size (sectp);
+      this->line_str.s.section = sectp;
+      this->line_str.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->addr))
+  else if (section_is_p (sectp->name, &names.addr))
     {
-      dwarf2_per_objfile->addr.s.section = sectp;
-      dwarf2_per_objfile->addr.size = bfd_get_section_size (sectp);
+      this->addr.s.section = sectp;
+      this->addr.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->frame))
+  else if (section_is_p (sectp->name, &names.frame))
     {
-      dwarf2_per_objfile->frame.s.section = sectp;
-      dwarf2_per_objfile->frame.size = bfd_get_section_size (sectp);
+      this->frame.s.section = sectp;
+      this->frame.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->eh_frame))
+  else if (section_is_p (sectp->name, &names.eh_frame))
     {
-      dwarf2_per_objfile->eh_frame.s.section = sectp;
-      dwarf2_per_objfile->eh_frame.size = bfd_get_section_size (sectp);
+      this->eh_frame.s.section = sectp;
+      this->eh_frame.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->ranges))
+  else if (section_is_p (sectp->name, &names.ranges))
     {
-      dwarf2_per_objfile->ranges.s.section = sectp;
-      dwarf2_per_objfile->ranges.size = bfd_get_section_size (sectp);
+      this->ranges.s.section = sectp;
+      this->ranges.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->rnglists))
+  else if (section_is_p (sectp->name, &names.rnglists))
     {
-      dwarf2_per_objfile->rnglists.s.section = sectp;
-      dwarf2_per_objfile->rnglists.size = bfd_get_section_size (sectp);
+      this->rnglists.s.section = sectp;
+      this->rnglists.size = bfd_get_section_size (sectp);
     }
-  else if (section_is_p (sectp->name, &names->types))
+  else if (section_is_p (sectp->name, &names.types))
     {
       struct dwarf2_section_info type_section;
 
@@ -2407,18 +2473,18 @@ 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))
     {
-      dwarf2_per_objfile->gdb_index.s.section = sectp;
-      dwarf2_per_objfile->gdb_index.size = bfd_get_section_size (sectp);
+      this->gdb_index.s.section = sectp;
+      this->gdb_index.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,
@@ -2651,10 +2717,10 @@ dwarf2_get_dwz_file (void)
   std::string abs_storage;
   if (!IS_ABSOLUTE_PATH (filename))
     {
-      char *abs = gdb_realpath (objfile_name (dwarf2_per_objfile->objfile));
+      gdb::unique_xmalloc_ptr<char> abs
+       = gdb_realpath (objfile_name (dwarf2_per_objfile->objfile));
 
-      make_cleanup (xfree, abs);
-      abs_storage = ldirname (abs) + SLASH_STRING + filename;
+      abs_storage = ldirname (abs.get ()) + SLASH_STRING + filename;
       filename = abs_storage.c_str ();
     }
 
@@ -2885,7 +2951,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);
@@ -3057,13 +3123,11 @@ 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;
@@ -3104,7 +3168,6 @@ 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
@@ -3526,7 +3589,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];
 }
@@ -3850,10 +3913,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, name))
            return stab;
          if (with_opaque != NULL
-             && strcmp_iw (SYMBOL_SEARCH_NAME (with_opaque), name) == 0)
+             && SYMBOL_MATCHES_SEARCH_NAME (with_opaque, name))
            stab_best = stab;
 
          /* Keep looking through other CUs.  */
@@ -4259,64 +4322,73 @@ static void
 dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
                          void *data, int need_fullname)
 {
-  int i;
-  htab_up visited (htab_create_alloc (10, htab_hash_pointer, htab_eq_pointer,
-                                     NULL, xcalloc, xfree));
-
   dw2_setup (objfile);
 
-  /* 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 (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+  if (!dwarf2_per_objfile->filenames_cache)
     {
-      struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
+      dwarf2_per_objfile->filenames_cache.emplace ();
 
-      if (per_cu->v.quick->compunit_symtab)
-       {
-         void **slot = htab_find_slot (visited.get (),
-                                       per_cu->v.quick->file_names,
-                                       INSERT);
+      htab_up visited (htab_create_alloc (10,
+                                         htab_hash_pointer, htab_eq_pointer,
+                                         NULL, xcalloc, xfree));
 
-         *slot = per_cu->v.quick->file_names;
-       }
-    }
-
-  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;
+      /* 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.  */
 
-      /* We only need to look at symtabs not already expanded.  */
-      if (per_cu->v.quick->compunit_symtab)
-       continue;
+      for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+       {
+         struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i);
 
-      file_data = dw2_get_file_names (per_cu);
-      if (file_data == NULL)
-       continue;
+         if (per_cu->v.quick->compunit_symtab)
+           {
+             void **slot = htab_find_slot (visited.get (),
+                                           per_cu->v.quick->file_names,
+                                           INSERT);
 
-      slot = htab_find_slot (visited.get (), file_data, INSERT);
-      if (*slot)
-       {
-         /* Already visited.  */
-         continue;
+             *slot = per_cu->v.quick->file_names;
+           }
        }
-      *slot = file_data;
 
-      for (j = 0; j < file_data->num_file_names; ++j)
+      for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
        {
-         const char *this_real_name;
+         int j;
+         struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+         struct quick_file_names *file_data;
+         void **slot;
 
-         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);
+         /* 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
@@ -6247,8 +6319,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
@@ -6257,12 +6327,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 ();
@@ -6623,7 +6698,6 @@ static void
 dwarf2_build_psymtabs_hard (struct objfile *objfile)
 {
   struct cleanup *back_to, *addrmap_cleanup;
-  struct obstack temp_obstack;
   int i;
 
   if (dwarf_read_debug)
@@ -6646,8 +6720,7 @@ 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);
+  auto_obstack temp_obstack;
   objfile->psymtabs_addrmap = addrmap_create_mutable (&temp_obstack);
   addrmap_cleanup = make_cleanup (psymtabs_addrmap_cleanup, objfile);
 
@@ -6717,6 +6790,7 @@ 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,
@@ -6736,20 +6810,33 @@ read_comp_units_from_section (struct objfile *objfile,
 
   while (info_ptr < section->buffer + section->size)
     {
-      unsigned int length, initial_length_size;
       struct dwarf2_per_cu_data *this_cu;
 
       sect_offset sect_off = (sect_offset) (info_ptr - section->buffer);
 
-      /* Read just enough information to find out where the next
-        compilation unit is.  */
-      length = read_initial_length (abfd, info_ptr, &initial_length_size);
+      comp_unit_head cu_header;
+      read_and_check_comp_unit_head (&cu_header, section, abbrev_section,
+                                    info_ptr, rcuh_kind::COMPILE);
 
       /* Save the compilation unit for later lookup.  */
-      this_cu = XOBNEW (&objfile->objfile_obstack, struct dwarf2_per_cu_data);
-      memset (this_cu, 0, sizeof (*this_cu));
+      if (cu_header.unit_type != DW_UT_type)
+       {
+         this_cu = XOBNEW (&objfile->objfile_obstack,
+                           struct dwarf2_per_cu_data);
+         memset (this_cu, 0, sizeof (*this_cu));
+       }
+      else
+       {
+         auto sig_type = XOBNEW (&objfile->objfile_obstack,
+                                 struct signatured_type);
+         memset (sig_type, 0, sizeof (*sig_type));
+         sig_type->signature = cu_header.signature;
+         sig_type->type_offset_in_tu = cu_header.type_cu_offset_in_tu;
+         this_cu = &sig_type->per_cu;
+       }
+      this_cu->is_debug_types = (cu_header.unit_type == DW_UT_type);
       this_cu->sect_off = sect_off;
-      this_cu->length = length + initial_length_size;
+      this_cu->length = cu_header.length + cu_header.initial_length_size;
       this_cu->is_dwz = is_dwz;
       this_cu->objfile = objfile;
       this_cu->section = section;
@@ -6782,12 +6869,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);
 
@@ -7949,6 +8037,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
@@ -7960,6 +8065,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;
@@ -7968,6 +8079,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;
+           }
+       }
     }
 }
 
@@ -8405,28 +8536,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)
     {
@@ -8517,8 +8664,6 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       new_symbol (die, NULL, cu);
       break;
     }
-
-  do_cleanups (in_process);
 }
 \f
 /* DWARF name computation.  */
@@ -8582,6 +8727,38 @@ die_needs_namespace (struct die_info *die, struct dwarf2_cu *cu)
     }
 }
 
+/* Return the DIE's linkage name attribute, either DW_AT_linkage_name
+   or DW_AT_MIPS_linkage_name.  Returns NULL if the attribute is not
+   defined for the given DIE.  */
+
+static struct attribute *
+dw2_linkage_name_attr (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct attribute *attr;
+
+  attr = dwarf2_attr (die, DW_AT_linkage_name, cu);
+  if (attr == NULL)
+    attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu);
+
+  return attr;
+}
+
+/* Return the DIE's linkage name as a string, either DW_AT_linkage_name
+   or DW_AT_MIPS_linkage_name.  Returns NULL if the attribute is not
+   defined for the given DIE.  */
+
+static const char *
+dw2_linkage_name (struct die_info *die, struct dwarf2_cu *cu)
+{
+  const char *linkage_name;
+
+  linkage_name = dwarf2_string_attr (die, DW_AT_linkage_name, cu);
+  if (linkage_name == NULL)
+    linkage_name = dwarf2_string_attr (die, DW_AT_MIPS_linkage_name, cu);
+
+  return linkage_name;
+}
+
 /* Compute the fully qualified name of DIE in CU.  If PHYSNAME is nonzero,
    compute the physname for the object, which include a method's:
    - formal parameters (C++),
@@ -8621,11 +8798,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;
     }
@@ -8866,9 +9040,7 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
 
   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.  */
@@ -9048,8 +9220,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)
@@ -9123,8 +9294,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))
@@ -9164,7 +9333,7 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
            continue;
          }
 
-       VEC_safe_push (const_char_ptr, excludes, imported_name);
+       excludes.push_back (imported_name);
 
        process_die (child_die, cu);
       }
@@ -9177,8 +9346,19 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
                       excludes,
                       0,
                       &objfile->objfile_obstack);
+}
 
-  do_cleanups (cleanups);
+/* ICC<14 does not output the required DW_AT_declaration on incomplete
+   types, but gives them a size of zero.  Starting with version 14,
+   ICC is compatible with GCC.  */
+
+static int
+producer_is_icc_lt_14 (struct dwarf2_cu *cu)
+{
+  if (!cu->checked_producer)
+    check_producer (cu);
+
+  return cu->producer_is_icc_lt_14;
 }
 
 /* Check for possibly missing DW_AT_comp_dir with relative .debug_line
@@ -9296,7 +9476,9 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
   line_header_up lh = dwarf_decode_line_header (line_offset, cu);
   if (lh == NULL)
     return;
-  cu->line_header = lh.get ();
+
+  cu->line_header = lh.release ();
+  cu->line_header_die_owner = die;
 
   if (dwarf2_per_objfile->line_header_hash == NULL)
     slot = NULL;
@@ -9312,6 +9494,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
     {
@@ -9326,7 +9509,6 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
   dwarf_decode_lines (cu->line_header, comp_dir, cu, NULL, lowpc,
                      decode_mapping);
 
-  lh.release ();
 }
 
 /* Process DW_TAG_compile_unit or DW_TAG_partial_unit.  */
@@ -9464,7 +9646,8 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
       return;
     }
 
-  cu->line_header = lh.get ();
+  cu->line_header = lh.release ();
+  cu->line_header_die_owner = die;
 
   if (first_time)
     {
@@ -9475,21 +9658,23 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
         process_full_type_unit still needs to know if this is the first
         time.  */
 
-      tu_group->num_symtabs = lh->file_names.size ();
-      tu_group->symtabs = XNEWVEC (struct symtab *, lh->file_names.size ());
+      tu_group->num_symtabs = cu->line_header->file_names.size ();
+      tu_group->symtabs = XNEWVEC (struct symtab *,
+                                  cu->line_header->file_names.size ());
 
-      for (i = 0; i < lh->file_names.size (); ++i)
+      for (i = 0; i < cu->line_header->file_names.size (); ++i)
        {
-         file_entry &fe = lh->file_names[i];
+         file_entry &fe = cu->line_header->file_names[i];
 
-         dwarf2_start_subfile (fe.name, fe.include_dir (lh.get ()));
+         dwarf2_start_subfile (fe.name, fe.include_dir (cu->line_header));
 
          if (current_subfile->symtab == NULL)
            {
-             /* NOTE: start_subfile will recognize when it's been passed
-                a file it has already seen.  So we can't assume there's a
-                simple mapping from lh->file_names to subfiles, plus
-                lh->file_names may contain dups.  */
+             /* NOTE: start_subfile will recognize when it's been
+                passed a file it has already seen.  So we can't
+                assume there's a simple mapping from
+                cu->line_header->file_names to subfiles, plus
+                cu->line_header->file_names may contain dups.  */
              current_subfile->symtab
                = allocate_symtab (cust, current_subfile->name);
            }
@@ -9502,16 +9687,14 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
     {
       restart_symtab (tu_group->compunit_symtab, "", 0);
 
-      for (i = 0; i < lh->file_names.size (); ++i)
+      for (i = 0; i < cu->line_header->file_names.size (); ++i)
        {
-         struct file_entry *fe = &lh->file_names[i];
+         file_entry &fe = cu->line_header->file_names[i];
 
-         fe->symtab = tu_group->symtabs[i];
+         fe.symtab = tu_group->symtabs[i];
        }
     }
 
-  lh.release ();
-
   /* The main symtab is allocated last.  Type units don't have DW_AT_name
      so they don't have a "real" (so to speak) symtab anyway.
      There is later code that will assign the main symtab to all symbols
@@ -9702,72 +9885,76 @@ create_dwo_cu_reader (const struct die_reader_specs *reader,
                        hex_string (dwo_unit->signature));
 }
 
-/* Create the dwo_unit for the lone CU in DWO_FILE.
+/* Create the dwo_units for the CUs in a DWO_FILE.
    Note: This function processes DWO files only, not DWP files.  */
 
-static struct dwo_unit *
-create_dwo_cu (struct dwo_file *dwo_file)
+static void
+create_cus_hash_table (struct dwo_file &dwo_file, dwarf2_section_info &section,
+                      htab_t &cus_htab)
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
-  struct dwarf2_section_info *section = &dwo_file->sections.info;
+  const struct dwarf2_section_info *abbrev_section = &dwo_file.sections.abbrev;
   const gdb_byte *info_ptr, *end_ptr;
-  struct create_dwo_cu_data create_dwo_cu_data;
-  struct dwo_unit *dwo_unit;
 
-  dwarf2_read_section (objfile, section);
-  info_ptr = section->buffer;
+  dwarf2_read_section (objfile, &section);
+  info_ptr = section.buffer;
 
   if (info_ptr == NULL)
-    return NULL;
+    return;
 
   if (dwarf_read_debug)
     {
       fprintf_unfiltered (gdb_stdlog, "Reading %s for %s:\n",
-                         get_section_name (section),
-                         get_section_file_name (section));
+                         get_section_name (&section),
+                         get_section_file_name (&section));
     }
 
-  create_dwo_cu_data.dwo_file = dwo_file;
-  dwo_unit = NULL;
-
-  end_ptr = info_ptr + section->size;
+  end_ptr = info_ptr + section.size;
   while (info_ptr < end_ptr)
     {
       struct dwarf2_per_cu_data per_cu;
+      struct create_dwo_cu_data create_dwo_cu_data;
+      struct dwo_unit *dwo_unit;
+      void **slot;
+      sect_offset sect_off = (sect_offset) (info_ptr - section.buffer);
 
       memset (&create_dwo_cu_data.dwo_unit, 0,
              sizeof (create_dwo_cu_data.dwo_unit));
       memset (&per_cu, 0, sizeof (per_cu));
       per_cu.objfile = objfile;
       per_cu.is_debug_types = 0;
-      per_cu.sect_off = sect_offset (info_ptr - section->buffer);
-      per_cu.section = section;
+      per_cu.sect_off = sect_offset (info_ptr - section.buffer);
+      per_cu.section = &section;
+      create_dwo_cu_data.dwo_file = &dwo_file;
+
+      init_cutu_and_read_dies_no_follow (
+         &per_cu, &dwo_file, create_dwo_cu_reader, &create_dwo_cu_data);
+      info_ptr += per_cu.length;
+
+      // If the unit could not be parsed, skip it.
+      if (create_dwo_cu_data.dwo_unit.dwo_file == NULL)
+       continue;
 
-      init_cutu_and_read_dies_no_follow (&per_cu, dwo_file,
-                                        create_dwo_cu_reader,
-                                        &create_dwo_cu_data);
+      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:
@@ -10772,7 +10959,7 @@ open_and_init_dwo_file (struct dwarf2_per_cu_data *per_cu,
   bfd_map_over_sections (dwo_file->dbfd, dwarf2_locate_dwo_sections,
                         &dwo_file->sections);
 
-  dwo_file->cu = create_dwo_cu (dwo_file);
+  create_cus_hash_table (*dwo_file, dwo_file->sections.info, dwo_file->cus);
 
   create_debug_types_hash_table (dwo_file, dwo_file->sections.types,
                                 dwo_file->tus);
@@ -11139,10 +11326,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)
@@ -11892,13 +12083,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
          const char *target_physname;
 
          /* Prefer the mangled name; otherwise compute the demangled one.  */
-         target_physname = dwarf2_string_attr (target_die,
-                                               DW_AT_linkage_name,
-                                               target_cu);
-         if (target_physname == NULL)
-           target_physname = dwarf2_string_attr (target_die,
-                                                DW_AT_MIPS_linkage_name,
-                                                target_cu);
+         target_physname = dw2_linkage_name (target_die, target_cu);
          if (target_physname == NULL)
            target_physname = dwarf2_physname (NULL, target_die, target_cu);
          if (target_physname == NULL)
@@ -12681,8 +12866,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
@@ -13423,17 +13608,6 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
   smash_to_methodptr_type (type, new_type);
 }
 
-/* Return non-zero if the CU's PRODUCER string matches the Intel C/C++ compiler
-   (icc).  */
-
-static int
-producer_is_icc (struct dwarf2_cu *cu)
-{
-  if (!cu->checked_producer)
-    check_producer (cu);
-
-  return cu->producer_is_icc;
-}
 
 /* Called when we find the DIE that starts a structure or union scope
    (definition) to create a type for the structure or union.  Fill in
@@ -13539,10 +13713,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
@@ -13793,15 +13967,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;
@@ -13846,8 +14017,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
@@ -14444,9 +14613,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);
        }
     }
 
@@ -15042,7 +15212,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;
 }
@@ -15080,7 +15250,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:
@@ -15146,8 +15316,7 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
       default:
        complaint (&symfile_complaints, _("unsupported DW_AT_encoding: '%s'"),
                   dwarf_type_encoding_name (encoding));
-       type = init_type (objfile, TYPE_CODE_ERROR,
-                         bits / TARGET_CHAR_BIT, name);
+       type = init_type (objfile, TYPE_CODE_ERROR, bits, name);
        break;
     }
 
@@ -17554,7 +17723,9 @@ dwarf2_string_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *c
   if (attr != NULL)
     {
       if (attr->form == DW_FORM_strp || attr->form == DW_FORM_line_strp
-         || attr->form == DW_FORM_string || attr->form == DW_FORM_GNU_strp_alt)
+         || attr->form == DW_FORM_string
+         || attr->form == DW_FORM_GNU_str_index
+         || attr->form == DW_FORM_GNU_strp_alt)
        str = DW_STRING (attr);
       else
         complaint (&symfile_complaints,
@@ -19024,8 +19195,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
@@ -19407,6 +19577,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;
 
@@ -19766,12 +19937,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
@@ -19826,9 +19993,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;
 
@@ -20154,10 +20319,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;
 
@@ -20400,6 +20562,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);
@@ -20491,7 +20657,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
@@ -20826,6 +20992,7 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
       break;
 
     case DW_FORM_sdata:
+    case DW_FORM_implicit_const:
       type = die_type (die, cu);
       result = write_constant_as_bytes (obstack, byte_order,
                                        type, DW_SND (attr), len);
@@ -21518,20 +21685,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)
 {
@@ -21591,7 +21744,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 == ' ')
@@ -21609,7 +21762,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);
@@ -21638,7 +21791,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);
@@ -21762,6 +21915,9 @@ skip_form_bytes (bfd *abfd, const gdb_byte *bytes, const gdb_byte *buffer_end,
        }
       break;
 
+    case DW_FORM_implicit_const:
+      break;
+
     default:
       {
       complain:
@@ -22403,6 +22559,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;
@@ -22758,21 +22915,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
@@ -22854,16 +22997,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.
@@ -23193,69 +23327,58 @@ dwarf2_per_objfile_free (struct objfile *objfile, void *d)
 \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.  */
-
-static hashval_t
-hash_strtab_entry (const void *e)
+/* In-memory buffer to prepare data to be written later to a file.  */
+class data_buf
 {
-  const struct strtab_entry *entry = (const struct strtab_entry *) e;
-  return mapped_index_string_hash (INT_MAX, entry->str);
-}
-
-/* Equality function for a strtab_entry.  */
+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)));
+  }
 
-static int
-eq_strtab_entry (const void *a, const void *b)
-{
-  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);
-}
+  /* 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));
+  }
 
-/* Create a strtab_entry hash table.  */
+  /* 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);
+  }
 
-static htab_t
-create_strtab (void)
-{
-  return htab_create_alloc (100, hash_strtab_entry, eq_strtab_entry,
-                           xfree, xcalloc, xfree);
-}
+  /* Return the size of the buffer.  */
+  size_t size () const
+  {
+    return m_vec.size ();
+  }
 
-/* Add a string to the constant pool.  Return the string's offset in
-   host order.  */
+  /* Write the buffer to FILE.  */
+  void file_write (FILE *file) const
+  {
+    if (::fwrite (m_vec.data (), 1, m_vec.size (), file) != m_vec.size ())
+      error (_("couldn't write data to file"));
+  }
 
-static offset_type
-add_string (htab_t table, struct obstack *cpool, const char *str)
-{
-  void **slot;
-  struct strtab_entry entry;
-  struct strtab_entry *result;
+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;
+  }
 
-  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;
-}
+  gdb::byte_vector m_vec;
+};
 
 /* An entry in the symbol table.  */
 struct symtab_index_entry
@@ -23266,107 +23389,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);
     }
 }
 
@@ -23375,24 +23432,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.
@@ -23404,20 +23454,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;
@@ -23432,18 +23479,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.  */
@@ -23451,112 +23487,116 @@ 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);
+private:
+  friend class c_str_view_hasher;
+  const char *const 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;
-}
+/* 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);
+  }
+};
 
-/* 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 std::vector<>.  */
+template<typename T>
+class vector_hasher
+{
+public:
+  size_t operator () (const std::vector<T> &key) const
+  {
+    return iterative_hash (key.data (),
+                          sizeof (key.front ()) * key.size (), 0);
+  }
+};
+
+/* 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 (struct mapped_symtab *symtab,
-                 struct obstack *output, struct obstack *cpool)
+write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool)
 {
-  offset_type i;
-  htab_t symbol_hash_table;
-  htab_t str_table;
-
-  symbol_hash_table = create_symbol_hash_table ();
-  str_table = create_strtab ();
+  {
+    /* 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
        {
@@ -23566,50 +23606,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
@@ -23621,24 +23634,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.  */
@@ -23650,44 +23658,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,
@@ -23699,7 +23702,7 @@ 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);
 }
@@ -23746,7 +23749,7 @@ symbol_kind (struct partial_symbol *psym)
 
 static void
 write_psymbols (struct mapped_symtab *symtab,
-               htab_t psyms_seen,
+               std::unordered_set<partial_symbol *> &psyms_seen,
                struct partial_symbol **psymp,
                int count,
                offset_type cu_index,
@@ -23755,43 +23758,33 @@ write_psymbols (struct mapped_symtab *symtab,
   for (; count-- > 0; ++psymp)
     {
       struct partial_symbol *psym = *psymp;
-      void **slot;
 
       if (SYMBOL_LANGUAGE (psym) == language_ada)
        error (_("Ada is not currently supported by the index"));
 
       /* Only add a given psymbol once.  */
-      slot = htab_find_slot (psyms_seen, psym, INSERT);
-      if (!*slot)
+      if (psyms_seen.insert (psym).second)
        {
          gdb_index_symbol_kind kind = symbol_kind (psym);
 
-         *slot = psym;
          add_index_entry (symtab, SYMBOL_SEARCH_NAME (psym),
                           is_static, kind, cu_index);
        }
     }
 }
 
-/* Write the contents of an ("unfinished") obstack to FILE.  Throw an
-   exception if there is an error.  */
-
-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"));
-}
-
 /* 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;
-  struct obstack *types_list;
-  htab_t psyms_seen;
+  data_buf &types_list;
+  std::unordered_set<partial_symbol *> &psyms_seen;
   int cu_index;
 };
 
@@ -23805,7 +23798,6 @@ write_one_signatured_type (void **slot, void *d)
     = (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];
 
   write_psymbols (info->symtab,
                  info->psyms_seen,
@@ -23820,20 +23812,33 @@ write_one_signatured_type (void **slot, void *d)
                  psymtab->n_static_syms, info->cu_index,
                  1);
 
-  store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE,
-                         to_underlying (entry->per_cu.sect_off));
-  obstack_grow (info->types_list, val, 8);
-  store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE,
-                         to_underlying (entry->type_offset_in_tu));
-  obstack_grow (info->types_list, val, 8);
-  store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->signature);
-  obstack_grow (info->types_list, val, 8);
+  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.  */
 
@@ -23841,7 +23846,7 @@ static void
 recursively_write_psymbols (struct objfile *objfile,
                            struct partial_symtab *psymtab,
                            struct mapped_symtab *symtab,
-                           htab_t psyms_seen,
+                           std::unordered_set<partial_symbol *> &psyms_seen,
                            offset_type cu_index)
 {
   int i;
@@ -23868,17 +23873,6 @@ recursively_write_psymbols (struct objfile *objfile,
 static void
 write_psymtabs_to_index (struct objfile *objfile, const char *dir)
 {
-  struct cleanup *cleanup;
-  char *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;
-
   if (dwarf2_per_objfile->using_index)
     error (_("Cannot use an index to create the index"));
 
@@ -23888,58 +23882,61 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
   if (!objfile->psymtabs || !objfile->psymtabs_addrmap)
     return;
 
+  struct stat st;
   if (stat (objfile_name (objfile), &st) < 0)
     perror_with_name (objfile_name (objfile));
 
-  filename = concat (dir, SLASH_STRING, lbasename (objfile_name (objfile)),
-                    INDEX_SUFFIX, (char *) NULL);
-  cleanup = make_cleanup (xfree, filename);
+  std::string filename (std::string (dir) + SLASH_STRING
+                       + lbasename (objfile_name (objfile)) + INDEX_SUFFIX);
 
-  out_file = gdb_fopen_cloexec (filename, "wb");
+  FILE *out_file = gdb_fopen_cloexec (filename.c_str (), "wb").release ();
   if (!out_file)
-    error (_("Can't open `%s' for writing"), filename);
-
-  gdb::unlinker unlink_file (filename);
-
-  symtab = create_mapped_symtab ();
-  make_cleanup (cleanup_mapped_symtab, symtab);
-
-  obstack_init (&addr_obstack);
-  make_cleanup_obstack_free (&addr_obstack);
-
-  obstack_init (&cu_list);
-  make_cleanup_obstack_free (&cu_list);
+    error (_("Can't open `%s' for writing"), filename.c_str ());
 
-  obstack_init (&types_cu_list);
-  make_cleanup_obstack_free (&types_cu_list);
+  /* 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);
 
-  htab_up psyms_seen (htab_create_alloc (100, htab_hash_pointer,
-                                        htab_eq_pointer,
-                                        NULL, xcalloc, xfree));
+  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)
+
+  /* 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.  */
+  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;
+
+      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.  */
+  std::unordered_set<partial_symbol *> psyms_seen (psyms_count / 4);
+  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
@@ -23948,36 +23945,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,
-                             to_underlying (per_cu->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);
@@ -23985,63 +23976,49 @@ 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);
-
-  gdb_assert (obstack_object_size (&contents) == size_of_contents);
+  contents.append_data (MAYBE_SWAP (total_len));
+  total_len += constant_pool.size ();
 
-  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);
+  gdb_assert (contents.size () == size_of_contents);
 
-  fclose (out_file);
+  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);
 
   /* We want to keep the file.  */
   unlink_file.keep ();
-
-  do_cleanups (cleanup);
 }
 
 /* Implementation of the `save gdb-index' command.
@@ -24050,7 +24027,7 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
    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;
 
@@ -24109,8 +24086,6 @@ show_check_physname (struct ui_file *file, int from_tty,
                    value);
 }
 
-void _initialize_dwarf2_read (void);
-
 void
 _initialize_dwarf2_read (void)
 {
This page took 0.065164 seconds and 4 git commands to generate.