1#!/usr/bin/env python3 2 3from __future__ import print_function 4 5import os 6import sys 7sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 8 9import tempfile 10import unittest 11 12from compat import StringIO 13from vndk_definition_tool import Elf_Sym, ELF 14 15class 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 42class 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 'FILE_SIZE\t0\n' 119 'RO_SEG_FILE_SIZE\t0\n' 120 'RO_SEG_MEM_SIZE\t0\n' 121 'RW_SEG_FILE_SIZE\t0\n' 122 'RW_SEG_MEM_SIZE\t0\n' 123 'DT_RPATH\ta\n' 124 'DT_RUNPATH\tb\n' 125 'DT_NEEDED\tlibc.so\n' 126 'DT_NEEDED\tlibm.so\n' 127 'EXP_SYMBOL\thello\n' 128 'EXP_SYMBOL\tworld\n' 129 'IMP_SYMBOL\td\n' 130 'IMP_SYMBOL\te\n', 131 actual_output) 132 133 def test_parse_dump_file(self): 134 data = ('EI_CLASS\t64\n' 135 'EI_DATA\t\tLittle-Endian\n' 136 'E_MACHINE\tEM_AARCH64\n' 137 'FILE_SIZE\t90\n' 138 'RO_SEG_FILE_SIZE\t18\n' 139 'RO_SEG_MEM_SIZE\t24\n' 140 'RW_SEG_FILE_SIZE\t42\n' 141 'RW_SEG_MEM_SIZE\t81\n' 142 'DT_RPATH\trpath_1\n' 143 'DT_RPATH\trpath_2\n' 144 'DT_RUNPATH\trunpath_1\n' 145 'DT_RUNPATH\trunpath_2\n' 146 'DT_NEEDED\tlibc.so\n' 147 'DT_NEEDED\tlibm.so\n' 148 'EXP_SYMBOL\texported_1\n' 149 'EXP_SYMBOL\texported_2\n' 150 'IMP_SYMBOL\timported_1\n' 151 'IMP_SYMBOL\timported_2\n') 152 153 def check_parse_dump_file_result(res): 154 self.assertEqual(ELF.ELFCLASS64, res.ei_class) 155 self.assertEqual(ELF.ELFDATA2LSB, res.ei_data) 156 self.assertEqual(183, res.e_machine) 157 self.assertEqual(90, res.file_size) 158 self.assertEqual(18, res.ro_seg_file_size) 159 self.assertEqual(24, res.ro_seg_mem_size) 160 self.assertEqual(42, res.rw_seg_file_size) 161 self.assertEqual(81, res.rw_seg_mem_size) 162 self.assertEqual(['rpath_1', 'rpath_2'], res.dt_rpath) 163 self.assertEqual(['runpath_1', 'runpath_2'], res.dt_runpath) 164 self.assertEqual(['libc.so', 'libm.so'], res.dt_needed) 165 self.assertSetEqual({'exported_1', 'exported_2'}, 166 res.exported_symbols) 167 self.assertSetEqual({'imported_1', 'imported_2'}, 168 res.imported_symbols) 169 170 # Parse ELF dump from the string buffer. 171 check_parse_dump_file_result(ELF.load_dumps(data)) 172 173 # Parse ELF dump from the given file path. 174 with tempfile.NamedTemporaryFile('w+') as f: 175 f.write(data) 176 f.flush() 177 f.seek(0) 178 179 check_parse_dump_file_result(ELF.load_dump(f.name)) 180 181 182class ELFJniLibTest(unittest.TestCase): 183 def test_lib_deps(self): 184 elf = ELF(dt_needed=['libnativehelper.so']) 185 self.assertTrue(elf.is_jni_lib()) 186 187 elf = ELF(dt_needed=['libandroid_runtime.so']) 188 self.assertTrue(elf.is_jni_lib()) 189 190 elf = ELF(dt_needed=['libc.so']) 191 self.assertFalse(elf.is_jni_lib()) 192 193 def test_jni_symbols(self): 194 elf = ELF(imported_symbols={'JNI_CreateJavaVM'}) 195 self.assertTrue(elf.is_jni_lib()) 196 197 elf = ELF(exported_symbols={'JNI_CreateJavaVM'}) 198 self.assertTrue(elf.is_jni_lib()) 199 200 elf = ELF(imported_symbols={'Java_com_example_Example_test'}) 201 self.assertTrue(elf.is_jni_lib()) 202 203 elf = ELF(exported_symbols={'Java_com_example_Example_test'}) 204 self.assertTrue(elf.is_jni_lib()) 205 206 elf = ELF(imported_symbols={'printf'}) 207 self.assertFalse(elf.is_jni_lib()) 208 209 elf = ELF(exported_symbols={'printf'}) 210 self.assertFalse(elf.is_jni_lib()) 211 212 213if __name__ == '__main__': 214 unittest.main() 215