1 #!/usr/bin/env python3 2 3 from __future__ import print_function 4 5 import os 6 import sys 7 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 8 9 import tempfile 10 import unittest 11 12 from compat import StringIO 13 from vndk_definition_tool import Elf_Sym, ELF 14 15 class ElfSymTest(unittest.TestCase): 16 def setUp(self): 17 self.sym_local = Elf_Sym(0, 0, 4, 0, 0, 1) 18 self.sym_global = Elf_Sym(0, 0, 4, 17, 0, 1) 19 self.sym_weak = Elf_Sym(0, 0, 4, 33, 0, 1) 20 self.sym_undef = Elf_Sym(0, 0, 4, 16, 0, 0) 21 22 def test_is_local(self): 23 self.assertTrue(self.sym_local.is_local) 24 self.assertFalse(self.sym_global.is_local) 25 self.assertFalse(self.sym_weak.is_local) 26 27 def test_is_global(self): 28 self.assertFalse(self.sym_local.is_global) 29 self.assertTrue(self.sym_global.is_global) 30 self.assertFalse(self.sym_weak.is_global) 31 32 def test_is_weak(self): 33 self.assertFalse(self.sym_local.is_weak) 34 self.assertFalse(self.sym_global.is_weak) 35 self.assertTrue(self.sym_weak.is_weak) 36 37 def test_is_undef(self): 38 self.assertFalse(self.sym_global.is_undef) 39 self.assertTrue(self.sym_undef.is_undef) 40 41 42 class ELFTest(unittest.TestCase): 43 def test_get_ei_class_from_name(self): 44 self.assertEqual(ELF.ELFCLASS32, ELF.get_ei_class_from_name('32')) 45 self.assertEqual(ELF.ELFCLASS64, ELF.get_ei_class_from_name('64')) 46 47 def test_get_ei_data_from_name(self): 48 self.assertEqual(ELF.ELFDATA2LSB, 49 ELF.get_ei_data_from_name('Little-Endian')) 50 self.assertEqual(ELF.ELFDATA2MSB, 51 ELF.get_ei_data_from_name('Big-Endian')) 52 53 def test_get_e_machine_from_name(self): 54 self.assertEqual(0, ELF.get_e_machine_from_name('EM_NONE')) 55 self.assertEqual(3, ELF.get_e_machine_from_name('EM_386')) 56 self.assertEqual(8, ELF.get_e_machine_from_name('EM_MIPS')) 57 self.assertEqual(40, ELF.get_e_machine_from_name('EM_ARM')) 58 self.assertEqual(62, ELF.get_e_machine_from_name('EM_X86_64')) 59 self.assertEqual(183, ELF.get_e_machine_from_name('EM_AARCH64')) 60 61 def test_repr(self): 62 elf = ELF() 63 self.assertEqual(elf, eval(repr(elf))) 64 65 elf = ELF(ei_class=ELF.ELFCLASS32, ei_data=ELF.ELFDATA2LSB, 66 e_machine=183, dt_rpath=['a'], dt_runpath=['b'], 67 dt_needed=['c', 'd'], exported_symbols={'e', 'f', 'g'}) 68 self.assertEqual(elf, eval(repr(elf))) 69 70 def test_class_name(self): 71 self.assertEqual('None', ELF().elf_class_name) 72 73 elf = ELF(ELF.ELFCLASS32) 74 self.assertEqual('32', elf.elf_class_name) 75 self.assertTrue(elf.is_32bit) 76 self.assertFalse(elf.is_64bit) 77 78 elf = ELF(ELF.ELFCLASS64) 79 self.assertEqual('64', elf.elf_class_name) 80 self.assertFalse(elf.is_32bit) 81 self.assertTrue(elf.is_64bit) 82 83 def test_endianness(self): 84 self.assertEqual('None', ELF().elf_data_name) 85 self.assertEqual('Little-Endian', 86 ELF(None, ELF.ELFDATA2LSB).elf_data_name) 87 self.assertEqual('Big-Endian', 88 ELF(None, ELF.ELFDATA2MSB).elf_data_name) 89 90 def test_machine_name(self): 91 self.assertEqual('EM_NONE', ELF(e_machine=0).elf_machine_name) 92 self.assertEqual('EM_386', ELF(e_machine=3).elf_machine_name) 93 self.assertEqual('EM_MIPS', ELF(e_machine=8).elf_machine_name) 94 self.assertEqual('EM_ARM', ELF(e_machine=40).elf_machine_name) 95 self.assertEqual('EM_X86_64', ELF(e_machine=62).elf_machine_name) 96 self.assertEqual('EM_AARCH64', ELF(e_machine=183).elf_machine_name) 97 98 def test_dt_rpath_runpath(self): 99 elf = ELF() 100 self.assertEqual([], elf.dt_rpath) 101 self.assertEqual([], elf.dt_runpath) 102 103 elf = ELF(None, None, 0, ['a'], ['b']) 104 self.assertEqual(['a'], elf.dt_rpath) 105 self.assertEqual(['b'], elf.dt_runpath) 106 107 def test_dump(self): 108 elf = ELF(ELF.ELFCLASS32, ELF.ELFDATA2LSB, 183, ['a'], ['b'], 109 ['libc.so', 'libm.so'], {'hello', 'world'}, {'d', 'e'}) 110 111 f = StringIO() 112 elf.dump(f) 113 actual_output = f.getvalue() 114 115 self.assertEqual('EI_CLASS\t32\n' 116 'EI_DATA\t\tLittle-Endian\n' 117 'E_MACHINE\tEM_AARCH64\n' 118 'DT_RPATH\ta\n' 119 'DT_RUNPATH\tb\n' 120 'DT_NEEDED\tlibc.so\n' 121 'DT_NEEDED\tlibm.so\n' 122 'EXP_SYMBOL\thello\n' 123 'EXP_SYMBOL\tworld\n' 124 'IMP_SYMBOL\td\n' 125 'IMP_SYMBOL\te\n', 126 actual_output) 127 128 def test_parse_dump_file(self): 129 data = ('EI_CLASS\t64\n' 130 'EI_DATA\t\tLittle-Endian\n' 131 'E_MACHINE\tEM_AARCH64\n' 132 'DT_RPATH\trpath_1\n' 133 'DT_RPATH\trpath_2\n' 134 'DT_RUNPATH\trunpath_1\n' 135 'DT_RUNPATH\trunpath_2\n' 136 'DT_NEEDED\tlibc.so\n' 137 'DT_NEEDED\tlibm.so\n' 138 'EXP_SYMBOL\texported_1\n' 139 'EXP_SYMBOL\texported_2\n' 140 'IMP_SYMBOL\timported_1\n' 141 'IMP_SYMBOL\timported_2\n') 142 143 def check_parse_dump_file_result(res): 144 self.assertEqual(ELF.ELFCLASS64, res.ei_class) 145 self.assertEqual(ELF.ELFDATA2LSB, res.ei_data) 146 self.assertEqual(183, res.e_machine) 147 self.assertEqual(['rpath_1', 'rpath_2'], res.dt_rpath) 148 self.assertEqual(['runpath_1', 'runpath_2'], res.dt_runpath) 149 self.assertEqual(['libc.so', 'libm.so'], res.dt_needed) 150 self.assertSetEqual({'exported_1', 'exported_2'}, 151 res.exported_symbols) 152 self.assertSetEqual({'imported_1', 'imported_2'}, 153 res.imported_symbols) 154 155 # Parse ELF dump from the string buffer. 156 check_parse_dump_file_result(ELF.load_dumps(data)) 157 158 # Parse ELF dump from the given file path. 159 with tempfile.NamedTemporaryFile('w+') as f: 160 f.write(data) 161 f.flush() 162 f.seek(0) 163 164 check_parse_dump_file_result(ELF.load_dump(f.name)) 165 166 167 if __name__ == '__main__': 168 unittest.main() 169