vndk-def: Add vndk-cap subcommand.

This commit adds vndk-cap subcommand.  vndk-cap subcommand will compute
the upper bound of the eligible libraries for VNDK definition.

Test: ./tests/test_elf_linker.py
Change-Id: Ie6600c35735de36055b2770836f2e87397221ddd
This commit is contained in:
Logan Chien
2017-03-09 17:21:29 +08:00
parent 9788c86218
commit d42d07d762
2 changed files with 147 additions and 1 deletions

View File

@@ -9,7 +9,8 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import unittest
from compat import StringIO
from vndk_definition_tool import ELF, ELFLinker, PT_SYSTEM, PT_VENDOR
from vndk_definition_tool import (BannedLibDict, ELF, ELFLinker, PT_SYSTEM,
PT_VENDOR)
class GraphBuilder(object):
@@ -451,6 +452,92 @@ class ELFLinkerTest(unittest.TestCase):
self.assertSetEqual(expected_vndk_fwk_ext, vndk_fwk_ext)
self.assertSetEqual(expected_vndk_vnd_ext, vndk_vnd_ext)
def test_compute_vndk_cap(self):
gb = GraphBuilder()
# Add LL-NDK libraries.
gb.add_multilib(PT_SYSTEM, 'libc')
gb.add_multilib(PT_SYSTEM, 'libdl')
gb.add_multilib(PT_SYSTEM, 'liblog')
gb.add_multilib(PT_SYSTEM, 'libm')
gb.add_multilib(PT_SYSTEM, 'libstdc++')
gb.add_multilib(PT_SYSTEM, 'libz')
# Add SP-NDK libraries.
gb.add_multilib(PT_SYSTEM, 'libEGL')
gb.add_multilib(PT_SYSTEM, 'libGLES_v2')
# Add banned libraries.
gb.add_multilib(PT_SYSTEM, 'libbinder')
gb.add_multilib(PT_SYSTEM, 'libselinux')
# Add good examples.
gb.add_multilib(PT_SYSTEM, 'libgood_a', dt_needed=['libc.so'])
gb.add_multilib(PT_SYSTEM, 'libgood_b', dt_needed=['libEGL.so'])
gb.add_multilib(PT_SYSTEM, 'libgood_c', dt_needed=['libGLES_v2.so'])
# Add bad examples.
gb.add_multilib(PT_SYSTEM, 'libbad_a', dt_needed=['libbinder.so'])
gb.add_multilib(PT_SYSTEM, 'libbad_b', dt_needed=['libselinux.so'])
gb.add_multilib(PT_SYSTEM, 'libbad_c', dt_needed=['libbad_a.so'])
gb.add_multilib(PT_SYSTEM, 'libbad_d', dt_needed=['libbad_c.so'])
gb.add_multilib(PT_VENDOR, 'libbad_e', dt_needed=['libc.so'])
gb.resolve()
# Compute VNDK cap.
banned_libs = BannedLibDict.create_default()
vndk_cap = gb.graph.compute_vndk_cap(banned_libs)
vndk_cap = set(lib.path for lib in vndk_cap)
# Check the existence of good examples.
self.assertIn('/system/lib/libgood_a.so', vndk_cap)
self.assertIn('/system/lib/libgood_b.so', vndk_cap)
self.assertIn('/system/lib/libgood_c.so', vndk_cap)
self.assertIn('/system/lib64/libgood_a.so', vndk_cap)
self.assertIn('/system/lib64/libgood_b.so', vndk_cap)
self.assertIn('/system/lib64/libgood_c.so', vndk_cap)
# Check the absence of bad examples.
self.assertNotIn('/system/lib/libbad_a.so', vndk_cap)
self.assertNotIn('/system/lib/libbad_b.so', vndk_cap)
self.assertNotIn('/system/lib/libbad_c.so', vndk_cap)
self.assertNotIn('/system/lib/libbad_d.so', vndk_cap)
self.assertNotIn('/vendor/lib/libbad_e.so', vndk_cap)
self.assertNotIn('/system/lib64/libbad_a.so', vndk_cap)
self.assertNotIn('/system/lib64/libbad_b.so', vndk_cap)
self.assertNotIn('/system/lib64/libbad_c.so', vndk_cap)
self.assertNotIn('/system/lib64/libbad_d.so', vndk_cap)
self.assertNotIn('/vendor/lib64/libbad_e.so', vndk_cap)
# Check the absence of banned libraries.
self.assertNotIn('/system/lib/libbinder.so', vndk_cap)
self.assertNotIn('/system/lib/libselinux.so', vndk_cap)
self.assertNotIn('/system/lib64/libbinder.so', vndk_cap)
self.assertNotIn('/system/lib64/libselinux.so', vndk_cap)
# Check the absence of NDK libraries. Although LL-NDK and SP-NDK
# libraries are not banned, they are not VNDK libraries either.
self.assertNotIn('/system/lib/libEGL.so', vndk_cap)
self.assertNotIn('/system/lib/libOpenGLES_v2.so', vndk_cap)
self.assertNotIn('/system/lib/libc.so', vndk_cap)
self.assertNotIn('/system/lib/libdl.so', vndk_cap)
self.assertNotIn('/system/lib/liblog.so', vndk_cap)
self.assertNotIn('/system/lib/libm.so', vndk_cap)
self.assertNotIn('/system/lib/libstdc++.so', vndk_cap)
self.assertNotIn('/system/lib/libz.so', vndk_cap)
self.assertNotIn('/system/lib64/libEGL.so', vndk_cap)
self.assertNotIn('/system/lib64/libOpenGLES_v2.so', vndk_cap)
self.assertNotIn('/system/lib64/libc.so', vndk_cap)
self.assertNotIn('/system/lib64/libdl.so', vndk_cap)
self.assertNotIn('/system/lib64/liblog.so', vndk_cap)
self.assertNotIn('/system/lib64/libm.so', vndk_cap)
self.assertNotIn('/system/lib64/libstdc++.so', vndk_cap)
self.assertNotIn('/system/lib64/libz.so', vndk_cap)
if __name__ == '__main__':
unittest.main()

View File

@@ -1282,6 +1282,43 @@ class ELFLinker(object):
extra_system_libs, extra_vendor_libs, extra_vndk_core,
vndk_core, vndk_indirect, vndk_fwk_ext, vndk_vnd_ext)
def compute_vndk_cap(self, banned_libs):
# ELF files on vendor partitions are banned unconditionally. ELF files
# on the system partition are banned if their file extensions are not
# '.so' or their file names are listed in banned_libs. LL-NDK and
# SP-NDK libraries are treated as a special case which will not be
# considered as banned libraries at the moment.
def is_banned(lib):
if lib.is_ndk:
return NDK_LIBS.is_hlndk(lib.path)
return (banned_libs.is_banned(lib.path) or
not lib.is_system_lib() or
not lib.path.endswith('.so'))
# Find all libraries that are banned.
banned_set = set()
for lib_set in self.lib_pt:
for lib in lib_set.values():
if is_banned(lib):
banned_set.add(lib)
# Find the transitive closure of the banned libraries.
stack = list(banned_set)
while stack:
lib = stack.pop()
for user in lib.users:
if not user.is_ndk and user not in banned_set:
banned_set.add(user)
stack.append(user)
# Find the non-NDK non-banned libraries.
vndk_cap = set()
for lib in self.lib_pt[PT_SYSTEM].values():
if not lib.is_ndk and lib not in banned_set:
vndk_cap.add(lib)
return vndk_cap
@staticmethod
def compute_closure(root_set, is_excluded):
closure = set(root_set)
@@ -1648,6 +1685,27 @@ class VNDKCommand(ELFGraphCommand):
return 0
class VNDKCapCommand(ELFGraphCommand):
def __init__(self):
super(VNDKCapCommand, self).__init__(
'vndk-cap', help='Compute VNDK set upper bound')
def add_argparser_options(self, parser):
super(VNDKCapCommand, self).add_argparser_options(parser)
def main(self, args):
graph = ELFLinker.create(args.system, args.system_dir_as_vendor,
args.vendor, args.vendor_dir_as_system,
args.load_extra_deps)
banned_libs = BannedLibDict.create_default()
vndk_cap = graph.compute_vndk_cap(banned_libs)
for lib in sorted_lib_path_list(vndk_cap):
print(lib)
class DepsCommand(ELFGraphCommand):
def __init__(self):
super(DepsCommand, self).__init__(
@@ -1788,6 +1846,7 @@ def main():
register_subcmd(ELFDumpCommand())
register_subcmd(CreateGenericRefCommand())
register_subcmd(VNDKCommand())
register_subcmd(VNDKCapCommand())
register_subcmd(DepsCommand())
register_subcmd(DepsClosureCommand())
register_subcmd(SpHalCommand())