Merge "Expand whitelist"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 125b469..7b533a4 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,3 +1,2 @@
 [Hook Scripts]
-versioner = tools/versioner/preupload.sh
 notice = tools/update_notice.sh
diff --git a/libc/Android.bp b/libc/Android.bp
index 5d0e8c7..9bba776 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -2036,15 +2036,12 @@
     defaults: ["crt_defaults"],
 }
 
-// The following module lives in prebuilts/ndk because we need to preprocess the
-// headers to include ifdef guards for __ANDROID_API__. Update with
-// bionic/tools/update_headers.sh.
-// ndk_headers {
-//     name: "common_libc",
-//     from: "include",
-//     to: "",
-//     srcs: ["include/**/*.h"],
-// }
+preprocessed_ndk_headers {
+    name: "common_libc",
+    from: "include",
+    to: "",
+    license: "NOTICE",
+}
 
 ndk_headers {
     name: "libc_uapi",
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index e5654c3..9094fc5 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -62,7 +62,11 @@
 char** environ;
 
 #if defined(__i386__)
-__LIBC_HIDDEN__ void* __libc_sysinfo = nullptr;
+__attribute__((__naked__)) static void __libc_int0x80() {
+  __asm__ volatile("int $0x80; ret");
+}
+
+__LIBC_HIDDEN__ void* __libc_sysinfo = reinterpret_cast<void*>(__libc_int0x80);
 
 __LIBC_HIDDEN__ void __libc_init_sysinfo(KernelArgumentBlock& args) {
   __libc_sysinfo = reinterpret_cast<void*>(args.getauxval(AT_SYSINFO));
diff --git a/libc/include/math.h b/libc/include/math.h
index 8bf6fb5..7dd1539 100644
--- a/libc/include/math.h
+++ b/libc/include/math.h
@@ -153,6 +153,20 @@
 long	lrint(double);
 long	lround(double);
 
+/*
+ * https://code.google.com/p/android/issues/detail?id=271629
+ * To be fully compliant with C++, we need to not define these (C doesn't
+ * specify them either). Exposing these means that isinf and isnan will have a
+ * return type of int in C++ rather than bool like they're supposed to be.
+ *
+ * GNU libstdc++ 4.9 isn't able to handle a standard compliant C library. Its
+ * <cmath> will `#undef isnan` from math.h and only adds the function overloads
+ * to the std namespace, making it impossible to use both <cmath> (which gets
+ * included by a lot of other standard headers) and ::isnan.
+ */
+int(isinf)(double) __attribute_const__ __INTRODUCED_IN(21);
+int	(isnan)(double) __attribute_const__;
+
 double nan(const char*) __attribute_const__ __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_MIPS(13)
     __INTRODUCED_IN_X86(9);
 
diff --git a/libc/versioner-dependencies/arm/arch-arm b/libc/versioner-dependencies/arm/arch-arm
new file mode 120000
index 0000000..cc94225
--- /dev/null
+++ b/libc/versioner-dependencies/arm/arch-arm
@@ -0,0 +1 @@
+../../arch-arm/include/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/arm/kernel_uapi_asm-arm b/libc/versioner-dependencies/arm/kernel_uapi_asm-arm
new file mode 120000
index 0000000..3c7584d
--- /dev/null
+++ b/libc/versioner-dependencies/arm/kernel_uapi_asm-arm
@@ -0,0 +1 @@
+../../kernel/uapi/asm-arm
\ No newline at end of file
diff --git a/libc/versioner-dependencies/arm64/arch-arm64 b/libc/versioner-dependencies/arm64/arch-arm64
new file mode 120000
index 0000000..2d9128a
--- /dev/null
+++ b/libc/versioner-dependencies/arm64/arch-arm64
@@ -0,0 +1 @@
+../../arch-arm64/include/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/arm64/kernel_uapi_asm-arm64 b/libc/versioner-dependencies/arm64/kernel_uapi_asm-arm64
new file mode 120000
index 0000000..7ee6fd2
--- /dev/null
+++ b/libc/versioner-dependencies/arm64/kernel_uapi_asm-arm64
@@ -0,0 +1 @@
+../../kernel/uapi/asm-arm64
\ No newline at end of file
diff --git a/libc/versioner-dependencies/common/clang-builtins b/libc/versioner-dependencies/common/clang-builtins
new file mode 120000
index 0000000..7bd481c
--- /dev/null
+++ b/libc/versioner-dependencies/common/clang-builtins
@@ -0,0 +1 @@
+../../../../external/clang/lib/Headers/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/common/kernel_android_uapi b/libc/versioner-dependencies/common/kernel_android_uapi
new file mode 120000
index 0000000..fd78315
--- /dev/null
+++ b/libc/versioner-dependencies/common/kernel_android_uapi
@@ -0,0 +1 @@
+../../kernel/android/uapi/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/common/kernel_uapi b/libc/versioner-dependencies/common/kernel_uapi
new file mode 120000
index 0000000..d5cb8ee
--- /dev/null
+++ b/libc/versioner-dependencies/common/kernel_uapi
@@ -0,0 +1 @@
+../../kernel/uapi/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/mips/arch-mips b/libc/versioner-dependencies/mips/arch-mips
new file mode 120000
index 0000000..56ed021
--- /dev/null
+++ b/libc/versioner-dependencies/mips/arch-mips
@@ -0,0 +1 @@
+../../arch-mips/include/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/mips/kernel_uapi_asm-mips b/libc/versioner-dependencies/mips/kernel_uapi_asm-mips
new file mode 120000
index 0000000..94bb3db
--- /dev/null
+++ b/libc/versioner-dependencies/mips/kernel_uapi_asm-mips
@@ -0,0 +1 @@
+../../kernel/uapi/asm-mips
\ No newline at end of file
diff --git a/libc/versioner-dependencies/mips64/arch-mips64 b/libc/versioner-dependencies/mips64/arch-mips64
new file mode 120000
index 0000000..4893b57
--- /dev/null
+++ b/libc/versioner-dependencies/mips64/arch-mips64
@@ -0,0 +1 @@
+../../arch-mips64/include/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/mips64/kernel_uapi_asm-mips b/libc/versioner-dependencies/mips64/kernel_uapi_asm-mips
new file mode 120000
index 0000000..94bb3db
--- /dev/null
+++ b/libc/versioner-dependencies/mips64/kernel_uapi_asm-mips
@@ -0,0 +1 @@
+../../kernel/uapi/asm-mips
\ No newline at end of file
diff --git a/libc/versioner-dependencies/x86/arch-x86 b/libc/versioner-dependencies/x86/arch-x86
new file mode 120000
index 0000000..6426384
--- /dev/null
+++ b/libc/versioner-dependencies/x86/arch-x86
@@ -0,0 +1 @@
+../../arch-x86/include/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/x86/kernel_uapi_asm-x86 b/libc/versioner-dependencies/x86/kernel_uapi_asm-x86
new file mode 120000
index 0000000..1b7a73d
--- /dev/null
+++ b/libc/versioner-dependencies/x86/kernel_uapi_asm-x86
@@ -0,0 +1 @@
+../../kernel/uapi/asm-x86/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/x86_64/arch-x86_64 b/libc/versioner-dependencies/x86_64/arch-x86_64
new file mode 120000
index 0000000..684d74e
--- /dev/null
+++ b/libc/versioner-dependencies/x86_64/arch-x86_64
@@ -0,0 +1 @@
+../../arch-x86_64/include/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/x86_64/kernel_uapi_asm-x86 b/libc/versioner-dependencies/x86_64/kernel_uapi_asm-x86
new file mode 120000
index 0000000..1b7a73d
--- /dev/null
+++ b/libc/versioner-dependencies/x86_64/kernel_uapi_asm-x86
@@ -0,0 +1 @@
+../../kernel/uapi/asm-x86/
\ No newline at end of file
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 5ccd656..96dd477 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -48,6 +48,7 @@
 
   char* old_value = *dlerror_slot;
   *dlerror_slot = new_value;
+  LD_LOG(kLogErrors, "%s\n", new_value);
   return old_value;
 }
 
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 60dff98..e2d6115 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -83,15 +83,17 @@
 #if defined(__LP64__)
 static const char* const kSystemLibDir     = "/system/lib64";
 static const char* const kVendorLibDir     = "/vendor/lib64";
-static const char* const kAsanSystemLibDir = "/data/lib64";
-static const char* const kAsanVendorLibDir = "/data/vendor/lib64";
+static const char* const kAsanSystemLibDir = "/data/asan/system/lib64";
+static const char* const kAsanVendorLibDir = "/data/asan/vendor/lib64";
 #else
 static const char* const kSystemLibDir     = "/system/lib";
 static const char* const kVendorLibDir     = "/vendor/lib";
-static const char* const kAsanSystemLibDir = "/data/lib";
-static const char* const kAsanVendorLibDir = "/data/vendor/lib";
+static const char* const kAsanSystemLibDir = "/data/asan/system/lib";
+static const char* const kAsanVendorLibDir = "/data/asan/vendor/lib";
 #endif
 
+static const char* const kAsanLibDirPrefix = "/data/asan";
+
 static const char* const kDefaultLdPaths[] = {
   kSystemLibDir,
   kVendorLibDir,
@@ -1897,20 +1899,10 @@
   if (g_is_asan && translated_name != nullptr && translated_name[0] == '/') {
     char translated_path[PATH_MAX];
     if (realpath(translated_name, translated_path) != nullptr) {
-      if (file_is_under_dir(translated_path, kSystemLibDir)) {
-        asan_name_holder = std::string(kAsanSystemLibDir) + "/" +
-            (translated_path + strlen(kSystemLibDir) + 1);
-        if (file_exists(asan_name_holder.c_str())) {
-          translated_name = asan_name_holder.c_str();
-          PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
-        }
-      } else if (file_is_under_dir(translated_path, kVendorLibDir)) {
-        asan_name_holder = std::string(kAsanVendorLibDir) + "/" +
-            (translated_path + strlen(kVendorLibDir) + 1);
-        if (file_exists(asan_name_holder.c_str())) {
-          translated_name = asan_name_holder.c_str();
-          PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
-        }
+      asan_name_holder = std::string(kAsanLibDirPrefix) + translated_path;
+      if (file_exists(asan_name_holder.c_str())) {
+        translated_name = asan_name_holder.c_str();
+        PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
       }
     }
   }
diff --git a/linker/linker_globals.h b/linker/linker_globals.h
index b6f8a04..e4e3d97 100644
--- a/linker/linker_globals.h
+++ b/linker/linker_globals.h
@@ -38,7 +38,6 @@
     do { \
       __libc_format_buffer(linker_get_error_buffer(), linker_get_error_buffer_size(), fmt, ##x); \
       /* If LD_DEBUG is set high enough, log every dlerror(3) message. */ \
-      LD_LOG(kLogErrors, "%s\n", linker_get_error_buffer()); \
     } while (false)
 
 #define DL_WARN(fmt, x...) \
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index ee9b2e1..aa8bd57 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -24,6 +24,7 @@
 
 #include <string>
 
+#include "gtest_globals.h"
 #include "utils.h"
 
 extern "C" int main_global_default_serial() {
@@ -86,4 +87,26 @@
 #endif
 }
 
+TEST(dl, preinit_system_calls) {
+#if defined(__BIONIC__)
+  std::string helper = get_testlib_root() +
+      "/preinit_syscall_test_helper/preinit_syscall_test_helper";
+  chmod(helper.c_str(), 0755); // TODO: "x" lost in CTS, b/34945607
+  ExecTestHelper eth;
+  eth.SetArgs({ helper.c_str(), nullptr });
+  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, nullptr);
+#endif
+}
+
+TEST(dl, xfail_preinit_getauxval) {
+#if defined(__BIONIC__)
+  std::string helper = get_testlib_root() +
+      "/preinit_getauxval_test_helper/preinit_getauxval_test_helper";
+  chmod(helper.c_str(), 0755); // TODO: "x" lost in CTS, b/34945607
+  ExecTestHelper eth;
+  eth.SetArgs({ helper.c_str(), nullptr });
+  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, nullptr);
+#endif
+}
+
 // TODO: Add tests for LD_PRELOADs
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 5eb16c5..a031fe9 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -547,3 +547,17 @@
     shared_libs: ["libcfi-test"],
     ldflags: ["-Wl,--rpath,${ORIGIN}/.."],
 }
+
+cc_test {
+    name: "preinit_getauxval_test_helper",
+    host_supported: false,
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["preinit_getauxval_test_helper.cpp"],
+}
+
+cc_test {
+    name: "preinit_syscall_test_helper",
+    host_supported: false,
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["preinit_syscall_test_helper.cpp"],
+}
diff --git a/tests/libs/libs_utils.h b/tests/libs/libs_utils.h
index f11cbe7..7dae241 100644
--- a/tests/libs/libs_utils.h
+++ b/tests/libs/libs_utils.h
@@ -17,13 +17,11 @@
 #ifndef LIBS_UTILS_H
 #define LIBS_UTILS_H
 
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 
-#define CHECK(x)                                                            \
-  do {                                                                      \
-    fprintf(stderr, "CHECK(" #x ") failed at %s:%d\n", __FILE__, __LINE__); \
-    if (!(x)) abort();                                                      \
-  } while (0)
+#define CHECK(e) \
+    ((e) ? static_cast<void>(0) : __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, #e))
 
 #endif  // LIBS_UTILS_H
diff --git a/tests/libs/preinit_getauxval_test_helper.cpp b/tests/libs/preinit_getauxval_test_helper.cpp
new file mode 100644
index 0000000..2a79b97
--- /dev/null
+++ b/tests/libs/preinit_getauxval_test_helper.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 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 <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/auxv.h>
+
+#include "libs_utils.h"
+
+static unsigned long g_AT_RANDOM;
+static unsigned long g_AT_PAGESZ;
+
+static void preinit_ctor() {
+  g_AT_RANDOM = getauxval(AT_RANDOM);
+  g_AT_PAGESZ = getauxval(AT_PAGESZ);
+}
+
+__attribute__((section(".preinit_array"), used)) void (*preinit_ctor_p)(void) = preinit_ctor;
+
+int main() {
+  // Did getauxval during preinit get the same results as getauxval now?
+  CHECK(getauxval(AT_RANDOM) == g_AT_RANDOM);
+  CHECK(getauxval(AT_PAGESZ) == g_AT_PAGESZ);
+  return 0;
+}
diff --git a/tests/libs/preinit_syscall_test_helper.cpp b/tests/libs/preinit_syscall_test_helper.cpp
new file mode 100644
index 0000000..9b6b6df
--- /dev/null
+++ b/tests/libs/preinit_syscall_test_helper.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 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 <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/auxv.h>
+
+#include "libs_utils.h"
+
+static ssize_t g_result;
+static int g_errno;
+
+static void preinit_ctor() {
+  // Can we make a system call?
+  g_result = write(-1, "", 1);
+  g_errno = errno;
+}
+
+__attribute__((section(".preinit_array"), used)) void (*preinit_ctor_p)(void) = preinit_ctor;
+
+int main() {
+  // Did we get the expected failure?
+  CHECK(g_result == -1);
+  CHECK(g_errno == EBADF);
+  return 0;
+}
diff --git a/tests/sys_ptrace_test.cpp b/tests/sys_ptrace_test.cpp
index bce5898..69638be 100644
--- a/tests/sys_ptrace_test.cpp
+++ b/tests/sys_ptrace_test.cpp
@@ -17,6 +17,7 @@
 #include <sys/ptrace.h>
 
 #include <elf.h>
+#include <err.h>
 #include <fcntl.h>
 #include <sched.h>
 #include <sys/prctl.h>
@@ -26,11 +27,16 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include <chrono>
+#include <thread>
+
 #include <gtest/gtest.h>
 
 #include <android-base/macros.h>
 #include <android-base/unique_fd.h>
 
+using namespace std::chrono_literals;
+
 using android::base::unique_fd;
 
 // Host libc does not define this.
@@ -367,31 +373,39 @@
 
 class PtraceResumptionTest : public ::testing::Test {
  public:
+  unique_fd worker_pipe_write;
+
   pid_t worker = -1;
+  pid_t tracer = -1;
+
   PtraceResumptionTest() {
+    unique_fd worker_pipe_read;
+    int pipefd[2];
+    if (pipe2(pipefd, O_CLOEXEC) != 0) {
+      err(1, "failed to create pipe");
+    }
+
+    worker_pipe_read.reset(pipefd[0]);
+    worker_pipe_write.reset(pipefd[1]);
+
+    worker = fork();
+    if (worker == -1) {
+      err(1, "failed to fork worker");
+    } else if (worker == 0) {
+      char buf;
+      worker_pipe_write.reset();
+      TEMP_FAILURE_RETRY(read(worker_pipe_read.get(), &buf, sizeof(buf)));
+      exit(0);
+    }
   }
 
   ~PtraceResumptionTest() {
   }
 
   void AssertDeath(int signo);
-  void Start(std::function<void()> f) {
-    unique_fd worker_pipe_read, worker_pipe_write;
-    int pipefd[2];
-    ASSERT_EQ(0, pipe2(pipefd, O_CLOEXEC));
-    worker_pipe_read.reset(pipefd[0]);
-    worker_pipe_write.reset(pipefd[1]);
 
-    worker = fork();
-    ASSERT_NE(-1, worker);
-    if (worker == 0) {
-      char buf;
-      worker_pipe_write.reset();
-      TEMP_FAILURE_RETRY(read(worker_pipe_read.get(), &buf, sizeof(buf)));
-      exit(0);
-    }
-
-    pid_t tracer = fork();
+  void StartTracer(std::function<void()> f) {
+    tracer = fork();
     ASSERT_NE(-1, tracer);
     if (tracer == 0) {
       f();
@@ -400,26 +414,66 @@
       }
       exit(0);
     }
+  }
+
+  bool WaitForTracer() {
+    if (tracer == -1) {
+      errx(1, "tracer not started");
+    }
 
     int result;
     pid_t rc = waitpid(tracer, &result, 0);
-    ASSERT_EQ(tracer, rc);
-    EXPECT_TRUE(WIFEXITED(result) || WIFSIGNALED(result));
+    if (rc != tracer) {
+      printf("waitpid returned %d (%s)\n", rc, strerror(errno));
+      return false;
+    }
+
+    if (!WIFEXITED(result) && !WIFSIGNALED(result)) {
+      printf("!WIFEXITED && !WIFSIGNALED\n");
+      return false;
+    }
+
     if (WIFEXITED(result)) {
       if (WEXITSTATUS(result) != 0) {
-        FAIL() << "tracer failed";
+        printf("tracer failed\n");
+        return false;
       }
     }
 
-    rc = waitpid(worker, &result, WNOHANG);
-    ASSERT_EQ(0, rc);
+    return true;
+  }
+
+  bool WaitForWorker() {
+    if (worker == -1) {
+      errx(1, "worker not started");
+    }
+
+    int result;
+    pid_t rc = waitpid(worker, &result, WNOHANG);
+    if (rc != 0) {
+      printf("worker exited prematurely\n");
+      return false;
+    }
 
     worker_pipe_write.reset();
 
     rc = waitpid(worker, &result, 0);
-    ASSERT_EQ(worker, rc);
-    EXPECT_TRUE(WIFEXITED(result));
-    EXPECT_EQ(WEXITSTATUS(result), 0);
+    if (rc != worker) {
+      printf("waitpid for worker returned %d (%s)\n", rc, strerror(errno));
+      return false;
+    }
+
+    if (!WIFEXITED(result)) {
+      printf("worker didn't exit\n");
+      return false;
+    }
+
+    if (WEXITSTATUS(result) != 0) {
+      printf("worker exited with status %d\n", WEXITSTATUS(result));
+      return false;
+    }
+
+    return true;
   }
 };
 
@@ -436,22 +490,74 @@
   }
 }
 
+TEST_F(PtraceResumptionTest, smoke) {
+  // Make sure that the worker doesn't exit before the tracer stops tracing.
+  StartTracer([this]() {
+    ASSERT_EQ(0, ptrace(PTRACE_SEIZE, worker, 0, 0)) << strerror(errno);
+    ASSERT_EQ(0, ptrace(PTRACE_INTERRUPT, worker, 0, 0)) << strerror(errno);
+    wait_for_ptrace_stop(worker);
+    std::this_thread::sleep_for(500ms);
+  });
+
+  worker_pipe_write.reset();
+  std::this_thread::sleep_for(250ms);
+
+  int result;
+  ASSERT_EQ(0, waitpid(worker, &result, WNOHANG));
+  ASSERT_TRUE(WaitForTracer());
+  ASSERT_EQ(worker, waitpid(worker, &result, 0));
+}
+
 TEST_F(PtraceResumptionTest, seize) {
-  Start([this]() { ASSERT_EQ(0, ptrace(PTRACE_SEIZE, worker, 0, 0)) << strerror(errno); });
+  StartTracer([this]() { ASSERT_EQ(0, ptrace(PTRACE_SEIZE, worker, 0, 0)) << strerror(errno); });
+  ASSERT_TRUE(WaitForTracer());
+  ASSERT_TRUE(WaitForWorker());
 }
 
 TEST_F(PtraceResumptionTest, seize_interrupt) {
-  Start([this]() {
+  StartTracer([this]() {
     ASSERT_EQ(0, ptrace(PTRACE_SEIZE, worker, 0, 0)) << strerror(errno);
     ASSERT_EQ(0, ptrace(PTRACE_INTERRUPT, worker, 0, 0)) << strerror(errno);
+    wait_for_ptrace_stop(worker);
   });
+  ASSERT_TRUE(WaitForTracer());
+  ASSERT_TRUE(WaitForWorker());
 }
 
 TEST_F(PtraceResumptionTest, seize_interrupt_cont) {
-  Start([this]() {
+  StartTracer([this]() {
     ASSERT_EQ(0, ptrace(PTRACE_SEIZE, worker, 0, 0)) << strerror(errno);
     ASSERT_EQ(0, ptrace(PTRACE_INTERRUPT, worker, 0, 0)) << strerror(errno);
     wait_for_ptrace_stop(worker);
     ASSERT_EQ(0, ptrace(PTRACE_CONT, worker, 0, 0)) << strerror(errno);
   });
+  ASSERT_TRUE(WaitForTracer());
+  ASSERT_TRUE(WaitForWorker());
+}
+
+TEST_F(PtraceResumptionTest, zombie_seize) {
+  StartTracer([this]() { ASSERT_EQ(0, ptrace(PTRACE_SEIZE, worker, 0, 0)) << strerror(errno); });
+  ASSERT_TRUE(WaitForWorker());
+  ASSERT_TRUE(WaitForTracer());
+}
+
+TEST_F(PtraceResumptionTest, zombie_seize_interrupt) {
+  StartTracer([this]() {
+    ASSERT_EQ(0, ptrace(PTRACE_SEIZE, worker, 0, 0)) << strerror(errno);
+    ASSERT_EQ(0, ptrace(PTRACE_INTERRUPT, worker, 0, 0)) << strerror(errno);
+    wait_for_ptrace_stop(worker);
+  });
+  ASSERT_TRUE(WaitForWorker());
+  ASSERT_TRUE(WaitForTracer());
+}
+
+TEST_F(PtraceResumptionTest, zombie_seize_interrupt_cont) {
+  StartTracer([this]() {
+    ASSERT_EQ(0, ptrace(PTRACE_SEIZE, worker, 0, 0)) << strerror(errno);
+    ASSERT_EQ(0, ptrace(PTRACE_INTERRUPT, worker, 0, 0)) << strerror(errno);
+    wait_for_ptrace_stop(worker);
+    ASSERT_EQ(0, ptrace(PTRACE_CONT, worker, 0, 0)) << strerror(errno);
+  });
+  ASSERT_TRUE(WaitForWorker());
+  ASSERT_TRUE(WaitForTracer());
 }
diff --git a/tools/update_headers.sh b/tools/update_headers.sh
deleted file mode 100755
index 0095d50..0000000
--- a/tools/update_headers.sh
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/bin/bash
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-cd $DIR
-
-which versioner >/dev/null 2>&1
-if [ $? -ne 0 ]; then
-  >&2 echo "versioner not in path; run mma in $DIR/versioner"
-  exit 1
-fi
-
-VERSION=$(git rev-parse --short HEAD)
-git diff-index --quiet HEAD
-DIRTY=$?
-git branch -r --contains HEAD | grep -q aosp/master
-SUBMITTED=$?
-
-if [ $DIRTY -ne 0 ]; then
-  >&2 echo "Warning: bionic has uncommitted changes"
-  VERSION="${VERSION}-dirty"
-elif [ $SUBMITTED -ne 0 ]; then
-  >&2 echo "Warning: current HEAD does not exist in aosp/master"
-  VERSION="${VERSION}-unsubmitted"
-fi
-
-PREBUILTS_DIR=$ANDROID_BUILD_TOP/prebuilts/ndk
-BRANCH_NAME=$(git -C $PREBUILTS_DIR symbolic-ref --short -q HEAD)
-if [ $? -ne 0 ]; then
-  BRANCH_NAME=update-bionic-headers-$VERSION
-  echo "prebuilts/ndk has detached head; creating branch $BRANCH_NAME"
-  repo start $BRANCH_NAME $PREBUILTS_DIR
-else
-  echo "prebuilts/ndk already on branch $BRANCH_NAME"
-fi
-
-HEADERS_INSTALL=$PREBUILTS_DIR/headers
-if [ -d "$HEADERS_INSTALL" ]; then
-  git -C $PREBUILTS_DIR rm -r --ignore-unmatch $HEADERS_INSTALL
-  if [ -d $HEADERS_INSTALL ]; then
-    rm -r $HEADERS_INSTALL
-  fi
-fi
-
-versioner -p versioner/platforms versioner/current versioner/dependencies \
-  -o $HEADERS_INSTALL
-if [ $? -ne 0 ]; then
-  >&2 echo "Header preprocessing failed"
-  exit 1
-fi
-
-cp ../libc/NOTICE $PREBUILTS_DIR
-
-git -C $PREBUILTS_DIR add $HEADERS_INSTALL $PREBUILTS_DIR/NOTICE
-git -C $PREBUILTS_DIR commit -m "Update bionic headers to $VERSION."
diff --git a/tools/versioner/dependencies/arm/arch-arm b/tools/versioner/dependencies/arm/arch-arm
deleted file mode 120000
index ed69f41..0000000
--- a/tools/versioner/dependencies/arm/arch-arm
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/arch-arm/include
\ No newline at end of file
diff --git a/tools/versioner/dependencies/arm/kernel_uapi_asm-arm b/tools/versioner/dependencies/arm/kernel_uapi_asm-arm
deleted file mode 120000
index fabed85..0000000
--- a/tools/versioner/dependencies/arm/kernel_uapi_asm-arm
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/kernel/uapi/asm-arm
\ No newline at end of file
diff --git a/tools/versioner/dependencies/arm64/arch-arm64 b/tools/versioner/dependencies/arm64/arch-arm64
deleted file mode 120000
index 21a21d4..0000000
--- a/tools/versioner/dependencies/arm64/arch-arm64
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/arch-arm64/include
\ No newline at end of file
diff --git a/tools/versioner/dependencies/arm64/kernel_uapi_asm-arm64 b/tools/versioner/dependencies/arm64/kernel_uapi_asm-arm64
deleted file mode 120000
index 16e74a3..0000000
--- a/tools/versioner/dependencies/arm64/kernel_uapi_asm-arm64
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/kernel/uapi/asm-arm64
\ No newline at end of file
diff --git a/tools/versioner/dependencies/common/clang-builtins b/tools/versioner/dependencies/common/clang-builtins
deleted file mode 120000
index fc27e65..0000000
--- a/tools/versioner/dependencies/common/clang-builtins
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../external/clang/lib/Headers
\ No newline at end of file
diff --git a/tools/versioner/dependencies/common/kernel_android_uapi b/tools/versioner/dependencies/common/kernel_android_uapi
deleted file mode 120000
index bcf6daa..0000000
--- a/tools/versioner/dependencies/common/kernel_android_uapi
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/kernel/android/uapi
\ No newline at end of file
diff --git a/tools/versioner/dependencies/common/kernel_uapi b/tools/versioner/dependencies/common/kernel_uapi
deleted file mode 120000
index 2a915ef..0000000
--- a/tools/versioner/dependencies/common/kernel_uapi
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/kernel/uapi
\ No newline at end of file
diff --git a/tools/versioner/dependencies/mips/arch-mips b/tools/versioner/dependencies/mips/arch-mips
deleted file mode 120000
index 7f2f104..0000000
--- a/tools/versioner/dependencies/mips/arch-mips
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/arch-mips/include
\ No newline at end of file
diff --git a/tools/versioner/dependencies/mips/kernel_uapi_asm-mips b/tools/versioner/dependencies/mips/kernel_uapi_asm-mips
deleted file mode 120000
index dcd1955..0000000
--- a/tools/versioner/dependencies/mips/kernel_uapi_asm-mips
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/kernel/uapi/asm-mips
\ No newline at end of file
diff --git a/tools/versioner/dependencies/mips64/arch-mips64 b/tools/versioner/dependencies/mips64/arch-mips64
deleted file mode 120000
index 48cea72..0000000
--- a/tools/versioner/dependencies/mips64/arch-mips64
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/arch-mips64/include
\ No newline at end of file
diff --git a/tools/versioner/dependencies/mips64/kernel_uapi_asm-mips b/tools/versioner/dependencies/mips64/kernel_uapi_asm-mips
deleted file mode 120000
index dcd1955..0000000
--- a/tools/versioner/dependencies/mips64/kernel_uapi_asm-mips
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/kernel/uapi/asm-mips
\ No newline at end of file
diff --git a/tools/versioner/dependencies/x86/arch-x86 b/tools/versioner/dependencies/x86/arch-x86
deleted file mode 120000
index d0f016a..0000000
--- a/tools/versioner/dependencies/x86/arch-x86
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/arch-x86/include
\ No newline at end of file
diff --git a/tools/versioner/dependencies/x86/kernel_uapi_asm-x86 b/tools/versioner/dependencies/x86/kernel_uapi_asm-x86
deleted file mode 120000
index 0efae62..0000000
--- a/tools/versioner/dependencies/x86/kernel_uapi_asm-x86
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/kernel/uapi/asm-x86
\ No newline at end of file
diff --git a/tools/versioner/dependencies/x86_64/arch-x86_64 b/tools/versioner/dependencies/x86_64/arch-x86_64
deleted file mode 120000
index deb647d..0000000
--- a/tools/versioner/dependencies/x86_64/arch-x86_64
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/arch-x86_64/include
\ No newline at end of file
diff --git a/tools/versioner/dependencies/x86_64/kernel_uapi_asm-x86 b/tools/versioner/dependencies/x86_64/kernel_uapi_asm-x86
deleted file mode 120000
index 0efae62..0000000
--- a/tools/versioner/dependencies/x86_64/kernel_uapi_asm-x86
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libc/kernel/uapi/asm-x86
\ No newline at end of file
diff --git a/tools/versioner/preupload.sh b/tools/versioner/preupload.sh
deleted file mode 100755
index 45d6cca..0000000
--- a/tools/versioner/preupload.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-if ! which versioner > /dev/null; then
-  echo "versioner not found (lunch and mma in bionic)"
-  exit 1
-fi
-
-versioner -r arm -r arm64
-exit $?
diff --git a/tools/versioner/src/Android.bp b/tools/versioner/src/Android.bp
index d1362d0..c5afa56 100644
--- a/tools/versioner/src/Android.bp
+++ b/tools/versioner/src/Android.bp
@@ -41,18 +41,8 @@
                 "-fno-rtti",
             ],
         },
-        darwin: {
-            enabled: false,
-        },
         windows: {
             enabled: false,
         },
     },
-
-    product_variables: {
-        unbundled_build: {
-            // Only do this when Clang is available.
-            enabled: false,
-        },
-    },
 }