Make init_type/arch_type take a size in bits
[deliverable/binutils-gdb.git] / gdb / dwarf2read.c
index da70884c48496053536109da8754b2c32cd36a05..7a59c1b4358276b0173eb965dc8b8051403d1c4f 100644 (file)
 #include "namespace.h"
 #include "common/gdb_unlinker.h"
 #include "common/function-view.h"
-
+#include "common/gdb_optional.h"
+#include "common/underlying.h"
+#include "common/byte-vector.h"
+#include "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);
@@ -219,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;
-
-  VEC (dwarf2_section_info_def) *types;
+  /* Construct a dwarf2_per_objfile for OBJFILE.  NAMES points to the
+     dwarf2 section names, or is NULL if the standard ELF names are
+     used.  */
+  dwarf2_per_objfile (struct objfile *objfile,
+                     const dwarf2_debug_sections *names);
+
+  ~dwarf2_per_objfile ();
+
+  DISABLE_COPY_AND_ASSIGN (dwarf2_per_objfile);
+
+  /* Free all cached compilation units.  */
+  void free_cached_comp_units ();
+private:
+  /* This function is mapped across the sections and remembers the
+     offset and size of each of the debugging sections we are
+     interested in.  */
+  void locate_sections (bfd *abfd, asection *sectp,
+                       const dwarf2_debug_sections &names);
+
+public:
+  dwarf2_section_info info {};
+  dwarf2_section_info abbrev {};
+  dwarf2_section_info line {};
+  dwarf2_section_info loc {};
+  dwarf2_section_info loclists {};
+  dwarf2_section_info macinfo {};
+  dwarf2_section_info macro {};
+  dwarf2_section_info str {};
+  dwarf2_section_info line_str {};
+  dwarf2_section_info ranges {};
+  dwarf2_section_info rnglists {};
+  dwarf2_section_info addr {};
+  dwarf2_section_info frame {};
+  dwarf2_section_info eh_frame {};
+  dwarf2_section_info gdb_index {};
+
+  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
@@ -306,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;
@@ -395,7 +425,7 @@ struct comp_unit_head
   short version;
   unsigned char addr_size;
   unsigned char signed_addr_p;
-  sect_offset abbrev_offset;
+  sect_offset abbrev_sect_off;
 
   /* Size of file offsets; either 4 or 8.  */
   unsigned int offset_size;
@@ -407,18 +437,18 @@ struct comp_unit_head
 
   /* Offset to the first byte of this compilation unit header in the
      .debug_info section, for resolving relative reference dies.  */
-  sect_offset offset;
+  sect_offset sect_off;
 
   /* Offset to first die in this cu from the start of the cu.
      This will be the first byte following the compilation unit header.  */
-  cu_offset first_die_offset;
+  cu_offset first_die_cu_offset;
 
   /* 64-bit signature of this type unit - it is valid only for
      UNIT_TYPE DW_UT_type.  */
   ULONGEST signature;
 
   /* For types, offset in the type's DIE of the type defined by this TU.  */
-  cu_offset type_offset_in_tu;
+  cu_offset type_cu_offset_in_tu;
 };
 
 /* Type used for delaying computation of method physnames.
@@ -515,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.  */
@@ -567,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
@@ -587,7 +623,7 @@ struct dwarf2_per_cu_data
      initial_length_size.
      If the DIE refers to a DWO file, this is always of the original die,
      not the DWO file.  */
-  sect_offset offset;
+  sect_offset sect_off;
   unsigned int length;
 
   /* DWARF standard version this data has been read from (such as 4 or 5).  */
@@ -726,7 +762,7 @@ struct stmt_list_hash
   struct dwo_unit *dwo_unit;
 
   /* Offset in .debug_line or .debug_line.dwo.  */
-  sect_offset line_offset;
+  sect_offset line_sect_off;
 };
 
 /* Each element of dwarf2_per_objfile->type_unit_groups is a pointer to
@@ -802,8 +838,8 @@ struct dwo_unit
   /* The section this CU/TU lives in, in the DWO file.  */
   struct dwarf2_section_info *section;
 
-  /* Same as dwarf2_per_cu_data:{offset,length} but in the DWO section.  */
-  sect_offset offset;
+  /* Same as dwarf2_per_cu_data:{sect_off,length} but in the DWO section.  */
+  sect_offset sect_off;
   unsigned int length;
 
   /* For types, offset in the type's DIE of the type defined by this TU.  */
@@ -850,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.  */
@@ -1052,16 +1087,46 @@ typedef void (die_reader_func_ftype) (const struct die_reader_specs *reader,
                                      int has_children,
                                      void *data);
 
+/* A 1-based directory index.  This is a strong typedef to prevent
+   accidentally using a directory index as a 0-based index into an
+   array/vector.  */
+enum class dir_index : unsigned int {};
+
+/* Likewise, a 1-based file name index.  */
+enum class file_name_index : unsigned int {};
+
 struct file_entry
 {
-  const char *name;
-  unsigned int dir_index;
-  unsigned int mod_time;
-  unsigned int length;
-  /* Non-zero if referenced by the Line Number Program.  */
-  int included_p;
+  file_entry () = default;
+
+  file_entry (const char *name_, dir_index d_index_,
+             unsigned int mod_time_, unsigned int length_)
+    : name (name_),
+      d_index (d_index_),
+      mod_time (mod_time_),
+      length (length_)
+  {}
+
+  /* Return the include directory at D_INDEX stored in LH.  Returns
+     NULL if D_INDEX is out of bounds.  */
+  const char *include_dir (const line_header *lh) const;
+
+  /* The file name.  Note this is an observing pointer.  The memory is
+     owned by debug_line_buffer.  */
+  const char *name {};
+
+  /* The directory index (1-based).  */
+  dir_index d_index {};
+
+  unsigned int mod_time {};
+
+  unsigned int length {};
+
+  /* True if referenced by the Line Number Program.  */
+  bool included_p {};
+
   /* The associated symbol table, if any.  */
-  struct symtab *symtab;
+  struct symtab *symtab {};
 };
 
 /* The line number information for a compilation unit (found in the
@@ -1069,52 +1134,99 @@ struct file_entry
    which contains the following information.  */
 struct line_header
 {
+  line_header ()
+    : offset_in_dwz {}
+  {}
+
+  /* Add an entry to the include directory table.  */
+  void add_include_dir (const char *include_dir);
+
+  /* Add an entry to the file name table.  */
+  void add_file_name (const char *name, dir_index d_index,
+                     unsigned int mod_time, unsigned int length);
+
+  /* Return the include dir at INDEX (1-based).  Returns NULL if INDEX
+     is out of bounds.  */
+  const char *include_dir_at (dir_index index) const
+  {
+    /* Convert directory index number (1-based) to vector index
+       (0-based).  */
+    size_t vec_index = to_underlying (index) - 1;
+
+    if (vec_index >= include_dirs.size ())
+      return NULL;
+    return include_dirs[vec_index];
+  }
+
+  /* Return the file name at INDEX (1-based).  Returns NULL if INDEX
+     is out of bounds.  */
+  file_entry *file_name_at (file_name_index index)
+  {
+    /* Convert file name index number (1-based) to vector index
+       (0-based).  */
+    size_t vec_index = to_underlying (index) - 1;
+
+    if (vec_index >= file_names.size ())
+      return NULL;
+    return &file_names[vec_index];
+  }
+
+  /* Const version of the above.  */
+  const file_entry *file_name_at (unsigned int index) const
+  {
+    if (index >= file_names.size ())
+      return NULL;
+    return &file_names[index];
+  }
+
   /* Offset of line number information in .debug_line section.  */
-  sect_offset offset;
+  sect_offset sect_off {};
 
   /* OFFSET is for struct dwz_file associated with dwarf2_per_objfile.  */
-  unsigned offset_in_dwz : 1;
-
-  unsigned int total_length;
-  unsigned short version;
-  unsigned int header_length;
-  unsigned char minimum_instruction_length;
-  unsigned char maximum_ops_per_instruction;
-  unsigned char default_is_stmt;
-  int line_base;
-  unsigned char line_range;
-  unsigned char opcode_base;
+  unsigned offset_in_dwz : 1; /* Can't initialize bitfields in-class.  */
+
+  unsigned int total_length {};
+  unsigned short version {};
+  unsigned int header_length {};
+  unsigned char minimum_instruction_length {};
+  unsigned char maximum_ops_per_instruction {};
+  unsigned char default_is_stmt {};
+  int line_base {};
+  unsigned char line_range {};
+  unsigned char opcode_base {};
 
   /* standard_opcode_lengths[i] is the number of operands for the
      standard opcode whose value is i.  This means that
      standard_opcode_lengths[0] is unused, and the last meaningful
      element is standard_opcode_lengths[opcode_base - 1].  */
-  unsigned char *standard_opcode_lengths;
+  std::unique_ptr<unsigned char[]> standard_opcode_lengths;
 
-  /* The include_directories table.  NOTE!  These strings are not
-     allocated with xmalloc; instead, they are pointers into
-     debug_line_buffer.  If you try to free them, `free' will get
-     indigestion.  */
-  unsigned int num_include_dirs, include_dirs_size;
-  const char **include_dirs;
+  /* The include_directories table.  Note these are observing
+     pointers.  The memory is owned by debug_line_buffer.  */
+  std::vector<const char *> include_dirs;
 
-  /* The file_names table.  NOTE!  These strings are not allocated
-     with xmalloc; instead, they are pointers into debug_line_buffer.
-     Don't try to free them directly.  */
-  unsigned int num_file_names, file_names_size;
-  struct file_entry *file_names;
+  /* The file_names table.  */
+  std::vector<file_entry> file_names;
 
   /* The start and end of the statement program following this
      header.  These point into dwarf2_per_objfile->line_buffer.  */
-  const gdb_byte *statement_program_start, *statement_program_end;
+  const gdb_byte *statement_program_start {}, *statement_program_end {};
 };
 
+typedef std::unique_ptr<line_header> line_header_up;
+
+const char *
+file_entry::include_dir (const line_header *lh) const
+{
+  return lh->include_dir_at (d_index);
+}
+
 /* When we construct a partial symbol table entry we only
    need this much information.  */
 struct partial_die_info
   {
     /* Offset of this DIE.  */
-    sect_offset offset;
+    sect_offset sect_off;
 
     /* DWARF-2 tag for this DIE.  */
     ENUM_BITFIELD(dwarf_tag) tag : 16;
@@ -1172,7 +1284,7 @@ struct partial_die_info
       /* The location description associated with this DIE, if any.  */
       struct dwarf_block *locdesc;
       /* The offset of an import, for DW_TAG_imported_unit.  */
-      sect_offset offset;
+      sect_offset sect_off;
     } d;
 
     /* If HAS_PC_INFO, the PC range associated with this DIE.  */
@@ -1224,7 +1336,7 @@ struct abbrev_table
 {
   /* Where the abbrev table came from.
      This is used as a sanity check when the table is used.  */
-  sect_offset offset;
+  sect_offset sect_off;
 
   /* Storage for the abbrev table.  */
   struct obstack abbrev_obstack;
@@ -1279,7 +1391,7 @@ struct die_info
     unsigned int abbrev;
 
     /* Offset in .debug_info or .debug_types section.  */
-    sect_offset offset;
+    sect_offset sect_off;
 
     /* The dies in a compilation unit form an n-ary tree.  PARENT
        points to this die's parent; CHILD points to the first child of
@@ -1372,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.  */
@@ -1423,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 *,
@@ -1566,10 +1677,8 @@ static int die_is_declaration (struct die_info *, struct dwarf2_cu *cu);
 static struct die_info *die_specification (struct die_info *die,
                                           struct dwarf2_cu **);
 
-static void free_line_header (struct line_header *lh);
-
-static struct line_header *dwarf_decode_line_header (unsigned int offset,
-                                                    struct dwarf2_cu *cu);
+static line_header_up dwarf_decode_line_header (sect_offset sect_off,
+                                               struct dwarf2_cu *cu);
 
 static void dwarf_decode_lines (struct line_header *, const char *,
                                struct dwarf2_cu *, struct partial_symtab *,
@@ -1748,7 +1857,7 @@ static const char *dwarf_attr_name (unsigned int);
 
 static const char *dwarf_form_name (unsigned int);
 
-static char *dwarf_bool_name (unsigned int);
+static const char *dwarf_bool_name (unsigned int);
 
 static const char *dwarf_type_encoding_name (unsigned int);
 
@@ -1833,7 +1942,7 @@ static hashval_t partial_die_hash (const void *item);
 static int partial_die_eq (const void *item_lhs, const void *item_rhs);
 
 static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit
-  (sect_offset offset, unsigned int offset_in_dwz, struct objfile *objfile);
+  (sect_offset sect_off, unsigned int offset_in_dwz, struct objfile *objfile);
 
 static void init_one_comp_unit (struct dwarf2_cu *cu,
                                struct dwarf2_per_cu_data *per_cu);
@@ -1885,9 +1994,27 @@ static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu,
 
 static void process_queue (void);
 
-static void find_file_and_directory (struct die_info *die,
-                                    struct dwarf2_cu *cu,
-                                    const char **name, const char **comp_dir);
+/* The return type of find_file_and_directory.  Note, the enclosed
+   string pointers are only valid while this object is valid.  */
+
+struct file_and_directory
+{
+  /* The filename.  This is never NULL.  */
+  const char *name;
+
+  /* The compilation directory.  NULL if not known.  If we needed to
+     compute a new string, this points to COMP_DIR_STORAGE, otherwise,
+     points directly to the DW_AT_comp_dir string attribute owned by
+     the obstack that owns the DIE.  */
+  const char *comp_dir;
+
+  /* If we needed to build a new string for comp_dir, this is what
+     owns the storage.  */
+  std::string comp_dir_storage;
+};
+
+static file_and_directory find_file_and_directory (struct die_info *die,
+                                                  struct dwarf2_cu *cu);
 
 static char *file_full_name (int file, struct line_header *lh,
                             const char *comp_dir);
@@ -2007,7 +2134,7 @@ dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2)
 static hashval_t
 line_header_hash (const struct line_header *ofs)
 {
-  return ofs->offset.sect_off ^ ofs->offset_in_dwz;
+  return to_underlying (ofs->sect_off) ^ ofs->offset_in_dwz;
 }
 
 /* Hash function for htab_create_alloc_ex for line_header_hash.  */
@@ -2028,7 +2155,7 @@ line_header_eq_voidp (const void *item_lhs, const void *item_rhs)
   const struct line_header *ofs_lhs = (const struct line_header *) item_lhs;
   const struct line_header *ofs_rhs = (const struct line_header *) item_rhs;
 
-  return (ofs_lhs->offset.sect_off == ofs_rhs->offset.sect_off
+  return (ofs_lhs->sect_off == ofs_rhs->sect_off
          && ofs_lhs->offset_in_dwz == ofs_rhs->offset_in_dwz);
 }
 
@@ -2051,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
@@ -2087,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
@@ -2104,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
@@ -2216,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;
 
@@ -2312,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,
@@ -2552,18 +2713,15 @@ dwarf2_get_dwz_file (void)
   buildid_len = (size_t) buildid_len_arg;
 
   filename = (const char *) data;
+
+  std::string abs_storage;
   if (!IS_ABSOLUTE_PATH (filename))
     {
-      char *abs = gdb_realpath (objfile_name (dwarf2_per_objfile->objfile));
-      char *rel;
-
-      make_cleanup (xfree, abs);
-      abs = ldirname (abs);
-      make_cleanup (xfree, abs);
+      gdb::unique_xmalloc_ptr<char> abs
+       = gdb_realpath (objfile_name (dwarf2_per_objfile->objfile));
 
-      rel = concat (abs, SLASH_STRING, filename, (char *) NULL);
-      make_cleanup (xfree, rel);
-      filename = rel;
+      abs_storage = ldirname (abs.get ()) + SLASH_STRING + filename;
+      filename = abs_storage.c_str ();
     }
 
   /* First try the file name given in the section.  If that doesn't
@@ -2651,7 +2809,7 @@ hash_stmt_list_entry (const struct stmt_list_hash *stmt_list_hash)
 
   if (stmt_list_hash->dwo_unit != NULL)
     v += (uintptr_t) stmt_list_hash->dwo_unit->dwo_file;
-  v += stmt_list_hash->line_offset.sect_off;
+  v += to_underlying (stmt_list_hash->line_sect_off);
   return v;
 }
 
@@ -2667,7 +2825,7 @@ eq_stmt_list_entry (const struct stmt_list_hash *lhs,
       && lhs->dwo_unit->dwo_file != rhs->dwo_unit->dwo_file)
     return 0;
 
-  return lhs->line_offset.sect_off == rhs->line_offset.sect_off;
+  return lhs->line_sect_off == rhs->line_sect_off;
 }
 
 /* Hash function for a quick_file_names.  */
@@ -2793,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);
@@ -2854,17 +3012,17 @@ create_cus_from_index_list (struct objfile *objfile,
 
   for (i = 0; i < n_elements; i += 2)
     {
-      struct dwarf2_per_cu_data *the_cu;
-      ULONGEST offset, length;
-
       gdb_static_assert (sizeof (ULONGEST) >= 8);
-      offset = extract_unsigned_integer (cu_list, 8, BFD_ENDIAN_LITTLE);
-      length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE);
+
+      sect_offset sect_off
+       = (sect_offset) extract_unsigned_integer (cu_list, 8, BFD_ENDIAN_LITTLE);
+      ULONGEST length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE);
       cu_list += 2 * 8;
 
-      the_cu = OBSTACK_ZALLOC (&objfile->objfile_obstack,
-                              struct dwarf2_per_cu_data);
-      the_cu->offset.sect_off = offset;
+      dwarf2_per_cu_data *the_cu
+       = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+                         struct dwarf2_per_cu_data);
+      the_cu->sect_off = sect_off;
       the_cu->length = length;
       the_cu->objfile = objfile;
       the_cu->section = section;
@@ -2923,23 +3081,26 @@ create_signatured_type_table_from_index (struct objfile *objfile,
   for (i = 0; i < elements; i += 3)
     {
       struct signatured_type *sig_type;
-      ULONGEST offset, type_offset_in_tu, signature;
+      ULONGEST signature;
       void **slot;
+      cu_offset type_offset_in_tu;
 
       gdb_static_assert (sizeof (ULONGEST) >= 8);
-      offset = extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE);
-      type_offset_in_tu = extract_unsigned_integer (bytes + 8, 8,
-                                                   BFD_ENDIAN_LITTLE);
+      sect_offset sect_off
+       = (sect_offset) extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE);
+      type_offset_in_tu
+       = (cu_offset) extract_unsigned_integer (bytes + 8, 8,
+                                               BFD_ENDIAN_LITTLE);
       signature = extract_unsigned_integer (bytes + 16, 8, BFD_ENDIAN_LITTLE);
       bytes += 3 * 8;
 
       sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
                                 struct signatured_type);
       sig_type->signature = signature;
-      sig_type->type_offset_in_tu.cu_off = type_offset_in_tu;
+      sig_type->type_offset_in_tu = type_offset_in_tu;
       sig_type->per_cu.is_debug_types = 1;
       sig_type->per_cu.section = section;
-      sig_type->per_cu.offset.sect_off = offset;
+      sig_type->per_cu.sect_off = sect_off;
       sig_type->per_cu.objfile = objfile;
       sig_type->per_cu.v.quick
        = OBSTACK_ZALLOC (&objfile->objfile_obstack,
@@ -2962,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;
@@ -3009,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
@@ -3329,13 +3487,10 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
   struct dwarf2_per_cu_data *this_cu = cu->per_cu;  
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct dwarf2_per_cu_data *lh_cu;
-  struct line_header *lh;
   struct attribute *attr;
   int i;
-  const char *name, *comp_dir;
   void **slot;
   struct quick_file_names *qfn;
-  unsigned int line_offset;
 
   gdb_assert (! this_cu->is_debug_types);
 
@@ -3348,21 +3503,22 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
     }
 
   lh_cu = this_cu;
-  lh = NULL;
   slot = NULL;
-  line_offset = 0;
+
+  line_header_up lh;
+  sect_offset line_offset {};
 
   attr = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, cu);
   if (attr)
     {
       struct quick_file_names find_entry;
 
-      line_offset = DW_UNSND (attr);
+      line_offset = (sect_offset) DW_UNSND (attr);
 
       /* We may have already read in this line header (TU line header sharing).
         If we have we're done.  */
       find_entry.hash.dwo_unit = cu->dwo_unit;
-      find_entry.hash.line_offset.sect_off = line_offset;
+      find_entry.hash.line_sect_off = line_offset;
       slot = htab_find_slot (dwarf2_per_objfile->quick_file_names_table,
                             &find_entry, INSERT);
       if (*slot != NULL)
@@ -3381,21 +3537,19 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
 
   qfn = XOBNEW (&objfile->objfile_obstack, struct quick_file_names);
   qfn->hash.dwo_unit = cu->dwo_unit;
-  qfn->hash.line_offset.sect_off = line_offset;
+  qfn->hash.line_sect_off = line_offset;
   gdb_assert (slot != NULL);
   *slot = qfn;
 
-  find_file_and_directory (comp_unit_die, cu, &name, &comp_dir);
+  file_and_directory fnd = find_file_and_directory (comp_unit_die, cu);
 
-  qfn->num_file_names = lh->num_file_names;
+  qfn->num_file_names = lh->file_names.size ();
   qfn->file_names =
-    XOBNEWVEC (&objfile->objfile_obstack, const char *, lh->num_file_names);
-  for (i = 0; i < lh->num_file_names; ++i)
-    qfn->file_names[i] = file_full_name (i + 1, lhcomp_dir);
+    XOBNEWVEC (&objfile->objfile_obstack, const char *, lh->file_names.size ());
+  for (i = 0; i < lh->file_names.size (); ++i)
+    qfn->file_names[i] = file_full_name (i + 1, lh.get (), fnd.comp_dir);
   qfn->real_names = NULL;
 
-  free_line_header (lh);
-
   lh_cu->v.quick->file_names = qfn;
 }
 
