Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NDK 18 hide symbols #829

Closed
huangqinjin opened this issue Oct 23, 2018 · 5 comments
Closed

NDK 18 hide symbols #829

huangqinjin opened this issue Oct 23, 2018 · 5 comments
Assignees
Labels
Milestone

Comments

@huangqinjin
Copy link

I create a simple project with android studio 3.2.1 (with latest ndk) including c++ support. Add the following code to native-lib.cpp:

#define HIDDEN __attribute__((visibility("hidden")))
HIDDEN int FLAGS_hello = 1;
HIDDEN int FLAGS_world = 2;
extern "C" JNIEXPORT int helloworld() { return FLAGS_hello + FLAGS_world; }

Run readelf -s libnative-lib.so | grep FLAGS for all ABIs and Debug/Release variants, I got the following output:

Debug:

armeabi-v7a:
  8482: 00019004     4 OBJECT  LOCAL  HIDDEN    20 FLAGS_hello
  8483: 00019008     4 OBJECT  LOCAL  HIDDEN    20 FLAGS_world

arm64-v8a:
  1634: 0000000000044008     4 OBJECT  LOCAL  DEFAULT   20 FLAGS_hello
  1666: 000000000004400c     4 OBJECT  LOCAL  DEFAULT   20 FLAGS_world

x86:
  6697: 00032004     4 OBJECT  LOCAL  HIDDEN    22 FLAGS_hello
  6698: 00032008     4 OBJECT  LOCAL  HIDDEN    22 FLAGS_world

x86_64:
   551: 0000000000036008     4 OBJECT  LOCAL  HIDDEN    22 FLAGS_hello
   552: 000000000003600c     4 OBJECT  LOCAL  HIDDEN    22 FLAGS_world

Release:

armeabi-v7a:
     4: 00019004     4 OBJECT  GLOBAL DEFAULT   20 FLAGS_hello
     5: 00019008     4 OBJECT  GLOBAL DEFAULT   20 FLAGS_world
  8549: 00019004     4 OBJECT  GLOBAL DEFAULT   20 FLAGS_hello
  8550: 00019008     4 OBJECT  GLOBAL DEFAULT   20 FLAGS_world

arm64-v8a:
  1549: 0000000000041008     4 OBJECT  LOCAL  DEFAULT   20 FLAGS_hello
  1579: 000000000004100c     4 OBJECT  LOCAL  DEFAULT   20 FLAGS_world

x86:
  5601: 0002f004     4 OBJECT  LOCAL  HIDDEN    22 FLAGS_hello
  5602: 0002f008     4 OBJECT  LOCAL  HIDDEN    22 FLAGS_world

x86_64:
   544: 0000000000033008     4 OBJECT  LOCAL  HIDDEN    22 FLAGS_hello
   545: 000000000003300c     4 OBJECT  LOCAL  HIDDEN    22 FLAGS_world

Symbols were not hidden in Release + armeabi-v7a. But if I replace helloworld() with

extern "C" JNIEXPORT int helloworld() { return FLAGS_hello; }

then same output got as Debug mode. I'm also confused with the Visibility of arm64-v8a being DEFAULT rather than HIDDEN.

@rprichard
Copy link
Collaborator

rprichard commented Oct 23, 2018

arm64 is special because it defaults to the gold linker, while the other three targets default to bfd. On all four targets, the linker is correctly leaving the symbol out of .dynsym for debug builds, but gold marks the local symbol visibility as local, while bfd uses hidden. I would guess that either visibility is fine, but I haven't researched it.

With the arm32 release build, on the other hand, the symbol is output as global in both .symtab and .dynsym. That looks like a Clang bug with the GlobalMerge pass, which is enabled with -Oz or -O3. It appears that it's dropping the visibility information.

int somevar1 __attribute__((visibility("hidden"))) = 1;
int somevar2 __attribute__((visibility("hidden"))) = 2;
int get() {
  return somevar1 + somevar2;
}
clang -target arm -Oz test.cpp -c && readelf -s test.o | grep somevar
     7: 00000000     4 OBJECT  GLOBAL DEFAULT    6 somevar1
     8: 00000004     4 OBJECT  GLOBAL DEFAULT    6 somevar2

Turning off the pass works around the issue (as would -Os or -O2):

clang -target arm -Oz test.cpp -c -mno-global-merge && readelf -s test.o | grep somevar
    10: 00000000     4 OBJECT  GLOBAL HIDDEN     6 somevar1
    11: 00000004     4 OBJECT  GLOBAL HIDDEN     6 somevar2

(All of my symbols are marked GLOBAL rather than LOCAL because I'm dumping symbols from an object file rather than a shared object.)


Edit: use -mno-global-merge instead of -mllvm -enable-global-merge=0

@rprichard
Copy link
Collaborator

I filed a bug against LLVM: https://bugs.llvm.org/show_bug.cgi?id=39413

@huangqinjin
Copy link
Author

huangqinjin commented Oct 24, 2018

Thanks @rprichard . I tested with NDK 17 and it worked correctly.

@srvasn
Copy link

srvasn commented Jun 7, 2020

Thanks @rprichard, your answer worked for me on NDK r20b.

@DanAlbert DanAlbert modified the milestones: external dependency, r22 Jun 8, 2020
@DanAlbert
Copy link
Member

clang-r383902 in our prebuilts doesn't have this problem any more, not a regression from r20, and has a workaround. Triaging to r22.

@DanAlbert DanAlbert self-assigned this Jun 8, 2020
@DanAlbert DanAlbert added the clang label Jun 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4 participants