1# -------------------------------------------------------------------------------
2# elftools: tests
3#
4# LeadroyaL (leadroyal@qq.com)
5# This code is in the public domain
6# -------------------------------------------------------------------------------
7
8import unittest
9import os
10
11from elftools.ehabi.ehabiinfo import EHABIEntry, CannotUnwindEHABIEntry, GenericEHABIEntry, CorruptEHABIEntry
12from elftools.elf.elffile import ELFFile
13
14
15class TestEHABIELF(unittest.TestCase):
16    """ Parse ELF and visit ARM exception handler index table entry.
17    """
18
19    def test_parse_object_file(self):
20        # FIXME: `.ARM.exidx.text.XXX` need relocation, it's too complex for current unittest.
21        fname = os.path.join('test', 'testfiles_for_unittests', 'arm_exidx_test.o')
22        with open(fname, 'rb') as f:
23            elf = ELFFile(f)
24            try:
25                elf.get_ehabi_infos()
26                self.assertTrue(False, "Unreachable code")
27            except AssertionError as e:
28                self.assertEqual(str(e), "Current version of pyelftools doesn't support relocatable file.")
29
30    def test_parse_shared_library(self):
31        fname = os.path.join('test', 'testfiles_for_unittests', 'arm_exidx_test.so')
32        with open(fname, 'rb') as f:
33            elf = ELFFile(f)
34            self.assertTrue(elf.has_ehabi_info())
35            infos = elf.get_ehabi_infos()
36            self.assertEqual(1, len(infos))
37            info = infos[0]
38
39            self.assertIsInstance(info.get_entry(0), EHABIEntry)
40            self.assertEqual(info.get_entry(0).function_offset, 0x34610)
41            self.assertEqual(info.get_entry(0).eh_table_offset, 0x69544)
42            self.assertEqual(info.get_entry(0).bytecode_array, [0x97, 0x41, 0x84, 0x0d, 0xb0, 0xb0])
43
44            self.assertIsInstance(info.get_entry(7), CannotUnwindEHABIEntry)
45            self.assertEqual(info.get_entry(7).function_offset, 0x346f8)
46
47            self.assertIsInstance(info.get_entry(8), EHABIEntry)
48            self.assertEqual(info.get_entry(8).personality, 0)
49            self.assertEqual(info.get_entry(8).function_offset, 0x3473c)
50            self.assertEqual(info.get_entry(8).bytecode_array, [0x97, 0x84, 0x08])
51
52            self.assertIsInstance(info.get_entry(9), GenericEHABIEntry)
53            self.assertEqual(info.get_entry(9).function_offset, 0x3477c)
54            self.assertEqual(info.get_entry(9).personality, 0x31a30)
55
56            for i in range(info.num_entry()):
57                self.assertNotIsInstance(info.get_entry(i), CorruptEHABIEntry)
58
59    def test_parse_executable(self):
60        fname = os.path.join('test', 'testfiles_for_unittests', 'arm_exidx_test.elf')
61        with open(fname, 'rb') as f:
62            elf = ELFFile(f)
63            self.assertTrue(elf.has_ehabi_info())
64            infos = elf.get_ehabi_infos()
65            self.assertEqual(1, len(infos))
66            info = infos[0]
67
68            self.assertIsInstance(info.get_entry(0), EHABIEntry)
69            self.assertEqual(info.get_entry(0).function_offset, 0x4f50)
70            self.assertEqual(info.get_entry(0).eh_table_offset, 0x22864)
71            self.assertEqual(info.get_entry(0).bytecode_array, [0x97, 0x41, 0x84, 0x0d, 0xb0, 0xb0])
72
73            self.assertIsInstance(info.get_entry(7), CannotUnwindEHABIEntry)
74            self.assertEqual(info.get_entry(7).function_offset, 0x5040)
75
76            self.assertIsInstance(info.get_entry(8), GenericEHABIEntry)
77            self.assertEqual(info.get_entry(8).personality, 0x15d21)
78
79            self.assertIsInstance(info.get_entry(9), EHABIEntry)
80            self.assertEqual(info.get_entry(9).function_offset, 0x5144)
81            self.assertEqual(info.get_entry(9).personality, 0)
82            self.assertEqual(info.get_entry(9).bytecode_array, [0x97, 0x84, 0x08])
83
84            for i in range(info.num_entry()):
85                self.assertNotIsInstance(info.get_entry(i), CorruptEHABIEntry)
86
87
88if __name__ == '__main__':
89    unittest.main()
90