-
Notifications
You must be signed in to change notification settings - Fork 255
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
[BUG] Unable to catch exception with NDK18b and Clang #889
Comments
The only thing I can think to recommend is to try the usual
This library appears to be linked twice, and the first use of it doesn't appear to be in the right order. I sort of doubt that's the issue since it's a static library and shouldn't contain any of the unwind pieces that usually cause this kind of problem, but it's the only thing I see here that's out of the ordinary.
I don't think order matters with |
Thank's for your reply @DanAlbert, here is the output of the readelf command for the static lib I link with:
All the symbols are marked with UND, so it seems correct. This lib is built with Qt5.12.0 and linked against some of the prebuilt shared libraries, all the shared libs are packaged into the final apk, for example libQt5Core.so. Here is the readelf output for libQt5Core.so:
Unwind* are all marked with 12. Here is the readelf output for my shared lib:
They are marked with UND, does it seem right for you, or is it going to conflict some way ? EDIT: I have a little bit more of informations... For the description below, lib1 and lib2 are static libraries used to build my shared library. When I set ANDROID_STL to c++_shared, I am able to catch an exception in lib1 thrown from lib1 as well, otherwise I am unable to catch an exception in lib1 thrown from lib2. When I set ANDROID_STL to c++_static, I am directly unable to catch an exception thrown within the same lib. |
I see only one static library ( |
@alexcohn I removed some static libraries from the description to make it a bit clearer. In addition to libAndroidToolsBased.a I have around 10 more static libraries to link with, they are all inside the whole-archive. I agree with you, according to the NDK documentation I must use the c++_shared STL instead of c++_static because of the other shared libraries packaged in my apk, and this is what I am trying to do.(I assume that libQt5Core.so has been built with c++_shared as the STL as well...) I don't understand why the 64 bits cross-compilation is not affected by that problem. |
Different unwinder that's less temperamental but doesn't work on ARM32. |
Based on that readelf output, your Qt libs weren't built correctly. STL static vs shared aside, they also need to be built with the |
@DanAlbert Are you talking about the libQt5Core.so ? If yes, how did you find that libQt5Core.so was built with the static STL instead of the shared with the readelf output ? I used the pre-built libraries, I will probably need to build them myself. |
I don't know that it was, I just know that the unwinder was linked incorrectly. If you do want to figure that out, |
Hi guys, I think I've understood what is happening. To sum up, I am using c++_shared to cross-compile my static libs and use them to generate my shared lib packaged in the final apk. What I did not see directly was that the symbol before this one was an Unwind_Resume symbol in libz.so. So why libz appears in my stack trace ? I decided to package the libz bundled within the ndk into my apk and load it explicitly at the beginning of my app to force it to use the "good one" without the Unwind_ symbols, and it worked ! I am not sure my workaround is great, I don't know if this could be dangerous in some way, can you tell me what you think about this ? Thank's in advance. |
I would rather rebuild zlib from sources. OpenSSL is a pretty dangerous dependency on its own, I believe you can have it linked to zlib statically. |
This is valid. libz is an NDK library.
This is the part that shouldn't be happening. For one, libz shouldn't have
There's no code in that library. It's a stub. I suspect the only reason this "worked" is because you haven't executed any of the libz.so code yet.
The proper fix is to ensure that the libraries in your app have been built properly. |
Hi @DanAlbert , when you say "If you've build the library correctly it is not possible for this to happen because the loader will always prefer a LOCAL symbol to a GLOBAL symbol (I think this might actually be pre-resolved when the library is linked, so it's not even possible for the loader to screw this up?).", do you mean that I need to explicitly link my shared lib with a specific lib ? Here is the backtrace I got when using the debugger and LLDB:
The exception thrown is in the constructor of the object Test in Lib2. Lib1 just instantiates a Lib2::Test in a try catch statement : Lib1:
Lib2:
Application, Jni.cpp:
In Lib2, I create an exception and throw it, so it is copied when thrown, the first object is correctly deleted but the second one is deleted before going into the catch statement... This is the first problem I saw. I have printed the address of this in the destructor of the exception and I saw that the first object destroyed is corresponding to the first object I created. For the second object, the address of this is not corresponding to the address of the copied object.
|
@DanAlbert , can you please explain me why in the Android CMake toolchain in the NDK the libunwind.a is excluded (for 32bit only)? If I understand correctly we do not want to embed the symbols of libunwind in the library(ies) ? The implementation is supposed to be directly embedded (memory jump at addr xxx) ? Here is the readelf output of my shared libs I package for my 32bit version:
As you can see, some libraries define Unwind symbols, I guess this is what is wrong... I managed to rebuild all my dependencies with the linker flags
This time they are all hidden, and it seems to work ! Some Unwind symbols appeared in lib where they were not present before (libQt5Network for example), but still HIDDEN, do you think it could be a problem ? I will perform more tests next week with multiple devices and let you know, in the mean time if you see something strange in the readelf output, please let me know ! |
https://android.googlesource.com/platform/ndk/+/master/docs/BuildSystemMaintainers.md#Unwinding
No. That's the correct behavior. |
As said in [1], unwinder is linked automatically by Clang and shared library must not re-export it. ndk after r23 (we are using r21) should be this. Else we must take care to not re-export it. From [2], we should pass the flags `Wl,--exclude-libs,libgcc.a` and `-Wl,--exclude-libs,libunwind.a` to avoid re-export `_Unwind_Resume` methods. Fix kiwix/kiwix-android#3661 [1] https://android.googlesource.com/platform/ndk/+/master/docs/BuildSystemMaintainers.md#Unwinding [2] android/ndk#889 (comment)
As said in [1], unwinder is linked automatically by Clang and shared library must not re-export it. ndk after r23 (we are using r21) should be this. Else we must take care to not re-export it. From [2], we should pass the flags `Wl,--exclude-libs,libgcc.a` and `-Wl,--exclude-libs,libunwind.a` to avoid re-export `_Unwind_Resume` methods. Fix kiwix/kiwix-android#3661 [1] https://android.googlesource.com/platform/ndk/+/master/docs/BuildSystemMaintainers.md#Unwinding [2] android/ndk#889 (comment)
Description
Hi,
I work with a C++ stack cross-compiled for Android. It builds correctly for both armeabi-v7a and arm64-v8a architectures.
When I run the apk containing the 32 bits library, my application crashes as soon as a C++ exception is thrown (even when there is a catch all statement...). I did some research and found a lot of interesting threads about libunwind/libgcc that need to be excluded when linking, but it does not fix my problem. More over, in the toolchain given by the NDK, I saw that these linker flags were already
added... I was wondering if these flags need to be set at the end of the flags list or at the beginning ?
When I run the apk containing the 64 bits library, there is no problem with the exception thrown.
EDIT: For the description below, lib1 and lib2 are static libraries used to build my shared library.
When I set ANDROID_STL to c++_shared, I am able to catch an exception in lib1 thrown from lib1 as well, otherwise I am unable to catch an exception in lib1 thrown from lib2.
When I set ANDROID_STL to c++_static, I am directly unable to catch an exception thrown within the same lib.
Anyway, I am lacking of ideas to fix this, I am open to any suggestions.
Here is the link command output:
Environment Details
The text was updated successfully, but these errors were encountered: