Merge "Fix the adb command to push the memory trace files."
diff --git a/benchmarks/linker_relocation/Android.bp b/benchmarks/linker_relocation/Android.bp
index b41d093..b78eb8e 100644
--- a/benchmarks/linker_relocation/Android.bp
+++ b/benchmarks/linker_relocation/Android.bp
@@ -32,7 +32,6 @@
     name: "linker_reloc_bench_headers",
     defaults: ["bionic_spawn_benchmark_targets"],
     export_include_dirs: ["include"],
-    bazel_module: { bp2build_available: true },
 }
 
 // TODO: This benchmark doesn't work with TradeFed/atest because it doesn't copy its test libraries
diff --git a/libc/Android.bp b/libc/Android.bp
index 4084b96..ba51b0e 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1028,9 +1028,7 @@
         "bionic/arpa_inet.cpp",
         "bionic/assert.cpp",
         "bionic/atof.cpp",
-        "bionic/bind.cpp",
         "bionic/bionic_allocator.cpp",
-        "bionic/bionic_appcompat.cpp",
         "bionic/bionic_arc4random.cpp",
         "bionic/bionic_futex.cpp",
         "bionic/bionic_netlink.cpp",
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index d263508..391e7af 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -113,7 +113,7 @@
 int         msync(const void*, size_t, int)    all
 int         mprotect(const void*, size_t, int)  all
 int         madvise(void*, size_t, int)  all
-int         process_madvise(int, const struct iovec*, size_t, int, unsigned int)     all
+ssize_t     process_madvise(int, const struct iovec*, size_t, int, unsigned int)     all
 int mlock(const void* addr, size_t len)    all
 int mlock2(const void* addr, size_t len, int flags)    all
 int         munlock(const void* addr, size_t len)   all
@@ -245,7 +245,7 @@
 # sockets
 int           __socket:socket(int, int, int)              arm,lp64
 int           __socketpair:socketpair(int, int, int, int*)    arm,lp64
-int           __bind:bind(int, struct sockaddr*, socklen_t)  arm,lp64
+int           bind(int, struct sockaddr*, socklen_t)  arm,lp64
 int           __connect:connect(int, struct sockaddr*, socklen_t)   arm,lp64
 int           listen(int, int)                   arm,lp64
 int           __accept4:accept4(int, struct sockaddr*, socklen_t*, int)  arm,lp64
@@ -263,7 +263,7 @@
 
 # sockets for x86. These are done as an "indexed" call to socketcall syscall.
 int           __socket:socketcall:1(int, int, int) x86
-int           __bind:socketcall:2(int, struct sockaddr*, int)  x86
+int           bind:socketcall:2(int, struct sockaddr*, int)  x86
 int           __connect:socketcall:3(int, struct sockaddr*, socklen_t)   x86
 int           listen:socketcall:4(int, int)                   x86
 int           getsockname:socketcall:6(int, struct sockaddr*, socklen_t*)  x86
diff --git a/libc/arch-arm/bionic/setjmp.S b/libc/arch-arm/bionic/setjmp.S
index 5fbcaf3..2579143 100644
--- a/libc/arch-arm/bionic/setjmp.S
+++ b/libc/arch-arm/bionic/setjmp.S
@@ -87,28 +87,6 @@
   b sigsetjmp
 END(_setjmp)
 
-#define MANGLE_REGISTERS 1
-#define USE_CHECKSUM 1
-
-.macro m_mangle_registers reg
-#if MANGLE_REGISTERS
-  eor r4, r4, \reg
-  eor r5, r5, \reg
-  eor r6, r6, \reg
-  eor r7, r7, \reg
-  eor r8, r8, \reg
-  eor r9, r9, \reg
-  eor r10, r10, \reg
-  eor r11, r11, \reg
-  eor r13, r13, \reg
-  eor r14, r14, \reg
-#endif
-.endm
-
-.macro m_unmangle_registers reg
-  m_mangle_registers \reg
-.endm
-
 .macro m_calculate_checksum dst, src, scratch
   mov \dst, #0
   .irp i,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28
@@ -167,12 +145,30 @@
 
   // Save core registers.
   add r1, r0, #(_JB_CORE_BASE * 4)
