sigchain: dlsym from libc.so instead of RTLD_NEXT.
RTLD_NEXT doesn't play well with linker namespaces currently, so switch
to directly referencing libc.so.
Bug: http://b/135284876
Test: treehugger
Test: m test-art-host
Test: adb shell /data/nativetest/art/arm/art_sigchain_tests/sigchain_test
Test: adb shell /data/nativetest64/art/arm64/art_sigchain_tests/sigchain_test
Change-Id: I980bf63e5e3bb0a1638a4806c7ad76f41d5db44e
diff --git a/sigchainlib/sigchain.cc b/sigchainlib/sigchain.cc
index ad54f23..76027f5 100644
--- a/sigchainlib/sigchain.cc
+++ b/sigchainlib/sigchain.cc
@@ -98,9 +98,28 @@
static decltype(&sigprocmask64) linked_sigprocmask64;
#endif
-template<typename T>
-static void lookup_next_symbol(T* output, T wrapper, const char* name) {
- void* sym = dlsym(RTLD_NEXT, name); // NOLINT glibc triggers cert-dcl16-c with RTLD_NEXT.
+template <typename T>
+static void lookup_libc_symbol(T* output, T wrapper, const char* name) {
+#if defined(__BIONIC__)
+ constexpr const char* libc_name = "libc.so";
+#elif defined(__GLIBC__)
+#if __GNU_LIBRARY__ != 6
+#error unsupported glibc version
+#endif
+ constexpr const char* libc_name = "libc.so.6";
+#else
+#error unsupported libc: not bionic or glibc?
+#endif
+
+ static void* libc = []() {
+ void* result = dlopen(libc_name, RTLD_LOCAL | RTLD_LAZY);
+ if (!result) {
+ fatal("failed to dlopen %s: %s", libc_name, dlerror());
+ }
+ return result;
+ }();
+
+ void* sym = dlsym(libc, name); // NOLINT glibc triggers cert-dcl16-c with RTLD_NEXT.
if (sym == nullptr) {
sym = dlsym(RTLD_DEFAULT, name);
if (sym == wrapper || sym == sigaction) {
@@ -113,12 +132,12 @@
__attribute__((constructor)) static void InitializeSignalChain() {
static std::once_flag once;
std::call_once(once, []() {
- lookup_next_symbol(&linked_sigaction, sigaction, "sigaction");
- lookup_next_symbol(&linked_sigprocmask, sigprocmask, "sigprocmask");
+ lookup_libc_symbol(&linked_sigaction, sigaction, "sigaction");
+ lookup_libc_symbol(&linked_sigprocmask, sigprocmask, "sigprocmask");
#if defined(__BIONIC__)
- lookup_next_symbol(&linked_sigaction64, sigaction64, "sigaction64");
- lookup_next_symbol(&linked_sigprocmask64, sigprocmask64, "sigprocmask64");
+ lookup_libc_symbol(&linked_sigaction64, sigaction64, "sigaction64");
+ lookup_libc_symbol(&linked_sigprocmask64, sigprocmask64, "sigprocmask64");
#endif
});
}