diff options
author | Ryan Prichard <rprichard@google.com> | 2018-03-27 22:10:55 -0700 |
---|---|---|
committer | Ryan Prichard <rprichard@google.com> | 2018-04-04 15:56:02 -0700 |
commit | 9dac3e9efdf6b00766b992940c831ca3881b48d5 (patch) | |
tree | 843f5110c21d06bd5f7f09a36c2872f330f3776b | |
parent | 075f77d6d6b7874577788ed5b2c800ee11e67135 (diff) | |
download | bionic-9dac3e9efdf6b00766b992940c831ca3881b48d5.tar.gz |
Break libdl.so and ld-android.so's dependency on libc.so.
* Specify "nocrt: true" to avoid calling __cxa_finalize.
* Define a dummy __aeabi_unwind_cpp_pr0 for arm32.
Bug: b/62815515
Bug: b/73873002
Test: boot AOSP hikey960-userdebug
Test: run ndk_cxa_example in special /system/bin/debug namespace
Test: run Bionic unit tests
Change-Id: I59bcb100a2753286b59c51a47d7a183507219a07
(cherry picked from commit 470b66644b912ac3025ea30141f2f327bb879445)
-rw-r--r-- | libdl/Android.bp | 7 | ||||
-rw-r--r-- | libdl/libdl.cpp | 12 | ||||
-rw-r--r-- | linker/Android.bp | 7 | ||||
-rw-r--r-- | linker/ld_android.cpp | 14 | ||||
-rw-r--r-- | tests/dlfcn_test.cpp | 13 |
5 files changed, 35 insertions, 18 deletions
diff --git a/libdl/Android.bp b/libdl/Android.bp index 082cdead1..5998f9bbc 100644 --- a/libdl/Android.bp +++ b/libdl/Android.bp @@ -84,12 +84,7 @@ cc_library { ], stl: "none", - // NOTE: libdl needs __aeabi_unwind_cpp_pr0 from libgcc.a but libgcc.a needs a - // few symbols from libc. Using --no-undefined here results in having to link - // against libc creating a circular dependency which is removed and we end up - // with missing symbols. Since this library is just a bunch of stubs, we set - // LOCAL_ALLOW_UNDEFINED_SYMBOLS to remove --no-undefined from the linker flags. - allow_undefined_symbols: true, + nocrt: true, system_shared_libs: [], // This is placeholder library the actual implementation is (currently) diff --git a/libdl/libdl.cpp b/libdl/libdl.cpp index c8340888e..402804ec5 100644 --- a/libdl/libdl.cpp +++ b/libdl/libdl.cpp @@ -214,4 +214,16 @@ struct android_namespace_t* android_get_exported_namespace(const char* name) { return __loader_android_get_exported_namespace(name); } +#if defined(__arm__) +// An arm32 unwinding table has an R_ARM_NONE relocation to +// __aeabi_unwind_cpp_pr0. This shared library will never invoke the unwinder, +// so it doesn't actually need the routine. Define a dummy version here, +// because the real version calls libc functions (e.g. memcpy, abort), which +// would create a dependency cycle with libc.so. +__attribute__((visibility("hidden"))) +void __aeabi_unwind_cpp_pr0() { + __builtin_trap(); +} +#endif + } // extern "C" diff --git a/linker/Android.bp b/linker/Android.bp index 2fcf369ef..7877a372d 100644 --- a/linker/Android.bp +++ b/linker/Android.bp @@ -271,12 +271,7 @@ cc_library { name: "ld-android", defaults: ["linux_bionic_supported"], - // NOTE: ld-android.so needs __aeabi_unwind_cpp_pr0 from libgcc.a but libgcc.a - // needs a few symbols from libc. Using --no-undefined here results in having to - // link against libc creating a circular dependency which is removed and we end - // up with missing symbols. Since this library is just a bunch of stubs, we set - // allow_undefined_symbols to remove --no-undefined from the linker flags. - allow_undefined_symbols: true, + nocrt: true, system_shared_libs: [], sanitize: { diff --git a/linker/ld_android.cpp b/linker/ld_android.cpp index e2499b300..0528cd889 100644 --- a/linker/ld_android.cpp +++ b/linker/ld_android.cpp @@ -26,11 +26,10 @@ * SUCH DAMAGE. */ -#include <stdlib.h> #include <sys/cdefs.h> extern "C" void __internal_linker_error() { - abort(); + __builtin_trap(); } __strong_alias(__loader_android_create_namespace, __internal_linker_error); @@ -59,3 +58,14 @@ __strong_alias(__loader_dl_unwind_find_exidx, __internal_linker_error); #endif __strong_alias(rtld_db_dlactivity, __internal_linker_error); +#if defined(__arm__) +// An arm32 unwinding table has an R_ARM_NONE relocation to +// __aeabi_unwind_cpp_pr0. This shared library will never invoke the unwinder, +// so it doesn't actually need the routine. Define a dummy version here, +// because the real version calls libc functions (e.g. memcpy, abort), which +// would create a dependency cycle with libc.so. +__attribute__((visibility("hidden"))) +extern "C" void __aeabi_unwind_cpp_pr0() { + __builtin_trap(); +} +#endif diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp index 84f525dee..7d9abf926 100644 --- a/tests/dlfcn_test.cpp +++ b/tests/dlfcn_test.cpp @@ -1438,7 +1438,8 @@ const llvm::ELF::Elf32_Dyn* to_dynamic_table(const char* p) { #define DT_ANDROID_RELA (llvm::ELF::DT_LOOS + 4) template<typename ELFT> -void validate_compatibility_of_native_library(const std::string& path, ELFT* elf) { +void validate_compatibility_of_native_library(const std::string& soname, + const std::string& path, ELFT* elf) { bool has_elf_hash = false; bool has_android_rel = false; bool has_rel = false; @@ -1464,10 +1465,14 @@ void validate_compatibility_of_native_library(const std::string& path, ELFT* elf ASSERT_TRUE(has_elf_hash) << path.c_str() << ": missing elf hash (DT_HASH)"; ASSERT_TRUE(!has_android_rel) << path.c_str() << ": has packed relocations"; - ASSERT_TRUE(has_rel) << path.c_str() << ": missing DT_REL/DT_RELA"; + // libdl.so is simple enough that it might not have any relocations, so + // exempt it from the DT_REL/DT_RELA check. + if (soname != "libdl.so") { + ASSERT_TRUE(has_rel) << path.c_str() << ": missing DT_REL/DT_RELA"; + } } -void validate_compatibility_of_native_library(const char* soname) { +void validate_compatibility_of_native_library(const std::string& soname) { // On the systems with emulation system libraries would be of different // architecture. Try to use alternate paths first. std::string path = std::string(ALTERNATE_PATH_TO_SYSTEM_LIB) + soname; @@ -1487,7 +1492,7 @@ void validate_compatibility_of_native_library(const char* soname) { ASSERT_TRUE(elf != nullptr); - validate_compatibility_of_native_library(path, elf); + validate_compatibility_of_native_library(soname, path, elf); } // This is a test for app compatibility workaround for arm apps |