Merge "vndk-def: Add regex support to extra deps format"
am: 5382b4e19a
Change-Id: I98bc109b811deb6a79df58c5e25b6572fbb386e3
This commit is contained in:
@@ -1,12 +1,6 @@
|
|||||||
/system/lib/libEGL.so:/system/lib/libEGL.so
|
/system/${LIB}/libEGL.so:/system/${LIB}/libEGL.so
|
||||||
/system/lib/libEGL.so:/system/lib/libGLESv1_CM.so
|
/system/${LIB}/libEGL.so:/system/${LIB}/libGLESv1_CM.so
|
||||||
/system/lib/libEGL.so:/system/lib/libGLESv2.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}/libc_malloc_debug.so
|
||||||
/system/lib/libc.so:/system/lib/libicuuc.so
|
/system/${LIB}/libc.so:/system/${LIB}/libicuuc.so
|
||||||
/system/lib/libc.so:/system/lib/libnetd_client.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
|
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
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 utils import GraphBuilder
|
||||||
from vndk_definition_tool import (ELF, GenericRefs, PT_SYSTEM, PT_VENDOR)
|
from vndk_definition_tool import (ELF, GenericRefs, PT_SYSTEM, PT_VENDOR)
|
||||||
|
|
||||||
@@ -41,9 +42,11 @@ class ELFLinkerTest(unittest.TestCase):
|
|||||||
gb.resolve()
|
gb.resolve()
|
||||||
return gb
|
return gb
|
||||||
|
|
||||||
|
|
||||||
def _get_paths_from_nodes(self, nodes):
|
def _get_paths_from_nodes(self, nodes):
|
||||||
return sorted([node.path for node in nodes])
|
return sorted([node.path for node in nodes])
|
||||||
|
|
||||||
|
|
||||||
def test_get_lib(self):
|
def test_get_lib(self):
|
||||||
gb = self._create_normal_graph()
|
gb = self._create_normal_graph()
|
||||||
graph = gb.graph
|
graph = gb.graph
|
||||||
@@ -62,6 +65,7 @@ class ELFLinkerTest(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(None, graph.get_lib('/no/such/path.so'))
|
self.assertEqual(None, graph.get_lib('/no/such/path.so'))
|
||||||
|
|
||||||
|
|
||||||
def test_map_paths_to_libs(self):
|
def test_map_paths_to_libs(self):
|
||||||
gb = self._create_normal_graph()
|
gb = self._create_normal_graph()
|
||||||
graph = gb.graph
|
graph = gb.graph
|
||||||
@@ -81,6 +85,7 @@ class ELFLinkerTest(unittest.TestCase):
|
|||||||
self.assertEqual(['/system/lib64/libdl.so'],
|
self.assertEqual(['/system/lib64/libdl.so'],
|
||||||
self._get_paths_from_nodes(nodes))
|
self._get_paths_from_nodes(nodes))
|
||||||
|
|
||||||
|
|
||||||
def test_elf_class_and_partitions(self):
|
def test_elf_class_and_partitions(self):
|
||||||
gb = self._create_normal_graph()
|
gb = self._create_normal_graph()
|
||||||
graph = gb.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].lib32))
|
||||||
self.assertEqual(1, len(graph.lib_pt[PT_VENDOR].lib64))
|
self.assertEqual(1, len(graph.lib_pt[PT_VENDOR].lib64))
|
||||||
|
|
||||||
|
|
||||||
def test_deps(self):
|
def test_deps(self):
|
||||||
gb = self._create_normal_graph()
|
gb = self._create_normal_graph()
|
||||||
graph = gb.graph
|
graph = gb.graph
|
||||||
@@ -109,6 +115,7 @@ class ELFLinkerTest(unittest.TestCase):
|
|||||||
'/system/lib64/libdl.so'],
|
'/system/lib64/libdl.so'],
|
||||||
self._get_paths_from_nodes(node.deps_all))
|
self._get_paths_from_nodes(node.deps_all))
|
||||||
|
|
||||||
|
|
||||||
def test_linked_symbols(self):
|
def test_linked_symbols(self):
|
||||||
gb = self._create_normal_graph()
|
gb = self._create_normal_graph()
|
||||||
graph = gb.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['fclose'])
|
||||||
self.assertIs(libc, libEGL.linked_symbols['fopen'])
|
self.assertIs(libc, libEGL.linked_symbols['fopen'])
|
||||||
|
|
||||||
|
|
||||||
def test_unresolved_symbols(self):
|
def test_unresolved_symbols(self):
|
||||||
gb = GraphBuilder()
|
gb = GraphBuilder()
|
||||||
gb.add_lib(PT_SYSTEM, ELF.ELFCLASS64, 'libfoo', dt_needed=[],
|
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')
|
lib = gb.graph.get_lib('/system/lib64/libfoo.so')
|
||||||
self.assertEqual({'__does_not_exist'}, lib.unresolved_symbols)
|
self.assertEqual({'__does_not_exist'}, lib.unresolved_symbols)
|
||||||
|
|
||||||
|
|
||||||
def test_users(self):
|
def test_users(self):
|
||||||
gb = self._create_normal_graph()
|
gb = self._create_normal_graph()
|
||||||
graph = gb.graph
|
graph = gb.graph
|
||||||
@@ -182,6 +191,7 @@ class ELFLinkerTest(unittest.TestCase):
|
|||||||
node = graph.get_lib('/vendor/lib64/libEGL.so')
|
node = graph.get_lib('/vendor/lib64/libEGL.so')
|
||||||
self.assertEqual([], self._get_paths_from_nodes(node.users_all))
|
self.assertEqual([], self._get_paths_from_nodes(node.users_all))
|
||||||
|
|
||||||
|
|
||||||
def test_compute_predefined_sp_hal(self):
|
def test_compute_predefined_sp_hal(self):
|
||||||
gb = GraphBuilder()
|
gb = GraphBuilder()
|
||||||
|
|
||||||
@@ -259,6 +269,7 @@ class ELFLinkerTest(unittest.TestCase):
|
|||||||
self.assertNotIn('/system/' + lib + '/libfoo.so', sp_hals)
|
self.assertNotIn('/system/' + lib + '/libfoo.so', sp_hals)
|
||||||
self.assertNotIn('/vendor/' + lib + '/libfoo.so', sp_hals)
|
self.assertNotIn('/vendor/' + lib + '/libfoo.so', sp_hals)
|
||||||
|
|
||||||
|
|
||||||
def test_compute_sp_lib(self):
|
def test_compute_sp_lib(self):
|
||||||
# Create graph.
|
# Create graph.
|
||||||
gb = GraphBuilder()
|
gb = GraphBuilder()
|
||||||
@@ -366,5 +377,103 @@ class ELFLinkerTest(unittest.TestCase):
|
|||||||
self.assertNotIn(libc_path, sp_ndk_indirect)
|
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__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class ELFLinkerVNDKTest(unittest.TestCase):
|
|||||||
with patch('sys.stderr', stderr):
|
with patch('sys.stderr', stderr):
|
||||||
gb.graph.normalize_partition_tags(set(), None)
|
gb.graph.normalize_partition_tags(set(), None)
|
||||||
|
|
||||||
self.assertRegex(
|
self.assertRegexpMatches(
|
||||||
stderr.getvalue(),
|
stderr.getvalue(),
|
||||||
'error: .*: system exe/lib must not depend on vendor lib .*. '
|
'error: .*: system exe/lib must not depend on vendor lib .*. '
|
||||||
'Assume such dependency does not exist.')
|
'Assume such dependency does not exist.')
|
||||||
|
|||||||
@@ -1144,21 +1144,36 @@ class ELFLinker(object):
|
|||||||
return lib
|
return lib
|
||||||
|
|
||||||
def add_dlopen_dep(self, src_path, dst_path):
|
def add_dlopen_dep(self, src_path, dst_path):
|
||||||
|
num_matches = 0
|
||||||
for elf_class in (ELF.ELFCLASS32, ELF.ELFCLASS64):
|
for elf_class in (ELF.ELFCLASS32, ELF.ELFCLASS64):
|
||||||
src = self.get_lib_in_elf_class(elf_class, src_path)
|
srcs = self._get_libs_in_elf_class(elf_class, src_path)
|
||||||
dst = self.get_lib_in_elf_class(elf_class, dst_path)
|
dsts = self._get_libs_in_elf_class(elf_class, dst_path)
|
||||||
if src and dst:
|
for src, dst in itertools.product(srcs, dsts):
|
||||||
src.add_dlopen_dep(dst)
|
src.add_dlopen_dep(dst)
|
||||||
return
|
num_matches += 1
|
||||||
print('error: cannot add dependency from {} to {}.'
|
if num_matches == 0:
|
||||||
.format(src_path, dst_path), file=sys.stderr)
|
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):
|
def _get_libs_in_elf_class(self, elf_class, path):
|
||||||
for partition in range(NUM_PARTITIONS):
|
result = set()
|
||||||
res = self.lib_pt[partition].get_lib_dict(elf_class).get(path)
|
if '${LIB}' in path:
|
||||||
if res:
|
lib_dir = 'lib' if elf_class == ELF.ELFCLASS32 else 'lib64'
|
||||||
return res
|
path = path.replace('${LIB}', lib_dir)
|
||||||
return default
|
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):
|
def get_lib(self, path):
|
||||||
for lib_set in self.lib_pt:
|
for lib_set in self.lib_pt:
|
||||||
@@ -1222,7 +1237,7 @@ class ELFLinker(object):
|
|||||||
else:
|
else:
|
||||||
self.add_lib(partition, short_path, elf)
|
self.add_lib(partition, short_path, elf)
|
||||||
|
|
||||||
def load_extra_deps(self, path):
|
def add_dlopen_deps(self, path):
|
||||||
patt = re.compile('([^:]*):\\s*(.*)')
|
patt = re.compile('([^:]*):\\s*(.*)')
|
||||||
with open(path, 'r') as f:
|
with open(path, 'r') as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
@@ -1812,7 +1827,7 @@ class ELFLinker(object):
|
|||||||
|
|
||||||
if extra_deps:
|
if extra_deps:
|
||||||
for path in extra_deps:
|
for path in extra_deps:
|
||||||
graph.load_extra_deps(path)
|
graph.add_dlopen_deps(path)
|
||||||
|
|
||||||
graph.resolve_deps(generic_refs)
|
graph.resolve_deps(generic_refs)
|
||||||
|
|
||||||
@@ -2112,7 +2127,7 @@ class VNDKCommandBase(ELFGraphCommand):
|
|||||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
minimum_dlopen_deps = os.path.join(script_dir, 'datasets',
|
minimum_dlopen_deps = os.path.join(script_dir, 'datasets',
|
||||||
'minimum_dlopen_deps.txt')
|
'minimum_dlopen_deps.txt')
|
||||||
graph.load_extra_deps(minimum_dlopen_deps)
|
graph.add_dlopen_deps(minimum_dlopen_deps)
|
||||||
|
|
||||||
return (generic_refs, graph, tagged_paths)
|
return (generic_refs, graph, tagged_paths)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user