Introduce gdb::byte_vector, add allocator that default-initializes
[deliverable/binutils-gdb.git] / gdb / dwarf2read.c
index c070cd74302298d69bf3d88ff124899d477b5f3a..abe14b25fd37a07c602e1497b5398dd4af9d5dd0 100644 (file)
@@ -1,6 +1,6 @@
 /* DWARF 2 debugging format support for GDB.
 
-   Copyright (C) 1994-2016 Free Software Foundation, Inc.
+   Copyright (C) 1994-2017 Free Software Foundation, Inc.
 
    Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
    Inc.  with support from Florida State University (under contract
 #include "filestuff.h"
 #include "build-id.h"
 #include "namespace.h"
+#include "common/gdb_unlinker.h"
+#include "common/function-view.h"
+#include "common/gdb_optional.h"
+#include "common/underlying.h"
+#include "common/byte-vector.h"
 
 #include <fcntl.h>
 #include <sys/types.h>
 #include <algorithm>
+#include <unordered_set>
+#include <unordered_map>
 
 typedef struct symbol *symbolp;
 DEF_VEC_P (symbolp);
@@ -221,10 +228,13 @@ struct dwarf2_per_objfile
   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;
@@ -332,10 +342,13 @@ static const struct dwarf2_debug_sections dwarf2_elf_names =
   { ".debug_abbrev", ".zdebug_abbrev" },
   { ".debug_line", ".zdebug_line" },
   { ".debug_loc", ".zdebug_loc" },
+  { ".debug_loclists", ".zdebug_loclists" },
   { ".debug_macinfo", ".zdebug_macinfo" },
   { ".debug_macro", ".zdebug_macro" },
   { ".debug_str", ".zdebug_str" },
+  { ".debug_line_str", ".zdebug_line_str" },
   { ".debug_ranges", ".zdebug_ranges" },
+  { ".debug_rnglists", ".zdebug_rnglists" },
   { ".debug_types", ".zdebug_types" },
   { ".debug_addr", ".zdebug_addr" },
   { ".debug_frame", ".zdebug_frame" },
@@ -352,6 +365,7 @@ static const struct dwop_section_names
   struct dwarf2_section_names info_dwo;
   struct dwarf2_section_names line_dwo;
   struct dwarf2_section_names loc_dwo;
+  struct dwarf2_section_names loclists_dwo;
   struct dwarf2_section_names macinfo_dwo;
   struct dwarf2_section_names macro_dwo;
   struct dwarf2_section_names str_dwo;
@@ -366,6 +380,7 @@ dwop_section_names =
   { ".debug_info.dwo", ".zdebug_info.dwo" },
   { ".debug_line.dwo", ".zdebug_line.dwo" },
   { ".debug_loc.dwo", ".zdebug_loc.dwo" },
+  { ".debug_loclists.dwo", ".zdebug_loclists.dwo" },
   { ".debug_macinfo.dwo", ".zdebug_macinfo.dwo" },
   { ".debug_macro.dwo", ".zdebug_macro.dwo" },
   { ".debug_str.dwo", ".zdebug_str.dwo" },
@@ -385,7 +400,7 @@ struct comp_unit_head
   short version;
   unsigned char addr_size;
   unsigned char signed_addr_p;
-  sect_offset abbrev_offset;
+  sect_offset abbrev_sect_off;
 
   /* Size of file offsets; either 4 or 8.  */
   unsigned int offset_size;
@@ -393,13 +408,22 @@ struct comp_unit_head
   /* Size of the length field; either 4 or 12.  */
   unsigned int initial_length_size;
 
+  enum dwarf_unit_type unit_type;
+
   /* Offset to the first byte of this compilation unit header in the
      .debug_info section, for resolving relative reference dies.  */
-  sect_offset offset;
+  sect_offset sect_off;
 
   /* Offset to first die in this cu from the start of the cu.
      This will be the first byte following the compilation unit header.  */
-  cu_offset first_die_offset;
+  cu_offset first_die_cu_offset;
+
+  /* 64-bit signature of this type unit - it is valid only for
+     UNIT_TYPE DW_UT_type.  */
+  ULONGEST signature;
+
+  /* For types, offset in the type's DIE of the type defined by this TU.  */
+  cu_offset type_cu_offset_in_tu;
 };
 
 /* Type used for delaying computation of method physnames.
@@ -568,9 +592,12 @@ struct dwarf2_per_cu_data
      initial_length_size.
      If the DIE refers to a DWO file, this is always of the original die,
      not the DWO file.  */
-  sect_offset offset;
+  sect_offset sect_off;
   unsigned int length;
 
+  /* DWARF standard version this data has been read from (such as 4 or 5).  */
+  short dwarf_version;
+
   /* Flag indicating this compilation unit will be read in before
      any of the current compilation units are processed.  */
   unsigned int queued : 1;
@@ -704,7 +731,7 @@ struct stmt_list_hash
   struct dwo_unit *dwo_unit;
 
   /* Offset in .debug_line or .debug_line.dwo.  */
-  sect_offset line_offset;
+  sect_offset line_sect_off;
 };
 
 /* Each element of dwarf2_per_objfile->type_unit_groups is a pointer to
@@ -755,6 +782,7 @@ struct dwo_sections
   struct dwarf2_section_info abbrev;
   struct dwarf2_section_info line;
   struct dwarf2_section_info loc;
+  struct dwarf2_section_info loclists;
   struct dwarf2_section_info macinfo;
   struct dwarf2_section_info macro;
   struct dwarf2_section_info str;
@@ -779,8 +807,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.  */
@@ -1029,16 +1057,46 @@ typedef void (die_reader_func_ftype) (const struct die_reader_specs *reader,
                                      int has_children,
                                      void *data);
 
+/* A 1-based directory index.  This is a strong typedef to prevent
+   accidentally using a directory index as a 0-based index into an
+   array/vector.  */
+enum class dir_index : unsigned int {};
+
+/* Likewise, a 1-based file name index.  */
+enum class file_name_index : unsigned int {};
+
 struct file_entry
 {
-  const char *name;
-  unsigned int dir_index;
-  unsigned int mod_time;
-  unsigned int length;
-  /* Non-zero if referenced by the Line Number Program.  */
-  int included_p;
+  file_entry () = default;
+
+  file_entry (const char *name_, dir_index d_index_,
+             unsigned int mod_time_, unsigned int length_)
+    : name (name_),
+      d_index (d_index_),
+      mod_time (mod_time_),
+      length (length_)
+  {}
+
+  /* Return the include directory at D_INDEX stored in LH.  Returns
+     NULL if D_INDEX is out of bounds.  */
+  const char *include_dir (const line_header *lh) const;
+
+  /* The file name.  Note this is an observing pointer.  The memory is
+     owned by debug_line_buffer.  */
+  const char *name {};
+
+  /* The directory index (1-based).  */
+  dir_index d_index {};
+
+  unsigned int mod_time {};
+
+  unsigned int length {};
+
+  /* True if referenced by the Line Number Program.  */
+  bool included_p {};
+
   /* The associated symbol table, if any.  */
-  struct symtab *symtab;
+  struct symtab *symtab {};
 };
 
 /* The line number information for a compilation unit (found in the
@@ -1046,52 +1104,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;
@@ -1105,6 +1210,9 @@ struct partial_die_info
     unsigned int has_pc_info : 1;
     unsigned int may_be_inlined : 1;
 
+    /* This DIE has been marked DW_AT_main_subprogram.  */
+    unsigned int main_subprogram : 1;
+
     /* Flag set if the SCOPE field of this structure has been
        computed.  */
     unsigned int scope_set : 1;
@@ -1146,7 +1254,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.  */
@@ -1184,6 +1292,9 @@ struct attr_abbrev
   {
     ENUM_BITFIELD(dwarf_attribute) name : 16;
     ENUM_BITFIELD(dwarf_form) form : 16;
+
+    /* It is valid only if FORM is DW_FORM_implicit_const.  */
+    LONGEST implicit_const;
   };
 
 /* Size of abbrev_table.abbrev_hash_table.  */
@@ -1195,7 +1306,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;
@@ -1250,7 +1361,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
@@ -1503,9 +1614,11 @@ static const char *read_indirect_string (bfd *, const gdb_byte *,
                                         const struct comp_unit_head *,
                                         unsigned int *);
 
-static const char *read_indirect_string_from_dwz (struct dwz_file *, LONGEST);
+static const char *read_indirect_line_string (bfd *, const gdb_byte *,
+                                             const struct comp_unit_head *,
+                                             unsigned int *);
 
-static ULONGEST read_unsigned_leb128 (bfd *, const gdb_byte *, unsigned int *);
+static const char *read_indirect_string_from_dwz (struct dwz_file *, LONGEST);
 
 static LONGEST read_signed_leb128 (bfd *, const gdb_byte *, unsigned int *);
 
@@ -1535,10 +1648,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 *,
@@ -1717,7 +1828,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);
 
@@ -1802,7 +1913,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);
@@ -1854,18 +1965,39 @@ static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu,
 
 static void process_queue (void);
 
-static void find_file_and_directory (struct die_info *die,
-                                    struct dwarf2_cu *cu,
-                                    const char **name, const char **comp_dir);
+/* The return type of find_file_and_directory.  Note, the enclosed
+   string pointers are only valid while this object is valid.  */
+
+struct file_and_directory
+{
+  /* The filename.  This is never NULL.  */
+  const char *name;
+
+  /* The compilation directory.  NULL if not known.  If we needed to
+     compute a new string, this points to COMP_DIR_STORAGE, otherwise,
+     points directly to the DW_AT_comp_dir string attribute owned by
+     the obstack that owns the DIE.  */
+  const char *comp_dir;
+
+  /* If we needed to build a new string for comp_dir, this is what
+     owns the storage.  */
+  std::string comp_dir_storage;
+};
+
+static file_and_directory find_file_and_directory (struct die_info *die,
+                                                  struct dwarf2_cu *cu);
 
 static char *file_full_name (int file, struct line_header *lh,
                             const char *comp_dir);
 
+/* Expected enum dwarf_unit_type for read_comp_unit_head.  */
+enum class rcuh_kind { COMPILE, TYPE };
+
 static const gdb_byte *read_and_check_comp_unit_head
   (struct comp_unit_head *header,
    struct dwarf2_section_info *section,
    struct dwarf2_section_info *abbrev_section, const gdb_byte *info_ptr,
-   int is_debug_types_section);
+   rcuh_kind section_kind);
 
 static void init_cutu_and_read_dies
   (struct dwarf2_per_cu_data *this_cu, struct abbrev_table *abbrev_table,
@@ -1973,7 +2105,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.  */
@@ -1994,7 +2126,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);
 }
 
@@ -2017,7 +2149,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
@@ -2220,6 +2352,11 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
       dwarf2_per_objfile->loc.s.section = sectp;
       dwarf2_per_objfile->loc.size = bfd_get_section_size (sectp);
     }
+  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);
+    }
   else if (section_is_p (sectp->name, &names->macinfo))
     {
       dwarf2_per_objfile->macinfo.s.section = sectp;
@@ -2235,6 +2372,11 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
       dwarf2_per_objfile->str.s.section = sectp;
       dwarf2_per_objfile->str.size = bfd_get_section_size (sectp);
     }
+  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);
+    }
   else if (section_is_p (sectp->name, &names->addr))
     {
       dwarf2_per_objfile->addr.s.section = sectp;
@@ -2255,6 +2397,11 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
       dwarf2_per_objfile->ranges.s.section = sectp;
       dwarf2_per_objfile->ranges.size = bfd_get_section_size (sectp);
     }
+  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);
+    }
   else if (section_is_p (sectp->name, &names->types))
     {
       struct dwarf2_section_info type_section;
@@ -2476,7 +2623,6 @@ locate_dwz_sections (bfd *abfd, asection *sectp, void *arg)
 static struct dwz_file *
 dwarf2_get_dwz_file (void)
 {
-  bfd *dwz_bfd;
   char *data;
   struct cleanup *cleanup;
   const char *filename;
@@ -2504,30 +2650,24 @@ 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);
-
-      rel = concat (abs, SLASH_STRING, filename, (char *) NULL);
-      make_cleanup (xfree, rel);
-      filename = rel;
+      abs_storage = ldirname (abs) + SLASH_STRING + filename;
+      filename = abs_storage.c_str ();
     }
 
   /* First try the file name given in the section.  If that doesn't
      work, try to use the build-id instead.  */
-  dwz_bfd = gdb_bfd_open (filename, gnutarget, -1);
+  gdb_bfd_ref_ptr dwz_bfd (gdb_bfd_open (filename, gnutarget, -1));
   if (dwz_bfd != NULL)
     {
-      if (!build_id_verify (dwz_bfd, buildid_len, buildid))
-       {
-         gdb_bfd_unref (dwz_bfd);
-         dwz_bfd = NULL;
-       }
+      if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
+       dwz_bfd.release ();
     }
 
   if (dwz_bfd == NULL)
@@ -2539,13 +2679,13 @@ dwarf2_get_dwz_file (void)
 
   result = OBSTACK_ZALLOC (&dwarf2_per_objfile->objfile->objfile_obstack,
                           struct dwz_file);
-  result->dwz_bfd = dwz_bfd;
+  result->dwz_bfd = dwz_bfd.release ();
 
-  bfd_map_over_sections (dwz_bfd, locate_dwz_sections, result);
+  bfd_map_over_sections (result->dwz_bfd, locate_dwz_sections, result);
 
   do_cleanups (cleanup);
 
-  gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, dwz_bfd);
+  gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, result->dwz_bfd);
   dwarf2_per_objfile->dwz_file = result;
   return result;
 }
@@ -2606,7 +2746,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;
 }
 
@@ -2622,7 +2762,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.  */
@@ -2748,7 +2888,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);
@@ -2809,17 +2949,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;
@@ -2878,23 +3018,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,
@@ -3284,13 +3427,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);
 
@@ -3303,21 +3443,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)
@@ -3336,21 +3477,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;
 }
 
@@ -3446,8 +3585,7 @@ static int
 dw2_map_expand_apply (struct objfile *objfile,
                      struct dwarf2_per_cu_data *per_cu,
                      const char *name, const char *real_path,
-                     int (*callback) (struct symtab *, void *),
-                     void *data)
+                     gdb::function_view<bool (symtab *)> callback)
 {
   struct compunit_symtab *last_made = objfile->compunit_symtabs;
 
@@ -3459,17 +3597,16 @@ dw2_map_expand_apply (struct objfile *objfile,
      all of them.  */
   dw2_instantiate_symtab (per_cu);
 
-  return iterate_over_some_symtabs (name, real_path, callback, data,
-                                   objfile->compunit_symtabs, last_made);
+  return iterate_over_some_symtabs (name, real_path, objfile->compunit_symtabs,
+                                   last_made, callback);
 }
 
 /* Implementation of the map_symtabs_matching_filename method.  */
 
-static int
-dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
-                                  const char *real_path,
-                                  int (*callback) (struct symtab *, void *),
-                                  void *data)
+static bool
+dw2_map_symtabs_matching_filename
+  (struct objfile *objfile, const char *name, const char *real_path,
+   gdb::function_view<bool (symtab *)> callback)
 {
   int i;
   const char *name_basename = lbasename (name);
@@ -3501,8 +3638,8 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
          if (compare_filenames_for_search (this_name, name))
            {
              if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
-                                       callback, data))
-               return 1;
+                                       callback))
+               return true;
              continue;
            }
 
@@ -3516,8 +3653,8 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
          if (compare_filenames_for_search (this_real_name, name))
            {
              if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
-                                       callback, data))
-               return 1;
+                                       callback))
+               return true;
              continue;
            }
 
@@ -3529,15 +3666,15 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
                  && FILENAME_CMP (real_path, this_real_name) == 0)
                {
                  if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
-                                           callback, data))
-                   return 1;
+                                           callback))
+                   return true;
                  continue;
                }
            }
        }
     }
 
-  return 0;
+  return false;
 }
 
 /* Struct used to manage iterating over all CUs looking for a symbol.  */
