Add reprocessing flag to struct attribute
authorTom Tromey <tom@tromey.com>
Wed, 30 Sep 2020 00:49:08 +0000 (18:49 -0600)
committerTom Tromey <tom@tromey.com>
Wed, 30 Sep 2020 02:29:06 +0000 (20:29 -0600)
Some forms require "reprocessing" -- a second pass to update their
value appropriately.  In this case, we'll set the unsigned value on
the attribute, and then later set it to the correct value.

To handle this, we introduce a reprocessing flag to attribute.  Then,
we manage this flag to ensure that setting and unsetting is done
properly.

gdb/ChangeLog
2020-09-29  Tom Tromey  <tom@tromey.com>

* dwarf2/read.c (read_cutu_die_from_dwo): Use OBSTACK_ZALLOC.
(read_attribute_reprocess, read_attribute_value): Update.
(read_attribute): Clear requires_reprocessing.
* dwarf2/attribute.h (struct attribute) <as_unsigned_reprocess,
form_requires_reprocessing>: New methods.
<string_init>: Clear requires_reprocessing.
<set_unsigned_reprocess>: New method.
<name>: Shrink by one bit.
<requires_reprocessing>: New member.
* dwarf2/attribute.c (attribute::form_requires_reprocessing): New
method.

gdb/ChangeLog
gdb/dwarf2/attribute.c
gdb/dwarf2/attribute.h
gdb/dwarf2/read.c

index ea0a4ae29a6b14d033faa069a4af13337656baa3..d02fd7d8cdafa1c5731a9071de5f90e21b32ccd9 100644 (file)
@@ -1,3 +1,17 @@
+2020-09-29  Tom Tromey  <tom@tromey.com>
+
+       * dwarf2/read.c (read_cutu_die_from_dwo): Use OBSTACK_ZALLOC.
+       (read_attribute_reprocess, read_attribute_value): Update.
+       (read_attribute): Clear requires_reprocessing.
+       * dwarf2/attribute.h (struct attribute) <as_unsigned_reprocess,
+       form_requires_reprocessing>: New methods.
+       <string_init>: Clear requires_reprocessing.
+       <set_unsigned_reprocess>: New method.
+       <name>: Shrink by one bit.
+       <requires_reprocessing>: New member.
+       * dwarf2/attribute.c (attribute::form_requires_reprocessing): New
+       method.
+
 2020-09-29  Tom Tromey  <tom@tromey.com>
 
        * dwarf2/read.c (read_attribute_value): Update.
index 69c59cc8bd8887e047cf6b2bd5344c41f6ce34eb..5d9c559194aa20d8afe3efaefdab4a7a52abd461 100644 (file)
@@ -182,3 +182,17 @@ attribute::form_is_unsigned () const
          || form == DW_FORM_ref8
          || form == DW_FORM_ref_udata);
 }
+
+/* See attribute.h.  */
+
+bool
+attribute::form_requires_reprocessing () const
+{
+  return (form == DW_FORM_strx1
+         || form == DW_FORM_strx2
+         || form == DW_FORM_strx3
+         || form == DW_FORM_strx4
+         || form == DW_FORM_GNU_str_index
+         || form == DW_FORM_addrx
+         || form == DW_FORM_GNU_addr_index);
+}
index 3067e2affa2d028aa5aa23e345ebfcf14372d248..b2c824f71f759b9fbc0a82982e8cc482f2e38604 100644 (file)
@@ -73,6 +73,15 @@ struct attribute
     return u.snd;
   }
 
+  /* Return the unsigned value, but only for attributes requiring
+     reprocessing.  */
+  ULONGEST as_unsigned_reprocess () const
+  {
+    gdb_assert (form_requires_reprocessing ());
+    gdb_assert (requires_reprocessing);
+    return u.unsnd;
+  }
+
   /* Return non-zero if ATTR's value is a section offset --- classes
      lineptr, loclistptr, macptr or rangelistptr --- or zero, otherwise.
      You may use DW_UNSND (attr) to retrieve such offsets.
@@ -127,6 +136,10 @@ struct attribute
   /* Check if the attribute's form is an unsigned integer form.  */
   bool form_is_unsigned () const;
 
+  /* Check if the attribute's form is a form that requires
+     "reprocessing".  */
+  bool form_requires_reprocessing () const;
+
   /* Return DIE offset of this attribute.  Return 0 with complaint if
      the attribute is not of the required kind.  */
 
