Closed goutnet closed 6 years ago
Checking libzip.so, and sure enough:
$ readelf -sW libzip.so | grep _Unwind | grep UND 166: 00000000 0 FUNC WEAK DEFAULT UND __gnu_Unwind_Find_exidx 840: 00000000 0 FUNC WEAK DEFAULT UND __gnu_Unwind_Find_exidx
This one is actually okay. The _Unwind*
symbols are a problem, but __gnu_Unwind_Find_exidx
actually comes from libc (the pedigree of the various unwind functions is complicated to say the least).
It looks like you've got all the unwind symbols properly hidden. Unless there are some other libraries in the dependency chain that aren't mentioned or libz.so is actually a library you ship in your APK rather than the system's, I think you've got that part right. If your build system is building your library correctly, the next guess is usually that one of your third-party dependencies is broken, but it looks like your dependencies are fine too.
-latomic -latomic -lunwind -lc++abi -landroid_support -lgcc -lc++_shared
This looks mostly right, but it's not quite correct for libc++_shared. I'm not 100% certain it'll make a difference, but could you try:
-landroid_support -lunwind -latomic -lgcc -lc++_shared
The NDK includes some linker scripts that can deal with this for you, btw. The same directory that has libc++_shared also has libc++.so.$API files that will link things properly for that API level. Rather than doing what you're doing, you should be able to just link that file (give the full path to the linker script as if it were a library rather than -lc++
, since it has a version attached to the name). That should work too and save you the trouble of maintaining the implementation detail.
Another choice would be getting your build system to use a standalone toolchain. If you've got resources to maintain a custom build system that may not actually be a better choice, but it is an option.
To add a bit...
as my readelf output shows, I do have a mix of gnu symbols with clang, but what bothers me is that the only C++ library is our lib, libzip is a pure C library, and should not embed any exception unwinder (unless I am wrong somewhere...).
If libzip is compiled with -funwind-tables
, then AFAICT the object file's arm32 exception table has an R_ARM_NONE
relocation referring to an unwinder routine (like __aeabi_unwind_cpp_pr0
). __aeabi_unwind_cpp_pr0
is provided by both libgcc.a
and libunwind.a
. On other architectures, using -funwind-tables
on a C file doesn't automatically link in an unwinder.
The mysolib.so
appears to be using the libgcc.a
unwinder rather than the one from libunwind.a
. Most of the __gnu_Unwind_*
functions come from libgcc.a
:
$ readelf -sW ./toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/armv7-a/libgcc.a | grep __gnu_Unwind_
43: 00000000 0 NOTYPE WEAK DEFAULT UND __gnu_Unwind_Find_exidx
46: 00000000 0 NOTYPE GLOBAL DEFAULT UND __gnu_Unwind_Restore_VFP_D
47: 00000000 0 NOTYPE GLOBAL DEFAULT UND __gnu_Unwind_Restore_VFP
48: 00000000 0 NOTYPE GLOBAL DEFAULT UND __gnu_Unwind_Restore_VFP_D_16_to_31
49: 00000000 0 NOTYPE GLOBAL DEFAULT UND __gnu_Unwind_Restore_WMMXD
50: 00000000 0 NOTYPE GLOBAL DEFAULT UND __gnu_Unwind_Restore_WMMXC
55: 0000042c 164 FUNC GLOBAL DEFAULT 1 __gnu_Unwind_RaiseException
56: 000004d0 28 FUNC GLOBAL DEFAULT 1 __gnu_Unwind_ForcedUnwind
57: 000004ec 116 FUNC GLOBAL DEFAULT 1 __gnu_Unwind_Resume
58: 00000560 32 FUNC GLOBAL DEFAULT 1 __gnu_Unwind_Resume_or_Rethrow
63: 000006a8 200 FUNC GLOBAL DEFAULT 1 __gnu_Unwind_Backtrace
69: 00000000 0 NOTYPE GLOBAL DEFAULT UND __gnu_Unwind_Save_VFP_D
70: 00000000 0 NOTYPE GLOBAL DEFAULT UND __gnu_Unwind_Save_VFP
71: 00000000 0 NOTYPE GLOBAL DEFAULT UND __gnu_Unwind_Save_VFP_D_16_to_31
72: 00000000 0 NOTYPE GLOBAL DEFAULT UND __gnu_Unwind_Save_WMMXD
73: 00000000 0 NOTYPE GLOBAL DEFAULT UND __gnu_Unwind_Save_WMMXC
13: 00000014 0 FUNC GLOBAL DEFAULT 1 __gnu_Unwind_Restore_VFP
14: 0000001c 0 FUNC GLOBAL DEFAULT 1 __gnu_Unwind_Save_VFP
15: 00000024 0 FUNC GLOBAL DEFAULT 1 __gnu_Unwind_Restore_VFP_D
16: 0000002c 0 FUNC GLOBAL DEFAULT 1 __gnu_Unwind_Save_VFP_D
17: 00000034 0 FUNC GLOBAL DEFAULT 1 __gnu_Unwind_Restore_VFP_D_16_to_31
18: 0000003c 0 FUNC GLOBAL DEFAULT 1 __gnu_Unwind_Save_VFP_D_16_to_31
19: 00000044 0 FUNC GLOBAL DEFAULT 1 __gnu_Unwind_Restore_WMMXD
20: 00000088 0 FUNC GLOBAL DEFAULT 1 __gnu_Unwind_Save_WMMXD
21: 000000cc 0 FUNC GLOBAL DEFAULT 1 __gnu_Unwind_Restore_WMMXC
22: 000000e0 0 FUNC GLOBAL DEFAULT 1 __gnu_Unwind_Save_WMMXC
24: 00000000 0 NOTYPE GLOBAL DEFAULT UND __gnu_Unwind_RaiseException
27: 00000000 0 NOTYPE GLOBAL DEFAULT UND __gnu_Unwind_Resume
30: 00000000 0 NOTYPE GLOBAL DEFAULT UND __gnu_Unwind_Resume_or_Rethrow
33: 00000000 0 NOTYPE GLOBAL DEFAULT UND __gnu_Unwind_ForcedUnwind
36: 00000000 0 NOTYPE GLOBAL DEFAULT UND __gnu_Unwind_Backtrace
$ readelf -sW ./sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libunwind.a | grep __gnu_Unwind
851: 00000000 0 NOTYPE GLOBAL DEFAULT UND __gnu_Unwind_Find_exidx
mysolib.so
has functions like __gnu_Unwind_Resume
in it.
The NDK includes some linker scripts that can deal with this for you, btw. The same directory that has libc++_shared also has libc++.so.$API files that will link things properly for that API level.
The libc++.so.$API files are new in r18. In r17b, there's still just a single libc++.so file. It has the correct library list for API 14 and up:
$ cat /x/android-ndk-r17b/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libc++.so
INPUT(-landroid_support -lunwind -latomic -lc++_shared)
It's important that -lgcc
only appears after -lunwind
, but I'm not sure it matters whether or where it appears other than that. The Clang driver adds two -lgcc
arguments to the end of the ld command-line if -lgcc
isn't passed explicitly.
ok, you guys are awesome! your comments helped me fixed my problem, :)
For others who may run in a similar issue, here what I had to do to make it work:
libatomic
, libunwind
and libgcc
-lc++
(which works in r17, but will break in r18 as mentioned, I will adjust this when r18 comes).libzip
before the the -lc++
(because libzip.so
is pulling the unwinder for some reason, it needs to be before what provides those symbols)What I also did, but I don't think it did anything to the problem:
-funwind-tables
(not sure that did anything, since libzip.so
is still pulling the unwinder even without this ` @rprichard )-ffunction-sections
(did not need it actually, and probably unrelated, but I mention it anyway)End of the day, the unwind symbols now looks like this:
$ readelf -sW libmylib.so | grep _Unwind
2545: 00000000 0 FUNC GLOBAL DEFAULT UND __gnu_Unwind_Find_exidx
4414: 001939e1 296 FUNC LOCAL DEFAULT 11 _ZL13unwind_phase2P13unw_context_tP21_Unwind_Control_Blockb
4415: 001938c5 92 FUNC LOCAL DEFAULT 11 _ZN12_GLOBAL__N_114unwindOneFrameEjP21_Unwind_Control_BlockP15_Unwind_Context
5196: 00193b09 2 FUNC LOCAL HIDDEN 11 _Unwind_Complete
5197: 00193bf1 12 FUNC LOCAL HIDDEN 11 _Unwind_DeleteException
5198: 00193b71 64 FUNC LOCAL HIDDEN 11 _Unwind_GetLanguageSpecificData
5199: 00193bb1 64 FUNC LOCAL HIDDEN 11 _Unwind_GetRegionStart
5200: 00193931 176 FUNC LOCAL HIDDEN 11 _Unwind_RaiseException
5201: 00193b0d 100 FUNC LOCAL HIDDEN 11 _Unwind_Resume
5202: 001935a5 212 FUNC LOCAL HIDDEN 11 _Unwind_VRS_Get
5203: 001932f5 688 FUNC LOCAL HIDDEN 11 _Unwind_VRS_Interpret
5204: 00193755 360 FUNC LOCAL HIDDEN 11 _Unwind_VRS_Pop
5205: 00193679 220 FUNC LOCAL HIDDEN 11 _Unwind_VRS_Set
7917: 00000000 0 FUNC GLOBAL DEFAULT UND __gnu_Unwind_Find_exidx
and I still have the two __gnu_Unwind_Find_exidx
undefined symbols:
$ readelf -sW libmylib.so | grep _Unwind | grep UND
2545: 00000000 0 FUNC GLOBAL DEFAULT UND __gnu_Unwind_Find_exidx
7917: 00000000 0 FUNC GLOBAL DEFAULT UND __gnu_Unwind_Find_exidx
the unwinder symbols embedded in libzip.so
did not change, and I still don't really grasp why the unwinder is pulled into libzip (it does not do that on the other archs, and I don't have any option set to bring those in… but well… the linker works in mysterious ways, I guess :/ ; even tried a -Wl,--no-whole-archive
just in case, but did not change anything) …
… but now the exceptions are working.
thanks again for the pointers.
Good to hear.
removed the -funwind-tables (not sure that did anything, since libzip.so is still pulling the unwinder even without this ` @rprichard )
I see some R_ARM_NONE references to __aeabi_unwind_cpp_pr{0,1,2} in various object files in libgcc.a, so maybe libzip.so links one of those in? I also see references in the NDK's libz.a, but I think libzip.so uses libz.so instead.
FWIW: I think Android's crash dumper needs the unwinding tables to generate a backtrace in a crash report.
ok thanks, I add back the -funwind-tables
in that case (always a good thing to have a somewhat meaningful trace :) )
Description
I am trying to build an application that relies on the NDK for several libs.
Our lib (that I will call
libmylib.so
) depends onlibzip.so
which in turns relies onlibz.so
In short,
libmylib.so
->libzip.so
->libz.so
I am not using ndkbuild or CMake, but rather integrated the last NDK (ndk 17) directly in our build system (custom makefiles that we have total control over).
The problem I am encountering only happens on ARM32, (all works fine on the other archs,
x86
,x86_64
andaarch64
).What happens is that exceptions are not working properly, catching an exception in the same function works, but not from a function to another, in other word:
In our build system, we use
libc++_shared
, I build libzip with clang, and use libz on the device. (that mean, we shiplibzip.so
, but notlibz.so
, as we are using the one on the device).After digging several issues that seems similar: #289 #774 It seems I am running in the same issue with the unwinder being used from two different places:
My understanding is that the issue I have is due to these two unreferenced symbols:
Checking
libzip.so
, and sure enough:full output:
as my readelf output shows, I do have a mix of gnu symbols with clang, but what bothers me is that the only C++ library is our lib, libzip is a pure C library, and should not embed any exception unwinder (unless I am wrong somewhere…).
I have tried all the solutions proposed in #289 #774 #379 but could not resolve those two symbols :/
the NDK sits in
/usr/local/toolchains/android-ndk-r17b
Here is the link command for libzip (output of clang -v) :
Here is the link command of our library:
I have been fighting this one for the last week… all works on other platforms, but am32 is giving me a hard time …
Could somebody help me figure out what is my mistake here?
@DanAlbert could I ask you a quick insight since you have been answering very similar questions in the past?
Environment Details
NDK Version: r17b Minimum API: android-21 ABI: armeabi-v7a Actual API of the device: android-24 STL: libc++ (shared) Toolchain: clang