From d03f73f942caa87afdc2852d851e476ae1843b44 Mon Sep 17 00:00:00 2001 From: Seva Alekseyev Date: Mon, 16 Oct 2023 09:44:11 -0400 Subject: [PATCH] Dynamic array size can be a loclist/locexpr (#512) * Dynamic array size can be a loclist/locexpr * False pos in is_loclist on ubound being constant --- elftools/dwarf/locationlists.py | 14 +++++++++----- test/test_dwarf_locationattr.py | 6 ++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/elftools/dwarf/locationlists.py b/elftools/dwarf/locationlists.py index 6397738..ffdfde8 100644 --- a/elftools/dwarf/locationlists.py +++ b/elftools/dwarf/locationlists.py @@ -329,14 +329,16 @@ class LocationParser(object): attr.form in ('DW_FORM_data1', 'DW_FORM_data2', 'DW_FORM_data4', 'DW_FORM_data8') and not attr.name == 'DW_AT_const_value') or attr.form in ('DW_FORM_sec_offset', 'DW_FORM_loclistx')) and - not LocationParser._attribute_is_member_offset(attr, dwarf_version)) + not LocationParser._attribute_is_constant(attr, dwarf_version)) # Starting with DWARF3, DW_AT_data_member_location may contain an integer offset # instead of a location expression. Need to prevent false positives on attribute_has_location(). + # As for DW_AT_upper_bound/DW_AT_count, we've seen it in form DW_FORM_locexpr in a V5 binary. usually it's a constant, + # but the constant sholdn't be misinterpreted as a loclist pointer. @staticmethod - def _attribute_is_member_offset(attr, dwarf_version): - return (dwarf_version >= 3 and - attr.name == 'DW_AT_data_member_location' and + def _attribute_is_constant(attr, dwarf_version): + return (((dwarf_version >= 3 and attr.name == 'DW_AT_data_member_location') or + (attr.name in ('DW_AT_upper_bound', 'DW_AT_count'))) and attr.form in ('DW_FORM_data1', 'DW_FORM_data2', 'DW_FORM_data4', 'DW_FORM_data8', 'DW_FORM_sdata', 'DW_FORM_udata')) @staticmethod @@ -354,4 +356,6 @@ class LocationParser(object): 'DW_AT_call_target', 'DW_AT_call_target_clobbered', 'DW_AT_call_data_location', - 'DW_AT_call_data_value')) + 'DW_AT_call_data_value', + 'DW_AT_upper_bound', + 'DW_AT_count')) diff --git a/test/test_dwarf_locationattr.py b/test/test_dwarf_locationattr.py index 6d764d2..e3befc7 100644 --- a/test/test_dwarf_locationattr.py +++ b/test/test_dwarf_locationattr.py @@ -35,6 +35,12 @@ class TestLocationAttrubute(unittest.TestCase): attr = AttributeValue(name='DW_AT_call_target', form='DW_FORM_exprloc', value=[80], raw_value=[80], offset=8509, indirection_length=0) self.assertTrue(LocationParser.attribute_has_location(attr, 5)) + # This attribute came from the binary in issue #508 + # DW_TAG_subrange_type at 0x45DEA + attr = AttributeValue(name='DW_AT_upper_bound', form='DW_FORM_exprloc', value=[163, 1, 94, 49, 28], raw_value=[163, 1, 94, 49, 28], offset=286191, indirection_length=0) + self.assertTrue(LocationParser.attribute_has_location(attr, 5)) + + if __name__ == '__main__': unittest.main() \ No newline at end of file -- 2.30.2