-
Notifications
You must be signed in to change notification settings - Fork 264
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
C++ exceptions can't be caught on x86 API 16 emulator when building for API 16 #505
Comments
I encountered the same issue for ABI x86-64 on Windows. This issue occurs only when building with Android Studio via CMake and Gradle: |
So it's not android-16 specifically that's the problem, it's PIE. For CMake, you should be able to unblock yourself with |
It's also worth noting that PIE only affects executables, so this shouldn't be a problem for your app unless you're shelling out to a binary you ship with your app (uncommon, but not unheard of). Still a problem because this is really harmful to unit testing, so will keep digging. |
Doesn't work on android-16 or android-17 emulators, but does work on android-18. |
According to the stack trace, |
libgcc calls I think @DanAlbert's CL is the fix for AFAICT, it's easy to work around in libgcc. When a module's load-base is 0, libgcc can recalculate it by searching for the I have a tool that dumps the Bionic module lists and shows the problem with PIE binary (android-16):
PIE binary (android-17):
PIE binary (android-18):
Between android-17 and android-18, |
The fix should be in r18 beta1. |
Summary: The workaround added in https://reviews.llvm.org/rL299575 appears to be working around a bug in Android JB 4.1.x and 4.2.x (API 16 and 17). Starting in API 16, Android added support for PIE binaries, but the dynamic linker failed to initialize dlpi_addr to the address that the executable was loaded at. The bug was fixed in Android JB 4.3.x (API 18). Improve the true load bias calculation: * The code was assuming that the first segment would be the PT_PHDR segment. I think it's better to be explicit and search for PT_PHDR. (It will be almost as fast in practice.) * It's more correct to use p_vaddr rather than p_offset. If a PIE executable is linked with a non-zero image base (e.g. lld's -Wl,--image-base=xxxx), then we must use p_vaddr here. The "phdr->p_vaddr < image_base" condition seems unnecessary and maybe slightly wrong. If the OS were to load a binary at an address smaller than a vaddr in the binary, we would still want to do this workaround. The workaround is safe when the linker bug isn't present, because it should calculate an image_base equal to dlpi_addr. Note that with API 21 and up, this workaround should never activate for dynamically-linked objects, because non-PIE executables aren't allowed. Consolidate the fix into a single block of code that calculates the true image base, and make it clear that the fix no longer applies after API 18. See android/ndk#505 for details. Reviewers: mclow.lists, srhines, danalbert, compnerd Reviewed By: compnerd Subscribers: srhines, krytarowski, christof, libcxx-commits Tags: #libc Differential Revision: https://reviews.llvm.org/D68971 llvm-svn: 374969
Summary: The workaround added in https://reviews.llvm.org/rL299575 appears to be working around a bug in Android JB 4.1.x and 4.2.x (API 16 and 17). Starting in API 16, Android added support for PIE binaries, but the dynamic linker failed to initialize dlpi_addr to the address that the executable was loaded at. The bug was fixed in Android JB 4.3.x (API 18). Improve the true load bias calculation: * The code was assuming that the first segment would be the PT_PHDR segment. I think it's better to be explicit and search for PT_PHDR. (It will be almost as fast in practice.) * It's more correct to use p_vaddr rather than p_offset. If a PIE executable is linked with a non-zero image base (e.g. lld's -Wl,--image-base=xxxx), then we must use p_vaddr here. The "phdr->p_vaddr < image_base" condition seems unnecessary and maybe slightly wrong. If the OS were to load a binary at an address smaller than a vaddr in the binary, we would still want to do this workaround. The workaround is safe when the linker bug isn't present, because it should calculate an image_base equal to dlpi_addr. Note that with API 21 and up, this workaround should never activate for dynamically-linked objects, because non-PIE executables aren't allowed. Consolidate the fix into a single block of code that calculates the true image base, and make it clear that the fix no longer applies after API 18. See android/ndk#505 for details. Reviewers: mclow.lists, srhines, danalbert, compnerd Reviewed By: compnerd Subscribers: srhines, krytarowski, christof, libcxx-commits Tags: #libc Differential Revision: https://reviews.llvm.org/D68971 git-svn-id: https://llvm.org/svn/llvm-project/libunwind/trunk@374969 91177308-0d34-0410-b5e6-96231b3b80d8
Summary: The workaround added in https://reviews.llvm.org/rL299575 appears to be working around a bug in Android JB 4.1.x and 4.2.x (API 16 and 17). Starting in API 16, Android added support for PIE binaries, but the dynamic linker failed to initialize dlpi_addr to the address that the executable was loaded at. The bug was fixed in Android JB 4.3.x (API 18). Improve the true load bias calculation: * The code was assuming that the first segment would be the PT_PHDR segment. I think it's better to be explicit and search for PT_PHDR. (It will be almost as fast in practice.) * It's more correct to use p_vaddr rather than p_offset. If a PIE executable is linked with a non-zero image base (e.g. lld's -Wl,--image-base=xxxx), then we must use p_vaddr here. The "phdr->p_vaddr < image_base" condition seems unnecessary and maybe slightly wrong. If the OS were to load a binary at an address smaller than a vaddr in the binary, we would still want to do this workaround. The workaround is safe when the linker bug isn't present, because it should calculate an image_base equal to dlpi_addr. Note that with API 21 and up, this workaround should never activate for dynamically-linked objects, because non-PIE executables aren't allowed. Consolidate the fix into a single block of code that calculates the true image base, and make it clear that the fix no longer applies after API 18. See android/ndk#505 for details. Reviewers: mclow.lists, srhines, danalbert, compnerd Reviewed By: compnerd Subscribers: srhines, krytarowski, christof, libcxx-commits Tags: #libc Differential Revision: https://reviews.llvm.org/D68971 llvm-svn: 374969
Summary: The workaround added in https://reviews.llvm.org/rL299575 appears to be working around a bug in Android JB 4.1.x and 4.2.x (API 16 and 17). Starting in API 16, Android added support for PIE binaries, but the dynamic linker failed to initialize dlpi_addr to the address that the executable was loaded at. The bug was fixed in Android JB 4.3.x (API 18). Improve the true load bias calculation: * The code was assuming that the first segment would be the PT_PHDR segment. I think it's better to be explicit and search for PT_PHDR. (It will be almost as fast in practice.) * It's more correct to use p_vaddr rather than p_offset. If a PIE executable is linked with a non-zero image base (e.g. lld's -Wl,--image-base=xxxx), then we must use p_vaddr here. The "phdr->p_vaddr < image_base" condition seems unnecessary and maybe slightly wrong. If the OS were to load a binary at an address smaller than a vaddr in the binary, we would still want to do this workaround. The workaround is safe when the linker bug isn't present, because it should calculate an image_base equal to dlpi_addr. Note that with API 21 and up, this workaround should never activate for dynamically-linked objects, because non-PIE executables aren't allowed. Consolidate the fix into a single block of code that calculates the true image base, and make it clear that the fix no longer applies after API 18. See android/ndk#505 for details. Reviewers: mclow.lists, srhines, danalbert, compnerd Reviewed By: compnerd Subscribers: srhines, krytarowski, christof, libcxx-commits Tags: #libc Differential Revision: https://reviews.llvm.org/D68971 llvm-svn: 374969
* Update ndk from branch 'master' to 3a21fd712122f16879ce937f0041c7b34a966c17 - Merge "Test emutls pthread key deletion" - Test emutls pthread key deletion The key should be deleted when an solib is dlclose'd, but __thread variables should continue working during cleanup functions. Bug: b/80453944 Test: manual Change-Id: Ie5719f6228911d4e9f8f58b86f994765a713691f * Update prebuilts/ndk from branch 'dev' to f0908f8e2856919868742937450d197b08d37073 - Merge "Update prebuilt GCC to build 4886780." into dev - Update prebuilt GCC to build 4886780. Test: ndk/checkbuild.py && ndk/run_tests.py Bug: android/ndk#505 Bug: http://b/80453944 Change-Id: I1bd7fe862704a10f24806de23bc67ec3f15e4cb4 - Merge "Update prebuilt GCC to build 4856068." into dev - Update prebuilt GCC to build 4856068. Update libgcc.a with a change to defer per-thread emutls cleanup by one round. Bug: android/ndk#687 Bug: b/78022094 Test: ./checkbuild.py && ./run_tests.py --filter=emutls-dealloc Change-Id: I413b4bd926472bb50865d4b91431302f803a49e6 - Merge "Update NDK platform prebuilts to build 4828202." into dev - Update NDK platform prebuilts to build 4828202. Test: ndk/checkbuild.py && ndk/run_tests.py Bug: None Change-Id: Ib963ec9d8afe1ff84dc9586eb774aad6c9d1236b - Merge "Update NDK platform prebuilts to build 4811751." into dev - Update NDK platform prebuilts to build 4811751. Test: ndk/checkbuild.py && ndk/run_tests.py Bug: None Change-Id: If2aaaf6fe05ea63c8e340908f8f00d218219ddfb - Merge "Update NDK platform prebuilts to build 4794421." into dev - Update NDK platform prebuilts to build 4794421. Test: ndk/checkbuild.py && ndk/run_tests.py Bug: android/ndk#702 Change-Id: I84362b1b3f1bec6236866cdae617a811abfd5f52 - Merge "Update prebuilt Clang to build r328903." into dev - Merge "Adapt to the new Clang naming scheme." into dev - Adapt to the new Clang naming scheme. Clang prebuilts are now named as clang-r${REVISION}${PATCH} rather than as clang-${BUILD_NUMBER}. Test: ./symlink-clang.py Bug: None Change-Id: I758feecb05ad568560333f63d3e0e9cdc25f9bcd - Update prebuilt Clang to build r328903. Change-Id: I07c5832446733f09aa48ff8a0c13d89516e69370 - Merge "Update NDK platform prebuilts to build 4753280." into dev - Update NDK platform prebuilts to build 4753280. Test: ndk/checkbuild.py && ndk/run_tests.py Bug: None Change-Id: Ic062d17cf3a7de3c82ea1d9a875c6cb3dc141b23 - Merge "Update prebuilt binutils to build 4724899." into dev - Merge "Don't fetch the repo.prop for platform prebuilts." into dev - Don't fetch the repo.prop for platform prebuilts. Not necessary. Test: ./update_platform.py ... Bug: None Change-Id: I079c65caedaf5c1a3f270af721133051aee00c0b - Update prebuilt binutils to build 4724899. Test: ndk/checkbuild.py && ndk/run_tests.py Bug: None Change-Id: I951f53a8bfc258eb4501df8d84e255bd1e1cc1f1 - Merge "Update prebuilt Clang to build 4691093." into dev - Update prebuilt Clang to build 4691093. Change-Id: Ibe8c95936a0bbb46a172f8efcd4a00386dfa5e8c - Merge "Update Validation layer binaries" into dev - Merge "Update prebuilt Clang to build 4639204." into dev - Update Validation layer binaries Build: 4634174 https://android-build.googleplex.com/builds/branch-dashboard/aosp-master-ndk-vulkan-validation-layers?build_id=4634174 Change-Id: I55d4ca67aa390d288c6c0f04bbafb21dee31aab8 - Merge "Update NDK platform prebuilts to build 4634113." into dev - Update prebuilt Clang to build 4639204. Change-Id: I456b400bc534de579078665a48ae5235869fb3f3 - Update NDK platform prebuilts to build 4634113. Test: ndk/checkbuild.py && ndk/run_tests.py Bug: None Change-Id: I9e7aa333073c61ba2724a6cd39f7b7e30ff2fef6 - Merge "Update prebuilt Clang to build 4630689." into dev - Merge "Update NDK platform prebuilts to build 4634436." into dev - Update NDK platform prebuilts to build 4634436. Test: ndk/checkbuild.py && ndk/run_tests.py Bug: None Change-Id: Idd13dfe5dc9b928b81b48a0e72dc8ae669739275 - Update prebuilt Clang to build 4630689. Change-Id: I852722d2bdfb4aeaa42fe943677d7adbf679d61b
* Update bionic from branch 'master' to 2e457f5128b230fe2d9f0a581ddb4771cf83bf24 - Merge "Call __emutls_unregister_key on dlclose" - Call __emutls_unregister_key on dlclose We want to delay the emutls pthread key deletion to keep __thread/thread_local variables working as long as possible. Currently, emutls has its own __attribute__((destructor)) function that deletes its pthread key. That function runs even on process exit, and it can run before other destructor functions and before C++ static object destructors. Move the destructor function to crtbegin_so.c, where an __attribute__((destructor)) function is only called on dlclose. Use a priority 0 destructor, which runs after every destructor with a default or greater priority value. __emutls_unregister_key will still run before destructor functions of DT_NEEDED solibs. It also still leaks memory (both the emutls arrays and each emutls object). Bug: b/80453944 Test: manual Change-Id: I6789bcf168415ab8badf2f64687c6a0136c5c917 * Update ndk from branch 'master' to 3a21fd712122f16879ce937f0041c7b34a966c17 - Merge "Test emutls pthread key deletion" - Test emutls pthread key deletion The key should be deleted when an solib is dlclose'd, but __thread variables should continue working during cleanup functions. Bug: b/80453944 Test: manual Change-Id: Ie5719f6228911d4e9f8f58b86f994765a713691f * Update prebuilts/ndk from branch 'dev' to f0908f8e2856919868742937450d197b08d37073 - Merge "Update prebuilt GCC to build 4886780." into dev - Update prebuilt GCC to build 4886780. Test: ndk/checkbuild.py && ndk/run_tests.py Bug: android/ndk#505 Bug: http://b/80453944 Change-Id: I1bd7fe862704a10f24806de23bc67ec3f15e4cb4
* Update bionic from branch 'ndk-release-r18' to 7e22622bdd18c0ac60db437b3c41dc3f94a9c752 - Merge "Call __emutls_unregister_key on dlclose" into ndk-release-r18 - Call __emutls_unregister_key on dlclose We want to delay the emutls pthread key deletion to keep __thread/thread_local variables working as long as possible. Currently, emutls has its own __attribute__((destructor)) function that deletes its pthread key. That function runs even on process exit, and it can run before other destructor functions and before C++ static object destructors. Move the destructor function to crtbegin_so.c, where an __attribute__((destructor)) function is only called on dlclose. Use a priority 0 destructor, which runs after every destructor with a default or greater priority value. __emutls_unregister_key will still run before destructor functions of DT_NEEDED solibs. It also still leaks memory (both the emutls arrays and each emutls object). Bug: b/80453944 Test: manual Change-Id: I6789bcf168415ab8badf2f64687c6a0136c5c917 (cherry picked from commit bcea0e2afd21ab72bcd7fef27af08dfe9bdcab29) * Update ndk from branch 'ndk-release-r18' to 749873efbb382cdb9a54ac93b79fed3c4095841d - Merge "Test emutls pthread key deletion" into ndk-release-r18 - Test emutls pthread key deletion The key should be deleted when an solib is dlclose'd, but __thread variables should continue working during cleanup functions. Bug: b/80453944 Test: manual Change-Id: Ie5719f6228911d4e9f8f58b86f994765a713691f (cherry picked from commit b7cd7520324500855f5af37db8f05b41df101f2e) * Update prebuilts/ndk from branch 'ndk-release-r18' to 773f9438ca0158a13c54985f88409720cbe7e12c - Merge "Update prebuilt GCC to build 4886780." into ndk-release-r18 - Update prebuilt GCC to build 4886780. Test: ndk/checkbuild.py && ndk/run_tests.py Bug: android/ndk#505 Bug: http://b/80453944 Change-Id: I1bd7fe862704a10f24806de23bc67ec3f15e4cb4 (cherry picked from commit c406d7fe184306987f19d4ca1e9d4f2be4b3f158)
dl_iterate_phdr returns a 0 load_base for a PIE executable when it should return the address where the executable was loaded (e.g. the load base or load bias). Recalculate the load base when it is zero. This recalculation should work on any ELF file with a PT_PHDR segment -- it will calculate 0 for a non-PIE executable. The load base is added to an ELF virtual address to produce a run-time address. Recalculate it by subtracting the PT_PHDR's virtual address from its run-time address. Bug: android/ndk#505 Test: manual Test: run NDK tests (./checkbuild.py && ./run_tests.py) Change-Id: I7de46c07a8b04e794b59f07b4d554238cfd6d5d9
Test: ndk/checkbuild.py && ndk/run_tests.py Bug: android/ndk#505 Bug: http://b/80453944 Change-Id: I1bd7fe862704a10f24806de23bc67ec3f15e4cb4 (cherry picked from commit c406d7f)
Description
When building for
android-16
and running on an API 16 x86 emulator, exceptions can't be caught. When building the same project for android-15, execution on the API 16 emulator works as expected. Also, executables built for android-16 ARMv7 or v8 work as expected when run on API 16 emulators.This can be reproduced with both NDK r15c and r16 beta 1 (the latter only with a patched toolchain file, see #504) and with both gcc and clang.
On host:
On emulator (after pushing libc++_shared.so and libgnustl_shared.so to tmp and exporting LD_LIBRARY_PATH=.):
When running an executable built with -DANDROID_STL=gnustl_shared, we get the following result:
With -DANDROID_STL=c++_static or -DANDROID_STL=gnustl_static:
Workaround
Build for android-15 instead of android-16. When run on the same simulator as above, it works:
Environment Details
The text was updated successfully, but these errors were encountered: