Merge "vndk-def: Add regex support to extra deps format"

This commit is contained in:
Logan Chien
2017-11-21 01:41:15 +00:00
committed by Gerrit Code Review
4 changed files with 147 additions and 29 deletions

View File

@@ -1,12 +1,6 @@
/system/lib/libEGL.so:/system/lib/libEGL.so
/system/lib/libEGL.so:/system/lib/libGLESv1_CM.so
/system/lib/libEGL.so:/system/lib/libGLESv2.so
/system/lib/libc.so:/system/lib/libc_malloc_debug.so
/system/lib/libc.so:/system/lib/libicuuc.so
/system/lib/libc.so:/system/lib/libnetd_client.so
/system/lib64/libEGL.so:/system/lib64/libEGL.so
/system/lib64/libEGL.so:/system/lib64/libGLESv1_CM.so
/system/lib64/libEGL.so:/system/lib64/libGLESv2.so
/system/lib64/libc.so:/system/lib64/libc_malloc_debug.so
/system/lib64/libc.so:/system/lib64/libicuuc.so
/system/lib64/libc.so:/system/lib64/libnetd_client.so
/system/${LIB}/libEGL.so:/system/${LIB}/libEGL.so
/system/${LIB}/libEGL.so:/system/${LIB}/libGLESv1_CM.so
/system/${LIB}/libEGL.so:/system/${LIB}/libGLESv2.so
/system/${LIB}/libc.so:/system/${LIB}/libc_malloc_debug.so
/system/${LIB}/libc.so:/system/${LIB}/libicuuc.so
/system/${LIB}/libc.so:/system/${LIB}/libnetd_client.so

View File