@@ -3435,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];
 }
@@ -3759,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.  */
@@ -4168,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);
-
-      if (per_cu->v.quick->compunit_symtab)
-       {
-         void **slot = htab_find_slot (visited.get (),
-                                       per_cu->v.quick->file_names,
-                                       INSERT);
+      dwarf2_per_objfile->filenames_cache.emplace ();
 
-         *slot = per_cu->v.quick->file_names;
-       }
-    }
+      htab_up visited (htab_create_alloc (10,
+                                         htab_hash_pointer, htab_eq_pointer,
+                                         NULL, xcalloc, xfree));
 
-  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
@@ -4331,15 +4494,15 @@ get_cu_length (const struct comp_unit_head *header)
   return header->initial_length_size + header->length;
 }
 
-/* Return TRUE if OFFSET is within CU_HEADER.  */
+/* Return TRUE if SECT_OFF is within CU_HEADER.  */
 
-static inline int
-offset_in_cu_p (const struct comp_unit_head *cu_header, sect_offset offset)
+static inline bool
+offset_in_cu_p (const comp_unit_head *cu_header, sect_offset sect_off)
 {
-  sect_offset bottom = { cu_header->offset.sect_off };
-  sect_offset top = { cu_header->offset.sect_off + get_cu_length (cu_header) };
+  sect_offset bottom = cu_header->sect_off;
+  sect_offset top = cu_header->sect_off + get_cu_length (cu_header);
 
-  return (offset.sect_off >= bottom.sect_off && offset.sect_off < top.sect_off);
+  return sect_off >= bottom && sect_off < top;
 }
 
 /* Find the base address of the compilation unit for range lists and
@@ -4433,8 +4596,9 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
       cu_header->addr_size = read_1_byte (abfd, info_ptr);
       info_ptr += 1;
     }
-  cu_header->abbrev_offset.sect_off = read_offset (abfd, info_ptr, cu_header,
-                                            &bytes_read);
+  cu_header->abbrev_sect_off = (sect_offset) read_offset (abfd, info_ptr,
+                                                         cu_header,
+                                                         &bytes_read);
   info_ptr += bytes_read;
   if (cu_header->version < 5)
     {
@@ -4456,8 +4620,8 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
 
       type_offset = read_offset (abfd, info_ptr, cu_header, &bytes_read);
       info_ptr += bytes_read;
-      cu_header->type_offset_in_tu.cu_off = type_offset;
-      if (cu_header->type_offset_in_tu.cu_off != type_offset)
+      cu_header->type_cu_offset_in_tu = (cu_offset) type_offset;
+      if (to_underlying (cu_header->type_cu_offset_in_tu) != type_offset)
        error (_("Dwarf Error: Too big type_offset in compilation unit "
               "header (is %s) [in module %s]"), plongest (type_offset),
               filename);
@@ -4498,20 +4662,21 @@ error_check_comp_unit_head (struct comp_unit_head *header,
           "(is %d, should be 2, 3, 4 or 5) [in module %s]"), header->version,
           filename);
 
-  if (header->abbrev_offset.sect_off
+  if (to_underlying (header->abbrev_sect_off)
       >= dwarf2_section_size (dwarf2_per_objfile->objfile, abbrev_section))
-    error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header "
-          "(offset 0x%lx + 6) [in module %s]"),
-          (long) header->abbrev_offset.sect_off, (long) header->offset.sect_off,
+    error (_("Dwarf Error: bad offset (0x%x) in compilation unit header "
+          "(offset 0x%x + 6) [in module %s]"),
+          to_underlying (header->abbrev_sect_off),
+          to_underlying (header->sect_off),
           filename);
 
-  /* Cast to unsigned long to use 64-bit arithmetic when possible to
+  /* Cast to ULONGEST to use 64-bit arithmetic when possible to
      avoid potential 32-bit overflow.  */
-  if (((unsigned long) header->offset.sect_off + get_cu_length (header))
+  if (((ULONGEST) header->sect_off + get_cu_length (header))
       > section->size)
-    error (_("Dwarf Error: bad length (0x%lx) in compilation unit header "
-          "(offset 0x%lx + 0) [in module %s]"),
-          (long) header->length, (long) header->offset.sect_off,
+    error (_("Dwarf Error: bad length (0x%x) in compilation unit header "
+          "(offset 0x%x + 0) [in module %s]"),
+          header->length, to_underlying (header->sect_off),
           filename);
 }
 
@@ -4529,11 +4694,11 @@ read_and_check_comp_unit_head (struct comp_unit_head *header,
   const gdb_byte *beg_of_comp_unit = info_ptr;
   bfd *abfd = get_section_bfd_owner (section);
 
-  header->offset.sect_off = beg_of_comp_unit - section->buffer;
+  header->sect_off = (sect_offset) (beg_of_comp_unit - section->buffer);
 
   info_ptr = read_comp_unit_head (header, info_ptr, section, section_kind);
 
-  header->first_die_offset.cu_off = info_ptr - beg_of_comp_unit;
+  header->first_die_cu_offset = (cu_offset) (info_ptr - beg_of_comp_unit);
 
   error_check_comp_unit_head (header, section, abbrev_section);
 
@@ -4544,16 +4709,15 @@ read_and_check_comp_unit_head (struct comp_unit_head *header,
 
 static sect_offset
 read_abbrev_offset (struct dwarf2_section_info *section,
-                   sect_offset offset)
+                   sect_offset sect_off)
 {
   bfd *abfd = get_section_bfd_owner (section);
   const gdb_byte *info_ptr;
   unsigned int initial_length_size, offset_size;
-  sect_offset abbrev_offset;
   uint16_t version;
 
   dwarf2_read_section (dwarf2_per_objfile->objfile, section);
-  info_ptr = section->buffer + offset.sect_off;
+  info_ptr = section->buffer + to_underlying (sect_off);
   read_initial_length (abfd, info_ptr, &initial_length_size);
   offset_size = initial_length_size == 4 ? 4 : 8;
   info_ptr += initial_length_size;
@@ -4566,8 +4730,7 @@ read_abbrev_offset (struct dwarf2_section_info *section,
       info_ptr += 2;
     }
 
-  abbrev_offset.sect_off = read_offset_1 (abfd, info_ptr, offset_size);
-  return abbrev_offset;
+  return (sect_offset) read_offset_1 (abfd, info_ptr, offset_size);
 }
 
 /* Allocate a new partial symtab for file named NAME and mark this new
@@ -4616,19 +4779,17 @@ dwarf2_build_include_psymtabs (struct dwarf2_cu *cu,
                               struct die_info *die,
                               struct partial_symtab *pst)
 {
-  struct line_header *lh = NULL;
+  line_header_up lh;
   struct attribute *attr;
 
   attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
   if (attr)
-    lh = dwarf_decode_line_header (DW_UNSND (attr), cu);
+    lh = dwarf_decode_line_header ((sect_offset) DW_UNSND (attr), cu);
   if (lh == NULL)
     return;  /* No linetable, so no includes.  */
 
   /* NOTE: pst->dirname is DW_AT_comp_dir (if present).  */
-  dwarf_decode_lines (lh, pst->dirname, cu, pst, pst->textlow, 1);
-
-  free_line_header (lh);
+  dwarf_decode_lines (lh.get (), pst->dirname, cu, pst, pst->textlow, 1);
 }
 
 static hashval_t
@@ -4718,7 +4879,6 @@ create_debug_type_hash_table (struct dwo_file *dwo_file,
   end_ptr = info_ptr + section->size;
   while (info_ptr < end_ptr)
     {
-      sect_offset offset;
       struct signatured_type *sig_type;
       struct dwo_unit *dwo_tu;
       void **slot;
@@ -4726,11 +4886,11 @@ create_debug_type_hash_table (struct dwo_file *dwo_file,
       struct comp_unit_head header;
       unsigned int length;
 
-      offset.sect_off = ptr - section->buffer;
+      sect_offset sect_off = (sect_offset) (ptr - section->buffer);
 
       /* Initialize it due to a false compiler warning.  */
       header.signature = -1;
-      header.type_offset_in_tu.cu_off = -1;
+      header.type_cu_offset_in_tu = (cu_offset) -1;
 
       /* We need to read the type's signature in order to build the hash
         table, but we don't need anything else just yet.  */
@@ -4764,9 +4924,9 @@ create_debug_type_hash_table (struct dwo_file *dwo_file,
                                   struct dwo_unit);
          dwo_tu->dwo_file = dwo_file;
          dwo_tu->signature = header.signature;
-         dwo_tu->type_offset_in_tu = header.type_offset_in_tu;
+         dwo_tu->type_offset_in_tu = header.type_cu_offset_in_tu;
          dwo_tu->section = section;
-         dwo_tu->offset = offset;
+         dwo_tu->sect_off = sect_off;
          dwo_tu->length = length;
        }
       else
@@ -4777,11 +4937,11 @@ create_debug_type_hash_table (struct dwo_file *dwo_file,
          sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
                                     struct signatured_type);
          sig_type->signature = header.signature;
-         sig_type->type_offset_in_tu = header.type_offset_in_tu;
+         sig_type->type_offset_in_tu = header.type_cu_offset_in_tu;
          sig_type->per_cu.objfile = objfile;
          sig_type->per_cu.is_debug_types = 1;
          sig_type->per_cu.section = section;
-         sig_type->per_cu.offset = offset;
+         sig_type->per_cu.sect_off = sect_off;
          sig_type->per_cu.length = length;
        }
 
@@ -4791,34 +4951,34 @@ create_debug_type_hash_table (struct dwo_file *dwo_file,
       gdb_assert (slot != NULL);
       if (*slot != NULL)
        {
-         sect_offset dup_offset;
+         sect_offset dup_sect_off;
 
          if (dwo_file)
            {
              const struct dwo_unit *dup_tu
                = (const struct dwo_unit *) *slot;
 
-             dup_offset = dup_tu->offset;
+             dup_sect_off = dup_tu->sect_off;
            }
          else
            {
              const struct signatured_type *dup_tu
                = (const struct signatured_type *) *slot;
 
-             dup_offset = dup_tu->per_cu.offset;
+             dup_sect_off = dup_tu->per_cu.sect_off;
            }
 
          complaint (&symfile_complaints,
                     _("debug type entry at offset 0x%x is duplicate to"
                       " the entry at offset 0x%x, signature %s"),
-                    offset.sect_off, dup_offset.sect_off,
+                    to_underlying (sect_off), to_underlying (dup_sect_off),
                     hex_string (header.signature));
        }
       *slot = dwo_file ? (void *) dwo_tu : (void *) sig_type;
 
       if (dwarf_read_debug > 1)
        fprintf_unfiltered (gdb_stdlog, "  offset 0x%x, signature %s\n",
-                           offset.sect_off,
+                           to_underlying (sect_off),
                            hex_string (header.signature));
 
       info_ptr += length;
@@ -4955,12 +5115,12 @@ fill_in_sig_entry_from_dwo_entry (struct objfile *objfile,
   else
       gdb_assert (sig_entry->per_cu.v.psymtab == NULL);
   gdb_assert (sig_entry->signature == dwo_entry->signature);
-  gdb_assert (sig_entry->type_offset_in_section.sect_off == 0);
+  gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0);
   gdb_assert (sig_entry->type_unit_group == NULL);
   gdb_assert (sig_entry->dwo_unit == NULL);
 
   sig_entry->per_cu.section = dwo_entry->section;
-  sig_entry->per_cu.offset = dwo_entry->offset;
+  sig_entry->per_cu.sect_off = dwo_entry->sect_off;
   sig_entry->per_cu.length = dwo_entry->length;
   sig_entry->per_cu.reading_dwo_directly = 1;
   sig_entry->per_cu.objfile = objfile;
@@ -5239,7 +5399,8 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data *this_cu,
   section = dwo_unit->section;
   dwarf2_read_section (objfile, section);
   abfd = get_section_bfd_owner (section);
-  begin_info_ptr = info_ptr = section->buffer + dwo_unit->offset.sect_off;
+  begin_info_ptr = info_ptr = (section->buffer
+                              + to_underlying (dwo_unit->sect_off));
   dwo_abbrev_section = &dwo_unit->dwo_file->sections.abbrev;
   init_cu_die_reader (result_reader, cu, section, dwo_unit->dwo_file);
 
@@ -5257,26 +5418,26 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data *this_cu,
                   " TU at offset 0x%x [in module %s]"),
                 hex_string (sig_type->signature),
                 hex_string (cu->header.signature),
-                dwo_unit->offset.sect_off,
+                to_underlying (dwo_unit->sect_off),
                 bfd_get_filename (abfd));
        }
-      gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
+      gdb_assert (dwo_unit->sect_off == cu->header.sect_off);
       /* For DWOs coming from DWP files, we don't know the CU length
         nor the type's offset in the TU until now.  */
       dwo_unit->length = get_cu_length (&cu->header);
-      dwo_unit->type_offset_in_tu = cu->header.type_offset_in_tu;
+      dwo_unit->type_offset_in_tu = cu->header.type_cu_offset_in_tu;
 
       /* Establish the type offset that can be used to lookup the type.
         For DWO files, we don't know it until now.  */
-      sig_type->type_offset_in_section.sect_off =
-       dwo_unit->offset.sect_off + dwo_unit->type_offset_in_tu.cu_off;
+      sig_type->type_offset_in_section
+       = dwo_unit->sect_off + to_underlying (dwo_unit->type_offset_in_tu);
     }
   else
     {
       info_ptr = read_and_check_comp_unit_head (&cu->header, section,
                                                dwo_abbrev_section,
                                                info_ptr, rcuh_kind::COMPILE);
-      gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
+      gdb_assert (dwo_unit->sect_off == cu->header.sect_off);
       /* For DWOs coming from DWP files, we don't know the CU length
         until now.  */
       dwo_unit->length = get_cu_length (&cu->header);
@@ -5536,7 +5697,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
   if (dwarf_die_debug)
     fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset 0x%x\n",
                        this_cu->is_debug_types ? "type" : "comp",
-                       this_cu->offset.sect_off);
+                       to_underlying (this_cu->sect_off));
 
   if (use_existing_cu)
     gdb_assert (keep);
@@ -5558,7 +5719,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
   /* This is cheap if the section is already read in.  */
   dwarf2_read_section (objfile, section);
 
-  begin_info_ptr = info_ptr = section->buffer + this_cu->offset.sect_off;
+  begin_info_ptr = info_ptr = section->buffer + to_underlying (this_cu->sect_off);
 
   abbrev_section = get_abbrev_section_for_cu (this_cu);
 
@@ -5585,10 +5746,10 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
     }
 
   /* Get the header.  */
-  if (cu->header.first_die_offset.cu_off != 0 && ! rereading_dwo_cu)
+  if (to_underlying (cu->header.first_die_cu_offset) != 0 && !rereading_dwo_cu)
     {
       /* We already have the header, there's no need to read it in again.  */
-      info_ptr += cu->header.first_die_offset.cu_off;
+      info_ptr += to_underlying (cu->header.first_die_cu_offset);
     }
   else
     {
@@ -5602,17 +5763,17 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
             we can go from a pointer to one to a pointer to the other.  */
          sig_type = (struct signatured_type *) this_cu;
          gdb_assert (sig_type->signature == cu->header.signature);
-         gdb_assert (sig_type->type_offset_in_tu.cu_off
-                     == cu->header.type_offset_in_tu.cu_off);
-         gdb_assert (this_cu->offset.sect_off == cu->header.offset.sect_off);
+         gdb_assert (sig_type->type_offset_in_tu
+                     == cu->header.type_cu_offset_in_tu);
+         gdb_assert (this_cu->sect_off == cu->header.sect_off);
 
          /* LENGTH has not been set yet for type units if we're
             using .gdb_index.  */
          this_cu->length = get_cu_length (&cu->header);
 
          /* Establish the type offset that can be used to lookup the type.  */
-         sig_type->type_offset_in_section.sect_off =
-           this_cu->offset.sect_off + sig_type->type_offset_in_tu.cu_off;
+         sig_type->type_offset_in_section =
+           this_cu->sect_off + to_underlying (sig_type->type_offset_in_tu);
 
          this_cu->dwarf_version = cu->header.version;
        }
@@ -5623,7 +5784,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
                                                    info_ptr,
                                                    rcuh_kind::COMPILE);
 
-         gdb_assert (this_cu->offset.sect_off == cu->header.offset.sect_off);
+         gdb_assert (this_cu->sect_off == cu->header.sect_off);
          gdb_assert (this_cu->length == get_cu_length (&cu->header));
          this_cu->dwarf_version = cu->header.version;
        }
@@ -5645,8 +5806,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
   if (abbrev_table != NULL)
     {
       gdb_assert (cu->abbrev_table == NULL);
-      gdb_assert (cu->header.abbrev_offset.sect_off
-                 == abbrev_table->offset.sect_off);
+      gdb_assert (cu->header.abbrev_sect_off == abbrev_table->sect_off);
       cu->abbrev_table = abbrev_table;
     }
   else if (cu->abbrev_table == NULL)
@@ -5679,7 +5839,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
          complaint (&symfile_complaints,
                     _("compilation unit with DW_AT_GNU_dwo_name"
                       " has children (offset 0x%x) [in module %s]"),
-                    this_cu->offset.sect_off, bfd_get_filename (abfd));
+                    to_underlying (this_cu->sect_off), bfd_get_filename (abfd));
        }
       dwo_unit = lookup_dwo_unit (this_cu, comp_unit_die);
       if (dwo_unit != NULL)
@@ -5769,7 +5929,7 @@ init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
   if (dwarf_die_debug)
     fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset 0x%x\n",
                        this_cu->is_debug_types ? "type" : "comp",
-                       this_cu->offset.sect_off);
+                       to_underlying (this_cu->sect_off));
 
   gdb_assert (this_cu->cu == NULL);
 
@@ -5784,7 +5944,7 @@ init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
 
   cleanups = make_cleanup (free_stack_comp_unit, &cu);
 
-  begin_info_ptr = info_ptr = section->buffer + this_cu->offset.sect_off;
+  begin_info_ptr = info_ptr = section->buffer + to_underlying (this_cu->sect_off);
   info_ptr = read_and_check_comp_unit_head (&cu.header, section,
                                            abbrev_section, info_ptr,
                                            (this_cu->is_debug_types
@@ -5897,7 +6057,7 @@ create_type_unit_group (struct dwarf2_cu *cu, sect_offset line_offset_struct)
     }
   else
     {
-      unsigned int line_offset = line_offset_struct.sect_off;
+      unsigned int line_offset = to_underlying (line_offset_struct);
       struct partial_symtab *pst;
       char *name;
 
@@ -5915,7 +6075,7 @@ create_type_unit_group (struct dwarf2_cu *cu, sect_offset line_offset_struct)
     }
 
   tu_group->hash.dwo_unit = cu->dwo_unit;
-  tu_group->hash.line_offset = line_offset_struct;
+  tu_group->hash.line_sect_off = line_offset_struct;
 
   return tu_group;
 }
@@ -5959,7 +6119,7 @@ get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list)
     }
 
   type_unit_group_for_lookup.hash.dwo_unit = cu->dwo_unit;
-  type_unit_group_for_lookup.hash.line_offset.sect_off = line_offset;
+  type_unit_group_for_lookup.hash.line_sect_off = (sect_offset) line_offset;
   slot = htab_find_slot (dwarf2_per_objfile->type_unit_groups,
                         &type_unit_group_for_lookup, INSERT);
   if (*slot != NULL)
@@ -5969,9 +6129,7 @@ get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list)
     }
   else
     {
-      sect_offset line_offset_struct;
-
-      line_offset_struct.sect_off = line_offset;
+      sect_offset line_offset_struct = (sect_offset) line_offset;
       tu_group = create_type_unit_group (cu, line_offset_struct);
       *slot = tu_group;
       ++tu_stats->nr_symtabs;
@@ -6146,7 +6304,7 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
                          "Psymtab for %s unit @0x%x: %s - %s"
                          ", %d global, %d static syms\n",
                          per_cu->is_debug_types ? "type" : "comp",
-                         per_cu->offset.sect_off,
+                         to_underlying (per_cu->sect_off),
                          paddress (gdbarch, pst->textlow),
                          paddress (gdbarch, pst->texthigh),
                          pst->n_global_syms, pst->n_static_syms);