@@ -3875,11 +4012,10 @@ dw2_map_matching_symbols (struct objfile *objfile,
 static void
 dw2_expand_symtabs_matching
   (struct objfile *objfile,
-   expand_symtabs_file_matcher_ftype *file_matcher,
-   expand_symtabs_symbol_matcher_ftype *symbol_matcher,
-   expand_symtabs_exp_notify_ftype *expansion_notify,
-   enum search_domain kind,
-   void *data)
+   gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
+   gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
+   gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+   enum search_domain kind)
 {
   int i;
   offset_type iter;
@@ -3894,17 +4030,12 @@ dw2_expand_symtabs_matching
 
   if (file_matcher != NULL)
     {
-      struct cleanup *cleanup;
-      htab_t visited_found, visited_not_found;
-
-      visited_found = htab_create_alloc (10,
-                                        htab_hash_pointer, htab_eq_pointer,
-                                        NULL, xcalloc, xfree);
-      cleanup = make_cleanup_htab_delete (visited_found);
-      visited_not_found = htab_create_alloc (10,
-                                            htab_hash_pointer, htab_eq_pointer,
-                                            NULL, xcalloc, xfree);
-      make_cleanup_htab_delete (visited_not_found);
+      htab_up visited_found (htab_create_alloc (10, htab_hash_pointer,
+                                               htab_eq_pointer,
+                                               NULL, xcalloc, xfree));
+      htab_up visited_not_found (htab_create_alloc (10, htab_hash_pointer,
+                                                   htab_eq_pointer,
+                                                   NULL, xcalloc, xfree));
 
       /* The rule is CUs specify all the files, including those used by
         any TU, so there's no need to scan TUs here.  */
@@ -3928,9 +4059,9 @@ dw2_expand_symtabs_matching
          if (file_data == NULL)
            continue;
 
-         if (htab_find (visited_not_found, file_data) != NULL)
+         if (htab_find (visited_not_found.get (), file_data) != NULL)
            continue;
-         else if (htab_find (visited_found, file_data) != NULL)
+         else if (htab_find (visited_found.get (), file_data) != NULL)
            {
              per_cu->v.quick->mark = 1;
              continue;
@@ -3940,7 +4071,7 @@ dw2_expand_symtabs_matching
            {
              const char *this_real_name;
 
-             if (file_matcher (file_data->file_names[j], data, 0))
+             if (file_matcher (file_data->file_names[j], false))
                {
                  per_cu->v.quick->mark = 1;
                  break;
@@ -3950,11 +4081,11 @@ dw2_expand_symtabs_matching
                 files are involved, do a quick comparison of the basenames.  */
              if (!basenames_may_differ
                  && !file_matcher (lbasename (file_data->file_names[j]),
-                                   data, 1))
+                                   true))
                continue;
 
              this_real_name = dw2_get_real_path (objfile, file_data, j);
-             if (file_matcher (this_real_name, data, 0))
+             if (file_matcher (this_real_name, false))
                {
                  per_cu->v.quick->mark = 1;
                  break;
@@ -3962,13 +4093,11 @@ dw2_expand_symtabs_matching
            }
 
          slot = htab_find_slot (per_cu->v.quick->mark
-                                ? visited_found
-                                : visited_not_found,
+                                ? visited_found.get ()
+                                : visited_not_found.get (),
                                 file_data, INSERT);
          *slot = file_data;
        }
-
-      do_cleanups (cleanup);
     }
 
   for (iter = 0; iter < index->symbol_table_slots; ++iter)
@@ -3985,7 +4114,7 @@ dw2_expand_symtabs_matching
 
       name = index->constant_pool + MAYBE_SWAP (index->symbol_table[idx]);
 
-      if (! (*symbol_matcher) (name, data))
+      if (!symbol_matcher (name))
        continue;
 
       /* The name was matched, now expand corresponding CUs that were
@@ -4063,8 +4192,7 @@ dw2_expand_symtabs_matching
                  && symtab_was_null
                  && per_cu->v.quick->compunit_symtab != NULL)
                {
-                 expansion_notify (per_cu->v.quick->compunit_symtab,
-                                   data);
+                 expansion_notify (per_cu->v.quick->compunit_symtab);
                }
            }
        }
@@ -4135,11 +4263,9 @@ dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
                          void *data, int need_fullname)
 {
   int i;
-  struct cleanup *cleanup;
-  htab_t visited = htab_create_alloc (10, htab_hash_pointer, htab_eq_pointer,
-                                     NULL, xcalloc, xfree);
+  htab_up visited (htab_create_alloc (10, htab_hash_pointer, htab_eq_pointer,
+                                     NULL, xcalloc, xfree));
 
-  cleanup = make_cleanup_htab_delete (visited);
   dw2_setup (objfile);
 
   /* The rule is CUs specify all the files, including those used by
@@ -4152,7 +4278,8 @@ dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
 
       if (per_cu->v.quick->compunit_symtab)
        {
-         void **slot = htab_find_slot (visited, per_cu->v.quick->file_names,
+         void **slot = htab_find_slot (visited.get (),
+                                       per_cu->v.quick->file_names,
                                        INSERT);
 
          *slot = per_cu->v.quick->file_names;
@@ -4174,7 +4301,7 @@ dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
       if (file_data == NULL)
        continue;
 
-      slot = htab_find_slot (visited, file_data, INSERT);
+      slot = htab_find_slot (visited.get (), file_data, INSERT);
       if (*slot)
        {
          /* Already visited.  */
@@ -4193,8 +4320,6 @@ dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
          (*fun) (file_data->file_names[j], this_real_name, data);
        }
     }
-
-  do_cleanups (cleanup);
 }
 
 static int
@@ -4281,10 +4406,9 @@ dwarf2_build_psymtabs (struct objfile *objfile)
       /* This isn't really ideal: all the data we allocate on the
         objfile's obstack is still uselessly kept around.  However,
         freeing it seems unsafe.  */
-      struct cleanup *cleanups = make_cleanup_discard_psymtabs (objfile);
-
+      psymtab_discarder psymtabs (objfile);
       dwarf2_build_psymtabs_hard (objfile);
-      discard_cleanups (cleanups);
+      psymtabs.keep ();
     }
   CATCH (except, RETURN_MASK_ERROR)
     {
@@ -4301,15 +4425,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
@@ -4344,15 +4468,20 @@ dwarf2_find_base_address (struct die_info *die, struct dwarf2_cu *cu)
 }
 
 /* Read in the comp unit header information from the debug_info at info_ptr.
+   Use rcuh_kind::COMPILE as the default type if not known by the caller.
    NOTE: This leaves members offset, first_die_offset to be filled in
    by the caller.  */
 
 static const gdb_byte *
 read_comp_unit_head (struct comp_unit_head *cu_header,
-                    const gdb_byte *info_ptr, bfd *abfd)
+                    const gdb_byte *info_ptr,
+                    struct dwarf2_section_info *section,
+                    rcuh_kind section_kind)
 {
   int signed_addr;
   unsigned int bytes_read;
+  const char *filename = get_section_file_name (section);
+  bfd *abfd = get_section_bfd_owner (section);
 
   cu_header->length = read_initial_length (abfd, info_ptr, &bytes_read);
   cu_header->initial_length_size = bytes_read;
@@ -4360,17 +4489,75 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
   info_ptr += bytes_read;
   cu_header->version = read_2_bytes (abfd, info_ptr);
   info_ptr += 2;
-  cu_header->abbrev_offset.sect_off = read_offset (abfd, info_ptr, cu_header,
-                                            &bytes_read);
+  if (cu_header->version < 5)
+    switch (section_kind)
+      {
+      case rcuh_kind::COMPILE:
+       cu_header->unit_type = DW_UT_compile;
+       break;
+      case rcuh_kind::TYPE:
+       cu_header->unit_type = DW_UT_type;
+       break;
+      default:
+       internal_error (__FILE__, __LINE__,
+                       _("read_comp_unit_head: invalid section_kind"));
+      }
+  else
+    {
+      cu_header->unit_type = static_cast<enum dwarf_unit_type>
+                                                (read_1_byte (abfd, info_ptr));
+      info_ptr += 1;
+      switch (cu_header->unit_type)
+       {
+       case DW_UT_compile:
+         if (section_kind != rcuh_kind::COMPILE)
+           error (_("Dwarf Error: wrong unit_type in compilation unit header "
+                  "(is DW_UT_compile, should be DW_UT_type) [in module %s]"),
+                  filename);
+         break;
+       case DW_UT_type:
+         section_kind = rcuh_kind::TYPE;
+         break;
+       default:
+         error (_("Dwarf Error: wrong unit_type in compilation unit header "
+                "(is %d, should be %d or %d) [in module %s]"),
+                cu_header->unit_type, DW_UT_compile, DW_UT_type, filename);
+       }
+
+      cu_header->addr_size = read_1_byte (abfd, info_ptr);
+      info_ptr += 1;
+    }
+  cu_header->abbrev_sect_off = (sect_offset) read_offset (abfd, info_ptr,
+                                                         cu_header,
+                                                         &bytes_read);
   info_ptr += bytes_read;
-  cu_header->addr_size = read_1_byte (abfd, info_ptr);
-  info_ptr += 1;
+  if (cu_header->version < 5)
+    {
+      cu_header->addr_size = read_1_byte (abfd, info_ptr);
+      info_ptr += 1;
+    }
   signed_addr = bfd_get_sign_extend_vma (abfd);
   if (signed_addr < 0)
     internal_error (__FILE__, __LINE__,
                    _("read_comp_unit_head: dwarf from non elf file"));
   cu_header->signed_addr_p = signed_addr;
 
+  if (section_kind == rcuh_kind::TYPE)
+    {
+      LONGEST type_offset;
+
+      cu_header->signature = read_8_bytes (abfd, info_ptr);
+      info_ptr += 8;
+
+      type_offset = read_offset (abfd, info_ptr, cu_header, &bytes_read);
+      info_ptr += bytes_read;
+      cu_header->type_cu_offset_in_tu = (cu_offset) type_offset;
+      if (to_underlying (cu_header->type_cu_offset_in_tu) != type_offset)
+       error (_("Dwarf Error: Too big type_offset in compilation unit "
+              "header (is %s) [in module %s]"), plongest (type_offset),
+              filename);
+    }
+
   return info_ptr;
 }
 
@@ -4401,25 +4588,26 @@ error_check_comp_unit_head (struct comp_unit_head *header,
 {
   const char *filename = get_section_file_name (section);
 
-  if (header->version != 2 && header->version != 3 && header->version != 4)
+  if (header->version < 2 || header->version > 5)
     error (_("Dwarf Error: wrong version in compilation unit header "
-          "(is %d, should be 2, 3, or 4) [in module %s]"), header->version,
+          "(is %d, should be 2, 3, 4 or 5) [in module %s]"), header->version,
           filename);
 
-  if (header->abbrev_offset.sect_off
+  if (to_underlying (header->abbrev_sect_off)
       >= dwarf2_section_size (dwarf2_per_objfile->objfile, abbrev_section))
-    error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header "
-          "(offset 0x%lx + 6) [in module %s]"),
-          (long) header->abbrev_offset.sect_off, (long) header->offset.sect_off,
+    error (_("Dwarf Error: bad offset (0x%x) in compilation unit header "
+          "(offset 0x%x + 6) [in module %s]"),
+          to_underlying (header->abbrev_sect_off),
+          to_underlying (header->sect_off),
           filename);
 
-  /* Cast to unsigned long to use 64-bit arithmetic when possible to
+  /* Cast to ULONGEST to use 64-bit arithmetic when possible to
      avoid potential 32-bit overflow.  */
-  if (((unsigned long) header->offset.sect_off + get_cu_length (header))
+  if (((ULONGEST) header->sect_off + get_cu_length (header))
       > section->size)
-    error (_("Dwarf Error: bad length (0x%lx) in compilation unit header "
-          "(offset 0x%lx + 0) [in module %s]"),
-          (long) header->length, (long) header->offset.sect_off,
+    error (_("Dwarf Error: bad length (0x%x) in compilation unit header "
+          "(offset 0x%x + 0) [in module %s]"),
+          header->length, to_underlying (header->sect_off),
           filename);
 }
 
@@ -4432,56 +4620,16 @@ read_and_check_comp_unit_head (struct comp_unit_head *header,
                               struct dwarf2_section_info *section,
                               struct dwarf2_section_info *abbrev_section,
                               const gdb_byte *info_ptr,
-                              int is_debug_types_section)
-{
-  const gdb_byte *beg_of_comp_unit = info_ptr;
-  bfd *abfd = get_section_bfd_owner (section);
-
-  header->offset.sect_off = beg_of_comp_unit - section->buffer;
-
-  info_ptr = read_comp_unit_head (header, info_ptr, abfd);
-
-  /* If we're reading a type unit, skip over the signature and
-     type_offset fields.  */
-  if (is_debug_types_section)
-    info_ptr += 8 /*signature*/ + header->offset_size;
-
-  header->first_die_offset.cu_off = info_ptr - beg_of_comp_unit;
-
-  error_check_comp_unit_head (header, section, abbrev_section);
-
-  return info_ptr;
-}
-
-/* Read in the types comp unit header information from .debug_types entry at
-   types_ptr.  The result is a pointer to one past the end of the header.  */
-
-static const gdb_byte *
-read_and_check_type_unit_head (struct comp_unit_head *header,
-                              struct dwarf2_section_info *section,
-                              struct dwarf2_section_info *abbrev_section,
-                              const gdb_byte *info_ptr,
-                              ULONGEST *signature,
-                              cu_offset *type_offset_in_tu)
+                              rcuh_kind section_kind)
 {
   const gdb_byte *beg_of_comp_unit = info_ptr;
   bfd *abfd = get_section_bfd_owner (section);
 
-  header->offset.sect_off = beg_of_comp_unit - section->buffer;
+  header->sect_off = (sect_offset) (beg_of_comp_unit - section->buffer);
 
-  info_ptr = read_comp_unit_head (header, info_ptr, abfd);
+  info_ptr = read_comp_unit_head (header, info_ptr, section, section_kind);
 
-  /* If we're reading a type unit, skip over the signature and
-     type_offset fields.  */
-  if (signature != NULL)
-    *signature = read_8_bytes (abfd, info_ptr);
-  info_ptr += 8;
-  if (type_offset_in_tu != NULL)
-    type_offset_in_tu->cu_off = read_offset_1 (abfd, info_ptr,
-                                              header->offset_size);
-  info_ptr += header->offset_size;
-
-  header->first_die_offset.cu_off = info_ptr - beg_of_comp_unit;
+  header->first_die_cu_offset = (cu_offset) (info_ptr - beg_of_comp_unit);
 
   error_check_comp_unit_head (header, section, abbrev_section);
 
@@ -4492,20 +4640,28 @@ read_and_check_type_unit_head (struct comp_unit_head *header,
 
 static sect_offset
 read_abbrev_offset (struct dwarf2_section_info *section,
-                   sect_offset offset)
+                   sect_offset sect_off)
 {
   bfd *abfd = get_section_bfd_owner (section);
   const gdb_byte *info_ptr;
   unsigned int initial_length_size, offset_size;
-  sect_offset abbrev_offset;
+  uint16_t version;
 
   dwarf2_read_section (dwarf2_per_objfile->objfile, section);
-  info_ptr = section->buffer + offset.sect_off;
+  info_ptr = section->buffer + to_underlying (sect_off);
   read_initial_length (abfd, info_ptr, &initial_length_size);
   offset_size = initial_length_size == 4 ? 4 : 8;
-  info_ptr += initial_length_size + 2 /*version*/;
-  abbrev_offset.sect_off = read_offset_1 (abfd, info_ptr, offset_size);
-  return abbrev_offset;
+  info_ptr += initial_length_size;
+
+  version = read_2_bytes (abfd, info_ptr);
+  info_ptr += 2;
+  if (version >= 5)
+    {
+      /* Skip unit type and address size.  */
+      info_ptr += 2;
+    }
+
+  return (sect_offset) read_offset_1 (abfd, info_ptr, offset_size);
 }
 
 /* Allocate a new partial symtab for file named NAME and mark this new
@@ -4554,19 +4710,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
@@ -4616,167 +4770,177 @@ add_signatured_type_cu_to_table (void **slot, void *datum)
   return 1;
 }
 
-/* Create the hash table of all entries in the .debug_types
-   (or .debug_types.dwo) section(s).
-   If reading a DWO file, then DWO_FILE is a pointer to the DWO file object,
-   otherwise it is NULL.
-
-   The result is a pointer to the hash table or NULL if there are no types.
-
-   Note: This function processes DWO files only, not DWP files.  */
+/* A helper for create_debug_types_hash_table.  Read types from SECTION
+   and fill them into TYPES_HTAB.  It will process only type units,
+   therefore DW_UT_type.  */
 
-static htab_t
-create_debug_types_hash_table (struct dwo_file *dwo_file,
-                              VEC (dwarf2_section_info_def) *types)
+static void
+create_debug_type_hash_table (struct dwo_file *dwo_file,
+                             dwarf2_section_info *section, htab_t &types_htab,
+                             rcuh_kind section_kind)
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
-  htab_t types_htab = NULL;
-  int ix;
-  struct dwarf2_section_info *section;
   struct dwarf2_section_info *abbrev_section;
-
-  if (VEC_empty (dwarf2_section_info_def, types))
-    return NULL;
+  bfd *abfd;
+  const gdb_byte *info_ptr, *end_ptr;
 
   abbrev_section = (dwo_file != NULL
                    ? &dwo_file->sections.abbrev
                    : &dwarf2_per_objfile->abbrev);
 
   if (dwarf_read_debug)
-    fprintf_unfiltered (gdb_stdlog, "Reading .debug_types%s for %s:\n",
-                       dwo_file ? ".dwo" : "",
+    fprintf_unfiltered (gdb_stdlog, "Reading %s for %s:\n",
+                       get_section_name (section),
                        get_section_file_name (abbrev_section));
 
-  for (ix = 0;
-       VEC_iterate (dwarf2_section_info_def, types, ix, section);
-       ++ix)
-    {
-      bfd *abfd;
-      const gdb_byte *info_ptr, *end_ptr;
+  dwarf2_read_section (objfile, section);
+  info_ptr = section->buffer;
 
-      dwarf2_read_section (objfile, section);
-      info_ptr = section->buffer;
+  if (info_ptr == NULL)
+    return;
 
-      if (info_ptr == NULL)
-       continue;
+  /* We can't set abfd until now because the section may be empty or
+     not present, in which case the bfd is unknown.  */
+  abfd = get_section_bfd_owner (section);
 
-      /* We can't set abfd until now because the section may be empty or
-        not present, in which case the bfd is unknown.  */
-      abfd = get_section_bfd_owner (section);
+  /* We don't use init_cutu_and_read_dies_simple, or some such, here
+     because we don't need to read any dies: the signature is in the
+     header.  */
 
-      /* We don't use init_cutu_and_read_dies_simple, or some such, here
-        because we don't need to read any dies: the signature is in the
-        header.  */
+  end_ptr = info_ptr + section->size;
+  while (info_ptr < end_ptr)
+    {
+      struct signatured_type *sig_type;
+      struct dwo_unit *dwo_tu;
+      void **slot;
+      const gdb_byte *ptr = info_ptr;
+      struct comp_unit_head header;
+      unsigned int length;
 
-      end_ptr = info_ptr + section->size;
-      while (info_ptr < end_ptr)
-       {
-         sect_offset offset;
-         cu_offset type_offset_in_tu;
-         ULONGEST signature;
-         struct signatured_type *sig_type;
-         struct dwo_unit *dwo_tu;
-         void **slot;
-         const gdb_byte *ptr = info_ptr;
-         struct comp_unit_head header;
-         unsigned int length;
+      sect_offset sect_off = (sect_offset) (ptr - section->buffer);
 
-         offset.sect_off = ptr - section->buffer;
+      /* Initialize it due to a false compiler warning.  */
+      header.signature = -1;
+      header.type_cu_offset_in_tu = (cu_offset) -1;
 
-         /* We need to read the type's signature in order to build the hash
-            table, but we don't need anything else just yet.  */
+      /* We need to read the type's signature in order to build the hash
+        table, but we don't need anything else just yet.  */
 
-         ptr = read_and_check_type_unit_head (&header, section,
-                                              abbrev_section, ptr,
-                                              &signature, &type_offset_in_tu);
+      ptr = read_and_check_comp_unit_head (&header, section,
+                                          abbrev_section, ptr, section_kind);
 
-         length = get_cu_length (&header);
+      length = get_cu_length (&header);
 
-         /* Skip dummy type units.  */
-         if (ptr >= info_ptr + length
-             || peek_abbrev_code (abfd, ptr) == 0)
-           {
-             info_ptr += length;
-             continue;
-           }
+      /* Skip dummy type units.  */
+      if (ptr >= info_ptr + length
+         || peek_abbrev_code (abfd, ptr) == 0
+         || header.unit_type != DW_UT_type)
+       {
+         info_ptr += length;
+         continue;
+       }
 
-         if (types_htab == NULL)
-           {
-             if (dwo_file)
-               types_htab = allocate_dwo_unit_table (objfile);
-             else
-               types_htab = allocate_signatured_type_table (objfile);
-           }
+      if (types_htab == NULL)
+       {
+         if (dwo_file)
+           types_htab = allocate_dwo_unit_table (objfile);
+         else
+           types_htab = allocate_signatured_type_table (objfile);
+       }
+
+      if (dwo_file)
+       {
+         sig_type = NULL;
+         dwo_tu = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+                                  struct dwo_unit);
+         dwo_tu->dwo_file = dwo_file;
+         dwo_tu->signature = header.signature;
+         dwo_tu->type_offset_in_tu = header.type_cu_offset_in_tu;
+         dwo_tu->section = section;
+         dwo_tu->sect_off = sect_off;
+         dwo_tu->length = length;
+       }
+      else
+       {
+         /* N.B.: type_offset is not usable if this type uses a DWO file.
+            The real type_offset is in the DWO file.  */
+         dwo_tu = NULL;
+         sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+                                    struct signatured_type);
+         sig_type->signature = header.signature;
+         sig_type->type_offset_in_tu = header.type_cu_offset_in_tu;
+         sig_type->per_cu.objfile = objfile;
+         sig_type->per_cu.is_debug_types = 1;
+         sig_type->per_cu.section = section;
+         sig_type->per_cu.sect_off = sect_off;
+         sig_type->per_cu.length = length;
+       }
+
+      slot = htab_find_slot (types_htab,
+                            dwo_file ? (void*) dwo_tu : (void *) sig_type,
+                            INSERT);
+      gdb_assert (slot != NULL);
+      if (*slot != NULL)
+       {
+         sect_offset dup_sect_off;
 
          if (dwo_file)
            {
-             sig_type = NULL;
-             dwo_tu = OBSTACK_ZALLOC (&objfile->objfile_obstack,
-                                      struct dwo_unit);
-             dwo_tu->dwo_file = dwo_file;
-             dwo_tu->signature = signature;
-             dwo_tu->type_offset_in_tu = type_offset_in_tu;
-             dwo_tu->section = section;
-             dwo_tu->offset = offset;
-             dwo_tu->length = length;
+             const struct dwo_unit *dup_tu
+               = (const struct dwo_unit *) *slot;
+
+             dup_sect_off = dup_tu->sect_off;
            }
          else
            {
-             /* N.B.: type_offset is not usable if this type uses a DWO file.
-                The real type_offset is in the DWO file.  */
-             dwo_tu = NULL;
-             sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
-                                        struct signatured_type);
-             sig_type->signature = signature;
-             sig_type->type_offset_in_tu = type_offset_in_tu;
-             sig_type->per_cu.objfile = objfile;
-             sig_type->per_cu.is_debug_types = 1;
-             sig_type->per_cu.section = section;
-             sig_type->per_cu.offset = offset;
-             sig_type->per_cu.length = length;
+             const struct signatured_type *dup_tu
+               = (const struct signatured_type *) *slot;
+
+             dup_sect_off = dup_tu->per_cu.sect_off;
            }
 
-         slot = htab_find_slot (types_htab,
-                                dwo_file ? (void*) dwo_tu : (void *) sig_type,
-                                INSERT);
-         gdb_assert (slot != NULL);
-         if (*slot != NULL)
-           {
-             sect_offset dup_offset;
+         complaint (&symfile_complaints,
+                    _("debug type entry at offset 0x%x is duplicate to"
+                      " the entry at offset 0x%x, signature %s"),
+                    to_underlying (sect_off), to_underlying (dup_sect_off),
+                    hex_string (header.signature));
+       }
+      *slot = dwo_file ? (void *) dwo_tu : (void *) sig_type;
 
-             if (dwo_file)
-               {
-                 const struct dwo_unit *dup_tu
-                   = (const struct dwo_unit *) *slot;
+      if (dwarf_read_debug > 1)
+       fprintf_unfiltered (gdb_stdlog, "  offset 0x%x, signature %s\n",
+                           to_underlying (sect_off),
+                           hex_string (header.signature));
 
-                 dup_offset = dup_tu->offset;
-               }
-             else
-               {
-                 const struct signatured_type *dup_tu
-                   = (const struct signatured_type *) *slot;
+      info_ptr += length;
+    }
+}
 
-                 dup_offset = dup_tu->per_cu.offset;
-               }
+/* Create the hash table of all entries in the .debug_types
+   (or .debug_types.dwo) section(s).
+   If reading a DWO file, then DWO_FILE is a pointer to the DWO file object,
+   otherwise it is NULL.
 
-             complaint (&symfile_complaints,
-                        _("debug type entry at offset 0x%x is duplicate to"
-                          " the entry at offset 0x%x, signature %s"),
-                        offset.sect_off, dup_offset.sect_off,
-                        hex_string (signature));
-           }
-         *slot = dwo_file ? (void *) dwo_tu : (void *) sig_type;
+   The result is a pointer to the hash table or NULL if there are no types.
 
-         if (dwarf_read_debug > 1)
-           fprintf_unfiltered (gdb_stdlog, "  offset 0x%x, signature %s\n",
-                               offset.sect_off,
-                               hex_string (signature));
+   Note: This function processes DWO files only, not DWP files.  */
 
-         info_ptr += length;
-       }
-    }
+static void
+create_debug_types_hash_table (struct dwo_file *dwo_file,
+                              VEC (dwarf2_section_info_def) *types,
+                              htab_t &types_htab)
+{
+  int ix;
+  struct dwarf2_section_info *section;
 
-  return types_htab;
+  if (VEC_empty (dwarf2_section_info_def, types))
+    return;
+
+  for (ix = 0;
+       VEC_iterate (dwarf2_section_info_def, types, ix, section);
+       ++ix)
+    create_debug_type_hash_table (dwo_file, section, types_htab,
+                                 rcuh_kind::TYPE);
 }
 
 /* Create the hash table of all entries in the .debug_types section,
@@ -4787,10 +4951,12 @@ create_debug_types_hash_table (struct dwo_file *dwo_file,
 static int
 create_all_type_units (struct objfile *objfile)
 {
-  htab_t types_htab;
+  htab_t types_htab = NULL;
   struct signatured_type **iter;
 
-  types_htab = create_debug_types_hash_table (NULL, dwarf2_per_objfile->types);
+  create_debug_type_hash_table (NULL, &dwarf2_per_objfile->info, types_htab,
+                               rcuh_kind::COMPILE);
+  create_debug_types_hash_table (NULL, dwarf2_per_objfile->types, types_htab);
   if (types_htab == NULL)
     {
       dwarf2_per_objfile->signatured_types = NULL;
@@ -4880,12 +5046,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;
@@ -5164,48 +5330,45 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data *this_cu,
   section = dwo_unit->section;
   dwarf2_read_section (objfile, section);
   abfd = get_section_bfd_owner (section);
-  begin_info_ptr = info_ptr = section->buffer + dwo_unit->offset.sect_off;
+  begin_info_ptr = info_ptr = (section->buffer
+                              + to_underlying (dwo_unit->sect_off));
   dwo_abbrev_section = &dwo_unit->dwo_file->sections.abbrev;
   init_cu_die_reader (result_reader, cu, section, dwo_unit->dwo_file);
 
   if (this_cu->is_debug_types)
     {
-      ULONGEST header_signature;
-      cu_offset type_offset_in_tu;
       struct signatured_type *sig_type = (struct signatured_type *) this_cu;
 
-      info_ptr = read_and_check_type_unit_head (&cu->header, section,
+      info_ptr = read_and_check_comp_unit_head (&cu->header, section,
                                                dwo_abbrev_section,
-                                               info_ptr,
-                                               &header_signature,
-                                               &type_offset_in_tu);
+                                               info_ptr, rcuh_kind::TYPE);
       /* This is not an assert because it can be caused by bad debug info.  */
