blob: 035a1af54ba98d3f2fb3f3fb3055162f45a5df71 [file] [log] [blame]
#!/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())