New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 682694 link

Starred by 2 users

Issue metadata

Status: WontFix
Owner:
Last visit > 30 days ago
Closed: Jan 2018
Cc:
EstimatedDays: ----
NextAction: ----
OS: Android
Pri: 3
Type: Bug



Sign in to add a comment

Remove libc++ symbols from being exported from Android release libraries

Project Member Reported by digit@chromium.org, Jan 19 2017

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.

 

Comment 1 by digit@chromium.org, Jan 19 2017

A 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.

Comment 2 by digit@chromium.org, 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

Comment 3 by torne@chromium.org, Jan 19 2017

Cc: torne@chromium.org
Does it work to just say --exclude-libs=libc++.a, instead of expanding the list out?

Comment 4 by digit@chromium.org, 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 :)

Comment 5 by digit@chromium.org, Jan 23 2018

Status: WontFix (was: Assigned)
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