@@ -6161,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
@@ -6171,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 ();
@@ -6244,8 +6405,8 @@ sort_tu_by_abbrev_offset (const void *ap, const void *bp)
     = (const struct tu_abbrev_offset * const*) ap;
   const struct tu_abbrev_offset * const *b
     = (const struct tu_abbrev_offset * const*) bp;
-  unsigned int aoff = (*a)->abbrev_offset.sect_off;
-  unsigned int boff = (*b)->abbrev_offset.sect_off;
+  sect_offset aoff = (*a)->abbrev_offset;
+  sect_offset boff = (*b)->abbrev_offset;
 
   return (aoff > boff) - (aoff < boff);
 }
@@ -6317,13 +6478,13 @@ build_type_psymtabs_1 (void)
       sorted_by_abbrev[i].sig_type = sig_type;
       sorted_by_abbrev[i].abbrev_offset =
        read_abbrev_offset (sig_type->per_cu.section,
-                           sig_type->per_cu.offset);
+                           sig_type->per_cu.sect_off);
     }
   cleanups = make_cleanup (xfree, sorted_by_abbrev);
   qsort (sorted_by_abbrev, dwarf2_per_objfile->n_type_units,
         sizeof (struct tu_abbrev_offset), sort_tu_by_abbrev_offset);
 
-  abbrev_offset.sect_off = ~(unsigned) 0;
+  abbrev_offset = (sect_offset) ~(unsigned) 0;
   abbrev_table = NULL;
   make_cleanup (abbrev_table_free_cleanup, &abbrev_table);
 
@@ -6333,7 +6494,7 @@ build_type_psymtabs_1 (void)
 
       /* Switch to the next abbrev table if necessary.  */
       if (abbrev_table == NULL
-         || tu->abbrev_offset.sect_off != abbrev_offset.sect_off)
+         || tu->abbrev_offset != abbrev_offset)
        {
          if (abbrev_table != NULL)
            {
@@ -6537,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)
@@ -6560,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);
 
@@ -6631,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,
@@ -6650,21 +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 offset;
 
-      offset.sect_off = info_ptr - section->buffer;
+      sect_offset sect_off = (sect_offset) (info_ptr - section->buffer);
 
-      /* Read just enough information to find out where the next
-        compilation unit is.  */
-      length = read_initial_length (abfd, info_ptr, &initial_length_size);
+      comp_unit_head cu_header;
+      read_and_check_comp_unit_head (&cu_header, section, abbrev_section,
+                                    info_ptr, rcuh_kind::COMPILE);
 
       /* Save the compilation unit for later lookup.  */
-      this_cu = XOBNEW (&objfile->objfile_obstack, struct dwarf2_per_cu_data);
-      memset (this_cu, 0, sizeof (*this_cu));
-      this_cu->offset = offset;
-      this_cu->length = length + initial_length_size;
+      if (cu_header.unit_type != DW_UT_type)
+       {
+         this_cu = XOBNEW (&objfile->objfile_obstack,
+                           struct dwarf2_per_cu_data);
+         memset (this_cu, 0, sizeof (*this_cu));
+       }
+      else
+       {
+         auto sig_type = XOBNEW (&objfile->objfile_obstack,
+                                 struct signatured_type);
+         memset (sig_type, 0, sizeof (*sig_type));
+         sig_type->signature = cu_header.signature;
+         sig_type->type_offset_in_tu = cu_header.type_cu_offset_in_tu;
+         this_cu = &sig_type->per_cu;
+       }
+      this_cu->is_debug_types = (cu_header.unit_type == DW_UT_type);
+      this_cu->sect_off = sect_off;
+      this_cu->length = cu_header.length + cu_header.initial_length_size;
       this_cu->is_dwz = is_dwz;
       this_cu->objfile = objfile;
       this_cu->section = section;
@@ -6697,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);
 
@@ -6799,7 +6972,7 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
                           objfile_name (cu->objfile));
                  }
 
-               per_cu = dwarf2_find_containing_comp_unit (pdi->d.offset,
+               per_cu = dwarf2_find_containing_comp_unit (pdi->d.sect_off,
                                                           pdi->is_dwz,
                                                           cu->objfile);
 
@@ -6912,7 +7085,7 @@ partial_die_parent_scope (struct partial_die_info *pdi,
         ignoring them.  */
       complaint (&symfile_complaints,
                 _("unhandled containing DIE tag %d for DIE at %d"),
-                parent->tag, pdi->offset.sect_off);
+                parent->tag, to_underlying (pdi->sect_off));
       parent->scope = grandparent_scope;
     }
 
@@ -6946,7 +7119,7 @@ partial_die_full_name (struct partial_die_info *pdi,
          /* DW_FORM_ref_addr is using section offset.  */
          attr.name = (enum dwarf_attribute) 0;
          attr.form = DW_FORM_ref_addr;
-         attr.u.unsnd = pdi->offset.sect_off;
+         attr.u.unsnd = to_underlying (pdi->sect_off);
          die = follow_die_ref (NULL, &attr, &ref_cu);
 
          return xstrdup (dwarf2_full_name (NULL, die, ref_cu));
@@ -7306,7 +7479,7 @@ peek_die_abbrev (const gdb_byte *info_ptr, unsigned int *bytes_read,
       error (_("Dwarf Error: Could not find abbrev number %d in %s"
               " at offset 0x%x [in module %s]"),
             abbrev_number, cu->per_cu->is_debug_types ? "TU" : "CU",
-            cu->header.offset.sect_off, bfd_get_filename (abfd));
+            to_underlying (cu->header.sect_off), bfd_get_filename (abfd));
     }
 
   return abbrev;
@@ -7362,8 +7535,8 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
                       _("ignoring absolute DW_AT_sibling"));
          else
            {
-             unsigned int off = dwarf2_get_ref_die_offset (&attr).sect_off;
-             const gdb_byte *sibling_ptr = buffer + off;
+             sect_offset off = dwarf2_get_ref_die_offset (&attr);
+             const gdb_byte *sibling_ptr = buffer + to_underlying (off);
 
              if (sibling_ptr < info_ptr)
                complaint (&symfile_complaints,
@@ -7651,14 +7824,15 @@ process_queue (void)
 
              sprintf (buf, "TU %s at offset 0x%x",
                       hex_string (sig_type->signature),
-                      per_cu->offset.sect_off);
+                      to_underlying (per_cu->sect_off));
              /* There can be 100s of TUs.
                 Only print them in verbose mode.  */
              debug_print_threshold = 2;
            }
          else
            {
-             sprintf (buf, "CU at offset 0x%x", per_cu->offset.sect_off);
+             sprintf (buf, "CU at offset 0x%x",
+                      to_underlying (per_cu->sect_off));
              debug_print_threshold = 1;
            }
 
@@ -7768,7 +7942,7 @@ die_hash (const void *item)
 {
   const struct die_info *die = (const struct die_info *) item;
 
-  return die->offset.sect_off;
+  return to_underlying (die->sect_off);
 }
 
 /* Trivial comparison function for die_info structures: two DIEs
@@ -7780,7 +7954,7 @@ die_eq (const void *item_lhs, const void *item_rhs)
   const struct die_info *die_lhs = (const struct die_info *) item_lhs;
   const struct die_info *die_rhs = (const struct die_info *) item_rhs;
 
-  return die_lhs->offset.sect_off == die_rhs->offset.sect_off;
+  return die_lhs->sect_off == die_rhs->sect_off;
 }
 
 /* die_reader_func for load_full_comp_unit.
@@ -7863,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
@@ -7874,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;
@@ -7882,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;
+           }
+       }
     }
 }
 
@@ -8305,13 +8522,10 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
   attr = dwarf2_attr (die, DW_AT_import, cu);
   if (attr != NULL)
     {
-      struct dwarf2_per_cu_data *per_cu;
-      sect_offset offset;
-      int is_dwz;
-
-      offset = dwarf2_get_ref_die_offset (attr);
-      is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz);
-      per_cu = dwarf2_find_containing_comp_unit (offset, is_dwz, cu->objfile);
+      sect_offset sect_off = dwarf2_get_ref_die_offset (attr);
+      bool is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz);
+      dwarf2_per_cu_data *per_cu
+       = dwarf2_find_containing_comp_unit (sect_off, is_dwz, cu->objfile);
 
       /* If necessary, add it to the queue and load its DIEs.  */
       if (maybe_queue_comp_unit (cu, per_cu, cu->language))
@@ -8322,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)
     {
@@ -8388,6 +8618,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
     case DW_TAG_pointer_type:
     case DW_TAG_ptr_to_member_type:
     case DW_TAG_reference_type:
+    case DW_TAG_rvalue_reference_type:
     case DW_TAG_string_type:
       break;
 
@@ -8433,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.  */
@@ -8498,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++),
@@ -8537,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;
     }
@@ -8782,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.  */
@@ -8844,7 +9100,7 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
          complaint (&symfile_complaints,
                     _("Computed physname <%s> does not match demangled <%s> "
                       "(from linkage <%s>) - DIE at 0x%x [in module %s]"),
-                    physname, canon, mangled, die->offset.sect_off,
+                    physname, canon, mangled, to_underlying (die->sect_off),
                     objfile_name (objfile));
 
          /* Prefer DW_AT_linkage_name (in the CANON form) - when it
@@ -8908,16 +9164,16 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
        {
          complaint (&symfile_complaints,
                     _("DIE at 0x%x has too many recursively imported "
-                      "declarations"), d->offset.sect_off);
+                      "declarations"), to_underlying (d->sect_off));
          return 0;
        }
 
       if (attr != NULL)
        {
          struct type *type;
-         sect_offset offset = dwarf2_get_ref_die_offset (attr);
+         sect_offset sect_off = dwarf2_get_ref_die_offset (attr);
 
-         type = get_die_type_at_offset (offset, cu->per_cu);
+         type = get_die_type_at_offset (sect_off, cu->per_cu);
          if (type != NULL && TYPE_CODE (type) == TYPE_CODE_NAMESPACE)
            {
              /* This declaration is a global namespace alias.  Add
@@ -8964,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)
@@ -9039,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))
@@ -9055,7 +9308,7 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
            complaint (&symfile_complaints,
                       _("child DW_TAG_imported_declaration expected "
                         "- DIE at 0x%x [in module %s]"),
-                      child_die->offset.sect_off, objfile_name (objfile));
+                      to_underlying (child_die->sect_off), objfile_name (objfile));
            continue;
          }
 
@@ -9076,11 +9329,11 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
            complaint (&symfile_complaints,
                       _("child DW_TAG_imported_declaration has unknown "
                         "imported name - DIE at 0x%x [in module %s]"),
-                      child_die->offset.sect_off, objfile_name (objfile));
+                      to_underlying (child_die->sect_off), objfile_name (objfile));
            continue;
          }
 
-       VEC_safe_push (const_char_ptr, excludes, imported_name);
+       excludes.push_back (imported_name);
 
        process_die (child_die, cu);
       }
@@ -9093,19 +9346,19 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
                       excludes,
                       0,
                       &objfile->objfile_obstack);
-
-  do_cleanups (cleanups);
 }
 
-/* Cleanup function for handle_DW_AT_stmt_list.  */
+/* ICC<14 does not output the required DW_AT_declaration on incomplete
+   types, but gives them a size of zero.  Starting with version 14,
+   ICC is compatible with GCC.  */
 
-static void
-free_cu_line_header (void *arg)
+static int
+producer_is_icc_lt_14 (struct dwarf2_cu *cu)
 {
-  struct dwarf2_cu *cu = (struct dwarf2_cu *) arg;
+  if (!cu->checked_producer)
+    check_producer (cu);
 
-  free_line_header (cu->line_header);
-  cu->line_header = NULL;
+  return cu->producer_is_icc_lt_14;
 }
 
 /* Check for possibly missing DW_AT_comp_dir with relative .debug_line
@@ -9121,37 +9374,38 @@ producer_is_gcc_lt_4_3 (struct dwarf2_cu *cu)
   return cu->producer_is_gcc_lt_4_3;
 }
 
-static void
-find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu,
-                        const char **name, const char **comp_dir)
+static file_and_directory
+find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu)
 {
+  file_and_directory res;
+
   /* Find the filename.  Do not use dwarf2_name here, since the filename
      is not a source language identifier.  */
-  *name = dwarf2_string_attr (die, DW_AT_name, cu);
-  *comp_dir = dwarf2_string_attr (die, DW_AT_comp_dir, cu);
+  res.name = dwarf2_string_attr (die, DW_AT_name, cu);
+  res.comp_dir = dwarf2_string_attr (die, DW_AT_comp_dir, cu);
 
-  if (*comp_dir == NULL
-      && producer_is_gcc_lt_4_3 (cu) && *name != NULL
-      && IS_ABSOLUTE_PATH (*name))
+  if (res.comp_dir == NULL
+      && producer_is_gcc_lt_4_3 (cu) && res.name != NULL
+      && IS_ABSOLUTE_PATH (res.name))
     {
-      char *d = ldirname (*name);
-
-      *comp_dir = d;
-      if (d != NULL)
-       make_cleanup (xfree, d);
+      res.comp_dir_storage = ldirname (res.name);
+      if (!res.comp_dir_storage.empty ())
+       res.comp_dir = res.comp_dir_storage.c_str ();
     }
-  if (*comp_dir != NULL)
+  if (res.comp_dir != NULL)
     {
       /* Irix 6.2 native cc prepends <machine>.: to the compilation
         directory, get rid of it.  */
-      const char *cp = strchr (*comp_dir, ':');
+      const char *cp = strchr (res.comp_dir, ':');
 
-      if (cp && cp != *comp_dir && cp[-1] == '.' && cp[1] == '/')
-       *comp_dir = cp + 1;
+      if (cp && cp != res.comp_dir && cp[-1] == '.' && cp[1] == '/')
+       res.comp_dir = cp + 1;
     }
 
-  if (*name == NULL)
-    *name = "<unknown>";
+  if (res.name == NULL)
+    res.name = "<unknown>";
+
+  return res;
 }
 
 /* Handle DW_AT_stmt_list for a compilation unit.
@@ -9165,7 +9419,6 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct attribute *attr;
-  unsigned int line_offset;
   struct line_header line_header_local;
   hashval_t line_header_local_hash;
   unsigned u;
@@ -9178,7 +9431,7 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
   if (attr == NULL)
     return;
 
-  line_offset = DW_UNSND (attr);
+  sect_offset line_offset = (sect_offset) DW_UNSND (attr);
 
   /* The line header hash table is only created if needed (it exists to
      prevent redundant reading of the line table for partial_units).
@@ -9198,7 +9451,7 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
                                dummy_obstack_deallocate);
     }
 
-  line_header_local.offset.sect_off = line_offset;
+  line_header_local.sect_off = line_offset;
   line_header_local.offset_in_dwz = cu->per_cu->is_dwz;
   line_header_local_hash = line_header_hash (&line_header_local);
   if (dwarf2_per_objfile->line_header_hash != NULL)
@@ -9220,10 +9473,13 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
 
   /* dwarf_decode_line_header does not yet provide sufficient information.
      We always have to call also dwarf_decode_lines for it.  */
-  cu->line_header = dwarf_decode_line_header (line_offset, cu);
-  if (cu->line_header == NULL)
+  line_header_up lh = dwarf_decode_line_header (line_offset, cu);
+  if (lh == NULL)
     return;
 
+  cu->line_header = lh.release ();
+  cu->line_header_die_owner = die;
+
   if (dwarf2_per_objfile->line_header_hash == NULL)
     slot = NULL;
   else
@@ -9238,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
     {
@@ -9247,11 +9504,11 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
         number information unit.  And if we're not using line_header_hash
         then this is what we want as well.  */
       gdb_assert (die->tag != DW_TAG_partial_unit);
-      make_cleanup (free_cu_line_header, cu);
     }
   decode_mapping = (die->tag != DW_TAG_partial_unit);
   dwarf_decode_lines (cu->line_header, comp_dir, cu, NULL, lowpc,
                      decode_mapping);
+
 }
 
 /* Process DW_TAG_compile_unit or DW_TAG_partial_unit.  */
@@ -9261,12 +9518,9 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
-  struct cleanup *back_to = make_cleanup (null_cleanup, 0);
   CORE_ADDR lowpc = ((CORE_ADDR) -1);
   CORE_ADDR highpc = ((CORE_ADDR) 0);
   struct attribute *attr;
-  const char *name = NULL;
-  const char *comp_dir = NULL;
   struct die_info *child_die;
   CORE_ADDR baseaddr;
 
@@ -9280,7 +9534,7 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
     lowpc = highpc;
   lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
 
-  find_file_and_directory (die, cu, &name, &comp_dir);
+  file_and_directory fnd = find_file_and_directory (die, cu);
 
   prepare_one_comp_unit (cu, die, cu->language);
 
@@ -9294,12 +9548,12 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
   if (cu->producer && strstr (cu->producer, "GNU Go ") != NULL)
     set_cu_language (DW_LANG_Go, cu);
 
-  dwarf2_start_symtab (cu, name, comp_dir, lowpc);
+  dwarf2_start_symtab (cu, fnd.name, fnd.comp_dir, lowpc);
 
   /* Decode line number information if present.  We do this before
      processing child DIEs, so that the line header table is available
      for DW_AT_decl_file.  */
-  handle_DW_AT_stmt_list (die, cu, comp_dir, lowpc);
+  handle_DW_AT_stmt_list (die, cu, fnd.comp_dir, lowpc);
 
   /* Process all dies in compilation unit.  */
   if (die->child != NULL)
@@ -9337,8 +9591,6 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
          dwarf_decode_macros (cu, macro_offset, 0);
        }
     }
-
-  do_cleanups (back_to);
 }
 
 /* TU version of handle_DW_AT_stmt_list for read_type_unit_scope.
@@ -9353,9 +9605,8 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
   struct dwarf2_per_cu_data *per_cu = cu->per_cu;
   struct type_unit_group *tu_group;
   int first_time;
-  struct line_header *lh;
   struct attribute *attr;
-  unsigned int i, line_offset;
+  unsigned int i;
   struct signatured_type *sig_type;
 
   gdb_assert (per_cu->is_debug_types);
@@ -9377,10 +9628,10 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
 
   /* We have to handle the case of both a missing DW_AT_stmt_list or bad
      debug info.  */
-  lh = NULL;
+  line_header_up lh;
   if (attr != NULL)
     {
-      line_offset = DW_UNSND (attr);
+      sect_offset line_offset = (sect_offset) DW_UNSND (attr);
       lh = dwarf_decode_line_header (line_offset, cu);
     }
   if (lh == NULL)
@@ -9395,8 +9646,8 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
       return;
     }
 
-  cu->line_header = lh;
-  make_cleanup (free_cu_line_header, cu);
+  cu->line_header = lh.release ();
+  cu->line_header_die_owner = die;
 
   if (first_time)
     {
@@ -9407,41 +9658,40 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
         process_full_type_unit still needs to know if this is the first
         time.  */
 
-      tu_group->num_symtabs = lh->num_file_names;
-      tu_group->symtabs = XNEWVEC (struct symtab *, lh->num_file_names);
+      tu_group->num_symtabs = cu->line_header->file_names.size ();
+      tu_group->symtabs = XNEWVEC (struct symtab *,
+                                  cu->line_header->file_names.size ());
 
-      for (i = 0; i < lh->num_file_names; ++i)
+      for (i = 0; i < cu->line_header->file_names.size (); ++i)
        {
-         const char *dir = NULL;
-         struct file_entry *fe = &lh->file_names[i];
+         file_entry &fe = cu->line_header->file_names[i];
 
-         if (fe->dir_index && lh->include_dirs != NULL)
-           dir = lh->include_dirs[fe->dir_index - 1];
-         dwarf2_start_subfile (fe->name, dir);
+         dwarf2_start_subfile (fe.name, fe.include_dir (cu->line_header));
 
          if (current_subfile->symtab == NULL)
            {
-             /* NOTE: start_subfile will recognize when it's been passed
-                a file it has already seen.  So we can't assume there's a
-                simple mapping from lh->file_names to subfiles, plus
-                lh->file_names may contain dups.  */
+             /* NOTE: start_subfile will recognize when it's been
+                passed a file it has already seen.  So we can't
+                assume there's a simple mapping from
+                cu->line_header->file_names to subfiles, plus
+                cu->line_header->file_names may contain dups.  */
              current_subfile->symtab
                = allocate_symtab (cust, current_subfile->name);
            }
 
-         fe->symtab = current_subfile->symtab;
-         tu_group->symtabs[i] = fe->symtab;
+         fe.symtab = current_subfile->symtab;
+         tu_group->symtabs[i] = fe.symtab;
        }
     }
   else
     {
       restart_symtab (tu_group->compunit_symtab, "", 0);
 
-      for (i = 0; i < lh->num_file_names; ++i)
+      for (i = 0; i < cu->line_header->file_names.size (); ++i)
        {
-         struct file_entry *fe = &lh->file_names[i];
+         file_entry &fe = cu->line_header->file_names[i];
 
-         fe->symtab = tu_group->symtabs[i];
+         fe.symtab = tu_group->symtabs[i];
        }
     }
 
