This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Increasing support for dwarf 5


(In the items below, "now" means "in dwarf 5").

* Support for .debug_str_offsets section:
  -  str_offsets_base attribute

* string and address indexes that point to an entry in .debug_str_offsets
and
.addr_offsets need special handling because they need .str_offsets_base and
addr_base attributes be known at the time, however, those attributes may
occur
later in the DIE. So, such attributes need to be reprocessed after other
parts
of the DIE are parsed.

* DW_FORM_GNU_str_index, DW_FORM_strx and other similar forms can also occur
in .dwo files. Likewise for DW_FORM_GNU_addr_index and DW_FORM_addrx.

* DW_UT_skeleton and DW_UT_split_compile compilation units also have
signatures
to match the compilation unit in the skeleton and .dwo files. The signature
is
part of the header.

* DW_AT_dwo_name is a new name for DW_AT_GNU_dwo_name.

* File and directory indexes in line table are now zero based.

* Line table header has new fields.

* Adding support for DW_UT_partial, DW_UT_skeleton, DW_UT_split_compile
compilation units.

After these changes, gdb is able to process a 'hello world' program compiled
with -gdwarf-5 flag. It is also able to support an additional -gsplit-dwarf
flag. As future work, it does not yet support address and range lists, also
type units may be lacking some support.
---
 gdb/dwarf2read.c | 597
+++++++++++++++++++++++++++++++++++++++----------------
 gdb/dwarf2read.h |   1 +
 gdb/symfile.h    |   1 +
 3 files changed, 425 insertions(+), 174 deletions(-)

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index de9755f6ce..73a83ae4cb 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -299,6 +299,7 @@ static const struct dwarf2_debug_sections
dwarf2_elf_names =
   { ".debug_macinfo", ".zdebug_macinfo" },
   { ".debug_macro", ".zdebug_macro" },
   { ".debug_str", ".zdebug_str" },
+  { ".debug_str_offsets", ".zdebug_str_offsets" },
   { ".debug_line_str", ".zdebug_line_str" },
   { ".debug_ranges", ".zdebug_ranges" },
   { ".debug_rnglists", ".zdebug_rnglists" },
@@ -373,8 +374,9 @@ struct comp_unit_head
      This will be the first byte following the compilation unit header.  */
   cu_offset first_die_cu_offset;

-  /* 64-bit signature of this type unit - it is valid only for
-     UNIT_TYPE DW_UT_type.  */
+  /* 64-bit signature of this type unit. In dwarf 4, it is valid only for
+     UNIT_TYPE DW_UT_type. In dwarf 5, DW_UT_split_type, DW_UT_partial,
+     DW_UT_skeleton, DW_UT_split_compile also contain a signature.  */
   ULONGEST signature;

   /* For types, offset in the type's DIE of the type defined by this TU.
 */
@@ -541,6 +543,12 @@ public:
      all such types here and process them after expansion.  */
   std::vector<struct type *> rust_unions;

+  /* The DW_AT_str_offsets_base attribute if present. For dw4 version DWO
files,
+     the value is implicitly zero. For dw5 version DWO files, the value is
often
+     implicit and is the size of the header of .debug_str_offsets section
(i.e.
+     8 or 4, depending on the address size).  */
+  gdb::optional<ULONGEST> str_offsets_base {};
+
   /* Mark used when releasing cached dies.  */
   bool mark : 1;

@@ -706,7 +714,7 @@ struct dwo_file
   dwo_file () = default;
   DISABLE_COPY_AND_ASSIGN (dwo_file);

-  /* The DW_AT_GNU_dwo_name attribute.
+  /* The DW_AT_GNU_dwo_name or DW_AT_dwo_name attribute.
      For virtual DWO files the name is constructed from the section offsets
      of abbrev,line,loc,str_offsets so that we combine virtual DWO files
      from related CU+TUs.  */
@@ -918,13 +926,13 @@ 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 {};
+/* dir_index is 1-based in dwarf 4 and before, and is 0-based in dwarf5 and
+   later.  */
+typedef int dir_index;

