1#!/usr/bin/env python3 2 3from __future__ import print_function 4 5import tempfile 6import unittest 7 8from vndk_definition_tool import Elf_Sym, ELF 9 10from .compat import StringIO 11 12 13class ElfSymTest(unittest.TestCase): 14 def setUp(self): 15 self.sym_local = Elf_Sym(0, 0, 4, 0, 0, 1) 16 self.sym_global = Elf_Sym(0, 0, 4, 17, 0, 1) 17 self.sym_weak = Elf_Sym(0, 0, 4, 33, 0, 1) 18 self.sym_undef = Elf_Sym(0, 0, 4, 16, 0, 0) 19 20 21 def test_is_local(self): 22 self.assertTrue(self.sym_local.is_local) 23 self.assertFalse(self.sym_global.is_local) 24 self.assertFalse(self.sym_weak.is_local) 25 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 33 def test_is_weak(self): 34 self.assertFalse(self.sym_local.is_weak) 35 self.assertFalse(self.sym_global.is_weak) 36 self.assertTrue(self.sym_weak.is_weak) 37 38 39 def test_is_undef(self): 40 self.assertFalse(self.sym_global.is_undef) 41 self.assertTrue(self.sym_undef.is_undef) 42 43 44class ELFTest(unittest.TestCase): 45 def test_get_ei_class_from_name(self): 46 self.assertEqual(ELF.ELFCLASS32, ELF.get_ei_class_from_name('32')) 47 self.assertEqual(ELF.ELFCLASS64, ELF.get_ei_class_from_name('64')) 48 49 50 def test_get_ei_data_from_name(self): 51 self.assertEqual(ELF.ELFDATA2LSB, 52 ELF.get_ei_data_from_name('Little-Endian')) 53 self.assertEqual(ELF.ELFDATA2MSB, 54 ELF.get_ei_data_from_name('Big-Endian')) 55 56 57 def test_get_e_machine_from_name(self): 58 self.assertEqual(0, ELF.get_e_machine_from_name('EM_NONE')) 59 self.assertEqual(3, ELF.get_e_machine_from_name('EM_386')) 60 self.assertEqual(8, ELF.get_e_machine_from_name('EM_MIPS')) 61 self.assertEqual(40, ELF.get_e_machine_from_name('EM_ARM')) 62 self.assertEqual(62, ELF.get_e_machine_from_name('EM_X86_64')) 63 self.assertEqual(183, ELF.get_e_machine_from_name('EM_AARCH64')) 64 65 66 def test_repr(self): 67 elf = ELF() 68 self.assertEqual(elf, eval(repr(elf))) 69 70 elf = ELF(ei_class=ELF.ELFCLASS32, ei_data=ELF.ELFDATA2LSB, 71 e_machine=183, dt_rpath=['a'], dt_runpath=['b'], 72 dt_needed=['c', 'd'], exported_symbols={'e', 'f', 'g'}) 73 self.assertEqual(elf, eval(repr(elf))) 74 75 76 def test_class_name(self): 77 self.assertEqual('None', ELF().elf_class_name) 78 79 elf = ELF(ELF.ELFCLASS32) 80 self.assertEqual('32', elf.elf_class_name) 81 self.assertTrue(elf.is_32bit) 82 self.assertFalse(elf.is_64bit) 83 84 elf = ELF(ELF.ELFCLASS64) 85 self.assertEqual('64', elf.elf_class_name) 86 self.assertFalse(elf.is_32bit) 87 self.assertTrue(elf.is_64bit) 88 89 90 def test_endianness(self): 91 self.assertEqual('None', ELF().elf_data_name) 92 self.assertEqual('Little-Endian', 93 ELF(None, ELF.ELFDATA2LSB).elf_data_name) 94 self.assertEqual('Big-Endian', 95 ELF(None, ELF.ELFDATA2MSB).elf_data_name) 96 97 98 def test_machine_name(self): 99 self.assertEqual('EM_NONE', ELF(e_machine=0).elf_machine_name) 100 self.assertEqual('EM_386', ELF(e_machine=3).elf_machine_name) 101 self.assertEqual('EM_MIPS', ELF(e_machine=8).elf_machine_name) 102 self.assertEqual('EM_ARM', ELF(e_machine=40).elf_machine_name) 103 self.assertEqual('EM_X86_64', ELF(e_machine=62).elf_machine_name) 104 self.assertEqual('EM_AARCH64', ELF(e_machine=183).elf_machine_name) 105 106 107 def test_dt_rpath_runpath(self): 108 elf = ELF() 109 self.assertEqual([], elf.dt_rpath) 110 self.assertEqual([], elf.dt_runpath) 111 112 elf = ELF(None, None, 0, ['a'], ['b']) 113 self.assertEqual(['a'], elf.dt_rpath) 114 self.assertEqual(['b'], elf.dt_runpath) 115 116 117 def test_dump(self): 118 elf = ELF(ELF.ELFCLASS32, ELF.ELFDATA2LSB, 183, ['a'], ['b'], 119 ['libc.so', 'libm.so'], {'hello', 'world'}, {'d', 'e'}) 120 121 f = StringIO() 122 elf.dump(f) 123 actual_output = f.getvalue() 124 125 self.assertEqual('EI_CLASS\t32\n' 126 'EI_DATA\t\tLittle-Endian\n' 127 'E_MACHINE\tEM_AARCH64\n' 128 'FILE_SIZE\t0\n' 129 'RO_SEG_FILE_SIZE\t0\n' 130 'RO_SEG_MEM_SIZE\t0\n' 131 'RW_SEG_FILE_SIZE\t0\n' 132 'RW_SEG_MEM_SIZE\t0\n' 133 'DT_RPATH\ta\n' 134 'DT_RUNPATH\tb\n' 135 'DT_NEEDED\tlibc.so\n' 136 'DT_NEEDED\tlibm.so\n' 137 'EXP_SYMBOL\thello\n' 138 'EXP_SYMBOL\tworld\n' 139 'IMP_SYMBOL\td\n' 140 'IMP_SYMBOL\te\n', 141 actual_output) 142 143 144 def test_parse_dump_file(self): 145 data = ('EI_CLASS\t64\n' 146 'EI_DATA\t\tLittle-Endian\n' 147 'E_MACHINE\tEM_AARCH64\n' 148 'FILE_SIZE\t90\n' 149 'RO_SEG_FILE_SIZE\t18\n' 150 'RO_SEG_MEM_SIZE\t24\n' 151 'RW_SEG_FILE_SIZE\t42\n' 152 'RW_SEG_MEM_SIZE\t81\n' 153 'DT_RPATH\trpath_1\n' 154 'DT_RPATH\trpath_2\n' 155 'DT_RUNPATH\trunpath_1\n' 156 'DT_RUNPATH\trunpath_2\n' 157 'DT_NEEDED\tlibc.so\n' 158 'DT_NEEDED\tlibm.so\n' 159 'EXP_SYMBOL\texported_1\n' 160 'EXP_SYMBOL\texported_2\n' 161 'IMP_SYMBOL\timported_1\n' 162 'IMP_SYMBOL\timported_2\n') 163 164 def check_parse_dump_file_result(res): 165 self.assertEqual(ELF.ELFCLASS64, res.ei_class) 166 self.assertEqual(ELF.ELFDATA2LSB, res.ei_data) 167 self.assertEqual(183, res.e_machine) 168 self.assertEqual(90, res.file_size) 169 self.assertEqual(18, res.ro_seg_file_size) 170 self.assertEqual(24, res.ro_seg_mem_size) 171 self.assertEqual(42, res.rw_seg_file_size) 172 self.assertEqual(81, res.rw_seg_mem_size) 173 self.assertEqual(['rpath_1', 'rpath_2'], res.dt_rpath) 174 self.assertEqual(['runpath_1', 'runpath_2'], res.dt_runpath) 175 self.assertEqual(['libc.so', 'libm.so'], res.dt_needed) 176 self.assertSetEqual({'exported_1', 'exported_2'}, 177 res.exported_symbols) 178 self.assertSetEqual({'imported_1', 'imported_2'}, 179 res.imported_symbols) 180 181 # Parse ELF dump from the string buffer. 182 check_parse_dump_file_result(ELF.load_dumps(data)) 183 184 # Parse ELF dump from the given file path. 185 with tempfile.NamedTemporaryFile('w+') as f: 186 f.write(data) 187 f.flush() 188 f.seek(0) 189 190 check_parse_dump_file_result(ELF.load_dump(f.name)) 191 192 193class ELFJniLibTest(unittest.TestCase): 194 def test_lib_deps(self): 195 elf = ELF(dt_needed=['libnativehelper.so']) 196 self.assertTrue(elf.is_jni_lib()) 197 198 elf = ELF(dt_needed=['libandroid_runtime.so']) 199 self.assertTrue(elf.is_jni_lib()) 200 201 elf = ELF(dt_needed=['libc.so']) 202 self.assertFalse(elf.is_jni_lib()) 203 204 205 def test_jni_symbols(self): 206 elf = ELF(imported_symbols={'JNI_CreateJavaVM'}) 207 self.assertTrue(elf.is_jni_lib()) 208 209 elf = ELF(exported_symbols={'JNI_CreateJavaVM'}) 210 self.assertTrue(elf.is_jni_lib()) 211 212 elf = ELF(imported_symbols={'Java_com_example_Example_test'}) 213 self.assertTrue(elf.is_jni_lib()) 214 215 elf = ELF(exported_symbols={'Java_com_example_Example_test'}) 216 self.assertTrue(elf.is_jni_lib()) 217 218 elf = ELF(imported_symbols={'printf'}) 219 self.assertFalse(elf.is_jni_lib()) 220 221 elf = ELF(exported_symbols={'printf'}) 222 self.assertFalse(elf.is_jni_lib()) 223