@@ -9606,7 +9856,7 @@ create_dwo_cu_reader (const struct die_reader_specs *reader,
                      void *datap)
 {
   struct dwarf2_cu *cu = reader->cu;
-  sect_offset offset = cu->per_cu->offset;
+  sect_offset sect_off = cu->per_cu->sect_off;
   struct dwarf2_section_info *section = cu->per_cu->section;
   struct create_dwo_cu_data *data = (struct create_dwo_cu_data *) datap;
   struct dwo_file *dwo_file = data->dwo_file;
@@ -9619,87 +9869,92 @@ create_dwo_cu_reader (const struct die_reader_specs *reader,
       complaint (&symfile_complaints,
                 _("Dwarf Error: debug entry at offset 0x%x is missing"
                   " its dwo_id [in module %s]"),
-                offset.sect_off, dwo_file->dwo_name);
+                to_underlying (sect_off), dwo_file->dwo_name);
       return;
     }
 
   dwo_unit->dwo_file = dwo_file;
   dwo_unit->signature = DW_UNSND (attr);
   dwo_unit->section = section;
-  dwo_unit->offset = offset;
+  dwo_unit->sect_off = sect_off;
   dwo_unit->length = cu->per_cu->length;
 
   if (dwarf_read_debug)
     fprintf_unfiltered (gdb_stdlog, "  offset 0x%x, dwo_id %s\n",
-                       offset.sect_off, hex_string (dwo_unit->signature));
+                       to_underlying (sect_off),
+                       hex_string (dwo_unit->signature));
 }
 
-/* Create the dwo_unit for the lone CU in DWO_FILE.
+/* Create the dwo_units for the CUs in a DWO_FILE.
    Note: This function processes DWO files only, not DWP files.  */
 
-static struct dwo_unit *
-create_dwo_cu (struct dwo_file *dwo_file)
+static void
+create_cus_hash_table (struct dwo_file &dwo_file, dwarf2_section_info &section,
+                      htab_t &cus_htab)
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
-  struct dwarf2_section_info *section = &dwo_file->sections.info;
+  const 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.offset.sect_off = info_ptr - section->buffer;
-      per_cu.section = section;
+      per_cu.sect_off = sect_offset (info_ptr - section.buffer);
+      per_cu.section = &section;
+      create_dwo_cu_data.dwo_file = &dwo_file;
+
+      init_cutu_and_read_dies_no_follow (
+         &per_cu, &dwo_file, create_dwo_cu_reader, &create_dwo_cu_data);
+      info_ptr += per_cu.length;
 
-      init_cutu_and_read_dies_no_follow (&per_cu, dwo_file,
-                                        create_dwo_cu_reader,
-                                        &create_dwo_cu_data);
+      // If the unit could not be parsed, skip it.
+      if (create_dwo_cu_data.dwo_unit.dwo_file == NULL)
+       continue;
+
+      if (cus_htab == NULL)
+       cus_htab = allocate_dwo_unit_table (objfile);
 
-      if (create_dwo_cu_data.dwo_unit.dwo_file != NULL)
+      dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
+      *dwo_unit = create_dwo_cu_data.dwo_unit;
+      slot = htab_find_slot (cus_htab, dwo_unit, INSERT);
+      gdb_assert (slot != NULL);
+      if (*slot != NULL)
        {
-         /* If we've already found one, complain.  We only support one
-            because having more than one requires hacking the dwo_name of
-            each to match, which is highly unlikely to happen.  */
-         if (dwo_unit != NULL)
-           {
-             complaint (&symfile_complaints,
-                        _("Multiple CUs in DWO file %s [in module %s]"),
-                        dwo_file->dwo_name, objfile_name (objfile));
-             break;
-           }
+         const struct dwo_unit *dup_cu = (const struct dwo_unit *)*slot;
+         sect_offset dup_sect_off = dup_cu->sect_off;
 
-         dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
-         *dwo_unit = create_dwo_cu_data.dwo_unit;
+         complaint (&symfile_complaints,
+                    _("debug cu entry at offset 0x%x is duplicate to"
+                      " the entry at offset 0x%x, signature %s"),
+                    to_underlying (sect_off), to_underlying (dup_sect_off),
+                    hex_string (dwo_unit->signature));
        }
-
-      info_ptr += per_cu.length;
+      *slot = (void *)dwo_unit;
     }
-
-  return dwo_unit;
 }
 
 /* DWP file .debug_{cu,tu}_index section format:
@@ -10704,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);
@@ -10891,49 +11146,44 @@ open_and_init_dwp_file (void)
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct dwp_file *dwp_file;
-  char *dwp_name;
-  struct cleanup *cleanups = make_cleanup (null_cleanup, 0);
 
   /* Try to find first .dwp for the binary file before any symbolic links
      resolving.  */
 
   /* If the objfile is a debug file, find the name of the real binary
      file and get the name of dwp file from there.  */
+  std::string dwp_name;
   if (objfile->separate_debug_objfile_backlink != NULL)
     {
       struct objfile *backlink = objfile->separate_debug_objfile_backlink;
       const char *backlink_basename = lbasename (backlink->original_name);
-      char *debug_dirname = ldirname (objfile->original_name);
 
-      make_cleanup (xfree, debug_dirname);
-      dwp_name = xstrprintf ("%s%s%s.dwp", debug_dirname,
-                            SLASH_STRING, backlink_basename);
+      dwp_name = ldirname (objfile->original_name) + SLASH_STRING + backlink_basename;
     }
   else
-    dwp_name = xstrprintf ("%s.dwp", objfile->original_name);
-  make_cleanup (xfree, dwp_name);
+    dwp_name = objfile->original_name;
+
+  dwp_name += ".dwp";
 
-  gdb_bfd_ref_ptr dbfd (open_dwp_file (dwp_name));
+  gdb_bfd_ref_ptr dbfd (open_dwp_file (dwp_name.c_str ()));
   if (dbfd == NULL
       && strcmp (objfile->original_name, objfile_name (objfile)) != 0)
     {
       /* Try to find .dwp for the binary file after gdb_realpath resolving.  */
-      dwp_name = xstrprintf ("%s.dwp", objfile_name (objfile));
-      make_cleanup (xfree, dwp_name);
-      dbfd = open_dwp_file (dwp_name);
+      dwp_name = objfile_name (objfile);
+      dwp_name += ".dwp";
+      dbfd = open_dwp_file (dwp_name.c_str ());
     }
 
   if (dbfd == NULL)
     {
       if (dwarf_read_debug)
-       fprintf_unfiltered (gdb_stdlog, "DWP file not found: %s\n", dwp_name);
-      do_cleanups (cleanups);
+       fprintf_unfiltered (gdb_stdlog, "DWP file not found: %s\n", dwp_name.c_str ());
       return NULL;
     }
   dwp_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwp_file);
   dwp_file->name = bfd_get_filename (dbfd.get ());
   dwp_file->dbfd = dbfd.release ();
-  do_cleanups (cleanups);
 
   /* +1: section 0 is unused */
   dwp_file->num_sections = bfd_count_sections (dwp_file->dbfd) + 1;
@@ -10957,7 +11207,7 @@ open_and_init_dwp_file (void)
       error (_("Dwarf Error: DWP file CU version %s doesn't match"
               " TU version %s [in DWP file %s]"),
             pulongest (dwp_file->cus->version),
-            pulongest (dwp_file->tus->version), dwp_name);
+            pulongest (dwp_file->tus->version), dwp_name.c_str ());
     }
   dwp_file->version = dwp_file->cus->version;
 
@@ -11076,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)
@@ -11122,7 +11376,7 @@ lookup_dwo_cutu (struct dwarf2_per_cu_data *this_unit,
             kind, dwo_name, hex_string (signature),
             dwp_text != NULL ? dwp_text : "",
             this_unit->is_debug_types ? "TU" : "CU",
-            this_unit->offset.sect_off, objfile_name (objfile));
+            to_underlying (this_unit->sect_off), objfile_name (objfile));
 
     do_cleanups (cleanups);
   }
@@ -11300,7 +11554,8 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
           && origin_die->tag == DW_TAG_subprogram))
     complaint (&symfile_complaints,
               _("DIE 0x%x and its abstract origin 0x%x have different tags"),
-              die->offset.sect_off, origin_die->offset.sect_off);
+              to_underlying (die->sect_off),
+              to_underlying (origin_die->sect_off));
 
   child_die = die->child;
   die_children_count = 0;
@@ -11355,25 +11610,27 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
                   && child_origin_die->tag == DW_TAG_subprogram))
            complaint (&symfile_complaints,
                       _("Child DIE 0x%x and its abstract origin 0x%x have "
-                        "different tags"), child_die->offset.sect_off,
-                      child_origin_die->offset.sect_off);
+                        "different tags"),
+                      to_underlying (child_die->sect_off),
+                      to_underlying (child_origin_die->sect_off));
          if (child_origin_die->parent != origin_die)
            complaint (&symfile_complaints,
                       _("Child DIE 0x%x and its abstract origin 0x%x have "
-                        "different parents"), child_die->offset.sect_off,
-                      child_origin_die->offset.sect_off);
+                        "different parents"),
+                      to_underlying (child_die->sect_off),
+                      to_underlying (child_origin_die->sect_off));
          else
-           *offsets_end++ = child_origin_die->offset;
+           *offsets_end++ = child_origin_die->sect_off;
        }
     }
   qsort (offsets, offsets_end - offsets, sizeof (*offsets),
         unsigned_int_compar);
   for (offsetp = offsets + 1; offsetp < offsets_end; offsetp++)
-    if (offsetp[-1].sect_off == offsetp->sect_off)
+    if (offsetp[-1] == *offsetp)
       complaint (&symfile_complaints,
                 _("Multiple children of DIE 0x%x refer "
                   "to DIE 0x%x as their abstract origin"),
-                die->offset.sect_off, offsetp->sect_off);
+                to_underlying (die->sect_off), to_underlying (*offsetp));
 
   offsetp = offsets;
   origin_child_die = origin_die->child;
@@ -11381,10 +11638,10 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
     {
       /* Is ORIGIN_CHILD_DIE referenced by any of the DIE children?  */
       while (offsetp < offsets_end
-            && offsetp->sect_off < origin_child_die->offset.sect_off)
+            && *offsetp < origin_child_die->sect_off)
        offsetp++;
       if (offsetp >= offsets_end
-         || offsetp->sect_off > origin_child_die->offset.sect_off)
+         || *offsetp > origin_child_die->sect_off)
        {
          /* Found that ORIGIN_CHILD_DIE is really not referenced.
             Check whether we're already processing ORIGIN_CHILD_DIE.
@@ -11441,7 +11698,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
     {
       complaint (&symfile_complaints,
                 _("missing name for subprogram DIE at %d"),
-                die->offset.sect_off);
+                to_underlying (die->sect_off));
       return;
     }
 
@@ -11454,7 +11711,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
        complaint (&symfile_complaints,
                   _("cannot get low and high bounds "
                     "for subprogram DIE at %d"),
-                  die->offset.sect_off);
+                  to_underlying (die->sect_off));
       return;
     }
 
@@ -11689,7 +11946,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
       complaint (&symfile_complaints,
                 _("missing DW_AT_call_return_pc for DW_TAG_call_site "
                   "DIE 0x%x [in module %s]"),
-                die->offset.sect_off, objfile_name (objfile));
+                to_underlying (die->sect_off), objfile_name (objfile));
       return;
     }
   pc = attr_value_as_address (attr) + baseaddr;
@@ -11706,7 +11963,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
       complaint (&symfile_complaints,
                 _("Duplicate PC %s for DW_TAG_call_site "
                   "DIE 0x%x [in module %s]"),
-                paddress (gdbarch, pc), die->offset.sect_off,
+                paddress (gdbarch, pc), to_underlying (die->sect_off),
                 objfile_name (objfile));
       return;
     }
@@ -11723,7 +11980,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
          complaint (&symfile_complaints,
                     _("Tag %d is not DW_TAG_call_site_parameter in "
                       "DW_TAG_call_site child DIE 0x%x [in module %s]"),
-                    child_die->tag, child_die->offset.sect_off,
+                    child_die->tag, to_underlying (child_die->sect_off),
                     objfile_name (objfile));
          continue;
        }
@@ -11786,7 +12043,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
            complaint (&symfile_complaints,
                       _("Cannot find function owning DW_TAG_call_site "
                         "DIE 0x%x [in module %s]"),
-                      die->offset.sect_off, objfile_name (objfile));
+                      to_underlying (die->sect_off), objfile_name (objfile));
        }
     }
 
@@ -11826,20 +12083,14 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
          const char *target_physname;
 
          /* Prefer the mangled name; otherwise compute the demangled one.  */
-         target_physname = dwarf2_string_attr (target_die,
-                                               DW_AT_linkage_name,
-                                               target_cu);
-         if (target_physname == NULL)
-           target_physname = dwarf2_string_attr (target_die,
-                                                DW_AT_MIPS_linkage_name,
-                                                target_cu);
+         target_physname = dw2_linkage_name (target_die, target_cu);
          if (target_physname == NULL)
            target_physname = dwarf2_physname (NULL, target_die, target_cu);
          if (target_physname == NULL)
            complaint (&symfile_complaints,
                       _("DW_AT_call_target target DIE has invalid "
                         "physname, for referencing DIE 0x%x [in module %s]"),
-                      die->offset.sect_off, objfile_name (objfile));
+                      to_underlying (die->sect_off), objfile_name (objfile));
          else
            SET_FIELD_PHYSNAME (call_site->target, target_physname);
        }
@@ -11853,7 +12104,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
            complaint (&symfile_complaints,
                       _("DW_AT_call_target target DIE has invalid "
                         "low pc, for referencing DIE 0x%x [in module %s]"),
-                      die->offset.sect_off, objfile_name (objfile));
+                      to_underlying (die->sect_off), objfile_name (objfile));
          else
            {
              lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
@@ -11865,7 +12116,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
     complaint (&symfile_complaints,
               _("DW_TAG_call_site DW_AT_call_target is neither "
                 "block nor reference, for DIE 0x%x [in module %s]"),
-              die->offset.sect_off, objfile_name (objfile));
+              to_underlying (die->sect_off), objfile_name (objfile));
 
   call_site->per_cu = cu->per_cu;
 
@@ -11900,11 +12151,11 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
        }
       if (loc == NULL && origin != NULL && attr_form_is_ref (origin))
        {
-         sect_offset offset;
-
          parameter->kind = CALL_SITE_PARAMETER_PARAM_OFFSET;
-         offset = dwarf2_get_ref_die_offset (origin);
-         if (!offset_in_cu_p (&cu->header, offset))
+
+         sect_offset sect_off
+           = (sect_offset) dwarf2_get_ref_die_offset (origin);
+         if (!offset_in_cu_p (&cu->header, sect_off))
            {
              /* As DW_OP_GNU_parameter_ref uses CU-relative offset this
                 binding can be done only inside one CU.  Such referenced DIE
@@ -11912,18 +12163,19 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
              complaint (&symfile_complaints,
                         _("DW_AT_call_parameter offset is not in CU for "
                           "DW_TAG_call_site child DIE 0x%x [in module %s]"),
-                        child_die->offset.sect_off, objfile_name (objfile));
+                        to_underlying (child_die->sect_off),
+                        objfile_name (objfile));
              continue;
            }
-         parameter->u.param_offset.cu_off = (offset.sect_off
-                                             - cu->header.offset.sect_off);
+         parameter->u.param_cu_off
+           = (cu_offset) (sect_off - cu->header.sect_off);
        }
       else if (loc == NULL || origin != NULL || !attr_form_is_block (loc))
        {
          complaint (&symfile_complaints,
                     _("No DW_FORM_block* DW_AT_location for "
                       "DW_TAG_call_site child DIE 0x%x [in module %s]"),
-                    child_die->offset.sect_off, objfile_name (objfile));
+                    to_underlying (child_die->sect_off), objfile_name (objfile));
          continue;
        }
       else
@@ -11943,7 +12195,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
                           "for DW_FORM_block* DW_AT_location is supported for "
                           "DW_TAG_call_site child DIE 0x%x "
                           "[in module %s]"),
-                        child_die->offset.sect_off, objfile_name (objfile));
+                        to_underlying (child_die->sect_off),
+                        objfile_name (objfile));
              continue;
            }
        }
@@ -11956,7 +12209,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
          complaint (&symfile_complaints,
                     _("No DW_FORM_block* DW_AT_call_value for "
                       "DW_TAG_call_site child DIE 0x%x [in module %s]"),
-                    child_die->offset.sect_off, objfile_name (objfile));
+                    to_underlying (child_die->sect_off),
+                    objfile_name (objfile));
          continue;
        }
       parameter->value = DW_BLOCK (attr)->data;
@@ -11976,7 +12230,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
            complaint (&symfile_complaints,
                       _("No DW_FORM_block* DW_AT_call_data_value for "
                         "DW_TAG_call_site child DIE 0x%x [in module %s]"),
-                      child_die->offset.sect_off, objfile_name (objfile));
+                      to_underlying (child_die->sect_off),
+                      objfile_name (objfile));
          else
            {
              parameter->data_value = DW_BLOCK (attr)->data;
@@ -12611,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
@@ -13225,7 +13480,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
                  complaint (&symfile_complaints,
                             _("cannot determine context for virtual member "
                               "function \"%s\" (offset %d)"),
-                            fieldname, die->offset.sect_off);
+                            fieldname, to_underlying (die->sect_off));
                }
              else
                {
@@ -13253,7 +13508,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
          complaint (&symfile_complaints,
                     _("Member function \"%s\" (offset %d) is virtual "
                       "but the vtable offset is not specified"),
-                    fieldname, die->offset.sect_off);
+                    fieldname, to_underlying (die->sect_off));
          ALLOCATE_CPLUS_STRUCT_TYPE (type);
          TYPE_CPLUS_DYNAMIC (type) = 1;
        }
@@ -13353,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
@@ -13469,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
@@ -13723,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;
@@ -13776,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
@@ -13943,8 +14182,8 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
       struct signatured_type *sig_type;
 
       sig_type = (struct signatured_type *) cu->per_cu;
-      gdb_assert (sig_type->type_offset_in_section.sect_off != 0);
-      if (sig_type->type_offset_in_section.sect_off != die->offset.sect_off)
+      gdb_assert (to_underlying (sig_type->type_offset_in_section) != 0);
+      if (sig_type->type_offset_in_section != die->sect_off)
        return;
     }
 
@@ -14184,7 +14423,7 @@ mark_common_block_symbol_computed (struct symbol *sym,
   baton->data = ptr;
 
   *ptr++ = DW_OP_call4;
-  cu_off = common_die->offset.sect_off - cu->per_cu->offset.sect_off;
+  cu_off = common_die->sect_off - cu->per_cu->sect_off;
   store_unsigned_integer (ptr, 4, byte_order, cu_off);
   ptr += 4;
 
@@ -14287,7 +14526,7 @@ read_common_block (struct die_info *die, struct dwarf2_cu *cu)
                             _("Variable in common block has "
                               "DW_AT_data_member_location "
                               "- DIE at 0x%x [in module %s]"),
-                            child_die->offset.sect_off,
+                            to_underlying (child_die->sect_off),
                             objfile_name (cu->objfile));
 
                  if (attr_form_is_section_offset (member_loc))
@@ -14374,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);
        }
     }
 
@@ -14407,7 +14647,7 @@ read_module_type (struct die_info *die, struct dwarf2_cu *cu)
   if (!module_name)
     complaint (&symfile_complaints,
               _("DW_TAG_module has no name, offset 0x%x"),
-               die->offset.sect_off);
+               to_underlying (die->sect_off));
   type = init_type (objfile, TYPE_CODE_MODULE, 0, module_name);
 
   /* determine_prefix uses TYPE_TAG_NAME.  */
@@ -14567,16 +14807,19 @@ read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu)
   return set_die_type (die, type, cu);
 }
 
-/* Extract all information from a DW_TAG_reference_type DIE and add to
+/* Extract all information from a DW_TAG_{rvalue_,}reference_type DIE and add to
    the user defined type vector.  */
 
 static struct type *
-read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu)
+read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu,
+                          enum type_code refcode)
 {
   struct comp_unit_head *cu_header = &cu->header;
   struct type *type, *target_type;
   struct attribute *attr;
 
+  gdb_assert (refcode == TYPE_CODE_REF || refcode == TYPE_CODE_RVALUE_REF);
+
   target_type = die_type (die, cu);
 
   /* The die_type call above may have already set the type for this DIE.  */
@@ -14584,7 +14827,7 @@ read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu)
   if (type)
     return type;
 
-  type = lookup_reference_type (target_type);
+  type = lookup_reference_type (target_type, refcode);
   attr = dwarf2_attr (die, DW_AT_byte_size, cu);
   if (attr)
     {
@@ -14947,7 +15190,7 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu)
       complaint (&symfile_complaints,
                 _("Self-referential DW_TAG_typedef "
                   "- DIE at 0x%x [in module %s]"),
-                die->offset.sect_off, objfile_name (objfile));
+                to_underlying (die->sect_off), objfile_name (objfile));
       TYPE_TARGET_TYPE (this_type) = NULL;
     }
   return this_type;