-      if (sig_type->signature != header_signature)
+      if (sig_type->signature != cu->header.signature)
        {
          error (_("Dwarf Error: signature mismatch %s vs %s while reading"
                   " TU at offset 0x%x [in module %s]"),
                 hex_string (sig_type->signature),
-                hex_string (header_signature),
-                dwo_unit->offset.sect_off,
+                hex_string (cu->header.signature),
+                to_underlying (dwo_unit->sect_off),
                 bfd_get_filename (abfd));
        }
-      gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
+      gdb_assert (dwo_unit->sect_off == cu->header.sect_off);
       /* For DWOs coming from DWP files, we don't know the CU length
         nor the type's offset in the TU until now.  */
       dwo_unit->length = get_cu_length (&cu->header);
-      dwo_unit->type_offset_in_tu = type_offset_in_tu;
+      dwo_unit->type_offset_in_tu = cu->header.type_cu_offset_in_tu;
 
       /* Establish the type offset that can be used to lookup the type.
         For DWO files, we don't know it until now.  */
-      sig_type->type_offset_in_section.sect_off =
-       dwo_unit->offset.sect_off + dwo_unit->type_offset_in_tu.cu_off;
+      sig_type->type_offset_in_section
+       = dwo_unit->sect_off + to_underlying (dwo_unit->type_offset_in_tu);
     }
   else
     {
       info_ptr = read_and_check_comp_unit_head (&cu->header, section,
                                                dwo_abbrev_section,
-                                               info_ptr, 0);
-      gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
+                                               info_ptr, rcuh_kind::COMPILE);
+      gdb_assert (dwo_unit->sect_off == cu->header.sect_off);
       /* For DWOs coming from DWP files, we don't know the CU length
         until now.  */
       dwo_unit->length = get_cu_length (&cu->header);
@@ -5465,7 +5628,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);
@@ -5487,7 +5650,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);
 
@@ -5514,47 +5677,47 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
     }
 
   /* Get the header.  */
-  if (cu->header.first_die_offset.cu_off != 0 && ! rereading_dwo_cu)
+  if (to_underlying (cu->header.first_die_cu_offset) != 0 && !rereading_dwo_cu)
     {
       /* We already have the header, there's no need to read it in again.  */
-      info_ptr += cu->header.first_die_offset.cu_off;
+      info_ptr += to_underlying (cu->header.first_die_cu_offset);
     }
   else
     {
       if (this_cu->is_debug_types)
        {
-         ULONGEST signature;
-         cu_offset type_offset_in_tu;
-
-         info_ptr = read_and_check_type_unit_head (&cu->header, section,
+         info_ptr = read_and_check_comp_unit_head (&cu->header, section,
                                                    abbrev_section, info_ptr,
-                                                   &signature,
-                                                   &type_offset_in_tu);
+                                                   rcuh_kind::TYPE);
 
          /* Since per_cu is the first member of struct signatured_type,
             we can go from a pointer to one to a pointer to the other.  */
          sig_type = (struct signatured_type *) this_cu;
-         gdb_assert (sig_type->signature == signature);
-         gdb_assert (sig_type->type_offset_in_tu.cu_off
-                     == type_offset_in_tu.cu_off);
-         gdb_assert (this_cu->offset.sect_off == cu->header.offset.sect_off);
+         gdb_assert (sig_type->signature == cu->header.signature);
+         gdb_assert (sig_type->type_offset_in_tu
+                     == cu->header.type_cu_offset_in_tu);
+         gdb_assert (this_cu->sect_off == cu->header.sect_off);
 
          /* LENGTH has not been set yet for type units if we're
             using .gdb_index.  */
          this_cu->length = get_cu_length (&cu->header);
 
          /* Establish the type offset that can be used to lookup the type.  */
-         sig_type->type_offset_in_section.sect_off =
-           this_cu->offset.sect_off + sig_type->type_offset_in_tu.cu_off;
+         sig_type->type_offset_in_section =
+           this_cu->sect_off + to_underlying (sig_type->type_offset_in_tu);
+
+         this_cu->dwarf_version = cu->header.version;
        }
       else
        {
          info_ptr = read_and_check_comp_unit_head (&cu->header, section,
                                                    abbrev_section,
-                                                   info_ptr, 0);
+                                                   info_ptr,
+                                                   rcuh_kind::COMPILE);
 
-         gdb_assert (this_cu->offset.sect_off == cu->header.offset.sect_off);
+         gdb_assert (this_cu->sect_off == cu->header.sect_off);
          gdb_assert (this_cu->length == get_cu_length (&cu->header));
+         this_cu->dwarf_version = cu->header.version;
        }
     }
 
@@ -5574,8 +5737,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)
@@ -5608,7 +5770,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)
@@ -5698,7 +5860,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);
 
@@ -5713,10 +5875,12 @@ init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
 
   cleanups = make_cleanup (free_stack_comp_unit, &cu);
 
-  begin_info_ptr = info_ptr = section->buffer + this_cu->offset.sect_off;
+  begin_info_ptr = info_ptr = section->buffer + to_underlying (this_cu->sect_off);
   info_ptr = read_and_check_comp_unit_head (&cu.header, section,
                                            abbrev_section, info_ptr,
-                                           this_cu->is_debug_types);
+                                           (this_cu->is_debug_types
+                                            ? rcuh_kind::TYPE
+                                            : rcuh_kind::COMPILE));
 
   this_cu->length = get_cu_length (&cu.header);
 
@@ -5824,7 +5988,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;
 
@@ -5842,7 +6006,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;
 }
@@ -5886,7 +6050,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)
@@ -5896,9 +6060,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;
@@ -6073,7 +6235,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);
@@ -6171,8 +6333,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);
 }
@@ -6244,13 +6406,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);
 
@@ -6260,7 +6422,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)
            {
@@ -6579,9 +6741,8 @@ read_comp_units_from_section (struct objfile *objfile,
     {
       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.  */
@@ -6590,7 +6751,7 @@ read_comp_units_from_section (struct objfile *objfile,
       /* 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->sect_off = sect_off;
       this_cu->length = length + initial_length_size;
       this_cu->is_dwz = is_dwz;
       this_cu->objfile = objfile;
@@ -6726,7 +6887,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);
 
@@ -6839,7 +7000,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;
     }
 
@@ -6873,7 +7034,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));
@@ -6930,6 +7091,9 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
                               &objfile->static_psymbols,
                               addr, cu->language, objfile);
        }
+
+      if (pdi->main_subprogram && actual_name != NULL)
+       set_objfile_main_name (objfile, actual_name, cu->language);
       break;
     case DW_TAG_constant:
       {
@@ -7230,7 +7394,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;
@@ -7286,8 +7450,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,
@@ -7324,6 +7488,7 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
          info_ptr += 1;
          break;
        case DW_FORM_flag_present:
+       case DW_FORM_implicit_const:
          break;
        case DW_FORM_data2:
        case DW_FORM_ref2:
@@ -7338,6 +7503,9 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
        case DW_FORM_ref_sig8:
          info_ptr += 8;
          break;
+       case DW_FORM_data16:
+         info_ptr += 16;
+         break;
        case DW_FORM_string:
          read_direct_string (abfd, info_ptr, &bytes_read);
          info_ptr += bytes_read;
@@ -7571,14 +7739,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;
            }
 
@@ -7688,7 +7857,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
@@ -7700,7 +7869,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.
@@ -8225,13 +8394,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))
@@ -8285,6 +8451,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
     case DW_TAG_catch_block:
       read_lexical_block_scope (die, cu);
       break;
+    case DW_TAG_call_site:
     case DW_TAG_GNU_call_site:
       read_call_site_scope (die, cu);
       break;
@@ -8307,6 +8474,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;
 
@@ -8417,17 +8585,6 @@ die_needs_namespace (struct die_info *die, struct dwarf2_cu *cu)
     }
 }
 
-/* Retrieve the last character from a mem_file.  */
-
-static void
-do_ui_file_peek_last (void *object, const char *buffer, long length)
-{
-  char *last_char_p = (char *) object;
-
-  if (length > 0)
-    *last_char_p = buffer[length - 1];
-}
-
 /* 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++),
@@ -8486,22 +8643,21 @@ dwarf2_compute_name (const char *name,
        {
          long length;
          const char *prefix;
-         struct ui_file *buf;
-         char *intermediate_name;
          const char *canonical_name = NULL;
 
+         string_file buf;
+
          prefix = determine_prefix (die, cu);
-         buf = mem_fileopen ();
          if (*prefix != '\0')
            {
              char *prefixed_name = typename_concat (NULL, prefix, name,
                                                     physname, cu);
 
-             fputs_unfiltered (prefixed_name, buf);
+             buf.puts (prefixed_name);
              xfree (prefixed_name);
            }
          else
-           fputs_unfiltered (name, buf);
+           buf.puts (name);
 
          /* Template parameters may be specified in the DIE's DW_AT_name, or
             as children with DW_TAG_template_type_param or
@@ -8546,25 +8702,25 @@ dwarf2_compute_name (const char *name,
 
                  if (first)
                    {
-                     fputs_unfiltered ("<", buf);
+                     buf.puts ("<");
                      first = 0;
                    }
                  else
-                   fputs_unfiltered (", ", buf);
+                   buf.puts (", ");
 
                  attr = dwarf2_attr (child, DW_AT_type, cu);
                  if (attr == NULL)
                    {
                      complaint (&symfile_complaints,
                                 _("template parameter missing DW_AT_type"));
-                     fputs_unfiltered ("UNKNOWN_TYPE", buf);
+                     buf.puts ("UNKNOWN_TYPE");
                      continue;
                    }
                  type = die_type (child, cu);
 
                  if (child->tag == DW_TAG_template_type_param)
                    {
-                     c_print_type (type, "", buf, -1, 0, &type_print_raw_options);
+                     c_print_type (type, "", &buf, -1, 0, &type_print_raw_options);
                      continue;
                    }
 
@@ -8574,7 +8730,7 @@ dwarf2_compute_name (const char *name,
                      complaint (&symfile_complaints,
                                 _("template parameter missing "
                                   "DW_AT_const_value"));
-                     fputs_unfiltered ("UNKNOWN_VALUE", buf);
+                     buf.puts ("UNKNOWN_VALUE");
                      continue;
                    }
 
@@ -8585,7 +8741,7 @@ dwarf2_compute_name (const char *name,
                  if (TYPE_NOSIGN (type))
                    /* GDB prints characters as NUMBER 'CHAR'.  If that's
                       changed, this can use value_print instead.  */
-                   c_printchar (value, type, buf);
+                   c_printchar (value, type, &buf);
                  else
                    {
                      struct value_print_options opts;
@@ -8608,7 +8764,7 @@ dwarf2_compute_name (const char *name,
                         the radix.  */
                      get_formatted_print_options (&opts, 'd');
                      opts.raw = 1;
-                     value_print (v, buf, &opts);
+                     value_print (v, &buf, &opts);
                      release_value (v);
                      value_free (v);
                    }
@@ -8620,12 +8776,10 @@ dwarf2_compute_name (const char *name,
                {
                  /* Close the argument list, with a space if necessary
                     (nested templates).  */
-                 char last_char = '\0';
-                 ui_file_put (buf, do_ui_file_peek_last, &last_char);
-                 if (last_char == '>')
-                   fputs_unfiltered (" >", buf);
+                 if (!buf.empty () && buf.string ().back () == '>')
+                   buf.puts (" >");
                  else
-                   fputs_unfiltered (">", buf);
+                   buf.puts (">");
                }
            }
 
@@ -8637,7 +8791,7 @@ dwarf2_compute_name (const char *name,
            {
              struct type *type = read_type_die (die, cu);
 
-             c_type_print_args (type, buf, 1, cu->language,
+             c_type_print_args (type, &buf, 1, cu->language,
                                 &type_print_raw_options);
 
              if (cu->language == language_cplus)
@@ -8652,30 +8806,27 @@ dwarf2_compute_name (const char *name,
                      && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_PTR
                      && TYPE_CONST (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type,
                                                                        0))))
-                   fputs_unfiltered (" const", buf);
+                   buf.puts (" const");
                }
            }
 
-         intermediate_name = ui_file_xstrdup (buf, &length);
-         ui_file_delete (buf);
+         const std::string &intermediate_name = buf.string ();
 
          if (cu->language == language_cplus)
            canonical_name
-             = dwarf2_canonicalize_name (intermediate_name, cu,
+             = dwarf2_canonicalize_name (intermediate_name.c_str (), cu,
                                          &objfile->per_bfd->storage_obstack);
 
          /* If we only computed INTERMEDIATE_NAME, or if
             INTERMEDIATE_NAME is already canonical, then we need to
             copy it to the appropriate obstack.  */
-         if (canonical_name == NULL || canonical_name == intermediate_name)
+         if (canonical_name == NULL || canonical_name == intermediate_name.c_str ())
            name = ((const char *)
                    obstack_copy0 (&objfile->per_bfd->storage_obstack,
-                                  intermediate_name,
-                                  strlen (intermediate_name)));
+                                  intermediate_name.c_str (),
+                                  intermediate_name.length ()));
          else
            name = canonical_name;
-
-         xfree (intermediate_name);
        }
     }
 
@@ -8780,7 +8931,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
@@ -8844,16 +8995,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
@@ -8991,7 +9142,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;
          }
 
