diff options
| author | Logan Chien <loganchien@google.com> | 2019-01-03 17:48:34 +0800 |
|---|---|---|
| committer | Logan Chien <loganchien@google.com> | 2019-01-03 18:18:04 +0800 |
| commit | 64c28f7422950f5684e446722bcf188483505407 (patch) | |
| tree | fa0907a917cff9fbd1e41c097b277b4ae1229365 /vndk | |
| parent | d7867edc4f1cdb176ce2f142dee2bbaae83bc68f (diff) | |
| download | android_development-64c28f7422950f5684e446722bcf188483505407.tar.gz android_development-64c28f7422950f5684e446722bcf188483505407.tar.bz2 android_development-64c28f7422950f5684e446722bcf188483505407.zip | |
vndk-def: Separate methods with two empty lines
This commit adds several empty lines to the file so that all method
definitions in `vndk_definition_tool.py` are separated by two empty
lines.
Test: n/a
Change-Id: I5976dec4ba73a80a29693bfa92fcaf5ecceace9d
Diffstat (limited to 'vndk')
| -rw-r--r-- | vndk/tools/definition-tool/tests/compat.py | 10 | ||||
| -rwxr-xr-x | vndk/tools/definition-tool/tests/ndk_toolchain.py | 13 | ||||
| -rwxr-xr-x | vndk/tools/definition-tool/tests/run.py | 1 | ||||
| -rwxr-xr-x | vndk/tools/definition-tool/tests/test_elf.py | 15 | ||||
| -rwxr-xr-x | vndk/tools/definition-tool/tests/test_elf_link_data.py | 8 | ||||
| -rwxr-xr-x | vndk/tools/definition-tool/tests/test_elf_resolver.py | 2 | ||||
| -rwxr-xr-x | vndk/tools/definition-tool/tests/test_elfdump.py | 6 | ||||
| -rwxr-xr-x | vndk/tools/definition-tool/tests/test_generic_refs.py | 4 | ||||
| -rwxr-xr-x | vndk/tools/definition-tool/tests/test_module_info.py | 1 | ||||
| -rw-r--r-- | vndk/tools/definition-tool/tests/utils.py | 7 | ||||
| -rwxr-xr-x | vndk/tools/definition-tool/vndk_definition_tool.py | 164 |
11 files changed, 231 insertions, 0 deletions
diff --git a/vndk/tools/definition-tool/tests/compat.py b/vndk/tools/definition-tool/tests/compat.py index 9f418539d..7fcbc2e93 100644 --- a/vndk/tools/definition-tool/tests/compat.py +++ b/vndk/tools/definition-tool/tests/compat.py @@ -3,30 +3,37 @@ import os import sys + try: from tempfile import TemporaryDirectory except ImportError: import shutil import tempfile + class TemporaryDirectory(object): def __init__(self, suffix='', prefix='tmp', dir=None): self.name = tempfile.mkdtemp(suffix, prefix, dir) + def __del__(self): self.cleanup() + def __enter__(self): return self.name + def __exit__(self, exc, value, tb): self.cleanup() + def cleanup(self): if self.name: shutil.rmtree(self.name) self.name = None + if sys.version_info >= (3, 0): from os import makedirs else: @@ -35,6 +42,7 @@ else: return return os.makedirs(path) + if sys.version_info >= (3, 0): from io import StringIO else: @@ -45,6 +53,8 @@ try: from unittest.mock import patch except ImportError: import contextlib + + @contextlib.contextmanager def patch(target, mock): obj, attr = target.rsplit('.') diff --git a/vndk/tools/definition-tool/tests/ndk_toolchain.py b/vndk/tools/definition-tool/tests/ndk_toolchain.py index 8ad9144ce..485b1b85c 100755 --- a/vndk/tools/definition-tool/tests/ndk_toolchain.py +++ b/vndk/tools/definition-tool/tests/ndk_toolchain.py @@ -9,6 +9,7 @@ import re import subprocess import sys + def detect_ndk_dir(): ndk_dir = os.getenv('NDK') if not ndk_dir: @@ -28,6 +29,7 @@ error:''' return ndk_dir + def detect_api_level(ndk_dir): try: apis = [] @@ -42,6 +44,7 @@ def detect_api_level(ndk_dir): except IOError: raise ValueError('failed to find latest api') + def detect_host(): if sys.platform.startswith('linux'): return 'linux-x86_64' @@ -49,15 +52,19 @@ def detect_host(): return 'darwin-x86_64' raise NotImplementedError('unknown host platform') + def get_gcc_dir(ndk_dir, arch, host): return os.path.join(ndk_dir, 'toolchains', arch, 'prebuilt', host) + def get_clang_dir(ndk_dir, host): return os.path.join(ndk_dir, 'toolchains', 'llvm', 'prebuilt', host) + def get_platform_dir(ndk_dir, api, subdirs): return os.path.join(ndk_dir, 'platforms', api, *subdirs) + class Target(object): def __init__(self, name, triple, cflags, ldflags, gcc_toolchain_dir, clang_dir, ndk_include, ndk_lib): @@ -71,6 +78,7 @@ class Target(object): self.ndk_include = ndk_include self.ndk_lib = ndk_lib + def check_paths(self): def check_path(path): if os.path.exists(path): @@ -88,6 +96,7 @@ class Target(object): success &= check_path(self.ndk_lib) return success + def compile(self, obj_file, src_file, cflags): clang = os.path.join(self.clang_dir, 'bin', 'clang') @@ -100,6 +109,7 @@ class Target(object): cmd.extend(self.target_cflags) subprocess.check_call(cmd) + def link(self, out_file, obj_files, ldflags): if '-shared' in ldflags: crtbegin = os.path.join(self.ndk_lib, 'crtbegin_so.o') @@ -124,6 +134,7 @@ class Target(object): cmd.append('-Wl,-pie') subprocess.check_call(cmd) + def create_targets(ndk_dir=None, api=None, host=None): if ndk_dir is None: ndk_dir = detect_ndk_dir() @@ -180,6 +191,7 @@ def create_targets(ndk_dir=None, api=None, host=None): return targets + def main(): parser = argparse.ArgumentParser( description='Dry-run NDK toolchain detection') @@ -198,5 +210,6 @@ def main(): print('succeed') + if __name__ == '__main__': main() diff --git a/vndk/tools/definition-tool/tests/run.py b/vndk/tools/definition-tool/tests/run.py index 2d2352bf5..2837d5cef 100755 --- a/vndk/tools/definition-tool/tests/run.py +++ b/vndk/tools/definition-tool/tests/run.py @@ -4,6 +4,7 @@ import argparse import os import unittest + def main(): parser = argparse.ArgumentParser() parser.add_argument('--verbose', '-v', action='store_true') diff --git a/vndk/tools/definition-tool/tests/test_elf.py b/vndk/tools/definition-tool/tests/test_elf.py index a45fb5816..160911d0e 100755 --- a/vndk/tools/definition-tool/tests/test_elf.py +++ b/vndk/tools/definition-tool/tests/test_elf.py @@ -12,6 +12,7 @@ import unittest from compat import StringIO from vndk_definition_tool import Elf_Sym, ELF + class ElfSymTest(unittest.TestCase): def setUp(self): self.sym_local = Elf_Sym(0, 0, 4, 0, 0, 1) @@ -19,21 +20,25 @@ class ElfSymTest(unittest.TestCase): 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) @@ -44,12 +49,14 @@ class ELFTest(unittest.TestCase): 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')) @@ -58,6 +65,7 @@ class ELFTest(unittest.TestCase): 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))) @@ -67,6 +75,7 @@ class ELFTest(unittest.TestCase): 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) @@ -80,6 +89,7 @@ class ELFTest(unittest.TestCase): 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', @@ -87,6 +97,7 @@ class ELFTest(unittest.TestCase): 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) @@ -95,6 +106,7 @@ class ELFTest(unittest.TestCase): 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) @@ -104,6 +116,7 @@ class ELFTest(unittest.TestCase): 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'}) @@ -130,6 +143,7 @@ class ELFTest(unittest.TestCase): 'IMP_SYMBOL\te\n', actual_output) + def test_parse_dump_file(self): data = ('EI_CLASS\t64\n' 'EI_DATA\t\tLittle-Endian\n' @@ -190,6 +204,7 @@ class ELFJniLibTest(unittest.TestCase): 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()) diff --git a/vndk/tools/definition-tool/tests/test_elf_link_data.py b/vndk/tools/definition-tool/tests/test_elf_link_data.py index e850307da..98ae69243 100755 --- a/vndk/tools/definition-tool/tests/test_elf_link_data.py +++ b/vndk/tools/definition-tool/tests/test_elf_link_data.py @@ -25,6 +25,7 @@ class ELFLinkDataTest(unittest.TestCase): self.z.add_needed_dep(self.w) self.z.add_dlopen_dep(self.w) + def test_add_dep_and_accessors(self): self.assertIn(self.y, self.x.deps_needed_all) self.assertIn(self.x, self.y.users_needed_all) @@ -36,6 +37,7 @@ class ELFLinkDataTest(unittest.TestCase): self.assertNotIn(self.z, self.x.deps_needed_all) self.assertNotIn(self.x, self.z.users_needed_all) + def test_remove_dep(self): self.assertIn(self.y, self.x.deps_needed_all) self.assertIn(self.x, self.y.users_needed_all) @@ -51,6 +53,7 @@ class ELFLinkDataTest(unittest.TestCase): self.assertNotIn(self.y, self.x.deps_needed) self.assertNotIn(self.x, self.y.users_needed) + def test_num_deps(self): self.assertEqual(2, self.x.num_deps) self.assertEqual(0, self.y.num_deps) @@ -60,6 +63,7 @@ class ELFLinkDataTest(unittest.TestCase): # NEEDED and DLOPEN are counted twice. self.assertEqual(2, self.z.num_deps) + def test_num_users(self): self.assertEqual(0, self.x.num_users) self.assertEqual(1, self.y.num_users) @@ -69,22 +73,26 @@ class ELFLinkDataTest(unittest.TestCase): # NEEDED and DLOPEN are counted twice. self.assertEqual(2, self.w.num_users) + def test_has_dep(self): self.assertTrue(self.x.has_dep(self.y)) self.assertTrue(self.x.has_dep(self.z)) self.assertFalse(self.x.has_dep(self.x)) self.assertFalse(self.x.has_dep(self.w)) + def test_has_user(self): self.assertTrue(self.y.has_user(self.x)) self.assertTrue(self.z.has_user(self.x)) self.assertFalse(self.x.has_user(self.x)) self.assertFalse(self.w.has_user(self.x)) + def test_is_system_lib(self): self.assertTrue(self.x.is_system_lib()) self.assertFalse(self.v.is_system_lib()) + def test_get_dep_linked_symbols(self): self.x.linked_symbols['c'] = self.y self.x.linked_symbols['b'] = self.y diff --git a/vndk/tools/definition-tool/tests/test_elf_resolver.py b/vndk/tools/definition-tool/tests/test_elf_resolver.py index 29973e302..30bab9f7c 100755 --- a/vndk/tools/definition-tool/tests/test_elf_resolver.py +++ b/vndk/tools/definition-tool/tests/test_elf_resolver.py @@ -10,6 +10,7 @@ import unittest from vndk_definition_tool import ELFResolver + class ELFResolverTest(unittest.TestCase): def setUp(self): lib_set = { @@ -24,6 +25,7 @@ class ELFResolverTest(unittest.TestCase): self.resolver = ELFResolver(lib_set, ['/system/lib', '/vendor/lib']) + def test_get_candidates(self): r = self.resolver diff --git a/vndk/tools/definition-tool/tests/test_elfdump.py b/vndk/tools/definition-tool/tests/test_elfdump.py index 2c0b2305d..c738fd8da 100755 --- a/vndk/tools/definition-tool/tests/test_elfdump.py +++ b/vndk/tools/definition-tool/tests/test_elfdump.py @@ -41,11 +41,13 @@ class ELFDumpTest(unittest.TestCase): cls._build_fixtures(cls.target_name) + @classmethod def tearDownClass(cls): if not test_dir_base: cls.tmp_dir.cleanup() + @classmethod def _build_fixtures(cls, target_name): target = cls.targets[target_name] @@ -97,6 +99,7 @@ class ELFDumpTest(unittest.TestCase): ['-shared', '-lc', '-Wl,-rpath,/system/lib:/vendor/lib', '-Wl,--enable-new-dtags']) + def _remove_size_lines(self, lines): """Remove file size information because they may vary.""" prefixes = ( @@ -109,6 +112,7 @@ class ELFDumpTest(unittest.TestCase): patt = re.compile('|'.join('(?:' + re.escape(x) +')' for x in prefixes)) return [line for line in lines if not patt.match(line)] + def _assert_equal_to_file(self, expected_file_name, actual): actual = actual.splitlines(True) expected_file_path = os.path.join(self.expected_dir, expected_file_name) @@ -117,10 +121,12 @@ class ELFDumpTest(unittest.TestCase): self.assertEqual(self._remove_size_lines(expected), self._remove_size_lines(actual)) + def _test_main_out(self): out_file = os.path.join(self.test_dir, 'main.out') self._assert_equal_to_file('main.out.txt', run_elf_dump(out_file)) + def _test_libtest(self, expected_file_name, lib_name): lib_file = os.path.join(self.test_dir, lib_name) self._assert_equal_to_file(expected_file_name, run_elf_dump(lib_file)) diff --git a/vndk/tools/definition-tool/tests/test_generic_refs.py b/vndk/tools/definition-tool/tests/test_generic_refs.py index c887d19d6..349debca5 100755 --- a/vndk/tools/definition-tool/tests/test_generic_refs.py +++ b/vndk/tools/definition-tool/tests/test_generic_refs.py @@ -39,6 +39,7 @@ class GenericRefsTest(unittest.TestCase): self.ref.add('/system/lib64/libm.so', MockELF({'cos', 'sin', 'tan'})) + def test_create_from_sym_dir(self): input_dir = os.path.join(SCRIPT_DIR, 'testdata', 'test_generic_refs') @@ -60,6 +61,7 @@ class GenericRefsTest(unittest.TestCase): self.assertEqual({'cos', 'sin', 'tan'}, g.refs['/system/lib64/libm.so'].exported_symbols) + def test_classify_lib(self): libc_sub = MockLib('/system/lib/libc.so', {'fclose', 'fopen', 'fread'}) libc_sup = MockLib('/system/lib/libc.so', @@ -75,6 +77,7 @@ class GenericRefsTest(unittest.TestCase): self.ref.classify_lib(libc_eq)) self.assertEqual(GenericRefs.NEW_LIB, self.ref.classify_lib(libfoo)) + def test_is_equivalent_lib(self): libc_sub = MockLib('/system/lib/libc.so', {'fclose', 'fopen', 'fread'}) libc_sup = MockLib('/system/lib/libc.so', @@ -87,6 +90,7 @@ class GenericRefsTest(unittest.TestCase): self.assertTrue(self.ref.is_equivalent_lib(libc_eq)) + def test_has_same_name_lib(self): self.assertTrue(self.ref.has_same_name_lib( MockLib('/vendor/lib/libc.so', {}))) diff --git a/vndk/tools/definition-tool/tests/test_module_info.py b/vndk/tools/definition-tool/tests/test_module_info.py index 2da17b40d..f36edb09d 100755 --- a/vndk/tools/definition-tool/tests/test_module_info.py +++ b/vndk/tools/definition-tool/tests/test_module_info.py @@ -18,6 +18,7 @@ class ModuleInfoTest(unittest.TestCase): m = ModuleInfo.load_from_path_or_default(None) self.assertEqual([], m.get_module_path('/system/lib64/libA.so')) + def test_get_module_path(self): json_path = os.path.join(SCRIPT_DIR, 'testdata', 'test_module_info', 'module-info.json') diff --git a/vndk/tools/definition-tool/tests/utils.py b/vndk/tools/definition-tool/tests/utils.py index 6c61a3467..c241dc577 100644 --- a/vndk/tools/definition-tool/tests/utils.py +++ b/vndk/tools/definition-tool/tests/utils.py @@ -16,14 +16,17 @@ class GraphBuilder(object): PT_VENDOR: 'vendor', } + _LIB_DIRS = { ELF.ELFCLASS32: 'lib', ELF.ELFCLASS64: 'lib64', } + def __init__(self): self.graph = ELFLinker() + def add_lib(self, partition, klass, name, dt_needed=[], exported_symbols=set(), imported_symbols=set(), extra_dir=None): @@ -44,18 +47,21 @@ class GraphBuilder(object): setattr(self, name + '_' + elf.elf_class_name, lib) return lib + def add_lib32(self, partition, name, dt_needed=[], exported_symbols=set(), imported_symbols=set(), extra_dir=None): return self.add_lib(partition, ELF.ELFCLASS32, name, dt_needed, exported_symbols, imported_symbols, extra_dir) + def add_lib64(self, partition, name, dt_needed=[], exported_symbols=set(), imported_symbols=set(), extra_dir=None): return self.add_lib(partition, ELF.ELFCLASS64, name, dt_needed, exported_symbols, imported_symbols, extra_dir) + def add_multilib(self, partition, name, dt_needed=[], exported_symbols=set(), imported_symbols=set(), extra_dir=None): @@ -67,6 +73,7 @@ class GraphBuilder(object): exported_symbols, imported_symbols, extra_dir) ) + def resolve(self, vndk_lib_dirs=None, ro_vndk_version=None): if vndk_lib_dirs is not None: self.graph.vndk_lib_dirs = vndk_lib_dirs diff --git a/vndk/tools/definition-tool/vndk_definition_tool.py b/vndk/tools/definition-tool/vndk_definition_tool.py index 4e29986de..996e5b20d 100755 --- a/vndk/tools/definition-tool/vndk_definition_tool.py +++ b/vndk/tools/definition-tool/vndk_definition_tool.py @@ -314,22 +314,27 @@ class Elf_Sym(collections.namedtuple( SHN_UNDEF = 0 + @property def st_bind(self): return self.st_info >> 4 + @property def is_local(self): return self.st_bind == Elf_Sym.STB_LOCAL + @property def is_global(self): return self.st_bind == Elf_Sym.STB_GLOBAL + @property def is_weak(self): return self.st_bind == Elf_Sym.STB_WEAK + @property def is_undef(self): return self.st_shndx == Elf_Sym.SHN_UNDEF @@ -381,6 +386,7 @@ class ELF(object): EM_X86_64 = 62 EM_AARCH64 = 183 + def _create_elf_machines(d): elf_machine_ids = {} for key, value in d.items(): @@ -400,14 +406,17 @@ class ELF(object): 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_MACHINES, name) @@ -440,41 +449,51 @@ class ELF(object): self.rw_seg_file_size = rw_seg_file_size self.rw_seg_mem_size = rw_seg_mem_size + def __repr__(self): args = (a + '=' + repr(getattr(self, a)) for a in self.__slots__) return 'ELF(' + ', '.join(args) + ')' + def __eq__(self, rhs): return all(getattr(self, a) == getattr(rhs, a) for a in self.__slots__) + @property def elf_class_name(self): return self._ELF_CLASS_NAMES.get(self.ei_class, 'None') + @property def elf_data_name(self): return self._ELF_DATA_NAMES.get(self.ei_data, 'None') + @property def elf_machine_name(self): return self.ELF_MACHINES.get(self.e_machine, str(self.e_machine)) + @property def is_32bit(self): return self.ei_class == ELF.ELFCLASS32 + @property def is_64bit(self): return self.ei_class == ELF.ELFCLASS64 + @property def sorted_exported_symbols(self): return sorted(list(self.exported_symbols)) + @property def sorted_imported_symbols(self): return sorted(list(self.imported_symbols)) + def dump(self, file=None): """Print parsed ELF information to the file""" file = file if file is not None else sys.stdout @@ -498,6 +517,7 @@ class ELF(object): for symbol in self.sorted_imported_symbols: print('IMP_SYMBOL\t' + symbol, file=file) + # Extract zero-terminated buffer slice. def _extract_zero_terminated_buf_slice(self, buf, offset): """Extract a zero-terminated buffer slice from the given offset""" @@ -506,6 +526,7 @@ class ELF(object): return buf[offset:] return buf[offset:end] + # Extract c-style interned string from the buffer. if sys.version_info >= (3, 0): def _extract_zero_terminated_str(self, buf, offset): @@ -517,6 +538,7 @@ class ELF(object): """Extract a c-style string from the given buffer and offset""" return intern(self._extract_zero_terminated_buf_slice(buf, offset)) + def _parse_from_buf_internal(self, buf): """Parse ELF image resides in the buffer""" @@ -695,6 +717,7 @@ class ELF(object): elif not ent.is_local: exp_symbols.add(symbol_name) + def _parse_from_buf(self, buf): """Parse ELF image resides in the buffer""" try: @@ -702,6 +725,7 @@ class ELF(object): except IndexError: raise ELFError('bad offset') + def _parse_from_file(self, path): """Parse ELF image from the file path""" with open(path, 'rb') as f: @@ -711,6 +735,7 @@ 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): @@ -752,16 +777,19 @@ class ELF(object): 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""" @@ -769,6 +797,7 @@ class ELF(object): elf._parse_from_file(path) return elf + @staticmethod def loads(buf): """Create an ELF instance from the buffer""" @@ -776,6 +805,7 @@ class ELF(object): elf._parse_from_buf(buf) return elf + @staticmethod def load_dump(path): """Create an ELF instance from a dump file path""" @@ -783,6 +813,7 @@ class ELF(object): elf._parse_from_dump_file(path) return elf + @staticmethod def load_dumps(buf): """Create an ELF instance from a dump file buffer""" @@ -790,6 +821,7 @@ class ELF(object): elf._parse_from_dump_buf(buf) return elf + def is_jni_lib(self): """Test whether the ELF file looks like a JNI library.""" for name in ['libnativehelper.so', 'libandroid_runtime.so']: @@ -1077,6 +1109,7 @@ class TaggedDict(object): _define_tag_constants(locals()) del _define_tag_constants + _TAG_ALIASES = { 'hl_ndk': 'fwk_only', # Treat HL-NDK as FWK-ONLY. 'sp_ndk': 'll_ndk', @@ -1094,6 +1127,7 @@ class TaggedDict(object): 'vndk_sp_private': 'vndk_sp_indirect_private', } + @classmethod def _normalize_tag(cls, tag): tag = tag.lower().replace('-', '_') @@ -1102,6 +1136,7 @@ class TaggedDict(object): raise ValueError('unknown lib tag ' + tag) return tag + _LL_NDK_VIS = {'ll_ndk', 'll_ndk_indirect'} _VNDK_SP_VIS = {'ll_ndk', 'vndk_sp', 'vndk_sp_indirect', 'vndk_sp_indirect_private', 'fwk_only_rs'} @@ -1134,10 +1169,12 @@ class TaggedDict(object): del _LL_NDK_VIS, _VNDK_SP_VIS, _FWK_ONLY_VIS, _SP_HAL_VIS + @classmethod def is_tag_visible(cls, from_tag, to_tag): return to_tag in cls._TAG_VISIBILITY[from_tag] + def __init__(self, vndk_lib_dirs=None): self._path_tag = dict() for tag in self.TAGS: @@ -1150,14 +1187,17 @@ class TaggedDict(object): self._vndk_suffixes = [VNDKLibDir.create_vndk_dir_suffix(version) for version in vndk_lib_dirs] + def add(self, tag, lib): lib_set = getattr(self, tag) lib_set.add(lib) self._path_tag[lib] = tag + def add_regex(self, tag, pattern): self._regex_patterns.append((re.compile(pattern), tag)) + def get_path_tag(self, lib): try: return self._path_tag[lib] @@ -1170,36 +1210,45 @@ class TaggedDict(object): return self.get_path_tag_default(lib) + def get_path_tag_default(self, lib): raise NotImplementedError() + def get_path_tag_bit(self, lib): return self.TAGS[self.get_path_tag(lib)] + def is_path_visible(self, from_lib, to_lib): return self.is_tag_visible(self.get_path_tag(from_lib), self.get_path_tag(to_lib)) + @staticmethod def is_ll_ndk(tag_bit): return bool(tag_bit & TaggedDict.LL_NDK) + @staticmethod def is_vndk_sp(tag_bit): return bool(tag_bit & TaggedDict.VNDK_SP) + @staticmethod def is_vndk_sp_indirect(tag_bit): return bool(tag_bit & TaggedDict.VNDK_SP_INDIRECT) + @staticmethod def is_vndk_sp_indirect_private(tag_bit): return bool(tag_bit & TaggedDict.VNDK_SP_INDIRECT_PRIVATE) + @staticmethod def is_fwk_only_rs(tag_bit): return bool(tag_bit & TaggedDict.FWK_ONLY_RS) + @staticmethod def is_sp_hal(tag_bit): return bool(tag_bit & TaggedDict.SP_HAL) @@ -1227,17 +1276,20 @@ class TaggedPathDict(TaggedDict): for row in reader: self.add(self._normalize_tag(row[tag_col]), row[path_col]) + @staticmethod def create_from_csv(fp, vndk_lib_dirs=None): d = TaggedPathDict(vndk_lib_dirs) d.load_from_csv(fp) return d + @staticmethod def create_from_csv_path(path, vndk_lib_dirs=None): with open(path, 'r') as fp: return TaggedPathDict.create_from_csv(fp, vndk_lib_dirs) + def _enumerate_paths_with_lib(self, pattern): if '${LIB}' in pattern: yield pattern.replace('${LIB}', 'lib') @@ -1245,6 +1297,7 @@ class TaggedPathDict(TaggedDict): else: yield pattern + def _enumerate_paths(self, pattern): if '${VNDK_VER}' not in pattern: for path in self._enumerate_paths_with_lib(pattern): @@ -1255,6 +1308,7 @@ class TaggedPathDict(TaggedDict): for path in self._enumerate_paths_with_lib(pattern_with_suffix): yield path + def add(self, tag, path): if path.startswith('[regex]'): super(TaggedPathDict, self).add_regex(tag, path[7:]) @@ -1262,6 +1316,7 @@ class TaggedPathDict(TaggedDict): for path in self._enumerate_paths(path): super(TaggedPathDict, self).add(tag, path) + def get_path_tag_default(self, path): return 'vnd_only' if path.startswith('/vendor') else 'fwk_only' @@ -1272,11 +1327,13 @@ class TaggedLibDict(object): for tag in TaggedDict.TAGS: setattr(self, tag, set()) + def add(self, tag, lib): lib_set = getattr(self, tag) lib_set.add(lib) self._path_tag[lib] = tag + @staticmethod def create_from_graph(graph, tagged_paths, generic_refs=None): d = TaggedLibDict() @@ -1294,12 +1351,14 @@ class TaggedLibDict(object): d.add('vnd_only', lib) return d + def get_path_tag(self, lib): try: return self._path_tag[lib] except KeyError: return self.get_path_tag_default(lib) + def get_path_tag_default(self, lib): return 'vnd_only' if lib.path.startswith('/vendor') else 'fwk_only' @@ -1672,6 +1731,7 @@ class ELFResolver(object): self.lib_set = lib_set self.default_search_path = default_search_path + def get_candidates(self, requester, name, dt_rpath=None, dt_runpath=None): # Search app-specific search paths. if _APP_DIR_PATTERNS.match(requester): @@ -1687,6 +1747,7 @@ class ELFResolver(object): for d in self.default_search_path: yield os.path.join(d, name) + def resolve(self, requester, name, dt_rpath=None, dt_runpath=None): for path in self.get_candidates(requester, name, dt_rpath, dt_runpath): try: @@ -1715,54 +1776,65 @@ class ELFLinkData(object): self.unresolved_dt_needed = [] self.linked_symbols = dict() + @property def is_ll_ndk(self): return TaggedDict.is_ll_ndk(self._tag_bit) + @property def is_vndk_sp(self): return TaggedDict.is_vndk_sp(self._tag_bit) + @property def is_vndk_sp_indirect(self): return TaggedDict.is_vndk_sp_indirect(self._tag_bit) + @property def is_vndk_sp_indirect_private(self): return TaggedDict.is_vndk_sp_indirect_private(self._tag_bit) + @property def is_fwk_only_rs(self): return TaggedDict.is_fwk_only_rs(self._tag_bit) + @property def is_sp_hal(self): return TaggedDict.is_sp_hal(self._tag_bit) + def add_needed_dep(self, dst): assert dst not in self.deps_needed_hidden assert self not in dst.users_needed_hidden self.deps_needed.add(dst) dst.users_needed.add(self) + def add_dlopen_dep(self, dst): assert dst not in self.deps_dlopen_hidden assert self not in dst.users_dlopen_hidden self.deps_dlopen.add(dst) dst.users_dlopen.add(self) + def hide_needed_dep(self, dst): self.deps_needed.remove(dst) dst.users_needed.remove(self) self.deps_needed_hidden.add(dst) dst.users_needed_hidden.add(self) + def hide_dlopen_dep(self, dst): self.deps_dlopen.remove(dst) dst.users_dlopen.remove(self) self.deps_dlopen_hidden.add(dst) dst.users_dlopen_hidden.add(self) + @property def num_deps(self): """Get the number of dependencies. If a library is linked by both @@ -1770,23 +1842,28 @@ class ELFLinkData(object): return (len(self.deps_needed) + len(self.deps_needed_hidden) + len(self.deps_dlopen) + len(self.deps_dlopen_hidden)) + @property def deps_all(self): return itertools.chain(self.deps_needed, self.deps_needed_hidden, self.deps_dlopen, self.deps_dlopen_hidden) + @property def deps_good(self): return itertools.chain(self.deps_needed, self.deps_dlopen) + @property def deps_needed_all(self): return itertools.chain(self.deps_needed, self.deps_needed_hidden) + @property def deps_dlopen_all(self): return itertools.chain(self.deps_dlopen, self.deps_dlopen_hidden) + @property def num_users(self): """Get the number of users. If a library is linked by both NEEDED and @@ -1794,34 +1871,42 @@ class ELFLinkData(object): return (len(self.users_needed) + len(self.users_needed_hidden) + len(self.users_dlopen) + len(self.users_dlopen_hidden)) + @property def users_all(self): return itertools.chain(self.users_needed, self.users_needed_hidden, self.users_dlopen, self.users_dlopen_hidden) + @property def users_good(self): return itertools.chain(self.users_needed, self.users_dlopen) + @property def users_needed_all(self): return itertools.chain(self.users_needed, self.users_needed_hidden) + @property def users_dlopen_all(self): return itertools.chain(self.users_dlopen, self.users_dlopen_hidden) + def has_dep(self, dst): return (dst in self.deps_needed or dst in self.deps_needed_hidden or dst in self.deps_dlopen or dst in self.deps_dlopen_hidden) + def has_user(self, dst): return (dst in self.users_needed or dst in self.users_needed_hidden or dst in self.users_dlopen or dst in self.users_dlopen_hidden) + def is_system_lib(self): return self.partition == PT_SYSTEM + def get_dep_linked_symbols(self, dep): symbols = set() for symbol, exp_lib in self.linked_symbols.items(): @@ -1829,6 +1914,7 @@ class ELFLinkData(object): symbols.add(symbol) return sorted(symbols) + def __lt__(self, rhs): return self.path < rhs.path @@ -1838,6 +1924,7 @@ def sorted_lib_path_list(libs): libs.sort() return libs + _VNDK_RESULT_FIELD_NAMES = ( 'll_ndk', 'll_ndk_indirect', 'vndk_sp', 'vndk_sp_unused', 'vndk_sp_indirect', @@ -1848,6 +1935,7 @@ _VNDK_RESULT_FIELD_NAMES = ( VNDKResult = defaultnamedtuple('VNDKResult', _VNDK_RESULT_FIELD_NAMES, set()) + _SIMPLE_VNDK_RESULT_FIELD_NAMES = ( 'vndk_sp', 'vndk_sp_ext', 'extra_vendor_libs') @@ -1859,12 +1947,15 @@ class ELFLibDict(defaultnamedtuple('ELFLibDict', ('lib32', 'lib64'), {})): def get_lib_dict(self, elf_class): return self[elf_class - 1] + def add(self, path, lib): self.get_lib_dict(lib.elf.ei_class)[path] = lib + def remove(self, lib): del self.get_lib_dict(lib.elf.ei_class)[lib.path] + def get(self, path, default=None): for lib_set in self: res = lib_set.get(path, None) @@ -1872,12 +1963,15 @@ class ELFLibDict(defaultnamedtuple('ELFLibDict', ('lib32', 'lib64'), {})): return res return default + def keys(self): return itertools.chain(self.lib32.keys(), self.lib64.keys()) + def values(self): return itertools.chain(self.lib32.values(), self.lib64.values()) + def items(self): return itertools.chain(self.lib32.items(), self.lib64.items()) @@ -1903,18 +1997,22 @@ class ELFLinker(object): self.ro_vndk_version = ro_vndk_version + def _add_lib_to_lookup_dict(self, lib): self.lib_pt[lib.partition].add(lib.path, lib) + def _remove_lib_from_lookup_dict(self, lib): self.lib_pt[lib.partition].remove(lib) + def add_lib(self, partition, path, elf): lib = ELFLinkData(partition, path, elf, self.tagged_paths.get_path_tag_bit(path)) self._add_lib_to_lookup_dict(lib) return lib + def add_dlopen_dep(self, src_path, dst_path): num_matches = 0 for elf_class in (ELF.ELFCLASS32, ELF.ELFCLASS64): @@ -1927,6 +2025,7 @@ class ELFLinker(object): raise ValueError('Failed to add dlopen dependency from {} to {}' .format(src_path, dst_path)) + def _get_libs_in_elf_class(self, elf_class, path): result = set() if '${LIB}' in path: @@ -1947,6 +2046,7 @@ class ELFLinker(object): result.add(lib) return result + def get_lib(self, path): for lib_set in self.lib_pt: lib = lib_set.get(path) @@ -1954,6 +2054,7 @@ class ELFLinker(object): return lib return None + def get_libs(self, paths, report_error=None): result = set() for path in paths: @@ -1966,23 +2067,27 @@ class ELFLinker(object): result.add(lib) return result + def all_libs(self): for lib_set in self.lib_pt: for lib in lib_set.values(): yield lib + def _compute_lib_dict(self, elf_class): res = dict() for lib_pt in self.lib_pt: res.update(lib_pt.get_lib_dict(elf_class)) return res + @staticmethod def _compile_path_matcher(root, subdirs): dirs = [os.path.normpath(os.path.join(root, i)) for i in subdirs] patts = ['(?:' + re.escape(i) + os.sep + ')' for i in dirs] return re.compile('|'.join(patts)) + def add_executables_in_dir(self, partition_name, partition, root, alter_partition, alter_subdirs, ignored_subdirs, scan_elf_files, unzip_files): @@ -2011,6 +2116,7 @@ class ELFLinker(object): else: self.add_lib(partition, short_path, elf) + def add_dlopen_deps(self, path): patt = re.compile('([^:]*):\\s*(.*)') with open(path, 'r') as dlopen_dep_file: @@ -2024,6 +2130,7 @@ class ELFLinker(object): print('error:{}:{}: {}.'.format(path, line_no, e), file=sys.stderr) + def _find_exported_symbol(self, symbol, libs): """Find the shared library with the exported symbol.""" for lib in libs: @@ -2031,6 +2138,7 @@ class ELFLinker(object): return lib return None + def _resolve_lib_imported_symbols(self, lib, imported_libs, generic_refs): """Resolve the imported symbols in a library.""" for symbol in lib.elf.imported_symbols: @@ -2044,6 +2152,7 @@ class ELFLinker(object): if not ref_lib or not symbol in ref_lib.exported_symbols: lib.imported_ext_symbols[imported_lib].add(symbol) + def _resolve_lib_dt_needed(self, lib, resolver): imported_libs = [] for dt_needed in lib.elf.dt_needed: @@ -2061,6 +2170,7 @@ class ELFLinker(object): imported_libs.append(dep) return imported_libs + def _resolve_lib_deps(self, lib, resolver, generic_refs): # Resolve DT_NEEDED entries. imported_libs = self._resolve_lib_dt_needed(lib, resolver) @@ -2076,6 +2186,7 @@ class ELFLinker(object): # Resolve imported symbols. self._resolve_lib_imported_symbols(lib, imported_libs, generic_refs) + def _resolve_lib_set_deps(self, lib_set, resolver, generic_refs): for lib in lib_set: self._resolve_lib_deps(lib, resolver, generic_refs) @@ -2088,6 +2199,7 @@ class ELFLinker(object): '/vendor/' + lib_dir, ] + def _get_vendor_search_paths(self, lib_dir, vndk_sp_dirs, vndk_dirs): vendor_lib_dirs = [ '/vendor/' + lib_dir + '/hw', @@ -2212,6 +2324,7 @@ class ELFLinker(object): return SPLibResult(sp_hal, sp_hal_dep, vndk_sp_hal, ll_ndk, ll_ndk_indirect, vndk_sp_both) + def normalize_partition_tags(self, sp_hals, generic_refs): def is_system_lib_or_sp_hal(lib): return lib.is_system_lib() or lib in sp_hals @@ -2237,6 +2350,7 @@ class ELFLinker(object): file=sys.stderr) lib.hide_dlopen_dep(dep) + @staticmethod def _parse_action_on_ineligible_lib(arg): follow = False @@ -2252,6 +2366,7 @@ class ELFLinker(object): raise ValueError('unknown action \"{}\"'.format(flag)) return (follow, warn) + def compute_degenerated_vndk(self, generic_refs, tagged_paths=None, action_ineligible_vndk_sp='warn', action_ineligible_vndk='warn'): @@ -2529,6 +2644,7 @@ class ELFLinker(object): vndk_sp_indirect_ext=vndk_sp_indirect_ext, extra_vendor_libs=extra_vendor_libs) + @staticmethod def _compute_closure(root_set, is_excluded, get_successors): closure = set(root_set) @@ -2543,6 +2659,7 @@ class ELFLinker(object): stack.append(succ) return closure + @classmethod def compute_deps_closure(cls, root_set, is_excluded, ignore_hidden_deps=False): @@ -2550,6 +2667,7 @@ class ELFLinker(object): (lambda x: x.deps_all) return cls._compute_closure(root_set, is_excluded, get_successors) + @classmethod def compute_users_closure(cls, root_set, is_excluded, ignore_hidden_users=False): @@ -2557,6 +2675,7 @@ class ELFLinker(object): (lambda x: x.users_all) return cls._compute_closure(root_set, is_excluded, get_successors) + @staticmethod def _create_internal(scan_elf_files, system_dirs, system_dirs_as_vendor, system_dirs_ignored, vendor_dirs, @@ -2591,6 +2710,7 @@ class ELFLinker(object): return graph + @staticmethod def create(system_dirs=None, system_dirs_as_vendor=None, system_dirs_ignored=None, vendor_dirs=None, @@ -2614,14 +2734,17 @@ class GenericRefs(object): EXPORT_SUPER_SET = 2 MODIFIED = 3 + def __init__(self): self.refs = dict() self._lib_names = set() + def add(self, path, elf): self.refs[path] = elf self._lib_names.add(os.path.basename(path)) + def _load_from_sym_dir(self, root): root = os.path.abspath(root) prefix_len = len(root) + 1 @@ -2633,24 +2756,28 @@ class GenericRefs(object): lib_path = '/' + path[prefix_len:-4] self.add(lib_path, ELF.load_dump(path)) + @staticmethod def create_from_sym_dir(root): result = GenericRefs() result._load_from_sym_dir(root) return result + def _load_from_image_dir(self, root, prefix): root = os.path.abspath(root) root_len = len(root) + 1 for path, elf in scan_elf_files(root): self.add(os.path.join(prefix, path[root_len:]), elf) + @staticmethod def create_from_image_dir(root, prefix): result = GenericRefs() result._load_from_image_dir(root, prefix) return result + def classify_lib(self, lib): ref_lib = self.refs.get(lib.path) if not ref_lib: @@ -2662,9 +2789,11 @@ class GenericRefs(object): return GenericRefs.EXPORT_SUPER_SET return GenericRefs.MODIFIED + def is_equivalent_lib(self, lib): return self.classify_lib(lib) == GenericRefs.EXPORT_EQUAL + def has_same_name_lib(self, lib): return os.path.basename(lib.path) in self._lib_names @@ -2802,13 +2931,16 @@ class ModuleInfo(object): self._mods = {installed_path: sorted(src_dirs) for installed_path, src_dirs in mods.items()} + def get_module_path(self, installed_path): return self._mods.get(installed_path, []) + @staticmethod def load(f): return ModuleInfo(json.load(f)) + @staticmethod def load_from_path_or_default(path): if not path: @@ -2838,9 +2970,11 @@ class ELFDumpCommand(Command): super(ELFDumpCommand, self).__init__( 'elfdump', help='Dump ELF .dynamic section') + def add_argparser_options(self, parser): parser.add_argument('path', help='path to an ELF file') + def main(self, args): try: ELF.load(args.path).dump() @@ -2856,12 +2990,14 @@ class CreateGenericRefCommand(Command): super(CreateGenericRefCommand, self).__init__( 'create-generic-ref', help='Create generic references') + def add_argparser_options(self, parser): parser.add_argument('dir') parser.add_argument('-o', '--output', required=True, help='output directory') + def main(self, args): root = os.path.abspath(args.dir) print(root) @@ -2926,6 +3062,7 @@ class ELFGraphCommand(Command): '--tag-file', required=is_tag_file_required, help='lib tag file') + def get_generic_refs_from_args(self, args): if args.load_generic_refs: return GenericRefs.create_from_sym_dir(args.load_generic_refs) @@ -2934,6 +3071,7 @@ class ELFGraphCommand(Command): args.aosp_system, '/system') return None + def _check_arg_dir_exists(self, arg_name, dirs): for path in dirs: if not os.path.exists(path): @@ -2945,10 +3083,12 @@ class ELFGraphCommand(Command): .format(path, arg_name), file=sys.stderr) sys.exit(1) + def check_dirs_from_args(self, args): self._check_arg_dir_exists('--system', args.system) self._check_arg_dir_exists('--vendor', args.vendor) + def create_from_args(self, args): self.check_dirs_from_args(args) @@ -2992,6 +3132,7 @@ class VNDKCommandBase(ELFGraphCommand): help='action when a vendor lib/exe uses fwk-only libs ' '(option: follow,warn,ignore)') + def create_from_args(self, args): """Create all essential data structures for VNDK computation.""" @@ -3012,6 +3153,7 @@ class VNDKCommand(VNDKCommandBase): super(VNDKCommand, self).__init__( 'vndk', help='Compute VNDK libraries set') + def add_argparser_options(self, parser): super(VNDKCommand, self).add_argparser_options(parser) @@ -3031,6 +3173,7 @@ class VNDKCommand(VNDKCommandBase): '--file-size-output', help='output file for calculated file sizes') + def _warn_incorrect_partition_lib_set(self, lib_set, partition, error_msg): for lib in lib_set.values(): if not lib.num_users: @@ -3038,6 +3181,7 @@ class VNDKCommand(VNDKCommandBase): if all((user.partition != partition for user in lib.users_all)): print(error_msg.format(lib.path), file=sys.stderr) + def _warn_incorrect_partition(self, graph): self._warn_incorrect_partition_lib_set( graph.lib_pt[PT_VENDOR], PT_VENDOR, @@ -3049,6 +3193,7 @@ class VNDKCommand(VNDKCommandBase): 'warning: {}: This is a framework library with vendor-only ' 'usages.') + @staticmethod def _extract_simple_vndk_result(vndk_result): field_name_tags = [ @@ -3069,6 +3214,7 @@ class VNDKCommand(VNDKCommandBase): getattr(results, tag).update(getattr(vndk_result, field_name)) return results + def _print_tags(self, vndk_lib, full, file=sys.stdout): if full: result_tags = _VNDK_RESULT_FIELD_NAMES @@ -3084,6 +3230,7 @@ class VNDKCommand(VNDKCommandBase): for lib in sorted_lib_path_list(libs): print(tag, lib, file=file) + def _print_make(self, vndk_lib, file=sys.stdout): def get_module_name(path): return os.path.splitext(os.path.basename(path))[0] @@ -3113,6 +3260,7 @@ class VNDKCommand(VNDKCommandBase): file.write(template) + def _print_file_size_output(self, graph, vndk_lib, file=sys.stderr): def collect_tags(lib): tags = [] @@ -3177,6 +3325,7 @@ class VNDKCommand(VNDKCommandBase): writer.writerow(SEPARATOR) writer.writerow(['Total', None] + calc_total_size(graph.all_libs())) + def main(self, args): generic_refs, graph, tagged_paths, _ = self.create_from_args(args) @@ -3206,6 +3355,7 @@ class DepsInsightCommand(VNDKCommandBase): super(DepsInsightCommand, self).__init__( 'deps-insight', help='Generate HTML to show dependencies') + def add_argparser_options(self, parser): super(DepsInsightCommand, self).add_argparser_options(parser) @@ -3214,6 +3364,7 @@ class DepsInsightCommand(VNDKCommandBase): parser.add_argument('-o', '--output', required=True, help='output directory') + @staticmethod def serialize_data(libs, vndk_lib, module_info): strs = [] @@ -3279,6 +3430,7 @@ class DepsInsightCommand(VNDKCommandBase): return (strs, mods) + def main(self, args): generic_refs, graph, tagged_paths, _ = self.create_from_args(args) @@ -3316,6 +3468,7 @@ class DepsCommand(ELFGraphCommand): super(DepsCommand, self).__init__( 'deps', help='Print binary dependencies for debugging') + def add_argparser_options(self, parser): super(DepsCommand, self).add_argparser_options(parser) @@ -3337,6 +3490,7 @@ class DepsCommand(ELFGraphCommand): parser.add_argument('--module-info') + def main(self, args): _, graph, _, _ = self.create_from_args(args) @@ -3399,6 +3553,7 @@ class DepsClosureCommand(ELFGraphCommand): super(DepsClosureCommand, self).__init__( 'deps-closure', help='Find transitive closure of dependencies') + def add_argparser_options(self, parser): super(DepsClosureCommand, self).add_argparser_options(parser) @@ -3417,6 +3572,7 @@ class DepsClosureCommand(ELFGraphCommand): parser.add_argument('--enumerate', action='store_true', help='print closure for each lib instead of union') + def print_deps_closure(self, root_libs, graph, is_excluded_libs, is_reverted, indent): if is_reverted: @@ -3464,11 +3620,13 @@ class DepsUnresolvedCommand(ELFGraphCommand): 'deps-unresolved', help='Show unresolved dt_needed entries or symbols') + def add_argparser_options(self, parser): super(DepsUnresolvedCommand, self).add_argparser_options(parser) parser.add_argument('--module-info') parser.add_argument('--path-filter') + def _dump_unresolved(self, lib, module_info, delimiter): if not lib.unresolved_symbols and not lib.unresolved_dt_needed: return @@ -3482,6 +3640,7 @@ class DepsUnresolvedCommand(ELFGraphCommand): for symbol in sorted(lib.unresolved_symbols): print('\tUNRESOLVED_SYMBOL:', symbol) + def main(self, args): _, graph, _, _ = self.create_from_args(args) module_info = ModuleInfo.load_from_path_or_default(args.module_info) @@ -3502,6 +3661,7 @@ class ApkDepsCommand(ELFGraphCommand): super(ApkDepsCommand, self).__init__( 'apk-deps', help='Print APK dependencies for debugging') + def main(self, args): _, graph, _, _ = self.create_from_args(args) @@ -3520,14 +3680,17 @@ class CheckDepCommandBase(ELFGraphCommand): super(CheckDepCommandBase, self).__init__(*args, **kwargs) self.delimiter = '' + def add_argparser_options(self, parser): super(CheckDepCommandBase, self).add_argparser_options(parser) parser.add_argument('--module-info') + def _print_delimiter(self): print(self.delimiter, end='') self.delimiter = '\n' + def _dump_dep(self, lib, bad_deps, module_info): self._print_delimiter() print(lib.path) @@ -3540,6 +3703,7 @@ class CheckDepCommandBase(ELFGraphCommand): for symbol in lib.get_dep_linked_symbols(dep): print('\t\t' + symbol) + def _dump_apk_dep(self, apk_path, bad_deps, module_info): self._print_delimiter() print(apk_path) |