@@ -14969,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;
 }
@@ -15007,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:
@@ -15052,16 +15295,28 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
          type = init_integer_type (objfile, bits, 1, name);
        break;
       case DW_ATE_UTF:
-       /* We just treat this as an integer and then recognize the
-          type by name elsewhere.  */
-       type = init_integer_type (objfile, bits, 0, name);
+       {
+         gdbarch *arch = get_objfile_arch (objfile);
+
+         if (bits == 16)
+           type = builtin_type (arch)->builtin_char16;
+         else if (bits == 32)
+           type = builtin_type (arch)->builtin_char32;
+         else
+           {
+             complaint (&symfile_complaints,
+                        _("unsupported DW_ATE_UTF bit size: '%d'"),
+                        bits);
+             type = init_integer_type (objfile, bits, 1, name);
+           }
+         return set_die_type (die, type, cu);
+       }
        break;
 
       default:
        complaint (&symfile_complaints, _("unsupported DW_AT_encoding: '%s'"),
                   dwarf_type_encoding_name (encoding));
-       type = init_type (objfile, TYPE_CODE_ERROR,
-                         bits / TARGET_CHAR_BIT, name);
+       type = init_type (objfile, TYPE_CODE_ERROR, bits, name);
        break;
     }
 
@@ -15241,7 +15496,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
   else if (!low_default_is_valid)
     complaint (&symfile_complaints, _("Missing DW_AT_lower_bound "
                                      "- DIE at 0x%x [in module %s]"),
-              die->offset.sect_off, objfile_name (cu->objfile));
+              to_underlying (die->sect_off), objfile_name (cu->objfile));
 
   attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
   if (!attr_to_dynamic_prop (attr, die, cu, &high))
@@ -15463,13 +15718,12 @@ read_full_die_1 (const struct die_reader_specs *reader,
                 int *has_children, int num_extra_attrs)
 {
   unsigned int abbrev_number, bytes_read, i;
-  sect_offset offset;
   struct abbrev_info *abbrev;
   struct die_info *die;
   struct dwarf2_cu *cu = reader->cu;
   bfd *abfd = reader->abfd;
 
-  offset.sect_off = info_ptr - reader->buffer;
+  sect_offset sect_off = (sect_offset) (info_ptr - reader->buffer);
   abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
   info_ptr += bytes_read;
   if (!abbrev_number)
@@ -15486,7 +15740,7 @@ read_full_die_1 (const struct die_reader_specs *reader,
           bfd_get_filename (abfd));
 
   die = dwarf_alloc_die (cu, abbrev->num_attrs + num_extra_attrs);
-  die->offset = offset;
+  die->sect_off = sect_off;
   die->tag = abbrev->tag;
   die->abbrev = abbrev_number;
 
@@ -15591,7 +15845,7 @@ abbrev_table_lookup_abbrev (const struct abbrev_table *abbrev_table,
 
 static struct abbrev_table *
 abbrev_table_read_table (struct dwarf2_section_info *section,
-                        sect_offset offset)
+                        sect_offset sect_off)
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   bfd *abfd = get_section_bfd_owner (section);
@@ -15604,7 +15858,7 @@ abbrev_table_read_table (struct dwarf2_section_info *section,
   unsigned int allocated_attrs;
 
   abbrev_table = XNEW (struct abbrev_table);
-  abbrev_table->offset = offset;
+  abbrev_table->sect_off = sect_off;
   obstack_init (&abbrev_table->abbrev_obstack);
   abbrev_table->abbrevs =
     XOBNEWVEC (&abbrev_table->abbrev_obstack, struct abbrev_info *,
@@ -15613,7 +15867,7 @@ abbrev_table_read_table (struct dwarf2_section_info *section,
          ABBREV_HASH_SIZE * sizeof (struct abbrev_info *));
 
   dwarf2_read_section (objfile, section);
-  abbrev_ptr = section->buffer + offset.sect_off;
+  abbrev_ptr = section->buffer + to_underlying (sect_off);
   abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
   abbrev_ptr += bytes_read;
 
@@ -15730,7 +15984,7 @@ dwarf2_read_abbrevs (struct dwarf2_cu *cu,
                     struct dwarf2_section_info *abbrev_section)
 {
   cu->abbrev_table =
-    abbrev_table_read_table (abbrev_section, cu->header.abbrev_offset);
+    abbrev_table_read_table (abbrev_section, cu->header.abbrev_sect_off);
 }
 
 /* Release the memory used by the abbrev table for a compilation unit.  */
@@ -15932,7 +16186,7 @@ load_partial_dies (const struct die_reader_specs *reader,
        complaint (&symfile_complaints,
                   _("DW_TAG_typedef has childen - GCC PR debug/47510 bug "
                     "- DIE at 0x%x [in module %s]"),
-                  part_die->offset.sect_off, objfile_name (objfile));
+                  to_underlying (part_die->sect_off), objfile_name (objfile));
 
       /* If we're at the second level, and we're an enumerator, and
         our parent has no specification (meaning possibly lives in a
@@ -16005,7 +16259,8 @@ load_partial_dies (const struct die_reader_specs *reader,
          void **slot;
 
          slot = htab_find_slot_with_hash (cu->partial_dies, part_die,
-                                          part_die->offset.sect_off, INSERT);
+                                          to_underlying (part_die->sect_off),
+                                          INSERT);
          *slot = part_die;
        }
 
@@ -16072,7 +16327,7 @@ read_partial_die (const struct die_reader_specs *reader,
 
   memset (part_die, 0, sizeof (struct partial_die_info));
 
-  part_die->offset.sect_off = info_ptr - buffer;
+  part_die->sect_off = (sect_offset) (info_ptr - buffer);
 
   info_ptr += abbrev_len;
 
@@ -16171,8 +16426,8 @@ read_partial_die (const struct die_reader_specs *reader,
                       _("ignoring absolute DW_AT_sibling"));
          else
            {
-             unsigned int off = dwarf2_get_ref_die_offset (&attr).sect_off;
-             const gdb_byte *sibling_ptr = buffer + off;
+             sect_offset off = dwarf2_get_ref_die_offset (&attr);
+             const gdb_byte *sibling_ptr = buffer + to_underlying (off);
 
              if (sibling_ptr < info_ptr)
                complaint (&symfile_complaints,
@@ -16217,7 +16472,7 @@ read_partial_die (const struct die_reader_specs *reader,
        case DW_AT_import:
          if (part_die->tag == DW_TAG_imported_unit)
            {
-             part_die->d.offset = dwarf2_get_ref_die_offset (&attr);
+             part_die->d.sect_off = dwarf2_get_ref_die_offset (&attr);
              part_die->is_dwz = (attr.form == DW_FORM_GNU_ref_alt
                                  || cu->per_cu->is_dwz);
            }
@@ -16253,7 +16508,7 @@ read_partial_die (const struct die_reader_specs *reader,
                     _("DW_AT_low_pc %s is zero "
                       "for DIE at 0x%x [in module %s]"),
                     paddress (gdbarch, part_die->lowpc),
-                    part_die->offset.sect_off, objfile_name (objfile));
+                    to_underlying (part_die->sect_off), objfile_name (objfile));
        }
       /* dwarf2_get_pc_bounds has also the strict low < high requirement.  */
       else if (part_die->lowpc >= part_die->highpc)
@@ -16265,7 +16520,8 @@ read_partial_die (const struct die_reader_specs *reader,
                       "for DIE at 0x%x [in module %s]"),
                     paddress (gdbarch, part_die->lowpc),
                     paddress (gdbarch, part_die->highpc),
-                    part_die->offset.sect_off, objfile_name (objfile));
+                    to_underlying (part_die->sect_off),
+                    objfile_name (objfile));
        }
       else
        part_die->has_pc_info = 1;
@@ -16277,15 +16533,15 @@ read_partial_die (const struct die_reader_specs *reader,
 /* Find a cached partial DIE at OFFSET in CU.  */
 
 static struct partial_die_info *
-find_partial_die_in_comp_unit (sect_offset offset, struct dwarf2_cu *cu)
+find_partial_die_in_comp_unit (sect_offset sect_off, struct dwarf2_cu *cu)
 {
   struct partial_die_info *lookup_die = NULL;
   struct partial_die_info part_die;
 
-  part_die.offset = offset;
+  part_die.sect_off = sect_off;
   lookup_die = ((struct partial_die_info *)
                htab_find_with_hash (cu->partial_dies, &part_die,
-                                    offset.sect_off));
+                                    to_underlying (sect_off)));
 
   return lookup_die;
 }
@@ -16296,16 +16552,16 @@ find_partial_die_in_comp_unit (sect_offset offset, struct dwarf2_cu *cu)
    DW_FORM_ref_sig8).  */
 
 static struct partial_die_info *
-find_partial_die (sect_offset offset, int offset_in_dwz, struct dwarf2_cu *cu)
+find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->objfile;
   struct dwarf2_per_cu_data *per_cu = NULL;
   struct partial_die_info *pd = NULL;
 
   if (offset_in_dwz == cu->per_cu->is_dwz
-      && offset_in_cu_p (&cu->header, offset))
+      && offset_in_cu_p (&cu->header, sect_off))
     {
-      pd = find_partial_die_in_comp_unit (offset, cu);
+      pd = find_partial_die_in_comp_unit (sect_off, cu);
       if (pd != NULL)
        return pd;
       /* We missed recording what we needed.
@@ -16317,19 +16573,19 @@ find_partial_die (sect_offset offset, int offset_in_dwz, struct dwarf2_cu *cu)
       /* TUs don't reference other CUs/TUs (except via type signatures).  */
       if (cu->per_cu->is_debug_types)
        {
-         error (_("Dwarf Error: Type Unit at offset 0x%lx contains"
-                  " external reference to offset 0x%lx [in module %s].\n"),
-                (long) cu->header.offset.sect_off, (long) offset.sect_off,
+         error (_("Dwarf Error: Type Unit at offset 0x%x contains"
+                  " external reference to offset 0x%x [in module %s].\n"),
+                to_underlying (cu->header.sect_off), to_underlying (sect_off),
                 bfd_get_filename (objfile->obfd));
        }
-      per_cu = dwarf2_find_containing_comp_unit (offset, offset_in_dwz,
+      per_cu = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
                                                 objfile);
 
       if (per_cu->cu == NULL || per_cu->cu->partial_dies == NULL)
        load_partial_comp_unit (per_cu);
 
       per_cu->cu->last_used = 0;
-      pd = find_partial_die_in_comp_unit (offset, per_cu->cu);
+      pd = find_partial_die_in_comp_unit (sect_off, per_cu->cu);
     }
 
   /* If we didn't find it, and not all dies have been loaded,
@@ -16347,14 +16603,14 @@ find_partial_die (sect_offset offset, int offset_in_dwz, struct dwarf2_cu *cu)
         set.  */
       load_partial_comp_unit (per_cu);
 
-      pd = find_partial_die_in_comp_unit (offset, per_cu->cu);
+      pd = find_partial_die_in_comp_unit (sect_off, per_cu->cu);
     }
 
   if (pd == NULL)
     internal_error (__FILE__, __LINE__,
                    _("could not find partial DIE 0x%x "
                      "in cache [from module %s]\n"),
-                   offset.sect_off, bfd_get_filename (objfile->obfd));
+                   to_underlying (sect_off), bfd_get_filename (objfile->obfd));
   return pd;
 }
 
@@ -16645,22 +16901,22 @@ read_attribute_value (const struct die_reader_specs *reader,
       info_ptr += bytes_read;
       break;
     case DW_FORM_ref1:
-      DW_UNSND (attr) = (cu->header.offset.sect_off
+      DW_UNSND (attr) = (to_underlying (cu->header.sect_off)
                         + read_1_byte (abfd, info_ptr));
       info_ptr += 1;
       break;
     case DW_FORM_ref2:
-      DW_UNSND (attr) = (cu->header.offset.sect_off
+      DW_UNSND (attr) = (to_underlying (cu->header.sect_off)
                         + read_2_bytes (abfd, info_ptr));
       info_ptr += 2;
       break;
     case DW_FORM_ref4:
-      DW_UNSND (attr) = (cu->header.offset.sect_off
+      DW_UNSND (attr) = (to_underlying (cu->header.sect_off)
                         + read_4_bytes (abfd, info_ptr));
       info_ptr += 4;
       break;
     case DW_FORM_ref8:
-      DW_UNSND (attr) = (cu->header.offset.sect_off
+      DW_UNSND (attr) = (to_underlying (cu->header.sect_off)
                         + read_8_bytes (abfd, info_ptr));
       info_ptr += 8;
       break;
@@ -16669,7 +16925,7 @@ read_attribute_value (const struct die_reader_specs *reader,
       info_ptr += 8;
       break;
     case DW_FORM_ref_udata:
-      DW_UNSND (attr) = (cu->header.offset.sect_off
+      DW_UNSND (attr) = (to_underlying (cu->header.sect_off)
                         + read_unsigned_leb128 (abfd, info_ptr, &bytes_read));
       info_ptr += bytes_read;
       break;
@@ -17308,16 +17564,16 @@ read_str_index (const struct die_reader_specs *reader, ULONGEST str_index)
   dwarf2_read_section (objfile, str_offsets_section);
   if (str_section->buffer == NULL)
     error (_("%s used without .debug_str.dwo section"
-            " in CU at offset 0x%lx [in module %s]"),
-          form_name, (long) cu->header.offset.sect_off, objf_name);
+            " in CU at offset 0x%x [in module %s]"),
+          form_name, to_underlying (cu->header.sect_off), objf_name);
   if (str_offsets_section->buffer == NULL)
     error (_("%s used without .debug_str_offsets.dwo section"
-            " in CU at offset 0x%lx [in module %s]"),
-          form_name, (long) cu->header.offset.sect_off, objf_name);
+            " in CU at offset 0x%x [in module %s]"),
+          form_name, to_underlying (cu->header.sect_off), objf_name);
   if (str_index * cu->header.offset_size >= str_offsets_section->size)
     error (_("%s pointing outside of .debug_str_offsets.dwo"
-            " section in CU at offset 0x%lx [in module %s]"),
-          form_name, (long) cu->header.offset.sect_off, objf_name);
+            " section in CU at offset 0x%x [in module %s]"),
+          form_name, to_underlying (cu->header.sect_off), objf_name);
   info_ptr = (str_offsets_section->buffer
              + str_index * cu->header.offset_size);
   if (cu->header.offset_size == 4)
@@ -17326,8 +17582,8 @@ read_str_index (const struct die_reader_specs *reader, ULONGEST str_index)
     str_offset = bfd_get_64 (abfd, info_ptr);
   if (str_offset >= str_section->size)
     error (_("Offset from %s pointing outside of"
-            " .debug_str.dwo section in CU at offset 0x%lx [in module %s]"),
-          form_name, (long) cu->header.offset.sect_off, objf_name);
+            " .debug_str.dwo section in CU at offset 0x%x [in module %s]"),
+          form_name, to_underlying (cu->header.sect_off), objf_name);
   return (const char *) (str_section->buffer + str_offset);
 }
 
@@ -17467,13 +17723,15 @@ 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,
                   _("string type expected for attribute %s for "
                     "DIE at 0x%x in module %s"),
-                  dwarf_attr_name (name), die->offset.sect_off,
+                  dwarf_attr_name (name), to_underlying (die->sect_off),
                   objfile_name (cu->objfile));
     }
 
@@ -17527,28 +17785,6 @@ die_specification (struct die_info *die, struct dwarf2_cu **spec_cu)
     return follow_die_ref (die, spec_attr, spec_cu);
 }
 
-/* Free the line_header structure *LH, and any arrays and strings it
-   refers to.
-   NOTE: This is also used as a "cleanup" function.  */
-
-static void
-free_line_header (struct line_header *lh)
-{
-  if (lh->standard_opcode_lengths)
-    xfree (lh->standard_opcode_lengths);
-
-  /* Remember that all the lh->file_names[i].name pointers are
-     pointers into debug_line_buffer, and don't need to be freed.  */
-  if (lh->file_names)
-    xfree (lh->file_names);
-
-  /* Similarly for the include directory names.  */
-  if (lh->include_dirs)
-    xfree (lh->include_dirs);
-
-  xfree (lh);
-}
-
 /* Stub for free_line_header to match void * callback types.  */
 
 static void
@@ -17556,69 +17792,30 @@ free_line_header_voidp (void *arg)
 {
   struct line_header *lh = (struct line_header *) arg;
 
-  free_line_header (lh);
+  delete lh;
 }
 
-/* Add an entry to LH's include directory table.  */
-
-static void
-add_include_dir (struct line_header *lh, const char *include_dir)
+void
+line_header::add_include_dir (const char *include_dir)
 {
   if (dwarf_line_debug >= 2)
-    fprintf_unfiltered (gdb_stdlog, "Adding dir %u: %s\n",
-                       lh->num_include_dirs + 1, include_dir);
+    fprintf_unfiltered (gdb_stdlog, "Adding dir %zu: %s\n",
+                       include_dirs.size () + 1, include_dir);
 
-  /* Grow the array if necessary.  */
-  if (lh->include_dirs_size == 0)
-    {
-      lh->include_dirs_size = 1; /* for testing */
-      lh->include_dirs = XNEWVEC (const char *, lh->include_dirs_size);
-    }
-  else if (lh->num_include_dirs >= lh->include_dirs_size)
-    {
-      lh->include_dirs_size *= 2;
-      lh->include_dirs = XRESIZEVEC (const char *, lh->include_dirs,
-                                    lh->include_dirs_size);
-    }
-
-  lh->include_dirs[lh->num_include_dirs++] = include_dir;
+  include_dirs.push_back (include_dir);
 }
 
-/* Add an entry to LH's file name table.  */
-
-static void
-add_file_name (struct line_header *lh,
-               const char *name,
-               unsigned int dir_index,
-               unsigned int mod_time,
-               unsigned int length)
+void
+line_header::add_file_name (const char *name,
+                           dir_index d_index,
+                           unsigned int mod_time,
+                           unsigned int length)
 {
-  struct file_entry *fe;
-
   if (dwarf_line_debug >= 2)
     fprintf_unfiltered (gdb_stdlog, "Adding file %u: %s\n",
-                       lh->num_file_names + 1, name);
-
-  /* Grow the array if necessary.  */
-  if (lh->file_names_size == 0)
-    {
-      lh->file_names_size = 1; /* for testing */
-      lh->file_names = XNEWVEC (struct file_entry, lh->file_names_size);
-    }
-  else if (lh->num_file_names >= lh->file_names_size)
-    {
-      lh->file_names_size *= 2;
-      lh->file_names
-       = XRESIZEVEC (struct file_entry, lh->file_names, lh->file_names_size);
-    }
+                       (unsigned) file_names.size () + 1, name);
 
-  fe = &lh->file_names[lh->num_file_names++];
-  fe->name = name;
-  fe->dir_index = dir_index;
-  fe->mod_time = mod_time;
-  fe->length = length;
-  fe->included_p = 0;
-  fe->symtab = NULL;
+  file_names.emplace_back (name, d_index, mod_time, length);
 }
 
 /* A convenience function to find the proper .debug_line section for a CU.  */
@@ -17644,16 +17841,6 @@ get_debug_line_section (struct dwarf2_cu *cu)
   return section;
 }
 
