]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
patch ../102427761.patch
authorDoug Evans <dje@google.com>
Thu, 10 Dec 2015 20:00:30 +0000 (12:00 -0800)
committerDoug Evans <dje@google.com>
Thu, 10 Dec 2015 20:00:30 +0000 (12:00 -0800)
README.google
gdb/dwarf2read.c
gdb/symfile.h
gdb/xcoffread.c
include/dwarf2.def

index 2ac5ac85d4b03f992baa2121c17919a08da88abc..1e722c0c223a0d390f521401b04ea56267e1ad5f 100644 (file)
@@ -158,3 +158,42 @@ they are an ongoing maintenance burden.
 +
 +      * gdbthread.h (any_running): Declare.
 +      * thread.c (any_running): New function.
+--- README.google      2015-09-05 16:33:32.000000000 -0700
++++ README.google      2015-09-05 17:01:28.000000000 -0700
++
++2015-09-05  Doug Evans  <google.com>
++
++      Ref# 12994080
++      Add support for DW_AT_str_offsets_base.
++      This patch is GOOGLE LOCAL for now.
++      Not sure when to submit it upstream.
++
++      * dwarf2read.c (struct dwarf2_per_objfile): New member str_offsets.
++      (dwarf2_elf_names): Add .debug_str_offsets.
++      (struct dwarf2_cu): New members str_offsets_base,
++      have_str_offsets_base.
++      (struct attribute): Reduce member form to 14 bits.  New member
++      string_is_str_index.
++      (DW_STRING_IS_STR_INDEX): New macro.
++      (dwarf2_locate_sections): Handle .debug_str_offsets.
++      (read_cutu_die_from_dwo): Initialize DW_STRING_IS_STR_INDEX for
++      comp_dir attribute.  Call get_comp_dir_attr.
++      (lookup_dwo_unit): Replace arg this_cu with reader.  All callers
++      updated.
++      (init_cutu_and_read_dies): Fetch value of DW_AT_str_offsets_base.
++      (init_cutu_and_read_dies_no_follow): Ditto.
++      (process_psymtab_comp_unit_reader): Call get_comp_dir_attr.
++      (find_file_and_directory): Ditto.
++      (read_attribute_value): Initialize DW_STRING_IS_STR_INDEX for all
++      string forms.
++      (read_attribute_value) <DW_FORM_GNU_str_index>: Handle appearance in
++      Fission stubs.
++      (read_str_index): Replace arg reader with cu, str_section,
++      str_offsets_section, str_offsets_base.  All callers updated.
++      (read_dwo_str_index, read_stub_str_index): New functions.
++      (get_stub_string_attr, get_comp_dir_attr): New functions.
++      * symfile.h (struct dwarf2_debug_sections): New member str_offsets.
++      * xcoffread.c (dwarf2_xcoff_names): Add entry for str_offsets.
++
++      include/
++      * dwarf2.def (DW_AT_str_offsets_base): New attribute.
index 48b65e063a54cdeb15de8871fe5b5810a66be81b..df37151fb32ee363514eb70fd16c504521c410ff 100644 (file)
@@ -228,6 +228,7 @@ struct dwarf2_per_objfile
   struct dwarf2_section_info macinfo;
   struct dwarf2_section_info macro;
   struct dwarf2_section_info str;
+  struct dwarf2_section_info str_offsets; /* GOOGLE LOCAL */
   struct dwarf2_section_info ranges;
   struct dwarf2_section_info addr;
   struct dwarf2_section_info frame;
@@ -339,6 +340,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" }, /* GOOGLE LOCAL */
   { ".debug_ranges", ".zdebug_ranges" },
   { ".debug_types", ".zdebug_types" },
   { ".debug_addr", ".zdebug_addr" },
@@ -536,6 +538,21 @@ struct dwarf2_cu
      whether the DW_AT_ranges attribute came from the skeleton or DWO.  */
   ULONGEST ranges_base;
 
