Move platform-private symbols out of libdl.so

Symbols not intended to be accessible from apps are moved to libdl_android.so

Test: bionic-unit-tests
Change-Id: Ib8ba6147a20cf56550c9a008f66570a2d419565a
diff --git a/libdl/Android.bp b/libdl/Android.bp
index 2e171d6..a41aa2d 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -110,6 +110,72 @@
     },
 }
 
+cc_library {
+    name: "libdl_android",
+
+    defaults: ["linux_bionic_supported"],
+
+    // NOTE: --exclude-libs=libgcc.a makes sure that any symbols libdl.so pulls from
+    // libgcc.a are made static to libdl.so.  This in turn ensures that libraries that
+    // a) pull symbols from libgcc.a and b) depend on libdl.so will not rely on libdl.so
+    // to provide those symbols, but will instead pull them from libgcc.a.  Specifically,
+    // we use this property to make sure libc.so has its own copy of the code from
+    // libgcc.a it uses.
+    //
+    // DO NOT REMOVE --exclude-libs!
+
+    ldflags: [
+        "-Wl,--exclude-libs=libgcc.a",
+        "-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
+        "-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
+        "-Wl,--exclude-libs=libclang_rt.builtins-x86-android.a",
+        "-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a",
+    ],
+
+    // for x86, exclude libgcc_eh.a for the same reasons as above
+    arch: {
+        x86: {
+            ldflags: [
+                "-Wl,--exclude-libs=libgcc_eh.a",
+            ],
+        },
+        x86_64: {
+            ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
+        },
+    },
+
+    srcs: [ "libdl_android.cpp" ],
+    version_script: "libdl_android.map.txt",
+
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Wunused",
+        "-Werror",
+    ],
+
+    stl: "none",
+
+    nocrt: true,
+    system_shared_libs: [],
+
+    // Opt out of native_coverage when opting out of system_shared_libs
+    native_coverage: false,
+
+    // This is placeholder library the actual implementation is (currently)
+    // provided by the linker.
+    shared_libs: ["ld-android"],
+
+    sanitize: {
+        never: true,
+    },
+
+    stubs: {
+        symbol_file: "libdl_android.map.txt",
+        versions: ["10000"],
+    },
+}
+
 ndk_library {
     name: "libdl",
     symbol_file: "libdl.map.txt",
diff --git a/libdl/libdl.cpp b/libdl/libdl.cpp
index a468f81..f3a76d4 100644
--- a/libdl/libdl.cpp
+++ b/libdl/libdl.cpp
@@ -67,37 +67,8 @@
                                   const void* caller_addr);
 
 __attribute__((__weak__, visibility("default")))
-void __loader_android_set_application_target_sdk_version(int target);
-
-__attribute__((__weak__, visibility("default")))
 int __loader_android_get_application_target_sdk_version();
 
-__attribute__((__weak__, visibility("default")))
-bool __loader_android_init_anonymous_namespace(const char* shared_libs_sonames,
-                                               const char* library_search_path);
-
-__attribute__((__weak__, visibility("default")))
-struct android_namespace_t* __loader_android_create_namespace(
-                                const char* name,
-                                const char* ld_library_path,
-                                const char* default_library_path,
-                                uint64_t type,
-                                const char* permitted_when_isolated_path,
-                                struct android_namespace_t* parent,
-                                const void* caller_addr);
-
-__attribute__((__weak__, visibility("default")))
-bool __loader_android_link_namespaces(
-                                struct android_namespace_t* namespace_from,
-                                struct android_namespace_t* namespace_to,
-                                const char* shared_libs_sonames);
-
-__attribute__((__weak__, visibility("default")))
-void __loader_android_dlwarning(void* obj, void (*f)(void*, const char*));
-
-__attribute__((__weak__, visibility("default")))
-struct android_namespace_t* __loader_android_get_exported_namespace(const char* name);
-
 // Proxy calls to bionic loader
 __attribute__((__weak__))
 void* dlopen(const char* filename, int flag) {
@@ -149,71 +120,16 @@
 }
 
 __attribute__((__weak__))
