* dwarf2read.c (attr_form_is_constant): New function.
authorJim Blandy <jimb@codesourcery.com>
Thu, 13 Dec 2007 19:02:51 +0000 (19:02 +0000)
committerJim Blandy <jimb@codesourcery.com>
Thu, 13 Dec 2007 19:02:51 +0000 (19:02 +0000)
(dwarf2_add_field): Use it and attr_form_is_section_offset to
recognize DW_AT_data_member_location attributes.  Use
dwarf2_get_attr_constant_value when the attribute is a constant.

* dwarf2read.c (attr_form_is_section_offset): New function.
(dwarf_add_member_fn, read_common_block, read_partial_die)
(dwarf2_symbol_mark_computed): Use it, instead of writing it out.

gdb/ChangeLog
gdb/dwarf2read.c

index e0428ed..23c38e6 100644 (file)
@@ -1,3 +1,14 @@
+2007-12-13  Jim Blandy  <jimb@codesourcery.com>
+
+       * dwarf2read.c (attr_form_is_constant): New function.
+       (dwarf2_add_field): Use it and attr_form_is_section_offset to
+       recognize DW_AT_data_member_location attributes.  Use
+       dwarf2_get_attr_constant_value when the attribute is a constant.
+
+       * dwarf2read.c (attr_form_is_section_offset): New function.
+       (dwarf_add_member_fn, read_common_block, read_partial_die)
+       (dwarf2_symbol_mark_computed): Use it, instead of writing it out.
+
 2007-12-12  Jim Blandy  <jimb@codesourcery.com>
 
        Remove unused support for target-based exception catching.
index eb2564e..ec0e645 100644 (file)
@@ -1027,6 +1027,10 @@ static void dwarf_decode_macros (struct line_header *, unsigned int,
 
 static int attr_form_is_block (struct attribute *);
 
+static int attr_form_is_section_offset (struct attribute *);
+
+static int attr_form_is_constant (struct attribute *);
+
 static void dwarf2_symbol_mark_computed (struct attribute *attr,
                                         struct symbol *sym,
                                         struct dwarf2_cu *cu);
@@ -3474,8 +3478,16 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
       attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
       if (attr)
        {
-         FIELD_BITPOS (*fp) =
-           decode_locdesc (DW_BLOCK (attr), cu) * bits_per_byte;
+          if (attr_form_is_section_offset (attr))
+            {
+              dwarf2_complex_location_expr_complaint ();
+              FIELD_BITPOS (*fp) = 0;
+            }
+          else if (attr_form_is_constant (attr))
+            FIELD_BITPOS (*fp) = dwarf2_get_attr_constant_value (attr, 0);
+          else
+            FIELD_BITPOS (*fp) =
+              decode_locdesc (DW_BLOCK (attr), cu) * bits_per_byte;
        }
       else
        FIELD_BITPOS (*fp) = 0;
@@ -3794,7 +3806,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
         {
           fnp->voffset = decode_locdesc (DW_BLOCK (attr), cu) + 2;
         }
-      else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
+      else if (attr_form_is_section_offset (attr))
         {
          dwarf2_complex_location_expr_complaint ();
         }
@@ -4510,7 +4522,7 @@ read_common_block (struct die_info *die, struct dwarf2_cu *cu)
         {
           base = decode_locdesc (DW_BLOCK (attr), cu);
         }
-      else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
+      else if (attr_form_is_section_offset (attr))
         {
          dwarf2_complex_location_expr_complaint ();
         }
@@ -5673,7 +5685,7 @@ read_partial_die (struct partial_die_info *part_die,
             {
               part_die->locdesc = DW_BLOCK (&attr);
             }
-          else if (attr.form == DW_FORM_data4 || attr.form == DW_FORM_data8)
+          else if (attr_form_is_section_offset (&attr))
             {
              dwarf2_complex_location_expr_complaint ();
             }
@@ -9722,6 +9734,46 @@ attr_form_is_block (struct attribute *attr)
       || attr->form == DW_FORM_block);
 }
 
+/* Return non-zero if ATTR's value is a section offset (classes
+   lineptr, loclistptr, macptr or rangelistptr).  In this case,
+   you may use DW_UNSND (attr) to retrieve the offset.  */
+static int
+attr_form_is_section_offset (struct attribute *attr)
+{
+  return (attr->form == DW_FORM_data4
+          || attr->form == DW_FORM_data8);
+}
+
+
+/* Return non-zero if ATTR's value falls in the 'constant' class, or
+   zero otherwise.  When this function returns true, you can apply
+   dwarf2_get_attr_constant_value to it.
+
+   However, note that for some attributes you must check
+   attr_form_is_section_offset before using this test.  DW_FORM_data4
+   and DW_FORM_data8 are members of both the constant class, and of
+   the classes that contain offsets into other debug sections
+   (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.  */
+static int
+attr_form_is_constant (struct attribute *attr)
+{
+  switch (attr->form)
+    {
+    case DW_FORM_sdata:
+    case DW_FORM_udata:
+    case DW_FORM_data1:
+    case DW_FORM_data2:
+    case DW_FORM_data4:
+    case DW_FORM_data8:
+      return 1;
+    default:
+      return 0;
+    }
+}
+
 static void
 dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
                             struct dwarf2_cu *cu)
@@ -9733,7 +9785,7 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
   if (objfile->separate_debug_objfile_backlink)
     objfile = objfile->separate_debug_objfile_backlink;
 
-  if ((attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
+  if (attr_form_is_section_offset (attr)
       /* ".debug_loc" may not exist at all, or the offset may be outside
         the section.  If so, fall through to the complaint in the
         other branch.  */