vndk-def: Link imported symbols.
This commit resolves the library dependencies down to symbol level. It will traverse all undefined symbols and try to find a matching symbol from the libraries specified in DT_NEEDED entries. This algorithm won't be able to find symbols for the libraries that are not built with -Wl,--no-undefined. Unresolved weak symbols are added to unresolved_symbols as well. Test: ./tests/run.py Change-Id: I3b0f06e38f256025bb6993d5c9f3d8afc3a4bf0e
This commit is contained in:
@@ -163,6 +163,56 @@ class ELFLinkerTest(unittest.TestCase):
|
||||
'/system/lib64/libdl.so'],
|
||||
self._get_paths_from_nodes(node.deps))
|
||||
|
||||
def test_linked_symbols(self):
|
||||
gb = self._create_normal_graph()
|
||||
graph = gb.graph
|
||||
|
||||
# Check the unresolved symbols.
|
||||
for lib_set in (graph.lib32, graph.lib64):
|
||||
for lib in lib_set.values():
|
||||
self.assertEqual(set(), lib.unresolved_symbols)
|
||||
|
||||
# Check the linked symbols.
|
||||
for lib in ('lib', 'lib64'):
|
||||
libdl = graph.map_path_to_lib('/system/' + lib + '/libdl.so')
|
||||
libm = graph.map_path_to_lib('/system/' + lib + '/libm.so')
|
||||
libc = graph.map_path_to_lib('/system/' + lib + '/libc.so')
|
||||
libRS = graph.map_path_to_lib('/system/' + lib + '/libRS.so')
|
||||
libcutils = \
|
||||
graph.map_path_to_lib('/system/' + lib + '/libcutils.so')
|
||||
libEGL = graph.map_path_to_lib('/vendor/' + lib + '/libEGL.so')
|
||||
|
||||
# Check the linked symbols for libc.so.
|
||||
self.assertIs(libdl, libc.linked_symbols['dlclose'])
|
||||
self.assertIs(libdl, libc.linked_symbols['dlopen'])
|
||||
self.assertIs(libm, libc.linked_symbols['cos'])
|
||||
self.assertIs(libm, libc.linked_symbols['sin'])
|
||||
|
||||
# Check the linked symbols for libRS.so.
|
||||
self.assertIs(libdl, libRS.linked_symbols['dlclose'])
|
||||
self.assertIs(libdl, libRS.linked_symbols['dlopen'])
|
||||
self.assertIs(libdl, libRS.linked_symbols['dlsym'])
|
||||
|
||||
# Check the linked symbols for libcutils.so.
|
||||
self.assertIs(libdl, libcutils.linked_symbols['dlclose'])
|
||||
self.assertIs(libdl, libcutils.linked_symbols['dlopen'])
|
||||
self.assertIs(libc, libcutils.linked_symbols['fclose'])
|
||||
self.assertIs(libc, libcutils.linked_symbols['fopen'])
|
||||
|
||||
# Check the linked symbols for libEGL.so.
|
||||
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=[],
|
||||
exported_symbols={'foo', 'bar'},
|
||||
imported_symbols={'__does_not_exist'})
|
||||
gb.resolve()
|
||||
|
||||
lib = gb.graph.map_path_to_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
|
||||
|
||||
@@ -546,6 +546,8 @@ class ELFLinkData(object):
|
||||
self.deps = set()
|
||||
self.users = set()
|
||||
self.is_ndk = NDK_LIBS.is_ndk(path)
|
||||
self.unresolved_symbols = set()
|
||||
self.linked_symbols = dict()
|
||||
|
||||
def add_dep(self, dst):
|
||||
self.deps.add(dst)
|
||||
@@ -631,7 +633,24 @@ class ELFLinker(object):
|
||||
if match:
|
||||
self.add_dep(match.group(1), match.group(2))
|
||||
|
||||
def _find_exported_symbol(self, symbol, libs):
|
||||
"""Find the shared library with the exported symbol."""
|
||||
for lib in libs:
|
||||
if symbol in lib.elf.exported_symbols:
|
||||
return lib
|
||||
return None
|
||||
|
||||
def _resolve_lib_imported_symbols(self, lib, imported_libs):
|
||||
"""Resolve the imported symbols in a library."""
|
||||
for symbol in lib.elf.imported_symbols:
|
||||
imported_lib = self._find_exported_symbol(symbol, imported_libs)
|
||||
if imported_lib:
|
||||
lib.linked_symbols[symbol] = imported_lib
|
||||
else:
|
||||
lib.unresolved_symbols.add(symbol)
|
||||
|
||||
def _resolve_lib_dt_needed(self, lib, resolver):
|
||||
imported_libs = []
|
||||
for dt_needed in lib.elf.dt_needed:
|
||||
dep = resolver.resolve(dt_needed, lib.elf.dt_rpath,
|
||||
lib.elf.dt_runpath)
|
||||
@@ -642,9 +661,12 @@ class ELFLinker(object):
|
||||
.format(lib.path, dt_needed, candidates), file=sys.stderr)
|
||||
continue
|
||||
lib.add_dep(dep)
|
||||
imported_libs.append(dep)
|
||||
return imported_libs
|
||||
|
||||
def _resolve_lib_deps(self, lib, resolver):
|
||||
self._resolve_lib_dt_needed(lib, resolver)
|
||||
imported_libs = self._resolve_lib_dt_needed(lib, resolver)
|
||||
self._resolve_lib_imported_symbols(lib, imported_libs)
|
||||
|
||||
def _resolve_lib_set_deps(self, lib_set, resolver):
|
||||
for lib in lib_set.values():
|
||||
|
||||
Reference in New Issue
Block a user