['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
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)
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
"""
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'])
--- /dev/null
+#------------------------------------------------------------------------------
+# 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()