Merge "Adopt remaining MTE string routines."
diff --git a/apex/Android.bp b/apex/Android.bp
index 8c8853f..ce9d82b 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -62,3 +62,13 @@
         "crtend_so",
     ],
 }
+
+module_exports {
+    name: "runtime-module-host-exports",
+    defaults: ["linux_bionic_supported"],
+    device_supported: false,
+
+    native_binaries: [
+        "linker",
+    ],
+}
diff --git a/libc/Android.bp b/libc/Android.bp
index 08b3db3..537b8cc 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -4,6 +4,7 @@
     "async_safe/async_safe_log.cpp",
     "bionic/ether_aton.c",
     "bionic/ether_ntoa.c",
+    "bionic/exit.cpp",
     "bionic/fts.c",
     "bionic/initgroups.c",
     "bionic/isatty.c",
@@ -17,7 +18,6 @@
     "stdio/stdio_ext.cpp",
     "stdio/vfscanf.cpp",
     "stdio/vfwscanf.c",
-    "stdlib/exit.c",
 ]
 
 // off64_t/time64_t support on LP32.
diff --git a/libc/async_safe/include/async_safe/CHECK.h b/libc/async_safe/include/async_safe/CHECK.h
index bec89a3..46d460c 100644
--- a/libc/async_safe/include/async_safe/CHECK.h
+++ b/libc/async_safe/include/async_safe/CHECK.h
@@ -36,12 +36,12 @@
 
 // TODO: replace this with something more like <android-base/logging.h>'s family of macros.
 