@@ -2,11 +2,12 @@
import os
import sys
import tempfile
import unittest
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from compat import StringIO
from compat import StringIO, patch
from utils import GraphBuilder
from vndk_definition_tool import (ELF, GenericRefs, PT_SYSTEM, PT_VENDOR)
@@ -41,9 +42,11 @@ class ELFLinkerTest(unittest.TestCase):
gb.resolve()
return gb
def _get_paths_from_nodes(self, nodes):
return sorted([node.path for node in nodes])
def test_get_lib(self):
gb = self._create_normal_graph()
graph = gb.graph
@@ -62,6 +65,7 @@ class ELFLinkerTest(unittest.TestCase):
self.assertEqual(None, graph.get_lib('/no/such/path.so'))
def test_map_paths_to_libs(self):
gb = self._create_normal_graph()
graph = gb.graph
@@ -81,6 +85,7 @@ class ELFLinkerTest(unittest.TestCase):
self.assertEqual(['/system/lib64/libdl.so'],
self._get_paths_from_nodes(nodes))
def test_elf_class_and_partitions(self):
gb = self._create_normal_graph()
graph = gb.graph
@@ -89,6 +94,7 @@ class ELFLinkerTest(unittest.TestCase):
self.assertEqual(1, len(graph.lib_pt[PT_VENDOR].lib32))
self.assertEqual(1, len(graph.lib_pt[PT_VENDOR].lib64))
def test_deps(self):
gb = self._create_normal_graph()
graph = gb.graph
@@ -109,6 +115,7 @@ class ELFLinkerTest(unittest.TestCase):
'/system/lib64/libdl.so'],
self._get_paths_from_nodes(node.deps_all))
def test_linked_symbols(self):
gb = self._create_normal_graph()
graph = gb.graph
@@ -149,6 +156,7 @@ class ELFLinkerTest(unittest.TestCase):
self.assertIs(libc, libEGL.linked_symbols['fclose'])
self.assertIs(libc, libEGL.linked_symbols['fopen'])
def test_unresolved_symbols(self):
gb = GraphBuilder()
gb.add_lib(PT_SYSTEM, ELF.ELFCLASS64, 'libfoo', dt_needed=[],
@@ -159,6 +167,7 @@ class ELFLinkerTest(unittest.TestCase):
lib = gb.graph.get_lib('/system/lib64/libfoo.so')
self.assertEqual({'__does_not_exist'}, lib.unresolved_symbols)
def test_users(self):
gb = self._create_normal_graph()
graph = gb.graph
@@ -182,6 +191,7 @@ class ELFLinkerTest(unittest.TestCase):
node = graph.get_lib('/vendor/lib64/libEGL.so')
self.assertEqual([], self._get_paths_from_nodes(node.users_all))
def test_compute_predefined_sp_hal(self):
gb = GraphBuilder()
@@ -259,6 +269,7 @@ class ELFLinkerTest(unittest.TestCase):
self.assertNotIn('/system/' + lib + '/libfoo.so', sp_hals)
self.assertNotIn('/vendor/' + lib + '/libfoo.so', sp_hals)
def test_compute_sp_lib(self):
# Create graph.
gb = GraphBuilder()
@@ -366,5 +377,103 @@ class ELFLinkerTest(unittest.TestCase):
self.assertNotIn(libc_path, sp_ndk_indirect)
class ELFLinkerDlopenDepsTest(unittest.TestCase):
def test_add_dlopen_deps(self):
gb = GraphBuilder()
liba = gb.add_lib32(PT_SYSTEM, 'liba')
libb = gb.add_lib32(PT_SYSTEM, 'libb')
gb.resolve()
with tempfile.NamedTemporaryFile(mode='w') as tmp_file:
tmp_file.write('/system/lib/liba.so: /system/lib/libb.so')
tmp_file.seek(0)
gb.graph.add_dlopen_deps(tmp_file.name)
self.assertIn(libb, liba.deps_dlopen)
self.assertIn(liba, libb.users_dlopen)
self.assertNotIn(libb, liba.deps_needed)
self.assertNotIn(liba, libb.users_needed)
def test_add_dlopen_deps_lib_subst(self):
gb = GraphBuilder()
liba_32, liba_64 = gb.add_multilib(PT_SYSTEM, 'liba')
libb_32, libb_64 = gb.add_multilib(PT_SYSTEM, 'libb')
gb.resolve()
with tempfile.NamedTemporaryFile(mode='w') as tmp_file:
tmp_file.write('/system/${LIB}/liba.so: /system/${LIB}/libb.so')
tmp_file.seek(0)
gb.graph.add_dlopen_deps(tmp_file.name)
self.assertIn(libb_32, liba_32.deps_dlopen)
self.assertIn(liba_32, libb_32.users_dlopen)
self.assertIn(libb_64, liba_64.deps_dlopen)
self.assertIn(liba_64, libb_64.users_dlopen)
def test_add_dlopen_deps_lib_subset_single_bitness(self):
gb = GraphBuilder()
liba_32, liba_64 = gb.add_multilib(PT_SYSTEM, 'liba')
libb_32 = gb.add_lib32(PT_SYSTEM, 'libb')
gb.resolve()
with tempfile.NamedTemporaryFile(mode='w') as tmp_file:
tmp_file.write('/system/${LIB}/libb.so: /system/${LIB}/liba.so')
tmp_file.seek(0)
stderr = StringIO()
with patch('sys.stderr', stderr):
gb.graph.add_dlopen_deps(tmp_file.name)
self.assertEqual('', stderr.getvalue())
self.assertIn(liba_32, libb_32.deps_dlopen)
self.assertIn(libb_32, liba_32.users_dlopen)
self.assertEqual(0, len(liba_64.users_dlopen))
def test_add_dlopen_deps_regex(self):
gb = GraphBuilder()
liba = gb.add_lib32(PT_SYSTEM, 'liba')
libb = gb.add_lib32(PT_SYSTEM, 'libb')
gb.resolve()
with tempfile.NamedTemporaryFile(mode='w') as tmp_file:
tmp_file.write('[regex].*libb\\.so: [regex].*/${LIB}/liba\\.so')
tmp_file.seek(0)
stderr = StringIO()
with patch('sys.stderr', stderr):
gb.graph.add_dlopen_deps(tmp_file.name)
self.assertEqual('', stderr.getvalue())
self.assertIn(liba, libb.deps_dlopen)
self.assertIn(libb, liba.users_dlopen)
def test_add_dlopen_deps_error(self):
gb = GraphBuilder()
liba = gb.add_lib32(PT_SYSTEM, 'liba')
libb = gb.add_lib32(PT_SYSTEM, 'libb')
gb.resolve()
with tempfile.NamedTemporaryFile(mode='w') as tmp_file:
tmp_file.write('/system/lib/libc.so: /system/lib/libd.so')
tmp_file.seek(0)
stderr = StringIO()
with patch('sys.stderr', stderr):
gb.graph.add_dlopen_deps(tmp_file.name)
self.assertRegexpMatches(
stderr.getvalue(),
'error: Failed to add dlopen dependency from .* to .*\\.\n')
if __name__ == '__main__':
unittest.main()

View File

@@ -31,7 +31,7 @@ class ELFLinkerVNDKTest(unittest.TestCase):
with patch('sys.stderr', stderr):
gb.graph.normalize_partition_tags(set(), None)
self.assertRegex(
self.assertRegexpMatches(
stderr.getvalue(),
'error: .*: system exe/lib must not depend on vendor lib .*. '
'Assume such dependency does not exist.')

View File

@@ -1144,21 +1144,36 @@ class ELFLinker(object):
return lib
def add_dlopen_dep(self, src_path, dst_path):
num_matches = 0
for elf_class in (ELF.ELFCLASS32, ELF.ELFCLASS64):
src = self.get_lib_in_elf_class(elf_class, src_path)
dst = self.get_lib_in_elf_class(elf_class, dst_path)
if src and dst:
srcs = self._get_libs_in_elf_class(elf_class, src_path)
dsts = self._get_libs_in_elf_class(elf_class, dst_path)
for src, dst in itertools.product(srcs, dsts):
src.add_dlopen_dep(dst)
return
print('error: cannot add dependency from {} to {}.'
.format(src_path, dst_path), file=sys.stderr)
num_matches += 1
if num_matches == 0:
print('error: Failed to add dlopen dependency from {} to {}.'
.format(src_path, dst_path), file=sys.stderr)
def get_lib_in_elf_class(self, elf_class, path, default=None):
for partition in range(NUM_PARTITIONS):
res = self.lib_pt[partition].get_lib_dict(elf_class).get(path)
if res:
return res
return default
def _get_libs_in_elf_class(self, elf_class, path):
result = set()
if '${LIB}' in path:
lib_dir = 'lib' if elf_class == ELF.ELFCLASS32 else 'lib64'
path = path.replace('${LIB}', lib_dir)
if path.startswith('[regex]'):
patt = re.compile(path[7:])
for partition in range(NUM_PARTITIONS):
lib_set = self.lib_pt[partition].get_lib_dict(elf_class)
for path ,lib in lib_set.items():
if patt.match(path):
result.add(lib)
else:
for partition in range(NUM_PARTITIONS):
lib_set = self.lib_pt[partition].get_lib_dict(elf_class)
lib = lib_set.get(path)
if lib:
result.add(lib)
return result
def get_lib(self, path):
for lib_set in self.lib_pt:
@@ -1222,7 +1237,7 @@ class ELFLinker(object):
else:
self.add_lib(partition, short_path, elf)
def load_extra_deps(self, path):
def add_dlopen_deps(self, path):
patt = re.compile('([^:]*):\\s*(.*)')
with open(path, 'r') as f:
for line in f:
@@ -1812,7 +1827,7 @@ class ELFLinker(object):
if extra_deps:
for path in extra_deps:
graph.load_extra_deps(path)
graph.add_dlopen_deps(path)
graph.resolve_deps(generic_refs)
@@ -2112,7 +2127,7 @@ class VNDKCommandBase(ELFGraphCommand):
script_dir = os.path.dirname(os.path.abspath(__file__))
minimum_dlopen_deps = os.path.join(script_dir, 'datasets',
'minimum_dlopen_deps.txt')
graph.load_extra_deps(minimum_dlopen_deps)
graph.add_dlopen_deps(minimum_dlopen_deps)
return (generic_refs, graph, tagged_paths)