@@ -162,6 +175,7 @@ struct attribute
     gdb_assert (form_is_string ());
     u.str = str;
     string_is_canonical = 0;
+    requires_reprocessing = 0;
   }
 
   /* Set the canonical string value for this attribute.  */
@@ -200,8 +214,29 @@ struct attribute
     u.unsnd = unsnd;
   }
 
+  /* Temporarily set this attribute to an unsigned integer.  This is
+     used only for those forms that require reprocessing.  */
+  void set_unsigned_reprocess (ULONGEST unsnd)
+  {
+    gdb_assert (form_requires_reprocessing ());
+    u.unsnd = unsnd;
+    requires_reprocessing = 1;
+  }
+
+
+  ENUM_BITFIELD(dwarf_attribute) name : 15;
+
+  /* A boolean that is used for forms that require reprocessing.  A
+     form may require data not directly available in the attribute.
+     E.g., DW_FORM_strx requires the corresponding
+     DW_AT_str_offsets_base.  In this case, the processing for the
+     attribute must be done in two passes.  In the first past, this
+     flag is set and the value is an unsigned.  In the second pass,
+     the unsigned value is turned into the correct value for the form,
+     and this flag is cleared.  This flag is unused for other
+     forms.  */
+  unsigned int requires_reprocessing : 1;
 
-  ENUM_BITFIELD(dwarf_attribute) name : 16;
   ENUM_BITFIELD(dwarf_form) form : 15;
 
   /* Has u.str already been updated by dwarf2_canonicalize_name?  This
index c572ed43c0bd028174371ad12199807a0ba37643..57b667e1bb7d52d84873eb24f3de965c826ace45 100644 (file)
@@ -6869,7 +6869,7 @@ read_cutu_die_from_dwo (dwarf2_cu *cu,
   else if (stub_comp_dir != NULL)
     {
       /* Reconstruct the comp_dir attribute to simplify the code below.  */
-      comp_dir = XOBNEW (&cu->comp_unit_obstack, struct attribute);
+      comp_dir = OBSTACK_ZALLOC (&cu->comp_unit_obstack, struct attribute);
       comp_dir->name = DW_AT_comp_dir;
       comp_dir->form = DW_FORM_string;
       comp_dir->set_string_noncanonical (stub_comp_dir);
@@ -19640,7 +19640,7 @@ read_attribute_reprocess (const struct die_reader_specs *reader,
     {
       case DW_FORM_addrx:
       case DW_FORM_GNU_addr_index:
-        DW_ADDR (attr) = read_addr_index (cu, DW_UNSND (attr));
+        DW_ADDR (attr) = read_addr_index (cu, attr->as_unsigned_reprocess ());
         break;
       case DW_FORM_loclistx:
         DW_UNSND (attr) = read_loclist_index (cu, DW_UNSND (attr));
@@ -19655,7 +19655,7 @@ read_attribute_reprocess (const struct die_reader_specs *reader,
       case DW_FORM_strx4:
       case DW_FORM_GNU_str_index:
        {
-         unsigned int str_index = DW_UNSND (attr);
+         unsigned int str_index = attr->as_unsigned_reprocess ();
          gdb_assert (!attr->canonical_string_p ());
          if (reader->dwo_file != NULL)
            attr->set_string_noncanonical (read_dwo_str_index (reader,
@@ -19879,7 +19879,8 @@ read_attribute_value (const struct die_reader_specs *reader,
     case DW_FORM_addrx:
     case DW_FORM_GNU_addr_index:
       *need_reprocess = true;
-      DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+      attr->set_unsigned_reprocess (read_unsigned_leb128 (abfd, info_ptr,
+                                                         &bytes_read));
       info_ptr += bytes_read;
       break;
     case DW_FORM_strx:
@@ -19916,7 +19917,7 @@ read_attribute_value (const struct die_reader_specs *reader,
            info_ptr += bytes_read;
          }
        *need_reprocess = true;
-        DW_UNSND (attr) = str_index;
+       attr->set_unsigned_reprocess (str_index);
        }
       break;
     default:
@@ -19957,6 +19958,7 @@ read_attribute (const struct die_reader_specs *reader,
 {
   attr->name = abbrev->name;
   attr->string_is_canonical = 0;
+  attr->requires_reprocessing = 0;
   return read_attribute_value (reader, attr, abbrev->form,
                               abbrev->implicit_const, info_ptr,
                               need_reprocess);