-#define CHECK(predicate) \
-  do { \
-    if (!(predicate)) { \
-      async_safe_fatal("%s:%d: %s CHECK '" #predicate "' failed", \
-          __FILE__, __LINE__, __FUNCTION__); \
-    } \
-  } while(0)
+#define CHECK(predicate)                                                                \
+  do {                                                                                  \
+    if (!(predicate)) {                                                                 \
+      async_safe_fatal("%s:%d: %s CHECK '%s' failed", __FILE__, __LINE__, __FUNCTION__, \
+                       #predicate);                                                     \
+    }                                                                                   \
+  } while (0)
 
 __END_DECLS
diff --git a/libc/bionic/exec.cpp b/libc/bionic/exec.cpp
index 3309585..fd2c401 100644
--- a/libc/bionic/exec.cpp
+++ b/libc/bionic/exec.cpp
@@ -44,9 +44,10 @@
 
 extern "C" char** environ;
 
-enum ExecVariant { kIsExecL, kIsExecLE, kIsExecLP };
+enum { ExecL, ExecLE, ExecLP };
 
-static int __execl(const char* name, const char* argv0, ExecVariant variant, va_list ap) {
+template <int variant>
+static int __execl(const char* name, const char* argv0, va_list ap) {
   // Count the arguments.
   va_list count_ap;
   va_copy(count_ap, ap);
@@ -65,17 +66,17 @@
   }
 
   // Collect the argp too.
-  char** argp = (variant == kIsExecLE) ? va_arg(ap, char**) : environ;
+  char** argp = (variant == ExecLE) ? va_arg(ap, char**) : environ;
 
   va_end(ap);
 
-  return (variant == kIsExecLP) ? execvp(name, argv) : execve(name, argv, argp);
+  return (variant == ExecLP) ? execvp(name, argv) : execve(name, argv, argp);
 }
 
 int execl(const char* name, const char* arg, ...) {
   va_list ap;
   va_start(ap, arg);
-  int result = __execl(name, arg, kIsExecL, ap);
+  int result = __execl<ExecL>(name, arg, ap);
   va_end(ap);
   return result;
 }
@@ -83,7 +84,7 @@
 int execle(const char* name, const char* arg, ...) {
   va_list ap;
   va_start(ap, arg);
-  int result = __execl(name, arg, kIsExecLE, ap);
+  int result = __execl<ExecLE>(name, arg, ap);
   va_end(ap);
   return result;
 }
@@ -91,7 +92,7 @@
 int execlp(const char* name, const char* arg, ...) {
   va_list ap;
   va_start(ap, arg);
-  int result = __execl(name, arg, kIsExecLP, ap);
+  int result = __execl<ExecLP>(name, arg, ap);
   va_end(ap);
   return result;
 }
diff --git a/libc/bionic/exit.cpp b/libc/bionic/exit.cpp
new file mode 100644
index 0000000..a5aed78
--- /dev/null
+++ b/libc/bionic/exit.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "private/bionic_defs.h"
+
+extern "C" void __cxa_finalize(void* dso_handle);
+extern "C" void __cxa_thread_finalize();
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+void exit(int status) {
+  __cxa_thread_finalize();
+  __cxa_finalize(nullptr);
+  _exit(status);
+}
diff --git a/libc/bionic/fork.cpp b/libc/bionic/fork.cpp
index cda5e85..3814ed0 100644
--- a/libc/bionic/fork.cpp
+++ b/libc/bionic/fork.cpp
@@ -34,23 +34,27 @@
 #include "pthread_internal.h"
 
 __BIONIC_WEAK_FOR_NATIVE_BRIDGE
+int __clone_for_fork() {
+  pthread_internal_t* self = __get_thread();
+
+  int result = clone(nullptr, nullptr, (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD),
+                     nullptr, nullptr, nullptr, &(self->tid));
+
+  if (result == 0) {
+    // Update the cached pid in child, since clone() will not set it directly (as
+    // self->tid is updated by the kernel).
+    self->set_cached_pid(gettid());
+  }
+
+  return result;
+}
+
 int fork() {
   __bionic_atfork_run_prepare();
 
-  pthread_internal_t* self = __get_thread();
+  int result = __clone_for_fork();
 
-  int result = clone(nullptr,
-                     nullptr,
-                     (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD),
-                     nullptr,
-                     nullptr,
-                     nullptr,
-                     &(self->tid));
   if (result == 0) {
-    // Update the cached pid, since clone() will not set it directly (as
-    // self->tid is updated by the kernel).
-    self->set_cached_pid(gettid());
-
     // Disable fdsan post-fork, so we don't falsely trigger on processes that
     // fork, close all of their fds blindly, and then exec.
     android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_DISABLED);
diff --git a/libc/bionic/pthread_attr.cpp b/libc/bionic/pthread_attr.cpp
index 3c4b169..1551c1f 100644
--- a/libc/bionic/pthread_attr.cpp
+++ b/libc/bionic/pthread_attr.cpp
@@ -30,13 +30,13 @@
 
 #include <inttypes.h>
 #include <stdio.h>
+#include <string.h>
 #include <sys/resource.h>
 #include <unistd.h>
 
 #include <async_safe/log.h>
 
 #include "private/bionic_defs.h"
-#include "private/bionic_string_utils.h"
 #include "private/ErrnoRestorer.h"
 #include "pthread_internal.h"
 
diff --git a/libc/kernel/tools/generate_uapi_headers.sh b/libc/kernel/tools/generate_uapi_headers.sh
index fde4a3d..4e7d2af 100755
--- a/libc/kernel/tools/generate_uapi_headers.sh
+++ b/libc/kernel/tools/generate_uapi_headers.sh
@@ -264,11 +264,6 @@
                  "${ANDROID_KERNEL_DIR}/uapi/asm-${arch}/asm"
 done
 
-# The arm kvm.h uapi header was removed from arch so copy it from the
-# tools/arch directory.
-cp "${KERNEL_DIR}/tools/arch/arm/include/uapi/asm/kvm.h" \
-   "${ANDROID_KERNEL_DIR}/uapi/asm-arm/asm"
-
 # Verify if modified headers have changed.
 verify_modified_hdrs "${KERNEL_DIR}/include/scsi" \
                      "${ANDROID_KERNEL_DIR}/scsi" \
diff --git a/libc/kernel/uapi/asm-arm/asm/kvm.h b/libc/kernel/uapi/asm-arm/asm/kvm.h
deleted file mode 100644
index 6a6d963..0000000
--- a/libc/kernel/uapi/asm-arm/asm/kvm.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- ***   This header was automatically generated from a Linux kernel header
- ***   of the same name, to make information necessary for userspace to
- ***   call into the kernel available to libc.  It contains only constants,
- ***   structures, and macros generated from the original header, and thus,
- ***   contains no copyrightable information.
- ***
- ***   To edit the content of this header, modify the corresponding
- ***   source file (e.g. under external/kernel-headers/original/) then
- ***   run bionic/libc/kernel/tools/update_all.py
- ***
- ***   Any manual change here will be lost the next time this script will
- ***   be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef __ARM_KVM_H__
-#define __ARM_KVM_H__
-#include <linux/types.h>
-#include <linux/psci.h>
-#include <asm/ptrace.h>
-#define __KVM_HAVE_GUEST_DEBUG
-#define __KVM_HAVE_IRQ_LINE
-#define __KVM_HAVE_READONLY_MEM
-#define __KVM_HAVE_VCPU_EVENTS
-#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
-#define KVM_REG_SIZE(id) (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
-#define KVM_ARM_SVC_sp svc_regs[0]
-#define KVM_ARM_SVC_lr svc_regs[1]
-#define KVM_ARM_SVC_spsr svc_regs[2]
-#define KVM_ARM_ABT_sp abt_regs[0]
-#define KVM_ARM_ABT_lr abt_regs[1]
-#define KVM_ARM_ABT_spsr abt_regs[2]
-#define KVM_ARM_UND_sp und_regs[0]
-#define KVM_ARM_UND_lr und_regs[1]
-#define KVM_ARM_UND_spsr und_regs[2]
-#define KVM_ARM_IRQ_sp irq_regs[0]
-#define KVM_ARM_IRQ_lr irq_regs[1]
-#define KVM_ARM_IRQ_spsr irq_regs[2]
-#define KVM_ARM_FIQ_r8 fiq_regs[0]
-#define KVM_ARM_FIQ_r9 fiq_regs[1]
-#define KVM_ARM_FIQ_r10 fiq_regs[2]
-#define KVM_ARM_FIQ_fp fiq_regs[3]
-#define KVM_ARM_FIQ_ip fiq_regs[4]
-#define KVM_ARM_FIQ_sp fiq_regs[5]
-#define KVM_ARM_FIQ_lr fiq_regs[6]
-#define KVM_ARM_FIQ_spsr fiq_regs[7]
-struct kvm_regs {
-  struct pt_regs usr_regs;
-  unsigned long svc_regs[3];
-  unsigned long abt_regs[3];
-  unsigned long und_regs[3];
-  unsigned long irq_regs[3];
-  unsigned long fiq_regs[8];
-};
-#define KVM_ARM_TARGET_CORTEX_A15 0
-#define KVM_ARM_TARGET_CORTEX_A7 1
-#define KVM_ARM_NUM_TARGETS 2
-#define KVM_ARM_DEVICE_TYPE_SHIFT 0
-#define KVM_ARM_DEVICE_TYPE_MASK (0xffff << KVM_ARM_DEVICE_TYPE_SHIFT)
-#define KVM_ARM_DEVICE_ID_SHIFT 16
-#define KVM_ARM_DEVICE_ID_MASK (0xffff << KVM_ARM_DEVICE_ID_SHIFT)
-#define KVM_ARM_DEVICE_VGIC_V2 0
-#define KVM_VGIC_V2_ADDR_TYPE_DIST 0
-#define KVM_VGIC_V2_ADDR_TYPE_CPU 1
-#define KVM_VGIC_V2_DIST_SIZE 0x1000
-#define KVM_VGIC_V2_CPU_SIZE 0x2000
-#define KVM_VGIC_V3_ADDR_TYPE_DIST 2
-#define KVM_VGIC_V3_ADDR_TYPE_REDIST 3
-#define KVM_VGIC_ITS_ADDR_TYPE 4
-#define KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION 5
-#define KVM_VGIC_V3_DIST_SIZE SZ_64K
-#define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K)
-#define KVM_VGIC_V3_ITS_SIZE (2 * SZ_64K)
-#define KVM_ARM_VCPU_POWER_OFF 0
-#define KVM_ARM_VCPU_PSCI_0_2 1
-struct kvm_vcpu_init {
-  __u32 target;
-  __u32 features[7];
-};
-struct kvm_sregs {
-};
-struct kvm_fpu {
-};
-struct kvm_guest_debug_arch {
-};
-struct kvm_debug_exit_arch {
-};
-struct kvm_sync_regs {
-  __u64 device_irq_level;
-};
-struct kvm_arch_memory_slot {
-};
-struct kvm_vcpu_events {
-  struct {
-    __u8 serror_pending;
-    __u8 serror_has_esr;
-    __u8 ext_dabt_pending;
-    __u8 pad[5];
-    __u64 serror_esr;
-  } exception;
-  __u32 reserved[12];
-};
-#define KVM_REG_ARM_COPROC_MASK 0x000000000FFF0000
-#define KVM_REG_ARM_COPROC_SHIFT 16
-#define KVM_REG_ARM_32_OPC2_MASK 0x0000000000000007
-#define KVM_REG_ARM_32_OPC2_SHIFT 0
-#define KVM_REG_ARM_OPC1_MASK 0x0000000000000078
-#define KVM_REG_ARM_OPC1_SHIFT 3
-#define KVM_REG_ARM_CRM_MASK 0x0000000000000780
-#define KVM_REG_ARM_CRM_SHIFT 7
-#define KVM_REG_ARM_32_CRN_MASK 0x0000000000007800
-#define KVM_REG_ARM_32_CRN_SHIFT 11
-#define KVM_REG_ARM_SECURE_MASK 0x0000000010000000
-#define KVM_REG_ARM_SECURE_SHIFT 28
-#define ARM_CP15_REG_SHIFT_MASK(x,n) (((x) << KVM_REG_ARM_ ##n ##_SHIFT) & KVM_REG_ARM_ ##n ##_MASK)
-#define __ARM_CP15_REG(op1,crn,crm,op2) (KVM_REG_ARM | (15 << KVM_REG_ARM_COPROC_SHIFT) | ARM_CP15_REG_SHIFT_MASK(op1, OPC1) | ARM_CP15_REG_SHIFT_MASK(crn, 32_CRN) | ARM_CP15_REG_SHIFT_MASK(crm, CRM) | ARM_CP15_REG_SHIFT_MASK(op2, 32_OPC2))
-#define ARM_CP15_REG32(...) (__ARM_CP15_REG(__VA_ARGS__) | KVM_REG_SIZE_U32)
-#define __ARM_CP15_REG64(op1,crm) (__ARM_CP15_REG(op1, 0, crm, 0) | KVM_REG_SIZE_U64)
-#define ARM_CP15_REG64(...) __ARM_CP15_REG64(__VA_ARGS__)
-#define KVM_REG_ARM_PTIMER_CTL ARM_CP15_REG32(0, 14, 2, 1)
-#define KVM_REG_ARM_PTIMER_CNT ARM_CP15_REG64(0, 14)
-#define KVM_REG_ARM_PTIMER_CVAL ARM_CP15_REG64(2, 14)
-#define KVM_REG_ARM_TIMER_CTL ARM_CP15_REG32(0, 14, 3, 1)
-#define KVM_REG_ARM_TIMER_CNT ARM_CP15_REG64(1, 14)
-#define KVM_REG_ARM_TIMER_CVAL ARM_CP15_REG64(3, 14)
-#define KVM_REG_ARM_CORE (0x0010 << KVM_REG_ARM_COPROC_SHIFT)
-#define KVM_REG_ARM_CORE_REG(name) (offsetof(struct kvm_regs, name) / 4)
-#define KVM_REG_ARM_DEMUX (0x0011 << KVM_REG_ARM_COPROC_SHIFT)
-#define KVM_REG_ARM_DEMUX_ID_MASK 0x000000000000FF00
-#define KVM_REG_ARM_DEMUX_ID_SHIFT 8
-#define KVM_REG_ARM_DEMUX_ID_CCSIDR (0x00 << KVM_REG_ARM_DEMUX_ID_SHIFT)
-#define KVM_REG_ARM_DEMUX_VAL_MASK 0x00000000000000FF
-#define KVM_REG_ARM_DEMUX_VAL_SHIFT 0
-#define KVM_REG_ARM_VFP (0x0012 << KVM_REG_ARM_COPROC_SHIFT)
-#define KVM_REG_ARM_VFP_MASK 0x000000000000FFFF
-#define KVM_REG_ARM_VFP_BASE_REG 0x0
-#define KVM_REG_ARM_VFP_FPSID 0x1000
-#define KVM_REG_ARM_VFP_FPSCR 0x1001
-#define KVM_REG_ARM_VFP_MVFR1 0x1006
-#define KVM_REG_ARM_VFP_MVFR0 0x1007
-#define KVM_REG_ARM_VFP_FPEXC 0x1008
-#define KVM_REG_ARM_VFP_FPINST 0x1009
-#define KVM_REG_ARM_VFP_FPINST2 0x100A
-#define KVM_REG_ARM_FW (0x0014 << KVM_REG_ARM_COPROC_SHIFT)
-#define KVM_REG_ARM_FW_REG(r) (KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_FW | ((r) & 0xffff))
-#define KVM_REG_ARM_PSCI_VERSION KVM_REG_ARM_FW_REG(0)
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1 KVM_REG_ARM_FW_REG(1)
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL 0
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL 1
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED 2
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2 KVM_REG_ARM_FW_REG(2)
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL 0
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN 1
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL 2
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED 3
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED (1U << 4)
-#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
-#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
-#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2
-#define KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
-#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
-#define KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT 32
-#define KVM_DEV_ARM_VGIC_V3_MPIDR_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
-#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
-#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
-#define KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff)
-#define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
-#define KVM_DEV_ARM_VGIC_GRP_CTRL 4
-#define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
-#define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
-#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7
-#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8
-#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
-#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
-#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
-#define VGIC_LEVEL_INFO_LINE_LEVEL 0
-#define KVM_ARM_VCPU_PMU_V3_CTRL 0
-#define KVM_ARM_VCPU_PMU_V3_IRQ 0
-#define KVM_ARM_VCPU_PMU_V3_INIT 1
-#define KVM_ARM_VCPU_TIMER_CTRL 1
-#define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0
-#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
-#define KVM_DEV_ARM_VGIC_CTRL_INIT 0
-#define KVM_DEV_ARM_ITS_SAVE_TABLES 1
-#define KVM_DEV_ARM_ITS_RESTORE_TABLES 2
-#define KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3
-#define KVM_DEV_ARM_ITS_CTRL_RESET 4
-#define KVM_ARM_IRQ_VCPU2_SHIFT 28
-#define KVM_ARM_IRQ_VCPU2_MASK 0xf
-#define KVM_ARM_IRQ_TYPE_SHIFT 24
-#define KVM_ARM_IRQ_TYPE_MASK 0xf
-#define KVM_ARM_IRQ_VCPU_SHIFT 16
-#define KVM_ARM_IRQ_VCPU_MASK 0xff
-#define KVM_ARM_IRQ_NUM_SHIFT 0
-#define KVM_ARM_IRQ_NUM_MASK 0xffff
-#define KVM_ARM_IRQ_TYPE_CPU 0
-#define KVM_ARM_IRQ_TYPE_SPI 1
-#define KVM_ARM_IRQ_TYPE_PPI 2
-#define KVM_ARM_IRQ_CPU_IRQ 0
-#define KVM_ARM_IRQ_CPU_FIQ 1
-#define KVM_ARM_IRQ_GIC_MAX 127
-#define KVM_NR_IRQCHIPS 1
-#define KVM_PSCI_FN_BASE 0x95c1ba5e
-#define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
-#define KVM_PSCI_FN_CPU_SUSPEND KVM_PSCI_FN(0)
-#define KVM_PSCI_FN_CPU_OFF KVM_PSCI_FN(1)
-#define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2)
-#define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
-#define KVM_PSCI_RET_SUCCESS PSCI_RET_SUCCESS
-#define KVM_PSCI_RET_NI PSCI_RET_NOT_SUPPORTED
-#define KVM_PSCI_RET_INVAL PSCI_RET_INVALID_PARAMS
-#define KVM_PSCI_RET_DENIED PSCI_RET_DENIED
-#endif
diff --git a/libc/private/WriteProtected.h b/libc/private/WriteProtected.h
index 8f5b32d..746f72a 100644
--- a/libc/private/WriteProtected.h
+++ b/libc/private/WriteProtected.h
@@ -40,23 +40,11 @@
 // explicitly.
 template <typename T>
 class WriteProtected {
+ public:
   static_assert(sizeof(T) < PAGE_SIZE,
                 "WriteProtected only supports contents up to PAGE_SIZE");
   static_assert(__is_pod(T), "WriteProtected only supports POD contents");
 
-  WriteProtectedContents<T> contents;
-
-  int set_protection(int prot) {
-    auto addr = &contents;
-#if __has_feature(hwaddress_sanitizer)
-    // The mprotect system call does not currently untag pointers, so do it
-    // ourselves.
-    addr = untag_address(addr);
-#endif
-    return mprotect(reinterpret_cast<void*>(addr), PAGE_SIZE, prot);
-  }
-
- public:
   WriteProtected() = default;
   BIONIC_DISALLOW_COPY_AND_ASSIGN(WriteProtected);
 
@@ -64,10 +52,7 @@
     // Not strictly necessary, but this will hopefully segfault if we initialize
     // multiple times by accident.
     memset(&contents, 0, sizeof(contents));
-
-    if (set_protection(PROT_READ)) {
-      async_safe_fatal("failed to make WriteProtected nonwritable in initialize");
-    }
+    set_protection(PROT_READ);
   }
 
   const T* operator->() {
@@ -80,14 +65,23 @@
 
   template <typename Mutator>
   void mutate(Mutator mutator) {
-    if (set_protection(PROT_READ | PROT_WRITE) != 0) {
-      async_safe_fatal("failed to make WriteProtected writable in mutate: %s",
-                       strerror(errno));
-    }
+    set_protection(PROT_READ | PROT_WRITE);
     mutator(&contents.value);
-    if (set_protection(PROT_READ) != 0) {
-      async_safe_fatal("failed to make WriteProtected nonwritable in mutate: %s",
-                       strerror(errno));
+    set_protection(PROT_READ);
+  }
+
+ private:
+  WriteProtectedContents<T> contents;
+
+  void set_protection(int prot) {
+    auto addr = &contents;
+#if __has_feature(hwaddress_sanitizer)
+    // The mprotect system call does not currently untag pointers, so do it
+    // ourselves.
+    addr = untag_address(addr);
+#endif
+    if (mprotect(reinterpret_cast<void*>(addr), PAGE_SIZE, prot) == -1) {
+      async_safe_fatal("WriteProtected mprotect %x failed: %s", prot, strerror(errno));
     }
   }
 };
diff --git a/libc/private/bionic_fortify.h b/libc/private/bionic_fortify.h
index 3c3292e..df83360 100644
--- a/libc/private/bionic_fortify.h
+++ b/libc/private/bionic_fortify.h
@@ -35,7 +35,11 @@
 
 #include <async_safe/log.h>
 
-static inline __noreturn void __fortify_fatal(const char* fmt, ...) {
+//
+// LLVM can't inline variadic functions, and we don't want one definition of
+// this per #include in libc.so, so no `static`.
+//
+inline __noreturn __printflike(1, 2) void __fortify_fatal(const char* fmt, ...) {
   va_list args;
   va_start(args, fmt);
   async_safe_fatal_va_list("FORTIFY", fmt, args);
@@ -52,7 +56,7 @@
     __fortify_fatal("%s: file descriptor %d < 0", fn, fd);
   }
   if (__predict_false(fd >= FD_SETSIZE)) {
-    __fortify_fatal("%s: file descriptor %d >= FD_SETSIZE %zu", fn, fd, FD_SETSIZE);
+    __fortify_fatal("%s: file descriptor %d >= FD_SETSIZE %d", fn, fd, FD_SETSIZE);
   }
   if (__predict_false(set_size < sizeof(fd_set))) {
     __fortify_fatal("%s: set size %zu is too small to be an fd_set", fn, set_size);
diff --git a/libc/private/bionic_string_utils.h b/libc/private/bionic_string_utils.h
deleted file mode 100644
index ab0eccf..0000000
--- a/libc/private/bionic_string_utils.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef _BIONIC_STRING_UTILS_H_
-#define _BIONIC_STRING_UTILS_H_
-
-#include <string.h>
-
-static inline bool ends_with(const char* s1, const char* s2) {
-  size_t s1_length = strlen(s1);
-  size_t s2_length = strlen(s2);
-  if (s2_length > s1_length) {
-    return false;
-  }
-  return memcmp(s1 + (s1_length - s2_length), s2, s2_length) == 0;
-}
-
-#endif // _BIONIC_STRING_UTILS_H_
diff --git a/libc/stdlib/exit.c b/libc/stdlib/exit.c
deleted file mode 100644
index e301a2a..0000000
--- a/libc/stdlib/exit.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*-
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <unistd.h>
-
-#include "private/bionic_defs.h"
-
-extern void __cxa_finalize(void* dso_handle);
-extern void __cxa_thread_finalize();
-
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-void exit(int status) {
-  __cxa_thread_finalize();
-  __cxa_finalize(NULL);
-  _exit(status);
-}
diff --git a/linker/linker_block_allocator.cpp b/linker/linker_block_allocator.cpp
index 1e2f9a2..5b68b1d 100644
--- a/linker/linker_block_allocator.cpp
+++ b/linker/linker_block_allocator.cpp
@@ -27,12 +27,15 @@
  */
 
 #include "linker_block_allocator.h"
+
 #include <inttypes.h>
 #include <string.h>
 #include <sys/mman.h>
 #include <sys/prctl.h>
 #include <unistd.h>
 
+#include "linker_debug.h"
+
 static constexpr size_t kAllocateSize = PAGE_SIZE * 100;
 static_assert(kAllocateSize % PAGE_SIZE == 0, "Invalid kAllocateSize.");
 
@@ -88,16 +91,10 @@
   }
 
   LinkerBlockAllocatorPage* page = find_page(block);
-
-  if (page == nullptr) {
-    abort();
-  }
+  CHECK(page != nullptr);
 
   ssize_t offset = reinterpret_cast<uint8_t*>(block) - page->bytes;
-
-  if (offset % block_size_ != 0) {
-    abort();
-  }
+  CHECK((offset % block_size_) == 0);
 
   memset(block, 0, block_size_);
 
@@ -114,7 +111,7 @@
 void LinkerBlockAllocator::protect_all(int prot) {
   for (LinkerBlockAllocatorPage* page = page_list_; page != nullptr; page = page->next) {
     if (mprotect(page, kAllocateSize, prot) == -1) {
-      abort();
+      async_safe_fatal("mprotect(%p, %zu, %d) failed: %m", page, kAllocateSize, prot);
     }
   }
 }
@@ -125,10 +122,7 @@
 
   LinkerBlockAllocatorPage* page = reinterpret_cast<LinkerBlockAllocatorPage*>(
       mmap(nullptr, kAllocateSize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0));
-
-  if (page == MAP_FAILED) {
-    abort(); // oom
-  }
+  CHECK(page != MAP_FAILED);
 
   prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, kAllocateSize, "linker_alloc");
 
@@ -143,9 +137,7 @@
 }
 
 LinkerBlockAllocatorPage* LinkerBlockAllocator::find_page(void* block) {
-  if (block == nullptr) {
-    abort();
-  }
+  CHECK(block != nullptr);
 
   LinkerBlockAllocatorPage* page = page_list_;
   while (page != nullptr) {
@@ -157,7 +149,7 @@
     page = page->next;
   }
 
-  abort();
+  async_safe_fatal("couldn't find page for %p", block);
 }
 
 void LinkerBlockAllocator::purge() {
diff --git a/tests/leak_test.cpp b/tests/leak_test.cpp
index e0a3d57..4ebf41f 100644
--- a/tests/leak_test.cpp
+++ b/tests/leak_test.cpp
@@ -109,23 +109,21 @@
 
 // http://b/36045112
 TEST(pthread_leak, join) {
+  SKIP_WITH_NATIVE_BRIDGE;  // http://b/37920774
+
   LeakChecker lc;
 
-  for (size_t pass = 0; pass < 2; ++pass) {
-    for (int i = 0; i < 100; ++i) {
-      pthread_t thread;
-      ASSERT_EQ(0, pthread_create(&thread, nullptr, [](void*) -> void* { return nullptr; }, nullptr));
-      ASSERT_EQ(0, pthread_join(thread, nullptr));
-    }
-
-    // A native bridge implementation might need a warm up pass to reach a steady state.
-    // http://b/37920774.
-    if (pass == 0) lc.Reset();
+  for (int i = 0; i < 100; ++i) {
+    pthread_t thread;
+    ASSERT_EQ(0, pthread_create(&thread, nullptr, [](void*) -> void* { return nullptr; }, nullptr));
+    ASSERT_EQ(0, pthread_join(thread, nullptr));
   }
 }
 
 // http://b/36045112
 TEST(pthread_leak, detach) {
+  SKIP_WITH_NATIVE_BRIDGE;  // http://b/37920774
+
   LeakChecker lc;
 
   // Ancient devices with only 2 cores need a lower limit.
@@ -158,8 +156,7 @@
 
     WaitUntilAllThreadsExited(tids, thread_count);
 
-    // A native bridge implementation might need a warm up pass to reach a steady state.
-    // http://b/37920774.
+    // TODO(b/158573595): the test is flaky without the warmup pass.
     if (pass == 0) lc.Reset();
   }
 }
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index d825738..851b86f 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -2821,6 +2821,9 @@
 }
 
 TEST(pthread, pthread_create__mmap_failures) {
+  // After thread is successfully created, native_bridge might need more memory to run it.
+  SKIP_WITH_NATIVE_BRIDGE;
+
   pthread_attr_t attr;
   ASSERT_EQ(0, pthread_attr_init(&attr));
   ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED));
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 378b4ac..74d691d 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -1005,3 +1005,7 @@
   GTEST_SKIP() << "glibc doesn't have timespec_get until 2.21";
 #endif
 }
+
+TEST(time, difftime) {
+  ASSERT_EQ(1.0, difftime(1, 0));
+}
diff --git a/tests/utils.h b/tests/utils.h
index a9b8513..c1b7f65 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -26,6 +26,10 @@
 #include <unistd.h>
 
 #if defined(__BIONIC__)
+#include <sys/system_properties.h>
+#endif
+
+#if defined(__BIONIC__)
 #include <bionic/macros.h>
 #else
 #define untag_address(p) p
@@ -72,6 +76,21 @@
 
 #define SKIP_WITH_HWASAN if (running_with_hwasan()) GTEST_SKIP()
 
+static inline bool running_with_native_bridge() {
+#if defined(__BIONIC__)
+#if defined(__arm__)
+  static const prop_info* pi = __system_property_find("ro.dalvik.vm.isa.arm");
+  return pi != nullptr;
+#elif defined(__aarch64__)
+  static const prop_info* pi = __system_property_find("ro.dalvik.vm.isa.arm64");
+  return pi != nullptr;
+#endif
+#endif
+  return false;
+}
+
+#define SKIP_WITH_NATIVE_BRIDGE if (running_with_native_bridge()) GTEST_SKIP()
+
 #if defined(__linux__)
 
 #include <sys/sysmacros.h>