@@ -9012,7 +9163,7 @@ 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;
          }
 
@@ -9033,20 +9184,9 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
   do_cleanups (cleanups);
 }
 
-/* Cleanup function for handle_DW_AT_stmt_list.  */
-
-static void
-free_cu_line_header (void *arg)
-{
-  struct dwarf2_cu *cu = (struct dwarf2_cu *) arg;
-
-  free_line_header (cu->line_header);
-  cu->line_header = NULL;
-}
-
-/* Check for possibly missing DW_AT_comp_dir with relative .debug_line
-   directory paths.  GCC SVN r127613 (new option -fdebug-prefix-map) fixed
-   this, it was first present in GCC release 4.3.0.  */
+/* Check for possibly missing DW_AT_comp_dir with relative .debug_line
+   directory paths.  GCC SVN r127613 (new option -fdebug-prefix-map) fixed
+   this, it was first present in GCC release 4.3.0.  */
 
 static int
 producer_is_gcc_lt_4_3 (struct dwarf2_cu *cu)
@@ -9057,37 +9197,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.
@@ -9101,7 +9242,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;
@@ -9114,7 +9254,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).
@@ -9134,7 +9274,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)
@@ -9156,9 +9296,10 @@ 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.get ();
 
   if (dwarf2_per_objfile->line_header_hash == NULL)
     slot = NULL;
@@ -9183,11 +9324,12 @@ 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);
+
+  lh.release ();
 }
 
 /* Process DW_TAG_compile_unit or DW_TAG_partial_unit.  */
@@ -9197,12 +9339,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;
 
@@ -9216,7 +9355,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);
 
@@ -9230,12 +9369,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)
@@ -9252,12 +9391,14 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
      refers to information in the line number info statement program
      header, so we can only read it if we've read the header
      successfully.  */
-  attr = dwarf2_attr (die, DW_AT_GNU_macros, cu);
+  attr = dwarf2_attr (die, DW_AT_macros, cu);
+  if (attr == NULL)
+    attr = dwarf2_attr (die, DW_AT_GNU_macros, cu);
   if (attr && cu->line_header)
     {
       if (dwarf2_attr (die, DW_AT_macro_info, cu))
        complaint (&symfile_complaints,
-                  _("CU refers to both DW_AT_GNU_macros and DW_AT_macro_info"));
+                  _("CU refers to both DW_AT_macros and DW_AT_macro_info"));
 
       dwarf_decode_macros (cu, DW_UNSND (attr), 1);
     }
@@ -9271,8 +9412,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.
@@ -9287,9 +9426,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);
@@ -9311,10 +9449,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)
@@ -9329,8 +9467,7 @@ 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.get ();
 
   if (first_time)
     {
@@ -9341,17 +9478,14 @@ 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 = lh->file_names.size ();
+      tu_group->symtabs = XNEWVEC (struct symtab *, lh->file_names.size ());
 
-      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 = &lh->file_names[i];
+         file_entry &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.get ()));
 
          if (current_subfile->symtab == NULL)
            {
@@ -9363,15 +9497,15 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
                = 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 < lh->file_names.size (); ++i)
        {
          struct file_entry *fe = &lh->file_names[i];
 
@@ -9379,6 +9513,8 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
        }
     }
 
+  lh.release ();
+
   /* The main symtab is allocated last.  Type units don't have DW_AT_name
      so they don't have a "real" (so to speak) symtab anyway.
      There is later code that will assign the main symtab to all symbols
@@ -9540,7 +9676,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;
@@ -9553,19 +9689,20 @@ 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.
@@ -9606,7 +9743,7 @@ create_dwo_cu (struct dwo_file *dwo_file)
       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.sect_off = sect_offset (info_ptr - section->buffer);
       per_cu.section = section;
 
       init_cutu_and_read_dies_no_follow (&per_cu, dwo_file,
@@ -10461,10 +10598,9 @@ lookup_dwo_unit_in_dwp (struct dwp_file *dwp_file, const char *comp_dir,
    If unable to find/open the file, return NULL.
    NOTE: This function is derived from symfile_bfd_open.  */
 
-static bfd *
+static gdb_bfd_ref_ptr
 try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
 {
-  bfd *sym_bfd;
   int desc, flags;
   char *absolute_name;
   /* Blech.  OPF_TRY_CWD_FIRST also disables searching the path list if
@@ -10493,23 +10629,20 @@ try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
   if (desc < 0)
     return NULL;
 
-  sym_bfd = gdb_bfd_open (absolute_name, gnutarget, desc);
+  gdb_bfd_ref_ptr sym_bfd (gdb_bfd_open (absolute_name, gnutarget, desc));
   xfree (absolute_name);
   if (sym_bfd == NULL)
     return NULL;
-  bfd_set_cacheable (sym_bfd, 1);
+  bfd_set_cacheable (sym_bfd.get (), 1);
 
-  if (!bfd_check_format (sym_bfd, bfd_object))
-    {
-      gdb_bfd_unref (sym_bfd); /* This also closes desc.  */
-      return NULL;
-    }
+  if (!bfd_check_format (sym_bfd.get (), bfd_object))
+    return NULL;
 
   /* Success.  Record the bfd as having been included by the objfile's bfd.
      This is important because things like demangled_names_hash lives in the
      objfile's per_bfd space and may have references to things like symbol
      names that live in the DWO/DWP file's per_bfd space.  PR 16426.  */
-  gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, sym_bfd);
+  gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, sym_bfd.get ());
 
   return sym_bfd;
 }
@@ -10521,11 +10654,9 @@ try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
    Upon success, the canonicalized path of the file is stored in the bfd,
    same as symfile_bfd_open.  */
 
-static bfd *
+static gdb_bfd_ref_ptr
 open_dwo_file (const char *file_name, const char *comp_dir)
 {
-  bfd *abfd;
-
   if (IS_ABSOLUTE_PATH (file_name))
     return try_open_dwop_file (file_name, 0 /*is_dwp*/, 0 /*search_cwd*/);
 
@@ -10538,7 +10669,8 @@ open_dwo_file (const char *file_name, const char *comp_dir)
 
       /* NOTE: If comp_dir is a relative path, this will also try the
         search path, which seems useful.  */
-      abfd = try_open_dwop_file (path_to_try, 0 /*is_dwp*/, 1 /*search_cwd*/);
+      gdb_bfd_ref_ptr abfd (try_open_dwop_file (path_to_try, 0 /*is_dwp*/,
+                                               1 /*search_cwd*/));
       xfree (path_to_try);
       if (abfd != NULL)
        return abfd;
@@ -10624,10 +10756,9 @@ open_and_init_dwo_file (struct dwarf2_per_cu_data *per_cu,
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct dwo_file *dwo_file;
-  bfd *dbfd;
   struct cleanup *cleanups;
 
-  dbfd = open_dwo_file (dwo_name, comp_dir);
+  gdb_bfd_ref_ptr dbfd (open_dwo_file (dwo_name, comp_dir));
   if (dbfd == NULL)
     {
       if (dwarf_read_debug)
@@ -10637,16 +10768,17 @@ open_and_init_dwo_file (struct dwarf2_per_cu_data *per_cu,
   dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_file);
   dwo_file->dwo_name = dwo_name;
   dwo_file->comp_dir = comp_dir;
-  dwo_file->dbfd = dbfd;
+  dwo_file->dbfd = dbfd.release ();
 
   cleanups = make_cleanup (free_dwo_file_cleanup, dwo_file);
 
-  bfd_map_over_sections (dbfd, dwarf2_locate_dwo_sections, &dwo_file->sections);
+  bfd_map_over_sections (dwo_file->dbfd, dwarf2_locate_dwo_sections,
+                        &dwo_file->sections);
 
   dwo_file->cu = create_dwo_cu (dwo_file);
 
-  dwo_file->tus = create_debug_types_hash_table (dwo_file,
-                                                dwo_file->sections.types);
+  create_debug_types_hash_table (dwo_file, dwo_file->sections.types,
+                                dwo_file->tus);
 
   discard_cleanups (cleanups);
 
@@ -10793,12 +10925,11 @@ allocate_dwp_loaded_cutus_table (struct objfile *objfile)
    Upon success, the canonicalized path of the file is stored in the bfd,
    same as symfile_bfd_open.  */
 
-static bfd *
+static gdb_bfd_ref_ptr
 open_dwp_file (const char *file_name)
 {
-  bfd *abfd;
-
-  abfd = try_open_dwop_file (file_name, 1 /*is_dwp*/, 1 /*search_cwd*/);
+  gdb_bfd_ref_ptr abfd (try_open_dwop_file (file_name, 1 /*is_dwp*/,
+                                           1 /*search_cwd*/));
   if (abfd != NULL)
     return abfd;
 
@@ -10831,58 +10962,53 @@ open_and_init_dwp_file (void)
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct dwp_file *dwp_file;
-  char *dwp_name;
-  bfd *dbfd;
-  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;
 
-  dbfd = open_dwp_file (dwp_name);
+  dwp_name += ".dwp";
+
+  gdb_bfd_ref_ptr dbfd (open_dwp_file (dwp_name.c_str ()));
   if (dbfd == NULL
       && strcmp (objfile->original_name, objfile_name (objfile)) != 0)
     {
       /* Try to find .dwp for the binary file after gdb_realpath resolving.  */
-      dwp_name = xstrprintf ("%s.dwp", objfile_name (objfile));
-      make_cleanup (xfree, dwp_name);
-      dbfd = open_dwp_file (dwp_name);
+      dwp_name = objfile_name (objfile);
+      dwp_name += ".dwp";
+      dbfd = open_dwp_file (dwp_name.c_str ());
     }
 
   if (dbfd == NULL)
     {
       if (dwarf_read_debug)
-       fprintf_unfiltered (gdb_stdlog, "DWP file not found: %s\n", dwp_name);
-      do_cleanups (cleanups);
+       fprintf_unfiltered (gdb_stdlog, "DWP file not found: %s\n", dwp_name.c_str ());
       return NULL;
     }
   dwp_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwp_file);
-  dwp_file->name = bfd_get_filename (dbfd);
-  dwp_file->dbfd = dbfd;
-  do_cleanups (cleanups);
+  dwp_file->name = bfd_get_filename (dbfd.get ());
+  dwp_file->dbfd = dbfd.release ();
 
   /* +1: section 0 is unused */
-  dwp_file->num_sections = bfd_count_sections (dbfd) + 1;
+  dwp_file->num_sections = bfd_count_sections (dwp_file->dbfd) + 1;
   dwp_file->elf_sections =
     OBSTACK_CALLOC (&objfile->objfile_obstack,
                    dwp_file->num_sections, asection *);
 
-  bfd_map_over_sections (dbfd, dwarf2_locate_common_dwp_sections, dwp_file);
+  bfd_map_over_sections (dwp_file->dbfd, dwarf2_locate_common_dwp_sections,
+                        dwp_file);
 
   dwp_file->cus = create_dwp_hash_table (dwp_file, 0);
 
@@ -10897,12 +11023,13 @@ open_and_init_dwp_file (void)
       error (_("Dwarf Error: DWP file CU version %s doesn't match"
               " TU version %s [in DWP file %s]"),
             pulongest (dwp_file->cus->version),
-            pulongest (dwp_file->tus->version), dwp_name);
+            pulongest (dwp_file->tus->version), dwp_name.c_str ());
     }
   dwp_file->version = dwp_file->cus->version;
 
   if (dwp_file->version == 2)
-    bfd_map_over_sections (dbfd, dwarf2_locate_v2_dwp_sections, dwp_file);
+    bfd_map_over_sections (dwp_file->dbfd, dwarf2_locate_v2_dwp_sections,
+                          dwp_file);
 
   dwp_file->loaded_cus = allocate_dwp_loaded_cutus_table (objfile);
   dwp_file->loaded_tus = allocate_dwp_loaded_cutus_table (objfile);
@@ -11061,7 +11188,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);
   }
@@ -11239,7 +11366,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;
@@ -11260,11 +11388,12 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
       struct dwarf2_cu *child_origin_cu;
 
       /* We are trying to process concrete instance entries:
-        DW_TAG_GNU_call_site DIEs indeed have a DW_AT_abstract_origin tag, but
+        DW_TAG_call_site DIEs indeed have a DW_AT_abstract_origin tag, but
         it's not relevant to our analysis here. i.e. detecting DIEs that are
         present in the abstract instance but not referenced in the concrete
         one.  */
-      if (child_die->tag == DW_TAG_GNU_call_site)
+      if (child_die->tag == DW_TAG_call_site
+          || child_die->tag == DW_TAG_GNU_call_site)
        continue;
 
       /* For each CHILD_DIE, find the corresponding child of
@@ -11293,25 +11422,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;
@@ -11319,10 +11450,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.
@@ -11379,7 +11510,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;
     }
 
@@ -11392,7 +11523,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;
     }
 
@@ -11599,7 +11730,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
   local_using_directives = newobj->local_using_directives;
 }
 
-/* Read in DW_TAG_GNU_call_site and insert it to CU->call_site_htab.  */
+/* Read in DW_TAG_call_site and insert it to CU->call_site_htab.  */
 
 static void
 read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
@@ -11615,13 +11746,19 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
 
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
-  attr = dwarf2_attr (die, DW_AT_low_pc, cu);
+  attr = dwarf2_attr (die, DW_AT_call_return_pc, cu);
+  if (attr == NULL)
+    {
+      /* This was a pre-DWARF-5 GNU extension alias
+        for DW_AT_call_return_pc.  */
+      attr = dwarf2_attr (die, DW_AT_low_pc, cu);
+    }
   if (!attr)
     {
       complaint (&symfile_complaints,
-                _("missing DW_AT_low_pc for DW_TAG_GNU_call_site "
+                _("missing DW_AT_call_return_pc for DW_TAG_call_site "
                   "DIE 0x%x [in module %s]"),
-                die->offset.sect_off, objfile_name (objfile));
+                to_underlying (die->sect_off), objfile_name (objfile));
       return;
     }
   pc = attr_value_as_address (attr) + baseaddr;
