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
   });
 }