+  /* GOOGLE LOCAL */
+  /* The DW_AT_str_offsets_base attribute if present, zero otherwise
+     (zero is a valid value though).
+     Note this value comes from a Fission stub CU/TU's DIE.
+     Also note that the value is zero in the DWO case so this value can
+     be used without needing to know whether DWO files are in use or not.
+     Note that this "base" value is for attributes in the stub only, we don't
+     need this to process DW_FORM_GNU_str_index in DWO files.  */
+  ULONGEST str_offsets_base;
+
+  /* Non-zero if str_offsets_base contains the value of
+     DW_AT_str_offsets_base.  */
+  unsigned int have_str_offsets_base : 1;
+  /* END GOOGLE LOCAL */
+
   /* Mark used when releasing cached dies.  */
   unsigned int mark : 1;
 
@@ -1214,13 +1231,29 @@ struct abbrev_table
 struct attribute
   {
     ENUM_BITFIELD(dwarf_attribute) name : 16;
-    ENUM_BITFIELD(dwarf_form) form : 15;
+    ENUM_BITFIELD(dwarf_form) form : 14;
+
+    /* These bitfields are specific to particular fields in the union, but
+       are recorded here for better struct attribute packing.  */
 
-    /* Has DW_STRING already been updated by dwarf2_canonicalize_name?  This
-       field should be in u.str (existing only for DW_STRING) but it is kept
-       here for better struct attribute alignment.  */
+    /* Has DW_STRING already been updated by dwarf2_canonicalize_name?  */
     unsigned int string_is_canonical : 1;
 
+    /* GOOGLE LOCAL */
+    /* 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 in Fission
+       stubs: 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 we
+       can't read the string until we read DW_AT_str_offsets_base.  Plus,
+       there's no guarantee it isn't recorded later in the DIE, after the
+       attribute that needs it.  Ugh.  */
+    unsigned int string_is_str_index : 1;
+    /* END GOOGLE LOCAL */
+
     union
       {
        const char *str;
@@ -1273,6 +1306,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) /* GOOGLE LOCAL */
 #define DW_UNSND(attr)     ((attr)->u.unsnd)
 #define DW_BLOCK(attr)     ((attr)->u.blk)
 #define DW_SND(attr)       ((attr)->u.snd)
@@ -1516,8 +1550,19 @@ 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);
+/* GOOGLE LOCAL */
+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);
+/* END GOOGLE LOCAL */
 
 static void set_cu_language (unsigned int, struct dwarf2_cu *);
 
@@ -2209,6 +2254,13 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
       dwarf2_per_objfile->str.s.asection = sectp;
       dwarf2_per_objfile->str.size = bfd_get_section_size (sectp);
     }
+  /* GOOGLE LOCAL */
+  else if (section_is_p (sectp->name, &names->str_offsets))
+    {
+      dwarf2_per_objfile->str_offsets.s.asection = sectp;
+      dwarf2_per_objfile->str_offsets.size = bfd_get_section_size (sectp);
+    }
+  /* END GOOGLE LOCAL */
   else if (section_is_p (sectp->name, &names->addr))
     {
       dwarf2_per_objfile->addr.s.asection = sectp;
@@ -5135,6 +5187,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; /* GOOGLE LOCAL */
       DW_STRING (comp_dir) = stub_comp_dir;
     }
 
@@ -5248,8 +5301,8 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data *this_cu,
      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);
+  /* GOOGLE LOCAL */
+  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
@@ -5260,15 +5313,18 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data *this_cu,
   return 1;
 }
 
+/* GOOGLE LOCAL */
+
 /* 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;
+  struct dwarf2_cu *cu = reader->cu;
+  struct dwarf2_per_cu_data *per_cu = cu->per_cu;
   struct attribute *attr;
   ULONGEST signature;
   struct dwo_unit *dwo_unit;
@@ -5279,19 +5335,17 @@ lookup_dwo_unit (struct dwarf2_per_cu_data *this_cu,
   /* Yeah, we look dwo_name up again, but it simplifies the code.  */
   attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_name, cu);
   gdb_assert (attr != NULL);