-/* Likewise, a 1-based file name index.  */
-enum class file_name_index : unsigned int {};
+/* file_name_index is 1-based in dwarf 4 and before, and is 0-based in
dwarf5
+   and later.  */
+typedef int file_name_index;

 struct file_entry
 {
@@ -976,26 +984,30 @@ struct line_header
   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.  */
+  /* Return the include dir at INDEX (0-based in dwarf5 and 1-based
before).
+     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;
+    size_t vec_index;
+    if (version <= 4)
+      vec_index = index - 1;
+    else
+      vec_index = index;

     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)
+  /* Return the file name at INDEX (0-based in dwarf5 and 1-based before).
+     Returns NULL if INDEX is out of bounds.  */
+  file_entry *file_name_at (file_name_index index, bool is_zero_indexed)
   {
-    /* Convert file name index number (1-based) to vector index
-       (0-based).  */
-    size_t vec_index = to_underlying (index) - 1;
+    size_t vec_index;
+    if (is_zero_indexed || version >= 5)
+        vec_index = index;
+    else
+      vec_index = index - 1;

     if (vec_index >= file_names.size ())
       return NULL;
@@ -1028,12 +1040,24 @@ struct line_header
      pointers.  The memory is owned by debug_line_buffer.  */
   std::vector<const char *> include_dirs;

-  /* The file_names table.  */
-  std::vector<file_entry> file_names;
+  int file_names_size() {
+    return file_names.size();
+  }
+
+  int first_file_index() {
+    return version >= 5 ? 0 : 1;
+  }

   /* 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 {};
+
+ private:
+  /* The file_names table. This is private because the meaning of indexes
differ
+     among dwarf versions (The first valid index is 1 in dwarf 4 and
before,
+     and is 0 in dwarf 5 and later). So the client should use file_name_at
+     method for access.  */
+  std::vector<file_entry> file_names;
 };

 typedef std::unique_ptr<line_header> line_header_up;
@@ -1259,6 +1283,18 @@ struct attribute
        here for better struct attribute alignment.  */
     unsigned int string_is_canonical : 1;

+    /* For strings in non-DWO files, was a string recorded with
+       DW_AT_GNU_str_index before we knew the value of
DW_AT_str_offsets_base?
+       If non-zero, then the "value" of the string is in u.unsnd, and
+       read_dwo_str_index must be called to obtain the actual string.
+       This is necessary for DW_AT_comp_dir and DW_AT_GNU_dwo_name (or
+       DW_AT_dwo_name) attributes: To save a relocation
DW_AT_GNU_str_index is
+       used, but because all .o file .debug_str_offsets sections are
+       concatenated together in the executable each .o has its own offset
into
+       this section. So if DW_AT_str_offsets_base comes later in the DIE,
we
+       need to reprocess these attributes later.  */
+    unsigned int string_is_str_index : 1;
+
     union
       {
  const char *str;
@@ -1311,6 +1347,7 @@ struct die_info

 #define DW_STRING(attr)    ((attr)->u.str)
 #define DW_STRING_IS_CANONICAL(attr) ((attr)->string_is_canonical)
+#define DW_STRING_IS_STR_INDEX(attr) ((attr)->string_is_str_index)
 #define DW_UNSND(attr)     ((attr)->u.unsnd)
 #define DW_BLOCK(attr)     ((attr)->u.blk)
 #define DW_SND(attr)       ((attr)->u.snd)
@@ -1506,7 +1543,12 @@ static const struct cu_partial_die_info
find_partial_die (sect_offset, int,

 static const gdb_byte *read_attribute (const struct die_reader_specs *,
        struct attribute *, struct attr_abbrev *,
-       const gdb_byte *);
+       const gdb_byte *, bool *need_reprocess);
+
+static void read_attribute_reprocess(const struct die_reader_specs *reader,
+     struct attribute *attr);
+
+static CORE_ADDR read_addr_index (struct dwarf2_cu *cu, unsigned int
addr_index);

 static unsigned int read_1_byte (bfd *, const gdb_byte *);

@@ -1565,8 +1607,17 @@ static CORE_ADDR read_addr_index_from_leb128 (struct
dwarf2_cu *,
       const gdb_byte *,
       unsigned int *);

-static const char *read_str_index (const struct die_reader_specs *reader,
-   ULONGEST str_index);
+static const char *read_dwo_str_index (const struct die_reader_specs
*reader,
+       ULONGEST str_index);
+
+static const char *read_stub_str_index (struct dwarf2_cu *cu,
+ ULONGEST str_index);
+
+static const char *get_comp_dir_attr (struct die_info *die,
+      struct dwarf2_cu *cu);
+
+static const char *get_stub_string_attr (struct dwarf2_cu *cu,
+ const struct attribute *attr);

 static void set_cu_language (unsigned int, struct dwarf2_cu *);

@@ -1579,6 +1630,8 @@ static struct attribute *dwarf2_attr_no_follow
(struct die_info *,
 static const char *dwarf2_string_attr (struct die_info *die, unsigned int
name,
                                        struct dwarf2_cu *cu);

+static const char *dwarf2_dwo_name (struct die_info *die, struct dwarf2_cu
*cu);
+
 static int dwarf2_flag_true_p (struct die_info *die, unsigned name,
                                struct dwarf2_cu *cu);

@@ -1954,7 +2007,7 @@ 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);
+     const char *comp_dir, bool is_zero_indexed);

 /* Expected enum dwarf_unit_type for read_comp_unit_head.  */
 enum class rcuh_kind { COMPILE, TYPE };
@@ -2377,6 +2430,11 @@ dwarf2_per_objfile::locate_sections (bfd *abfd,
asection *sectp,
       this->str.s.section = sectp;
       this->str.size = bfd_get_section_size (sectp);
     }
+  else if (section_is_p (sectp->name, &names.str_offsets))
+    {
+      this->str_offsets.s.section = sectp;
+      this->str_offsets.size = bfd_get_section_size (sectp);
+    }
   else if (section_is_p (sectp->name, &names.line_str))
     {
       this->line_str.s.section = sectp;
@@ -3630,7 +3688,7 @@ dw2_get_file_names_reader (const struct
die_reader_specs *reader,
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct dwarf2_per_cu_data *lh_cu;
   struct attribute *attr;
-  int i;
+  int i = 0;
   void **slot;
   struct quick_file_names *qfn;

@@ -3685,11 +3743,11 @@ dw2_get_file_names_reader (const struct
die_reader_specs *reader,

   file_and_directory fnd = find_file_and_directory (comp_unit_die, cu);

-  qfn->num_file_names = lh->file_names.size ();
+  qfn->num_file_names = lh->file_names_size ();
   qfn->file_names =
-    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);
+    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, lh.get (), fnd.comp_dir, true);
   qfn->real_names = NULL;

   lh_cu->v.quick->file_names = qfn;
@@ -6384,18 +6442,24 @@ read_comp_unit_head (struct comp_unit_head
*cu_header,
       switch (cu_header->unit_type)
  {
  case DW_UT_compile:
+ case DW_UT_partial:
+ case DW_UT_skeleton:
+ case DW_UT_split_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);
+   "(is %d, should be DW_UT_type) [in module %s]"),
+   cu_header->unit_type, filename);
   break;
  case DW_UT_type:
+ case DW_UT_split_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);
+ "(is %d, should be one of: %d, %d, %d, %d or %d) "
+ "[in module %s]"),
+ cu_header->unit_type, DW_UT_compile, DW_UT_skeleton,
+ DW_UT_split_compile, DW_UT_type, DW_UT_split_type, filename);
  }

       cu_header->addr_size = read_1_byte (abfd, info_ptr);