@@ -11636,9 +11773,9 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
   if (*slot != NULL)
     {
       complaint (&symfile_complaints,
-                _("Duplicate PC %s for DW_TAG_GNU_call_site "
+                _("Duplicate PC %s for DW_TAG_call_site "
                   "DIE 0x%x [in module %s]"),
-                paddress (gdbarch, pc), die->offset.sect_off,
+                paddress (gdbarch, pc), to_underlying (die->sect_off),
                 objfile_name (objfile));
       return;
     }
@@ -11649,12 +11786,13 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
   for (child_die = die->child; child_die && child_die->tag;
        child_die = sibling_die (child_die))
     {
-      if (child_die->tag != DW_TAG_GNU_call_site_parameter)
+      if (child_die->tag != DW_TAG_call_site_parameter
+          && child_die->tag != DW_TAG_GNU_call_site_parameter)
        {
          complaint (&symfile_complaints,
-                    _("Tag %d is not DW_TAG_GNU_call_site_parameter in "
-                      "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
-                    child_die->tag, child_die->offset.sect_off,
+                    _("Tag %d is not DW_TAG_call_site_parameter in "
+                      "DW_TAG_call_site child DIE 0x%x [in module %s]"),
+                    child_die->tag, to_underlying (child_die->sect_off),
                     objfile_name (objfile));
          continue;
        }
@@ -11671,7 +11809,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
   memset (call_site, 0, sizeof (*call_site) - sizeof (*call_site->parameter));
   call_site->pc = pc;
 
-  if (dwarf2_flag_true_p (die, DW_AT_GNU_tail_call, cu))
+  if (dwarf2_flag_true_p (die, DW_AT_call_tail_call, cu)
+      || dwarf2_flag_true_p (die, DW_AT_GNU_tail_call, cu))
     {
       struct die_info *func_die;
 
@@ -11681,10 +11820,12 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
           && func_die->tag != DW_TAG_subroutine_type;
           func_die = func_die->parent);
 
-      /* DW_AT_GNU_all_call_sites is a superset
-        of DW_AT_GNU_all_tail_call_sites.  */
+      /* DW_AT_call_all_calls is a superset
+        of DW_AT_call_all_tail_calls.  */
       if (func_die
+          && !dwarf2_flag_true_p (func_die, DW_AT_call_all_calls, cu)
           && !dwarf2_flag_true_p (func_die, DW_AT_GNU_all_call_sites, cu)
+         && !dwarf2_flag_true_p (func_die, DW_AT_call_all_tail_calls, cu)
          && !dwarf2_flag_true_p (func_die, DW_AT_GNU_all_tail_call_sites, cu))
        {
          /* TYPE_TAIL_CALL_LIST is not interesting in functions where it is
@@ -11712,15 +11853,22 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
            }
          else
            complaint (&symfile_complaints,
-                      _("Cannot find function owning DW_TAG_GNU_call_site "
+                      _("Cannot find function owning DW_TAG_call_site "
                         "DIE 0x%x [in module %s]"),
-                      die->offset.sect_off, objfile_name (objfile));
+                      to_underlying (die->sect_off), objfile_name (objfile));
        }
     }
 
-  attr = dwarf2_attr (die, DW_AT_GNU_call_site_target, cu);
+  attr = dwarf2_attr (die, DW_AT_call_target, cu);
+  if (attr == NULL)
+    attr = dwarf2_attr (die, DW_AT_GNU_call_site_target, cu);
   if (attr == NULL)
-    attr = dwarf2_attr (die, DW_AT_abstract_origin, cu);
+    attr = dwarf2_attr (die, DW_AT_call_origin, cu);
+  if (attr == NULL)
+    {
+      /* This was a pre-DWARF-5 GNU extension alias for DW_AT_call_origin.  */
+      attr = dwarf2_attr (die, DW_AT_abstract_origin, cu);
+    }
   SET_FIELD_DWARF_BLOCK (call_site->target, NULL);
   if (!attr || (attr_form_is_block (attr) && DW_BLOCK (attr)->size == 0))
     /* Keep NULL DWARF_BLOCK.  */;
@@ -11758,9 +11906,9 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
            target_physname = dwarf2_physname (NULL, target_die, target_cu);
          if (target_physname == NULL)
            complaint (&symfile_complaints,
-                      _("DW_AT_GNU_call_site_target target DIE has invalid "
+                      _("DW_AT_call_target target DIE has invalid "
                         "physname, for referencing DIE 0x%x [in module %s]"),
-                      die->offset.sect_off, objfile_name (objfile));
+                      to_underlying (die->sect_off), objfile_name (objfile));
          else
            SET_FIELD_PHYSNAME (call_site->target, target_physname);
        }
@@ -11772,9 +11920,9 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
          if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu, NULL)
              <= PC_BOUNDS_INVALID)
            complaint (&symfile_complaints,
-                      _("DW_AT_GNU_call_site_target target DIE has invalid "
+                      _("DW_AT_call_target target DIE has invalid "
                         "low pc, for referencing DIE 0x%x [in module %s]"),
-                      die->offset.sect_off, objfile_name (objfile));
+                      to_underlying (die->sect_off), objfile_name (objfile));
          else
            {
              lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
@@ -11784,9 +11932,9 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
     }
   else
     complaint (&symfile_complaints,
-              _("DW_TAG_GNU_call_site DW_AT_GNU_call_site_target is neither "
+              _("DW_TAG_call_site DW_AT_call_target is neither "
                 "block nor reference, for DIE 0x%x [in module %s]"),
-              die->offset.sect_off, objfile_name (objfile));
+              to_underlying (die->sect_off), objfile_name (objfile));
 
   call_site->per_cu = cu->per_cu;
 
@@ -11797,7 +11945,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
       struct call_site_parameter *parameter;
       struct attribute *loc, *origin;
 
-      if (child_die->tag != DW_TAG_GNU_call_site_parameter)
+      if (child_die->tag != DW_TAG_call_site_parameter
+          && child_die->tag != DW_TAG_GNU_call_site_parameter)
        {
          /* Already printed the complaint above.  */
          continue;
@@ -11808,37 +11957,43 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
 
       /* DW_AT_location specifies the register number or DW_AT_abstract_origin
         specifies DW_TAG_formal_parameter.  Value of the data assumed for the
-        register is contained in DW_AT_GNU_call_site_value.  */
+        register is contained in DW_AT_call_value.  */
 
       loc = dwarf2_attr (child_die, DW_AT_location, cu);
-      origin = dwarf2_attr (child_die, DW_AT_abstract_origin, cu);
+      origin = dwarf2_attr (child_die, DW_AT_call_parameter, cu);
+      if (origin == NULL)
+       {
+         /* This was a pre-DWARF-5 GNU extension alias
+            for DW_AT_call_parameter.  */
+         origin = dwarf2_attr (child_die, DW_AT_abstract_origin, cu);
+       }
       if (loc == NULL && origin != NULL && attr_form_is_ref (origin))
        {
-         sect_offset offset;
-
          parameter->kind = CALL_SITE_PARAMETER_PARAM_OFFSET;
-         offset = dwarf2_get_ref_die_offset (origin);
-         if (!offset_in_cu_p (&cu->header, offset))
+
+         sect_offset sect_off
+           = (sect_offset) dwarf2_get_ref_die_offset (origin);
+         if (!offset_in_cu_p (&cu->header, sect_off))
            {
              /* As DW_OP_GNU_parameter_ref uses CU-relative offset this
                 binding can be done only inside one CU.  Such referenced DIE
                 therefore cannot be even moved to DW_TAG_partial_unit.  */
              complaint (&symfile_complaints,
-                        _("DW_AT_abstract_origin offset is not in CU for "
-                          "DW_TAG_GNU_call_site child DIE 0x%x "
-                          "[in module %s]"),
-                        child_die->offset.sect_off, objfile_name (objfile));
+                        _("DW_AT_call_parameter offset is not in CU for "
+                          "DW_TAG_call_site child DIE 0x%x [in module %s]"),
+                        to_underlying (child_die->sect_off),
+                        objfile_name (objfile));
              continue;
            }
-         parameter->u.param_offset.cu_off = (offset.sect_off
-                                             - cu->header.offset.sect_off);
+         parameter->u.param_cu_off
+           = (cu_offset) (sect_off - cu->header.sect_off);
        }
       else if (loc == NULL || origin != NULL || !attr_form_is_block (loc))
        {
          complaint (&symfile_complaints,
                     _("No DW_FORM_block* DW_AT_location for "
-                      "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
-                    child_die->offset.sect_off, objfile_name (objfile));
+                      "DW_TAG_call_site child DIE 0x%x [in module %s]"),
+                    to_underlying (child_die->sect_off), objfile_name (objfile));
          continue;
        }
       else
@@ -11856,20 +12011,24 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
              complaint (&symfile_complaints,
                         _("Only single DW_OP_reg or DW_OP_fbreg is supported "
                           "for DW_FORM_block* DW_AT_location is supported for "
-                          "DW_TAG_GNU_call_site child DIE 0x%x "
+                          "DW_TAG_call_site child DIE 0x%x "
                           "[in module %s]"),
-                        child_die->offset.sect_off, objfile_name (objfile));
+                        to_underlying (child_die->sect_off),
+                        objfile_name (objfile));
              continue;
            }
        }
 
-      attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_value, cu);
+      attr = dwarf2_attr (child_die, DW_AT_call_value, cu);
+      if (attr == NULL)
+       attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_value, cu);
       if (!attr_form_is_block (attr))
        {
          complaint (&symfile_complaints,
-                    _("No DW_FORM_block* DW_AT_GNU_call_site_value for "
-                      "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
-                    child_die->offset.sect_off, objfile_name (objfile));
+                    _("No DW_FORM_block* DW_AT_call_value for "
+                      "DW_TAG_call_site child DIE 0x%x [in module %s]"),
+                    to_underlying (child_die->sect_off),
+                    objfile_name (objfile));
          continue;
        }
       parameter->value = DW_BLOCK (attr)->data;
@@ -11880,14 +12039,17 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
       parameter->data_value_size = 0;
       call_site->parameter_count++;
 
-      attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_data_value, cu);
+      attr = dwarf2_attr (child_die, DW_AT_call_data_value, cu);
+      if (attr == NULL)
+       attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_data_value, cu);
       if (attr)
        {
          if (!attr_form_is_block (attr))
            complaint (&symfile_complaints,
-                      _("No DW_FORM_block* DW_AT_GNU_call_site_data_value for "
-                        "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
-                      child_die->offset.sect_off, objfile_name (objfile));
+                      _("No DW_FORM_block* DW_AT_call_data_value for "
+                        "DW_TAG_call_site child DIE 0x%x [in module %s]"),
+                      to_underlying (child_die->sect_off),
+                      objfile_name (objfile));
          else
            {
              parameter->data_value = DW_BLOCK (attr)->data;
@@ -11897,14 +12059,17 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
     }
 }
 
-/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
-   Return 1 if the attributes are present and valid, otherwise, return 0.
-   If RANGES_PST is not NULL we should setup `objfile->psymtabs_addrmap'.  */
+/* Call CALLBACK from DW_AT_ranges attribute value OFFSET
+   reading .debug_rnglists.
+   Callback's type should be:
+    void (CORE_ADDR range_beginning, CORE_ADDR range_end)
+   Return true if the attributes are present and valid, otherwise,
+   return false.  */
 
-static int
-dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
-                   CORE_ADDR *high_return, struct dwarf2_cu *cu,
-                   struct partial_symtab *ranges_pst)
+template <typename Callback>
+static bool
+dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
+                        Callback &&callback)
 {
   struct objfile *objfile = cu->objfile;
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
@@ -11917,10 +12082,183 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
   int found_base;
   unsigned int dummy;
   const gdb_byte *buffer;
-  int low_set;
   CORE_ADDR low = 0;
   CORE_ADDR high = 0;
   CORE_ADDR baseaddr;
+  bool overflow = false;
+
+  found_base = cu->base_known;
+  base = cu->base_address;
+
+  dwarf2_read_section (objfile, &dwarf2_per_objfile->rnglists);
+  if (offset >= dwarf2_per_objfile->rnglists.size)
+    {
+      complaint (&symfile_complaints,
+                _("Offset %d out of bounds for DW_AT_ranges attribute"),
+                offset);
+      return false;
+    }
+  buffer = dwarf2_per_objfile->rnglists.buffer + offset;
+
+  baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+  while (1)
+    {
+      /* Initialize it due to a false compiler warning.  */
+      CORE_ADDR range_beginning = 0, range_end = 0;
+      const gdb_byte *buf_end = (dwarf2_per_objfile->rnglists.buffer
+                                + dwarf2_per_objfile->rnglists.size);
+      unsigned int bytes_read;
+
+      if (buffer == buf_end)
+       {
+         overflow = true;
+         break;
+       }
+      const auto rlet = static_cast<enum dwarf_range_list_entry>(*buffer++);
+      switch (rlet)
+       {
+       case DW_RLE_end_of_list:
+         break;
+       case DW_RLE_base_address:
+         if (buffer + cu->header.addr_size > buf_end)
+           {
+             overflow = true;
+             break;
+           }
+         base = read_address (obfd, buffer, cu, &bytes_read);
+         found_base = 1;
+         buffer += bytes_read;
+         break;
+       case DW_RLE_start_length:
+         if (buffer + cu->header.addr_size > buf_end)
+           {
+             overflow = true;
+             break;
+           }
+         range_beginning = read_address (obfd, buffer, cu, &bytes_read);
+         buffer += bytes_read;
+         range_end = (range_beginning
+                      + read_unsigned_leb128 (obfd, buffer, &bytes_read));
+         buffer += bytes_read;
+         if (buffer > buf_end)
+           {
+             overflow = true;
+             break;
+           }
+         break;
+       case DW_RLE_offset_pair:
+         range_beginning = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+         buffer += bytes_read;
+         if (buffer > buf_end)
+           {
+             overflow = true;
+             break;
+           }
+         range_end = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+         buffer += bytes_read;
+         if (buffer > buf_end)
+           {
+             overflow = true;
+             break;
+           }
+         break;
+       case DW_RLE_start_end:
+         if (buffer + 2 * cu->header.addr_size > buf_end)
+           {
+             overflow = true;
+             break;
+           }
+         range_beginning = read_address (obfd, buffer, cu, &bytes_read);
+         buffer += bytes_read;
+         range_end = read_address (obfd, buffer, cu, &bytes_read);
+         buffer += bytes_read;
+         break;
+       default:
+         complaint (&symfile_complaints,
+                    _("Invalid .debug_rnglists data (no base address)"));
+         return false;
+       }
+      if (rlet == DW_RLE_end_of_list || overflow)
+       break;
+      if (rlet == DW_RLE_base_address)
+       continue;
+
+      if (!found_base)
+       {
+         /* We have no valid base address for the ranges
+            data.  */
+         complaint (&symfile_complaints,
+                    _("Invalid .debug_rnglists data (no base address)"));
+         return false;
+       }
+
+      if (range_beginning > range_end)
+       {
+         /* Inverted range entries are invalid.  */
+         complaint (&symfile_complaints,
+                    _("Invalid .debug_rnglists data (inverted range)"));
+         return false;
+       }
+
+      /* Empty range entries have no effect.  */
+      if (range_beginning == range_end)
+       continue;
+
+      range_beginning += base;
+      range_end += base;
+
+      /* A not-uncommon case of bad debug info.
+        Don't pollute the addrmap with bad data.  */
+      if (range_beginning + baseaddr == 0
+         && !dwarf2_per_objfile->has_section_at_zero)
+       {
+         complaint (&symfile_complaints,
+                    _(".debug_rnglists entry has start address of zero"
+                      " [in module %s]"), objfile_name (objfile));
+         continue;
+       }
+
+      callback (range_beginning, range_end);
+    }
+
+  if (overflow)
+    {
+      complaint (&symfile_complaints,
+                _("Offset %d is not terminated "
+                  "for DW_AT_ranges attribute"),
+                offset);
+      return false;
+    }
+
+  return true;
+}
+
+/* Call CALLBACK from DW_AT_ranges attribute value OFFSET reading .debug_ranges.
+   Callback's type should be:
+    void (CORE_ADDR range_beginning, CORE_ADDR range_end)
+   Return 1 if the attributes are present and valid, otherwise, return 0.  */
+
+template <typename Callback>
+static int
+dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu,
+                      Callback &&callback)
+{
+  struct objfile *objfile = cu->objfile;
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct comp_unit_head *cu_header = &cu->header;
+  bfd *obfd = objfile->obfd;
+  unsigned int addr_size = cu_header->addr_size;
+  CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
+  /* Base address selection entry.  */
+  CORE_ADDR base;
+  int found_base;
+  unsigned int dummy;
+  const gdb_byte *buffer;
+  CORE_ADDR baseaddr;
+
+  if (cu_header->version >= 5)
+    return dwarf2_rnglists_process (offset, cu, callback);
 
   found_base = cu->base_known;
   base = cu->base_address;
@@ -11935,8 +12273,6 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
     }
   buffer = dwarf2_per_objfile->ranges.buffer + offset;
 
-  low_set = 0;
-
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
   while (1)
@@ -12001,6 +12337,33 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
          continue;
        }
 
+      callback (range_beginning, range_end);
+    }
+
+  return 1;
+}
+
+/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
+   Return 1 if the attributes are present and valid, otherwise, return 0.
+   If RANGES_PST is not NULL we should setup `objfile->psymtabs_addrmap'.  */
+
+static int
+dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
+                   CORE_ADDR *high_return, struct dwarf2_cu *cu,
+                   struct partial_symtab *ranges_pst)
+{
+  struct objfile *objfile = cu->objfile;
+  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  const CORE_ADDR baseaddr = ANOFFSET (objfile->section_offsets,
+                                      SECT_OFF_TEXT (objfile));
+  int low_set = 0;
+  CORE_ADDR low = 0;
+  CORE_ADDR high = 0;
+  int retval;
+
+  retval = dwarf2_ranges_process (offset, cu,
+    [&] (CORE_ADDR range_beginning, CORE_ADDR range_end)
+    {
       if (ranges_pst != NULL)
        {
          CORE_ADDR lowpc;
@@ -12031,7 +12394,9 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
          if (range_end > high)
            high = range_end;
        }
-    }
+    });
+  if (!retval)
+    return 0;
 
   if (! low_set)
     /* If the first entry is an end-of-list marker, the range
@@ -12283,79 +12648,15 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
       CORE_ADDR base = cu->base_address;
       int base_known = cu->base_known;
 
-      dwarf2_read_section (objfile, &dwarf2_per_objfile->ranges);
-      if (offset >= dwarf2_per_objfile->ranges.size)
-        {
-          complaint (&symfile_complaints,
-                     _("Offset %lu out of bounds for DW_AT_ranges attribute"),
-                     offset);
-          return;
-        }
-      buffer = dwarf2_per_objfile->ranges.buffer + offset;
-
-      for (;;)
-        {
-          unsigned int bytes_read;
-          CORE_ADDR start, end;
-
-          start = read_address (obfd, buffer, cu, &bytes_read);
-          buffer += bytes_read;
-          end = read_address (obfd, buffer, cu, &bytes_read);
-          buffer += bytes_read;
-
-          /* Did we find the end of the range list?  */
-          if (start == 0 && end == 0)
-            break;
-
-          /* Did we find a base address selection entry?  */
-          else if ((start & base_select_mask) == base_select_mask)
-            {
-              base = end;
-              base_known = 1;
-            }
-
-          /* We found an ordinary address range.  */
-          else
-            {
-              if (!base_known)
-                {
-                  complaint (&symfile_complaints,
-                            _("Invalid .debug_ranges data "
-                              "(no base address)"));
-                  return;
-                }
-
-             if (start > end)
-               {
-                 /* Inverted range entries are invalid.  */
-                 complaint (&symfile_complaints,
-                            _("Invalid .debug_ranges data "
-                              "(inverted range)"));
-                 return;
-               }
-
-             /* Empty range entries have no effect.  */
-             if (start == end)
-               continue;
-
-             start += base + baseaddr;
-             end += base + baseaddr;
-
-             /* A not-uncommon case of bad debug info.
-                Don't pollute the addrmap with bad data.  */
-             if (start == 0 && !dwarf2_per_objfile->has_section_at_zero)
-               {
-                 complaint (&symfile_complaints,
-                            _(".debug_ranges entry has start address of zero"
-                              " [in module %s]"), objfile_name (objfile));
-                 continue;
-               }
-
-             start = gdbarch_adjust_dwarf2_addr (gdbarch, start);
-             end = gdbarch_adjust_dwarf2_addr (gdbarch, end);
-              record_block_range (block, start, end - 1);
-            }
-        }
+      dwarf2_ranges_process (offset, cu,
+       [&] (CORE_ADDR start, CORE_ADDR end)
+       {
+         start += baseaddr;
+         end += baseaddr;
+         start = gdbarch_adjust_dwarf2_addr (gdbarch, start);
+         end = gdbarch_adjust_dwarf2_addr (gdbarch, end);
+         record_block_range (block, start, end - 1);
+       });
     }
 }
 
