File: test_dynamic.py

package info (click to toggle)
python-pyelftools 0.32-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 68,964 kB
  • sloc: python: 15,903; ansic: 298; asm: 86; makefile: 24; cpp: 18; sh: 4
file content (123 lines) | stat: -rw-r--r-- 4,899 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#-------------------------------------------------------------------------------
# elftools tests
#
# Eli Bendersky (eliben@gmail.com)
# This code is in the public domain
#-------------------------------------------------------------------------------
import unittest
import os

from elftools.elf.elffile import ELFFile
from elftools.common.exceptions import ELFError
from elftools.elf.dynamic import DynamicTag
from elftools.elf.enums import ENUM_D_TAG
from elftools.elf.descriptions import _DESCR_D_TAG, _low_priority_D_TAG


class TestDynamicTag(unittest.TestCase):
    """Tests for the DynamicTag class."""

    def test_requires_stringtable(self):
        with self.assertRaises(ELFError):
            dt = DynamicTag('', None)

    def test_tag_priority(self):
        for tag in _low_priority_D_TAG:
            val = ENUM_D_TAG[tag]
            # if the low priority tag is present in the descriptions,
            # assert that it has not overridden any other tag
            if _DESCR_D_TAG[val] == tag:
                for tag2 in ENUM_D_TAG:
                    if tag2 == tag:
                        continue
                    self.assertNotEqual(ENUM_D_TAG[tag2], val)


class TestDynamic(unittest.TestCase):
    """Tests for the Dynamic class."""

    def test_missing_sections(self):
        """Verify we can get dynamic strings w/out section headers"""

        libs = []
        with open(os.path.join('test', 'testfiles_for_unittests',
                               'aarch64_super_stripped.elf'), 'rb') as f:
            elf = ELFFile(f)
            for segment in elf.iter_segments():
                if segment.header.p_type != 'PT_DYNAMIC':
                    continue

                for t in segment.iter_tags():
                    if t.entry.d_tag == 'DT_NEEDED':
                        libs.append(t.needed)

        exp = ['libc.so.6']
        self.assertEqual(libs, exp)

    def test_reading_symbols_elf_hash(self):
        """ Verify we can read symbol table without SymbolTableSection but with
            a SYSV-style symbol hash table"""
        with open(os.path.join('test', 'testfiles_for_unittests',
                               'aarch64_super_stripped.elf'), 'rb') as f:
            elf = ELFFile(f)
            for segment in elf.iter_segments():
                if segment.header.p_type != 'PT_DYNAMIC':
                    continue

                num_symbols = segment.num_symbols()
                symbol_names = [x.name for x in segment.iter_symbols()]
                symbol_at_index_3 = segment.get_symbol(3)
                symbols_abort = segment.get_symbol_by_name('abort')

        self.assertEqual(num_symbols, 4)
        exp = ['', '__libc_start_main', '__gmon_start__', 'abort']
        self.assertEqual(symbol_names, exp)
        self.assertEqual(symbol_at_index_3.name, 'abort')
        self.assertIsNotNone(symbols_abort)

    def test_reading_symbols_gnu_hash(self):
        """ Verify we can read symbol table without SymbolTableSection but with
            a GNU symbol hash table"""
        with open(os.path.join('test', 'testfiles_for_unittests',
                               'android_dyntags.elf'), 'rb') as f:
            elf = ELFFile(f)
            for segment in elf.iter_segments():
                if segment.header.p_type != 'PT_DYNAMIC':
                    continue

                num_symbols = segment.num_symbols()
                symbol_names = [x.name for x in segment.iter_symbols()]
                symbol_at_index_3 = segment.get_symbol(3)
                symbols_atfork = segment.get_symbol_by_name('__register_atfork')

        self.assertEqual(num_symbols, 212)
        exp = ['', '__cxa_finalize' , '__cxa_atexit', '__register_atfork',
               '__stack_chk_fail', '_ZNK7android7RefBase9decStrongEPKv',
               '_ZN7android7RefBaseD2Ev', '_ZdlPv', 'pthread_mutex_lock']
        self.assertEqual(symbol_names[:9], exp)
        self.assertEqual(symbol_at_index_3.name, '__register_atfork')
        self.assertIsNotNone(symbols_atfork)

    def test_sunw_tags(self):
        def extract_sunw(filename):
            with open(filename, 'rb') as f:
                elf = ELFFile(f)
                dyn = elf.get_section_by_name('.dynamic')

                seen = set()
                for tag in dyn.iter_tags():
                    if type(tag.entry.d_tag) is str and \
                            tag.entry.d_tag.startswith("DT_SUNW"):
                        seen.add(tag.entry.d_tag)

            return seen

        f1 = extract_sunw(os.path.join('test', 'testfiles_for_unittests',
            'exe_solaris32_cc.sparc.elf'))
        f2 = extract_sunw(os.path.join('test', 'testfiles_for_unittests',
            'android_dyntags.elf'))
        self.assertEqual(f1, {'DT_SUNW_STRPAD', 'DT_SUNW_LDMACH'})
        self.assertEqual(f2, set())

if __name__ == '__main__':
    unittest.main()