-  m_mangle_registers r2
-
-  // ARM deprecates using sp in the register list for stmia.
-  stmia r1, {r4-r11, lr}
-  str sp, [r1, #(9 * 4)]
-  m_unmangle_registers r2
+  // Mangle the easy registers in-place, write them out in one go, and unmangle
+  // them again.
+  eor r4, r4, r2
+  eor r5, r5, r2
+  eor r6, r6, r2
+  eor r7, r7, r2
+  eor r8, r8, r2
+  eor r9, r9, r2
+  eor r10, r10, r2
+  eor r11, r11, r2
+  stmia r1, {r4-r11}
+  eor r4, r4, r2
+  eor r5, r5, r2
+  eor r6, r6, r2
+  eor r7, r7, r2
+  eor r8, r8, r2
+  eor r9, r9, r2
+  eor r10, r10, r2
+  eor r11, r11, r2
+  // We need to avoid invalid values in sp or lr (http://b/152210274).
+  eor r3, lr, r2
+  str r3, [r1, #(8 * 4)]
+  eor r3, sp, r2
+  str r3, [r1, #(9 * 4)]
 
   // Save floating-point registers.
   add r1, r0, #(_JB_FLOAT_BASE * 4)
@@ -182,11 +178,9 @@
   fmrx r1, fpscr
   str r1, [r0, #(_JB_FLOAT_STATE * 4)]
 
-#if USE_CHECKSUM
   // Calculate the checksum.
   m_calculate_checksum r12, r0, r2
   str r12, [r0, #(_JB_CHECKSUM * 4)]
-#endif
 
   mov r0, #0
   bx lr
@@ -201,14 +195,11 @@
   .cfi_rel_offset r1, 4
   .cfi_rel_offset lr, 8
 
-#if USE_CHECKSUM
   // Check the checksum before doing anything.
   m_calculate_checksum r12, r0, r3
   ldr r2, [r0, #(_JB_CHECKSUM * 4)]
-
   teq r2, r12
   bne __bionic_setjmp_checksum_mismatch
-#endif
 
   // Fetch the signal flag.
   ldr r1, [r0, #(_JB_SIGFLAG * 4)]
@@ -245,10 +236,21 @@
   // Restore core registers.
   add r2, r0, #(_JB_CORE_BASE * 4)
 
-  // ARM deprecates using sp in the register list for ldmia.
-  ldmia r2, {r4-r11, lr}
-  ldr sp, [r2, #(9 * 4)]
-  m_unmangle_registers r3
+  // Do all the easy registers in one go.
+  ldmia r2, {r4-r11}
+  eor r4, r4, r3
+  eor r5, r5, r3
+  eor r6, r6, r3
+  eor r7, r7, r3
+  eor r8, r8, r3
+  eor r9, r9, r3
+  eor r10, r10, r3
+  eor r11, r11, r3
+  // We need to avoid invalid values in sp or lr (http://b/152210274).
+  ldr r0, [r2, #(8 * 4)]
+  eor lr, r0, r3
+  ldr r0, [r2, #(9 * 4)]
+  eor sp, r0, r3
 
   // Save the return value/address and check the setjmp cookie.
   stmfd sp!, {r1, lr}
diff --git a/libc/arch-arm64/bionic/setjmp.S b/libc/arch-arm64/bionic/setjmp.S
index 351516f..d2fafdb 100644
--- a/libc/arch-arm64/bionic/setjmp.S
+++ b/libc/arch-arm64/bionic/setjmp.S
@@ -69,11 +69,8 @@
 #define _JB_CHECKSUM    (_JB_D8_D9 + 2)
 
 #define SCS_MASK (SCS_SIZE - 1)
-#define MANGLE_REGISTERS 1
-#define USE_CHECKSUM 1
 
 .macro m_mangle_registers reg, sp_reg
-#if MANGLE_REGISTERS
   eor x3, x3, \reg
   eor x19, x19, \reg
   eor x20, x20, \reg
@@ -88,7 +85,6 @@
   eor x29, x29, \reg
   eor x30, x30, \reg
   eor \sp_reg, \sp_reg, \reg
-#endif
 .endm
 
 .macro m_calculate_checksum dst, src, scratch
@@ -179,11 +175,9 @@
   stp d10, d11, [x0, #(_JB_D10_D11 * 8)]
   stp d8,  d9,  [x0, #(_JB_D8_D9   * 8)]
 
-#if USE_CHECKSUM
   // Calculate the checksum.
   m_calculate_checksum x12, x0, x2
   str x12, [x0, #(_JB_CHECKSUM * 8)]
-#endif
 
   mov w0, #0
   autiasp
@@ -194,14 +188,11 @@
 // void siglongjmp(sigjmp_buf env, int value);
 ENTRY(siglongjmp)
 __BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp)
-#if USE_CHECKSUM
   // Check the checksum before doing anything.
   m_calculate_checksum x12, x0, x2
   ldr x2, [x0, #(_JB_CHECKSUM * 8)]
-
   cmp x2, x12
   bne __bionic_setjmp_checksum_mismatch
-#endif
 
 #if __has_feature(hwaddress_sanitizer)
   stp x0, x30, [sp, #-16]!
diff --git a/libc/arch-common/bionic/crtbegin.c b/libc/arch-common/bionic/crtbegin.c
index f2b6638..62878378 100644
--- a/libc/arch-common/bionic/crtbegin.c
+++ b/libc/arch-common/bionic/crtbegin.c
@@ -89,6 +89,3 @@
 #include "__dso_handle.h"
 #include "atexit.h"
 #include "pthread_atfork.h"
-#ifdef __i386__
-# include "../../arch-x86/bionic/__stack_chk_fail_local.h"
-#endif
diff --git a/libc/arch-common/bionic/crtbegin_so.c b/libc/arch-common/bionic/crtbegin_so.c
index cf369cc..2f3b118 100644
--- a/libc/arch-common/bionic/crtbegin_so.c
+++ b/libc/arch-common/bionic/crtbegin_so.c
@@ -73,6 +73,3 @@
 # include "atexit.h"
 #endif
 #include "pthread_atfork.h"
-#ifdef __i386__
-# include "../../arch-x86/bionic/__stack_chk_fail_local.h"
-#endif
diff --git a/libc/arch-x86/bionic/__stack_chk_fail_local.h b/libc/arch-x86/bionic/__stack_chk_fail_local.h
deleted file mode 100644
index 0b0fd7f..0000000
--- a/libc/arch-x86/bionic/__stack_chk_fail_local.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2012 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 <sys/cdefs.h>
-
-/*
-   __stack_chk_fail routine is runtime part of stack protector compiler
-   feature. It's implemented in libc and represents die routine when stack
-   corruption is detected.
-
-   Calls are generated by compiler and injected into user functions when
-   -fstack-protector* options are used.
-
-   __stack_chk_fail_local is wrapper for __stack_chk_fail. Compiler generates
-   wrapper calls instead for PIC code only and only on IA32 for optimization
-   purpose (see gcc/config/i386/i386.c). Wrapper body is always included into
-   executable or library. This is the idea of optimization.
-
-   Glibc is doing this via libc_nonshared.a which is linked automatically
-   everytime with libc.so. In bionic we have to bring it within crtfiles
-   because libc.so is real library and not a link script like libc.so at glibc.
-
-   For x86_64 or non-PIC code compiler always generates __stack_chk_fail calls.
-*/
-
-#ifdef __i386__
-extern void __stack_chk_fail();
-
-__LIBC_HIDDEN__ void __stack_chk_fail_local() {
-  __stack_chk_fail();
-}
-#endif
diff --git a/libc/arch-x86/bionic/setjmp.S b/libc/arch-x86/bionic/setjmp.S
index 1e1ce58..1a3eb4b 100644
--- a/libc/arch-x86/bionic/setjmp.S
+++ b/libc/arch-x86/bionic/setjmp.S
@@ -57,19 +57,6 @@
 #define _JB_SIGFLAG 8
 #define _JB_CHECKSUM 9
 
-.macro m_mangle_registers reg
-  xorl \reg,%edx
-  xorl \reg,%ebx
-  xorl \reg,%esp
-  xorl \reg,%ebp
-  xorl \reg,%esi
-  xorl \reg,%edi
-.endm
-
-.macro m_unmangle_registers reg
-  m_mangle_registers \reg
-.endm
-
 .macro m_calculate_checksum dst, src
   movl $0, \dst
   .irp i,0,1,2,3,4,5
@@ -129,14 +116,17 @@
 
   // Save the callee-save registers.
   movl 0(%esp),%edx
-  m_mangle_registers %eax
-  movl %edx,(_JB_EDX * 4)(%ecx)
-  movl %ebx,(_JB_EBX * 4)(%ecx)
-  movl %esp,(_JB_ESP * 4)(%ecx)
-  movl %ebp,(_JB_EBP * 4)(%ecx)
-  movl %esi,(_JB_ESI * 4)(%ecx)
-  movl %edi,(_JB_EDI * 4)(%ecx)
-  m_unmangle_registers %eax
+
+.macro m_mangle_register reg, offset
+  movl \reg,(\offset * 4)(%ecx)
+  xorl %eax,(\offset * 4)(%ecx)
+.endm
+  m_mangle_register %edx, _JB_EDX
+  m_mangle_register %ebx, _JB_EBX
+  m_mangle_register %esp, _JB_ESP
+  m_mangle_register %ebp, _JB_EBP
+  m_mangle_register %esi, _JB_ESI
+  m_mangle_register %edi, _JB_EDI
 
   m_calculate_checksum %eax, %ecx
   movl %eax, (_JB_CHECKSUM * 4)(%ecx)
@@ -174,18 +164,26 @@
   movl 4(%esp),%edx
   movl 8(%esp),%eax
 
+  // Fetch the setjmp cookie and clear the signal flag bit.
   movl (_JB_SIGFLAG * 4)(%edx),%ecx
   andl $-2,%ecx
 
+  // Carefully unmangle esp/ebp without ever having an invalid value in the
+  // register (http://b/152210274).
+  movl (_JB_ESP * 4)(%edx),%edi
+  xorl %ecx,%edi
+  movl %edi,%esp
+  movl (_JB_EBP * 4)(%edx),%edi
+  xorl %ecx,%edi
+  movl %edi,%ebp
+
+  // The others don't matter as much, but we do need to finish using the cookie
+  // from %ecx before we clobber it, so we seed each register with the cookie.
   movl %ecx,%ebx
-  movl %ecx,%esp
-  movl %ecx,%ebp
   movl %ecx,%esi
   movl %ecx,%edi
   xorl (_JB_EDX * 4)(%edx),%ecx
   xorl (_JB_EBX * 4)(%edx),%ebx
-  xorl (_JB_ESP * 4)(%edx),%esp
-  xorl (_JB_EBP * 4)(%edx),%ebp
   xorl (_JB_ESI * 4)(%edx),%esi
   xorl (_JB_EDI * 4)(%edx),%edi
 
diff --git a/libc/arch-x86_64/bionic/setjmp.S b/libc/arch-x86_64/bionic/setjmp.S
index 1d34561..ba3f05f 100644
--- a/libc/arch-x86_64/bionic/setjmp.S
+++ b/libc/arch-x86_64/bionic/setjmp.S
@@ -64,25 +64,6 @@
 #define _JB_SIGMASK 9
 #define _JB_CHECKSUM 10
 
-#define MANGLE_REGISTERS 1
-
-.macro m_mangle_registers reg
-#if MANGLE_REGISTERS
-  xorq \reg,%rbx
-  xorq \reg,%rbp
-  xorq \reg,%r12
-  xorq \reg,%r13
-  xorq \reg,%r14
-  xorq \reg,%r15
-  xorq \reg,%rsp
-  xorq \reg,%r11
-#endif
-.endm
-
-.macro m_unmangle_registers reg
-  m_mangle_registers \reg
-.endm
-
 .macro m_calculate_checksum dst, src
   movq $0, \dst
   .irp i,0,1,2,3,4,5,6,7
@@ -127,20 +108,26 @@
   popq %rdi // Pop 'env'.
 
 2:
-  // Save the callee-save registers.
+  // Fetch the setjmp cookie and clear the signal flag bit.
   popq %rax
   andq $-2,%rax
   movq (%rsp),%r11
-  m_mangle_registers %rax
-  movq %rbx,(_JB_RBX * 8)(%rdi)
-  movq %rbp,(_JB_RBP * 8)(%rdi)
-  movq %r12,(_JB_R12 * 8)(%rdi)
-  movq %r13,(_JB_R13 * 8)(%rdi)
-  movq %r14,(_JB_R14 * 8)(%rdi)
-  movq %r15,(_JB_R15 * 8)(%rdi)
-  movq %rsp,(_JB_RSP * 8)(%rdi)
-  movq %r11,(_JB_PC  * 8)(%rdi)
-  m_unmangle_registers %rax
+
+  // Save the callee-save registers.
+
+.macro m_mangle_register reg, offset
+  movq \reg, (\offset * 8)(%rdi)
+  xorq %rax, (\offset * 8)(%rdi)  // %rax contains the cookie.
+.endm
+
+  m_mangle_register %rbx, _JB_RBX
+  m_mangle_register %rbp, _JB_RBP
+  m_mangle_register %r12, _JB_R12
+  m_mangle_register %r13, _JB_R13
+  m_mangle_register %r14, _JB_R14
+  m_mangle_register %r15, _JB_R15
+  m_mangle_register %rsp, _JB_RSP
+  m_mangle_register %r11, _JB_PC
 
   m_calculate_checksum %rax, %rdi
   movq %rax, (_JB_CHECKSUM * 8)(%rdi)
@@ -179,15 +166,22 @@
   popq %rax // Pop 'value'.
 
   // Restore the callee-save registers.
-  movq (_JB_RBX * 8)(%r12),%rbx
-  movq (_JB_RBP * 8)(%r12),%rbp
-  movq (_JB_R13 * 8)(%r12),%r13
-  movq (_JB_R14 * 8)(%r12),%r14
-  movq (_JB_R15 * 8)(%r12),%r15
-  movq (_JB_RSP * 8)(%r12),%rsp
-  movq (_JB_PC  * 8)(%r12),%r11
-  movq (_JB_R12 * 8)(%r12),%r12
-  m_unmangle_registers %rcx
+
+.macro m_unmangle_register reg, offset
+  movq (\offset * 8)(%r12), %rdx  // Clobbers rdx.
+  xorq %rcx, %rdx                 // %rcx contains the cookie.
+  // Now it's safe to overwrite the register (http://b/152210274).
+  movq %rdx, \reg
+.endm
+
+  m_unmangle_register %rbx, _JB_RBX
+  m_unmangle_register %rbp, _JB_RBP
+  m_unmangle_register %r13, _JB_R13
+  m_unmangle_register %r14, _JB_R14
+  m_unmangle_register %r15, _JB_R15
+  m_unmangle_register %rsp, _JB_RSP
+  m_unmangle_register %r11, _JB_PC
+  m_unmangle_register %r12, _JB_R12
 
   // Check the cookie.
   pushq %rax
diff --git a/libc/async_safe/Android.bp b/libc/async_safe/Android.bp
index 2e05d7a..e4a5837 100644
--- a/libc/async_safe/Android.bp
+++ b/libc/async_safe/Android.bp
@@ -57,5 +57,4 @@
         "//apex_available:platform",
         "com.android.runtime",
     ],
-    bazel_module: { bp2build_available: true },
 }
diff --git a/libc/bionic/bind.cpp b/libc/bionic/bind.cpp
deleted file mode 100644
index 79e8020..0000000
--- a/libc/bionic/bind.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.
- */
-
-// b/170214442: Intercept bind calls on NETLINK_ROUTE sockets.
-// This entire file will be reverted before release.
-
-#include <async_safe/log.h>
-#include <errno.h>
-#include <linux/rtnetlink.h>
-#include <string.h>
-#include <sys/socket.h>
-
-#include "bionic_appcompat.h"
-
-extern "C" int __bind(int fd, const struct sockaddr* addr, socklen_t addr_length);
-
-int bind(int fd, const struct sockaddr* addr, socklen_t addr_length) {
-  if (should_apply_soft_mac_bind_restrictions()) {
-    int sock_domain, sock_protocol;
-    socklen_t sock_domain_length = sizeof(sock_domain);
-    socklen_t sock_protocol_length = sizeof(sock_protocol);
-    if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &sock_domain, &sock_domain_length) < 0 ||
-        getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &sock_protocol, &sock_protocol_length) < 0) {
-      async_safe_format_log(ANDROID_LOG_ERROR, "mac-restrictions",
-                            "Could not get socket type/protocol: %s", strerror(errno));
-    } else if (AF_NETLINK == sock_domain && NETLINK_ROUTE == sock_protocol) {
-      char package_name[MAX_PACKAGE_NAME_LENGTH + 1];
-      get_package_name(package_name, sizeof(package_name));
-      async_safe_format_log(
-          ANDROID_LOG_ERROR, "mac-restrictions",
-          "%s tried to call bind() on a NETLINK_ROUTE socket, which is not allowed. Please follow "
-          "instructions at go/netlink-bug if this app behaves incorrectly.",
-          package_name);
-      errno = EACCES;
-      return -1;
-    }
-  }
-
-  return __bind(fd, addr, addr_length);
-}
diff --git a/libc/bionic/bionic_appcompat.cpp b/libc/bionic/bionic_appcompat.cpp
deleted file mode 100644
index dcca0da..0000000
--- a/libc/bionic/bionic_appcompat.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.
- */
-
-// b/170214442: Intercept bind calls on NETLINK_ROUTE sockets and getifaddrs() calls.
-// This entire file will be reverted before release.
-
-#include <async_safe/log.h>
-#include <cutils/misc.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "bionic_appcompat.h"
-
-bool should_apply_soft_mac_restrictions(const char* const allowlist[]) {
-  if (getuid() < FIRST_APPLICATION_UID) {
-    // System app. No restrictions should be applied.
-    return false;
-  }
-  if (android_get_application_target_sdk_version() >= __ANDROID_API_R__) {
-    // Restrictions already applied by SELinux. Behave as normally.
-    return false;
-  }
-
-  char package_name[MAX_PACKAGE_NAME_LENGTH + 1];
-  if (get_package_name(package_name, sizeof(package_name)) < 0) {
-    // Error in getting own package name. Apply restrictions by default.
-    async_safe_format_log(ANDROID_LOG_ERROR, "mac-restrictions",
-                          "Could not determine own package name for uid %d", getuid());
-    return true;
-  }
-  for (int i = 0; allowlist[i] != nullptr; i++) {
-    if (strcmp(package_name, allowlist[i]) == 0) {
-      async_safe_format_log(ANDROID_LOG_WARN, "mac-restrictions",
-                            "Temporarily allowing %s to bypass MAC address restrictions.",
-                            package_name);
-      return false;
-    }
-  }
-  return true;
-}
-
-bool should_apply_soft_mac_bind_restrictions() {
-  return should_apply_soft_mac_restrictions(soft_mac_bind_allowlist);
-}
-
-bool should_apply_soft_mac_getlink_restrictions() {
-  return should_apply_soft_mac_restrictions(soft_mac_getlink_allowlist);
-}
-
-int get_package_name(char* buffer, const int bufferlen) {
-  int file = open("/proc/self/cmdline", O_RDONLY | O_CLOEXEC);
-  if (file < 0) {
-    return file;
-  }
-
-  ssize_t len = read(file, buffer, bufferlen - 1);
-  if (len < 0) {
-    close(file);
-    return -1;
-  }
-  buffer[len] = 0;
-
-  close(file);
-  return 0;
-}
diff --git a/libc/bionic/bionic_appcompat.h b/libc/bionic/bionic_appcompat.h
deleted file mode 100644
index e67e50c..0000000
--- a/libc/bionic/bionic_appcompat.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-constexpr int MAX_PACKAGE_NAME_LENGTH = 230;
-
-static inline const char* const soft_mac_bind_allowlist[] = {
-    "com.cisco.anyconnect.vpn.android.avf:nchs",
-    "com.skype.raider",
-    nullptr,
-};
-
-static inline const char* const soft_mac_getlink_allowlist[] = {
-    "com.cisco.anyconnect.vpn.android.avf:nchs",
-    nullptr,
-};
-
-int get_package_name(char* buffer, const int bufferlen);
-bool should_apply_soft_mac_bind_restrictions();
-bool should_apply_soft_mac_getlink_restrictions();
diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp
index 043510c..48e8674 100644
--- a/libc/bionic/fdsan.cpp
+++ b/libc/bionic/fdsan.cpp
@@ -137,14 +137,6 @@
     return;
   }
 
-  // Lots of code will (sensibly) fork, call close on all of their fds,
-  // and then exec. Compare our cached pid value against the real one to detect
-  // this scenario and permit it.
-  pid_t cached_pid = __get_cached_pid();
-  if (cached_pid == 0 || cached_pid != syscall(__NR_getpid)) {
-    return;
-  }
-
   struct {
     size_t size;
     char buf[512];
diff --git a/libc/bionic/fdtrack.cpp b/libc/bionic/fdtrack.cpp
index 1123512..89a208f 100644
--- a/libc/bionic/fdtrack.cpp
+++ b/libc/bionic/fdtrack.cpp
@@ -37,8 +37,14 @@
 
 _Atomic(android_fdtrack_hook_t) __android_fdtrack_hook;
 
+bool __android_fdtrack_globally_disabled = false;
+
+void android_fdtrack_set_globally_enabled(bool new_value) {
+  __android_fdtrack_globally_disabled = !new_value;
+}
+
 bool android_fdtrack_get_enabled() {
-  return !__get_bionic_tls().fdtrack_disabled;
+  return !__get_bionic_tls().fdtrack_disabled && !__android_fdtrack_globally_disabled;
 }
 
 bool android_fdtrack_set_enabled(bool new_value) {
diff --git a/libc/bionic/fork.cpp b/libc/bionic/fork.cpp
index 8c5cf2b..d432c6d 100644
--- a/libc/bionic/fork.cpp
+++ b/libc/bionic/fork.cpp
@@ -31,6 +31,7 @@
 #include <android/fdsan.h>
 
 #include "private/bionic_defs.h"
+#include "private/bionic_fdtrack.h"
 #include "pthread_internal.h"
 
 __BIONIC_WEAK_FOR_NATIVE_BRIDGE_INLINE
@@ -55,9 +56,10 @@
   int result = __clone_for_fork();
 
   if (result == 0) {
-    // Disable fdsan post-fork, so we don't falsely trigger on processes that
+    // Disable fdsan and fdtrack post-fork, so we don't falsely trigger on processes that
     // fork, close all of their fds, and then exec.
     android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_DISABLED);
+    android_fdtrack_set_globally_enabled(false);
 
     // Reset the stack_and_tls VMA name so it doesn't end with a tid from the
     // parent process.
diff --git a/libc/bionic/ifaddrs.cpp b/libc/bionic/ifaddrs.cpp
index 22ecdb4..1536333 100644
--- a/libc/bionic/ifaddrs.cpp
+++ b/libc/bionic/ifaddrs.cpp
@@ -42,7 +42,6 @@
 
 #include "private/ErrnoRestorer.h"
 
-#include "bionic_appcompat.h"
 #include "bionic_netlink.h"
 
 // The public ifaddrs struct is full of pointers. Rather than track several
@@ -311,12 +310,9 @@
   // - System apps
   // - Apps with a target SDK version lower than R
   bool getlink_success = false;
-  if (!should_apply_soft_mac_getlink_restrictions()) {
+  if (getuid() < FIRST_APPLICATION_UID ||
+      android_get_application_target_sdk_version() < __ANDROID_API_R__) {
     getlink_success = nc.SendRequest(RTM_GETLINK) && nc.ReadResponses(__getifaddrs_callback, out);
-  } else if (android_get_application_target_sdk_version() < __ANDROID_API_R__) {
-    async_safe_format_log(ANDROID_LOG_WARN, "mac-restrictions",
-                          "ifaddr no longer returns link info. Please follow instructions at "
-                          "go/netlink-bug if this app behaves incorrectly.");
   }
   bool getaddr_success =
     nc.SendRequest(RTM_GETADDR) && nc.ReadResponses(__getifaddrs_callback, out);
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 206d5fd..f3fee88 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -344,6 +344,12 @@
   __set_stack_and_tls_vma_name(false);
   __init_additional_stacks(thread);
   __rt_sigprocmask(SIG_SETMASK, &thread->start_mask, nullptr, sizeof(thread->start_mask));
+#ifdef __aarch64__
+  // Chrome's sandbox prevents this prctl, so only reset IA if the target SDK level is high enough.
+  if (android_get_application_target_sdk_version() >= __ANDROID_API_S__) {
+    prctl(PR_PAC_RESET_KEYS, PR_PAC_APIAKEY, 0, 0, 0);
+  }
+#endif
 
   void* result = thread->start_routine(thread->start_routine_arg);
   pthread_exit(result);
diff --git a/libc/bionic/scandir.cpp b/libc/bionic/scandir.cpp
index 6a7e368..f528286 100644
--- a/libc/bionic/scandir.cpp
+++ b/libc/bionic/scandir.cpp
@@ -16,8 +16,9 @@
 
 #include <dirent.h>
 
-#include <fcntl.h>
+#include <assert.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -32,10 +33,8 @@
   }
 
   ~ScandirResult() {
-    while (size_ > 0) {
-      free(names_[--size_]);
-    }
-    free(names_);
+    // We always call release(), so this can't happen.
+    if (names_ != nullptr) __assert(__FILE__, __LINE__, "missing call to release()");
   }
 
   size_t size() {
diff --git a/libc/dns/resolv/res_data.c b/libc/dns/resolv/res_data.c
index 9bc02e7..4f8df69 100644
--- a/libc/dns/resolv/res_data.c
+++ b/libc/dns/resolv/res_data.c
@@ -40,6 +40,7 @@
 #include <ctype.h>
 #include <netdb.h>
 #include "resolv_private.h"
+#include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -82,11 +83,9 @@
 
 int  res_ourserver_p(const res_state, const struct sockaddr *);
 
-#define res_need_init()   ((_nres.options & RES_INIT) == 0U)
+static pthread_once_t once_control = PTHREAD_ONCE_INIT;
 
-int
-res_init(void) {
-	int rv;
+static void init_once(void) {
 	extern int __res_vinit(res_state, int);
 #ifdef COMPAT__RES
 	/*
@@ -140,11 +139,21 @@
 	if (!_nres.id)
 		_nres.id = res_randomid();
 
-	rv = __res_vinit(&_nres, 1);
+	__res_vinit(&_nres, 1);
 #ifdef COMPAT__RES
 	__res_put_old_state(&_nres);
 #endif
-	return rv;
+}
+
+int
+res_init(void) {
+    pthread_once(&once_control, init_once);
+    return 0;
+}
+
+static res_state get_static_res_state() {
+    pthread_once(&once_control, init_once);
+    return &_nres;
 }
 
 void
@@ -159,10 +168,7 @@
 
 void
 fp_nquery(const u_char *msg, int len, FILE *file) {
-	if (res_need_init() && res_init() == -1)
-		return;
-
-	res_pquery(&_nres, msg, len, file);
+	res_pquery(get_static_res_state(), msg, len, file);
 }
 
 int
@@ -175,11 +181,7 @@
 	    u_char *buf,		/* buffer to put query */
 	    int buflen)			/* size of buffer */
 {
-	if (res_need_init() && res_init() == -1) {
-		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
-		return (-1);
-	}
-	return (res_nmkquery(&_nres, op, dname, class, type,
+	return (res_nmkquery(get_static_res_state(), op, dname, class, type,
 			     data, datalen,
 			     newrr_in, buf, buflen));
 }
@@ -187,12 +189,7 @@
 #ifdef _LIBRESOLV
 int
 res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
-	if (res_need_init() && res_init() == -1) {
-		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
-		return (-1);
-	}
-
-	return (res_nmkupdate(&_nres, rrecp_in, buf, buflen));
+	return (res_nmkupdate(get_static_res_state(), rrecp_in, buf, buflen));
 }
 #endif
 
@@ -202,11 +199,7 @@
 	  u_char *answer,	/* buffer to put answer */
 	  int anslen)		/* size of answer buffer */
 {
-	if (res_need_init() && res_init() == -1) {
-		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
-		return (-1);
-	}
-	return (res_nquery(&_nres, name, class, type, answer, anslen));
+	return (res_nquery(get_static_res_state(), name, class, type, answer, anslen));
 }
 
 void
@@ -226,12 +219,7 @@
 
 int
 res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
-	if (res_need_init() && res_init() == -1) {
-		/* errno should have been set by res_init() in this case. */
-		return (-1);
-	}
-
-	return (res_nsend(&_nres, buf, buflen, ans, anssiz));
+	return (res_nsend(get_static_res_state(), buf, buflen, ans, anssiz));
 }
 
 #ifdef _LIBRESOLV
@@ -239,12 +227,7 @@
 res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key,
 	       u_char *ans, int anssiz)
 {
-	if (res_need_init() && res_init() == -1) {
-		/* errno should have been set by res_init() in this case. */
-		return (-1);
-	}
-
-	return (res_nsendsigned(&_nres, buf, buflen, key, ans, anssiz));
+	return (res_nsendsigned(get_static_res_state(), buf, buflen, key, ans, anssiz));
 }
 #endif
 
@@ -256,12 +239,7 @@
 #ifdef _LIBRESOLV
 int
 res_update(ns_updrec *rrecp_in) {
-	if (res_need_init() && res_init() == -1) {
-		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
-		return (-1);
-	}
-
-	return (res_nupdate(&_nres, rrecp_in, NULL));
+	return (res_nupdate(get_static_res_state(), rrecp_in, NULL));
 }
 #endif
 
@@ -271,12 +249,7 @@
 	   u_char *answer,	/* buffer to put answer */
 	   int anslen)		/* size of answer */
 {
-	if (res_need_init() && res_init() == -1) {
-		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
-		return (-1);
-	}
-
-	return (res_nsearch(&_nres, name, class, type, answer, anslen));
+	return (res_nsearch(get_static_res_state(), name, class, type, answer, anslen));
 }
 
 int
@@ -286,12 +259,7 @@
 		u_char *answer,		/* buffer to put answer */
 		int anslen)		/* size of answer */
 {
-	if (res_need_init() && res_init() == -1) {
-		RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL);
-		return (-1);
-	}
-
-	return (res_nquerydomain(&_nres, name, domain,
+	return (res_nquerydomain(get_static_res_state(), name, domain,
 				 class, type,
 				 answer, anslen));
 }
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index b1bd713..2556d11 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -281,10 +281,12 @@
  */
 #  define __call_bypassing_fortify(fn) (&fn)
 /*
- * Because clang-FORTIFY uses overloads, we can't mark functions as `extern
- * inline` without making them available externally.
+ * Because clang-FORTIFY uses overloads, we can't mark functions as `extern inline` without making
+ * them available externally. FORTIFY'ed functions try to be as close to possible as 'invisible';
+ * having stack protectors detracts from that (b/182948263).
  */
-#  define __BIONIC_FORTIFY_INLINE static __inline__ __always_inline __VERSIONER_FORTIFY_INLINE
+#  define __BIONIC_FORTIFY_INLINE static __inline__ __attribute__((no_stack_protector)) \
+      __always_inline __VERSIONER_FORTIFY_INLINE
 /*
  * We should use __BIONIC_FORTIFY_VARIADIC instead of __BIONIC_FORTIFY_INLINE
  * for variadic functions because compilers cannot inline them.
diff --git a/libc/include/sys/mman.h b/libc/include/sys/mman.h
index 3b44dab..6ef0c12 100644
--- a/libc/include/sys/mman.h
+++ b/libc/include/sys/mman.h
@@ -167,9 +167,9 @@
  * works just like madvise(2) but applies to the process specified by the given
  * PID file descriptor.
  *
- * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ * Returns the number of bytes advised on success, and returns -1 and sets `errno` on failure.
  */
-int process_madvise(int __pid_fd, const struct iovec* __iov, size_t __count, int __advice, unsigned int __flags);
+ssize_t process_madvise(int __pid_fd, const struct iovec* __iov, size_t __count, int __advice, unsigned __flags);
 
 #if defined(__USE_GNU)
 
diff --git a/libc/kernel/README.md b/libc/kernel/README.md
index 6db08d6..5f1c81d 100644
--- a/libc/kernel/README.md
+++ b/libc/kernel/README.md
@@ -17,11 +17,23 @@
 
 Description of the directories involved in generating the parsed kernel headers:
 
-  * `external/kernel-headers/original/`
-    Contains the uapi kernel headers found in the android kernel. Note this
+  * `external/kernel-headers/original/uapi/`
+    Contains the uapi kernel headers found in the Android kernel. Note this
     also includes the header files that are generated by building the kernel
     sources.
 
+  * `external/kernel-headers/original/scsi/`
+    Contains copies of the kernel scsi header files. These where never
+    made into uapi files, but some user space code expects that these
+    headers are available.
+
+  * `external/kernel-headers/modified/scsi/`
+    Contains hand-modified versions of a few files from `original/scsi/`
+    that removes the kernel specific code from these files so they can
+    be used as uapi headers. The tools to process the kernel headers will
+    warn if any scsi header files have changed and require new versions
+    to be hand-modified.
+
   * `bionic/libc/kernel/uapi/`
     Contains the cleaned kernel headers and mirrors the directory structure
     in `external/kernel-headers/original/uapi/`.
@@ -33,7 +45,7 @@
 The tools to get/parse the headers:
 
   * `tools/generate_uapi_headers.sh`
-    Checks out the android kernel and generates all uapi header files.
+    Checks out the Android kernel and generates all uapi header files.
     copies all the changed files into external/kernel-headers.
 
   * `tools/clean_header.py`
@@ -60,19 +72,25 @@
   kernel_src> git clone https://android.googlesource.com/kernel/common/ -b android-mainline
 ```
 
-For now, there are no tags, take the top of tree version. To find the
-version of the linux stable kernel headers the mainline source code is
-tracking, read the uapi/linux/version.h that is generated.
+The Android mainline kernel source has tags that indicate the kernel
+version to which they correspond. The format of a tag is
+android-mainline-XXX, where XXX is the kernel version. For example,
+android-mainline-5.10 corresponds to linux stable kernel 5.10. To check out
+a particular tag:
 ```
-  kernel_src> cd linux-stable
-  kernel_src/linux-stable> git checkout tags/vXXX
+  kernel_src> cd common
+  kernel_src/common> git checkout tags/android-mainline-XXX
 ```
 
+It is expected that a kernel update should only be performed on a valid tag.
+For testing purposes, it is possible that you can use the top of tree
+version, but never use that as the basis for importing new kernel headers.
+
 Before running the command to import the headers, make sure that you have
 done a lunch TARGET. The script uses a variable set by the lunch command
 to determine which directory to use as the destination directory.
 
-After running lunch, run this command to import the headers into the android
+After running lunch, run this command to import the headers into the Android
 source tree if there is a kernel source tree already checked out:
 ```
   bionic/libc/kernel/tools/generate_uapi_headers.sh --use-kernel-dir kernel_src
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 51a1076..c31e306 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1772,6 +1772,7 @@
     android_fdtrack_compare_exchange_hook; # llndk
     android_fdtrack_get_enabled; # llndk
     android_fdtrack_set_enabled; # llndk
+    android_fdtrack_set_globally_enabled; # llndk
     android_net_res_stats_get_info_for_net;
     android_net_res_stats_aggregate;
     android_net_res_stats_get_usable_servers;
diff --git a/libc/platform/bionic/fdtrack.h b/libc/platform/bionic/fdtrack.h
index 6eb379b..fe6ca84 100644
--- a/libc/platform/bionic/fdtrack.h
+++ b/libc/platform/bionic/fdtrack.h
@@ -70,4 +70,8 @@
 bool android_fdtrack_get_enabled() __INTRODUCED_IN(30);
 bool android_fdtrack_set_enabled(bool new_value) __INTRODUCED_IN(30);
 
+// Globally enable/disable fdtrack.
+// This is primaryily useful to reenable fdtrack after it's been automatically disabled post-fork.
+void android_fdtrack_set_globally_enabled(bool new_value) __INTRODUCED_IN(31);
+
 __END_DECLS
diff --git a/libc/private/bionic_fdtrack.h b/libc/private/bionic_fdtrack.h
index 259897c..c05b32b 100644
--- a/libc/private/bionic_fdtrack.h
+++ b/libc/private/bionic_fdtrack.h
@@ -28,41 +28,43 @@
 
 #pragma once
 
-#include <sys/cdefs.h>
 #include <stdatomic.h>
+#include <sys/cdefs.h>
 
 #include "platform/bionic/fdtrack.h"
 
 #include "bionic/pthread_internal.h"
-#include "private/bionic_tls.h"
 #include "private/ErrnoRestorer.h"
+#include "private/bionic_tls.h"
 
 extern "C" _Atomic(android_fdtrack_hook_t) __android_fdtrack_hook;
+extern "C" bool __android_fdtrack_globally_disabled;
 
 // Macro to record file descriptor creation.
 // e.g.:
 //   int socket(int domain, int type, int protocol) {
 //     return FDTRACK_CREATE_NAME("socket", __socket(domain, type, protocol));
 //   }
-#define FDTRACK_CREATE_NAME(name, fd_value)                       \
-  ({                                                              \
-    int __fd = (fd_value);                                        \
-    if (__fd != -1 && __predict_false(__android_fdtrack_hook) &&  \
-        !__predict_false(__get_thread()->is_vforked())) {         \
-      bionic_tls& tls = __get_bionic_tls();                       \
-      /* fdtrack_disabled is only true during reentrant calls. */ \
-      if (!__predict_false(tls.fdtrack_disabled)) {               \
-        ErrnoRestorer r;                                          \
-        tls.fdtrack_disabled = true;                              \
-        android_fdtrack_event event;                              \
-        event.fd = __fd;                                          \
-        event.type = ANDROID_FDTRACK_EVENT_TYPE_CREATE;           \
-        event.data.create.function_name = name;                   \
-        atomic_load(&__android_fdtrack_hook)(&event);             \
-        tls.fdtrack_disabled = false;                             \
-      }                                                           \
-    }                                                             \
-    __fd;                                                         \
+#define FDTRACK_CREATE_NAME(name, fd_value)                        \
+  ({                                                               \
+    int __fd = (fd_value);                                         \
+    if (__fd != -1 && __predict_false(__android_fdtrack_hook) &&   \
+        !__predict_false(__get_thread()->is_vforked())) {          \
+      bionic_tls& tls = __get_bionic_tls();                        \
+      /* fdtrack_disabled is only true during reentrant calls. */  \
+      if (!__predict_false(tls.fdtrack_disabled) &&                \
+          !__predict_false(__android_fdtrack_globally_disabled)) { \
+        ErrnoRestorer r;                                           \
+        tls.fdtrack_disabled = true;                               \
+        android_fdtrack_event event;                               \
+        event.fd = __fd;                                           \
+        event.type = ANDROID_FDTRACK_EVENT_TYPE_CREATE;            \
+        event.data.create.function_name = name;                    \
+        atomic_load (&__android_fdtrack_hook)(&event);             \
+        tls.fdtrack_disabled = false;                              \
+      }                                                            \
+    }                                                              \
+    __fd;                                                          \
   })
 
 // Macro to record file descriptor creation, with the current function's name.
@@ -74,22 +76,23 @@
 
 // Macro to record file descriptor closure.
 // Note that this does not actually close the file descriptor.
-#define FDTRACK_CLOSE(fd_value)                                  \
-  ({                                                             \
-    int __fd = (fd_value);                                       \
-    if (__fd != -1 && __predict_false(__android_fdtrack_hook) && \
-        !__predict_false(__get_thread()->is_vforked())) {        \
-      bionic_tls& tls = __get_bionic_tls();                      \
-      if (!__predict_false(tls.fdtrack_disabled)) {              \
-        int saved_errno = errno;                                 \
-        tls.fdtrack_disabled = true;                             \
-        android_fdtrack_event event;                             \
-        event.fd = __fd;                                         \
-        event.type = ANDROID_FDTRACK_EVENT_TYPE_CLOSE;           \
-        atomic_load(&__android_fdtrack_hook)(&event);            \
-        tls.fdtrack_disabled = false;                            \
-        errno = saved_errno;                                     \
-      }                                                          \
-    }                                                            \
-    __fd;                                                        \
+#define FDTRACK_CLOSE(fd_value)                                    \
+  ({                                                               \
+    int __fd = (fd_value);                                         \
+    if (__fd != -1 && __predict_false(__android_fdtrack_hook) &&   \
+        !__predict_false(__get_thread()->is_vforked())) {          \
+      bionic_tls& tls = __get_bionic_tls();                        \
+      if (!__predict_false(tls.fdtrack_disabled) &&                \
+          !__predict_false(__android_fdtrack_globally_disabled)) { \
+        int saved_errno = errno;                                   \
+        tls.fdtrack_disabled = true;                               \
+        android_fdtrack_event event;                               \
+        event.fd = __fd;                                           \
+        event.type = ANDROID_FDTRACK_EVENT_TYPE_CLOSE;             \
+        atomic_load (&__android_fdtrack_hook)(&event);             \
+        tls.fdtrack_disabled = false;                              \
+        errno = saved_errno;                                       \
+      }                                                            \
+    }                                                              \
+    __fd;                                                          \
   })
diff --git a/libc/system_properties/system_properties.cpp b/libc/system_properties/system_properties.cpp
index 3fd20b7..344c838 100644
--- a/libc/system_properties/system_properties.cpp
+++ b/libc/system_properties/system_properties.cpp
@@ -133,7 +133,7 @@
 
   prop_area* pa = contexts_->GetPropAreaForName(name);
   if (!pa) {
-    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied finding property \"%s\"", name);
+    async_safe_format_log(ANDROID_LOG_WARN, "libc", "Access denied finding property \"%s\"", name);
     return nullptr;
   }
 
diff --git a/libc/tools/Android.bp b/libc/tools/Android.bp
index 575a31a..116b853 100644
--- a/libc/tools/Android.bp
+++ b/libc/tools/Android.bp
@@ -11,7 +11,6 @@
 filegroup {
     name: "bionic-gensyscalls",
     srcs: ["gensyscalls.py"],
-    bazel_module: { bp2build_available: true },
 }
 
 // Generate the C++ policy sources for app and system seccomp-bpf filters.
diff --git a/libfdtrack/fdtrack.cpp b/libfdtrack/fdtrack.cpp
index fd56274..2e9cfbc 100644
--- a/libfdtrack/fdtrack.cpp
+++ b/libfdtrack/fdtrack.cpp
@@ -93,6 +93,8 @@
     android_fdtrack_hook_t expected = nullptr;
     installed = android_fdtrack_compare_exchange_hook(&expected, &fd_hook);
   }
+
+  android_fdtrack_set_globally_enabled(true);
 }
 
 __attribute__((destructor)) static void dtor() {
diff --git a/linker/Android.bp b/linker/Android.bp
index dd376da..3370f28 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -68,6 +68,9 @@
 
     // We need to access Bionic private headers in the linker.
     include_dirs: ["bionic/libc"],
+
+    // b/182338959
+    bazel_module: { bp2build_available: false },
 }
 
 // ========================================================
diff --git a/tests/fdtrack_test.cpp b/tests/fdtrack_test.cpp
index 13f1b2e..9fcb402 100644
--- a/tests/fdtrack_test.cpp
+++ b/tests/fdtrack_test.cpp
@@ -57,8 +57,13 @@
   }
 }
 
-std::vector<android_fdtrack_event> FdtrackRun(void (*func)()) {
+std::vector<android_fdtrack_event> FdtrackRun(void (*func)(), bool reenable = true) {
   // Each bionic test is run in separate process, so we can safely use a static here.
+  // However, since they're all forked, we need to reenable fdtrack.
+  if (reenable) {
+    android_fdtrack_set_globally_enabled(true);
+  }
+
   static std::vector<android_fdtrack_event> events;
   events.clear();
 
@@ -129,6 +134,21 @@
 #endif
 }
 
+TEST(fdtrack, fork) {
+#if defined(__BIONIC__)
+  ASSERT_EXIT(
+      []() {
+        static int fd = open("/dev/null", O_WRONLY | O_CLOEXEC);
+        ASSERT_NE(-1, fd);
+
+        auto events = FdtrackRun([]() { close(fd); }, false);
+        ASSERT_EQ(0U, events.size());
+        exit(0);
+      }(),
+      testing::ExitedWithCode(0), "");
+#endif
+}
+
 TEST(fdtrack, enable_disable) {
 #if defined(__BIONIC__)
   static int fd1 = -1;
diff --git a/tests/math_test.cpp b/tests/math_test.cpp
index 1dd45b4..9f7e65b 100644
--- a/tests/math_test.cpp
+++ b/tests/math_test.cpp
@@ -1473,16 +1473,40 @@
   ASSERT_EQ(-1, sign);
 }
 
+TEST(MATH_TEST, tgamma_NaN) {
+  ASSERT_TRUE(isnan(tgamma(nan(""))));
+  ASSERT_TRUE(isnanf(tgammaf(nanf(""))));
+  ASSERT_TRUE(isnanl(tgammal(nanl(""))));
+}
+
+TEST(MATH_TEST, tgamma_inf) {
+  ASSERT_TRUE(isinf(tgamma(HUGE_VAL)));
+  ASSERT_TRUE(isinff(tgammaf(HUGE_VALF)));
+  ASSERT_TRUE(isinfl(tgammal(HUGE_VALL)));
+}
+
+TEST(MATH_TEST, tgamma_negative) {
+  ASSERT_TRUE(isnan(tgamma(-1.0)));
+  ASSERT_TRUE(isnanf(tgammaf(-1.0f)));
+  ASSERT_TRUE(isnanl(tgammal(-1.0L)));
+}
+
 TEST(MATH_TEST, tgamma) {
   ASSERT_DOUBLE_EQ(24.0, tgamma(5.0));
+  ASSERT_DOUBLE_EQ(120.0, tgamma(6.0));
+  ASSERT_TRUE(isinf(tgamma(172.0)));
 }
 
 TEST(MATH_TEST, tgammaf) {
   ASSERT_FLOAT_EQ(24.0f, tgammaf(5.0f));
+  ASSERT_FLOAT_EQ(120.0f, tgammaf(6.0f));
+  ASSERT_TRUE(isinff(tgammaf(172.0f)));
 }
 
 TEST(MATH_TEST, tgammal) {
   ASSERT_DOUBLE_EQ(24.0L, tgammal(5.0L));
+  ASSERT_DOUBLE_EQ(120.0L, tgammal(6.0L));
+  ASSERT_TRUE(isinf(tgammal(172.0L)));
 }
 
 TEST(MATH_TEST, j0) {
diff --git a/tests/setjmp_test.cpp b/tests/setjmp_test.cpp
index e6b6819..ec1badc 100644
--- a/tests/setjmp_test.cpp
+++ b/tests/setjmp_test.cpp
@@ -18,6 +18,8 @@
 
 #include <setjmp.h>
 #include <stdlib.h>
+#include <sys/syscall.h>
+#include <unistd.h>
 
 #include "BionicDeathTest.h"
 #include "SignalUtils.h"
@@ -268,3 +270,57 @@
   if (value == 0) call_longjmp(buf);
   EXPECT_EQ(123, value);
 }
+
+TEST(setjmp, bug_152210274) {
+  // Ensure that we never have a mangled value in the stack pointer.
+#if defined(__BIONIC__)
+  struct sigaction sa = {.sa_flags = SA_SIGINFO, .sa_sigaction = [](int, siginfo_t*, void*) {}};
+  ASSERT_EQ(0, sigaction(SIGPROF, &sa, 0));
+
+  constexpr size_t kNumThreads = 20;
+
+  // Start a bunch of threads calling setjmp/longjmp.
+  auto jumper = [](void* arg) -> void* {
+    sigset_t set;
+    sigemptyset(&set);
+    sigaddset(&set, SIGPROF);
+    pthread_sigmask(SIG_UNBLOCK, &set, nullptr);
+
+    jmp_buf buf;
+    for (size_t count = 0; count < 100000; ++count) {
+      if (setjmp(buf) != 0) {
+        perror("setjmp");
+        abort();
+      }
+      if (*static_cast<pid_t*>(arg) == 100) longjmp(buf, 1);
+    }
+    return nullptr;
+  };
+  pid_t tids[kNumThreads] = {};
+  for (size_t i = 0; i < kNumThreads; ++i) {
+    pthread_t t;
+    ASSERT_EQ(0, pthread_create(&t, nullptr, jumper, &tids[i]));
+    tids[i] = pthread_gettid_np(t);
+  }
+
+  // Start the interrupter thread.
+  auto interrupter = [](void* arg) -> void* {
+    pid_t* tids = static_cast<pid_t*>(arg);
+    for (size_t count = 0; count < 1000; ++count) {
+      for (size_t i = 0; i < kNumThreads; i++) {
+        if (tgkill(getpid(), tids[i], SIGPROF) == -1 && errno != ESRCH) {
+          perror("tgkill failed");
+          abort();
+        }
+      }
+      usleep(100);
+    }
+    return nullptr;
+  };
+  pthread_t t;
+  ASSERT_EQ(0, pthread_create(&t, nullptr, interrupter, tids));
+  pthread_join(t, nullptr);
+#else
+  GTEST_SKIP() << "tests uses functions not in glibc";
+#endif
+}
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 7c2c890..b16fe16 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -31,8 +31,6 @@
 #include "SignalUtils.h"
 #include "utils.h"
 
-#include "private/bionic_constants.h"
-
 using namespace std::chrono_literals;
 
 TEST(time, time) {
@@ -760,22 +758,22 @@
 
 TEST(time, clock_gettime) {
   // Try to ensure that our vdso clock_gettime is working.
+  timespec ts0;
   timespec ts1;
-  ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts1));
   timespec ts2;
-  ASSERT_EQ(0, syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts2));
+  ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts0));
+  ASSERT_EQ(0, syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts1));
+  ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts2));
 
-  // What's the difference between the two?
-  ts2.tv_sec -= ts1.tv_sec;
-  ts2.tv_nsec -= ts1.tv_nsec;
-  if (ts2.tv_nsec < 0) {
-    --ts2.tv_sec;
-    ts2.tv_nsec += NS_PER_S;
+  // Check we have a nice monotonic timestamp sandwich.
+  ASSERT_LE(ts0.tv_sec, ts1.tv_sec);
+  if (ts0.tv_sec == ts1.tv_sec) {
+    ASSERT_LE(ts0.tv_nsec, ts1.tv_nsec);
   }
-
-  // To try to avoid flakiness we'll accept answers within 10,000,000ns (0.01s).
-  ASSERT_EQ(0, ts2.tv_sec);
-  ASSERT_LT(ts2.tv_nsec, 10'000'000);
+  ASSERT_LE(ts1.tv_sec, ts2.tv_sec);
+  if (ts1.tv_sec == ts2.tv_sec) {
+    ASSERT_LE(ts1.tv_nsec, ts2.tv_nsec);
+  }
 }
 
 TEST(time, clock_gettime_CLOCK_REALTIME) {
@@ -851,11 +849,15 @@
 }
 
 TEST(time, clock) {
-  // clock(3) is hard to test, but a 1s sleep should cost less than 20ms.
+  // clock(3) is hard to test, but a 1s sleep should cost less than 10ms on average.
+  static const clock_t N = 5;
+  static const clock_t mean_limit_ms = 10;
   clock_t t0 = clock();
-  sleep(1);
+  for (size_t i = 0; i < N; ++i) {
+    sleep(1);
+  }
   clock_t t1 = clock();
-  ASSERT_LT(t1 - t0, 20 * (CLOCKS_PER_SEC / 1000));
+  ASSERT_LT(t1 - t0, N * mean_limit_ms * (CLOCKS_PER_SEC / 1000));
 }
 
 static pid_t GetInvalidPid() {
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index 9b4fc4f..d0b5a4a 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -228,14 +228,22 @@
 }
 
 TEST(wchar, wcsstr) {
-  const wchar_t* haystack = L"matches hello world, not the second hello world";
-  const wchar_t* empty_needle = L"";
-  const wchar_t* good_needle = L"ll";
-  const wchar_t* bad_needle = L"wort";
+  const wchar_t* haystack = L"big daddy/giant haystacks!";
+  const wchar_t* empty_haystack = L"";
 
-  ASSERT_EQ(haystack, wcsstr(haystack, empty_needle));
-  ASSERT_EQ(&haystack[10], wcsstr(haystack, good_needle));
-  ASSERT_EQ(nullptr, wcsstr(haystack, bad_needle));
+  // The empty needle is a special case.
+  ASSERT_EQ(haystack, wcsstr(haystack, L""));
+  ASSERT_EQ(empty_haystack, wcsstr(empty_haystack, L""));
+
+  ASSERT_EQ(haystack, wcsstr(haystack, L"b"));
+  ASSERT_EQ(haystack, wcsstr(haystack, L"big"));
+  ASSERT_EQ(haystack + 9, wcsstr(haystack, L"/"));
+  ASSERT_EQ(haystack + 9, wcsstr(haystack, L"/giant"));
+  ASSERT_EQ(haystack + 25, wcsstr(haystack, L"!"));
+  ASSERT_EQ(haystack + 19, wcsstr(haystack, L"stacks!"));
+
+  ASSERT_EQ(nullptr, wcsstr(haystack, L"monkey"));
+  ASSERT_EQ(nullptr, wcsstr(empty_haystack, L"monkey"));
 }
 
 TEST(wchar, wcsstr_80199) {
@@ -646,6 +654,8 @@
   EXPECT_EQ(dst, wcsncpy(dst, src, 6));
   dst[6] = L'\0';
   EXPECT_STREQ(dst, L"Source");
+  EXPECT_EQ(dst, wcsncpy(dst, L"clobber", 0));
+  EXPECT_STREQ(dst, L"Source");
 
   wmemset(dst, L'x', NUM_WCHARS(sizeof(dst)));
   EXPECT_EQ(dst, wcsncpy(dst, src, src_len + 4));
@@ -1024,3 +1034,169 @@
   EXPECT_EQ(2, wcwidth(L'ㅜ')); // Korean "crying" emoticon.
   EXPECT_EQ(2, wcwidth(L'ㅋ')); // Korean "laughing" emoticon.
 }
+
+TEST(wchar, wcswidth) {
+  EXPECT_EQ(2, wcswidth(L"abc", 2));
+  EXPECT_EQ(2, wcswidth(L"ab\t", 2));
+  EXPECT_EQ(-1, wcswidth(L"a\tb", 2));
+}
+
+TEST(wchar, wcslcpy) {
+#if defined(__BIONIC__)
+  wchar_t dst[32];
+  ASSERT_EQ(11U, wcslcpy(dst, L"hello world", 3));
+  ASSERT_STREQ(L"he", dst);
+  ASSERT_EQ(11U, wcslcpy(dst, L"hello world", 32));
+  ASSERT_STREQ(L"hello world", dst);
+#else
+  GTEST_SKIP() << "no wcslcpy in glibc";
+#endif
+}
+
+TEST(wchar, wcscat) {
+  wchar_t dst[32];
+  ASSERT_EQ(dst, wcscat(dst, L"hello"));
+  ASSERT_STREQ(dst, L"hello");
+  ASSERT_EQ(dst, wcscat(dst, L" world"));
+  ASSERT_STREQ(dst, L"hello world");
+}
+
+TEST(wchar, wcscpy) {
+  wchar_t dst[32];
+  ASSERT_EQ(dst, wcscpy(dst, L"hello"));
+  ASSERT_STREQ(dst, L"hello");
+  ASSERT_EQ(dst, wcscpy(dst, L"world"));
+  ASSERT_STREQ(dst, L"world");
+}
+
+TEST(wchar, wcscasecmp) {
+  ASSERT_EQ(0, wcscasecmp(L"hello", L"HELLO"));
+  ASSERT_TRUE(wcscasecmp(L"hello1", L"HELLO2") < 0);
+  ASSERT_TRUE(wcscasecmp(L"hello2", L"HELLO1") > 0);
+  ASSERT_TRUE(wcscasecmp(L"hello", L"HELL") > 0);
+  ASSERT_TRUE(wcscasecmp(L"hell", L"HELLO") < 0);
+}
+
+TEST(wchar, wcscspn) {
+  ASSERT_EQ(0U, wcscspn(L"hello world", L"abcdefghijklmnopqrstuvwxyz"));
+  ASSERT_EQ(5U, wcscspn(L"hello world", L" "));
+  ASSERT_EQ(11U, wcscspn(L"hello world", L"!"));
+}
+
+TEST(wchar, wcsspn) {
+  ASSERT_EQ(0U, wcsspn(L"hello world", L"!"));
+  ASSERT_EQ(5U, wcsspn(L"hello world", L"abcdefghijklmnopqrstuvwxyz"));
+  ASSERT_EQ(11U, wcsspn(L"hello world", L"abcdefghijklmnopqrstuvwxyz "));
+}
+
+TEST(wchar, wcsdup) {
+  wchar_t* s = wcsdup(L"hello");
+  ASSERT_STREQ(s, L"hello");
+  free(s);
+}
+
+TEST(wchar, wcslcat) {
+#if defined(__BIONIC__)
+  wchar_t dst[4] = {};
+  ASSERT_EQ(1U, wcslcat(dst, L"a", 4));
+  ASSERT_EQ(7U, wcslcat(dst, L"bcdefg", 4));
+  ASSERT_STREQ(dst, L"abc");
+#else
+  GTEST_SKIP() << "no wcslcpy in glibc";
+#endif
+}
+
+TEST(wchar, wcsncasecmp) {
+  ASSERT_EQ(0, wcsncasecmp(L"foo", L"bar", 0));
+
+  ASSERT_EQ(0, wcsncasecmp(L"hello1", L"HELLO2", 5));
+  ASSERT_TRUE(wcsncasecmp(L"hello1", L"HELLO2", 6) < 0);
+  ASSERT_TRUE(wcsncasecmp(L"hello2", L"HELLO1", 6) > 0);
+  ASSERT_TRUE(wcsncasecmp(L"hello", L"HELL", 5) > 0);
+  ASSERT_TRUE(wcsncasecmp(L"hell", L"HELLO", 5) < 0);
+}
+
+TEST(wchar, wcsncat) {
+  wchar_t dst[32];
+  ASSERT_EQ(dst, wcsncat(dst, L"hello, world!", 5));
+  ASSERT_STREQ(dst, L"hello");
+  ASSERT_EQ(dst, wcsncat(dst, L"hello, world!", 0));
+  ASSERT_STREQ(dst, L"hello");
+  ASSERT_EQ(dst, wcsncat(dst, L", world!", 8));
+  ASSERT_STREQ(dst, L"hello, world!");
+}
+
+TEST(wchar, wcsncmp) {
+  ASSERT_EQ(0, wcsncmp(L"foo", L"bar", 0));
+  ASSERT_EQ(0, wcsncmp(L"aaaa", L"aaab", 3));
+  ASSERT_TRUE(wcsncmp(L"aaaa", L"aaab", 4) < 0);
+  ASSERT_TRUE(wcsncmp(L"aaab", L"aaaa", 4) > 0);
+}
+
+TEST(wchar, wcsnlen) {
+  ASSERT_EQ(2U, wcsnlen(L"hello", 2));
+  ASSERT_EQ(5U, wcsnlen(L"hello", 5));
+  ASSERT_EQ(5U, wcsnlen(L"hello", 666));
+}
+
+TEST(wchar, wcspbrk) {
+  const wchar_t* s = L"hello, world!";
+  ASSERT_EQ(nullptr, wcspbrk(s, L"-"));
+  ASSERT_EQ(s, wcspbrk(s, L"abch"));
+  ASSERT_EQ(s + 2, wcspbrk(s, L"l"));
+  ASSERT_EQ(s + 5, wcspbrk(s, L",. !"));
+}
+
+TEST(wchar, wcstok) {
+  wchar_t s[] = L"this is\ta\nstring";
+  wchar_t* p;
+  ASSERT_EQ(s, wcstok(s, L"\t\n ", &p));
+  ASSERT_STREQ(s, L"this");
+  ASSERT_STREQ(p, L"is\ta\nstring");
+  ASSERT_EQ(s + 5, wcstok(nullptr, L"\t\n ", &p));
+  ASSERT_STREQ(s + 5, L"is");
+  ASSERT_STREQ(p, L"a\nstring");
+  ASSERT_EQ(s + 8, wcstok(nullptr, L"\t\n ", &p));
+  ASSERT_STREQ(s + 8, L"a");
+  ASSERT_STREQ(p, L"string");
+  ASSERT_EQ(s + 10, wcstok(nullptr, L"\t\n ", &p));
+  ASSERT_STREQ(s + 10, L"string");
+  ASSERT_EQ(nullptr, p);
+}
+
+TEST(wchar, wmemchr) {
+  const wchar_t* s = L"hello, world!";
+  ASSERT_EQ(s, wmemchr(s, L'h', 13));
+  ASSERT_EQ(s + 5, wmemchr(s, L',', 13));
+  ASSERT_EQ(s + 12, wmemchr(s, L'!', 13));
+  ASSERT_EQ(nullptr, wmemchr(s, L'a', 13));
+}
+
+TEST(wchar, wmemcmp) {
+  ASSERT_EQ(0, wmemcmp(L"aaaa", L"aaab", 3));
+  ASSERT_TRUE(wmemcmp(L"aaaa", L"aaab", 4) < 0);
+  ASSERT_TRUE(wmemcmp(L"aaab", L"aaaa", 4) > 0);
+}
+
+TEST(wchar, wmemcpy) {
+  wchar_t dst[32] = {};
+  ASSERT_EQ(dst, wmemcpy(dst, L"hello", 5));
+  ASSERT_STREQ(dst, L"hello");
+}
+
+TEST(wchar, wmemmove) {
+  wchar_t dst[32] = {};
+  ASSERT_EQ(dst, wmemmove(dst, L"hello", 5));
+  ASSERT_STREQ(dst, L"hello");
+}
+
+TEST(wchar, wmemset) {
+  wchar_t dst[4] = {};
+  ASSERT_EQ(dst, wmemset(dst, 0x12345678, 3));
+  ASSERT_EQ(dst[0], wchar_t(0x12345678));
+  ASSERT_EQ(dst[1], wchar_t(0x12345678));
+  ASSERT_EQ(dst[2], wchar_t(0x12345678));
+  ASSERT_EQ(dst[3], wchar_t(0));
+  ASSERT_EQ(dst, wmemset(dst, L'y', 0));
+  ASSERT_EQ(dst[0], wchar_t(0x12345678));
+}
diff --git a/tools/Android.bp b/tools/Android.bp
index 5a54fe4..dcd2a7d 100644
--- a/tools/Android.bp
+++ b/tools/Android.bp
@@ -18,5 +18,4 @@
 filegroup {
     name: "bionic-generate-version-script",
     srcs: ["generate-version-script.py"],
-    bazel_module: { bp2build_available: true },
 }