From 4cbbf8bd5d4cfbb9269e9bca2a3eed2f04ce6c72 Mon Sep 17 00:00:00 2001 From: Yann Rouillard Date: Tue, 9 Jul 2013 20:22:27 +0200 Subject: [PATCH] Correctly handle the "multiple string tables" case for string resolution in the dynamic section The index of the string table section used to resolve various strings in the dynamic section is given by the sh_link field in the dynamic section header. As several string tables with the same name can co-exist in an elf file we must explicitely look for this specific string table instead of looking for the first string table in the file. --- elftools/elf/dynamic.py | 26 +++++-- test/test_double_dynstr_section.py | 64 ++++++++++++++++++ .../lib_with_two_dynstr_sections.so.1.elf | Bin 0 -> 8800 bytes ...with_two_dynstr_sections_reversed.so.1.elf | Bin 0 -> 2102032 bytes 4 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 test/test_double_dynstr_section.py create mode 100755 test/testfiles_for_unittests/lib_with_two_dynstr_sections.so.1.elf create mode 100755 test/testfiles_for_unittests/lib_with_two_dynstr_sections_reversed.so.1.elf diff --git a/elftools/elf/dynamic.py b/elftools/elf/dynamic.py index 60fb450..e36598e 100644 --- a/elftools/elf/dynamic.py +++ b/elftools/elf/dynamic.py @@ -28,12 +28,11 @@ class DynamicTag(object): ['DT_NEEDED', 'DT_RPATH', 'DT_RUNPATH', 'DT_SONAME', 'DT_SUNW_FILTER']) - def __init__(self, entry, elffile): + def __init__(self, entry, stringtable): self.entry = entry if entry.d_tag in self._HANDLED_TAGS: - dynstr = elffile.get_section_by_name(b'.dynstr') setattr(self, entry.d_tag[3:].lower(), - dynstr.get_string(self.entry.d_val)) + stringtable.get_string(self.entry.d_val)) def __getitem__(self, name): """ Implement dict-like access to entries @@ -54,13 +53,14 @@ class DynamicTag(object): class Dynamic(object): """ Shared functionality between dynamic sections and segments. """ - def __init__(self, stream, elffile, position): + def __init__(self, stream, elffile, stringtable, position): self._stream = stream self._elffile = elffile self._elfstructs = elffile.structs self._num_tags = -1 self._offset = position self._tagsize = self._elfstructs.Elf_Dyn.sizeof() + self._stringtable = stringtable def iter_tags(self, type=None): """ Yield all tags (limit to |type| if specified) @@ -80,7 +80,7 @@ class Dynamic(object): self._elfstructs.Elf_Dyn, self._stream, stream_pos=offset) - return DynamicTag(entry, self._elffile) + return DynamicTag(entry, self._stringtable) def num_tags(self): """ Number of dynamic tags in the file @@ -100,12 +100,24 @@ class DynamicSection(Section, Dynamic): """ def __init__(self, header, name, stream, elffile): Section.__init__(self, header, name, stream) - Dynamic.__init__(self, stream, elffile, self['sh_offset']) + stringtable = elffile.get_section(header['sh_link']) + Dynamic.__init__(self, stream, elffile, stringtable, self['sh_offset']) class DynamicSegment(Segment, Dynamic): """ ELF dynamic table segment. Knows how to process the list of tags. """ def __init__(self, header, stream, elffile): + # The string table section to be used to resolve string names in + # the dynamic tag array is the one pointed at by the sh_link field + # of the dynamic section header. + # So we must look for the dynamic section contained in the dynamic + # segment, we do so by searching for the dynamic section whose content + # is located at the same offset as the dynamic segment + for section in elffile.iter_sections(): + if (isinstance(section, DynamicSection) and + section['sh_offset'] == header['p_offset']): + stringtable = elffile.get_section(section['sh_link']) + break Segment.__init__(self, header, stream) - Dynamic.__init__(self, stream, elffile, self['p_offset']) + Dynamic.__init__(self, stream, elffile, stringtable, self['p_offset']) diff --git a/test/test_double_dynstr_section.py b/test/test_double_dynstr_section.py new file mode 100644 index 0000000..c907928 --- /dev/null +++ b/test/test_double_dynstr_section.py @@ -0,0 +1,64 @@ +#------------------------------------------------------------------------------ +# elftools tests +# +# Yann Rouillard (yann@pleiades.fr.eu.org) +# This code is in the public domain +#------------------------------------------------------------------------------ +try: + import unittest2 as unittest +except ImportError: + import unittest +import os + +from utils import setup_syspath +setup_syspath() +from elftools.elf.elffile import ELFFile +from elftools.elf.dynamic import DynamicSection, DynamicTag + + +class TestDoubleDynstrSections(unittest.TestCase): + """ This test make sure than dynamic tags + are properly analyzed when two .dynstr + sections are present in an elf file + """ + + reference_data = [ + b'libz.so.1', + b'libc.so.6', + b'lib_versioned.so.1', + ] + + def _test_double_dynstr_section_generic(self, testfile): + + with open(os.path.join('test', 'testfiles_for_unittests', testfile), + 'rb') as f: + + elf = ELFFile(f) + for section in elf.iter_sections(): + if isinstance(section, DynamicSection): + d_tags = [getattr(x, x.entry.d_tag[3:].lower()) + for x in section.iter_tags() + if x.entry.d_tag in DynamicTag._HANDLED_TAGS] + self.assertListEqual( + TestDoubleDynstrSections.reference_data, + d_tags) + return + + self.fail('No dynamic section found !!') + + + def test_double_dynstr_section(self): + """ First test with the good dynstr section first + """ + self._test_double_dynstr_section_generic( + 'lib_with_two_dynstr_sections.so.1.elf') + + def test_double_dynstr_section_reverse(self): + """ Second test with the good dynstr section last + """ + self._test_double_dynstr_section_generic( + 'lib_with_two_dynstr_sections_reversed.so.1.elf') + + +if __name__ == '__main__': + unittest.main() diff --git a/test/testfiles_for_unittests/lib_with_two_dynstr_sections.so.1.elf b/test/testfiles_for_unittests/lib_with_two_dynstr_sections.so.1.elf new file mode 100755 index 0000000000000000000000000000000000000000..661950b8d800fd11038326accbdc68cea417777a GIT binary patch literal 8800 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 JcS0YU{0DVV6V?C# literal 0 HcmV?d00001 diff --git a/test/testfiles_for_unittests/lib_with_two_dynstr_sections_reversed.so.1.elf b/test/testfiles_for_unittests/lib_with_two_dynstr_sections_reversed.so.1.elf new file mode 100755 index 0000000000000000000000000000000000000000..8d07de1d20585c436d69b1ca3dfd6c250de98f1f GIT binary patch literal 2102032 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