You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
7.8 KiB
223 lines
7.8 KiB
#!/usr/bin/env python3
|
|
|
|
from __future__ import print_function
|
|
|
|
import tempfile
|
|
import unittest
|
|
|
|
from vndk_definition_tool import Elf_Sym, ELF
|
|
|
|
from .compat import StringIO
|
|
|
|
|
|
class ElfSymTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.sym_local = Elf_Sym(0, 0, 4, 0, 0, 1)
|
|
self.sym_global = Elf_Sym(0, 0, 4, 17, 0, 1)
|
|
self.sym_weak = Elf_Sym(0, 0, 4, 33, 0, 1)
|
|
self.sym_undef = Elf_Sym(0, 0, 4, 16, 0, 0)
|
|
|
|
|
|
def test_is_local(self):
|
|
self.assertTrue(self.sym_local.is_local)
|
|
self.assertFalse(self.sym_global.is_local)
|
|
self.assertFalse(self.sym_weak.is_local)
|
|
|
|
|
|
def test_is_global(self):
|
|
self.assertFalse(self.sym_local.is_global)
|
|
self.assertTrue(self.sym_global.is_global)
|
|
self.assertFalse(self.sym_weak.is_global)
|
|
|
|
|
|
def test_is_weak(self):
|
|
self.assertFalse(self.sym_local.is_weak)
|
|
self.assertFalse(self.sym_global.is_weak)
|
|
self.assertTrue(self.sym_weak.is_weak)
|
|
|
|
|
|
def test_is_undef(self):
|
|
self.assertFalse(self.sym_global.is_undef)
|
|
self.assertTrue(self.sym_undef.is_undef)
|
|
|
|
|
|
class ELFTest(unittest.TestCase):
|
|
def test_get_ei_class_from_name(self):
|
|
self.assertEqual(ELF.ELFCLASS32, ELF.get_ei_class_from_name('32'))
|
|
self.assertEqual(ELF.ELFCLASS64, ELF.get_ei_class_from_name('64'))
|
|
|
|
|
|
def test_get_ei_data_from_name(self):
|
|
self.assertEqual(ELF.ELFDATA2LSB,
|
|
ELF.get_ei_data_from_name('Little-Endian'))
|
|
self.assertEqual(ELF.ELFDATA2MSB,
|
|
ELF.get_ei_data_from_name('Big-Endian'))
|
|
|
|
|
|
def test_get_e_machine_from_name(self):
|
|
self.assertEqual(0, ELF.get_e_machine_from_name('EM_NONE'))
|
|
self.assertEqual(3, ELF.get_e_machine_from_name('EM_386'))
|
|
self.assertEqual(8, ELF.get_e_machine_from_name('EM_MIPS'))
|
|
self.assertEqual(40, ELF.get_e_machine_from_name('EM_ARM'))
|
|
self.assertEqual(62, ELF.get_e_machine_from_name('EM_X86_64'))
|
|
self.assertEqual(183, ELF.get_e_machine_from_name('EM_AARCH64'))
|
|
|
|
|
|
def test_repr(self):
|
|
elf = ELF()
|
|
self.assertEqual(elf, eval(repr(elf)))
|
|
|
|
elf = ELF(ei_class=ELF.ELFCLASS32, ei_data=ELF.ELFDATA2LSB,
|
|
e_machine=183, dt_rpath=['a'], dt_runpath=['b'],
|
|
dt_needed=['c', 'd'], exported_symbols={'e', 'f', 'g'})
|
|
self.assertEqual(elf, eval(repr(elf)))
|
|
|
|
|
|
def test_class_name(self):
|
|
self.assertEqual('None', ELF().elf_class_name)
|
|
|
|
elf = ELF(ELF.ELFCLASS32)
|
|
self.assertEqual('32', elf.elf_class_name)
|
|
self.assertTrue(elf.is_32bit)
|
|
self.assertFalse(elf.is_64bit)
|
|
|
|
elf = ELF(ELF.ELFCLASS64)
|
|
self.assertEqual('64', elf.elf_class_name)
|
|
self.assertFalse(elf.is_32bit)
|
|
self.assertTrue(elf.is_64bit)
|
|
|
|
|
|
def test_endianness(self):
|
|
self.assertEqual('None', ELF().elf_data_name)
|
|
self.assertEqual('Little-Endian',
|
|
ELF(None, ELF.ELFDATA2LSB).elf_data_name)
|
|
self.assertEqual('Big-Endian',
|
|
ELF(None, ELF.ELFDATA2MSB).elf_data_name)
|
|
|
|
|
|
def test_machine_name(self):
|
|
self.assertEqual('EM_NONE', ELF(e_machine=0).elf_machine_name)
|
|
self.assertEqual('EM_386', ELF(e_machine=3).elf_machine_name)
|
|
self.assertEqual('EM_MIPS', ELF(e_machine=8).elf_machine_name)
|
|
self.assertEqual('EM_ARM', ELF(e_machine=40).elf_machine_name)
|
|
self.assertEqual('EM_X86_64', ELF(e_machine=62).elf_machine_name)
|
|
self.assertEqual('EM_AARCH64', ELF(e_machine=183).elf_machine_name)
|
|
|
|
|
|
def test_dt_rpath_runpath(self):
|
|
elf = ELF()
|
|
self.assertEqual([], elf.dt_rpath)
|
|
self.assertEqual([], elf.dt_runpath)
|
|
|
|
elf = ELF(None, None, 0, ['a'], ['b'])
|
|
self.assertEqual(['a'], elf.dt_rpath)
|
|
self.assertEqual(['b'], elf.dt_runpath)
|
|
|
|
|
|
def test_dump(self):
|
|
elf = ELF(ELF.ELFCLASS32, ELF.ELFDATA2LSB, 183, ['a'], ['b'],
|
|
['libc.so', 'libm.so'], {'hello', 'world'}, {'d', 'e'})
|
|
|
|
f = StringIO()
|
|
elf.dump(f)
|
|
actual_output = f.getvalue()
|
|
|
|
self.assertEqual('EI_CLASS\t32\n'
|
|
'EI_DATA\t\tLittle-Endian\n'
|
|
'E_MACHINE\tEM_AARCH64\n'
|
|
'FILE_SIZE\t0\n'
|
|
'RO_SEG_FILE_SIZE\t0\n'
|
|
'RO_SEG_MEM_SIZE\t0\n'
|
|
'RW_SEG_FILE_SIZE\t0\n'
|
|
'RW_SEG_MEM_SIZE\t0\n'
|
|
'DT_RPATH\ta\n'
|
|
'DT_RUNPATH\tb\n'
|
|
'DT_NEEDED\tlibc.so\n'
|
|
'DT_NEEDED\tlibm.so\n'
|
|
'EXP_SYMBOL\thello\n'
|
|
'EXP_SYMBOL\tworld\n'
|
|
'IMP_SYMBOL\td\n'
|
|
'IMP_SYMBOL\te\n',
|
|
actual_output)
|
|
|
|
|
|
def test_parse_dump_file(self):
|
|
data = ('EI_CLASS\t64\n'
|
|
'EI_DATA\t\tLittle-Endian\n'
|
|
'E_MACHINE\tEM_AARCH64\n'
|
|
'FILE_SIZE\t90\n'
|
|
'RO_SEG_FILE_SIZE\t18\n'
|
|
'RO_SEG_MEM_SIZE\t24\n'
|
|
'RW_SEG_FILE_SIZE\t42\n'
|
|
'RW_SEG_MEM_SIZE\t81\n'
|
|
'DT_RPATH\trpath_1\n'
|
|
'DT_RPATH\trpath_2\n'
|
|
'DT_RUNPATH\trunpath_1\n'
|
|
'DT_RUNPATH\trunpath_2\n'
|
|
'DT_NEEDED\tlibc.so\n'
|
|
'DT_NEEDED\tlibm.so\n'
|
|
'EXP_SYMBOL\texported_1\n'
|
|
'EXP_SYMBOL\texported_2\n'
|
|
'IMP_SYMBOL\timported_1\n'
|
|
'IMP_SYMBOL\timported_2\n')
|
|
|
|
def check_parse_dump_file_result(res):
|
|
self.assertEqual(ELF.ELFCLASS64, res.ei_class)
|
|
self.assertEqual(ELF.ELFDATA2LSB, res.ei_data)
|
|
self.assertEqual(183, res.e_machine)
|
|
self.assertEqual(90, res.file_size)
|
|
self.assertEqual(18, res.ro_seg_file_size)
|
|
self.assertEqual(24, res.ro_seg_mem_size)
|
|
self.assertEqual(42, res.rw_seg_file_size)
|
|
self.assertEqual(81, res.rw_seg_mem_size)
|
|
self.assertEqual(['rpath_1', 'rpath_2'], res.dt_rpath)
|
|
self.assertEqual(['runpath_1', 'runpath_2'], res.dt_runpath)
|
|
self.assertEqual(['libc.so', 'libm.so'], res.dt_needed)
|
|
self.assertSetEqual({'exported_1', 'exported_2'},
|
|
res.exported_symbols)
|
|
self.assertSetEqual({'imported_1', 'imported_2'},
|
|
res.imported_symbols)
|
|
|
|
# Parse ELF dump from the string buffer.
|
|
check_parse_dump_file_result(ELF.load_dumps(data))
|
|
|
|
# Parse ELF dump from the given file path.
|
|
with tempfile.NamedTemporaryFile('w+') as f:
|
|
f.write(data)
|
|
f.flush()
|
|
f.seek(0)
|
|
|
|
check_parse_dump_file_result(ELF.load_dump(f.name))
|
|
|
|
|
|
class ELFJniLibTest(unittest.TestCase):
|
|
def test_lib_deps(self):
|
|
elf = ELF(dt_needed=['libnativehelper.so'])
|
|
self.assertTrue(elf.is_jni_lib())
|
|
|
|
elf = ELF(dt_needed=['libandroid_runtime.so'])
|
|
self.assertTrue(elf.is_jni_lib())
|
|
|
|
elf = ELF(dt_needed=['libc.so'])
|
|
self.assertFalse(elf.is_jni_lib())
|
|
|
|
|
|
def test_jni_symbols(self):
|
|
elf = ELF(imported_symbols={'JNI_CreateJavaVM'})
|
|
self.assertTrue(elf.is_jni_lib())
|
|
|
|
elf = ELF(exported_symbols={'JNI_CreateJavaVM'})
|
|
self.assertTrue(elf.is_jni_lib())
|
|
|
|
elf = ELF(imported_symbols={'Java_com_example_Example_test'})
|
|
self.assertTrue(elf.is_jni_lib())
|
|
|
|
elf = ELF(exported_symbols={'Java_com_example_Example_test'})
|
|
self.assertTrue(elf.is_jni_lib())
|
|
|
|
elf = ELF(imported_symbols={'printf'})
|
|
self.assertFalse(elf.is_jni_lib())
|
|
|
|
elf = ELF(exported_symbols={'printf'})
|
|
self.assertFalse(elf.is_jni_lib())
|