@@ -12587,6 +12888,10 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
                                 - bit_offset - FIELD_BITSIZE (*fp)));
            }
        }
+      attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
+      if (attr != NULL)
+       SET_FIELD_BITPOS (*fp, (FIELD_BITPOS (*fp)
+                               + dwarf2_get_attr_constant_value (attr, 0)));
 
       /* Get name of field.  */
       fieldname = dwarf2_name (die, cu);
@@ -12993,7 +13298,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
                {
@@ -13021,7 +13326,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;
        }
@@ -13711,8 +14016,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;
     }
 
@@ -13952,7 +14257,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;
 
@@ -14055,7 +14360,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))
@@ -14175,7 +14480,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.  */
@@ -14335,16 +14640,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.  */
@@ -14352,7 +14660,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)
     {
@@ -14715,7 +15023,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;
@@ -14820,9 +15128,22 @@ 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:
@@ -15009,7 +15330,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))
@@ -15231,13 +15552,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)
@@ -15254,7 +15574,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;
 
@@ -15359,7 +15679,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);
@@ -15372,7 +15692,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 *,
@@ -15381,7 +15701,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;
 
@@ -15402,12 +15722,29 @@ abbrev_table_read_table (struct dwarf2_section_info *section,
       abbrev_ptr += 1;
 
       /* now read in declarations */
-      abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
-      abbrev_ptr += bytes_read;
-      abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
-      abbrev_ptr += bytes_read;
-      while (abbrev_name)
+      for (;;)
        {
+         LONGEST implicit_const;
+
+         abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+         abbrev_ptr += bytes_read;
+         abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+         abbrev_ptr += bytes_read;
+         if (abbrev_form == DW_FORM_implicit_const)
+           {
+             implicit_const = read_signed_leb128 (abfd, abbrev_ptr,
+                                                  &bytes_read);
+             abbrev_ptr += bytes_read;
+           }
+         else
+           {
+             /* Initialize it due to a false compiler warning.  */
+             implicit_const = -1;
+           }
+
+         if (abbrev_name == 0)
+           break;
+
          if (cur_abbrev->num_attrs == allocated_attrs)
            {
              allocated_attrs += ATTR_ALLOC_CHUNK;
@@ -15417,12 +15754,10 @@ abbrev_table_read_table (struct dwarf2_section_info *section,
 
          cur_attrs[cur_abbrev->num_attrs].name
            = (enum dwarf_attribute) abbrev_name;
-         cur_attrs[cur_abbrev->num_attrs++].form
+         cur_attrs[cur_abbrev->num_attrs].form
            = (enum dwarf_form) abbrev_form;
-         abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
-         abbrev_ptr += bytes_read;
-         abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
-         abbrev_ptr += bytes_read;
+         cur_attrs[cur_abbrev->num_attrs].implicit_const = implicit_const;
+         ++cur_abbrev->num_attrs;
        }
 
       cur_abbrev->attrs =
@@ -15483,7 +15818,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.  */
@@ -15685,7 +16020,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
@@ -15758,7 +16093,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;
        }
 
@@ -15825,7 +16161,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;
 
@@ -15924,8 +16260,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,
@@ -15948,19 +16284,18 @@ read_partial_die (const struct die_reader_specs *reader,
             to describe functions' calling conventions.
 
             However, because it's a necessary piece of information in
-            Fortran, and because DW_CC_program is the only piece of debugging
-            information whose definition refers to a 'main program' at all,
-            several compilers have begun marking Fortran main programs with
-            DW_CC_program --- even when those functions use the standard
-            calling conventions.
-
-            So until DWARF specifies a way to provide this information and
-            compilers pick up the new representation, we'll support this
-            practice.  */
+            Fortran, and before DWARF 4 DW_CC_program was the only
+            piece of debugging information whose definition refers to
+            a 'main program' at all, several compilers marked Fortran
+            main programs with DW_CC_program --- even when those
+            functions use the standard calling conventions.
+
+            Although DWARF now specifies a way to provide this
+            information, we support this practice for backward
+            compatibility.  */
          if (DW_UNSND (&attr) == DW_CC_program
-             && cu->language == language_fortran
-             && part_die->name != NULL)
-           set_objfile_main_name (objfile, part_die->name, language_fortran);
+             && cu->language == language_fortran)
+           part_die->main_subprogram = 1;
          break;
        case DW_AT_inline:
          if (DW_UNSND (&attr) == DW_INL_inlined
@@ -15971,12 +16306,16 @@ 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);
            }
          break;
 
+       case DW_AT_main_subprogram:
+         part_die->main_subprogram = DW_UNSND (&attr);
+         break;
+
        default:
          break;
        }
@@ -16003,7 +16342,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)
@@ -16015,7 +16354,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;
@@ -16027,15 +16367,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;
 }
@@ -16046,16 +16386,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.
@@ -16067,19 +16407,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,
@@ -16097,14 +16437,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;
 }
 
@@ -16253,7 +16593,7 @@ fixup_partial_die (struct partial_die_info *part_die,
 static const gdb_byte *
 read_attribute_value (const struct die_reader_specs *reader,
                      struct attribute *attr, unsigned form,
-                     const gdb_byte *info_ptr)
+                     LONGEST implicit_const, const gdb_byte *info_ptr)
 {
   struct dwarf2_cu *cu = reader->cu;
   struct objfile *objfile = cu->objfile;
@@ -16311,8 +16651,15 @@ read_attribute_value (const struct die_reader_specs *reader,
       DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
       info_ptr += 8;
       break;
-    case DW_FORM_sec_offset:
-      DW_UNSND (attr) = read_offset (abfd, info_ptr, &cu->header, &bytes_read);
+    case DW_FORM_data16:
+      blk = dwarf_alloc_block (cu);
+      blk->size = 16;
+      blk->data = read_n_bytes (abfd, info_ptr, 16);
+      info_ptr += 16;
+      DW_BLOCK (attr) = blk;
+      break;
+    case DW_FORM_sec_offset:
+      DW_UNSND (attr) = read_offset (abfd, info_ptr, &cu->header, &bytes_read);
       info_ptr += bytes_read;
       break;
     case DW_FORM_string:
@@ -16330,6 +16677,16 @@ read_attribute_value (const struct die_reader_specs *reader,
          break;
        }
       /* FALLTHROUGH */
+    case DW_FORM_line_strp:
+      if (!cu->per_cu->is_dwz)
+       {
+         DW_STRING (attr) = read_indirect_line_string (abfd, info_ptr,
+                                                       cu_header, &bytes_read);
+         DW_STRING_IS_CANONICAL (attr) = 0;
+         info_ptr += bytes_read;
+         break;
+       }
+      /* FALLTHROUGH */
     case DW_FORM_GNU_strp_alt:
       {
        struct dwz_file *dwz = dwarf2_get_dwz_file ();
@@ -16378,22 +16735,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;
@@ -16402,14 +16759,23 @@ read_attribute_value (const struct die_reader_specs *reader,
       info_ptr += 8;
       break;
     case DW_FORM_ref_udata:
-      DW_UNSND (attr) = (cu->header.offset.sect_off
+      DW_UNSND (attr) = (to_underlying (cu->header.sect_off)
                         + read_unsigned_leb128 (abfd, info_ptr, &bytes_read));
       info_ptr += bytes_read;
       break;
     case DW_FORM_indirect:
       form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
       info_ptr += bytes_read;
-      info_ptr = read_attribute_value (reader, attr, form, info_ptr);
+      if (form == DW_FORM_implicit_const)
+       {
+         implicit_const = read_signed_leb128 (abfd, info_ptr, &bytes_read);
+         info_ptr += bytes_read;
+       }
+      info_ptr = read_attribute_value (reader, attr, form, implicit_const,
+                                      info_ptr);
+      break;
+    case DW_FORM_implicit_const:
+      DW_SND (attr) = implicit_const;
       break;
     case DW_FORM_GNU_addr_index:
       if (reader->dwo_file == NULL)
@@ -16479,7 +16845,8 @@ read_attribute (const struct die_reader_specs *reader,
                const gdb_byte *info_ptr)
 {
   attr->name = abbrev->name;
-  return read_attribute_value (reader, attr, abbrev->form, info_ptr);
+  return read_attribute_value (reader, attr, abbrev->form,
+                              abbrev->implicit_const, info_ptr);
 }
 
 /* Read dwarf information from a buffer.  */
@@ -16732,21 +17099,47 @@ read_direct_string (bfd *abfd, const gdb_byte *buf,
   return (const char *) buf;
 }
 
+/* Return pointer to string at section SECT offset STR_OFFSET with error
+   reporting strings FORM_NAME and SECT_NAME.  */
+
 static const char *
-read_indirect_string_at_offset (bfd *abfd, LONGEST str_offset)
-{
-  dwarf2_read_section (dwarf2_per_objfile->objfile, &dwarf2_per_objfile->str);
-  if (dwarf2_per_objfile->str.buffer == NULL)
-    error (_("DW_FORM_strp used without .debug_str section [in module %s]"),
-          bfd_get_filename (abfd));
-  if (str_offset >= dwarf2_per_objfile->str.size)
-    error (_("DW_FORM_strp pointing outside of "
-            ".debug_str section [in module %s]"),
-          bfd_get_filename (abfd));
+read_indirect_string_at_offset_from (bfd *abfd, LONGEST str_offset,
+                                    struct dwarf2_section_info *sect,
+                                    const char *form_name,
+                                    const char *sect_name)
+{
+  dwarf2_read_section (dwarf2_per_objfile->objfile, sect);
+  if (sect->buffer == NULL)
+    error (_("%s used without %s section [in module %s]"),
+          form_name, sect_name, bfd_get_filename (abfd));
+  if (str_offset >= sect->size)
+    error (_("%s pointing outside of %s section [in module %s]"),
+          form_name, sect_name, bfd_get_filename (abfd));
   gdb_assert (HOST_CHAR_BIT == 8);
-  if (dwarf2_per_objfile->str.buffer[str_offset] == '\0')
+  if (sect->buffer[str_offset] == '\0')
     return NULL;
-  return (const char *) (dwarf2_per_objfile->str.buffer + str_offset);
+  return (const char *) (sect->buffer + str_offset);
+}
+
+/* Return pointer to string at .debug_str offset STR_OFFSET.  */
+
+static const char *
+read_indirect_string_at_offset (bfd *abfd, LONGEST str_offset)
+{
+  return read_indirect_string_at_offset_from (abfd, str_offset,
+                                             &dwarf2_per_objfile->str,
+                                             "DW_FORM_strp", ".debug_str");
+}
+
+/* Return pointer to string at .debug_line_str offset STR_OFFSET.  */
+
+static const char *
+read_indirect_line_string_at_offset (bfd *abfd, LONGEST str_offset)
+{
+  return read_indirect_string_at_offset_from (abfd, str_offset,
+                                             &dwarf2_per_objfile->line_str,
+                                             "DW_FORM_line_strp",
+                                             ".debug_line_str");
 }
 
 /* Read a string at offset STR_OFFSET in the .debug_str section from
@@ -16773,6 +17166,10 @@ read_indirect_string_from_dwz (struct dwz_file *dwz, LONGEST str_offset)
   return (const char *) (dwz->str.buffer + str_offset);
 }
 
+/* Return pointer to string at .debug_str offset as read from BUF.
+   BUF is assumed to be in a compilation unit described by CU_HEADER.
+   Return *BYTES_READ_PTR count of bytes read from BUF.  */
+
 static const char *
 read_indirect_string (bfd *abfd, const gdb_byte *buf,
                      const struct comp_unit_head *cu_header,
@@ -16783,9 +17180,23 @@ read_indirect_string (bfd *abfd, const gdb_byte *buf,
   return read_indirect_string_at_offset (abfd, str_offset);
 }
 
-static ULONGEST
+/* Return pointer to string at .debug_line_str offset as read from BUF.
+   BUF is assumed to be in a compilation unit described by CU_HEADER.
+   Return *BYTES_READ_PTR count of bytes read from BUF.  */
+
+static const char *
+read_indirect_line_string (bfd *abfd, const gdb_byte *buf,
+                          const struct comp_unit_head *cu_header,
+                          unsigned int *bytes_read_ptr)
+{
+  LONGEST str_offset = read_offset (abfd, buf, cu_header, bytes_read_ptr);
+
+  return read_indirect_line_string_at_offset (abfd, str_offset);
+}
+
+ULONGEST
 read_unsigned_leb128 (bfd *abfd, const gdb_byte *buf,
-                     unsigned int *bytes_read_ptr)
+                         unsigned int *bytes_read_ptr)
 {
   ULONGEST result;
   unsigned int num_read;
@@ -16987,16 +17398,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)
@@ -17005,8 +17416,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);
 }
 
@@ -17145,14 +17556,14 @@ dwarf2_string_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *c
 
   if (attr != NULL)
     {
-      if (attr->form == DW_FORM_strp || attr->form == DW_FORM_string
-         || attr->form == DW_FORM_GNU_strp_alt)
+      if (attr->form == DW_FORM_strp || attr->form == DW_FORM_line_strp
+         || attr->form == DW_FORM_string || 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));
     }
 
@@ -17206,28 +17617,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
@@ -17235,69 +17624,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.  */
@@ -17323,6 +17673,135 @@ get_debug_line_section (struct dwarf2_cu *cu)
   return section;
 }
 
+/* Read directory or file name entry format, starting with byte of
+   format count entries, ULEB128 pairs of entry formats, ULEB128 of
+   entries count and the entries themselves in the described entry
+   format.  */
+
+static void
+read_formatted_entries (bfd *abfd, const gdb_byte **bufp,
+                       struct line_header *lh,
+                       const struct comp_unit_head *cu_header,
+                       void (*callback) (struct line_header *lh,
+                                         const char *name,
+                                         dir_index d_index,
+                                         unsigned int mod_time,
+                                         unsigned int length))
+{
+  gdb_byte format_count, formati;
+  ULONGEST data_count, datai;
+  const gdb_byte *buf = *bufp;
+  const gdb_byte *format_header_data;
+  int i;
+  unsigned int bytes_read;
+
+  format_count = read_1_byte (abfd, buf);
+  buf += 1;
+  format_header_data = buf;
+  for (formati = 0; formati < format_count; formati++)
+    {
+      read_unsigned_leb128 (abfd, buf, &bytes_read);
+      buf += bytes_read;
+      read_unsigned_leb128 (abfd, buf, &bytes_read);
+      buf += bytes_read;
+    }
+
+  data_count = read_unsigned_leb128 (abfd, buf, &bytes_read);
+  buf += bytes_read;
+  for (datai = 0; datai < data_count; datai++)
+    {
+      const gdb_byte *format = format_header_data;
+      struct file_entry fe;
+
+      for (formati = 0; formati < format_count; formati++)
+       {
+         ULONGEST content_type = read_unsigned_leb128 (abfd, format, &bytes_read);
+         format += bytes_read;
+
+         ULONGEST form  = read_unsigned_leb128 (abfd, format, &bytes_read);
+         format += bytes_read;
+
+         gdb::optional<const char *> string;
+         gdb::optional<unsigned int> uint;
+
+         switch (form)
+           {
+           case DW_FORM_string:
+             string.emplace (read_direct_string (abfd, buf, &bytes_read));
+             buf += bytes_read;
+             break;
+
+           case DW_FORM_line_strp:
+             string.emplace (read_indirect_line_string (abfd, buf,
+                                                        cu_header,
+                                                        &bytes_read));
+             buf += bytes_read;
+             break;
+
+           case DW_FORM_data1:
+             uint.emplace (read_1_byte (abfd, buf));
+             buf += 1;
+             break;
+
+           case DW_FORM_data2:
+             uint.emplace (read_2_bytes (abfd, buf));
+             buf += 2;
+             break;
+
+           case DW_FORM_data4:
+             uint.emplace (read_4_bytes (abfd, buf));
+             buf += 4;
+             break;
+
+           case DW_FORM_data8:
+             uint.emplace (read_8_bytes (abfd, buf));
+             buf += 8;
+             break;
+
+           case DW_FORM_udata:
+             uint.emplace (read_unsigned_leb128 (abfd, buf, &bytes_read));
+             buf += bytes_read;
+             break;
+
+           case DW_FORM_block:
+             /* It is valid only for DW_LNCT_timestamp which is ignored by
+                current GDB.  */
+             break;
+           }
+
+         switch (content_type)
+           {
+           case DW_LNCT_path:
+             if (string.has_value ())
+               fe.name = *string;
+             break;
+           case DW_LNCT_directory_index:
+             if (uint.has_value ())
+               fe.d_index = (dir_index) *uint;
+             break;
+           case DW_LNCT_timestamp:
+             if (uint.has_value ())
+               fe.mod_time = *uint;
+             break;
+           case DW_LNCT_size:
+             if (uint.has_value ())
+               fe.length = *uint;
+             break;
+           case DW_LNCT_MD5:
+             break;
+           default:
+             complaint (&symfile_complaints,
+                        _("Unknown format content type %s"),
+                        pulongest (content_type));
+           }
+       }
+
+      callback (lh, fe.name, fe.d_index, fe.mod_time, fe.length);
+    }
+
+  *bufp = buf;
+}
+
 /* Read the statement program header starting at OFFSET in
    .debug_line, or .debug_line.dwo.  Return a pointer
    to a struct line_header, allocated using xmalloc.
@@ -17333,11 +17812,9 @@ get_debug_line_section (struct dwarf2_cu *cu)
    the returned object point into the dwarf line section buffer,
    and must not be freed.  */
 
-static struct line_header *
-dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
+static line_header_up
+dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu)
 {
-  struct cleanup *back_to;
-  struct line_header *lh;
   const gdb_byte *line_ptr;
   unsigned int bytes_read, offset_size;
   int i;
@@ -17362,21 +17839,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 =
@@ -17386,13 +17860,12 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
   if (line_ptr + lh->total_length > (section->buffer + section->size))
     {
       dwarf2_statement_list_fits_in_line_number_section_complaint ();
-      do_cleanups (back_to);
       return 0;
     }
   lh->statement_program_end = line_ptr + lh->total_length;
   lh->version = read_2_bytes (abfd, line_ptr);
   line_ptr += 2;
-  if (lh->version > 4)
+  if (lh->version > 5)
     {
       /* This is a version we don't understand.  The format could have
         changed in ways we don't handle properly so just punt.  */
@@ -17400,6 +17873,25 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
                 _("unsupported version in .debug_line section"));
       return NULL;
     }
+  if (lh->version >= 5)
+    {
+      gdb_byte segment_selector_size;
+
+      /* Skip address size.  */
+      read_1_byte (abfd, line_ptr);
+      line_ptr += 1;
+
+      segment_selector_size = read_1_byte (abfd, line_ptr);
+      line_ptr += 1;
+      if (segment_selector_size != 0)
+       {
+         complaint (&symfile_complaints,
+                    _("unsupported segment selector size %u "
+                      "in .debug_line section"),
+                    segment_selector_size);
+         return NULL;
+       }
+    }
   lh->header_length = read_offset_1 (abfd, line_ptr, offset_size);
   line_ptr += offset_size;
   lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
@@ -17428,7 +17920,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)
@@ -17437,30 +17929,54 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
       line_ptr += 1;
     }
 
