Remove libc++ symbols from being exported from Android release libraries |
|||
Issue description
After performing an official release build of Chrome for Android, I can see that most shared libraries, export many symbols from libc++ that should not appear here. For example, in:
libchrome.so
libcronet.so
libchromium_android_linker.so
The following will show many libc++ symbols exported publicly exported by the libraries:
readelf --dyn-sym -W libchrome.so
Example entries:
68: 003c1c07 53 FUNC GLOBAL DEFAULT 11 _Znaj
69: 003c1c3c 36 FUNC GLOBAL DEFAULT 11 _ZdaPv
78: 002f9c90 125 FUNC WEAK DEFAULT 11 _ZNSt6__ndk118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEED1Ev
79: 0634db80 60 OBJECT WEAK DEFAULT 17 _ZTVNSt6__ndk118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE
...
1777: 06455680 8 OBJECT GLOBAL DEFAULT 17 _ZTIDh
1778: 06455748 8 OBJECT GLOBAL DEFAULT 17 _ZTIDi
1779: 06455450 8 OBJECT GLOBAL DEFAULT 17 _ZTIDn
1780: 06455720 8 OBJECT GLOBAL DEFAULT 17 _ZTIDs
This issue it to track why and remove these symbol entries from the libraries, for the following reasons:
- They are not needed to use the libraries properly (e.g. libchrome.so
should only export a JNI_OnLoad function, and that's all)
- They increase the libraries' total sizes.
- Each exported symbol on ELF requires a PLT indirection each time one
of the corresponding is called, even from within the library, this
actually slows down *every* call at runtime, compared to a direct
call that could be used if the static linker didn't choose to export
the symbols.
- In the case where several libraries are used in the same process, this
might break the One Definition Rule (ODR) principle and introduce
hard-to-debug bugs.
,
Jan 19 2017
It looks like the link uses libc++.a instead now, even on Android. Looking at the content of: third_party/android_tools/ndk/sources/llvm-libc++/libs/armeabi-v7a/libc++.a On can that this is a tiny linker script that contains a simple line: INPUT(-lc++_static -lc++abi -landroid_support -lunwind -latomic) So it looks like --exclude-libs doesn't search inside linker scripts and/or the symbols come from other libs like libc++-abi.a
,
Jan 19 2017
Does it work to just say --exclude-libs=libc++.a, instead of expanding the list out?
,
Jan 20 2017
--exclude-libs=libc++.a doesn't work, nor is listing individual libraries that it contains, or even all of these :-/ I suspect --excluse-libs doesn't work with linker scripts and only considers libraries that are explicitly passed on the command line at link time. I'm trying to replace the link against libc++.a with a link against the explicit list of libraries (-lc++_static -lc++abi -landroid_support -lunwind -latomic). Our build rules are a little complicated though, but I'm slowly getting there, will post when I have good news :)
,
Jan 23 2018
This is now obsolete, since the list of exported symbols is controlled through linker scripts (e.g. see configs "hide_all_but_jni_onload" or "hide_all_but_jni" in build/config/android/BUILD.gn) |
|||
►
Sign in to add a comment |
|||
Comment 1 by digit@chromium.org
, Jan 19 2017A little bit more information here about why this happens: - In component builds, the issue doesn't exist because the shared library version of libc++, which comes as an NDK prebuilt named libc++_shared.so is used. All shared libraries link against it, and simply import symbols from it. - In a non-component build though, the static version of libc++ is linked to *every* shared library. - The NDK static libc++ library is compiled with -fvisibility=public intentionally, for historical reasons too long to discuss here. Normally, we should not expose its symbols because of the following line in build/config/android/BUILD.gn: ------------------------------------------- ldflags = [ "-Wl,--build-id=sha1", "-Wl,--no-undefined", # Don't allow visible symbols from libgcc or libc++ to be # re-exported. "-Wl,--exclude-libs=libgcc.a", "-Wl,--exclude-libs=libc++_static.a", ... ------------------------------------------- For some reason, it seems this mechanism is not working properly, and the symbols _are_ indeed re-exported.