ndk
ndk copied to clipboard
[BUG] Can't auto hide STL Libc++ symbols since r22
Description
I started to use r22, and found it generated bigger binary than r21. And I found it show many std::string symbol in the binary.
So I need to add below code to hide it
#if (_LIBCPP_VERSION >= 11000)
#include <string>
#include <vector>
_LIBCPP_BEGIN_NAMESPACE_STD
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>;
_LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char)
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __vector_base_common<true>;
_LIBCPP_END_NAMESPACE_STD
#endif
and add options in CMakeLists.txt
add_compile_options( -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS )
Environment Details
- NDK Version: r22
- Build system: Android Studio 4.1
- Host OS: Windows
- ABI: Any
- NDK API level: Any
- Device API level: Any
add_compile_options( -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS )
https://libcxx.llvm.org/docs/UsingLibcxx.html#libc-configuration-macros
This macro is used to disable all visibility annotations inside libc++. Defining this macro and then building libc++ with hidden visibility gives a build of libc++ which does not export any symbols, which can be useful when building statically for inclusion into another library.
The NDK ships a prebuilt libc++, so that macro does nothing for you. You'd need to build your own libc++ to use that. I'm unsure what part of this is "since r22". It looks like this has always been the case and is the expected behavior?
But I think your actual complaint here is that binary size has increased. Is this a duplicate of https://github.com/android/ndk/issues/1402? If not, we don't have the information we need to investigate and you'll need to provide the repro case the template asked for.
add_compile_options( -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS )
https://libcxx.llvm.org/docs/UsingLibcxx.html#libc-configuration-macros
This macro is used to disable all visibility annotations inside libc++. Defining this macro and then building libc++ with hidden visibility gives a build of libc++ which does not export any symbols, which can be useful when building statically for inclusion into another library.
The NDK ships a prebuilt libc++, so that macro does nothing for you. You'd need to build your own libc++ to use that. I'm unsure what part of this is "since r22". It looks like this has always been the case and is the expected behavior?
That I tried to do the same result as r21. It would be many symbols without _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS.
But I think your actual complaint here is that binary size has increased. Is this a duplicate of #1402? If not, we don't have the information we need to investigate and you'll need to provide the repro case the template asked for.
Maybe the same problem. I think the different between r21 and r22, the r21 is inline std::string functions and the r22 is extern linking std::string functions. The result is not any std::string symbols in r21, and all std::string functions symbols in r22 that it need to link libc++ library. So what kind is right? Maybe r22 is accord to C++ Standard.
It is possible that some template instantiation become visible without _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS. But it is difficult to locate what is changed. I eye scanned through string
but didn't notice any obvious visibility change. Can you provide a repro case? So that we can figure what symbols become visible.
Closing as we have insufficient information currently. If we get a repro case it'll get reopened.
teststl.cpp
#include <string>
#include <vector>
__attribute__((visibility("default")))
std::string foo()
{
return "Hello, World!";
}
__attribute__((visibility("default")))
std::vector<char> bar()
{
return {1};
}
__attribute__((visibility("default")))
void add_string(std::string& value)
{
value += "Hello, World!";
}
__attribute__((visibility("default")))
void add_vector(std::vector<char>& value)
{
value.push_back(1);
}
#if defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
_LIBCPP_BEGIN_NAMESPACE_STD
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>;
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<char>;
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __vector_base_common<true>;
_LIBCPP_END_NAMESPACE_STD
#endif
ndk-r21
$ clang++ teststl.cpp --shared -fno-exceptions -fvisibility=hidden -Ofast -o a.out.21 -Wl,--strip-all
$ objdump -d a.out.21 | grep 0000
00000000000006c0 .plt:
0000000000000740 .text:
000000000000077c _Z3foov:
00000000000007a8 _Z3barv:
00000000000007e0 _Z10add_stringRNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE:
00000000000007f0 _Z10add_vectorRNSt6__ndk16vectorIcNS_9allocatorIcEEEE:
ndk-r22
$ clang++ teststl.cpp --shared -fno-exceptions -fvisibility=hidden -Ofast -o a.out.22 -Wl,--strip-all
$ objdump -d a.out.22 | grep 0000
0000000000001758 .text:
0000000000001794 _Z3foov:
00000000000017bc _Z3barv:
00000000000017f4 _Z10add_stringRNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE:
0000000000001800 _Z10add_vectorRNSt6__ndk16vectorIcNS_9allocatorIcEEEE:
00000000000018f0 .plt:
0000000000001910 __cxa_finalize@plt:
0000000000001920 __cxa_atexit@plt:
0000000000001930 _Znwm@plt:
0000000000001940 _ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6appendEPKc@plt:
0000000000001950 memcpy@plt:
0000000000001960 _ZdlPv@plt:
0000000000001970 _ZNKSt6__ndk120__vector_base_commonILb1EE20__throw_length_errorEv@plt:
ndk-r22 (_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
$ clang++ teststl.cpp --shared -fno-exceptions -fvisibility=hidden -Ofast -o a.out.22d -Wl,--strip-all -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS
$ objdump -d a.out.22d | grep 0000
0000000000001680 .text:
00000000000016bc _Z3foov:
00000000000016e4 _Z3barv:
000000000000171c _Z10add_stringRNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE:
000000000000172c _Z10add_vectorRNSt6__ndk16vectorIcNS_9allocatorIcEEEE:
00000000000019b0 .plt:
00000000000019d0 __cxa_finalize@plt:
00000000000019e0 __cxa_atexit@plt:
00000000000019f0 _Znwm@plt:
0000000000001a00 memcpy@plt:
0000000000001a10 _ZdlPv@plt:
0000000000001a20 abort@plt:
Thanks! You've missed the window for r22b but we can take a look.
Been trying for an hour and I can't reproduce your r21 results. Which target are you using? Assuming x86_64-linux-android21 since you're using what appears to be your system's objdump and 64-bit addresses:
danalbert :: src/ndk/ndk ‹docs*› » ../../android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ -target x86_64-linux-android21 foo.cpp --shared -fno-exceptions -fvisibility=hidden -Ofast -o libfoo.21.so -Wl,--strip-all
danalbert :: src/ndk/ndk ‹docs*› » objdump -d libfoo.21.so | grep 0000
00000000000006d0 <__cxa_finalize@plt-0x10>:
00000000000006e0 <__cxa_finalize@plt>:
00000000000006f0 <__cxa_atexit@plt>:
0000000000000700 <_Znwm@plt>:
0000000000000710 <memcpy@plt>:
0000000000000720 <_ZdlPv@plt>:
0000000000000730 <abort@plt>:
0000000000000740 <_Z3foov@@Base-0x60>:
00000000000007a0 <_Z3foov@@Base>:
00000000000007e0 <_Z3barv@@Base>:
0000000000000810 <_Z10add_stringRNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE@@Base>:
0000000000000830 <_Z10add_vectorRNSt6__ndk16vectorIcNS_9allocatorIcEEEE@@Base>:
Using readelf to look for defined vs undefined symbols even shows the opposite, though the symbols that disappeared aren't really interesting and are probably just a bfd -> lld change:
danalbert :: src/ndk/ndk ‹docs*› » readelf -sW libfoo.22.so | grep -v UND
Symbol table '.dynsym' contains 12 entries:
Num: Value Size Type Bind Vis Ndx Name
8: 00000000000019b0 12 FUNC GLOBAL DEFAULT 13 _Z10add_stringRNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
9: 00000000000019c0 220 FUNC GLOBAL DEFAULT 13 _Z10add_vectorRNSt6__ndk16vectorIcNS_9allocatorIcEEEE
10: 0000000000001980 37 FUNC GLOBAL DEFAULT 13 _Z3barv
11: 0000000000001950 39 FUNC GLOBAL DEFAULT 13 _Z3foov
danalbert :: src/ndk/ndk ‹docs*› » readelf -sW libfoo.21.so | grep -v UND
Symbol table '.dynsym' contains 14 entries:
Num: Value Size Type Bind Vis Ndx Name
7: 0000000000002000 0 NOTYPE GLOBAL DEFAULT ABS _end
8: 0000000000002000 0 NOTYPE GLOBAL DEFAULT ABS _edata
9: 0000000000000810 17 FUNC GLOBAL DEFAULT 12 _Z10add_stringRNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
10: 00000000000007e0 37 FUNC GLOBAL DEFAULT 12 _Z3barv
11: 00000000000007a0 53 FUNC GLOBAL DEFAULT 12 _Z3foov
12: 0000000000002000 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
13: 0000000000000830 218 FUNC GLOBAL DEFAULT 12 _Z10add_vectorRNSt6__ndk16vectorIcNS_9allocatorIcEEEE
I can't make sense of why your fix actually changes anything:
_LIBCPP_BEGIN_NAMESPACE_STD
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>;
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<char>;
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __vector_base_common<true>;
_LIBCPP_END_NAMESPACE_STD
_LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
is an empty definition and afaict always has been for non-Windows.
I can't make sense of why your fix actually changes anything:
_LIBCPP_BEGIN_NAMESPACE_STD template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>; template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<char>; template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __vector_base_common<true>; _LIBCPP_END_NAMESPACE_STD
_LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
is an empty definition and afaict always has been for non-Windows.
the _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS can be ignored. the code is copied from libcxx source. the code is Implemented code because libcxx changed method that let some codes to source to make building faster.
If the visibility macro isn't the important part there then I really don't know what that would do anything.
And without a repro case we're back to not being able to do anything to help.