-/* Forwarding function for read_formatted_entries.  */
-
-static void
-add_include_dir_stub (struct line_header *lh, const char *name,
-                     unsigned int dir_index, unsigned int mod_time,
-                     unsigned int length)
-{
-  add_include_dir (lh, name);
-}
-
 /* Read directory or file name entry format, starting with byte of
    format count entries, ULEB128 pairs of entry formats, ULEB128 of
    entries count and the entries themselves in the described entry
@@ -17665,7 +17852,7 @@ read_formatted_entries (bfd *abfd, const gdb_byte **bufp,
                        const struct comp_unit_head *cu_header,
                        void (*callback) (struct line_header *lh,
                                          const char *name,
-                                         unsigned int dir_index,
+                                         dir_index d_index,
                                          unsigned int mod_time,
                                          unsigned int length))
 {
@@ -17694,75 +17881,53 @@ read_formatted_entries (bfd *abfd, const gdb_byte **bufp,
       const gdb_byte *format = format_header_data;
       struct file_entry fe;
 
-      memset (&fe, 0, sizeof (fe));
-
       for (formati = 0; formati < format_count; formati++)
        {
-         ULONGEST content_type, form;
-         const char *string_trash;
-         const char **stringp = &string_trash;
-         unsigned int uint_trash, *uintp = &uint_trash;
-
-         content_type = read_unsigned_leb128 (abfd, format, &bytes_read);
+         ULONGEST content_type = read_unsigned_leb128 (abfd, format, &bytes_read);
          format += bytes_read;
-         switch (content_type)
-           {
-           case DW_LNCT_path:
-             stringp = &fe.name;
-             break;
-           case DW_LNCT_directory_index:
-             uintp = &fe.dir_index;
-             break;
-           case DW_LNCT_timestamp:
-             uintp = &fe.mod_time;
-             break;
-           case DW_LNCT_size:
-             uintp = &fe.length;
-             break;
-           case DW_LNCT_MD5:
-             break;
-           default:
-             complaint (&symfile_complaints,
-                        _("Unknown format content type %s"),
-                        pulongest (content_type));
-           }
 
-         form = read_unsigned_leb128 (abfd, format, &bytes_read);
+         ULONGEST form  = read_unsigned_leb128 (abfd, format, &bytes_read);
          format += bytes_read;
+
+         gdb::optional<const char *> string;
+         gdb::optional<unsigned int> uint;
+
          switch (form)
            {
            case DW_FORM_string:
-             *stringp = read_direct_string (abfd, buf, &bytes_read);
+             string.emplace (read_direct_string (abfd, buf, &bytes_read));
              buf += bytes_read;
              break;
 
            case DW_FORM_line_strp:
-             *stringp = read_indirect_line_string (abfd, buf, cu_header, &bytes_read);
+             string.emplace (read_indirect_line_string (abfd, buf,
+                                                        cu_header,
+                                                        &bytes_read));
              buf += bytes_read;
              break;
 
            case DW_FORM_data1:
-             *uintp = read_1_byte (abfd, buf);
+             uint.emplace (read_1_byte (abfd, buf));
              buf += 1;
              break;
 
            case DW_FORM_data2:
-             *uintp = read_2_bytes (abfd, buf);
+             uint.emplace (read_2_bytes (abfd, buf));
              buf += 2;
              break;
 
            case DW_FORM_data4:
-             *uintp = read_4_bytes (abfd, buf);
+             uint.emplace (read_4_bytes (abfd, buf));
              buf += 4;
              break;
 
            case DW_FORM_data8:
-             *uintp = read_8_bytes (abfd, buf);
+             uint.emplace (read_8_bytes (abfd, buf));
              buf += 8;
              break;
 
            case DW_FORM_udata:
-             *uintp = read_unsigned_leb128 (abfd, buf, &bytes_read);
+             uint.emplace (read_unsigned_leb128 (abfd, buf, &bytes_read));
              buf += bytes_read;
              break;
 
@@ -17771,9 +17936,35 @@ read_formatted_entries (bfd *abfd, const gdb_byte **bufp,
                 current GDB.  */
              break;
            }
+
+         switch (content_type)
+           {
+           case DW_LNCT_path:
+             if (string.has_value ())
+               fe.name = *string;
+             break;
+           case DW_LNCT_directory_index:
+             if (uint.has_value ())
+               fe.d_index = (dir_index) *uint;
+             break;
+           case DW_LNCT_timestamp:
+             if (uint.has_value ())
+               fe.mod_time = *uint;
+             break;
+           case DW_LNCT_size:
+             if (uint.has_value ())
+               fe.length = *uint;
+             break;
+           case DW_LNCT_MD5:
+             break;
+           default:
+             complaint (&symfile_complaints,
+                        _("Unknown format content type %s"),
+                        pulongest (content_type));
+           }
        }
 
-      callback (lh, fe.name, fe.dir_index, fe.mod_time, fe.length);
+      callback (lh, fe.name, fe.d_index, fe.mod_time, fe.length);
     }
 
   *bufp = buf;
@@ -17789,11 +17980,9 @@ read_formatted_entries (bfd *abfd, const gdb_byte **bufp,
    the returned object point into the dwarf line section buffer,
    and must not be freed.  */
 
-static struct line_header *
-dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
+static line_header_up
+dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu)
 {
-  struct cleanup *back_to;
-  struct line_header *lh;
   const gdb_byte *line_ptr;
   unsigned int bytes_read, offset_size;
   int i;
@@ -17818,21 +18007,18 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
 
   /* Make sure that at least there's room for the total_length field.
      That could be 12 bytes long, but we're just going to fudge that.  */
-  if (offset + 4 >= section->size)
+  if (to_underlying (sect_off) + 4 >= section->size)
     {
       dwarf2_statement_list_fits_in_line_number_section_complaint ();
       return 0;
     }
 
-  lh = XNEW (struct line_header);
-  memset (lh, 0, sizeof (*lh));
-  back_to = make_cleanup ((make_cleanup_ftype *) free_line_header,
-                          (void *) lh);
+  line_header_up lh (new line_header ());
 
-  lh->offset.sect_off = offset;
+  lh->sect_off = sect_off;
   lh->offset_in_dwz = cu->per_cu->is_dwz;
 
-  line_ptr = section->buffer + offset;
+  line_ptr = section->buffer + to_underlying (sect_off);
 
   /* Read in the header.  */
   lh->total_length =
@@ -17842,7 +18028,6 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
   if (line_ptr + lh->total_length > (section->buffer + section->size))
     {
       dwarf2_statement_list_fits_in_line_number_section_complaint ();
-      do_cleanups (back_to);
       return 0;
     }
   lh->statement_program_end = line_ptr + lh->total_length;
@@ -17903,7 +18088,7 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
   line_ptr += 1;
   lh->opcode_base = read_1_byte (abfd, line_ptr);
   line_ptr += 1;
-  lh->standard_opcode_lengths = XNEWVEC (unsigned char, lh->opcode_base);
+  lh->standard_opcode_lengths.reset (new unsigned char[lh->opcode_base]);
 
   lh->standard_opcode_lengths[0] = 1;  /* This should never be used anyway.  */
   for (i = 1; i < lh->opcode_base; ++i)
@@ -17915,11 +18100,22 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
   if (lh->version >= 5)
     {
       /* Read directory table.  */
-      read_formatted_entries (abfd, &line_ptr, lh, &cu->header,
-                             add_include_dir_stub);
+      read_formatted_entries (abfd, &line_ptr, lh.get (), &cu->header,
+                             [] (struct line_header *lh, const char *name,
+                                 dir_index d_index, unsigned int mod_time,
+                                 unsigned int length)
+       {
+         lh->add_include_dir (name);
+       });
 
       /* Read file name table.  */
-      read_formatted_entries (abfd, &line_ptr, lh, &cu->header, add_file_name);
+      read_formatted_entries (abfd, &line_ptr, lh.get (), &cu->header,
+                             [] (struct line_header *lh, const char *name,
+                                 dir_index d_index, unsigned int mod_time,
+                                 unsigned int length)
+       {
+         lh->add_file_name (name, d_index, mod_time, length);
+       });
     }
   else
     {
@@ -17927,24 +18123,25 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
       while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
        {
          line_ptr += bytes_read;
-         add_include_dir (lh, cur_dir);
+         lh->add_include_dir (cur_dir);
        }
       line_ptr += bytes_read;
 
       /* Read file name table.  */
       while ((cur_file = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
        {
-         unsigned int dir_index, mod_time, length;
+         unsigned int mod_time, length;
+         dir_index d_index;
 
          line_ptr += bytes_read;
-         dir_index = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+         d_index = (dir_index) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
          line_ptr += bytes_read;
          mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
          line_ptr += bytes_read;
          length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
          line_ptr += bytes_read;
 
-         add_file_name (lh, cur_file, dir_index, mod_time, length);
+         lh->add_file_name (cur_file, d_index, mod_time, length);
        }
       line_ptr += bytes_read;
     }
@@ -17955,7 +18152,6 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
               _("line number info header doesn't "
                 "fit in `.debug_line' section"));
 
-  discard_cleanups (back_to);
   return lh;
 }
 
@@ -17973,16 +18169,14 @@ psymtab_include_file_name (const struct line_header *lh, int file_index,
                           const struct partial_symtab *pst,
                           const char *comp_dir)
 {
-  const struct file_entry fe = lh->file_names [file_index];
+  const file_entry &fe = lh->file_names[file_index];
   const char *include_name = fe.name;
   const char *include_name_to_compare = include_name;
-  const char *dir_name = NULL;
   const char *pst_filename;
   char *copied_name = NULL;
   int file_is_pst;
 
-  if (fe.dir_index && lh->include_dirs != NULL)
-    dir_name = lh->include_dirs[fe.dir_index - 1];
+  const char *dir_name = fe.include_dir (lh);
 
   if (!IS_ABSOLUTE_PATH (include_name)
       && (dir_name != NULL || comp_dir != NULL))
@@ -18047,51 +18241,203 @@ psymtab_include_file_name (const struct line_header *lh, int file_index,
 
 /* State machine to track the state of the line number program.  */
 
-typedef struct
+class lnp_state_machine
 {
-  /* These are part of the standard DWARF line number state machine.  */
+public:
+  /* Initialize a machine state for the start of a line number
+     program.  */
+  lnp_state_machine (gdbarch *arch, line_header *lh, bool record_lines_p);
+
+  file_entry *current_file ()
+  {
+    /* lh->file_names is 0-based, but the file name numbers in the
+       statement program are 1-based.  */
+    return m_line_header->file_name_at (m_file);
+  }
+
+  /* Record the line in the state machine.  END_SEQUENCE is true if
+     we're processing the end of a sequence.  */
+  void record_line (bool end_sequence);
+
+  /* Check address and if invalid nop-out the rest of the lines in this
+     sequence.  */
+  void check_line_address (struct dwarf2_cu *cu,
+                          const gdb_byte *line_ptr,
+                          CORE_ADDR lowpc, CORE_ADDR address);
+
+  void handle_set_discriminator (unsigned int discriminator)
+  {
+    m_discriminator = discriminator;
+    m_line_has_non_zero_discriminator |= discriminator != 0;
+  }
+
+  /* Handle DW_LNE_set_address.  */
+  void handle_set_address (CORE_ADDR baseaddr, CORE_ADDR address)
+  {
+    m_op_index = 0;
+    address += baseaddr;
+    m_address = gdbarch_adjust_dwarf2_line (m_gdbarch, address, false);
+  }
+
+  /* Handle DW_LNS_advance_pc.  */
+  void handle_advance_pc (CORE_ADDR adjust);
+
+  /* Handle a special opcode.  */
+  void handle_special_opcode (unsigned char op_code);
+
+  /* Handle DW_LNS_advance_line.  */
+  void handle_advance_line (int line_delta)
+  {
+    advance_line (line_delta);
+  }
+
+  /* Handle DW_LNS_set_file.  */
+  void handle_set_file (file_name_index file);
 
-  unsigned char op_index;
-  unsigned int file;
-  unsigned int line;
-  CORE_ADDR address;
-  int is_stmt;
-  unsigned int discriminator;
+  /* Handle DW_LNS_negate_stmt.  */
+  void handle_negate_stmt ()
+  {
+    m_is_stmt = !m_is_stmt;
+  }
+
+  /* Handle DW_LNS_const_add_pc.  */
+  void handle_const_add_pc ();
+
+  /* Handle DW_LNS_fixed_advance_pc.  */
+  void handle_fixed_advance_pc (CORE_ADDR addr_adj)
+  {
+    m_address += gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
+    m_op_index = 0;
+  }
+
+  /* Handle DW_LNS_copy.  */
+  void handle_copy ()
+  {
+    record_line (false);
+    m_discriminator = 0;
+  }
+
+  /* Handle DW_LNE_end_sequence.  */
+  void handle_end_sequence ()
+  {
+    m_record_line_callback = ::record_line;
+  }
+
+private:
+  /* Advance the line by LINE_DELTA.  */
+  void advance_line (int line_delta)
+  {
+    m_line += line_delta;
+
+    if (line_delta != 0)
+      m_line_has_non_zero_discriminator = m_discriminator != 0;
+  }
+
+  gdbarch *m_gdbarch;
+
+  /* True if we're recording lines.
+     Otherwise we're building partial symtabs and are just interested in
+     finding include files mentioned by the line number program.  */
+  bool m_record_lines_p;
+
+  /* The line number header.  */
+  line_header *m_line_header;
+
+  /* These are part of the standard DWARF line number state machine,
+     and initialized according to the DWARF spec.  */
+
+  unsigned char m_op_index = 0;
+  /* The line table index (1-based) of the current file.  */
+  file_name_index m_file = (file_name_index) 1;
+  unsigned int m_line = 1;
+
+  /* These are initialized in the constructor.  */
+
+  CORE_ADDR m_address;
+  bool m_is_stmt;
+  unsigned int m_discriminator;
 
   /* Additional bits of state we need to track.  */
 
   /* The last file that we called dwarf2_start_subfile for.
      This is only used for TLLs.  */
-  unsigned int last_file;
+  unsigned int m_last_file = 0;
   /* The last file a line number was recorded for.  */
-  struct subfile *last_subfile;
+  struct subfile *m_last_subfile = NULL;
 
   /* The function to call to record a line.  */
-  record_line_ftype *record_line;
+  record_line_ftype *m_record_line_callback = NULL;
 
   /* The last line number that was recorded, used to coalesce
      consecutive entries for the same line.  This can happen, for
      example, when discriminators are present.  PR 17276.  */
-  unsigned int last_line;
-  int line_has_non_zero_discriminator;
-} lnp_state_machine;
+  unsigned int m_last_line = 0;
+  bool m_line_has_non_zero_discriminator = false;
+};
 
-/* There's a lot of static state to pass to dwarf_record_line.
-   This keeps it all together.  */
+void
+lnp_state_machine::handle_advance_pc (CORE_ADDR adjust)
+{
+  CORE_ADDR addr_adj = (((m_op_index + adjust)
+                        / m_line_header->maximum_ops_per_instruction)
+                       * m_line_header->minimum_instruction_length);
+  m_address += gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
+  m_op_index = ((m_op_index + adjust)
+               % m_line_header->maximum_ops_per_instruction);
+}
 
-typedef struct
+void
+lnp_state_machine::handle_special_opcode (unsigned char op_code)
 {
-  /* The gdbarch.  */
-  struct gdbarch *gdbarch;
+  unsigned char adj_opcode = op_code - m_line_header->opcode_base;
+  CORE_ADDR addr_adj = (((m_op_index
+                         + (adj_opcode / m_line_header->line_range))
+                        / m_line_header->maximum_ops_per_instruction)
+                       * m_line_header->minimum_instruction_length);
+  m_address += gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
+  m_op_index = ((m_op_index + (adj_opcode / m_line_header->line_range))
+               % m_line_header->maximum_ops_per_instruction);
 
-  /* The line number header.  */
-  struct line_header *line_header;
+  int line_delta = (m_line_header->line_base
+                   + (adj_opcode % m_line_header->line_range));
+  advance_line (line_delta);
+  record_line (false);
+  m_discriminator = 0;
+}
 
-  /* Non-zero if we're recording lines.
-     Otherwise we're building partial symtabs and are just interested in
-     finding include files mentioned by the line number program.  */
-  int record_lines_p;
-} lnp_reader_state;
+void
+lnp_state_machine::handle_set_file (file_name_index file)
+{
+  m_file = file;
+
+  const file_entry *fe = current_file ();
+  if (fe == NULL)
+    dwarf2_debug_line_missing_file_complaint ();
+  else if (m_record_lines_p)
+    {
+      const char *dir = fe->include_dir (m_line_header);
+
+      m_last_subfile = current_subfile;
+      m_line_has_non_zero_discriminator = m_discriminator != 0;
+      dwarf2_start_subfile (fe->name, dir);
+    }
+}
+
+void
+lnp_state_machine::handle_const_add_pc ()
+{
+  CORE_ADDR adjust
+    = (255 - m_line_header->opcode_base) / m_line_header->line_range;
+
+  CORE_ADDR addr_adj
+    = (((m_op_index + adjust)
+       / m_line_header->maximum_ops_per_instruction)
+       * m_line_header->minimum_instruction_length);
+
+  m_address += gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
+  m_op_index = ((m_op_index + adjust)
+               % m_line_header->maximum_ops_per_instruction);
+}
 
 /* Ignore this record_line request.  */
 
@@ -18192,102 +18538,76 @@ dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile,
   dwarf_record_line_1 (gdbarch, subfile, 0, address, p_record_line);
 }
 
-/* Record the line in STATE.
-   END_SEQUENCE is non-zero if we're processing the end of a sequence.  */
-
-static void
-dwarf_record_line (lnp_reader_state *reader, lnp_state_machine *state,
-                  int end_sequence)
+void
+lnp_state_machine::record_line (bool end_sequence)
 {
-  const struct line_header *lh = reader->line_header;
-  unsigned int file, line, discriminator;
-  int is_stmt;
-
-  file = state->file;
-  line = state->line;
-  is_stmt = state->is_stmt;
-  discriminator = state->discriminator;
-
   if (dwarf_line_debug)
     {
       fprintf_unfiltered (gdb_stdlog,
                          "Processing actual line %u: file %u,"
                          " address %s, is_stmt %u, discrim %u\n",
-                         line, file,
-                         paddress (reader->gdbarch, state->address),
-                         is_stmt, discriminator);
+                         m_line, to_underlying (m_file),
+                         paddress (m_gdbarch, m_address),
+                         m_is_stmt, m_discriminator);
     }
 
-  if (file == 0 || file - 1 >= lh->num_file_names)
+  file_entry *fe = current_file ();
+
+  if (fe == NULL)
     dwarf2_debug_line_missing_file_complaint ();
   /* For now we ignore lines not starting on an instruction boundary.
      But not when processing end_sequence for compatibility with the
      previous version of the code.  */
-  else if (state->op_index == 0 || end_sequence)
+  else if (m_op_index == 0 || end_sequence)
     {
-      lh->file_names[file - 1].included_p = 1;
-      if (reader->record_lines_p && is_stmt)
+      fe->included_p = 1;
+      if (m_record_lines_p && m_is_stmt)
        {
-         if (state->last_subfile != current_subfile || end_sequence)
+         if (m_last_subfile != current_subfile || end_sequence)
            {
-             dwarf_finish_line (reader->gdbarch, state->last_subfile,
-                                state->address, state->record_line);
+             dwarf_finish_line (m_gdbarch, m_last_subfile,
+                                m_address, m_record_line_callback);
            }
 
          if (!end_sequence)
            {
-             if (dwarf_record_line_p (line, state->last_line,
-                                      state->line_has_non_zero_discriminator,
-                                      state->last_subfile))
+             if (dwarf_record_line_p (m_line, m_last_line,
+                                      m_line_has_non_zero_discriminator,
+                                      m_last_subfile))
                {
-                 dwarf_record_line_1 (reader->gdbarch, current_subfile,
-                                      line, state->address,
-                                      state->record_line);
+                 dwarf_record_line_1 (m_gdbarch, current_subfile,
+                                      m_line, m_address,
+                                      m_record_line_callback);
                }
-             state->last_subfile = current_subfile;
-             state->last_line = line;
+             m_last_subfile = current_subfile;
+             m_last_line = m_line;
            }
        }
     }
 }
 
-/* Initialize STATE for the start of a line number program.  */
-
-static void
-init_lnp_state_machine (lnp_state_machine *state,
-                       const lnp_reader_state *reader)
+lnp_state_machine::lnp_state_machine (gdbarch *arch, line_header *lh,
+                                     bool record_lines_p)
 {
-  memset (state, 0, sizeof (*state));
-
-  /* Just starting, there is no "last file".  */
-  state->last_file = 0;
-  state->last_subfile = NULL;
-
-  state->record_line = record_line;
+  m_gdbarch = arch;
+  m_record_lines_p = record_lines_p;
+  m_line_header = lh;
 
-  state->last_line = 0;
-  state->line_has_non_zero_discriminator = 0;
+  m_record_line_callback = ::record_line;
 
-  /* Initialize these according to the DWARF spec.  */
-  state->op_index = 0;
-  state->file = 1;
-  state->line = 1;
   /* Call `gdbarch_adjust_dwarf2_line' on the initial 0 address as if there
      was a line entry for it so that the backend has a chance to adjust it
      and also record it in case it needs it.  This is currently used by MIPS
      code, cf. `mips_adjust_dwarf2_line'.  */
-  state->address = gdbarch_adjust_dwarf2_line (reader->gdbarch, 0, 0);
-  state->is_stmt = reader->line_header->default_is_stmt;
-  state->discriminator = 0;
+  m_address = gdbarch_adjust_dwarf2_line (arch, 0, 0);
+  m_is_stmt = lh->default_is_stmt;
+  m_discriminator = 0;
 }
 
-/* Check address and if invalid nop-out the rest of the lines in this
-   sequence.  */
-
-static void
-check_line_address (struct dwarf2_cu *cu, lnp_state_machine *state,
-                   const gdb_byte *line_ptr,
-                   CORE_ADDR lowpc, CORE_ADDR address)
+void
+lnp_state_machine::check_line_address (struct dwarf2_cu *cu,
+                                      const gdb_byte *line_ptr,
+                                      CORE_ADDR lowpc, CORE_ADDR address)
 {
   /* If address < lowpc then it's not a usable value, it's outside the
      pc range of the CU.  However, we restrict the test to only address
@@ -18305,9 +18625,9 @@ check_line_address (struct dwarf2_cu *cu, lnp_state_machine *state,
       complaint (&symfile_complaints,
                 _(".debug_line address at offset 0x%lx is 0 [in module %s]"),
                 line_offset, objfile_name (objfile));
-      state->record_line = noop_record_line;
-      /* Note: sm.record_line is left as noop_record_line
-        until we see DW_LNE_end_sequence.  */
+      m_record_line_callback = noop_record_line;
+      /* Note: record_line_callback is left as noop_record_line until
+        we see DW_LNE_end_sequence.  */
     }
 }
 