-  dwo_name = DW_STRING (attr);
-  comp_dir = NULL;
-  attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, cu);
-  if (attr)
-    comp_dir = DW_STRING (attr);
+  dwo_name = get_stub_string_attr (cu, attr);
 
-  if (this_cu->is_debug_types)
+  comp_dir = get_comp_dir_attr (comp_unit_die, cu);
+
+  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;
+      sig_type = (struct signatured_type *) per_cu;
       signature = sig_type->signature;
       dwo_unit = lookup_dwo_type_unit (sig_type, dwo_name, comp_dir);
     }
@@ -5303,15 +5357,17 @@ lookup_dwo_unit (struct dwarf2_per_cu_data *this_cu,
       if (! attr)
        error (_("Dwarf Error: missing dwo_id for dwo_name %s"
                 " [in module %s]"),
-              dwo_name, objfile_name (this_cu->objfile));
+              dwo_name, objfile_name (per_cu->objfile));
       signature = DW_UNSND (attr);
-      dwo_unit = lookup_dwo_comp_unit (this_cu, dwo_name, comp_dir,
+      dwo_unit = lookup_dwo_comp_unit (per_cu, dwo_name, comp_dir,
                                       signature);
     }
 
   return dwo_unit;
 }
 
+/* END GOOGLE LOCAL */
+
 /* Subroutine of init_cutu_and_read_dies to simplify it.
    See it for a description of the parameters.
    Read a TU directly from a DWO file, bypassing the stub.
@@ -5577,6 +5633,17 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
   init_cu_die_reader (&reader, cu, section, NULL);
   info_ptr = read_full_die (&reader, &comp_unit_die, info_ptr, &has_children);
 
+  /* GOOGLE LOCAL */
+  /* DWO_AT_GNU_dwo_name and DW_AT_comp_dir in the stub may be using
+     DW_FORM_GNU_str_index which needs DW_AT_str_offsets_base.  */
+  attr = dwarf2_attr (comp_unit_die, DW_AT_str_offsets_base, cu);
+  if (attr)
+    {
+      cu->str_offsets_base = DW_UNSND (attr);
+      cu->have_str_offsets_base = 1;
+    }
+  /* END GOOGLE LOCAL */
+
   /* If we are in a DWO stub, process it and then read in the "real" CU/TU
      from the DWO file.
      Note that if USE_EXISTING_OK != 0, and THIS_CU->cu already contains a
@@ -5594,7 +5661,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
                       " has children (offset 0x%x) [in module %s]"),
                     this_cu->offset.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); /* GOOGLE LOCAL */
       if (dwo_unit != NULL)
        {
          if (read_cutu_die_from_dwo (this_cu, dwo_unit,
@@ -5677,6 +5744,7 @@ init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
   struct die_reader_specs reader;
   struct cleanup *cleanups;
   struct die_info *comp_unit_die;
+  struct attribute *attr; /* GOOGLE LOCAL */
   int has_children;
 
   if (dwarf_die_debug)
@@ -5718,6 +5786,29 @@ init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
   init_cu_die_reader (&reader, &cu, section, dwo_file);
   info_ptr = read_full_die (&reader, &comp_unit_die, info_ptr, &has_children);
 
+  /* GOOGLE LOCAL */
+  /* DWO_AT_GNU_dwo_name and DW_AT_comp_dir in the stub may be using
+     DW_FORM_GNU_str_index, so we need to fetch DW_AT_str_offsets_base
+     ASAP.  */
+  attr = dwarf2_attr (comp_unit_die, DW_AT_str_offsets_base, &cu);
+  if (attr)
+    {
+      /* DW_AT_str_offsets_base shouldn't appear in DWOs.  */
+      if (dwo_file != NULL)
+       {
+         complaint (&symfile_complaints,
+                    _("DW_AT_str_offsets_base present in DWO file %s,"
+                      " ignored"),
+                    dwo_file->dwo_name);
+       }
+      else
+       {
+         cu.str_offsets_base = DW_UNSND (attr);
+         cu.have_str_offsets_base = 1;
+       }
+    }
+  /* END GOOGLE LOCAL */
+
   die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data);
 
   do_cleanups (cleanups);
@@ -5972,9 +6063,7 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
   pst = create_partial_symtab (per_cu, filename);
 
   /* This must be done before calling dwarf2_build_include_psymtabs.  */
-  attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, cu);
-  if (attr != NULL)
-    pst->dirname = DW_STRING (attr);
+  pst->dirname = get_comp_dir_attr (comp_unit_die, cu); /* GOOGLE LOCAL */
 
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
@@ -9060,7 +9149,7 @@ find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu,
 
   attr = dwarf2_attr (die, DW_AT_comp_dir, cu);
   if (attr)
-    *comp_dir = DW_STRING (attr);
+    *comp_dir = get_comp_dir_attr (die, cu); /* GOOGLE LOCAL */
   else if (producer_is_gcc_lt_4_3 (cu) && *name != NULL
           && IS_ABSOLUTE_PATH (*name))
     {
@@ -16269,6 +16358,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; /* GOOGLE LOCAL */
       info_ptr += bytes_read;
       break;
     case DW_FORM_strp:
@@ -16277,6 +16367,7 @@ read_attribute_value (const struct die_reader_specs *reader,
          DW_STRING (attr) = read_indirect_string (abfd, info_ptr, cu_header,
                                                   &bytes_read);
          DW_STRING_IS_CANONICAL (attr) = 0;
+         DW_STRING_IS_STR_INDEX (attr) = 0; /* GOOGLE LOCAL */
          info_ptr += bytes_read;
          break;
        }
@@ -16289,6 +16380,7 @@ read_attribute_value (const struct die_reader_specs *reader,
 
        DW_STRING (attr) = read_indirect_string_from_dwz (dwz, str_offset);
        DW_STRING_IS_CANONICAL (attr) = 0;
+       DW_STRING_IS_STR_INDEX (attr) = 0; /* GOOGLE LOCAL */
        info_ptr += bytes_read;
       }
       break;
@@ -16375,22 +16467,47 @@ read_attribute_value (const struct die_reader_specs *reader,
       info_ptr += bytes_read;
       break;
     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));
-       }
+      /* GOOGLE LOCAL */
       {
        ULONGEST str_index =
          read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
 
-       DW_STRING (attr) = read_str_index (reader, str_index);
-       DW_STRING_IS_CANONICAL (attr) = 0;
+       /* 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->have_str_offsets_base)
+         {
+           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)
+             {
+               error (_("Dwarf Error: %s/%s found in non-DWO CU"
+                        " [in module %s]"),
+                      dwarf_form_name (form), dwarf_attr_name (attr->name),
+                      bfd_get_filename (abfd));
+             }
+           DW_UNSND (attr) = str_index;
+           DW_STRING_IS_STR_INDEX (attr) = 1;
+         }
        info_ptr += bytes_read;
       }
+      /* END GOOGLE LOCAL */
       break;
     default:
       error (_("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]"),
@@ -16919,50 +17036,132 @@ dwarf2_read_addr_index (struct dwarf2_per_cu_data *per_cu,
   return read_addr_index_1 (addr_index, addr_base, addr_size);
 }
 
-/* Given a DW_FORM_GNU_str_index, fetch the string.
-   This is only used by the Fission support.  */
+/* GOOGLE LOCAL */
+
+/* Given a DW_FORM_GNU_str_index value STR_INDEX, fetch the string.
+   STR_SECTION, STR_OFFSETS_SECTION are either from a Fission stub or a
+   DWO file.  If the former, then STR_OFFSETS_BASE is the value of the
+   DW_AT_str_offsets_base attribute, otherwise it must be zero.  */
 
 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 objfile *objfile = dwarf2_per_objfile->objfile;
   const char *objf_name = objfile_name (objfile);
   bfd *abfd = objfile->obfd;
-  struct dwarf2_cu *cu = reader->cu;
-  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";
+  static const char str_offsets_attr_name[] = "DW_AT_str_offsets";
 
   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 0x%lx [in module %s]"),
-          form_name, (long) cu->header.offset.sect_off, objf_name);
+          form_name, get_section_name (str_section),
+          (long) cu->header.offset.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 0x%lx [in module %s]"),
-          form_name, (long) cu->header.offset.sect_off, objf_name);
+          form_name, get_section_name (str_offsets_section),
+          (long) cu->header.offset.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);
+    error (_("%s pointing outside of %s section"
+            " in CU at offset 0x%lx [in module %s]"),
+          form_name, get_section_name (str_offsets_section),
+          (long) cu->header.offset.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);
   else
     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);
