Merge "vndk-def: Add regex support to extra deps format" am: 5382b4e19a
am: f8627184fa
Change-Id: I5bf9e001b461ed674e23d16addcfc6922e78f3df
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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.')
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user