@@ -18328,44 +18648,32 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
   struct objfile *objfile = cu->objfile;
   bfd *abfd = objfile->obfd;
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
-  /* Non-zero if we're recording line info (as opposed to building partial
-     symtabs).  */
-  int record_lines_p = !decode_for_pst_p;
-  /* A collection of things we need to pass to dwarf_record_line.  */
-  lnp_reader_state reader_state;
+  /* True if we're recording line info (as opposed to building partial
+     symtabs and just interested in finding include files mentioned by
+     the line number program).  */
+  bool record_lines_p = !decode_for_pst_p;
 
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
   line_ptr = lh->statement_program_start;
   line_end = lh->statement_program_end;
 
-  reader_state.gdbarch = gdbarch;
-  reader_state.line_header = lh;
-  reader_state.record_lines_p = record_lines_p;
-
   /* Read the statement sequences until there's nothing left.  */
   while (line_ptr < line_end)
     {
-      /* The DWARF line number program state machine.  */
-      lnp_state_machine state_machine;
-      int end_sequence = 0;
+      /* The DWARF line number program state machine.  Reset the state
+        machine at the start of each sequence.  */
+      lnp_state_machine state_machine (gdbarch, lh, record_lines_p);
+      bool end_sequence = false;
 
-      /* Reset the state machine at the start of each sequence.  */
-      init_lnp_state_machine (&state_machine, &reader_state);
-
-      if (record_lines_p && lh->num_file_names >= state_machine.file)
+      if (record_lines_p)
        {
-          /* Start a subfile for the current file of the state machine.  */
-         /* lh->include_dirs and lh->file_names are 0-based, but the
-            directory and file name numbers in the statement program
-            are 1-based.  */
-          struct file_entry *fe = &lh->file_names[state_machine.file - 1];
-          const char *dir = NULL;
-
-          if (fe->dir_index && lh->include_dirs != NULL)
-            dir = lh->include_dirs[fe->dir_index - 1];
+         /* Start a subfile for the current file of the state
+            machine.  */
+         const file_entry *fe = state_machine.current_file ();
 
-         dwarf2_start_subfile (fe->name, dir);
+         if (fe != NULL)
+           dwarf2_start_subfile (fe->name, fe->include_dir (lh));
        }
 
       /* Decode the table.  */
@@ -18377,28 +18685,7 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
          if (op_code >= lh->opcode_base)
            {
              /* Special opcode.  */
-             unsigned char adj_opcode;
-             CORE_ADDR addr_adj;
-             int line_delta;
-
-             adj_opcode = op_code - lh->opcode_base;
-             addr_adj = (((state_machine.op_index
-                           + (adj_opcode / lh->line_range))
-                          / lh->maximum_ops_per_instruction)
-                         * lh->minimum_instruction_length);
-             state_machine.address
-               += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
-             state_machine.op_index = ((state_machine.op_index
-                                        + (adj_opcode / lh->line_range))
-                                       % lh->maximum_ops_per_instruction);
-             line_delta = lh->line_base + (adj_opcode % lh->line_range);
-             state_machine.line += line_delta;
-             if (line_delta != 0)
-               state_machine.line_has_non_zero_discriminator
-                 = state_machine.discriminator != 0;
-
-             dwarf_record_line (&reader_state, &state_machine, 0);
-             state_machine.discriminator = 0;
+             state_machine.handle_special_opcode (op_code);
            }
          else switch (op_code)
            {
@@ -18412,32 +18699,30 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
              switch (extended_op)
                {
                case DW_LNE_end_sequence:
-                 state_machine.record_line = record_line;
-                 end_sequence = 1;
+                 state_machine.handle_end_sequence ();
+                 end_sequence = true;
                  break;
                case DW_LNE_set_address:
                  {
                    CORE_ADDR address
                      = read_address (abfd, line_ptr, cu, &bytes_read);
-
                    line_ptr += bytes_read;
-                   check_line_address (cu, &state_machine, line_ptr,
-                                       lowpc, address);
-                   state_machine.op_index = 0;
-                   address += baseaddr;
-                   state_machine.address
-                     = gdbarch_adjust_dwarf2_line (gdbarch, address, 0);
+
+                   state_machine.check_line_address (cu, line_ptr,
+                                                     lowpc, address);
+                   state_machine.handle_set_address (baseaddr, address);
                  }
                  break;
                case DW_LNE_define_file:
                   {
                     const char *cur_file;
-                    unsigned int dir_index, mod_time, length;
+                   unsigned int mod_time, length;
+                   dir_index dindex;
 
                     cur_file = read_direct_string (abfd, line_ptr,
                                                   &bytes_read);
                     line_ptr += bytes_read;
-                    dir_index =
+                    dindex = (dir_index)
                       read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
                     line_ptr += bytes_read;
                     mod_time =
@@ -18446,20 +18731,23 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
                     length =
                       read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
                     line_ptr += bytes_read;
-                    add_file_name (lh, cur_file, dir_index, mod_time, length);
+                    lh->add_file_name (cur_file, dindex, mod_time, length);
                   }
                  break;
                case DW_LNE_set_discriminator:
-                 /* The discriminator is not interesting to the debugger;
-                    just ignore it.  We still need to check its value though:
-                    if there are consecutive entries for the same
-                    (non-prologue) line we want to coalesce them.
-                    PR 17276.  */
-                 state_machine.discriminator
-                   = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-                 state_machine.line_has_non_zero_discriminator
-                   |= state_machine.discriminator != 0;
-                 line_ptr += bytes_read;
+                 {
+                   /* The discriminator is not interesting to the
+                      debugger; just ignore it.  We still need to
+                      check its value though:
+                      if there are consecutive entries for the same
+                      (non-prologue) line we want to coalesce them.
+                      PR 17276.  */
+                   unsigned int discr
+                     = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                   line_ptr += bytes_read;
+
+                   state_machine.handle_set_discriminator (discr);
+                 }
                  break;
                default:
                  complaint (&symfile_complaints,
@@ -18477,64 +18765,34 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
                }
              break;
            case DW_LNS_copy:
-             dwarf_record_line (&reader_state, &state_machine, 0);
-             state_machine.discriminator = 0;
+             state_machine.handle_copy ();
              break;
            case DW_LNS_advance_pc:
              {
                CORE_ADDR adjust
                  = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-               CORE_ADDR addr_adj;
-
-               addr_adj = (((state_machine.op_index + adjust)
-                            / lh->maximum_ops_per_instruction)
-                           * lh->minimum_instruction_length);
-               state_machine.address
-                 += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
-               state_machine.op_index = ((state_machine.op_index + adjust)
-                                         % lh->maximum_ops_per_instruction);
                line_ptr += bytes_read;
+
+               state_machine.handle_advance_pc (adjust);
              }
              break;
            case DW_LNS_advance_line:
              {
                int line_delta
                  = read_signed_leb128 (abfd, line_ptr, &bytes_read);
-
-               state_machine.line += line_delta;
-               if (line_delta != 0)
-                 state_machine.line_has_non_zero_discriminator
-                   = state_machine.discriminator != 0;
                line_ptr += bytes_read;
+
+               state_machine.handle_advance_line (line_delta);
              }
              break;
            case DW_LNS_set_file:
              {
-               /* The arrays lh->include_dirs and lh->file_names are
-                  0-based, but the directory and file name numbers in
-                  the statement program are 1-based.  */
-               struct file_entry *fe;
-               const char *dir = NULL;
-
-               state_machine.file = read_unsigned_leb128 (abfd, line_ptr,
-                                                          &bytes_read);
+               file_name_index file
+                 = (file_name_index) read_unsigned_leb128 (abfd, line_ptr,
+                                                           &bytes_read);
                line_ptr += bytes_read;
-               if (state_machine.file == 0
-                   || state_machine.file - 1 >= lh->num_file_names)
-                 dwarf2_debug_line_missing_file_complaint ();
-               else
-                 {
-                   fe = &lh->file_names[state_machine.file - 1];
-                   if (fe->dir_index && lh->include_dirs != NULL)
-                     dir = lh->include_dirs[fe->dir_index - 1];
-                   if (record_lines_p)
-                     {
-                       state_machine.last_subfile = current_subfile;
-                       state_machine.line_has_non_zero_discriminator
-                         = state_machine.discriminator != 0;
-                       dwarf2_start_subfile (fe->name, dir);
-                     }
-                 }
+
+               state_machine.handle_set_file (file);
              }
              break;
            case DW_LNS_set_column:
@@ -18542,7 +18800,7 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
              line_ptr += bytes_read;
              break;
            case DW_LNS_negate_stmt:
-             state_machine.is_stmt = (!state_machine.is_stmt);
+             state_machine.handle_negate_stmt ();
              break;
            case DW_LNS_set_basic_block:
              break;
@@ -18552,28 +18810,14 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
               instruction length since special opcode 255 would have
               scaled the increment.  */
            case DW_LNS_const_add_pc:
-             {
-               CORE_ADDR adjust = (255 - lh->opcode_base) / lh->line_range;
-               CORE_ADDR addr_adj;
-
-               addr_adj = (((state_machine.op_index + adjust)
-                            / lh->maximum_ops_per_instruction)
-                           * lh->minimum_instruction_length);
-               state_machine.address
-                 += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
-               state_machine.op_index = ((state_machine.op_index + adjust)
-                                         % lh->maximum_ops_per_instruction);
-             }
+             state_machine.handle_const_add_pc ();
              break;
            case DW_LNS_fixed_advance_pc:
              {
-               CORE_ADDR addr_adj;
-
-               addr_adj = read_2_bytes (abfd, line_ptr);
-               state_machine.address
-                 += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
-               state_machine.op_index = 0;
+               CORE_ADDR addr_adj = read_2_bytes (abfd, line_ptr);
                line_ptr += 2;
+
+               state_machine.handle_fixed_advance_pc (addr_adj);
              }
              break;
            default:
@@ -18595,7 +18839,7 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
 
       /* We got a DW_LNE_end_sequence (or we ran off the end of the buffer,
         in which case we still finish recording the last line).  */
-      dwarf_record_line (&reader_state, &state_machine, 1);
+      state_machine.record_line (true);
     }
 }
 
@@ -18644,7 +18888,7 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
 
       /* Now that we're done scanning the Line Header Program, we can
          create the psymtab of each included file.  */
-      for (file_index = 0; file_index < lh->num_file_names; file_index++)
+      for (file_index = 0; file_index < lh->file_names.size (); file_index++)
         if (lh->file_names[file_index].included_p == 1)
           {
            const char *include_name =
@@ -18661,22 +18905,18 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
       struct compunit_symtab *cust = buildsym_compunit_symtab ();
       int i;
 
-      for (i = 0; i < lh->num_file_names; i++)
+      for (i = 0; i < lh->file_names.size (); i++)
        {
-         const char *dir = NULL;
-         struct file_entry *fe;
+         file_entry &fe = lh->file_names[i];
 
-         fe = &lh->file_names[i];
-         if (fe->dir_index && lh->include_dirs != NULL)
-           dir = lh->include_dirs[fe->dir_index - 1];
-         dwarf2_start_subfile (fe->name, dir);
+         dwarf2_start_subfile (fe.name, fe.include_dir (lh));
 
          if (current_subfile->symtab == NULL)
            {
              current_subfile->symtab
                = allocate_symtab (cust, current_subfile->name);
            }
-         fe->symtab = current_subfile->symtab;
+         fe.symtab = current_subfile->symtab;
        }
     }
 }
@@ -18885,19 +19125,19 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
                          cu);
       if (attr)
        {
-         int file_index = DW_UNSND (attr);
+         file_name_index file_index = (file_name_index) DW_UNSND (attr);
+         struct file_entry *fe;
 
-         if (cu->line_header == NULL
-             || file_index > cu->line_header->num_file_names)
+         if (cu->line_header != NULL)
+           fe = cu->line_header->file_name_at (file_index);
+         else
+           fe = NULL;
+
+         if (fe == NULL)
            complaint (&symfile_complaints,
                       _("file index out of range"));
-         else if (file_index > 0)
-           {
-             struct file_entry *fe;
-
-             fe = &cu->line_header->file_names[file_index - 1];
-             symbol_set_symtab (sym, fe->symtab);
-           }
+         else
+           symbol_set_symtab (sym, fe->symtab);
        }
 
       switch (die->tag)
@@ -18955,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
@@ -19338,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;
 
@@ -19481,8 +19721,8 @@ build_error_marker_type (struct dwarf2_cu *cu, struct die_info *die)
 
   message = xstrprintf (_("<unknown type in %s, CU 0x%x, DIE 0x%x>"),
                        objfile_name (objfile),
-                       cu->header.offset.sect_off,
-                       die->offset.sect_off);
+                       to_underlying (cu->header.sect_off),
+                       to_underlying (die->sect_off));
   saved = (char *) obstack_copy0 (&objfile->objfile_obstack,
                                  message, strlen (message));
   xfree (message);
@@ -19511,16 +19751,16 @@ lookup_die_type (struct die_info *die, const struct attribute *attr,
   if (attr->form == DW_FORM_GNU_ref_alt)
     {
       struct dwarf2_per_cu_data *per_cu;
-      sect_offset offset = dwarf2_get_ref_die_offset (attr);
+      sect_offset sect_off = dwarf2_get_ref_die_offset (attr);
 
-      per_cu = dwarf2_find_containing_comp_unit (offset, 1, cu->objfile);
-      this_type = get_die_type_at_offset (offset, per_cu);
+      per_cu = dwarf2_find_containing_comp_unit (sect_off, 1, cu->objfile);
+      this_type = get_die_type_at_offset (sect_off, per_cu);
     }
   else if (attr_form_is_ref (attr))
     {
-      sect_offset offset = dwarf2_get_ref_die_offset (attr);
+      sect_offset sect_off = dwarf2_get_ref_die_offset (attr);
 
-      this_type = get_die_type_at_offset (offset, cu->per_cu);
+      this_type = get_die_type_at_offset (sect_off, cu->per_cu);
     }
   else if (attr->form == DW_FORM_ref_sig8)
     {
@@ -19533,7 +19773,7 @@ lookup_die_type (struct die_info *die, const struct attribute *attr,
       complaint (&symfile_complaints,
                 _("Dwarf Error: Bad type attribute %s in DIE"
                   " at 0x%x [in module %s]"),
-                dwarf_attr_name (attr->name), die->offset.sect_off,
+                dwarf_attr_name (attr->name), to_underlying (die->sect_off),
                 objfile_name (objfile));
       return build_error_marker_type (cu, die);
     }
@@ -19620,7 +19860,10 @@ read_type_die_1 (struct die_info *die, struct dwarf2_cu *cu)
       this_type = read_tag_ptr_to_member_type (die, cu);
       break;
     case DW_TAG_reference_type:
-      this_type = read_tag_reference_type (die, cu);
+      this_type = read_tag_reference_type (die, cu, TYPE_CODE_REF);
+      break;
+    case DW_TAG_rvalue_reference_type:
+      this_type = read_tag_reference_type (die, cu, TYPE_CODE_RVALUE_REF);
       break;
     case DW_TAG_const_type:
       this_type = read_tag_const_type (die, cu);
@@ -19694,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
@@ -19741,7 +19980,7 @@ guess_full_die_structure_name (struct die_info *die, struct dwarf2_cu *cu)
    prefix part in such case.  See
    http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47510.  */
 
-static char *
+static const char *
 anonymous_struct_prefix (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;
@@ -19754,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;
 
@@ -19794,7 +20031,7 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
   struct die_info *parent, *spec_die;
   struct dwarf2_cu *spec_cu;
   struct type *parent_type;
-  char *retval;
+  const char *retval;
 
   if (cu->language != language_cplus
       && cu->language != language_fortran && cu->language != language_d
@@ -20082,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;
 
@@ -20196,7 +20430,7 @@ dwarf_form_name (unsigned form)
   return name;
 }
 
-static char *
+static const char *
 dwarf_bool_name (unsigned mybool)
 {
   if (mybool)
@@ -20225,13 +20459,14 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
 
   print_spaces (indent, f);
   fprintf_unfiltered (f, "Die: %s (abbrev %d, offset 0x%x)\n",
-          dwarf_tag_name (die->tag), die->abbrev, die->offset.sect_off);
+                     dwarf_tag_name (die->tag), die->abbrev,
+                     to_underlying (die->sect_off));
 
   if (die->parent != NULL)
     {
       print_spaces (indent, f);
       fprintf_unfiltered (f, "  parent at offset: 0x%x\n",
-                         die->parent->offset.sect_off);
+                         to_underlying (die->parent->sect_off));
     }
 
   print_spaces (indent, f);
@@ -20327,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);
@@ -20390,7 +20629,8 @@ store_in_ref_table (struct die_info *die, struct dwarf2_cu *cu)
 {
   void **slot;
 
-  slot = htab_find_slot_with_hash (cu->die_hash, die, die->offset.sect_off,
+  slot = htab_find_slot_with_hash (cu->die_hash, die,
+                                  to_underlying (die->sect_off),
                                   INSERT);
 
   *slot = die;
@@ -20402,16 +20642,13 @@ store_in_ref_table (struct die_info *die, struct dwarf2_cu *cu)
 static sect_offset
 dwarf2_get_ref_die_offset (const struct attribute *attr)
 {
-  sect_offset retval = { DW_UNSND (attr) };
-
   if (attr_form_is_ref (attr))
-    return retval;
+    return (sect_offset) DW_UNSND (attr);
 
-  retval.sect_off = 0;
   complaint (&symfile_complaints,
             _("unsupported die ref attribute form: '%s'"),
             dwarf_form_name (attr->form));
-  return retval;
+  return {};
 }
 
 /* Return the constant value held by ATTR.  Return DEFAULT_VALUE if
@@ -20420,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
@@ -20468,7 +20705,7 @@ follow_die_ref_or_sig (struct die_info *src_die, const struct attribute *attr,
    Returns NULL if OFFSET is invalid.  */
 
 static struct die_info *
-follow_die_offset (sect_offset offset, int offset_in_dwz,
+follow_die_offset (sect_offset sect_off, int offset_in_dwz,
                   struct dwarf2_cu **ref_cu)
 {
   struct die_info temp_die;
@@ -20483,15 +20720,15 @@ follow_die_offset (sect_offset offset, int offset_in_dwz,
       /* .debug_types CUs cannot reference anything outside their CU.
         If they need to, they have to reference a signatured type via
         DW_FORM_ref_sig8.  */
-      if (! offset_in_cu_p (&cu->header, offset))
+      if (!offset_in_cu_p (&cu->header, sect_off))
        return NULL;
     }
   else if (offset_in_dwz != cu->per_cu->is_dwz
-          || ! offset_in_cu_p (&cu->header, offset))
+          || !offset_in_cu_p (&cu->header, sect_off))
     {
       struct dwarf2_per_cu_data *per_cu;
 
-      per_cu = dwarf2_find_containing_comp_unit (offset, offset_in_dwz,
+      per_cu = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
                                                 cu->objfile);
 
       /* If necessary, add it to the queue and load its DIEs.  */
@@ -20508,9 +20745,10 @@ follow_die_offset (sect_offset offset, int offset_in_dwz,
     }
 
   *ref_cu = target_cu;
-  temp_die.offset = offset;
+  temp_die.sect_off = sect_off;
   return (struct die_info *) htab_find_with_hash (target_cu->die_hash,
-                                                 &temp_die, offset.sect_off);
+                                                 &temp_die,
+                                                 to_underlying (sect_off));
 }
 
 /* Follow reference attribute ATTR of SRC_DIE.
@@ -20521,29 +20759,29 @@ static struct die_info *
 follow_die_ref (struct die_info *src_die, const struct attribute *attr,
                struct dwarf2_cu **ref_cu)
 {
-  sect_offset offset = dwarf2_get_ref_die_offset (attr);
+  sect_offset sect_off = dwarf2_get_ref_die_offset (attr);
   struct dwarf2_cu *cu = *ref_cu;
   struct die_info *die;
 
-  die = follow_die_offset (offset,
+  die = follow_die_offset (sect_off,
                           (attr->form == DW_FORM_GNU_ref_alt
                            || cu->per_cu->is_dwz),
                           ref_cu);
   if (!die)
     error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE "
           "at 0x%x [in module %s]"),
-          offset.sect_off, src_die->offset.sect_off,
+          to_underlying (sect_off), to_underlying (src_die->sect_off),
           objfile_name (cu->objfile));
 
   return die;
 }
 
-/* Return DWARF block referenced by DW_AT_location of DIE at OFFSET at PER_CU.
+/* Return DWARF block referenced by DW_AT_location of DIE at SECT_OFF at PER_CU.
    Returned value is intended for DW_OP_call*.  Returned
    dwarf2_locexpr_baton->data has lifetime of PER_CU->OBJFILE.  */
 
 struct dwarf2_locexpr_baton
-dwarf2_fetch_die_loc_sect_off (sect_offset offset,
+dwarf2_fetch_die_loc_sect_off (sect_offset sect_off,
                               struct dwarf2_per_cu_data *per_cu,
                               CORE_ADDR (*get_frame_pc) (void *baton),
                               void *baton)
@@ -20563,13 +20801,13 @@ dwarf2_fetch_die_loc_sect_off (sect_offset offset,
       /* We shouldn't get here for a dummy CU, but don't crash on the user.
         Instead just throw an error, not much else we can do.  */
       error (_("Dwarf Error: Dummy CU at 0x%x referenced in module %s"),
-            offset.sect_off, objfile_name (per_cu->objfile));
+            to_underlying (sect_off), objfile_name (per_cu->objfile));
     }
 
-  die = follow_die_offset (offset, per_cu->is_dwz, &cu);
+  die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
   if (!die)
     error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
-          offset.sect_off, objfile_name (per_cu->objfile));
+          to_underlying (sect_off), objfile_name (per_cu->objfile));
 
   attr = dwarf2_attr (die, DW_AT_location, cu);
   if (!attr)
@@ -20597,7 +20835,7 @@ dwarf2_fetch_die_loc_sect_off (sect_offset offset,
       if (!attr_form_is_block (attr))
        error (_("Dwarf Error: DIE at 0x%x referenced in module %s "
                 "is neither DW_FORM_block* nor DW_FORM_exprloc"),
-              offset.sect_off, objfile_name (per_cu->objfile));
+              to_underlying (sect_off), objfile_name (per_cu->objfile));
 
       retval.data = DW_BLOCK (attr)->data;
       retval.size = DW_BLOCK (attr)->size;
@@ -20618,9 +20856,9 @@ dwarf2_fetch_die_loc_cu_off (cu_offset offset_in_cu,
                             CORE_ADDR (*get_frame_pc) (void *baton),
                             void *baton)
 {
-  sect_offset offset = { per_cu->offset.sect_off + offset_in_cu.cu_off };
+  sect_offset sect_off = per_cu->sect_off + to_underlying (offset_in_cu);
 
-  return dwarf2_fetch_die_loc_sect_off (offset, per_cu, get_frame_pc, baton);
+  return dwarf2_fetch_die_loc_sect_off (sect_off, per_cu, get_frame_pc, baton);
 }
 
 /* Write a constant of a given type as target-ordered bytes into
@@ -20648,7 +20886,7 @@ write_constant_as_bytes (struct obstack *obstack,
    does not have a DW_AT_const_value, return NULL.  */
 
 const gdb_byte *
-dwarf2_fetch_constant_bytes (sect_offset offset,
+dwarf2_fetch_constant_bytes (sect_offset sect_off,
                             struct dwarf2_per_cu_data *per_cu,
                             struct obstack *obstack,
                             LONGEST *len)
@@ -20671,13 +20909,13 @@ dwarf2_fetch_constant_bytes (sect_offset offset,
       /* We shouldn't get here for a dummy CU, but don't crash on the user.
         Instead just throw an error, not much else we can do.  */
       error (_("Dwarf Error: Dummy CU at 0x%x referenced in module %s"),
-            offset.sect_off, objfile_name (per_cu->objfile));
+            to_underlying (sect_off), objfile_name (per_cu->objfile));
     }
 
-  die = follow_die_offset (offset, per_cu->is_dwz, &cu);
+  die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
   if (!die)
     error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
-          offset.sect_off, objfile_name (per_cu->objfile));
+          to_underlying (sect_off), objfile_name (per_cu->objfile));
 
 
   attr = dwarf2_attr (die, DW_AT_const_value, cu);
@@ -20754,6 +20992,7 @@ dwarf2_fetch_constant_bytes (sect_offset offset,
       break;
 
     case DW_FORM_sdata:
+    case DW_FORM_implicit_const:
       type = die_type (die, cu);
       result = write_constant_as_bytes (obstack, byte_order,
                                        type, DW_SND (attr), len);
@@ -20779,7 +21018,7 @@ dwarf2_fetch_constant_bytes (sect_offset offset,
    valid type for this die is found.  */
 
 struct type *
-dwarf2_fetch_die_type_sect_off (sect_offset offset,
+dwarf2_fetch_die_type_sect_off (sect_offset sect_off,
                                struct dwarf2_per_cu_data *per_cu)
 {
   struct dwarf2_cu *cu;
@@ -20793,7 +21032,7 @@ dwarf2_fetch_die_type_sect_off (sect_offset offset,
   if (!cu)
     return NULL;
 
-  die = follow_die_offset (offset, per_cu->is_dwz, &cu);
+  die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
   if (!die)
     return NULL;
 
@@ -20807,11 +21046,9 @@ struct type *
 dwarf2_get_die_type (cu_offset die_offset,
                     struct dwarf2_per_cu_data *per_cu)
 {
-  sect_offset die_offset_sect;
-
   dw2_setup (per_cu->objfile);
 
-  die_offset_sect.sect_off = per_cu->offset.sect_off + die_offset.cu_off;
+  sect_offset die_offset_sect = per_cu->sect_off + to_underlying (die_offset);
   return get_die_type_at_offset (die_offset_sect, per_cu);
 }
 
@@ -20839,10 +21076,10 @@ follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type,
 
   sig_cu = sig_type->per_cu.cu;
   gdb_assert (sig_cu != NULL);
-  gdb_assert (sig_type->type_offset_in_section.sect_off != 0);
-  temp_die.offset = sig_type->type_offset_in_section;
+  gdb_assert (to_underlying (sig_type->type_offset_in_section) != 0);
+  temp_die.sect_off = sig_type->type_offset_in_section;
   die = (struct die_info *) htab_find_with_hash (sig_cu->die_hash, &temp_die,
-                                                temp_die.offset.sect_off);
+                                                to_underlying (temp_die.sect_off));
   if (die)
     {
       /* For .gdb_index version 7 keep track of included TUs.
@@ -20885,7 +21122,7 @@ follow_die_sig (struct die_info *src_die, const struct attribute *attr,
     {
       error (_("Dwarf Error: Cannot find signatured DIE %s referenced"
                " from DIE at 0x%x [in module %s]"),
-             hex_string (signature), src_die->offset.sect_off,
+             hex_string (signature), to_underlying (src_die->sect_off),
             objfile_name ((*ref_cu)->objfile));
     }
 
@@ -20895,7 +21132,7 @@ follow_die_sig (struct die_info *src_die, const struct attribute *attr,
       dump_die_for_error (src_die);
       error (_("Dwarf Error: Problem reading signatured DIE %s referenced"
               " from DIE at 0x%x [in module %s]"),
-            hex_string (signature), src_die->offset.sect_off,
+            hex_string (signature), to_underlying (src_die->sect_off),
             objfile_name ((*ref_cu)->objfile));
     }
 
@@ -20922,7 +21159,7 @@ get_signatured_type (struct die_info *die, ULONGEST signature,
       complaint (&symfile_complaints,
                 _("Dwarf Error: Cannot find signatured DIE %s referenced"
                   " from DIE at 0x%x [in module %s]"),
-                hex_string (signature), die->offset.sect_off,
+                hex_string (signature), to_underlying (die->sect_off),
                 objfile_name (dwarf2_per_objfile->objfile));
       return build_error_marker_type (cu, die);
     }
@@ -20944,7 +21181,7 @@ get_signatured_type (struct die_info *die, ULONGEST signature,
          complaint (&symfile_complaints,
                     _("Dwarf Error: Cannot build signatured type %s"
                       " referenced from DIE at 0x%x [in module %s]"),
-                    hex_string (signature), die->offset.sect_off,
+                    hex_string (signature), to_underlying (die->sect_off),
                     objfile_name (dwarf2_per_objfile->objfile));
          type = build_error_marker_type (cu, die);
        }
@@ -20954,7 +21191,7 @@ get_signatured_type (struct die_info *die, ULONGEST signature,
       complaint (&symfile_complaints,
                 _("Dwarf Error: Problem reading signatured DIE %s referenced"
                   " from DIE at 0x%x [in module %s]"),
-                hex_string (signature), die->offset.sect_off,
+                hex_string (signature), to_underlying (die->sect_off),
                 objfile_name (dwarf2_per_objfile->objfile));
       type = build_error_marker_type (cu, die);
     }
@@ -20987,7 +21224,7 @@ get_DW_AT_signature_type (struct die_info *die, const struct attribute *attr,
       complaint (&symfile_complaints,
                 _("Dwarf Error: DW_AT_signature has bad form %s in DIE"
                   " at 0x%x [in module %s]"),
-                dwarf_form_name (attr->form), die->offset.sect_off,
+                dwarf_form_name (attr->form), to_underlying (die->sect_off),
                 objfile_name (dwarf2_per_objfile->objfile));
       return build_error_marker_type (cu, die);
     }
@@ -21368,15 +21605,17 @@ file_file_name (int file, struct line_header *lh)
 {
   /* Is the file number a valid index into the line header's file name
      table?  Remember that file numbers start with one, not zero.  */
-  if (1 <= file && file <= lh->num_file_names)
+  if (1 <= file && file <= lh->file_names.size ())
     {
-      struct file_entry *fe = &lh->file_names[file - 1];
+      const file_entry &fe = lh->file_names[file - 1];
 
-      if (IS_ABSOLUTE_PATH (fe->name) || fe->dir_index == 0
-         || lh->include_dirs == NULL)
-        return xstrdup (fe->name);
-      return concat (lh->include_dirs[fe->dir_index - 1], SLASH_STRING,
-                    fe->name, (char *) NULL);
+      if (!IS_ABSOLUTE_PATH (fe.name))
+       {
+         const char *dir = fe.include_dir (lh);
+         if (dir != NULL)
+           return concat (dir, SLASH_STRING, fe.name, (char *) NULL);
+       }
+      return xstrdup (fe.name);
     }
   else
     {
@@ -21405,7 +21644,7 @@ file_full_name (int file, struct line_header *lh, const char *comp_dir)
 {
   /* Is the file number a valid index into the line header's file name
      table?  Remember that file numbers start with one, not zero.  */
-  if (1 <= file && file <= lh->num_file_names)
+  if (1 <= file && file <= lh->file_names.size ())
     {
       char *relative = file_file_name (file, lh);
 
@@ -21446,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)
 {
@@ -21519,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 == ' ')
@@ -21537,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);
@@ -21566,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);
@@ -21690,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:
@@ -22331,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;
@@ -22487,7 +22716,7 @@ per_cu_header_read_in (struct comp_unit_head *cu_headerp,
   if (per_cu->cu)
     return &per_cu->cu->header;
 
-  info_ptr = per_cu->section->buffer + per_cu->offset.sect_off;
+  info_ptr = per_cu->section->buffer + to_underlying (per_cu->sect_off);
 
   memset (cu_headerp, 0, sizeof (*cu_headerp));
   read_comp_unit_head (cu_headerp, info_ptr, per_cu->section,
@@ -22563,7 +22792,7 @@ dwarf2_version (struct dwarf2_per_cu_data *per_cu)
    the DIE at OFFSET.  Raises an error on failure.  */
 
 static struct dwarf2_per_cu_data *
-dwarf2_find_containing_comp_unit (sect_offset offset,
+dwarf2_find_containing_comp_unit (sect_offset sect_off,
                                  unsigned int offset_in_dwz,
                                  struct objfile *objfile)
 {
@@ -22579,35 +22808,34 @@ dwarf2_find_containing_comp_unit (sect_offset offset,
       int mid = low + (high - low) / 2;
 
       mid_cu = dwarf2_per_objfile->all_comp_units[mid];
-      cu_off = &mid_cu->offset;
+      cu_off = &mid_cu->sect_off;
       if (mid_cu->is_dwz > offset_in_dwz
-         || (mid_cu->is_dwz == offset_in_dwz
-             && cu_off->sect_off >= offset.sect_off))
+         || (mid_cu->is_dwz == offset_in_dwz && *cu_off >= sect_off))
        high = mid;
       else
        low = mid + 1;
     }
   gdb_assert (low == high);
   this_cu = dwarf2_per_objfile->all_comp_units[low];
-  cu_off = &this_cu->offset;
-  if (this_cu->is_dwz != offset_in_dwz || cu_off->sect_off > offset.sect_off)
+  cu_off = &this_cu->sect_off;
+  if (this_cu->is_dwz != offset_in_dwz || *cu_off > sect_off)
     {
       if (low == 0 || this_cu->is_dwz != offset_in_dwz)
        error (_("Dwarf Error: could not find partial DIE containing "
-              "offset 0x%lx [in module %s]"),
-              (long) offset.sect_off, bfd_get_filename (objfile->obfd));
+              "offset 0x%x [in module %s]"),
+              to_underlying (sect_off), bfd_get_filename (objfile->obfd));
 
-      gdb_assert (dwarf2_per_objfile->all_comp_units[low-1]->offset.sect_off
-                 <= offset.sect_off);
+      gdb_assert (dwarf2_per_objfile->all_comp_units[low-1]->sect_off
+                 <= sect_off);
       return dwarf2_per_objfile->all_comp_units[low-1];
     }
   else
     {
       this_cu = dwarf2_per_objfile->all_comp_units[low];
       if (low == dwarf2_per_objfile->n_comp_units - 1
-         && offset.sect_off >= this_cu->offset.sect_off + this_cu->length)
-       error (_("invalid dwarf2 offset %u"), offset.sect_off);
-      gdb_assert (offset.sect_off < this_cu->offset.sect_off + this_cu->length);
+         && sect_off >= this_cu->sect_off + this_cu->length)
+       error (_("invalid dwarf2 offset %u"), to_underlying (sect_off));
+      gdb_assert (sect_off < this_cu->sect_off + this_cu->length);
       return this_cu;
     }
 }
@@ -22687,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
@@ -22783,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.
@@ -22812,7 +23017,7 @@ dwarf2_free_objfile (struct objfile *objfile)
 struct dwarf2_per_cu_offset_and_type
 {
   const struct dwarf2_per_cu_data *per_cu;
-  sect_offset offset;
+  sect_offset sect_off;
   struct type *type;
 };
 
@@ -22824,7 +23029,7 @@ per_cu_offset_and_type_hash (const void *item)
   const struct dwarf2_per_cu_offset_and_type *ofs
     = (const struct dwarf2_per_cu_offset_and_type *) item;
 
-  return (uintptr_t) ofs->per_cu + ofs->offset.sect_off;
+  return (uintptr_t) ofs->per_cu + to_underlying (ofs->sect_off);
 }
 
 /* Equality function for a dwarf2_per_cu_offset_and_type.  */
@@ -22838,7 +23043,7 @@ per_cu_offset_and_type_eq (const void *item_lhs, const void *item_rhs)
     = (const struct dwarf2_per_cu_offset_and_type *) item_rhs;
 
   return (ofs_lhs->per_cu == ofs_rhs->per_cu
-         && ofs_lhs->offset.sect_off == ofs_rhs->offset.sect_off);
+         && ofs_lhs->sect_off == ofs_rhs->sect_off);
 }
 
 /* Set the type associated with DIE to TYPE.  Save it in CU's hash
@@ -22893,9 +23098,9 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
   else if (attr != NULL)
     {
       complaint (&symfile_complaints,
-                _("DW_AT_allocated has the wrong form (%s) at DIE 0x%x"),
-                (attr != NULL ? dwarf_form_name (attr->form) : "n/a"),
-                die->offset.sect_off);
+                _("DW_AT_allocated has the wrong form (%s) at DIE 0x%x"),
+                (attr != NULL ? dwarf_form_name (attr->form) : "n/a"),
+                to_underlying (die->sect_off));
     }
 
   /* Read DW_AT_associated and set in type.  */
@@ -22908,9 +23113,9 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
   else if (attr != NULL)
     {
       complaint (&symfile_complaints,
-                _("DW_AT_associated has the wrong form (%s) at DIE 0x%x"),
-                (attr != NULL ? dwarf_form_name (attr->form) : "n/a"),
-                die->offset.sect_off);
+                _("DW_AT_associated has the wrong form (%s) at DIE 0x%x"),
+                (attr != NULL ? dwarf_form_name (attr->form) : "n/a"),
+                to_underlying (die->sect_off));
     }
 
   /* Read DW_AT_data_location and set in type.  */
@@ -22931,25 +23136,25 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
     }
 
   ofs.per_cu = cu->per_cu;
-  ofs.offset = die->offset;
+  ofs.sect_off = die->sect_off;
   ofs.type = type;
   slot = (struct dwarf2_per_cu_offset_and_type **)
     htab_find_slot (dwarf2_per_objfile->die_type_hash, &ofs, INSERT);
   if (*slot)
     complaint (&symfile_complaints,
               _("A problem internal to GDB: DIE 0x%x has type already set"),
-              die->offset.sect_off);
+              to_underlying (die->sect_off));
   *slot = XOBNEW (&objfile->objfile_obstack,
                  struct dwarf2_per_cu_offset_and_type);
   **slot = ofs;
   return type;
 }
 
-/* Look up the type for the die at OFFSET in PER_CU in die_type_hash,
+/* Look up the type for the die at SECT_OFF in PER_CU in die_type_hash,
    or return NULL if the die does not have a saved type.  */
 
 static struct type *
-get_die_type_at_offset (sect_offset offset,
+get_die_type_at_offset (sect_offset sect_off,
                        struct dwarf2_per_cu_data *per_cu)
 {
   struct dwarf2_per_cu_offset_and_type *slot, ofs;
@@ -22958,7 +23163,7 @@ get_die_type_at_offset (sect_offset offset,
     return NULL;
 
   ofs.per_cu = per_cu;
-  ofs.offset = offset;
+  ofs.sect_off = sect_off;
   slot = ((struct dwarf2_per_cu_offset_and_type *)
          htab_find (dwarf2_per_objfile->die_type_hash, &ofs));
   if (slot)
@@ -22973,7 +23178,7 @@ get_die_type_at_offset (sect_offset offset,
 static struct type *
 get_die_type (struct die_info *die, struct dwarf2_cu *cu)
 {
-  return get_die_type_at_offset (die->offset, cu->per_cu);
+  return get_die_type_at_offset (die->sect_off, cu->per_cu);
 }
 
 /* Add a dependence relationship from CU to REF_PER_CU.  */
@@ -23055,7 +23260,7 @@ partial_die_hash (const void *item)
   const struct partial_die_info *part_die
     = (const struct partial_die_info *) item;
 
-  return part_die->offset.sect_off;
+  return to_underlying (part_die->sect_off);
 }
 
 /* Trivial comparison function for partial_die_info structures: two DIEs
@@ -23069,7 +23274,7 @@ partial_die_eq (const void *item_lhs, const void *item_rhs)
   const struct partial_die_info *part_die_rhs
     = (const struct partial_die_info *) item_rhs;
 
-  return part_die_lhs->offset.sect_off == part_die_rhs->offset.sect_off;
+  return part_die_lhs->sect_off == part_die_rhs->sect_off;
 }
 
 static struct cmd_list_element *set_dwarf_cmdlist;
@@ -23122,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
@@ -23195,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);
     }
 }
 
@@ -23304,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.
@@ -23333,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;
@@ -23361,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.  */
@@ -23380,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);
+  }
+};
+
+/* 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 obstack OUTPUT, with
-   constant pool entries going into the obstack CPOOL.  */
+/* 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
        {
@@ -23495,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
@@ -23550,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.  */
@@ -23579,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,
@@ -23628,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);
 }
@@ -23675,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,
@@ -23684,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;
 };
 
@@ -23734,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,
@@ -23749,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,
-                         entry->per_cu.offset.sect_off);
-  obstack_grow (info->types_list, val, 8);
-  store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE,
-                         entry->type_offset_in_tu.cu_off);
-  obstack_grow (info->types_list, val, 8);
-  store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->signature);
-  obstack_grow (info->types_list, val, 8);
+  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.  */
 
@@ -23770,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;
@@ -23797,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"));
 
@@ -23817,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
@@ -23877,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,
-                             per_cu->offset.sect_off);
-      obstack_grow (&cu_list, val, 8);
-      store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, per_cu->length);
-      obstack_grow (&cu_list, val, 8);
+      cu_list.append_uint (8, BFD_ENDIAN_LITTLE,
+                          to_underlying (per_cu->sect_off));
+      cu_list.append_uint (8, BFD_ENDIAN_LITTLE, per_cu->length);
     }
 
   /* Dump the address map.  */
-  write_address_map (objfile, &addr_obstack, cu_index_htab.get ());
+  data_buf addr_vec;
+  write_address_map (objfile, addr_vec, cu_index_htab);
 
   /* Write out the .debug_type entries, if any.  */
+  data_buf types_cu_list;
   if (dwarf2_per_objfile->signatured_types)
     {
-      struct signatured_type_index_data sig_data;
+      signatured_type_index_data sig_data (types_cu_list,
+                                          psyms_seen);
 
       sig_data.objfile = objfile;
-      sig_data.symtab = symtab;
-      sig_data.types_list = &types_cu_list;
-      sig_data.psyms_seen = psyms_seen.get ();
+      sig_data.symtab = &symtab;
       sig_data.cu_index = dwarf2_per_objfile->n_comp_units;
       htab_traverse_noresize (dwarf2_per_objfile->signatured_types,
                              write_one_signatured_type, &sig_data);
@@ -23914,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.
@@ -23979,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;
 
@@ -24038,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.150448 seconds and 4 git commands to generate.