+    error (_("Offset from %s pointing outside of %s section"
+            " in CU at offset 0x%lx [in module %s]"),
+          form_name, get_section_name (str_section),
+          (long) cu->header.offset.sect_off, objf_name);
+
+  if (str_section->buffer[str_offset] == '\0')
+    return NULL;
   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)
+{
+  return read_str_index (reader->cu,
+                        &reader->dwo_file->sections.str,
+                        &reader->dwo_file->sections.str_offsets,
+                        0, 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 = 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->have_str_offsets_base)
+    {
+      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.sect_off, objf_name);
+    }
+
+  return read_str_index (cu,
+                        &dwarf2_per_objfile->str,
+                        &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.  This is currently only
+   appropriate for Fission stubs, but nothing precludes it from being
+   used in general (not that that's necessarily a good thing).  */
+
+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);
+}
+
+/* END GOOGLE LOCAL */
+
 /* Return the length of an LEB128 number in BUF.  */
 
 static int
index 9ef3f0baee6f1db30ba7d9bc7fde45128ceca92e..1e719dc716c43ef80220f7e15fdd26398714832d 100644 (file)
@@ -614,6 +614,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; /* GOOGLE LOCAL */
   struct dwarf2_section_names ranges;
   struct dwarf2_section_names types;
   struct dwarf2_section_names addr;
