Merge "Support getting/setting API level in static binaries."
diff --git a/libdl/Android.bp b/libdl/Android.bp
index d5fae0e..a2b29cf 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -84,12 +84,7 @@
     ],
     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 c834088..402804e 100644
--- a/libdl/libdl.cpp
+++ b/libdl/libdl.cpp
@@ -214,4 +214,16 @@
   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 2fcf369..7877a37 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -271,12 +271,7 @@
     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 e2499b3..0528cd8 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 @@
 #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/dl_test.cpp b/tests/dl_test.cpp
index 7444e3a..38d7783 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -31,6 +31,7 @@
 #include <fstream>
 
 #include "gtest_globals.h"
+#include "TemporaryFile.h"
 #include "utils.h"
 
 extern "C" int main_global_default_serial() {
@@ -167,8 +168,8 @@
 }
 
 #if defined(__BIONIC__)
-static void create_ld_config_file(std::string& config_file) {
-  std::ofstream fout(config_file.c_str(), std::ios::out);
+static void create_ld_config_file(const char* config_file) {
+  std::ofstream fout(config_file, std::ios::out);
   fout << "dir.test = " << get_testlib_root() << "/ld_config_test_helper/" << std::endl
        << "[test]" << std::endl
        << "additional.namespaces = ns2" << std::endl
@@ -196,9 +197,9 @@
   }
   std::string helper = get_testlib_root() +
       "/ld_config_test_helper/ld_config_test_helper";
-  std::string config_file = get_testlib_root() + "/ld.config.txt";
-  create_ld_config_file(config_file);
-  std::string env = std::string("LD_CONFIG_FILE=") + config_file;
+  TemporaryFile config_file;
+  create_ld_config_file(config_file.filename);
+  std::string env = std::string("LD_CONFIG_FILE=") + config_file.filename;
   chmod(helper.c_str(), 0755);
   ExecTestHelper eth;
   eth.SetArgs({ helper.c_str(), nullptr });
@@ -218,9 +219,9 @@
   }
   std::string helper = get_testlib_root() +
       "/ld_config_test_helper/ld_config_test_helper";
-  std::string config_file = get_testlib_root() + "/ld.config.txt";
-  create_ld_config_file(config_file);
-  std::string env = std::string("LD_CONFIG_FILE=") + config_file;
+  TemporaryFile config_file;
+  create_ld_config_file(config_file.filename);
+  std::string env = std::string("LD_CONFIG_FILE=") + config_file.filename;
   std::string env2 = std::string("LD_PRELOAD=") + get_testlib_root() + "/ld_config_test_helper_lib3.so";
   chmod(helper.c_str(), 0755);
   ExecTestHelper eth;
@@ -248,9 +249,9 @@
   std::string error_message = "CANNOT LINK EXECUTABLE \"" + get_testlib_root() + "/ld_config_test_helper/ld_config_test_helper\": library \"ld_config_test_helper_lib1.so\" not found\n";
   std::string helper = get_testlib_root() +
       "/ld_config_test_helper/ld_config_test_helper";
-  std::string config_file = get_testlib_root() + "/ld.config.txt";
-  create_ld_config_file(config_file);
-  std::string env = std::string("LD_CONFIG_FILE=") + config_file;
+  TemporaryFile config_file;
+  create_ld_config_file(config_file.filename);
+  std::string env = std::string("LD_CONFIG_FILE=") + config_file.filename;
   chmod(helper.c_str(), 0755);
   ExecTestHelper eth;
   eth.SetArgs({ helper.c_str(), nullptr });
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 84f525d..7d9abf9 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1438,7 +1438,8 @@
 #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 @@
 
   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 @@
 
   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
diff --git a/tests/spawn_test.cpp b/tests/spawn_test.cpp
index 86175f9..7e45ec3 100644
--- a/tests/spawn_test.cpp
+++ b/tests/spawn_test.cpp
@@ -433,12 +433,12 @@
   static pid_t parent = getpid();
 
   setpgid(0, 0);
+  signal(SIGRTMIN, SIG_IGN);
 
   pid_t pid = fork();
   ASSERT_NE(-1, pid);
 
   if (pid == 0) {
-    signal(SIGRTMIN, SIG_IGN);
     for (size_t i = 0; i < 1024; ++i) {
       kill(0, SIGRTMIN);
       usleep(10);