From 8b97f5da6838791fd5c6b47b1623fb414daed2f0 Mon Sep 17 00:00:00 2001 From: Seva Alekseyev Date: Wed, 15 Nov 2023 21:12:15 -0500 Subject: [PATCH] Fix for mixed version loclists, tests (#521) --- elftools/dwarf/dwarfinfo.py | 2 +- scripts/dwarfdump.py | 4 +- test/test_dwarf_llpair.py | 48 ++++++++++++++++++ test/testfiles_for_dwarfdump/dwarf_llpair.elf | Bin 0 -> 22600 bytes test/testfiles_for_dwarfdump/llpair.c | 29 +++++++++++ test/testfiles_for_dwarfdump/llpaira.c | 10 ++++ test/testfiles_for_unittests/dwarf_llpair.elf | Bin 0 -> 22600 bytes 7 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 test/test_dwarf_llpair.py create mode 100644 test/testfiles_for_dwarfdump/dwarf_llpair.elf create mode 100644 test/testfiles_for_dwarfdump/llpair.c create mode 100644 test/testfiles_for_dwarfdump/llpaira.c create mode 100644 test/testfiles_for_unittests/dwarf_llpair.elf diff --git a/elftools/dwarf/dwarfinfo.py b/elftools/dwarf/dwarfinfo.py index 96f33d9..4061462 100644 --- a/elftools/dwarf/dwarfinfo.py +++ b/elftools/dwarf/dwarfinfo.py @@ -367,7 +367,7 @@ class DWARFInfo(object): elif self.debug_loc_sec and self.debug_loclists_sec is None: return LocationLists(self.debug_loc_sec.stream, self.structs, 4, self) elif self.debug_loc_sec and self.debug_loclists_sec: - return LocationListsPair(self.debug_loclists_sec.stream, self.debug_loclists_sec.stream, self.structs, self) + return LocationListsPair(self.debug_loc_sec.stream, self.debug_loclists_sec.stream, self.structs, self) else: return None diff --git a/scripts/dwarfdump.py b/scripts/dwarfdump.py index bf05bdb..6d46ba5 100644 --- a/scripts/dwarfdump.py +++ b/scripts/dwarfdump.py @@ -325,7 +325,9 @@ ATTR_DESCRIPTIONS = dict( DW_AT_call_line=_desc_value, DW_AT_call_file=_desc_decl_file, DW_AT_abstract_origin=_desc_origin, - DW_AT_specification=_desc_spec + DW_AT_specification=_desc_spec, + DW_AT_call_site_value=lambda attr, die: _desc_expression(attr.value, die) if attr.form.startswith('DW_FORM_block') else _desc_locations(attr, die), + DW_AT_GNU_call_site_value=lambda attr, die: _desc_expression(attr.value, die) if attr.form.startswith('DW_FORM_block') else _desc_locations(attr, die), ) class ReadElf(object): diff --git a/test/test_dwarf_llpair.py b/test/test_dwarf_llpair.py new file mode 100644 index 0000000..e4f0c7e --- /dev/null +++ b/test/test_dwarf_llpair.py @@ -0,0 +1,48 @@ +#------------------------------------------------------------------------------- +# elftools tests +# +# Seva Alekseyev (sevaa@sprynet.com) +# This code is in the public domain +#------------------------------------------------------------------------------- +import unittest +import os +from elftools.dwarf.locationlists import LocationListsPair, LocationParser +from elftools.elf.elffile import ELFFile + +class TestLocListsPair(unittest.TestCase): + def test_llpair(self): + path = os.path.join('test', 'testfiles_for_unittests', + 'dwarf_llpair.elf') + with open(path, 'rb') as f: + elffile = ELFFile(f) + dwarfinfo = elffile.get_dwarf_info(follow_links=False) + # This binary has both V4- loclists and V5+ loclists + self.assertTrue(dwarfinfo.debug_loc_sec and dwarfinfo.debug_loclists_sec) + # On this binary, it's a pair object + llp = dwarfinfo.location_lists() + self.assertTrue(isinstance(llp, LocationListsPair)) + locparser = LocationParser(llp) + + CUs = list(dwarfinfo.iter_CUs()) + + # The first CU is the v5 one + # Just in case, make sure we can hit a loclist in a V5 section + CU = CUs[0] + self.assertTrue(CU.header.version == 5) + # DW_TAG_variable for i inside b() + die = next(die for die in CU.iter_DIEs() if die.offset == 0x333) + ll = locparser.parse_from_attribute(die.attributes['DW_AT_location'], CU.header.version, die=die) + self.assertTrue(len(ll) == 8) + + # The second CU is the V2 one + # Now hit a loclist in a V4- sectoin + # This would fail before 11/15/2023 + CU = CUs[1] + self.assertTrue(CU.header.version == 2) + # DW_TAG_variable for i inside a() + die = next(die for die in CU.iter_DIEs() if die.offset == 0x796) + ll = locparser.parse_from_attribute(die.attributes['DW_AT_location'], CU.header.version, die=die) + self.assertTrue(len(ll) == 7) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/test/testfiles_for_dwarfdump/dwarf_llpair.elf b/test/testfiles_for_dwarfdump/dwarf_llpair.elf new file mode 100644 index 0000000000000000000000000000000000000000..5909d60c7c9782567ff1b9b2c72f63371a225fce GIT binary patch literal 22600 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 literal 0 HcmV?d00001 diff --git a/test/testfiles_for_dwarfdump/llpair.c b/test/testfiles_for_dwarfdump/llpair.c new file mode 100644 index 0000000..712b3ad --- /dev/null +++ b/test/testfiles_for_dwarfdump/llpair.c @@ -0,0 +1,29 @@ +/* +To compile: +Linux x86-64 +gcc version 8.3.0 + +gcc -gdwarf-2 -O2 -c llpaira.c +gcc -gdwarf-5 -O2 -o dwarf_llpair.elf llpair.c llpaira.o +*/ +#include +#include + +extern void a(int n); + +void b(int n) +{ + int i; + for(i=0;i +void a(int n) +{ + int i; + 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 literal 0 HcmV?d00001 -- 2.30.2