vndk-def: Add parse from ELF dump file.
Test: ./tests/test_elf.py Change-Id: Icff8aeeb395c201261ed53f421d714edb28dba5d
This commit is contained in:
@@ -6,6 +6,7 @@ import os
|
||||
import sys
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
from compat import StringIO
|
||||
@@ -39,6 +40,24 @@ class ElfSymTest(unittest.TestCase):
|
||||
|
||||
|
||||
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)))
|
||||
@@ -116,5 +135,44 @@ class ELFTest(unittest.TestCase):
|
||||
|
||||
self.assertEqual('hello\nworld\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'
|
||||
'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(['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))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -141,6 +141,26 @@ class ELF(object):
|
||||
}
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _dict_find_key_by_value(d, dst):
|
||||
for key, value in d.items():
|
||||
if value == dst:
|
||||
return key
|
||||
raise KeyError(dst)
|
||||
|
||||
@staticmethod
|
||||
def get_ei_class_from_name(name):
|
||||
return ELF._dict_find_key_by_value(ELF._ELF_CLASS_NAMES, name)
|
||||
|
||||
@staticmethod
|
||||
def get_ei_data_from_name(name):
|
||||
return ELF._dict_find_key_by_value(ELF._ELF_DATA_NAMES, name)
|
||||
|
||||
@staticmethod
|
||||
def get_e_machine_from_name(name):
|
||||
return ELF._dict_find_key_by_value(ELF._ELF_MACHINE_IDS, name)
|
||||
|
||||
|
||||
__slots__ = ('ei_class', 'ei_data', 'e_machine', 'dt_rpath', 'dt_runpath',
|
||||
'dt_needed', 'exported_symbols', 'imported_symbols',)
|
||||
|
||||
@@ -388,6 +408,47 @@ class ELF(object):
|
||||
with mmap(f.fileno(), st.st_size, access=ACCESS_READ) as image:
|
||||
self._parse_from_buf(image)
|
||||
|
||||
def _parse_from_dump_lines(self, path, lines):
|
||||
patt = re.compile('^([A-Za-z_]+)\t+(.*)$')
|
||||
for line_no, line in enumerate(lines):
|
||||
match = patt.match(line)
|
||||
if not match:
|
||||
print('error: {}: {}: failed to parse'
|
||||
.format(path, line_no + 1), file=sys.stderr)
|
||||
continue
|
||||
key = match.group(1)
|
||||
value = match.group(2)
|
||||
|
||||
if key == 'EI_CLASS':
|
||||
self.ei_class = ELF.get_ei_class_from_name(value)
|
||||
elif key == 'EI_DATA':
|
||||
self.ei_data = ELF.get_ei_data_from_name(value)
|
||||
elif key == 'E_MACHINE':
|
||||
self.e_machine = ELF.get_e_machine_from_name(value)
|
||||
elif key == 'DT_RPATH':
|
||||
self.dt_rpath.append(intern(value))
|
||||
elif key == 'DT_RUNPATH':
|
||||
self.dt_runpath.append(intern(value))
|
||||
elif key == 'DT_NEEDED':
|
||||
self.dt_needed.append(intern(value))
|
||||
elif key == 'EXP_SYMBOL':
|
||||
self.exported_symbols.add(intern(value))
|
||||
elif key == 'IMP_SYMBOL':
|
||||
self.imported_symbols.add(intern(value))
|
||||
else:
|
||||
print('error: {}: {}: unknown tag name: {}'
|
||||
.format(path, line_no + 1, key), file=sys.stderr)
|
||||
|
||||
def _parse_from_dump_file(self, path):
|
||||
"""Load information from ELF dump file."""
|
||||
with open(path, 'r') as f:
|
||||
self._parse_from_dump_lines(path, f)
|
||||
|
||||
def _parse_from_dump_buf(self, buf):
|
||||
"""Load information from ELF dump buffer."""
|
||||
self._parse_from_dump_lines('<str:0x{:x}>'.format(id(buf)),
|
||||
buf.splitlines())
|
||||
|
||||
@staticmethod
|
||||
def load(path):
|
||||
"""Create an ELF instance from the file path"""
|
||||
@@ -402,6 +463,20 @@ class ELF(object):
|
||||
elf._parse_from_buf(buf)
|
||||
return elf
|
||||
|
||||
@staticmethod
|
||||
def load_dump(path):
|
||||
"""Create an ELF instance from a dump file path"""
|
||||
elf = ELF()
|
||||
elf._parse_from_dump_file(path)
|
||||
return elf
|
||||
|
||||
@staticmethod
|
||||
def load_dumps(buf):
|
||||
"""Create an ELF instance from a dump file buffer"""
|
||||
elf = ELF()
|
||||
elf._parse_from_dump_buf(buf)
|
||||
return elf
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# NDK and Banned Libraries
|
||||
|
||||
Reference in New Issue
Block a user