-void android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
-  __loader_android_get_LD_LIBRARY_PATH(buffer, buffer_size);
-}
-
-__attribute__((__weak__))
-void android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
-  __loader_android_update_LD_LIBRARY_PATH(ld_library_path);
-}
-
-__attribute__((__weak__))
 void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo) {
   const void* caller_addr = __builtin_return_address(0);
   return __loader_android_dlopen_ext(filename, flag, extinfo, caller_addr);
 }
 
 __attribute__((__weak__))
-void android_set_application_target_sdk_version(int target) {
-  __loader_android_set_application_target_sdk_version(target);
-}
-
-__attribute__((__weak__))
 int android_get_application_target_sdk_version() {
   return __loader_android_get_application_target_sdk_version();
 }
 
-__attribute__((__weak__))
-bool android_init_anonymous_namespace(const char* shared_libs_sonames,
-                                      const char* library_search_path) {
-  return __loader_android_init_anonymous_namespace(shared_libs_sonames, library_search_path);
-}
-
-__attribute__((__weak__))
-struct android_namespace_t* android_create_namespace(const char* name,
-                                                     const char* ld_library_path,
-                                                     const char* default_library_path,
-                                                     uint64_t type,
-                                                     const char* permitted_when_isolated_path,
-                                                     struct android_namespace_t* parent) {
-  const void* caller_addr = __builtin_return_address(0);
-  return __loader_android_create_namespace(name,
-                                           ld_library_path,
-                                           default_library_path,
-                                           type,
-                                           permitted_when_isolated_path,
-                                           parent,
-                                           caller_addr);
-}
-
-__attribute__((__weak__))
-bool android_link_namespaces(struct android_namespace_t* namespace_from,
-                             struct android_namespace_t* namespace_to,
-                             const char* shared_libs_sonames) {
-  return __loader_android_link_namespaces(namespace_from, namespace_to, shared_libs_sonames);
-}
-
-__attribute__((__weak__))
-void android_dlwarning(void* obj, void (*f)(void*, const char*)) {
-  __loader_android_dlwarning(obj, f);
-}
-
-__attribute__((__weak__))
-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,
diff --git a/libdl/libdl.map.txt b/libdl/libdl.map.txt
index 1514827..b4b4117 100644
--- a/libdl/libdl.map.txt
+++ b/libdl/libdl.map.txt
@@ -41,19 +41,7 @@
     __cfi_slowpath_diag;
 } LIBC_N;
 