-  /* Read directory table.  */
-  while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
+  if (lh->version >= 5)
     {
-      line_ptr += bytes_read;
-      add_include_dir (lh, cur_dir);
+      /* Read directory table.  */
+      read_formatted_entries (abfd, &line_ptr, lh.get (), &cu->header,
+                             [] (struct line_header *lh, const char *name,
+                                 dir_index d_index, unsigned int mod_time,
+                                 unsigned int length)
+       {
+         lh->add_include_dir (name);
+       });
+
+      /* Read file name table.  */
+      read_formatted_entries (abfd, &line_ptr, lh.get (), &cu->header,
+                             [] (struct line_header *lh, const char *name,
+                                 dir_index d_index, unsigned int mod_time,
+                                 unsigned int length)
+       {
+         lh->add_file_name (name, d_index, mod_time, length);
+       });
     }
-  line_ptr += bytes_read;
-
-  /* Read file name table.  */
-  while ((cur_file = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
+  else
     {
-      unsigned int dir_index, mod_time, length;
-
-      line_ptr += bytes_read;
-      dir_index = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-      line_ptr += bytes_read;
-      mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-      line_ptr += bytes_read;
-      length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+      /* Read directory table.  */
+      while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
+       {
+         line_ptr += bytes_read;
+         lh->add_include_dir (cur_dir);
+       }
       line_ptr += bytes_read;
 
-      add_file_name (lh, cur_file, dir_index, mod_time, length);
+      /* Read file name table.  */
+      while ((cur_file = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
+       {
+         unsigned int mod_time, length;
+         dir_index d_index;
+
+         line_ptr += bytes_read;
+         d_index = (dir_index) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+         line_ptr += bytes_read;
+         mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+         line_ptr += bytes_read;
+         length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+         line_ptr += bytes_read;
+
+         lh->add_file_name (cur_file, d_index, mod_time, length);
+       }
+      line_ptr += bytes_read;
     }
-  line_ptr += bytes_read;
   lh->statement_program_start = line_ptr;
 
   if (line_ptr > (section->buffer + section->size))
@@ -17468,7 +17984,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;
 }
 
@@ -17486,16 +18001,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))
@@ -17560,51 +18073,203 @@ psymtab_include_file_name (const struct line_header *lh, int file_index,
 
 /* State machine to track the state of the line number program.  */
 
-typedef struct
+class lnp_state_machine
 {
-  /* These are part of the standard DWARF line number state machine.  */
+public:
+  /* Initialize a machine state for the start of a line number
+     program.  */
+  lnp_state_machine (gdbarch *arch, line_header *lh, bool record_lines_p);
+
+  file_entry *current_file ()
+  {
+    /* lh->file_names is 0-based, but the file name numbers in the
+       statement program are 1-based.  */
+    return m_line_header->file_name_at (m_file);
+  }
+
+  /* Record the line in the state machine.  END_SEQUENCE is true if
+     we're processing the end of a sequence.  */
+  void record_line (bool end_sequence);
+
+  /* Check address and if invalid nop-out the rest of the lines in this
+     sequence.  */
+  void check_line_address (struct dwarf2_cu *cu,
+                          const gdb_byte *line_ptr,
+                          CORE_ADDR lowpc, CORE_ADDR address);
+
+  void handle_set_discriminator (unsigned int discriminator)
+  {
+    m_discriminator = discriminator;
+    m_line_has_non_zero_discriminator |= discriminator != 0;
+  }
+
+  /* Handle DW_LNE_set_address.  */
+  void handle_set_address (CORE_ADDR baseaddr, CORE_ADDR address)
+  {
+    m_op_index = 0;
+    address += baseaddr;
+    m_address = gdbarch_adjust_dwarf2_line (m_gdbarch, address, false);
+  }
+
+  /* Handle DW_LNS_advance_pc.  */
+  void handle_advance_pc (CORE_ADDR adjust);
+
+  /* Handle a special opcode.  */
+  void handle_special_opcode (unsigned char op_code);
+
+  /* Handle DW_LNS_advance_line.  */
+  void handle_advance_line (int line_delta)
+  {
+    advance_line (line_delta);
+  }
+
+  /* Handle DW_LNS_set_file.  */
+  void handle_set_file (file_name_index file);
+
+  /* Handle DW_LNS_negate_stmt.  */
+  void handle_negate_stmt ()
+  {
+    m_is_stmt = !m_is_stmt;
+  }
+
+  /* Handle DW_LNS_const_add_pc.  */
+  void handle_const_add_pc ();
+
+  /* Handle DW_LNS_fixed_advance_pc.  */
+  void handle_fixed_advance_pc (CORE_ADDR addr_adj)
+  {
+    m_address += gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
+    m_op_index = 0;
+  }
+
+  /* Handle DW_LNS_copy.  */
+  void handle_copy ()
+  {
+    record_line (false);
+    m_discriminator = 0;
+  }
+
+  /* Handle DW_LNE_end_sequence.  */
+  void handle_end_sequence ()
+  {
+    m_record_line_callback = ::record_line;
+  }
+
+private:
+  /* Advance the line by LINE_DELTA.  */
+  void advance_line (int line_delta)
+  {
+    m_line += line_delta;
+
+    if (line_delta != 0)
+      m_line_has_non_zero_discriminator = m_discriminator != 0;
+  }
+
+  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;
 
-  unsigned char op_index;
-  unsigned int file;
-  unsigned int line;
-  CORE_ADDR address;
-  int is_stmt;
-  unsigned int discriminator;
+  /* 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.  */
 
@@ -17705,102 +18370,76 @@ dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile,
   dwarf_record_line_1 (gdbarch, subfile, 0, address, p_record_line);
 }
 
-/* Record the line in STATE.
-   END_SEQUENCE is non-zero if we're processing the end of a sequence.  */
-
-static void
-dwarf_record_line (lnp_reader_state *reader, lnp_state_machine *state,
-                  int end_sequence)
+void
+lnp_state_machine::record_line (bool end_sequence)
 {
-  const struct line_header *lh = reader->line_header;
-  unsigned int file, line, discriminator;
-  int is_stmt;
-
-  file = state->file;
-  line = state->line;
-  is_stmt = state->is_stmt;
-  discriminator = state->discriminator;
-
   if (dwarf_line_debug)
     {
       fprintf_unfiltered (gdb_stdlog,
                          "Processing actual line %u: file %u,"
                          " address %s, is_stmt %u, discrim %u\n",
-                         line, file,
-                         paddress (reader->gdbarch, state->address),
-                         is_stmt, discriminator);
+                         m_line, to_underlying (m_file),
+                         paddress (m_gdbarch, m_address),
+                         m_is_stmt, m_discriminator);
     }
 
-  if (file == 0 || file - 1 >= lh->num_file_names)
+  file_entry *fe = current_file ();
+
+  if (fe == NULL)
     dwarf2_debug_line_missing_file_complaint ();
   /* For now we ignore lines not starting on an instruction boundary.
      But not when processing end_sequence for compatibility with the
      previous version of the code.  */
-  else if (state->op_index == 0 || end_sequence)
+  else if (m_op_index == 0 || end_sequence)
     {
-      lh->file_names[file - 1].included_p = 1;
-      if (reader->record_lines_p && is_stmt)
+      fe->included_p = 1;
+      if (m_record_lines_p && m_is_stmt)
        {
-         if (state->last_subfile != current_subfile || end_sequence)
+         if (m_last_subfile != current_subfile || end_sequence)
            {
-             dwarf_finish_line (reader->gdbarch, state->last_subfile,
-                                state->address, state->record_line);
+             dwarf_finish_line (m_gdbarch, m_last_subfile,
+                                m_address, m_record_line_callback);
            }
 
          if (!end_sequence)
            {
-             if (dwarf_record_line_p (line, state->last_line,
-                                      state->line_has_non_zero_discriminator,
-                                      state->last_subfile))
+             if (dwarf_record_line_p (m_line, m_last_line,
+                                      m_line_has_non_zero_discriminator,
+                                      m_last_subfile))
                {
-                 dwarf_record_line_1 (reader->gdbarch, current_subfile,
-                                      line, state->address,
-                                      state->record_line);
+                 dwarf_record_line_1 (m_gdbarch, current_subfile,
+                                      m_line, m_address,
+                                      m_record_line_callback);
                }
-             state->last_subfile = current_subfile;
-             state->last_line = line;
+             m_last_subfile = current_subfile;
+             m_last_line = m_line;
            }
        }
     }
 }
 
-/* Initialize STATE for the start of a line number program.  */
-
-static void
-init_lnp_state_machine (lnp_state_machine *state,
-                       const lnp_reader_state *reader)
+lnp_state_machine::lnp_state_machine (gdbarch *arch, line_header *lh,
+                                     bool record_lines_p)
 {
-  memset (state, 0, sizeof (*state));
-
-  /* Just starting, there is no "last file".  */
-  state->last_file = 0;
-  state->last_subfile = NULL;
+  m_gdbarch = arch;
+  m_record_lines_p = record_lines_p;
+  m_line_header = lh;
 
-  state->record_line = record_line;
+  m_record_line_callback = ::record_line;
 
-  state->last_line = 0;
-  state->line_has_non_zero_discriminator = 0;
-
-  /* Initialize these according to the DWARF spec.  */
-  state->op_index = 0;
-  state->file = 1;
-  state->line = 1;
   /* Call `gdbarch_adjust_dwarf2_line' on the initial 0 address as if there
      was a line entry for it so that the backend has a chance to adjust it
      and also record it in case it needs it.  This is currently used by MIPS
      code, cf. `mips_adjust_dwarf2_line'.  */
-  state->address = gdbarch_adjust_dwarf2_line (reader->gdbarch, 0, 0);
-  state->is_stmt = reader->line_header->default_is_stmt;
-  state->discriminator = 0;
+  m_address = gdbarch_adjust_dwarf2_line (arch, 0, 0);
+  m_is_stmt = lh->default_is_stmt;
+  m_discriminator = 0;
 }
 
-/* Check address and if invalid nop-out the rest of the lines in this
-   sequence.  */
-
-static void
-check_line_address (struct dwarf2_cu *cu, lnp_state_machine *state,
-                   const gdb_byte *line_ptr,
-                   CORE_ADDR lowpc, CORE_ADDR address)
+void
+lnp_state_machine::check_line_address (struct dwarf2_cu *cu,
+                                      const gdb_byte *line_ptr,
+                                      CORE_ADDR lowpc, CORE_ADDR address)
 {
   /* If address < lowpc then it's not a usable value, it's outside the
      pc range of the CU.  However, we restrict the test to only address
@@ -17818,9 +18457,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.  */
     }
 }
 
@@ -17841,44 +18480,32 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
   struct objfile *objfile = cu->objfile;
   bfd *abfd = objfile->obfd;
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
-  /* Non-zero if we're recording line info (as opposed to building partial
-     symtabs).  */
-  int record_lines_p = !decode_for_pst_p;
-  /* A collection of things we need to pass to dwarf_record_line.  */
-  lnp_reader_state reader_state;
+  /* True if we're recording line info (as opposed to building partial
+     symtabs and just interested in finding include files mentioned by
+     the line number program).  */
+  bool record_lines_p = !decode_for_pst_p;
 
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
   line_ptr = lh->statement_program_start;
   line_end = lh->statement_program_end;
 
-  reader_state.gdbarch = gdbarch;
-  reader_state.line_header = lh;
-  reader_state.record_lines_p = record_lines_p;
-
   /* Read the statement sequences until there's nothing left.  */
   while (line_ptr < line_end)
     {
-      /* The DWARF line number program state machine.  */
-      lnp_state_machine state_machine;
-      int end_sequence = 0;
-
-      /* Reset the state machine at the start of each sequence.  */
-      init_lnp_state_machine (&state_machine, &reader_state);
+      /* The DWARF line number program state machine.  Reset the state
+        machine at the start of each sequence.  */
+      lnp_state_machine state_machine (gdbarch, lh, record_lines_p);
+      bool end_sequence = false;
 
-      if (record_lines_p && lh->num_file_names >= state_machine.file)
+      if (record_lines_p)
        {
-          /* Start a subfile for the current file of the state machine.  */
-         /* lh->include_dirs and lh->file_names are 0-based, but the
-            directory and file name numbers in the statement program
-            are 1-based.  */
-          struct file_entry *fe = &lh->file_names[state_machine.file - 1];
-          const char *dir = NULL;
+         /* Start a subfile for the current file of the state
+            machine.  */
+         const file_entry *fe = state_machine.current_file ();
 
-          if (fe->dir_index && lh->include_dirs != NULL)
-            dir = lh->include_dirs[fe->dir_index - 1];
-
-         dwarf2_start_subfile (fe->name, dir);
+         if (fe != NULL)
+           dwarf2_start_subfile (fe->name, fe->include_dir (lh));
        }
 
       /* Decode the table.  */
@@ -17890,28 +18517,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)
            {
@@ -17925,32 +18531,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 =
@@ -17959,20 +18563,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,
@@ -17990,64 +18597,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:
@@ -18055,7 +18632,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;
@@ -18065,28 +18642,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:
@@ -18108,7 +18671,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);
     }
 }
 
@@ -18157,7 +18720,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 =
@@ -18174,22 +18737,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;
        }
     }
 }
@@ -18398,19 +18957,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)
+           fe = cu->line_header->file_name_at (file_index);
+         else
+           fe = NULL;
 
-         if (cu->line_header == NULL
-             || file_index > cu->line_header->num_file_names)
+         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)
@@ -18824,6 +19383,7 @@ dwarf2_const_value_attr (const struct attribute *attr, struct type *type,
     case DW_FORM_block4:
     case DW_FORM_block:
     case DW_FORM_exprloc:
+    case DW_FORM_data16:
       blk = DW_BLOCK (attr);
       if (TYPE_LENGTH (type) != blk->size)
        dwarf2_const_value_length_mismatch_complaint (name, blk->size,
@@ -18993,8 +19553,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);
@@ -19023,16 +19583,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)
     {
@@ -19045,7 +19605,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);
     }
@@ -19132,7 +19692,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);
@@ -19253,7 +19816,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;
@@ -19306,7 +19869,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
@@ -19527,14 +20090,14 @@ dwarf2_canonicalize_name (const char *name, struct dwarf2_cu *cu,
 {
   if (name && cu->language == language_cplus)
     {
-      char *canon_name = cp_canonicalize_string (name);
+      std::string canon_name = cp_canonicalize_string (name);
 
-      if (canon_name != NULL)
+      if (!canon_name.empty ())
        {
-         if (strcmp (canon_name, name) != 0)
-           name = (const char *) obstack_copy0 (obstack, canon_name,
-                                                strlen (canon_name));
-         xfree (canon_name);
+         if (canon_name != name)
+           name = (const char *) obstack_copy0 (obstack,
+                                                canon_name.c_str (),
+                                                canon_name.length ());
        }
     }
 
@@ -19708,7 +20271,7 @@ dwarf_form_name (unsigned form)
   return name;
 }
 
-static char *
+static const char *
 dwarf_bool_name (unsigned mybool)
 {
   if (mybool)
@@ -19737,13 +20300,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);
@@ -19778,6 +20342,9 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
          fprintf_unfiltered (f, "expression: size %s",
                              pulongest (DW_BLOCK (&die->attrs[i])->size));
          break;
+       case DW_FORM_data16:
+         fprintf_unfiltered (f, "constant of 16 bytes");
+         break;
        case DW_FORM_ref_addr:
          fprintf_unfiltered (f, "ref address: ");
          fputs_filtered (hex_string (DW_UNSND (&die->attrs[i])), f);
@@ -19813,6 +20380,7 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
          break;
        case DW_FORM_string:
        case DW_FORM_strp:
+       case DW_FORM_line_strp:
        case DW_FORM_GNU_str_index:
        case DW_FORM_GNU_strp_alt:
          fprintf_unfiltered (f, "string: \"%s\" (%s canonicalized)",
@@ -19898,7 +20466,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;
@@ -19910,16 +20479,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
@@ -19938,6 +20504,7 @@ dwarf2_get_attr_constant_value (const struct attribute *attr, int default_value)
     return DW_UNSND (attr);
   else
     {
+      /* For DW_FORM_data16 see attr_form_is_constant.  */
       complaint (&symfile_complaints,
                 _("Attribute value is not a constant (%s)"),
                  dwarf_form_name (attr->form));
@@ -19975,7 +20542,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;
@@ -19990,15 +20557,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.  */
@@ -20015,9 +20582,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.
@@ -20028,29 +20596,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)
@@ -20070,13 +20638,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)
@@ -20104,7 +20672,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;
@@ -20125,9 +20693,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
@@ -20155,7 +20723,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)
@@ -20178,13 +20746,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);
@@ -20221,6 +20789,7 @@ dwarf2_fetch_constant_bytes (sect_offset offset,
     case DW_FORM_block4:
     case DW_FORM_block:
     case DW_FORM_exprloc:
+    case DW_FORM_data16:
       result = DW_BLOCK (attr)->data;
       *len = DW_BLOCK (attr)->size;
       break;
@@ -20281,6 +20850,31 @@ dwarf2_fetch_constant_bytes (sect_offset offset,
   return result;
 }
 
+/* Return the type of the die at OFFSET in PER_CU.  Return NULL if no
+   valid type for this die is found.  */
+
+struct type *
+dwarf2_fetch_die_type_sect_off (sect_offset sect_off,
+                               struct dwarf2_per_cu_data *per_cu)
+{
+  struct dwarf2_cu *cu;
+  struct die_info *die;
+
+  dw2_setup (per_cu->objfile);
+
+  if (per_cu->cu == NULL)
+    load_cu (per_cu);
+  cu = per_cu->cu;
+  if (!cu)
+    return NULL;
+
+  die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
+  if (!die)
+    return NULL;
+
+  return die_type (die, cu);
+}
+
 /* Return the type of the DIE at DIE_OFFSET in the CU named by
    PER_CU.  */
 
@@ -20288,11 +20882,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);
 }
 