index b5b2a1d27d325462b3c11268be0fea7c8e0e4d57..9e9409bc66cc468593feee7d733126d3a662633f 100644 (file)
@@ -162,6 +162,7 @@ static const struct dwarf2_debug_sections dwarf2_xcoff_names = {
   { NULL, NULL }, /* debug_macinfo */
   { NULL, NULL }, /* debug_macro */
   { ".dwstr", NULL },
+  { NULL, NULL }, /* debug_str_offsets */ /* GOOGLE LOCAL */
   { ".dwrnges", NULL },
   { NULL, NULL }, /* debug_types */
   { NULL, NULL }, /* debug_addr */
index e61cfbeb4076742b96a7ecb7a2c26a6a2c9f62f4..e29c5361387cacf22f375508e25dbe16de084175 100644 (file)
@@ -309,6 +309,7 @@ DW_AT (DW_AT_const_expr, 0x6c)
 DW_AT (DW_AT_enum_class, 0x6d)
 DW_AT (DW_AT_linkage_name, 0x6e)
 /* DWARF 5.  */
+DW_AT (DW_AT_str_offsets_base, 0x72) /* GOOGLE LOCAL */
 DW_AT (DW_AT_noreturn, 0x87)
 
 DW_AT_DUP (DW_AT_lo_user, 0x2000) /* Implementation-defined range start.  */