Improved DWARFv4 support.
authorSeth LaForge <seth@ridemission.com>
Thu, 3 Dec 2015 04:43:36 +0000 (20:43 -0800)
committerSeth LaForge <sethml@google.com>
Thu, 10 Dec 2015 18:52:25 +0000 (10:52 -0800)
Handle DW_AT_data_member_location attributes with type DW_FORM_data*, which
store a simple integer offset rather than dwarf expression. This seems to come
up with struct members, at least on ARM.

Handle DW_AT_location attributes with type DW_FORM_sec_offset as not having
dwarf expressions, as allowed by the DWARFv4 standard. This seems to come up
with some local variables, at least on ARM.

Test DW_FORM_sec_offset support in location lists and DW_AT_data_member_location formatting support.
Test code, compiled with gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4 on x86-64:

struct Foo {
  char bim : 8;
  char bar : 3;
  char baz : 5;
};

int get_bar(struct Foo foo) {
  return foo.bar;
}

int f1(int a, char b) {
  return a+b;
}

elftools/dwarf/descriptions.py
test/testfiles_for_readelf/improved-dwarfv4.o.elf [new file with mode: 0644]

index abe9252d1c5f398138d0f16ff3a94ecc7d65f937..a894ceb09fe3917a2589464229b390d19cec12af 100644 (file)
@@ -420,13 +420,24 @@ _DWARF_EXPR_DUMPER_CACHE = {}
 def _location_list_extra(attr, die, section_offset):
     # According to section 2.6 of the DWARF spec v3, class loclistptr means
     # a location list, and class block means a location expression.
-    #
-    if attr.form in ('DW_FORM_data4', 'DW_FORM_data8'):
+    # DW_FORM_sec_offset is new in DWARFv4 as a section offset.
+    if attr.form in ('DW_FORM_data4', 'DW_FORM_data8', 'DW_FORM_sec_offset'):
         return '(location list)'
     else:
         return describe_DWARF_expr(attr.value, die.cu.structs)
 
 
+def _data_member_location_extra(attr, die, section_offset):
+    # According to section 5.5.6 of the DWARF spec v4, a data member location
+    # can be an integer offset, or a location description.
+    #
+    if attr.form in ('DW_FORM_data1', 'DW_FORM_data2',
+                     'DW_FORM_data4', 'DW_FORM_data8'):
+        return ''  # No extra description needed
+    else:
+        return describe_DWARF_expr(attr.value, die.cu.structs)
+
+
 def _import_extra(attr, die, section_offset):
     # For DW_AT_import the value points to a DIE (that can be either in the
     # current DIE's CU or in another CU, depending on the FORM). The extra
@@ -479,7 +490,7 @@ _EXTRA_INFO_DESCRIPTION_MAP = defaultdict(
     DW_AT_location=_location_list_extra,
     DW_AT_string_length=_location_list_extra,
     DW_AT_return_addr=_location_list_extra,
-    DW_AT_data_member_location=_location_list_extra,
+    DW_AT_data_member_location=_data_member_location_extra,
     DW_AT_vtable_elem_location=_location_list_extra,
     DW_AT_segment=_location_list_extra,
     DW_AT_static_link=_location_list_extra,
diff --git a/test/testfiles_for_readelf/improved-dwarfv4.o.elf b/test/testfiles_for_readelf/improved-dwarfv4.o.elf
new file mode 100644 (file)
index 0000000..f8fda66
Binary files /dev/null and b/test/testfiles_for_readelf/improved-dwarfv4.o.elf differ