@@ -6416,13 +6480,19 @@ read_comp_unit_head (struct comp_unit_head
*cu_header,
     _("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;
+  bool header_has_signature = section_kind == rcuh_kind::TYPE
+    || cu_header->unit_type == DW_UT_skeleton
+    || cu_header->unit_type == DW_UT_split_compile;

+  if (header_has_signature)
+    {
       cu_header->signature = read_8_bytes (abfd, info_ptr);
       info_ptr += 8;
+    }

+  if (section_kind == rcuh_kind::TYPE)
+    {
+      LONGEST type_offset;
       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;
@@ -7157,10 +7227,6 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data
*this_cu,
       ranges = dwarf2_attr (stub_comp_unit_die, DW_AT_ranges, cu);
       comp_dir = dwarf2_attr (stub_comp_unit_die, DW_AT_comp_dir, cu);

-      /* There should be a DW_AT_addr_base attribute here (if needed).
- We need the value before we can process DW_FORM_GNU_addr_index
-         or DW_FORM_addrx.  */
-      cu->addr_base = 0;
       attr = dwarf2_attr (stub_comp_unit_die, DW_AT_GNU_addr_base, cu);
       if (attr)
  cu->addr_base = DW_UNSND (attr);
@@ -7179,6 +7245,7 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data
*this_cu,
       comp_dir->name = DW_AT_comp_dir;
       comp_dir->form = DW_FORM_string;
       DW_STRING_IS_CANONICAL (comp_dir) = 0;
+      DW_STRING_IS_STR_INDEX (comp_dir) = 0;
       DW_STRING (comp_dir) = stub_comp_dir;
     }

@@ -7278,9 +7345,8 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data
*this_cu,
   /* Save the comp_dir attribute.  If there is no DWP file then we'll read
      TUs by skipping the stub and going directly to the entry in the DWO
file.
      However, skipping the stub means we won't get DW_AT_comp_dir, so we
have
-     to get it via circuitous means.  Blech.  */
-  if (comp_dir != NULL)
-    result_reader->comp_dir = DW_STRING (comp_dir);
+     to get it via circuitous means.  */
+  result_reader->comp_dir = get_comp_dir_attr (comp_unit_die, cu);

   /* Skip dummy compilation units.  */
   if (info_ptr >= begin_info_ptr + dwo_unit->length
@@ -7291,46 +7357,59 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data
*this_cu,
   return 1;
 }

+/* Return the signature of the compile unit. In dwarf 4 and before, the
+   signature is in the DW_AT_GNU_dwo_id attribute. In dwarf 5 and later,
the
+   signature is part of the header. Returns 0 if the signature is not
found.  */
+static ULONGEST
+lookup_signature (struct dwarf2_cu *cu, struct die_info* comp_unit_die)
+{
+  ULONGEST signature = 0;
+  struct attribute *attr;
+
+ attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_id, cu);
+ if (attr)
+   signature = DW_UNSND (attr);
+ else if (cu->header.signature)
+   signature = cu->header.signature;
+ return signature;
+}
+
 /* Subroutine of init_cutu_and_read_dies to simplify it.
    Look up the DWO unit specified by COMP_UNIT_DIE of THIS_CU.
    Returns NULL if the specified DWO unit cannot be found.  */

 static struct dwo_unit *
-lookup_dwo_unit (struct dwarf2_per_cu_data *this_cu,
+lookup_dwo_unit (const struct die_reader_specs *reader,
  struct die_info *comp_unit_die)
 {
-  struct dwarf2_cu *cu = this_cu->cu;
-  ULONGEST signature;
+  struct dwarf2_cu *cu = reader->cu;
+  struct dwarf2_per_cu_data *per_cu = cu->per_cu;
   struct dwo_unit *dwo_unit;
   const char *comp_dir, *dwo_name;

   gdb_assert (cu != NULL);

   /* Yeah, we look dwo_name up again, but it simplifies the code.  */
-  dwo_name = dwarf2_string_attr (comp_unit_die, DW_AT_GNU_dwo_name, cu);
+  dwo_name = dwarf2_dwo_name (comp_unit_die, cu);
   comp_dir = dwarf2_string_attr (comp_unit_die, DW_AT_comp_dir, cu);

-  if (this_cu->is_debug_types)
+  if (per_cu->is_debug_types)
     {
       struct signatured_type *sig_type;

-      /* Since this_cu is the first member of struct signatured_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;
-      signature = sig_type->signature;
+      sig_type = (struct signatured_type *) per_cu;
       dwo_unit = lookup_dwo_type_unit (sig_type, dwo_name, comp_dir);
     }
   else
     {
-      struct attribute *attr;
-
-      attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_id, cu);
-      if (! attr)
+      ULONGEST signature = lookup_signature(cu, comp_unit_die);
+      if (!signature)
  error (_("Dwarf Error: missing dwo_id for dwo_name %s"
  " [in module %s]"),
-       dwo_name, objfile_name (this_cu->dwarf2_per_objfile->objfile));
-      signature = DW_UNSND (attr);
-      dwo_unit = lookup_dwo_comp_unit (this_cu, dwo_name, comp_dir,
+       dwo_name, objfile_name (per_cu->dwarf2_per_objfile->objfile));
+      dwo_unit = lookup_dwo_comp_unit (per_cu, dwo_name, comp_dir,
        signature);
     }

@@ -7443,7 +7522,6 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data
*this_cu,
   struct die_reader_specs reader;
   struct die_info *comp_unit_die;
   int has_children;
-  struct attribute *attr;
   struct signatured_type *sig_type = NULL;
   struct dwarf2_section_info *abbrev_section;
   /* Non-zero if CU currently points to a DWO file and we need to
@@ -7580,9 +7658,9 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data
*this_cu,

      Note that if USE_EXISTING_OK != 0, and THIS_CU->cu already contains a
      DWO CU, that this test will fail (the attribute will not be present).
 */
-  attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_name, cu);
+  const char *dwo_name = dwarf2_dwo_name (comp_unit_die, cu);
   abbrev_table_up dwo_abbrev_table;
-  if (attr)
+  if (dwo_name)
     {
       struct dwo_unit *dwo_unit;
       struct die_info *dwo_comp_unit_die;
@@ -7594,7 +7672,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data
*this_cu,
      sect_offset_str (this_cu->sect_off),
      bfd_get_filename (abfd));
  }
-      dwo_unit = lookup_dwo_unit (this_cu, comp_unit_die);
+      dwo_unit = lookup_dwo_unit (&reader, comp_unit_die);
       if (dwo_unit != NULL)
  {
   if (read_cutu_die_from_dwo (this_cu, dwo_unit,
@@ -7632,9 +7710,9 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data
*this_cu,
     }
 }

-/* Read CU/TU THIS_CU but do not follow DW_AT_GNU_dwo_name if present.
-   DWO_FILE, if non-NULL, is the DWO file to read (the caller is assumed
-   to have already done the lookup to find the DWO file).
+/* Read CU/TU THIS_CU but do not follow DW_AT_GNU_dwo_name
(DW_AT_GNU_dwo_name)
+   if present. DWO_FILE, if non-NULL, is the DWO file to read (the caller
is
+   assumed to have already done the lookup to find the DWO file).

    The caller is required to fill in THIS_CU->section, THIS_CU->offset, and
    THIS_CU->is_debug_types, but nothing else.
@@ -7650,6 +7728,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data
*this_cu,

 static void
 init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
+   struct dwarf2_cu *parent_cu,
    struct dwo_file *dwo_file,
    die_reader_func_ftype *die_reader_func,
    void *data)
@@ -7688,6 +7767,11 @@ init_cutu_and_read_dies_no_follow (struct
dwarf2_per_cu_data *this_cu,
      ? rcuh_kind::TYPE
      : rcuh_kind::COMPILE));

+  if (parent_cu)
+    {
+      cu.str_offsets_base = parent_cu->str_offsets_base;
+      cu.addr_base = parent_cu->addr_base;
+    }
   this_cu->length = get_cu_length (&cu.header);

   /* Skip dummy compilation units.  */
@@ -7705,8 +7789,8 @@ init_cutu_and_read_dies_no_follow (struct
dwarf2_per_cu_data *this_cu,
   die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data);
 }

-/* Read a CU/TU, except that this does not look for DW_AT_GNU_dwo_name and
-   does not lookup the specified DWO file.
+/* Read a CU/TU, except that this does not look for DW_AT_GNU_dwo_name
+   (DW_AT_dwo_name) and does not lookup the specified DWO file.
    This cannot be used to read DWO files.

    THIS_CU->cu is always freed when done.
@@ -7719,7 +7803,7 @@ init_cutu_and_read_dies_simple (struct
dwarf2_per_cu_data *this_cu,
  die_reader_func_ftype *die_reader_func,
  void *data)
 {
-  init_cutu_and_read_dies_no_follow (this_cu, NULL, die_reader_func, data);
+  init_cutu_and_read_dies_no_follow (this_cu, NULL, NULL, die_reader_func,
data);
 }


 /* Type Unit Groups.
@@ -9222,7 +9306,8 @@ skip_one_die (const struct die_reader_specs *reader,
const gdb_byte *info_ptr,
       /* The only abbrev we care about is DW_AT_sibling.  */
       if (abbrev->attrs[i].name == DW_AT_sibling)
  {
-  read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
+  bool ignored;
+  read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr, &ignored);
   if (attr.form == DW_FORM_ref_addr)
     complaint (_("ignoring absolute DW_AT_sibling"));
   else
@@ -9261,6 +9346,7 @@ skip_one_die (const struct die_reader_specs *reader,
const gdb_byte *info_ptr,
  case DW_FORM_data1:
  case DW_FORM_ref1:
  case DW_FORM_flag:
+ case DW_FORM_strx1:
   info_ptr += 1;
   break;
  case DW_FORM_flag_present:
@@ -9268,10 +9354,15 @@ skip_one_die (const struct die_reader_specs
*reader, const gdb_byte *info_ptr,
   break;
  case DW_FORM_data2:
  case DW_FORM_ref2:
+ case DW_FORM_strx2:
   info_ptr += 2;
   break;
+ case DW_FORM_strx3:
+  info_ptr += 3;
+  break;
  case DW_FORM_data4:
  case DW_FORM_ref4:
+ case DW_FORM_strx4:
   info_ptr += 4;
   break;
  case DW_FORM_data8:
@@ -10302,7 +10393,7 @@ process_full_comp_unit (struct dwarf2_per_cu_data
*per_cu,
   if (cu->language == language_go)
     fixup_go_packaging (cu);

-  /* Now that we have processed all the DIEs in the CU, all the types
+  /* Now that we have processed all the DIEs in the CU, all the types
      should be complete, and it should now be safe to compute all of the
      physnames.  */
   compute_delayed_physnames (cu);
@@ -10351,7 +10442,7 @@ process_full_comp_unit (struct dwarf2_per_cu_data
*per_cu,

  Still one can confuse GDB by using non-standard GCC compilation
  options - this waits on GCC PR other/32998 (-frecord-gcc-switches).
- */
+ */
       if (cu->has_loclist && gcc_4_minor >= 5)
  cust->locations_valid = 1;

@@ -10406,7 +10497,7 @@ process_full_type_unit (struct dwarf2_per_cu_data
*per_cu,
   if (cu->language == language_go)
     fixup_go_packaging (cu);

-  /* Now that we have processed all the DIEs in the CU, all the types
+  /* Now that we have processed all the DIEs in the CU, all the types
      should be complete, and it should now be safe to compute all of the
      physnames.  */
   compute_delayed_physnames (cu);
@@ -11615,16 +11706,16 @@ dwarf2_cu::setup_type_unit_groups (struct
die_info *die)
  process_full_type_unit still needs to know if this is the first
  time.  */

-      tu_group->num_symtabs = line_header->file_names.size ();
+      tu_group->num_symtabs = line_header->file_names_size ();
       tu_group->symtabs = XNEWVEC (struct symtab *,
-   line_header->file_names.size ());
+   line_header->file_names_size ());

-      for (i = 0; i < line_header->file_names.size (); ++i)
+      for (i = 0; i < line_header->file_names_size (); ++i)
  {
-  file_entry &fe = line_header->file_names[i];
+  file_entry *fe = line_header->file_name_at(i, true);

-  dwarf2_start_subfile (this, fe.name,
- fe.include_dir (line_header));
+  dwarf2_start_subfile (this, fe->name,
+ fe->include_dir (line_header));
   buildsym_compunit *b = get_builder ();
   if (b->get_current_subfile ()->symtab == NULL)
     {
@@ -11637,8 +11728,8 @@ dwarf2_cu::setup_type_unit_groups (struct die_info
*die)
  = allocate_symtab (cust, b->get_current_subfile ()->name);
     }

-  fe.symtab = b->get_current_subfile ()->symtab;
-  tu_group->symtabs[i] = fe.symtab;
+  fe->symtab = b->get_current_subfile ()->symtab;
+  tu_group->symtabs[i] = fe->symtab;
  }
     }
   else
@@ -11651,11 +11742,10 @@ dwarf2_cu::setup_type_unit_groups (struct
die_info *die)
  compunit_language (cust),
  0, cust));

-      for (i = 0; i < line_header->file_names.size (); ++i)
+      for (i = 0; i < line_header->file_names_size (); ++i)
  {
-  file_entry &fe = line_header->file_names[i];
-
-  fe.symtab = tu_group->symtabs[i];
+  file_entry *fe = line_header->file_name_at(i, true);
+  fe->symtab = tu_group->symtabs[i];
  }
     }

@@ -11833,10 +11923,9 @@ create_dwo_cu_reader (const struct
die_reader_specs *reader,
   struct create_dwo_cu_data *data = (struct create_dwo_cu_data *) datap;
   struct dwo_file *dwo_file = data->dwo_file;
   struct dwo_unit *dwo_unit = &data->dwo_unit;
-  struct attribute *attr;

-  attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_id, cu);
-  if (attr == NULL)
+  ULONGEST signature = lookup_signature(cu, comp_unit_die);
+  if (!signature)
     {
       complaint (_("Dwarf Error: debug entry at offset %s is missing"
    " its dwo_id [in module %s]"),
@@ -11845,7 +11934,7 @@ create_dwo_cu_reader (const struct die_reader_specs
*reader,
     }

   dwo_unit->dwo_file = dwo_file;
-  dwo_unit->signature = DW_UNSND (attr);
+  dwo_unit->signature = signature;
   dwo_unit->section = section;
   dwo_unit->sect_off = sect_off;
   dwo_unit->length = cu->per_cu->length;
@@ -11861,8 +11950,8 @@ create_dwo_cu_reader (const struct die_reader_specs
*reader,

 static void
 create_cus_hash_table (struct dwarf2_per_objfile *dwarf2_per_objfile,
-       struct dwo_file &dwo_file, dwarf2_section_info &section,
-       htab_t &cus_htab)
+       dwarf2_cu *cu, struct dwo_file &dwo_file,
+       dwarf2_section_info &section, htab_t &cus_htab)
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   const gdb_byte *info_ptr, *end_ptr;
@@ -11899,7 +11988,7 @@ create_cus_hash_table (struct dwarf2_per_objfile
*dwarf2_per_objfile,
       create_dwo_cu_data.dwo_file = &dwo_file;

       init_cutu_and_read_dies_no_follow (
-  &per_cu, &dwo_file, create_dwo_cu_reader, &create_dwo_cu_data);
+  &per_cu, cu, &dwo_file, create_dwo_cu_reader, &create_dwo_cu_data);
       info_ptr += per_cu.length;

       // If the unit could not be parsed, skip it.
@@ -12933,7 +13022,7 @@ open_and_init_dwo_file (struct dwarf2_per_cu_data
*per_cu,
   bfd_map_over_sections (dwo_file->dbfd.get (), dwarf2_locate_dwo_sections,
  &dwo_file->sections);

-  create_cus_hash_table (dwarf2_per_objfile, *dwo_file, dwo_file->
sections.info,
+  create_cus_hash_table (dwarf2_per_objfile, per_cu->cu, *dwo_file,
dwo_file->sections.info,
  dwo_file->cus);

   create_debug_types_hash_table (dwarf2_per_objfile, dwo_file.get (),
@@ -16129,7 +16218,7 @@ process_structure_scope (struct die_info *die,
struct dwarf2_cu *cu)
     {
       /* Any related symtab will do.  */
       symtab
- = cu->line_header->file_name_at (file_name_index (1))->symtab;
+ = cu->line_header->file_name_at (0, true)->symtab;
     }
   else
     {
@@ -18102,10 +18191,26 @@ read_full_die_1 (const struct die_reader_specs
*reader,
      attributes.  */
   die->num_attrs = abbrev->num_attrs;

+  std::vector<int> indexes_that_need_reprocess;
   for (i = 0; i < abbrev->num_attrs; ++i)
-    info_ptr = read_attribute (reader, &die->attrs[i], &abbrev->attrs[i],
-       info_ptr);
+    {
+      bool need_reprocess;
+      info_ptr =
+        read_attribute (reader, &die->attrs[i], &abbrev->attrs[i],
+ info_ptr, &need_reprocess);
+      if (need_reprocess)
+        indexes_that_need_reprocess.push_back(i);
+    }

+  struct attribute *attr = dwarf2_attr_no_follow (die,
DW_AT_str_offsets_base);
+  if (attr)
+    cu->str_offsets_base = DW_UNSND (attr);
+
+  attr = dwarf2_attr_no_follow (die, DW_AT_addr_base);
+  if (attr)
+    cu->addr_base = DW_UNSND (attr);
+  for (int index : indexes_that_need_reprocess)
+    read_attribute_reprocess(reader, &die->attrs[index]);
   *diep = die;
   *has_children = abbrev->has_children;
   return info_ptr;
@@ -18616,12 +18721,23 @@ partial_die_info::read (const struct
die_reader_specs *reader,
   int has_high_pc_attr = 0;
   int high_pc_relative = 0;

+  std::vector<struct attribute> attr_vec;
+  std::vector<int> indexes_that_need_reprocess;
+  attr_vec.resize(abbrev.num_attrs);
   for (i = 0; i < abbrev.num_attrs; ++i)
     {
-      struct attribute attr;
-
-      info_ptr = read_attribute (reader, &attr, &abbrev.attrs[i],
info_ptr);
+      bool need_reprocess;
+      info_ptr = read_attribute (reader, &attr_vec[i], &abbrev.attrs[i],
+ info_ptr, &need_reprocess);
+      if (need_reprocess)
+        indexes_that_need_reprocess.push_back(i);
+    }
+  for (int index : indexes_that_need_reprocess)
+    read_attribute_reprocess(reader, &attr_vec[index]);

+  for (i = 0; i < abbrev.num_attrs; ++i)
+    {
+      struct attribute &attr = attr_vec[i];
       /* Store the data if it is of an attribute we want to keep in a
          partial symbol table.  */
       switch (attr.name)
@@ -18712,9 +18828,7 @@ partial_die_info::read (const struct
die_reader_specs *reader,
       sect_offset off = dwarf2_get_ref_die_offset (&attr);
       const gdb_byte *sibling_ptr = buffer + to_underlying (off);

-      if (sibling_ptr < info_ptr)
- complaint (_("DW_AT_sibling points backwards"));
-      else if (sibling_ptr > reader->buffer_end)
+      if (sibling_ptr > reader->buffer_end)
  dwarf2_section_buffer_overflow_complaint (reader->die_section);
       else
  sibling = sibling_ptr;
@@ -19063,12 +19177,66 @@ partial_die_info::fixup (struct dwarf2_cu *cu)
   fixup_called = 1;
 }

+void read_attribute_reprocess(const struct die_reader_specs *reader,
+                 struct attribute *attr)
+{
+  struct dwarf2_cu *cu = reader->cu;
+  switch (attr->form)
+    {
+      case DW_FORM_addrx:
+      case DW_FORM_GNU_addr_index:
+        DW_ADDR (attr) = read_addr_index(cu, DW_UNSND (attr));
+        break;
+      case DW_FORM_strx:
+      case DW_FORM_strx1:
+      case DW_FORM_strx2:
+      case DW_FORM_strx3:
+      case DW_FORM_strx4:
+      case DW_FORM_GNU_str_index:
+        unsigned int str_index = DW_UNSND (attr);
+ /* If the DIE is from a Fission stub and we don't have
+   DW_AT_str_offsets yet then we cannot fetch the string.
+   All we can do is record the index and leave it to the caller
+   to deal with.  */
+ if (reader->dwo_file != NULL)
+  {
+    DW_STRING (attr) = read_dwo_str_index (reader, str_index);
+    DW_STRING_IS_CANONICAL (attr) = 0;
+    DW_STRING_IS_STR_INDEX (attr) = 0;
+  }
+ else
+ if (cu->str_offsets_base.has_value())
+  {
+    DW_STRING (attr) = read_stub_str_index (cu, str_index);
+    DW_STRING_IS_CANONICAL (attr) = 0;
+    DW_STRING_IS_STR_INDEX (attr) = 0;
+  }
+ else
+  {
+    /* Until it's clear handling the general case is worth it,
+       flag any other uses of this situation as errors to avoid
+       latent bugs.  What should happen is we should make DW_STRING
+       check DW_STRING_IS_STR_INDEX, but ugh.  */
+    if (attr->name != DW_AT_comp_dir
+ && attr->name != DW_AT_GNU_dwo_name
+ && attr->name != DW_AT_dwo_name)
+      {
+ error (_("Dwarf Error: %s/%s found in non-DWO CU"),
+       dwarf_form_name (attr->form), dwarf_attr_name (attr->name));
+      }
+    DW_UNSND (attr) = str_index;
+    DW_STRING_IS_STR_INDEX (attr) = 1;
+  }
+    }
+}
+
 /* Read an attribute value described by an attribute form.  */

 static const gdb_byte *
 read_attribute_value (const struct die_reader_specs *reader,
       struct attribute *attr, unsigned form,
-      LONGEST implicit_const, const gdb_byte *info_ptr)
+      LONGEST implicit_const, const gdb_byte *info_ptr,
+      bool *need_reprocess)
 {
   struct dwarf2_cu *cu = reader->cu;
   struct dwarf2_per_objfile *dwarf2_per_objfile
@@ -19079,6 +19247,7 @@ read_attribute_value (const struct die_reader_specs
*reader,
   struct comp_unit_head *cu_header = &cu->header;
   unsigned int bytes_read;
   struct dwarf_block *blk;
+  *need_reprocess = false;

   attr->form = (enum dwarf_form) form;
   switch (form)
@@ -19142,6 +19311,7 @@ read_attribute_value (const struct die_reader_specs
*reader,
     case DW_FORM_string:
       DW_STRING (attr) = read_direct_string (abfd, info_ptr, &bytes_read);
       DW_STRING_IS_CANONICAL (attr) = 0;
+      DW_STRING_IS_STR_INDEX (attr) = 0;
       info_ptr += bytes_read;
       break;
     case DW_FORM_strp:
@@ -19151,6 +19321,7 @@ read_attribute_value (const struct die_reader_specs
*reader,
    abfd, info_ptr, cu_header,
    &bytes_read);
   DW_STRING_IS_CANONICAL (attr) = 0;
+  DW_STRING_IS_STR_INDEX (attr) = 0;
   info_ptr += bytes_read;
   break;
  }
@@ -19175,6 +19346,7 @@ read_attribute_value (const struct die_reader_specs
*reader,
  DW_STRING (attr) = read_indirect_string_from_dwz (objfile,
   dwz, str_offset);
  DW_STRING_IS_CANONICAL (attr) = 0;
+ DW_STRING_IS_STR_INDEX (attr) = 0;
  info_ptr += bytes_read;
       }
       break;
@@ -19252,22 +19424,15 @@ read_attribute_value (const struct
die_reader_specs *reader,
   info_ptr += bytes_read;
  }
       info_ptr = read_attribute_value (reader, attr, form, implicit_const,
-       info_ptr);
+       info_ptr, need_reprocess);
       break;
     case DW_FORM_implicit_const:
       DW_SND (attr) = implicit_const;
       break;
     case DW_FORM_addrx:
     case DW_FORM_GNU_addr_index:
-      if (reader->dwo_file == NULL)
- {
-  /* For now flag a hard error.
-     Later we can turn this into a complaint.  */
-  error (_("Dwarf Error: %s found in non-DWO CU [in module %s]"),
- dwarf_form_name (form),
- bfd_get_filename (abfd));
- }
-      DW_ADDR (attr) = read_addr_index_from_leb128 (cu, info_ptr,
&bytes_read);
+      *need_reprocess = true;
+      DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
       info_ptr += bytes_read;
       break;
     case DW_FORM_strx:
@@ -19276,14 +19441,6 @@ read_attribute_value (const struct
die_reader_specs *reader,
     case DW_FORM_strx3:
     case DW_FORM_strx4:
     case DW_FORM_GNU_str_index:
-      if (reader->dwo_file == NULL)
- {
-  /* For now flag a hard error.
-     Later we can turn this into a complaint if warranted.  */
-  error (_("Dwarf Error: %s found in non-DWO CU [in module %s]"),
- dwarf_form_name (form),
- bfd_get_filename (abfd));
- }
       {
  ULONGEST str_index;
  if (form == DW_FORM_strx1)
@@ -19311,9 +19468,9 @@ read_attribute_value (const struct die_reader_specs
*reader,
     str_index = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
     info_ptr += bytes_read;
   }
- DW_STRING (attr) = read_str_index (reader, str_index);
- DW_STRING_IS_CANONICAL (attr) = 0;
-      }
+ *need_reprocess = true;
+ DW_UNSND (attr) = str_index;
+ }
       break;
     default:
       error (_("Dwarf Error: Cannot handle %s in DWARF reader [in module
%s]"),
@@ -19349,11 +19506,12 @@ read_attribute_value (const struct
die_reader_specs *reader,
 static const gdb_byte *
 read_attribute (const struct die_reader_specs *reader,
  struct attribute *attr, struct attr_abbrev *abbrev,
- const gdb_byte *info_ptr)
+ const gdb_byte *info_ptr, bool *need_reprocess)
 {
   attr->name = abbrev->name;
   return read_attribute_value (reader, attr, abbrev->form,
-       abbrev->implicit_const, info_ptr);
+       abbrev->implicit_const, info_ptr,
+       need_reprocess);
 }

 /* Read dwarf information from a buffer.  */
@@ -19905,21 +20063,21 @@ dwarf2_read_addr_index (struct dwarf2_per_cu_data
*per_cu,
     addr_size);
 }

-/* Given a DW_FORM_GNU_str_index or DW_FORM_strx, fetch the string.
-   This is only used by the Fission support.  */
+/* Given a DW_FORM_GNU_str_index value STR_INDEX, fetch the string.
+   STR_SECTION, STR_OFFSETS_SECTION can be from a Fission stub or a
+   DWO file.  */

 static const char *
-read_str_index (const struct die_reader_specs *reader, ULONGEST str_index)
+read_str_index (struct dwarf2_cu *cu,
+ struct dwarf2_section_info *str_section,
+ struct dwarf2_section_info *str_offsets_section,
+ ULONGEST str_offsets_base, ULONGEST str_index)
 {
-  struct dwarf2_cu *cu = reader->cu;
   struct dwarf2_per_objfile *dwarf2_per_objfile
     = cu->per_cu->dwarf2_per_objfile;
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   const char *objf_name = objfile_name (objfile);
   bfd *abfd = objfile->obfd;
-  struct dwarf2_section_info *str_section =
&reader->dwo_file->sections.str;
-  struct dwarf2_section_info *str_offsets_section =
-    &reader->dwo_file->sections.str_offsets;
   const gdb_byte *info_ptr;
   ULONGEST str_offset;
   static const char form_name[] = "DW_FORM_GNU_str_index or DW_FORM_strx";
@@ -19927,18 +20085,17 @@ read_str_index (const struct die_reader_specs
*reader, ULONGEST str_index)
   dwarf2_read_section (objfile, str_section);
   dwarf2_read_section (objfile, str_offsets_section);
   if (str_section->buffer == NULL)
-    error (_("%s used without .debug_str.dwo section"
+    error (_("%s used without %s section"
      " in CU at offset %s [in module %s]"),
-   form_name, sect_offset_str (cu->header.sect_off), objf_name);
+   form_name, get_section_name (str_section),
+           sect_offset_str (cu->header.sect_off), objf_name);
   if (str_offsets_section->buffer == NULL)
-    error (_("%s used without .debug_str_offsets.dwo section"
+    error (_("%s used without %s section"
      " in CU at offset %s [in module %s]"),
-   form_name, sect_offset_str (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 %s [in module %s]"),
-   form_name, sect_offset_str (cu->header.sect_off), objf_name);
+   form_name, get_section_name(str_section),
+           sect_offset_str (cu->header.sect_off), objf_name);
   info_ptr = (str_offsets_section->buffer
+      + str_offsets_base
       + str_index * cu->header.offset_size);
   if (cu->header.offset_size == 4)
     str_offset = bfd_get_32 (abfd, info_ptr);
@@ -19951,6 +20108,73 @@ read_str_index (const struct die_reader_specs
*reader, ULONGEST str_index)
   return (const char *) (str_section->buffer + str_offset);
 }

+/* Given a DW_FORM_GNU_str_index from a DWO file, fetch the string.  */
+
+static const char *
+read_dwo_str_index (const struct die_reader_specs *reader, ULONGEST
str_index)
+{
+  ULONGEST str_offsets_base = reader->cu->header.version >= 5 ?
+    reader->cu->header.addr_size : 0;
+  return read_str_index (reader->cu,
+ &reader->dwo_file->sections.str,
+ &reader->dwo_file->sections.str_offsets,
+ str_offsets_base, str_index);
+}
+
+/* Given a DW_FORM_GNU_str_index from a Fission stub, fetch the string.  */
+
+static const char *
+read_stub_str_index (struct dwarf2_cu *cu, ULONGEST str_index)
+{
+  struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
+  const char *objf_name = objfile_name (objfile);
+  static const char form_name[] = "DW_FORM_GNU_str_index";
+  static const char str_offsets_attr_name[] = "DW_AT_str_offsets";
+
+  if (!cu->str_offsets_base.has_value())
+    {
+      error (_("%s used in Fission stub without %s"
+       " in CU at offset 0x%lx [in module %s]"),
+     form_name, str_offsets_attr_name,
+     (long) cu->header.offset_size, objf_name);
+    }
+
+  return read_str_index (cu,
+ &cu->per_cu->dwarf2_per_objfile->str,
+ &cu->per_cu->dwarf2_per_objfile->str_offsets,
+ *cu->str_offsets_base, str_index);
+}
+
+/* Wrapper around read_stub_str_index for attributes that *may* be using
+   DW_AT_GNU_str_index from a non-DWO file.  */
+
+static const char *
+get_stub_string_attr (struct dwarf2_cu *cu, const struct attribute *attr)
+{
+  if (DW_STRING_IS_STR_INDEX (attr))
+    return read_stub_str_index (cu, DW_UNSND (attr));
+  return DW_STRING (attr);
+}
+
+/* Fetch the value of the DW_AT_comp_dir attribute.
+   The result is NULL if the attribute isn't present or if the value of
+   the attribute is "".  If the caller needs to do something different
+   depending on whether the attribute is present, the caller must check.
+   This function should always be used to fetch this attribute as it
+   handles DW_AT_GNU_str_index from Fission stubs.  This is important as
+   the low level DIE reader combines the contents of the stub with the DWO
+   top level DIE so that the rest of the code only ever sees one DIE.  */
+
+static const char *
+get_comp_dir_attr (struct die_info *die, struct dwarf2_cu *cu)
+{
+  const struct attribute *attr = dwarf2_attr (die, DW_AT_comp_dir, cu);
+
+  if (attr == NULL)
+    return NULL;
+  return get_stub_string_attr (cu, attr);
+}
+
 /* Return the length of an LEB128 number in BUF.  */

 static int
@@ -20089,6 +20313,10 @@ dwarf2_string_attr (struct die_info *die, unsigned
int name, struct dwarf2_cu *c
       if (attr->form == DW_FORM_strp || attr->form == DW_FORM_line_strp
   || attr->form == DW_FORM_string
   || attr->form == DW_FORM_strx
+  || attr->form == DW_FORM_strx1
+  || attr->form == DW_FORM_strx2
+  || attr->form == DW_FORM_strx3
+  || attr->form == DW_FORM_strx4
   || attr->form == DW_FORM_GNU_str_index
   || attr->form == DW_FORM_GNU_strp_alt)
  str = DW_STRING (attr);
@@ -20102,6 +20330,17 @@ dwarf2_string_attr (struct die_info *die, unsigned
int name, struct dwarf2_cu *c
   return str;
 }

+/* Return the dwo name or NULL if not present. If present, it is in either
+   DW_AT_GNU_dwo_name or DW_AT_dwo_name atrribute.  */
+static const char *
+dwarf2_dwo_name (struct die_info *die, struct dwarf2_cu *cu)
+{
+  const char *dwo_name = dwarf2_string_attr (die, DW_AT_GNU_dwo_name, cu);
+  if (!dwo_name)
+    dwo_name = dwarf2_string_attr (die, DW_AT_dwo_name, cu);
+  return dwo_name;
+}
+
 /* Return non-zero iff the attribute NAME is defined for the given DIE,
    and holds a non-zero value.  This function should only be used for
    DW_FORM_flag or DW_FORM_flag_present attributes.  */
@@ -20177,7 +20416,7 @@ line_header::add_file_name (const char *name,
 {
   if (dwarf_line_debug >= 2)
     fprintf_unfiltered (gdb_stdlog, "Adding file %u: %s\n",
- (unsigned) file_names.size () + 1, name);
+ (unsigned) file_names_size () + 1, name);

   file_names.emplace_back (name, d_index, mod_time, length);
 }
@@ -20393,12 +20632,15 @@ dwarf_decode_line_header (sect_offset sect_off,
struct dwarf2_cu *cu)
     read_checked_initial_length_and_offset (abfd, line_ptr, &cu->header,
     &bytes_read, &offset_size);
   line_ptr += bytes_read;
+
+  const gdb_byte *start_here = line_ptr;
+
   if (line_ptr + lh->total_length > (section->buffer + section->size))
     {
       dwarf2_statement_list_fits_in_line_number_section_complaint ();
       return 0;
     }
-  lh->statement_program_end = line_ptr + lh->total_length;
+  lh->statement_program_end = start_here + lh->total_length;
   lh->version = read_2_bytes (abfd, line_ptr);
   line_ptr += 2;
   if (lh->version > 5)
@@ -20428,6 +20670,7 @@ dwarf_decode_line_header (sect_offset sect_off,
struct dwarf2_cu *cu)
     }
   lh->header_length = read_offset_1 (abfd, line_ptr, offset_size);
   line_ptr += offset_size;
+  lh->statement_program_start = line_ptr + lh->header_length;
   lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
   line_ptr += 1;
   if (lh->version >= 4)
@@ -20512,7 +20755,6 @@ dwarf_decode_line_header (sect_offset sect_off,
struct dwarf2_cu *cu)
  }
       line_ptr += bytes_read;
     }
-  lh->statement_program_start = line_ptr;

   if (line_ptr > (section->buffer + section->size))
     complaint (_("line number info header doesn't "
@@ -20529,18 +20771,18 @@ dwarf_decode_line_header (sect_offset sect_off,
struct dwarf2_cu *cu)
    Returns NULL if FILE_INDEX should be ignored, i.e., it is
pst->filename.  */

 static const char *
-psymtab_include_file_name (const struct line_header *lh, int file_index,
+psymtab_include_file_name (struct line_header *lh, int file_index,
    const struct partial_symtab *pst,
    const char *comp_dir,
    gdb::unique_xmalloc_ptr<char> *name_holder)
 {
-  const file_entry &fe = lh->file_names[file_index];
-  const char *include_name = fe.name;
+  file_entry *fe = lh->file_name_at(file_index, true);
+  const char *include_name = fe->name;
   const char *include_name_to_compare = include_name;
   const char *pst_filename;
   int file_is_pst;

-  const char *dir_name = fe.include_dir (lh);
+  const char *dir_name = fe->include_dir (lh);

   gdb::unique_xmalloc_ptr<char> hold_compare;
   if (!IS_ABSOLUTE_PATH (include_name)
@@ -20612,7 +20854,7 @@ public:
   {
     /* 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);
+    return m_line_header->file_name_at (m_file, false);
   }

   /* Record the line in the state machine.  END_SEQUENCE is true if
@@ -20709,12 +20951,11 @@ private:
      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.  */

+  file_name_index m_file;
   CORE_ADDR m_address;
   bool m_is_stmt;
   unsigned int m_discriminator;
@@ -20902,7 +21143,7 @@ lnp_state_machine::record_line (bool end_sequence)
       fprintf_unfiltered (gdb_stdlog,
   "Processing actual line %u: file %u,"
   " address %s, is_stmt %u, discrim %u\n",
-  m_line, to_underlying (m_file),
+  m_line, m_file,
   paddress (m_gdbarch, m_address),
   m_is_stmt, m_discriminator);
     }
@@ -20952,6 +21193,7 @@ lnp_state_machine::lnp_state_machine (struct
dwarf2_cu *cu, gdbarch *arch,
   m_gdbarch = arch;
   m_record_lines_p = record_lines_p;
   m_line_header = lh;
+  m_file = m_line_header->first_file_index();

   m_currently_recording_lines = true;

@@ -21245,8 +21487,8 @@ 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->file_names.size ();
file_index++)
-        if (lh->file_names[file_index].included_p == 1)
+      for (file_index = 0; file_index < lh->file_names_size ();
file_index++)
+        if (lh->file_name_at(file_index, true)->included_p == 1)
           {
     gdb::unique_xmalloc_ptr<char> name_holder;
     const char *include_name =
@@ -21265,11 +21507,11 @@ dwarf_decode_lines (struct line_header *lh, const
char *comp_dir,
       struct compunit_symtab *cust = builder->get_compunit_symtab ();
       int i;

-      for (i = 0; i < lh->file_names.size (); i++)
+      for (i = 0; i < lh->file_names_size (); i++)
  {
-  file_entry &fe = lh->file_names[i];
+  file_entry *fe = lh->file_name_at(i, true);

-  dwarf2_start_subfile (cu, fe.name, fe.include_dir (lh));
+  dwarf2_start_subfile (cu, fe->name, fe->include_dir (lh));

   if (builder->get_current_subfile ()->symtab == NULL)
     {
@@ -21277,7 +21519,7 @@ dwarf_decode_lines (struct line_header *lh, const
char *comp_dir,
  = allocate_symtab (cust,
    builder->get_current_subfile ()->name);
     }
-  fe.symtab = builder->get_current_subfile ()->symtab;
+  fe->symtab = builder->get_current_subfile ()->symtab;
  }
     }
 }
@@ -21496,7 +21738,7 @@ new_symbol (struct die_info *die, struct type
*type, struct dwarf2_cu *cu,
   struct file_entry *fe;

   if (cu->line_header != NULL)
-    fe = cu->line_header->file_name_at (file_index);
+    fe = cu->line_header->file_name_at (file_index, false);
   else
     fe = NULL;

@@ -22945,7 +23187,7 @@ dump_die_shallow (struct ui_file *f, int indent,
struct die_info *die)
  case DW_FORM_indirect:
   /* The reader will have reduced the indirect form to
      the "base form" so this form should not occur.  */
-  fprintf_unfiltered (f,
+  fprintf_unfiltered (f,
       "unexpected attribute form: DW_FORM_indirect");
   break;
  case DW_FORM_implicit_const:
@@ -24027,22 +24269,28 @@ dwarf_alloc_die (struct dwarf2_cu *cu, int
num_attrs)
    *LH's file name table.  The result is allocated using xmalloc; the
caller is
    responsible for freeing it.  */

+bool is_valid_file_index(int file_index, struct line_header *lh, bool
is_zero_indexed) {
+  if (is_zero_indexed || lh->version >= 5)
+    return 0 <= file_index && file_index < lh->file_names_size ();
+  return 1 <= file_index && file_index <= lh->file_names_size ();
+}
+
 static char *
-file_file_name (int file, struct line_header *lh)
+file_file_name (int file, struct line_header *lh, bool is_zero_indexed)
 {
   /* 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->file_names.size ())
+  if (is_valid_file_index(file, lh, is_zero_indexed))
     {
-      const file_entry &fe = lh->file_names[file - 1];
+      const file_entry *fe = lh->file_name_at(file, is_zero_indexed);

-      if (!IS_ABSOLUTE_PATH (fe.name))
+      if (!IS_ABSOLUTE_PATH (fe->name))
  {
-  const char *dir = fe.include_dir (lh);
+  const char *dir = fe->include_dir (lh);
   if (dir != NULL)
-    return concat (dir, SLASH_STRING, fe.name, (char *) NULL);
+    return concat (dir, SLASH_STRING, fe->name, (char *) NULL);
  }
-      return xstrdup (fe.name);
+      return xstrdup (fe->name);
     }
   else
     {
@@ -24066,13 +24314,14 @@ file_file_name (int file, struct line_header *lh)
    compilation.  The result is allocated using xmalloc; the caller is
    responsible for freeing it.  */
 static char *
-file_full_name (int file, struct line_header *lh, const char *comp_dir)
+file_full_name (int file, struct line_header *lh, const char *comp_dir,
+ bool is_zero_indexed)
 {
   /* 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->file_names.size ())
+  if (is_valid_file_index(file, lh, is_zero_indexed))
     {
-      char *relative = file_file_name (file, lh);
+      char *relative = file_file_name (file, lh, is_zero_indexed);

       if (IS_ABSOLUTE_PATH (relative) || comp_dir == NULL)
  return relative;
@@ -24080,7 +24329,7 @@ file_full_name (int file, struct line_header *lh,
const char *comp_dir)
        relative, (char *) NULL);
     }
   else
-    return file_file_name (file, lh);
+    return file_file_name (file, lh, is_zero_indexed);
 }


@@ -24091,7 +24340,7 @@ macro_start_file (struct dwarf2_cu *cu,
                   struct line_header *lh)
 {
   /* File name relative to the compilation directory of this source file.
 */
-  char *file_name = file_file_name (file, lh);
+  char *file_name = file_file_name (file, lh, false);

   if (! current_file)
     {
@@ -25046,7 +25295,7 @@ cu_debug_loc_section (struct dwarf2_cu *cu)
   if (cu->dwo_unit)
     {
       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
diff --git a/gdb/dwarf2read.h b/gdb/dwarf2read.h
index 8939f97af5..3f6d52d9a3 100644
--- a/gdb/dwarf2read.h
+++ b/gdb/dwarf2read.h
@@ -154,6 +154,7 @@ public:
   dwarf2_section_info macinfo {};
   dwarf2_section_info macro {};
   dwarf2_section_info str {};
+  dwarf2_section_info str_offsets {};
   dwarf2_section_info line_str {};
   dwarf2_section_info ranges {};
   dwarf2_section_info rnglists {};
diff --git a/gdb/symfile.h b/gdb/symfile.h
index 741b085e0c..a227022be4 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -569,6 +569,7 @@ struct dwarf2_debug_sections {
   struct dwarf2_section_names macinfo;
   struct dwarf2_section_names macro;
   struct dwarf2_section_names str;
+  struct dwarf2_section_names str_offsets;
   struct dwarf2_section_names line_str;
   struct dwarf2_section_names ranges;
   struct dwarf2_section_names rnglists;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]