@@ -20320,10 +20912,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.
@@ -20366,7 +20958,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));
     }
 
@@ -20376,7 +20968,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));
     }
 
@@ -20403,7 +20995,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);
     }
@@ -20425,7 +21017,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);
        }
@@ -20435,7 +21027,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);
     }
@@ -20468,7 +21060,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);
     }
@@ -20849,15 +21441,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
     {
@@ -20886,7 +21480,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);
 
@@ -21129,6 +21723,10 @@ skip_form_bytes (bfd *abfd, const gdb_byte *bytes, const gdb_byte *buffer_end,
       bytes += 8;
       break;
 
+    case DW_FORM_data16:
+      bytes += 16;
+      break;
+
     case DW_FORM_string:
       read_direct_string (abfd, bytes, &bytes_read);
       bytes += bytes_read;
@@ -21242,7 +21840,7 @@ dwarf_parse_macro_header (const gdb_byte **opcode_definitions,
       unsigned int version, flags;
 
       version = read_2_bytes (abfd, mac_ptr);
-      if (version != 4)
+      if (version != 4 && version != 5)
        {
          complaint (&symfile_complaints,
                     _("unrecognized version `%d' in .debug_macro section"),
@@ -21285,7 +21883,7 @@ dwarf_parse_macro_header (const gdb_byte **opcode_definitions,
 }
 
 /* A helper for dwarf_decode_macros that handles the GNU extensions,
-   including DW_MACRO_GNU_transparent_include.  */
+   including DW_MACRO_import.  */
 
 static void
 dwarf_decode_macro_bytes (bfd *abfd,
@@ -21340,12 +21938,12 @@ dwarf_decode_macro_bytes (bfd *abfd,
        case 0:
          break;
 
-        case DW_MACRO_GNU_define:
-        case DW_MACRO_GNU_undef:
-       case DW_MACRO_GNU_define_indirect:
-       case DW_MACRO_GNU_undef_indirect:
-       case DW_MACRO_GNU_define_indirect_alt:
-       case DW_MACRO_GNU_undef_indirect_alt:
+        case DW_MACRO_define:
+        case DW_MACRO_undef:
+       case DW_MACRO_define_strp:
+       case DW_MACRO_undef_strp:
+       case DW_MACRO_define_sup:
+       case DW_MACRO_undef_sup:
           {
             unsigned int bytes_read;
             int line;
@@ -21355,8 +21953,8 @@ dwarf_decode_macro_bytes (bfd *abfd,
            line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
            mac_ptr += bytes_read;
 
-           if (macinfo_type == DW_MACRO_GNU_define
-               || macinfo_type == DW_MACRO_GNU_undef)
+           if (macinfo_type == DW_MACRO_define
+               || macinfo_type == DW_MACRO_undef)
              {
                body = read_direct_string (abfd, mac_ptr, &bytes_read);
                mac_ptr += bytes_read;
@@ -21368,8 +21966,8 @@ dwarf_decode_macro_bytes (bfd *abfd,
                str_offset = read_offset_1 (abfd, mac_ptr, offset_size);
                mac_ptr += offset_size;
 
-               if (macinfo_type == DW_MACRO_GNU_define_indirect_alt
-                   || macinfo_type == DW_MACRO_GNU_undef_indirect_alt
+               if (macinfo_type == DW_MACRO_define_sup
+                   || macinfo_type == DW_MACRO_undef_sup
                    || section_is_dwz)
                  {
                    struct dwz_file *dwz = dwarf2_get_dwz_file ();
@@ -21380,9 +21978,9 @@ dwarf_decode_macro_bytes (bfd *abfd,
                  body = read_indirect_string_at_offset (abfd, str_offset);
              }
 
-           is_define = (macinfo_type == DW_MACRO_GNU_define
-                        || macinfo_type == DW_MACRO_GNU_define_indirect
-                        || macinfo_type == DW_MACRO_GNU_define_indirect_alt);
+           is_define = (macinfo_type == DW_MACRO_define
+                        || macinfo_type == DW_MACRO_define_strp
+                        || macinfo_type == DW_MACRO_define_sup);
             if (! current_file)
              {
                /* DWARF violation as no main source is present.  */
@@ -21405,15 +22003,15 @@ dwarf_decode_macro_bytes (bfd *abfd,
              parse_macro_definition (current_file, line, body);
            else
              {
-               gdb_assert (macinfo_type == DW_MACRO_GNU_undef
-                           || macinfo_type == DW_MACRO_GNU_undef_indirect
-                           || macinfo_type == DW_MACRO_GNU_undef_indirect_alt);
+               gdb_assert (macinfo_type == DW_MACRO_undef
+                           || macinfo_type == DW_MACRO_undef_strp
+                           || macinfo_type == DW_MACRO_undef_sup);
                macro_undef (current_file, line, body);
              }
           }
           break;
 
-        case DW_MACRO_GNU_start_file:
+        case DW_MACRO_start_file:
           {
             unsigned int bytes_read;
             int line, file;
@@ -21433,7 +22031,7 @@ dwarf_decode_macro_bytes (bfd *abfd,
 
            if (at_commandline)
              {
-               /* This DW_MACRO_GNU_start_file was executed in the
+               /* This DW_MACRO_start_file was executed in the
                   pass one.  */
                at_commandline = 0;
              }
@@ -21442,7 +22040,7 @@ dwarf_decode_macro_bytes (bfd *abfd,
           }
           break;
 
-        case DW_MACRO_GNU_end_file:
+        case DW_MACRO_end_file:
           if (! current_file)
            complaint (&symfile_complaints,
                       _("macro debug info has an unmatched "
@@ -21481,8 +22079,8 @@ dwarf_decode_macro_bytes (bfd *abfd,
             }
           break;
 
-       case DW_MACRO_GNU_transparent_include:
-       case DW_MACRO_GNU_transparent_include_alt:
+       case DW_MACRO_import:
+       case DW_MACRO_import_sup:
          {
            LONGEST offset;
            void **slot;
@@ -21495,7 +22093,7 @@ dwarf_decode_macro_bytes (bfd *abfd,
            offset = read_offset_1 (abfd, mac_ptr, offset_size);
            mac_ptr += offset_size;
 
-           if (macinfo_type == DW_MACRO_GNU_transparent_include_alt)
+           if (macinfo_type == DW_MACRO_import_sup)
              {
                struct dwz_file *dwz = dwarf2_get_dwz_file ();
 
@@ -21515,7 +22113,7 @@ dwarf_decode_macro_bytes (bfd *abfd,
                /* This has actually happened; see
                   http://sourceware.org/bugzilla/show_bug.cgi?id=13568.  */
                complaint (&symfile_complaints,
-                          _("recursive DW_MACRO_GNU_transparent_include in "
+                          _("recursive DW_MACRO_import in "
                             ".debug_macro section"));
              }
            else
@@ -21573,7 +22171,6 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
   unsigned int offset_size = cu->header.offset_size;
   const gdb_byte *opcode_definitions[256];
   struct cleanup *cleanup;
-  htab_t include_hash;
   void **slot;
   struct dwarf2_section_info *section;
   const char *section_name;
@@ -21658,8 +22255,8 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
         case 0:
          break;
 
-       case DW_MACRO_GNU_define:
-       case DW_MACRO_GNU_undef:
+       case DW_MACRO_define:
+       case DW_MACRO_undef:
          /* Only skip the data by MAC_PTR.  */
          {
            unsigned int bytes_read;
@@ -21671,7 +22268,7 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
          }
          break;
 
-       case DW_MACRO_GNU_start_file:
+       case DW_MACRO_start_file:
          {
            unsigned int bytes_read;
            int line, file;
@@ -21685,14 +22282,14 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
          }
          break;
 
-       case DW_MACRO_GNU_end_file:
+       case DW_MACRO_end_file:
          /* No data to skip by MAC_PTR.  */
          break;
 
-       case DW_MACRO_GNU_define_indirect:
-       case DW_MACRO_GNU_undef_indirect:
-       case DW_MACRO_GNU_define_indirect_alt:
-       case DW_MACRO_GNU_undef_indirect_alt:
+       case DW_MACRO_define_strp:
+       case DW_MACRO_undef_strp:
+       case DW_MACRO_define_sup:
+       case DW_MACRO_undef_sup:
          {
            unsigned int bytes_read;
 
@@ -21702,10 +22299,10 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
          }
          break;
 
-       case DW_MACRO_GNU_transparent_include:
-       case DW_MACRO_GNU_transparent_include_alt:
+       case DW_MACRO_import:
+       case DW_MACRO_import_sup:
          /* Note that, according to the spec, a transparent include
-            chain cannot call DW_MACRO_GNU_start_file.  So, we can just
+            chain cannot call DW_MACRO_start_file.  So, we can just
             skip this opcode.  */
          mac_ptr += offset_size;
          break;
@@ -21739,16 +22336,16 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
      command-line macro definitions/undefinitions.  This flag is unset when we
      reach the first DW_MACINFO_start_file entry.  */
 
-  include_hash = htab_create_alloc (1, htab_hash_pointer, htab_eq_pointer,
-                                   NULL, xcalloc, xfree);
-  cleanup = make_cleanup_htab_delete (include_hash);
+  htab_up include_hash (htab_create_alloc (1, htab_hash_pointer,
+                                          htab_eq_pointer,
+                                          NULL, xcalloc, xfree));
   mac_ptr = section->buffer + offset;
-  slot = htab_find_slot (include_hash, mac_ptr, INSERT);
+  slot = htab_find_slot (include_hash.get (), mac_ptr, INSERT);
   *slot = (void *) mac_ptr;
   dwarf_decode_macro_bytes (abfd, mac_ptr, mac_end,
                            current_file, lh, section,
-                           section_is_gnu, 0, offset_size, include_hash);
-  do_cleanups (cleanup);
+                           section_is_gnu, 0, offset_size,
+                           include_hash.get ());
 }
 
 /* Check if the attribute's form is a DW_FORM_block*
@@ -21793,7 +22390,10 @@ attr_form_is_section_offset (const struct attribute *attr)
    (lineptr, loclistptr, macptr or rangelistptr).  The DWARF spec says
    that, if an attribute's can be either a constant or one of the
    section offset classes, DW_FORM_data4 and DW_FORM_data8 should be
-   taken as section offsets, not constants.  */
+   taken as section offsets, not constants.
+
+   DW_FORM_data16 is not considered as dwarf2_get_attr_constant_value
+   cannot handle that.  */
 
 static int
 attr_form_is_constant (const struct attribute *attr)
@@ -21841,8 +22441,13 @@ static struct dwarf2_section_info *
 cu_debug_loc_section (struct dwarf2_cu *cu)
 {
   if (cu->dwo_unit)
-    return &cu->dwo_unit->dwo_file->sections.loc;
-  return &dwarf2_per_objfile->loc;
+    {
+      struct dwo_sections *sections = &cu->dwo_unit->dwo_file->sections;
+      
+      return cu->header.version >= 5 ? &sections->loclists : &sections->loc;
+    }
+  return (cu->header.version >= 5 ? &dwarf2_per_objfile->loclists
+                                 : &dwarf2_per_objfile->loc);
 }
 
 /* A helper function that fills in a dwarf2_loclist_baton.  */
@@ -21957,10 +22562,11 @@ per_cu_header_read_in (struct comp_unit_head *cu_headerp,
   if (per_cu->cu)
     return &per_cu->cu->header;
 
-  info_ptr = per_cu->section->buffer + per_cu->offset.sect_off;
+  info_ptr = per_cu->section->buffer + to_underlying (per_cu->sect_off);
 
   memset (cu_headerp, 0, sizeof (*cu_headerp));
-  read_comp_unit_head (cu_headerp, info_ptr, per_cu->objfile->obfd);
+  read_comp_unit_head (cu_headerp, info_ptr, per_cu->section,
+                      rcuh_kind::COMPILE);
 
   return cu_headerp;
 }
@@ -22020,11 +22626,19 @@ dwarf2_per_cu_text_offset (struct dwarf2_per_cu_data *per_cu)
   return ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 }
 
+/* Return DWARF version number of PER_CU.  */
+
+short
+dwarf2_version (struct dwarf2_per_cu_data *per_cu)
+{
+  return per_cu->dwarf_version;
+}
+
 /* Locate the .debug_info compilation unit from CU's objfile which contains
    the DIE at OFFSET.  Raises an error on failure.  */
 
 static struct dwarf2_per_cu_data *
-dwarf2_find_containing_comp_unit (sect_offset offset,
+dwarf2_find_containing_comp_unit (sect_offset sect_off,
                                  unsigned int offset_in_dwz,
                                  struct objfile *objfile)
 {
@@ -22040,35 +22654,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;
     }
 }
@@ -22273,7 +22886,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;
 };
 
@@ -22285,7 +22898,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.  */
@@ -22299,7 +22912,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
@@ -22354,9 +22967,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.  */
@@ -22369,9 +22982,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.  */
@@ -22392,25 +23005,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;
@@ -22419,7 +23032,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)
@@ -22434,7 +23047,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.  */
@@ -22516,7 +23129,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
@@ -22530,7 +23143,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;
@@ -22583,69 +23196,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
+/* In-memory buffer to prepare data to be written later to a file.  */
+class data_buf
 {
-  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)
-{
-  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
@@ -22656,107 +23258,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);
     }
 }
 
@@ -22765,24 +23301,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;
-
-  symtab->size *= 2;
-  symtab->data = XCNEWVEC (struct symtab_index_entry *, symtab->size);
+  auto old_entries = std::move (symtab->data);
 
-  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];
-       }
-    }
+  symtab->data.clear ();
+  symtab->data.resize (old_entries.size () * 2);
 
-  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.
@@ -22794,20 +23323,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;
@@ -22822,18 +23348,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.  */
@@ -22841,112 +23356,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
        {
@@ -22956,50 +23475,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
@@ -23011,24 +23503,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.  */
@@ -23040,44 +23527,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,
@@ -23089,7 +23571,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);
 }
@@ -23136,7 +23618,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,
@@ -23145,53 +23627,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"));
-}
-
-/* Unlink a file if the argument is not NULL.  */
-
-static void
-unlink_if_set (void *p)
-{
-  char **filename = (char **) p;
-  if (*filename)
-    unlink (*filename);
-}
-
 /* 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;
 };
 
@@ -23205,7 +23667,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,
@@ -23220,20 +23681,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.  */
 
@@ -23241,7 +23715,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;
@@ -23263,24 +23737,25 @@ recursively_write_psymbols (struct objfile *objfile,
                  1);
 }
 
+/* Closes FILE on scope exit.  */
+struct file_closer
+{
+  explicit file_closer (FILE *file)
+    : m_file (file)
+  {}
+
+  ~file_closer ()
+  { fclose (m_file); }
+
+private:
+  FILE *m_file;
+};
+
 /* Create an index file for OBJFILE in the directory DIR.  */
 
 static void
 write_psymtabs_to_index (struct objfile *objfile, const char *dir)
 {
-  struct cleanup *cleanup;
-  char *filename, *cleanup_filename;
-  struct obstack contents, addr_obstack, constant_pool, symtab_obstack;
-  struct obstack cu_list, types_cu_list;
-  int i;
-  FILE *out_file;
-  struct mapped_symtab *symtab;
-  offset_type val, size_of_contents, total_len;
-  struct stat st;
-  htab_t psyms_seen;
-  htab_t cu_index_htab;
-  struct psymtab_cu_index_map *psymtab_cu_index_map;
-
   if (dwarf2_per_objfile->using_index)
     error (_("Cannot use an index to create the index"));
 
@@ -23290,60 +23765,57 @@ 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");
   if (!out_file)
-    error (_("Can't open `%s' for writing"), filename);
-
-  cleanup_filename = filename;
-  make_cleanup (unlink_if_set, &cleanup_filename);
-
-  symtab = create_mapped_symtab ();
-  make_cleanup (cleanup_mapped_symtab, symtab);
+    error (_("Can't open `%s' for writing"), filename.c_str ());
 
-  obstack_init (&addr_obstack);
-  make_cleanup_obstack_free (&addr_obstack);
+  file_closer close_out_file (out_file);
+  gdb::unlinker unlink_file (filename.c_str ());
 
-  obstack_init (&cu_list);
-  make_cleanup_obstack_free (&cu_list);
-
-  obstack_init (&types_cu_list);
-  make_cleanup_obstack_free (&types_cu_list);
-
-  psyms_seen = htab_create_alloc (100, htab_hash_pointer, htab_eq_pointer,
-                                 NULL, xcalloc, xfree);
-  make_cleanup_htab_delete (psyms_seen);
+  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.  */
-  cu_index_htab = htab_create_alloc (100,
-                                    hash_psymtab_cu_index,
-                                    eq_psymtab_cu_index,
-                                    NULL, xcalloc, xfree);
-  make_cleanup_htab_delete (cu_index_htab);
-  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
@@ -23352,35 +23824,30 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
        continue;
 
       if (psymtab->user == NULL)
-       recursively_write_psymbols (objfile, psymtab, symtab, psyms_seen, 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, 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);
+  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;
+      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);
@@ -23388,64 +23855,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);
+  contents.append_data (MAYBE_SWAP (total_len));
+  total_len += constant_pool.size ();
 
-  gdb_assert (obstack_object_size (&contents) == size_of_contents);
+  gdb_assert (contents.size () == size_of_contents);
 
-  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);
+  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);
 
-  fclose (out_file);
-
-  /* We want to keep the file, so we set cleanup_filename to NULL
-     here.  See unlink_if_set.  */
-  cleanup_filename = NULL;
-
-  do_cleanups (cleanup);
+  /* We want to keep the file.  */
+  unlink_file.keep ();
 }
 
 /* Implementation of the `save gdb-index' command.
This page took 0.138861 seconds and 4 git commands to generate.