-LIBC_Q { # introduced=29
-  global:
-    android_create_namespace; # apex
-    android_dlwarning; # apex
-    android_get_LD_LIBRARY_PATH; # apex
-    android_get_exported_namespace; # apex
-    android_init_anonymous_namespace; # apex
-    android_link_namespaces; # apex
-    android_set_application_target_sdk_version; # apex
-} LIBC_OMR1;
-
 LIBC_PLATFORM {
   global:
     __cfi_init;
-    android_update_LD_LIBRARY_PATH;
-} LIBC_Q;
+} LIBC_OMR1;
diff --git a/libdl/libdl_android.cpp b/libdl/libdl_android.cpp
new file mode 100644
index 0000000..9ad8250
--- /dev/null
+++ b/libdl/libdl_android.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dlfcn.h>
+#include <link.h>
+#include <stdlib.h>
+#include <android/dlext.h>
+
+// These functions are exported by the loader
+// TODO(dimitry): replace these with reference to libc.so
+
+extern "C" {
+
+__attribute__((__weak__, visibility("default")))
+void __loader_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size);
+
+__attribute__((__weak__, visibility("default")))
+    void __loader_android_update_LD_LIBRARY_PATH(const char* ld_library_path);
+
+__attribute__((__weak__, visibility("default")))
+void __loader_android_set_application_target_sdk_version(int target);
+
+__attribute__((__weak__, visibility("default")))
+bool __loader_android_init_anonymous_namespace(const char* shared_libs_sonames,
+                                               const char* library_search_path);
+
+__attribute__((__weak__, visibility("default")))
+struct android_namespace_t* __loader_android_create_namespace(
+                                const char* name,
+                                const char* ld_library_path,
+                                const char* default_library_path,
+                                uint64_t type,
+                                const char* permitted_when_isolated_path,
+                                struct android_namespace_t* parent,
+                                const void* caller_addr);
+
+__attribute__((__weak__, visibility("default")))
+bool __loader_android_link_namespaces(
+                                struct android_namespace_t* namespace_from,
+                                struct android_namespace_t* namespace_to,
+                                const char* shared_libs_sonames);
+
+__attribute__((__weak__, visibility("default")))
+void __loader_android_dlwarning(void* obj, void (*f)(void*, const char*));
+
+__attribute__((__weak__, visibility("default")))
+struct android_namespace_t* __loader_android_get_exported_namespace(const char* name);
+
+// Proxy calls to bionic loader
+__attribute__((__weak__))
+void android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
+  __loader_android_get_LD_LIBRARY_PATH(buffer, buffer_size);
+}
+
+__attribute__((__weak__))
+void android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
+  __loader_android_update_LD_LIBRARY_PATH(ld_library_path);
+}
+
+__attribute__((__weak__))
+void android_set_application_target_sdk_version(int target) {
+  __loader_android_set_application_target_sdk_version(target);
+}
+
+__attribute__((__weak__))
+bool android_init_anonymous_namespace(const char* shared_libs_sonames,
+                                      const char* library_search_path) {
+  return __loader_android_init_anonymous_namespace(shared_libs_sonames, library_search_path);
+}
+
+__attribute__((__weak__))
+struct android_namespace_t* android_create_namespace(const char* name,
+                                                     const char* ld_library_path,
+                                                     const char* default_library_path,
+                                                     uint64_t type,
+                                                     const char* permitted_when_isolated_path,
+                                                     struct android_namespace_t* parent) {
+  const void* caller_addr = __builtin_return_address(0);
+  return __loader_android_create_namespace(name,
+                                           ld_library_path,
+                                           default_library_path,
+                                           type,
+                                           permitted_when_isolated_path,
+                                           parent,
+                                           caller_addr);
+}
+
+__attribute__((__weak__))
+bool android_link_namespaces(struct android_namespace_t* namespace_from,
+                             struct android_namespace_t* namespace_to,
+                             const char* shared_libs_sonames) {
+  return __loader_android_link_namespaces(namespace_from, namespace_to, shared_libs_sonames);
+}
+
+__attribute__((__weak__))
+void android_dlwarning(void* obj, void (*f)(void*, const char*)) {
+  __loader_android_dlwarning(obj, f);
+}
+
+__attribute__((__weak__))
+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/libdl/libdl_android.map.txt b/libdl/libdl_android.map.txt
new file mode 100644
index 0000000..7afcd9c
--- /dev/null
+++ b/libdl/libdl_android.map.txt
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LIBDL_ANDROID {
+  global:
+    android_create_namespace; # apex
+    android_dlwarning; # apex
+    android_get_LD_LIBRARY_PATH; # apex
+    android_update_LD_LIBRARY_PATH;
+    android_get_exported_namespace; # apex
+    android_init_anonymous_namespace; # apex
+    android_link_namespaces; # apex
+    android_set_application_target_sdk_version; # apex
+  local:
+    *;
+};
diff --git a/tests/Android.bp b/tests/Android.bp
index c200ef4..894a7cb 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -467,6 +467,7 @@
             shared_libs: [
                 "ld-android",
                 "libdl",
+                "libdl_android",
                 "libdl_preempt_test_1",
                 "libdl_preempt_test_2",
                 "libdl_test_df_1_global",