Merge "Reduce max DNS response from 64K to 8K"
diff --git a/Android.bp b/Android.bp
index dbe5c97..b44c296 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,2 +1 @@
 subdirs = ["*"]
-
diff --git a/README.md b/README.md
index f0be759..a6cf467 100644
--- a/README.md
+++ b/README.md
@@ -144,8 +144,23 @@
 </pre>
 
 
-Adding system calls
--------------------
+Adding libc wrappers for system calls
+-------------------------------------
+
+The first question you should ask is "should I add a libc wrapper for
+this system call?". The answer is usually "no".
+
+The answer is "yes" if the system call is part of the POSIX standard.
+
+The answer is probably "yes" if the system call has a wrapper in at
+least one other C library.
+
+The answer may be "yes" if the system call has three/four distinct
+users in different projects, and there isn't a more specific library
+that would make more sense as the place to add the wrapper.
+
+In all other cases, you should use
+[syscall(3)](http://man7.org/linux/man-pages/man2/syscall.2.html) instead.
 
 Adding a system call usually involves:
 
@@ -157,7 +172,8 @@
      kernel uapi header files, in which case you just need to make sure that
      the appropriate POSIX header file in libc/include/ includes the
      relevant file or files.
-  4. Add function declarations to the appropriate header file.
+  4. Add function declarations to the appropriate header file. Don't forget
+     to include the appropriate `__INTRODUCED_IN()`.
   5. Add the function name to the correct section in libc/libc.map.txt and
      run `./libc/tools/genversion-scripts.py`.
   6. Add at least basic tests. Even a test that deliberately supplies
diff --git a/benchmarks/Android.bp b/benchmarks/Android.bp
index 115236b..f6d0e4d 100644
--- a/benchmarks/Android.bp
+++ b/benchmarks/Android.bp
@@ -67,7 +67,7 @@
         "libsystemproperties",
         "libasync_safe",
     ],
-    include_dirs: ["bionic/libc",],
+    include_dirs: ["bionic/libc"],
 }
 
 // We don't build a static benchmark executable because it's not usually
@@ -107,5 +107,8 @@
         "libbase",
         "libBionicBenchmarksUtils",
     ],
-    data: ["suites/*", "test_suites/*"],
+    data: [
+        "suites/*",
+        "test_suites/*",
+    ],
 }
diff --git a/benchmarks/property_benchmark.cpp b/benchmarks/property_benchmark.cpp
index 9868765..17e37b0 100644
--- a/benchmarks/property_benchmark.cpp
+++ b/benchmarks/property_benchmark.cpp
@@ -98,7 +98,7 @@
       return;
     }
 
-    system_properties_.contexts()->FreeAndUnmap();
+    system_properties_.contexts_->FreeAndUnmap();
 
     for (int i = 0; i < nprops; i++) {
       delete names[i];
diff --git a/benchmarks/pthread_benchmark.cpp b/benchmarks/pthread_benchmark.cpp
index 46d6e64..c72736e 100644
--- a/benchmarks/pthread_benchmark.cpp
+++ b/benchmarks/pthread_benchmark.cpp
@@ -96,7 +96,6 @@
 }
 BIONIC_BENCHMARK(BM_pthread_mutex_lock_RECURSIVE);
 
-#if defined(__LP64__)
 namespace {
 struct PIMutex {
   pthread_mutex_t mutex;
@@ -145,7 +144,6 @@
   }
 }
 BIONIC_BENCHMARK(BM_pthread_mutex_lock_RECURSIVE_PI);
-#endif  // defined(__LP64__)
 
 static void BM_pthread_rwlock_read(benchmark::State& state) {
   pthread_rwlock_t lock;
diff --git a/benchmarks/util.h b/benchmarks/util.h
index 3225bc2..d9e10f4 100644
--- a/benchmarks/util.h
+++ b/benchmarks/util.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef _BIONIC_BENCHMARKS_UTIL_H_
-#define _BIONIC_BENCHMARKS_UTIL_H_
+#pragma once
 
 #include <map>
 #include <mutex>
@@ -62,5 +61,3 @@
 char* GetAlignedPtrFilled(std::vector<char>* buf, size_t alignment, size_t nbytes, char fill_byte);
 
 bool LockToCPU(long cpu_to_lock);
-
-#endif // _BIONIC_BENCHMARKS_UTIL_H
diff --git a/docs/32-bit-abi.md b/docs/32-bit-abi.md
index 9ae1973..0ea94d4 100644
--- a/docs/32-bit-abi.md
+++ b/docs/32-bit-abi.md
@@ -59,15 +59,27 @@
 
 In the 64-bit ABI, `off_t` is always 64-bit.
 
+For source compatibility, the names containing `64` are also available
+in the 64-bit ABI even though they're identical to the non-`64` names.
+
 
 ## `sigset_t` is too small for real-time signals
 
 On 32-bit Android, `sigset_t` is too small for ARM and x86 (but correct for
 MIPS). This means that there is no support for real-time signals in 32-bit
-code.
+code. Android P (API level 28) adds `sigset64_t` and a corresponding function
+for every function that takes a `sigset_t` (so `sigprocmask64` takes a
+`sigset64_t` where `sigprocmask` takes a `sigset_t`).
+
+On 32-bit Android, `struct sigaction` is also too small because it contains
+a `sigset_t`. We also offer a `struct sigaction64` and `sigaction64` function
+to work around this.
 
 In the 64-bit ABI, `sigset_t` is the correct size for every architecture.
 
+For source compatibility, the names containing `64` are also available
+in the 64-bit ABI even though they're identical to the non-`64` names.
+
 
 ## `time_t` is 32-bit
 
@@ -77,10 +89,11 @@
 
 In the 64-bit ABI, `time_t` is 64-bit.
 
+
 ## `pthread_mutex_t` is too small for large pids
 
 This doesn't generally affect Android devices, because on devices
-`/proc/sys/kernel/pid_max` is usually too small to hit the 16-bit limit,
+`/proc/sys/kernel/pid_max` is usually too small to hit our 16-bit limit,
 but 32-bit bionic's `pthread_mutex` is a total of 32 bits, leaving just
 16 bits for the owner thread id. This means bionic isn't able to support
 mutexes for tids that don't fit in 16 bits. This typically manifests as
diff --git a/docs/status.md b/docs/status.md
index 8cef5b7..2666e58 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -49,11 +49,12 @@
   * `iconv`/`iconv_close`/`iconv_open` (adding <iconv.h>)
   * `pthread_attr_getinheritsched`/`pthread_attr_setinheritsched`/`pthread_setschedprio`
   * `pthread_mutexattr_getprotocol`/`pthread_mutexattr_setprotocol` (mutex priority inheritance)
+  * <signal.h> support for `sigaction64_t` and `sigset64_t` allowing LP32 access to real-time signals
   * <spawn.h>
   * `swab`
   * `syncfs`
-  * `%C` and `%S` support in the printf family (previously only the wprintf family supported these).
-  * `%mc`/`%ms`/`%m[` support in the scanf family.
+  * `%C` and `%S` support in the printf family (previously only the wprintf family supported these)
+  * `%mc`/`%ms`/`%m[` support in the scanf family
 
 New libc functions in O:
   * `sendto` FORTIFY support
diff --git a/libc/Android.bp b/libc/Android.bp
index 2ea8514..7454d03 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -33,6 +33,7 @@
 
 libc_common_flags = [
     "-D_LIBC=1",
+    "-D__BIONIC_LP32_USE_STAT64",
     "-Wall",
     "-Wextra",
     "-Wunused",
@@ -46,6 +47,10 @@
     "-Werror=int-to-pointer-cast",
     "-Werror=type-limits",
     "-Werror",
+
+    // Clang's exit-time destructor registration hides __dso_handle, but
+    // __dso_handle needs to have default visibility on ARM32. See b/73485611.
+    "-Wexit-time-destructors",
 ]
 
 // Define some common cflags
@@ -538,7 +543,7 @@
 cc_library_static {
     defaults: ["libc_defaults"],
     srcs: [
-        // These two depend on getentropy_linux.c, which isn't in libc_ndk.a.
+        // These two depend on getentropy, which isn't in libc_ndk.a.
         "upstream-openbsd/lib/libc/crypt/arc4random.c",
         "upstream-openbsd/lib/libc/crypt/arc4random_uniform.c",
 
@@ -709,7 +714,10 @@
 
     // Disable FORTIFY for the compilation of these, so we don't end up having
     // FORTIFY silently call itself.
-    cflags: ["-U_FORTIFY_SOURCE", "-D__BIONIC_DECLARE_FORTIFY_HELPERS"],
+    cflags: [
+        "-U_FORTIFY_SOURCE",
+        "-D__BIONIC_DECLARE_FORTIFY_HELPERS",
+    ],
 
     arch: {
         arm: {
@@ -718,7 +726,10 @@
                 "arch-arm/generic/bionic/__memcpy_chk.S",
             ],
             neon: {
-                cflags: ["-DNO___STRCAT_CHK", "-DNO___STRCPY_CHK"],
+                cflags: [
+                    "-DNO___STRCAT_CHK",
+                    "-DNO___STRCPY_CHK",
+                ],
                 srcs: [
                     "arch-arm/cortex-a15/bionic/__strcat_chk.S",
                     "arch-arm/cortex-a15/bionic/__strcpy_chk.S",
@@ -817,9 +828,7 @@
         // initialized, resulting in nullptr dereferences.
         "bionic/getauxval.cpp",
 
-        // These four require getauxval, which isn't available on older
-        // platforms.
-        "bionic/getentropy_linux.c",
+        // These require getauxval, which isn't available on older platforms.
         "bionic/sysconf.cpp",
         "bionic/vdso.cpp",
         "bionic/setjmp_cookie.cpp",
@@ -1248,9 +1257,6 @@
         "bionic/dirent.cpp",
         "bionic/dup2.cpp",
         "bionic/environ.cpp",
-        "bionic/epoll_create.cpp",
-        "bionic/epoll_pwait.cpp",
-        "bionic/epoll_wait.cpp",
         "bionic/error.cpp",
         "bionic/eventfd_read.cpp",
         "bionic/eventfd_write.cpp",
@@ -1269,6 +1275,7 @@
         "bionic/futimens.cpp",
         "bionic/getcwd.cpp",
         "bionic/getdomainname.cpp",
+        "bionic/getentropy.cpp",
         "bionic/gethostname.cpp",
         "bionic/getpagesize.cpp",
         "bionic/getpgrp.cpp",
@@ -1276,6 +1283,7 @@
         "bionic/getpriority.cpp",
         "bionic/gettid.cpp",
         "bionic/grp_pwd.cpp",
+        "bionic/grp_pwd_file.cpp",
         "bionic/iconv.cpp",
         "bionic/icu_wrappers.cpp",
         "bionic/ifaddrs.cpp",
@@ -1334,6 +1342,7 @@
         "bionic/setpgrp.cpp",
         "bionic/sigaction.cpp",
         "bionic/signal.cpp",
+        "bionic/sigprocmask.cpp",
         "bionic/socket.cpp",
         "bionic/spawn.cpp",
         "bionic/stat.cpp",
@@ -1350,6 +1359,7 @@
         "bionic/swab.cpp",
         "bionic/symlink.cpp",
         "bionic/sync_file_range.cpp",
+        "bionic/sys_epoll.cpp",
         "bionic/sys_msg.cpp",
         "bionic/sys_sem.cpp",
         "bionic/sys_shm.cpp",
@@ -1431,7 +1441,6 @@
         "bionic/pthread_self.cpp",
         "bionic/pthread_setname_np.cpp",
         "bionic/pthread_setschedparam.cpp",
-        "bionic/pthread_sigmask.cpp",
         "bionic/pthread_spinlock.cpp",
 
         // The following implementations depend on pthread data or implementation,
@@ -1699,7 +1708,10 @@
         "ld-android",
         "libdl",
     ],
-    whole_static_libs: ["libc_common", "libjemalloc"],
+    whole_static_libs: [
+        "libc_common",
+        "libjemalloc",
+    ],
 
     nocrt: true,
 
@@ -1797,7 +1809,11 @@
     defaults: ["linux_bionic_supported"],
     vendor_available: true,
 
-    cflags: ["-Wno-gcc-compat", "-Wall", "-Werror"],
+    cflags: [
+        "-Wno-gcc-compat",
+        "-Wall",
+        "-Werror",
+    ],
 }
 
 cc_defaults {
diff --git a/libc/NOTICE b/libc/NOTICE
index daf8491..f9a2aff 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -5511,26 +5511,6 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
-Copyright (c) 2014 Bob Beck <beck@obtuse.com>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-Emulation of getentropy(2) as documented at:
-http://man.openbsd.org/getentropy.2
-
--------------------------------------------------------------------
-
 Copyright (c) 2014, Intel Corporation
 All rights reserved.
 
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 5c9a284..5c63c0f 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -229,12 +229,12 @@
 # signals
 int     __sigaction:sigaction(int, const struct sigaction*, struct sigaction*)  arm,mips,x86
 int     __rt_sigaction:rt_sigaction(int, const struct sigaction*, struct sigaction*, size_t)  all
-int     __rt_sigpending:rt_sigpending(sigset_t*, size_t)  all
-int     __rt_sigprocmask:rt_sigprocmask(int, const sigset_t*, sigset_t*, size_t)  all
-int     __rt_sigsuspend:rt_sigsuspend(const sigset_t*, size_t)  all
-int     __rt_sigtimedwait:rt_sigtimedwait(const sigset_t*, siginfo_t*, const timespec*, size_t)  all
+int     __rt_sigpending:rt_sigpending(sigset64_t*, size_t)  all
+int     __rt_sigprocmask:rt_sigprocmask(int, const sigset64_t*, sigset64_t*, size_t)  all
+int     __rt_sigsuspend:rt_sigsuspend(const sigset64_t*, size_t)  all
+int     __rt_sigtimedwait:rt_sigtimedwait(const sigset64_t*, siginfo_t*, const timespec*, size_t)  all
 int     ___rt_sigqueueinfo:rt_sigqueueinfo(pid_t, int, siginfo_t*)  all
-int     __signalfd4:signalfd4(int, const sigset_t*, size_t, int)  all
+int     __signalfd4:signalfd4(int, const sigset64_t*, size_t, int)  all
 
 # sockets
 int           __socket:socket(int, int, int)              arm,arm64,mips,mips64,x86_64
@@ -305,7 +305,7 @@
 
 int epoll_create1(int)  all
 int epoll_ctl(int, int op, int, struct epoll_event*)  all
-int __epoll_pwait:epoll_pwait(int, struct epoll_event*, int, int, const sigset_t*, size_t)  all
+int __epoll_pwait:epoll_pwait(int, struct epoll_event*, int, int, const sigset64_t*, size_t)  all
 
 int eventfd:eventfd2(unsigned int, int)  all
 
@@ -317,7 +317,7 @@
 int inotify_rm_watch(int, unsigned int)  all
 
 int __pselect6:pselect6(int, fd_set*, fd_set*, fd_set*, timespec*, void*)  all
-int __ppoll:ppoll(pollfd*, unsigned int, timespec*, const sigset_t*, size_t)  all
+int __ppoll:ppoll(pollfd*, unsigned int, timespec*, const sigset64_t*, size_t)  all
 
 ssize_t process_vm_readv(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long)  all
 ssize_t process_vm_writev(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long)  all
diff --git a/libc/arch-arm/bionic/exidx_static.c b/libc/arch-arm/bionic/exidx_static.c
index 1686d6a..ef3745f 100644
--- a/libc/arch-arm/bionic/exidx_static.c
+++ b/libc/arch-arm/bionic/exidx_static.c
@@ -35,10 +35,15 @@
  * EXIDX section.
  */
 
-extern unsigned __exidx_end;
-extern unsigned __exidx_start;
+struct exidx_entry {
+  uint32_t key;
+  uint32_t value;
+};
+
+extern struct exidx_entry __exidx_end;
+extern struct exidx_entry __exidx_start;
 
 _Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr pc __attribute__((unused)), int* pcount) {
-  *pcount = (&__exidx_end - &__exidx_start) / 8;
+  *pcount = (&__exidx_end - &__exidx_start);
   return (_Unwind_Ptr)&__exidx_start;
 }
diff --git a/libc/arch-arm/bionic/setjmp.S b/libc/arch-arm/bionic/setjmp.S
index b814124..5fbcaf3 100644
--- a/libc/arch-arm/bionic/setjmp.S
+++ b/libc/arch-arm/bionic/setjmp.S
@@ -56,21 +56,21 @@
 //
 // word   name            description
 // 0      sigflag/cookie  setjmp cookie in top 31 bits, signal mask flag in low bit
-// 1      sigmask         signal mask (not used with _setjmp / _longjmp)
-// 2      float_base      base of float registers (d8 to d15)
-// 18     float_state     floating-point status and control register
-// 19     core_base       base of core registers (r4-r11, r13-r14)
-// 29     checksum        checksum of all of the core registers, to give better error messages.
-// 30     reserved        reserved entries (room to grow)
-// 64
-//
-// NOTE: float_base must be at an even word index, since the
-//       FP registers will be loaded/stored with instructions
-//       that expect 8-byte alignment.
+// 1      sigmask         64-bit signal mask (not used with _setjmp / _longjmp)
+// 2      "               "
+// 3      reserved        (unused to allow float_base to be maximally aligned;
+//                        this avoids software emulation of unaligned loads/stores)
+// 4      float_base      base of float registers (d8 to d15)
+// 20     float_state     floating-point status and control register
+// 21     core_base       base of core registers (r4-r11, r13-r14)
+// 31     checksum        checksum of all of the core registers, to give better error messages
+// 32     reserved        reserved entries (room to grow)
+// ...
+// 63     "               "
 
 #define _JB_SIGFLAG     0
-#define _JB_SIGMASK     (_JB_SIGFLAG+1)
-#define _JB_FLOAT_BASE  (_JB_SIGMASK+1)
+#define _JB_SIGMASK     (_JB_SIGFLAG + 1)
+#define _JB_FLOAT_BASE  (_JB_SIGMASK + 3)
 #define _JB_FLOAT_STATE (_JB_FLOAT_BASE + (15-8+1)*2)
 #define _JB_CORE_BASE   (_JB_FLOAT_STATE+1)
 #define _JB_CHECKSUM    (_JB_CORE_BASE+10)
@@ -151,7 +151,7 @@
   add r2, r0, #(_JB_SIGMASK * 4)
   mov r0, #2 // SIG_SETMASK
   mov r1, #0
-  bl sigprocmask
+  bl sigprocmask64
 
   // Unalign the stack.
   add sp, #4
@@ -218,8 +218,10 @@
   beq 1f
 
   // Restore the signal mask.
-  ldr r0, [r0, #(_JB_SIGMASK * 4)]
-  bl sigsetmask
+  mov r2, #0
+  add r1, r0, #(_JB_SIGMASK * 4)
+  mov r0, #2 // SIG_SETMASK
+  bl sigprocmask64
 
 1:
   ldmfd sp!, {r0, r1, lr}
diff --git a/libc/arch-arm/generic/bionic/strlen.c b/libc/arch-arm/generic/bionic/strlen.c
index dccd564..44bd72f 100644
--- a/libc/arch-arm/generic/bionic/strlen.c
+++ b/libc/arch-arm/generic/bionic/strlen.c
@@ -29,7 +29,7 @@
 #include <string.h>
 #include <stdint.h>
 
-size_t strlen(const char *s) __overloadable
+size_t strlen(const char *s)
 {
     __builtin_prefetch(s);
     __builtin_prefetch(s+32);
diff --git a/libc/arch-common/bionic/crtbegin.c b/libc/arch-common/bionic/crtbegin.c
index 31ad621..c4d2a5a 100644
--- a/libc/arch-common/bionic/crtbegin.c
+++ b/libc/arch-common/bionic/crtbegin.c
@@ -53,7 +53,7 @@
 #elif defined(__arm__)
 __asm__(PRE "mov r0,sp; b _start_main" POST);
 #elif defined(__i386__)
-__asm__(PRE "movl %esp,%eax; andl $~0xf,%esp; pushl %eax; calll _start_main" POST);
+__asm__(PRE "movl %esp,%eax; andl $~0xf,%esp; subl $12,%esp; pushl %eax; calll _start_main" POST);
 #elif defined(__x86_64__)
 __asm__(PRE "movq %rsp,%rdi; andq $~0xf,%rsp; callq _start_main" POST);
 #else
diff --git a/libc/arch-common/bionic/pthread_atfork.h b/libc/arch-common/bionic/pthread_atfork.h
index c6a33ff..742d078 100644
--- a/libc/arch-common/bionic/pthread_atfork.h
+++ b/libc/arch-common/bionic/pthread_atfork.h
@@ -16,9 +16,9 @@
 
 #include <android/api-level.h>
 
-// __register_atfork wasn't available until android-23. We need to build a
-// pre-23 and 23+ version of crtbegin.
-#if __ANDROID_API__ >= __ANDROID_API_M__
+// __register_atfork wasn't available until android-23. When using libc.a, we're
+// using the latest library regardless of target API level.
+#if defined(_FORCE_CRT_ATFORK) || __ANDROID_API__ >= __ANDROID_API_M__
 
 extern void* __dso_handle;
 
diff --git a/libc/arch-mips/string/memchr.c b/libc/arch-mips/string/memchr.c
index 6b4c8cc..bc24f79 100644
--- a/libc/arch-mips/string/memchr.c
+++ b/libc/arch-mips/string/memchr.c
@@ -100,7 +100,7 @@
 }
 
 void *
-memchr (void const *s, int c_in, size_t n) __overloadable
+memchr (void const *s, int c_in, size_t n)
 {
   if (n != 0) {
     const unsigned char *p = (const unsigned char *) s;
diff --git a/libc/arch-mips/string/memcpy.c b/libc/arch-mips/string/memcpy.c
index 68827b6..bb0d179 100644
--- a/libc/arch-mips/string/memcpy.c
+++ b/libc/arch-mips/string/memcpy.c
@@ -286,7 +286,7 @@
 }
 
 void *
-memcpy (void *a, const void *b, size_t len) __overloadable
+memcpy (void *a, const void *b, size_t len)
 {
   unsigned long bytes, words;
   void *ret = a;
diff --git a/libc/arch-mips/string/memmove.c b/libc/arch-mips/string/memmove.c
index fbff297..74d4cd0 100644
--- a/libc/arch-mips/string/memmove.c
+++ b/libc/arch-mips/string/memmove.c
@@ -383,7 +383,7 @@
 }
 
 void *
-memmove (void *dst0, const void *src0, size_t length) __overloadable
+memmove (void *dst0, const void *src0, size_t length)
 {
   unsigned long bytes, words;
   void *ret = dst0;
diff --git a/libc/arch-mips/string/strchr.c b/libc/arch-mips/string/strchr.c
index c9397e7..3458f66 100644
--- a/libc/arch-mips/string/strchr.c
+++ b/libc/arch-mips/string/strchr.c
@@ -92,7 +92,7 @@
   return (char *)p;
 }
 
-char* strchr(const char* s, int c) __overloadable
+char* strchr(const char* s, int c)
 {
   const op_t *w;
   op_t mask_1, mask_128, mask_c;
diff --git a/libc/arch-mips/string/strcpy.c b/libc/arch-mips/string/strcpy.c
index 7b5dee3..b77105e 100644
--- a/libc/arch-mips/string/strcpy.c
+++ b/libc/arch-mips/string/strcpy.c
@@ -167,7 +167,7 @@
 }
 
 char *
-strcpy (char *to, const char *from) __overloadable
+strcpy (char *to, const char *from)
 {
   char *ret = to;
   op_t mask_1, mask_128;
diff --git a/libc/arch-mips/string/strlen.c b/libc/arch-mips/string/strlen.c
index 491efae..28463f6 100644
--- a/libc/arch-mips/string/strlen.c
+++ b/libc/arch-mips/string/strlen.c
@@ -79,7 +79,7 @@
 #endif
 
 size_t
-strlen (const char *str) __overloadable
+strlen (const char *str)
 {
   if (*str) {
     const char *p = (const char *) str;
diff --git a/libc/arch-x86/bionic/setjmp.S b/libc/arch-x86/bionic/setjmp.S
index 6e6c365..1e1ce58 100644
--- a/libc/arch-x86/bionic/setjmp.S
+++ b/libc/arch-x86/bionic/setjmp.S
@@ -42,10 +42,10 @@
 // 3      ebp
 // 4      esi
 // 5      edi
-// 6      sigmask         signal mask (not used with _setjmp / _longjmp)
-// 7      sigflag/cookie  setjmp cookie in top 31 bits, signal mask flag in low bit
-// 8      checksum        checksum of the core registers, to give better error messages.
-// 9      reserved
+// 6      sigmask         64-bit signal mask (not used with _setjmp / _longjmp)
+// 7      "               "
+// 8      sigflag/cookie  setjmp cookie in top 31 bits, signal mask flag in low bit
+// 9      checksum        checksum of the core registers, to give better error messages.
 
 #define _JB_EDX 0
 #define _JB_EBX 1
@@ -54,8 +54,8 @@
 #define _JB_ESI 4
 #define _JB_EDI 5
 #define _JB_SIGMASK 6
-#define _JB_SIGFLAG 7
-#define _JB_CHECKSUM 8
+#define _JB_SIGFLAG 8
+#define _JB_CHECKSUM 9
 
 .macro m_mangle_registers reg
   xorl \reg,%edx
@@ -110,16 +110,17 @@
   testl $1,%eax
   jz 1f
 
-  // Get the current signal mask.
+  // Save the current signal mask.
+  pushl %ecx
   PIC_PROLOGUE
-  pushl $0
-  call PIC_PLT(sigblock)
-  addl $4,%esp
+  leal (_JB_SIGMASK * 4)(%ecx),%eax
+  pushl %eax
+  pushl $0 // NULL
+  pushl $2 // SIG_SETMASK
+  call PIC_PLT(sigprocmask64)
+  addl $12,%esp
   PIC_EPILOGUE
-
-  // Save the signal mask.
-  movl 4(%esp),%ecx
-  movl %eax,(_JB_SIGMASK * 4)(%ecx)
+  popl %ecx
 
 1:
   // Fetch the setjmp cookie and clear the signal flag bit.
@@ -159,10 +160,13 @@
   jz 1f
 
   // Restore the signal mask.
+  leal (_JB_SIGMASK * 4)(%edx),%eax
   PIC_PROLOGUE
-  pushl (_JB_SIGMASK * 4)(%edx)
-  call PIC_PLT(sigsetmask)
-  addl $4,%esp
+  pushl $0 // NULL
+  pushl %eax
+  pushl $2 // SIG_SETMASK
+  call PIC_PLT(sigprocmask64)
+  addl $12,%esp
   PIC_EPILOGUE
 
 1:
diff --git a/libc/async_safe/include/async_safe/log.h b/libc/async_safe/include/async_safe/log.h
index 10833e4..415b48e 100644
--- a/libc/async_safe/include/async_safe/log.h
+++ b/libc/async_safe/include/async_safe/log.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _ASYNC_SAFE_LOG_LOG_H
-#define _ASYNC_SAFE_LOG_LOG_H
+#pragma once
 
 #include <sys/cdefs.h>
 #include <stdarg.h>
@@ -104,5 +103,3 @@
   } while(0)
 
 __END_DECLS
-
-#endif
diff --git a/libc/bionic/__libc_current_sigrtmin.cpp b/libc/bionic/__libc_current_sigrtmin.cpp
index 04caa89..d2ea75d 100644
--- a/libc/bionic/__libc_current_sigrtmin.cpp
+++ b/libc/bionic/__libc_current_sigrtmin.cpp
@@ -28,14 +28,8 @@
 
 #include <signal.h>
 
-// Realtime signals reserved for internal use:
-//   32 (__SIGRTMIN + 0)        POSIX timers
-//   33 (__SIGRTMIN + 1)        libbacktrace
-//   34 (__SIGRTMIN + 2)        libcore
-//   35 (__SIGRTMIN + 3)        debuggerd -b
+#include "private/sigrtmin.h"
 
-int __libc_current_sigrtmin(void) {
-  // If you change this, also change __ndk_legacy___libc_current_sigrtmin
-  // in <android/legacy_signal_inlines.h> to match.
-  return __SIGRTMIN + 4;
+int __libc_current_sigrtmin() {
+  return __SIGRTMIN + __SIGRT_RESERVED;
 }
diff --git a/libc/bionic/abort.cpp b/libc/bionic/abort.cpp
index 9f1c31f..d2c99a5 100644
--- a/libc/bionic/abort.cpp
+++ b/libc/bionic/abort.cpp
@@ -32,8 +32,6 @@
 #include <sys/syscall.h>
 #include <unistd.h>
 
-#include "private/kernel_sigset_t.h"
-
 // We call tgkill(2) directly instead of raise (or even the libc tgkill wrapper), to reduce the
 // number of uninteresting stack frames at the top of a crash.
 static inline __always_inline void inline_tgkill(pid_t pid, pid_t tid, int sig) {
@@ -62,22 +60,19 @@
 
   // Don't block SIGABRT to give any signal handler a chance; we ignore
   // any errors -- X311J doesn't allow abort to return anyway.
-  kernel_sigset_t mask;
-  mask.fill();
-  mask.clear(SIGABRT);
-  __rt_sigprocmask(SIG_SETMASK, &mask, nullptr, sizeof(mask));
+  sigset64_t mask;
+  sigfillset64(&mask);
+  sigdelset64(&mask, SIGABRT);
 
+  sigprocmask64(SIG_SETMASK, &mask, nullptr);
   inline_tgkill(pid, tid, SIGABRT);
 
-  // If SIGABRT ignored, or caught and the handler returns,
+  // If SIGABRT is ignored or it's caught and the handler returns,
   // remove the SIGABRT signal handler and raise SIGABRT again.
-  struct sigaction sa;
-  sa.sa_handler = SIG_DFL;
-  sa.sa_flags   = SA_RESTART;
-  sigemptyset(&sa.sa_mask);
-  sigaction(SIGABRT, &sa, &sa);
-  __rt_sigprocmask(SIG_SETMASK, &mask, nullptr, sizeof(mask));
+  struct sigaction64 sa = { .sa_handler = SIG_DFL, .sa_flags = SA_RESTART };
+  sigaction64(SIGABRT, &sa, nullptr);
 
+  sigprocmask64(SIG_SETMASK, &mask, nullptr);
   inline_tgkill(pid, tid, SIGABRT);
 
   // If we get this far, just exit.
diff --git a/libc/bionic/bionic_arc4random.cpp b/libc/bionic/bionic_arc4random.cpp
index 391eb0c..fa2617f 100644
--- a/libc/bionic/bionic_arc4random.cpp
+++ b/libc/bionic/bionic_arc4random.cpp
@@ -28,8 +28,6 @@
 
 #include "private/bionic_arc4random.h"
 
-#include <errno.h>
-#include <stdatomic.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/auxv.h>
@@ -39,15 +37,12 @@
 
 #include "private/KernelArgumentBlock.h"
 
-bool __libc_arc4random_has_unlimited_entropy() {
-  static bool have_urandom = access("/dev/urandom", R_OK) == 0;
-  return have_urandom;
-}
-
 void __libc_safe_arc4random_buf(void* buf, size_t n, KernelArgumentBlock& args) {
-  // Only call arc4random_buf once we `have_urandom', since in getentropy_getrandom we may fallback
-  // to use /dev/urandom, if the kernel entropy pool hasn't been initialized or not enough bytes
-  if (__libc_arc4random_has_unlimited_entropy()) {
+  // Only call arc4random_buf once we have `/dev/urandom` because getentropy(3)
+  // will fall back to using `/dev/urandom` if getrandom(2) fails, and abort if
+  // if can't use `/dev/urandom`.
+  static bool have_urandom = access("/dev/urandom", R_OK) == 0;
+  if (have_urandom) {
     arc4random_buf(buf, n);
     return;
   }
diff --git a/libc/bionic/bionic_netlink.h b/libc/bionic/bionic_netlink.h
index bc0e3f0..a21200e 100644
--- a/libc/bionic/bionic_netlink.h
+++ b/libc/bionic/bionic_netlink.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef BIONIC_NETLINK_H
-#define BIONIC_NETLINK_H
+#pragma once
 
 #include <sys/types.h>
 
@@ -49,5 +48,3 @@
   char* data_;
   size_t size_;
 };
-
-#endif
diff --git a/libc/bionic/bionic_systrace.cpp b/libc/bionic/bionic_systrace.cpp
index 970a92b..bac3d88 100644
--- a/libc/bionic/bionic_systrace.cpp
+++ b/libc/bionic/bionic_systrace.cpp
@@ -29,12 +29,11 @@
 #define WRITE_OFFSET   32
 
 static Lock g_lock;
+static CachedProperty g_debug_atrace_tags_enableflags("debug.atrace.tags.enableflags");
+static uint64_t g_tags;
 static int g_trace_marker_fd = -1;
 
 static bool should_trace() {
-  static CachedProperty g_debug_atrace_tags_enableflags("debug.atrace.tags.enableflags");
-  static uint64_t g_tags;
-
   g_lock.lock();
   if (g_debug_atrace_tags_enableflags.DidChange()) {
     g_tags = strtoull(g_debug_atrace_tags_enableflags.Get(), nullptr, 0);
diff --git a/libc/bionic/epoll_wait.cpp b/libc/bionic/epoll_wait.cpp
deleted file mode 100644
index deb19da..0000000
--- a/libc/bionic/epoll_wait.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2013 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/epoll.h>
-
-int epoll_wait(int fd, struct epoll_event* events, int max_events, int timeout) {
-  return epoll_pwait(fd, events, max_events, timeout, NULL);
-}
diff --git a/libc/bionic/getcwd.cpp b/libc/bionic/getcwd.cpp
index 50487ec..a8bbcf3 100644
--- a/libc/bionic/getcwd.cpp
+++ b/libc/bionic/getcwd.cpp
@@ -33,7 +33,7 @@
 
 extern "C" int __getcwd(char* buf, size_t size);
 
-char* getcwd(char* buf, size_t size) __overloadable {
+char* getcwd(char* buf, size_t size) {
   // You can't specify size 0 unless you're asking us to allocate for you.
   if (buf != NULL && size == 0) {
     errno = EINVAL;
diff --git a/libc/bionic/getentropy.cpp b/libc/bionic/getentropy.cpp
new file mode 100644
index 0000000..2c6e417
--- /dev/null
+++ b/libc/bionic/getentropy.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2018 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 <errno.h>
+#include <fcntl.h>
+#include <sys/random.h>
+#include <unistd.h>
+
+static int getentropy_urandom(void* buffer, size_t buffer_size, int saved_errno) {
+  int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_NOFOLLOW | O_CLOEXEC, 0));
+  if (fd == -1) return -1;
+
+  size_t collected = 0;
+  while (collected < buffer_size) {
+    ssize_t count = TEMP_FAILURE_RETRY(read(fd, static_cast<char*>(buffer) + collected,
+                                            buffer_size - collected));
+    if (count == -1) {
+      close(fd);
+      return -1;
+    }
+    collected += count;
+  }
+
+  close(fd);
+  errno = saved_errno;
+  return 0;
+}
+
+int getentropy(void* buffer, size_t buffer_size) {
+  if (buffer_size > 256) {
+    errno = EIO;
+    return -1;
+  }
+
+  int saved_errno = errno;
+
+  size_t collected = 0;
+  while (collected < buffer_size) {
+    long count = TEMP_FAILURE_RETRY(getrandom(static_cast<char*>(buffer) + collected,
+                                              buffer_size - collected, GRND_NONBLOCK));
+    if (count == -1) {
+      // EAGAIN: there isn't enough entropy right now.
+      // ENOSYS/EINVAL: getrandom(2) or GRND_NONBLOCK isn't supported.
+      // EFAULT: `buffer` is invalid.
+      // Try /dev/urandom regardless because it can't hurt,
+      // and we don't need to optimize the EFAULT case.
+      // See http://b/33059407 and http://b/67015565.
+      return getentropy_urandom(buffer, buffer_size, saved_errno);
+    }
+    collected += count;
+  }
+
+  errno = saved_errno;
+  return 0;
+}
diff --git a/libc/bionic/getentropy_linux.c b/libc/bionic/getentropy_linux.c
deleted file mode 100644
index cf0aa45..0000000
--- a/libc/bionic/getentropy_linux.c
+++ /dev/null
@@ -1,552 +0,0 @@
-/*	$OpenBSD: getentropy_linux.c,v 1.42 2016/04/19 20:20:24 tj Exp $	*/
-
-/*
- * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
- * Copyright (c) 2014 Bob Beck <beck@obtuse.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Emulation of getentropy(2) as documented at:
- * http://man.openbsd.org/getentropy.2
- */
-
-#define	_POSIX_C_SOURCE	199309L
-#define	_GNU_SOURCE	1
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/ioctl.h>
-#include <sys/resource.h>
-#include <sys/syscall.h>
-#ifdef SYS__sysctl
-#include <linux/sysctl.h>
-#endif
-#include <sys/statvfs.h>
-#include <sys/socket.h>
-#include <sys/mount.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <link.h>
-#include <termios.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#ifdef HAVE_OPENSSL
-#include <openssl/sha.h>
-#endif
-
-#include <linux/types.h>
-#include <linux/random.h>
-#ifdef HAVE_GETAUXVAL
-#include <sys/auxv.h>
-#endif
-#include <sys/vfs.h>
-
-#define REPEAT 5
-#define min(a, b) (((a) < (b)) ? (a) : (b))
-
-#define HX(a, b) \
-	do { \
-		if ((a)) \
-			HD(errno); \
-		else \
-			HD(b); \
-	} while (0)
-
-#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
-#define HD(x)	 (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
-#define HF(x)    (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
-
-int	getentropy(void *buf, size_t len);
-
-static int gotdata(char *buf, size_t len);
-static int getentropy_getrandom(void *buf, size_t len);
-static int getentropy_urandom(void *buf, size_t len);
-#ifdef SYS__sysctl
-static int getentropy_sysctl(void *buf, size_t len);
-#endif
-#ifdef HAVE_OPENSSL
-static int getentropy_fallback(void *buf, size_t len);
-static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
-#endif
-
-int
-getentropy(void *buf, size_t len)
-{
-	int ret = -1;
-
-	if (len > 256) {
-		errno = EIO;
-		return (-1);
-	}
-
-	/*
-	 * Try descriptor-less getrandom()
-	 */
-	ret = getentropy_getrandom(buf, len);
-	if (ret != -1)
-		return (ret);
-	if (errno != ENOSYS && errno != EAGAIN)
-		return (-1);
-
-	/*
-	 * Try to get entropy with /dev/urandom
-	 *
-	 * This can fail if the process is inside a chroot or if file
-	 * descriptors are exhausted.
-	 */
-	ret = getentropy_urandom(buf, len);
-	if (ret != -1)
-		return (ret);
-
-#ifdef SYS__sysctl
-	/*
-	 * Try to use sysctl CTL_KERN, KERN_RANDOM, RANDOM_UUID.
-	 * sysctl is a failsafe API, so it guarantees a result.  This
-	 * should work inside a chroot, or when file descriptors are
-	 * exhausted.
-	 *
-	 * However this can fail if the Linux kernel removes support
-	 * for sysctl.  Starting in 2007, there have been efforts to
-	 * deprecate the sysctl API/ABI, and push callers towards use
-	 * of the chroot-unavailable fd-using /proc mechanism --
-	 * essentially the same problems as /dev/urandom.
-	 *
-	 * Numerous setbacks have been encountered in their deprecation
-	 * schedule, so as of June 2014 the kernel ABI still exists on
-	 * most Linux architectures. The sysctl() stub in libc is missing
-	 * on some systems.  There are also reports that some kernels
-	 * spew messages to the console.
-	 */
-	ret = getentropy_sysctl(buf, len);
-	if (ret != -1)
-		return (ret);
-#endif /* SYS__sysctl */
-
-	/*
-	 * Entropy collection via /dev/urandom and sysctl have failed.
-	 *
-	 * No other API exists for collecting entropy.  See the large
-	 * comment block above.
-	 *
-	 * We have very few options:
-	 *     - Even syslog_r is unsafe to call at this low level, so
-	 *	 there is no way to alert the user or program.
-	 *     - Cannot call abort() because some systems have unsafe
-	 *	 corefiles.
-	 *     - Could raise(SIGKILL) resulting in silent program termination.
-	 *     - Return EIO, to hint that arc4random's stir function
-	 *       should raise(SIGKILL)
-	 *     - Do the best under the circumstances....
-	 *
-	 * This code path exists to bring light to the issue that Linux
-	 * does not provide a failsafe API for entropy collection.
-	 *
-	 * We hope this demonstrates that Linux should either retain their
-	 * sysctl ABI, or consider providing a new failsafe API which
-	 * works in a chroot or when file descriptors are exhausted.
-	 */
-#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
-#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
-	raise(SIGKILL);
-#endif
-#ifdef HAVE_OPENSSL
-	ret = getentropy_fallback(buf, len);
-	if (ret != -1)
-		return (ret);
-#endif
-
-	errno = EIO;
-	return (ret);
-}
-
-/*
- * Basic sanity checking; wish we could do better.
- */
-static int
-gotdata(char *buf, size_t len)
-{
-	char	any_set = 0;
-	size_t	i;
-
-	for (i = 0; i < len; ++i)
-		any_set |= buf[i];
-	if (any_set == 0)
-		return (-1);
-	return (0);
-}
-
-static int
-getentropy_getrandom(void *buf, size_t len)
-{
-	int pre_errno = errno;
-	int ret;
-	if (len > 256)
-		return (-1);
-	do {
-		/*
-		 * Use GRND_NONBLOCK to avoid blocking before the
-		 * entropy pool has been initialized
-		 */
-		ret = syscall(SYS_getrandom, buf, len, GRND_NONBLOCK);
-	} while (ret == -1 && errno == EINTR);
-
-	if ((size_t)ret != len)
-		return (-1);
-	errno = pre_errno;
-	return (0);
-}
-
-static int
-getentropy_urandom(void *buf, size_t len)
-{
-	struct stat st;
-	size_t i;
-	int fd, cnt, flags;
-	int save_errno = errno;
-
-start:
-
-	flags = O_RDONLY;
-#ifdef O_NOFOLLOW
-	flags |= O_NOFOLLOW;
-#endif
-#ifdef O_CLOEXEC
-	flags |= O_CLOEXEC;
-#endif
-	fd = open("/dev/urandom", flags, 0);
-	if (fd == -1) {
-		if (errno == EINTR)
-			goto start;
-		goto nodevrandom;
-	}
-#ifndef O_CLOEXEC
-	fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
-#endif
-
-	/* Lightly verify that the device node looks sane */
-	if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
-		close(fd);
-		goto nodevrandom;
-	}
-	if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
-		close(fd);
-		goto nodevrandom;
-	}
-	for (i = 0; i < len; ) {
-		size_t wanted = len - i;
-		ssize_t ret = read(fd, (char *)buf + i, wanted);
-
-		if (ret == -1) {
-			if (errno == EAGAIN || errno == EINTR)
-				continue;
-			close(fd);
-			goto nodevrandom;
-		}
-		i += ret;
-	}
-	close(fd);
-	if (gotdata(buf, len) == 0) {
-		errno = save_errno;
-		return (0);		/* satisfied */
-	}
-nodevrandom:
-	errno = EIO;
-	return (-1);
-}
-
-#ifdef SYS__sysctl
-static int
-getentropy_sysctl(void *buf, size_t len)
-{
-	static int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID };
-	size_t i;
-	int save_errno = errno;
-
-	for (i = 0; i < len; ) {
-		size_t chunk = min(len - i, 16);
-
-		/* SYS__sysctl because some systems already removed sysctl() */
-		struct __sysctl_args args = {
-			.name = mib,
-			.nlen = 3,
-			.oldval = (char *)buf + i,
-			.oldlenp = &chunk,
-		};
-		if (syscall(SYS__sysctl, &args) != 0)
-			goto sysctlfailed;
-		i += chunk;
-	}
-	if (gotdata(buf, len) == 0) {
-		errno = save_errno;
-		return (0);			/* satisfied */
-	}
-sysctlfailed:
-	errno = EIO;
-	return (-1);
-}
-#endif /* SYS__sysctl */
-
-#ifdef HAVE_OPENSSL
-static const int cl[] = {
-	CLOCK_REALTIME,
-#ifdef CLOCK_MONOTONIC
-	CLOCK_MONOTONIC,
-#endif
-#ifdef CLOCK_MONOTONIC_RAW
-	CLOCK_MONOTONIC_RAW,
-#endif
-#ifdef CLOCK_TAI
-	CLOCK_TAI,
-#endif
-#ifdef CLOCK_VIRTUAL
-	CLOCK_VIRTUAL,
-#endif
-#ifdef CLOCK_UPTIME
-	CLOCK_UPTIME,
-#endif
-#ifdef CLOCK_PROCESS_CPUTIME_ID
-	CLOCK_PROCESS_CPUTIME_ID,
-#endif
-#ifdef CLOCK_THREAD_CPUTIME_ID
-	CLOCK_THREAD_CPUTIME_ID,
-#endif
-};
-
-static int
-getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
-{
-	SHA512_CTX *ctx = data;
-
-	SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
-	return (0);
-}
-
-static int
-getentropy_fallback(void *buf, size_t len)
-{
-	uint8_t results[SHA512_DIGEST_LENGTH];
-	int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
-	static int cnt;
-	struct timespec ts;
-	struct timeval tv;
-	struct rusage ru;
-	sigset_t sigset;
-	struct stat st;
-	SHA512_CTX ctx;
-	static pid_t lastpid;
-	pid_t pid;
-	size_t i, ii, m;
-	char *p;
-
-	pid = getpid();
-	if (lastpid == pid) {
-		faster = 1;
-		repeat = 2;
-	} else {
-		faster = 0;
-		lastpid = pid;
-		repeat = REPEAT;
-	}
-	for (i = 0; i < len; ) {
-		int j;
-		SHA512_Init(&ctx);
-		for (j = 0; j < repeat; j++) {
-			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
-			if (e != -1) {
-				cnt += (int)tv.tv_sec;
-				cnt += (int)tv.tv_usec;
-			}
-
-			dl_iterate_phdr(getentropy_phdr, &ctx);
-
-			for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
-				HX(clock_gettime(cl[ii], &ts) == -1, ts);
-
-			HX((pid = getpid()) == -1, pid);
-			HX((pid = getsid(pid)) == -1, pid);
-			HX((pid = getppid()) == -1, pid);
-			HX((pid = getpgid(0)) == -1, pid);
-			HX((e = getpriority(0, 0)) == -1, e);
-
-			if (!faster) {
-				ts.tv_sec = 0;
-				ts.tv_nsec = 1;
-				(void) nanosleep(&ts, NULL);
-			}
-
-			HX(sigpending(&sigset) == -1, sigset);
-			HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
-			    sigset);
-
-			HF(getentropy);	/* an addr in this library */
-			HF(printf);		/* an addr in libc */
-			p = (char *)&p;
-			HD(p);		/* an addr on stack */
-			p = (char *)&errno;
-			HD(p);		/* the addr of errno */
-
-			if (i == 0) {
-				struct sockaddr_storage ss;
-				struct statvfs stvfs;
-				struct termios tios;
-				struct statfs stfs;
-				socklen_t ssl;
-				off_t off;
-
-				/*
-				 * Prime-sized mappings encourage fragmentation;
-				 * thus exposing some address entropy.
-				 */
-				struct mm {
-					size_t	npg;
-					void	*p;
-				} mm[] =	 {
-					{ 17, MAP_FAILED }, { 3, MAP_FAILED },
-					{ 11, MAP_FAILED }, { 2, MAP_FAILED },
-					{ 5, MAP_FAILED }, { 3, MAP_FAILED },
-					{ 7, MAP_FAILED }, { 1, MAP_FAILED },
-					{ 57, MAP_FAILED }, { 3, MAP_FAILED },
-					{ 131, MAP_FAILED }, { 1, MAP_FAILED },
-				};
-
-				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
-					HX(mm[m].p = mmap(NULL,
-					    mm[m].npg * pgs,
-					    PROT_READ|PROT_WRITE,
-					    MAP_PRIVATE|MAP_ANON, -1,
-					    (off_t)0), mm[m].p);
-					if (mm[m].p != MAP_FAILED) {
-						size_t mo;
-
-						/* Touch some memory... */
-						p = mm[m].p;
-						mo = cnt %
-						    (mm[m].npg * pgs - 1);
-						p[mo] = 1;
-						cnt += (int)((long)(mm[m].p)
-						    / pgs);
-					}
-
-					/* Check cnts and times... */
-					for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
-					    ii++) {
-						HX((e = clock_gettime(cl[ii],
-						    &ts)) == -1, ts);
-						if (e != -1)
-							cnt += (int)ts.tv_nsec;
-					}
-
-					HX((e = getrusage(RUSAGE_SELF,
-					    &ru)) == -1, ru);
-					if (e != -1) {
-						cnt += (int)ru.ru_utime.tv_sec;
-						cnt += (int)ru.ru_utime.tv_usec;
-					}
-				}
-
-				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
-					if (mm[m].p != MAP_FAILED)
-						munmap(mm[m].p, mm[m].npg * pgs);
-					mm[m].p = MAP_FAILED;
-				}
-
-				HX(stat(".", &st) == -1, st);
-				HX(statvfs(".", &stvfs) == -1, stvfs);
-				HX(statfs(".", &stfs) == -1, stfs);
-
-				HX(stat("/", &st) == -1, st);
-				HX(statvfs("/", &stvfs) == -1, stvfs);
-				HX(statfs("/", &stfs) == -1, stfs);
-
-				HX((e = fstat(0, &st)) == -1, st);
-				if (e == -1) {
-					if (S_ISREG(st.st_mode) ||
-					    S_ISFIFO(st.st_mode) ||
-					    S_ISSOCK(st.st_mode)) {
-						HX(fstatvfs(0, &stvfs) == -1,
-						    stvfs);
-						HX(fstatfs(0, &stfs) == -1,
-						    stfs);
-						HX((off = lseek(0, (off_t)0,
-						    SEEK_CUR)) < 0, off);
-					}
-					if (S_ISCHR(st.st_mode)) {
-						HX(tcgetattr(0, &tios) == -1,
-						    tios);
-					} else if (S_ISSOCK(st.st_mode)) {
-						memset(&ss, 0, sizeof ss);
-						ssl = sizeof(ss);
-						HX(getpeername(0,
-						    (void *)&ss, &ssl) == -1,
-						    ss);
-					}
-				}
-
-				HX((e = getrusage(RUSAGE_CHILDREN,
-				    &ru)) == -1, ru);
-				if (e != -1) {
-					cnt += (int)ru.ru_utime.tv_sec;
-					cnt += (int)ru.ru_utime.tv_usec;
-				}
-			} else {
-				/* Subsequent hashes absorb previous result */
-				HD(results);
-			}
-
-			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
-			if (e != -1) {
-				cnt += (int)tv.tv_sec;
-				cnt += (int)tv.tv_usec;
-			}
-
-			HD(cnt);
-		}
-#ifdef HAVE_GETAUXVAL
-#ifdef AT_RANDOM
-		/* Not as random as you think but we take what we are given */
-		p = (char *) getauxval(AT_RANDOM);
-		if (p)
-			HR(p, 16);
-#endif
-#ifdef AT_SYSINFO_EHDR
-		p = (char *) getauxval(AT_SYSINFO_EHDR);
-		if (p)
-			HR(p, pgs);
-#endif
-#ifdef AT_BASE
-		p = (char *) getauxval(AT_BASE);
-		if (p)
-			HD(p);
-#endif
-#endif
-
-		SHA512_Final(results, &ctx);
-		memcpy((char *)buf + i, results, min(sizeof(results), len - i));
-		i += min(sizeof(results), len - i);
-	}
-	memset(results, 0, sizeof results);
-	if (gotdata(buf, len) == 0) {
-		errno = save_errno;
-		return (0);		/* satisfied */
-	}
-	errno = EIO;
-	return (-1);
-}
-#endif /* HAVE_OPENSSL */
diff --git a/libc/bionic/grp_pwd.cpp b/libc/bionic/grp_pwd.cpp
index 43a5032..952058f 100644
--- a/libc/bionic/grp_pwd.cpp
+++ b/libc/bionic/grp_pwd.cpp
@@ -44,6 +44,10 @@
 
 // Generated android_ids array
 #include "generated_android_ids.h"
+#include "grp_pwd_file.h"
+
+static PasswdFile vendor_passwd("/vendor/etc/passwd");
+static GroupFile vendor_group("/vendor/etc/group");
 
 // POSIX seems to envisage an implementation where the <pwd.h> functions are
 // implemented by brute-force searching with getpwent(3), and the <grp.h>
@@ -422,7 +426,11 @@
 
 static passwd* oem_id_to_passwd(uid_t uid, passwd_state_t* state) {
   if (!is_oem_id(uid)) {
-    return NULL;
+    return nullptr;
+  }
+
+  if (vendor_passwd.FindById(uid, state)) {
+    return &state->passwd_;
   }
 
   snprintf(state->name_buffer_, sizeof(state->name_buffer_), "oem_%u", uid);
@@ -440,7 +448,11 @@
 
 static group* oem_id_to_group(gid_t gid, group_state_t* state) {
   if (!is_oem_id(gid)) {
-    return NULL;
+    return nullptr;
+  }
+
+  if (vendor_group.FindById(gid, state)) {
+    return &state->group_;
   }
 
   snprintf(state->group_name_buffer_, sizeof(state->group_name_buffer_),
@@ -530,6 +542,13 @@
   if (pw != NULL) {
     return pw;
   }
+
+  if (vendor_passwd.FindByName(login, state)) {
+    if (is_oem_id(state->passwd_.pw_uid)) {
+      return &state->passwd_;
+    }
+  }
+
   // Handle OEM range.
   pw = oem_id_to_passwd(oem_id_from_name(login), state);
   if (pw != NULL) {
@@ -640,6 +659,13 @@
   if (grp != NULL) {
     return grp;
   }
+
+  if (vendor_group.FindByName(name, state)) {
+    if (is_oem_id(state->group_.gr_gid)) {
+      return &state->group_;
+    }
+  }
+
   // Handle OEM range.
   grp = oem_id_to_group(oem_id_from_name(name), state);
   if (grp != NULL) {
diff --git a/libc/bionic/grp_pwd_file.cpp b/libc/bionic/grp_pwd_file.cpp
new file mode 100644
index 0000000..37493a7
--- /dev/null
+++ b/libc/bionic/grp_pwd_file.cpp
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2018 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 "grp_pwd_file.h"
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include "private/ErrnoRestorer.h"
+
+// This file mmap's /*/etc/passwd and /*/etc/group in order to return their contents without any
+// allocations.  Note that these files and the strings contained within them are explicitly not
+// null-terminated.  ':'s are used to deliminate fields and '\n's are used to deliminate lines.
+// There is a check that the file ends with '\n', such that terminating loops at '\n' ensures that
+// memory will be not ready before the mmap region.
+
+namespace {
+
+void CopyFieldToString(char* dest, const char* source, size_t max) {
+  while (*source != ':' && *source != '\n' && max > 1) {
+    *dest++ = *source++;
+    --max;
+  }
+  *dest = '\0';
+}
+
+bool FieldToUid(const char* field, uid_t* uid) {
+  if (field == nullptr) {
+    return false;
+  }
+
+  char* end = nullptr;
+  errno = 0;
+  uid_t result = strtoul(field, &end, 0);
+  if (errno != 0 || field == end || *end != ':') {
+    return false;
+  }
+  *uid = result;
+  return true;
+}
+
+// Returns a pointer to one past the end of line.
+const char* ParseLine(const char* begin, const char* end, const char** fields, size_t num_fields) {
+  size_t fields_written = 0;
+  const char* position = begin;
+  fields[fields_written++] = position;
+
+  while (position < end && fields_written < num_fields) {
+    if (*position == '\n') {
+      return position + 1;
+    }
+    if (*position == ':') {
+      fields[fields_written++] = position + 1;
+    }
+    position++;
+  }
+
+  while (position < end && *position != '\n') {
+    position++;
+  }
+
+  return position + 1;
+}
+
+struct PasswdLine {
+  const char* name() const {
+    return fields[0];
+  }
+  // Password is not supported.
+  const char* uid() const {
+    return fields[2];
+  }
+  const char* gid() const {
+    return fields[3];
+  }
+  // User Info is not supported
+  const char* dir() const {
+    return fields[5];
+  }
+  const char* shell() const {
+    return fields[6];
+  }
+
+  bool ToPasswdState(passwd_state_t* passwd_state) {
+    if (name() == nullptr || dir() == nullptr || shell() == nullptr) {
+      return false;
+    }
+
+    uid_t uid;
+    if (!FieldToUid(this->uid(), &uid)) {
+      return false;
+    }
+
+    gid_t gid;
+    if (!FieldToUid(this->gid(), &gid)) {
+      return false;
+    }
+
+    passwd_state->passwd_.pw_uid = uid;
+    passwd_state->passwd_.pw_gid = gid;
+
+    CopyFieldToString(passwd_state->name_buffer_, name(), sizeof(passwd_state->name_buffer_));
+    passwd_state->passwd_.pw_name = passwd_state->name_buffer_;
+
+    passwd_state->passwd_.pw_passwd = nullptr;
+
+#ifdef __LP64__
+    passwd_state->passwd_.pw_gecos = nullptr;
+#endif
+
+    CopyFieldToString(passwd_state->dir_buffer_, dir(), sizeof(passwd_state->dir_buffer_));
+    passwd_state->passwd_.pw_dir = passwd_state->dir_buffer_;
+
+    CopyFieldToString(passwd_state->sh_buffer_, shell(), sizeof(passwd_state->sh_buffer_));
+    passwd_state->passwd_.pw_shell = passwd_state->sh_buffer_;
+
+    return true;
+  }
+
+  static constexpr size_t kNumFields = 7;
+  const char* fields[kNumFields] = {};
+};
+
+struct GroupLine {
+  const char* name() const {
+    return fields[0];
+  }
+  // Password is not supported.
+  const char* gid() const {
+    return fields[2];
+  }
+  // User list is not supported (returns simply name)
+
+  bool ToGroupState(group_state_t* group_state) {
+    if (name() == nullptr || gid() == nullptr) {
+      return false;
+    }
+
+    gid_t gid;
+    if (!FieldToUid(this->gid(), &gid)) {
+      return false;
+    }
+
+    group_state->group_.gr_gid = gid;
+
+    CopyFieldToString(group_state->group_name_buffer_, name(),
+                      sizeof(group_state->group_name_buffer_));
+    group_state->group_.gr_name = group_state->group_name_buffer_;
+
+    group_state->group_.gr_passwd = nullptr;
+
+    group_state->group_.gr_mem = group_state->group_members_;
+    group_state->group_.gr_mem[0] = group_state->group_.gr_name;
+    group_state->group_.gr_mem[1] = nullptr;
+
+    return true;
+  }
+
+  static constexpr size_t kNumFields = 4;
+  const char* fields[kNumFields] = {};
+};
+
+}  // namespace
+
+MmapFile::MmapFile(const char* filename) : filename_(filename) {
+  lock_.init(false);
+}
+
+void MmapFile::Unmap() {
+  if (status_ == FileStatus::Initialized) {
+    size_t size = end_ - start_ + 1;
+    munmap(const_cast<char*>(start_), size);
+    status_ = FileStatus::Uninitialized;
+    start_ = nullptr;
+    end_ = nullptr;
+  }
+}
+
+bool MmapFile::GetFile(const char** start, const char** end) {
+  LockGuard guard(lock_);
+  if (status_ == FileStatus::Initialized) {
+    *start = start_;
+    *end = end_;
+    return true;
+  }
+  if (status_ == FileStatus::Error) {
+    return false;
+  }
+
+  if (!DoMmap()) {
+    status_ = FileStatus::Error;
+    return false;
+  }
+
+  status_ = FileStatus::Initialized;
+  *start = start_;
+  *end = end_;
+  return true;
+}
+
+bool MmapFile::DoMmap() {
+  int fd = open(filename_, O_CLOEXEC | O_NOFOLLOW | O_RDONLY);
+
+  struct stat fd_stat;
+  if (fstat(fd, &fd_stat) == -1) {
+    close(fd);
+    return false;
+  }
+
+  auto mmap_size = fd_stat.st_size;
+
+  void* map_result = mmap(nullptr, mmap_size, PROT_READ, MAP_SHARED, fd, 0);
+  close(fd);
+
+  if (map_result == MAP_FAILED) {
+    return false;
+  }
+
+  start_ = static_cast<const char*>(map_result);
+  end_ = start_ + mmap_size - 1;
+
+  if (*end_ != '\n') {
+    munmap(map_result, mmap_size);
+    return false;
+  }
+
+  return true;
+}
+
+template <typename Line, typename Predicate>
+bool MmapFile::Find(Line* line, Predicate predicate) {
+  const char* start;
+  const char* end;
+  if (!GetFile(&start, &end)) {
+    return false;
+  }
+
+  const char* line_beginning = start;
+
+  while (line_beginning < end) {
+    line_beginning = ParseLine(line_beginning, end, line->fields, line->kNumFields);
+    if (predicate(line)) return true;
+  }
+
+  return false;
+}
+
+template <typename Line>
+bool MmapFile::FindById(uid_t uid, Line* line) {
+  return Find(line, [uid](const auto& line) {
+    uid_t line_id;
+    if (!FieldToUid(line->fields[2], &line_id)) {
+      return false;
+    }
+
+    return line_id == uid;
+  });
+}
+
+template <typename Line>
+bool MmapFile::FindByName(const char* name, Line* line) {
+  return Find(line, [name](const auto& line) {
+    const char* line_name = line->fields[0];
+    if (line_name == nullptr) {
+      return false;
+    }
+
+    const char* match_name = name;
+    while (*line_name != '\n' && *line_name != ':' && *match_name != '\0') {
+      if (*line_name++ != *match_name++) {
+        return false;
+      }
+    }
+
+    return *line_name == ':' && *match_name == '\0';
+  });
+}
+
+PasswdFile::PasswdFile(const char* filename) : mmap_file_(filename) {
+}
+
+bool PasswdFile::FindById(uid_t id, passwd_state_t* passwd_state) {
+  ErrnoRestorer errno_restorer;
+  PasswdLine passwd_line;
+  return mmap_file_.FindById(id, &passwd_line) && passwd_line.ToPasswdState(passwd_state);
+}
+
+bool PasswdFile::FindByName(const char* name, passwd_state_t* passwd_state) {
+  ErrnoRestorer errno_restorer;
+  PasswdLine passwd_line;
+  return mmap_file_.FindByName(name, &passwd_line) && passwd_line.ToPasswdState(passwd_state);
+}
+
+GroupFile::GroupFile(const char* filename) : mmap_file_(filename) {
+}
+
+bool GroupFile::FindById(gid_t id, group_state_t* group_state) {
+  ErrnoRestorer errno_restorer;
+  GroupLine group_line;
+  return mmap_file_.FindById(id, &group_line) && group_line.ToGroupState(group_state);
+}
+
+bool GroupFile::FindByName(const char* name, group_state_t* group_state) {
+  ErrnoRestorer errno_restorer;
+  GroupLine group_line;
+  return mmap_file_.FindByName(name, &group_line) && group_line.ToGroupState(group_state);
+}
diff --git a/libc/bionic/grp_pwd_file.h b/libc/bionic/grp_pwd_file.h
new file mode 100644
index 0000000..048cd82
--- /dev/null
+++ b/libc/bionic/grp_pwd_file.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2018 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
+
+#include <grp.h>
+#include <pwd.h>
+
+#include "private/bionic_lock.h"
+#include "private/bionic_macros.h"
+#include "private/grp_pwd.h"
+
+class MmapFile {
+ public:
+  MmapFile(const char* filename);
+
+  template <typename Line>
+  bool FindById(uid_t uid, Line* line);
+  template <typename Line>
+  bool FindByName(const char* name, Line* line);
+  void Unmap();
+
+  DISALLOW_COPY_AND_ASSIGN(MmapFile);
+
+ private:
+  enum class FileStatus {
+    Uninitialized,
+    Initialized,
+    Error,
+  };
+
+  bool GetFile(const char** start, const char** end);
+  bool DoMmap();
+
+  template <typename Line, typename Predicate>
+  bool Find(Line* line, Predicate predicate);
+
+  FileStatus status_ = FileStatus::Uninitialized;
+  Lock lock_;
+  const char* filename_ = nullptr;
+  const char* start_ = nullptr;
+  const char* end_ = nullptr;
+};
+
+class PasswdFile {
+ public:
+  PasswdFile(const char* filename);
+
+  bool FindById(uid_t id, passwd_state_t* passwd_state);
+  bool FindByName(const char* name, passwd_state_t* passwd_state);
+  void Unmap() {
+    mmap_file_.Unmap();
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(PasswdFile);
+
+ private:
+  MmapFile mmap_file_;
+};
+
+class GroupFile {
+ public:
+  GroupFile(const char* filename);
+
+  bool FindById(gid_t id, group_state_t* group_state);
+  bool FindByName(const char* name, group_state_t* group_state);
+  void Unmap() {
+    mmap_file_.Unmap();
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(GroupFile);
+
+ private:
+  MmapFile mmap_file_;
+};
diff --git a/libc/bionic/jemalloc.h b/libc/bionic/jemalloc.h
index f7e8770..79a4f72 100644
--- a/libc/bionic/jemalloc.h
+++ b/libc/bionic/jemalloc.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef LIBC_BIONIC_JEMALLOC_H_
-#define LIBC_BIONIC_JEMALLOC_H_
+#pragma once
 
 #include <jemalloc/jemalloc.h>
 #include <malloc.h>  // For struct mallinfo.
@@ -35,5 +34,3 @@
 void* je_pvalloc(size_t);
 
 __END_DECLS
-
-#endif  // LIBC_BIONIC_DLMALLOC_H_
diff --git a/libc/bionic/libc_init_common.h b/libc/bionic/libc_init_common.h
index 5066652..6ce4d10 100644
--- a/libc/bionic/libc_init_common.h
+++ b/libc/bionic/libc_init_common.h
@@ -25,8 +25,8 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#ifndef LIBC_INIT_COMMON_H
-#define LIBC_INIT_COMMON_H
+
+#pragma once
 
 #include <sys/cdefs.h>
 
@@ -59,5 +59,3 @@
 __LIBC_HIDDEN__ void __libc_init_AT_SECURE(KernelArgumentBlock& args);
 
 #endif
-
-#endif
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 1f201d1..1ea4ac1 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -69,8 +69,15 @@
     Malloc(malloc_disable),
     Malloc(malloc_enable),
     Malloc(mallopt),
+    Malloc(aligned_alloc),
   };
 
+// Malloc hooks.
+void* (*volatile __malloc_hook)(size_t, const void*);
+void* (*volatile __realloc_hook)(void*, size_t, const void*);
+void (*volatile __free_hook)(void*, const void*);
+void* (*volatile __memalign_hook)(size_t, size_t, const void*);
+
 // In a VM process, this is set to 1 after fork()ing out of zygote.
 int gMallocLeakZygoteChild = 0;
 
@@ -142,6 +149,14 @@
   return Malloc(posix_memalign)(memptr, alignment, size);
 }
 
+extern "C" void* aligned_alloc(size_t alignment, size_t size) {
+  auto _aligned_alloc = __libc_globals->malloc_dispatch.aligned_alloc;
+  if (__predict_false(_aligned_alloc != nullptr)) {
+    return _aligned_alloc(alignment, size);
+  }
+  return Malloc(aligned_alloc)(alignment, size);
+}
+
 extern "C" void* realloc(void* old_mem, size_t bytes) {
   auto _realloc = __libc_globals->malloc_dispatch.realloc;
   if (__predict_false(_realloc != nullptr)) {
@@ -181,17 +196,30 @@
 
 extern "C" int __cxa_atexit(void (*func)(void *), void *arg, void *dso);
 
+static const char* HOOKS_SHARED_LIB = "libc_malloc_hooks.so";
+static const char* HOOKS_PROPERTY_ENABLE = "libc.debug.hooks.enable";
+static const char* HOOKS_ENV_ENABLE = "LIBC_HOOKS_ENABLE";
+
 static const char* DEBUG_SHARED_LIB = "libc_malloc_debug.so";
-static const char* DEBUG_MALLOC_PROPERTY_OPTIONS = "libc.debug.malloc.options";
-static const char* DEBUG_MALLOC_PROPERTY_PROGRAM = "libc.debug.malloc.program";
-static const char* DEBUG_MALLOC_ENV_OPTIONS = "LIBC_DEBUG_MALLOC_OPTIONS";
+static const char* DEBUG_PROPERTY_OPTIONS = "libc.debug.malloc.options";
+static const char* DEBUG_PROPERTY_PROGRAM = "libc.debug.malloc.program";
+static const char* DEBUG_ENV_OPTIONS = "LIBC_DEBUG_MALLOC_OPTIONS";
 
-static void* libc_malloc_impl_handle = nullptr;
+enum FunctionEnum : uint8_t {
+  FUNC_INITIALIZE,
+  FUNC_FINALIZE,
+  FUNC_GET_MALLOC_LEAK_INFO,
+  FUNC_FREE_MALLOC_LEAK_INFO,
+  FUNC_MALLOC_BACKTRACE,
+  FUNC_LAST,
+};
+static void* g_functions[FUNC_LAST];
 
-static void (*g_debug_finalize_func)();
-static void (*g_debug_get_malloc_leak_info_func)(uint8_t**, size_t*, size_t*, size_t*, size_t*);
-static void (*g_debug_free_malloc_leak_info_func)(uint8_t*);
-static ssize_t (*g_debug_malloc_backtrace_func)(void*, uintptr_t*, size_t);
+typedef void (*finalize_func_t)();
+typedef bool (*init_func_t)(const MallocDispatch*, int*, const char*);
+typedef void (*get_malloc_leak_info_func_t)(uint8_t**, size_t*, size_t*, size_t*, size_t*);
+typedef void (*free_malloc_leak_info_func_t)(uint8_t*);
+typedef ssize_t (*malloc_backtrace_func_t)(void*, uintptr_t*, size_t);
 
 // =============================================================================
 // Log functions
@@ -216,17 +244,20 @@
 // "*backtrace_size" is set to the maximum number of entries in the back trace
 extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overall_size,
     size_t* info_size, size_t* total_memory, size_t* backtrace_size) {
-  if (g_debug_get_malloc_leak_info_func == nullptr) {
+  void* func = g_functions[FUNC_GET_MALLOC_LEAK_INFO];
+  if (func == nullptr) {
     return;
   }
-  g_debug_get_malloc_leak_info_func(info, overall_size, info_size, total_memory, backtrace_size);
+  reinterpret_cast<get_malloc_leak_info_func_t>(func)(info, overall_size, info_size, total_memory,
+                                                      backtrace_size);
 }
 
 extern "C" void free_malloc_leak_info(uint8_t* info) {
-  if (g_debug_free_malloc_leak_info_func == nullptr) {
+  void* func = g_functions[FUNC_FREE_MALLOC_LEAK_INFO];
+  if (func == nullptr) {
     return;
   }
-  g_debug_free_malloc_leak_info_func(info);
+  reinterpret_cast<free_malloc_leak_info_func_t>(func)(info);
 }
 
 // =============================================================================
@@ -243,62 +274,56 @@
   return true;
 }
 
-static bool InitMalloc(void* malloc_impl_handler, MallocDispatch* table, const char* prefix) {
-  if (!InitMallocFunction<MallocCalloc>(malloc_impl_handler, &table->calloc,
-                                        prefix, "calloc")) {
+static bool InitMallocFunctions(void* impl_handler, MallocDispatch* table, const char* prefix) {
+  if (!InitMallocFunction<MallocCalloc>(impl_handler, &table->calloc, prefix, "calloc")) {
     return false;
   }
-  if (!InitMallocFunction<MallocFree>(malloc_impl_handler, &table->free,
-                                      prefix, "free")) {
+  if (!InitMallocFunction<MallocFree>(impl_handler, &table->free, prefix, "free")) {
     return false;
   }
-  if (!InitMallocFunction<MallocMallinfo>(malloc_impl_handler, &table->mallinfo,
-                                          prefix, "mallinfo")) {
+  if (!InitMallocFunction<MallocMallinfo>(impl_handler, &table->mallinfo, prefix, "mallinfo")) {
     return false;
   }
-  if (!InitMallocFunction<MallocMallopt>(malloc_impl_handler, &table->mallopt,
-                                         prefix, "mallopt")) {
+  if (!InitMallocFunction<MallocMallopt>(impl_handler, &table->mallopt, prefix, "mallopt")) {
     return false;
   }
-  if (!InitMallocFunction<MallocMalloc>(malloc_impl_handler, &table->malloc,
-                                        prefix, "malloc")) {
+  if (!InitMallocFunction<MallocMalloc>(impl_handler, &table->malloc, prefix, "malloc")) {
     return false;
   }
-  if (!InitMallocFunction<MallocMallocUsableSize>(
-      malloc_impl_handler, &table->malloc_usable_size, prefix, "malloc_usable_size")) {
+  if (!InitMallocFunction<MallocMallocUsableSize>(impl_handler, &table->malloc_usable_size, prefix,
+                                                  "malloc_usable_size")) {
     return false;
   }
-  if (!InitMallocFunction<MallocMemalign>(malloc_impl_handler, &table->memalign,
-                                          prefix, "memalign")) {
+  if (!InitMallocFunction<MallocMemalign>(impl_handler, &table->memalign, prefix, "memalign")) {
     return false;
   }
-  if (!InitMallocFunction<MallocPosixMemalign>(malloc_impl_handler, &table->posix_memalign,
-                                               prefix, "posix_memalign")) {
+  if (!InitMallocFunction<MallocPosixMemalign>(impl_handler, &table->posix_memalign, prefix,
+                                               "posix_memalign")) {
     return false;
   }
-  if (!InitMallocFunction<MallocRealloc>(malloc_impl_handler, &table->realloc,
-                                         prefix, "realloc")) {
+  if (!InitMallocFunction<MallocAlignedAlloc>(impl_handler, &table->aligned_alloc,
+                                              prefix, "aligned_alloc")) {
     return false;
   }
-  if (!InitMallocFunction<MallocIterate>(malloc_impl_handler, &table->iterate,
-                                         prefix, "iterate")) {
+  if (!InitMallocFunction<MallocRealloc>(impl_handler, &table->realloc, prefix, "realloc")) {
     return false;
   }
-  if (!InitMallocFunction<MallocMallocDisable>(malloc_impl_handler, &table->malloc_disable,
-                                         prefix, "malloc_disable")) {
+  if (!InitMallocFunction<MallocIterate>(impl_handler, &table->iterate, prefix, "iterate")) {
     return false;
   }
-  if (!InitMallocFunction<MallocMallocEnable>(malloc_impl_handler, &table->malloc_enable,
-                                         prefix, "malloc_enable")) {
+  if (!InitMallocFunction<MallocMallocDisable>(impl_handler, &table->malloc_disable, prefix,
+                                               "malloc_disable")) {
+    return false;
+  }
+  if (!InitMallocFunction<MallocMallocEnable>(impl_handler, &table->malloc_enable, prefix,
+                                              "malloc_enable")) {
     return false;
   }
 #if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
-  if (!InitMallocFunction<MallocPvalloc>(malloc_impl_handler, &table->pvalloc,
-                                         prefix, "pvalloc")) {
+  if (!InitMallocFunction<MallocPvalloc>(impl_handler, &table->pvalloc, prefix, "pvalloc")) {
     return false;
   }
-  if (!InitMallocFunction<MallocValloc>(malloc_impl_handler, &table->valloc,
-                                        prefix, "valloc")) {
+  if (!InitMallocFunction<MallocValloc>(impl_handler, &table->valloc, prefix, "valloc")) {
     return false;
   }
 #endif
@@ -315,102 +340,114 @@
   fclose(stdout);
   fclose(stderr);
 
-  g_debug_finalize_func();
+  reinterpret_cast<finalize_func_t>(g_functions[FUNC_FINALIZE])();
+}
+
+static bool CheckLoadMallocHooks(char** options) {
+  char* env = getenv(HOOKS_ENV_ENABLE);
+  if ((env == nullptr || env[0] == '\0' || env[0] == '0') &&
+    (__system_property_get(HOOKS_PROPERTY_ENABLE, *options) == 0 || *options[0] == '\0' || *options[0] == '0')) {
+    return false;
+  }
+  *options = nullptr;
+  return true;
+}
+
+static bool CheckLoadMallocDebug(char** options) {
+  // If DEBUG_MALLOC_ENV_OPTIONS is set then it overrides the system properties.
+  char* env = getenv(DEBUG_ENV_OPTIONS);
+  if (env == nullptr || env[0] == '\0') {
+    if (__system_property_get(DEBUG_PROPERTY_OPTIONS, *options) == 0 || *options[0] == '\0') {
+      return false;
+    }
+
+    // Check to see if only a specific program should have debug malloc enabled.
+    char program[PROP_VALUE_MAX];
+    if (__system_property_get(DEBUG_PROPERTY_PROGRAM, program) != 0 &&
+        strstr(getprogname(), program) == nullptr) {
+      return false;
+    }
+  } else {
+    *options = env;
+  }
+  return true;
+}
+
+static void ClearGlobalFunctions() {
+  for (size_t i = 0; i < FUNC_LAST; i++) {
+    g_functions[i] = nullptr;
+  }
+}
+
+static void* LoadSharedLibrary(const char* shared_lib, const char* prefix, MallocDispatch* dispatch_table) {
+  void* impl_handle = dlopen(shared_lib, RTLD_NOW | RTLD_LOCAL);
+  if (impl_handle == nullptr) {
+    error_log("%s: Unable to open shared library %s: %s", getprogname(), shared_lib, dlerror());
+    return nullptr;
+  }
+
+  static constexpr const char* names[] = {
+    "initialize",
+    "finalize",
+    "get_malloc_leak_info",
+    "free_malloc_leak_info",
+    "malloc_backtrace",
+  };
+  for (size_t i = 0; i < FUNC_LAST; i++) {
+    char symbol[128];
+    snprintf(symbol, sizeof(symbol), "%s_%s", prefix, names[i]);
+    g_functions[i] = dlsym(impl_handle, symbol);
+    if (g_functions[i] == nullptr) {
+      error_log("%s: %s routine not found in %s", getprogname(), symbol, shared_lib);
+      dlclose(impl_handle);
+      ClearGlobalFunctions();
+      return nullptr;
+    }
+  }
+
+  if (!InitMallocFunctions(impl_handle, dispatch_table, prefix)) {
+    dlclose(impl_handle);
+    ClearGlobalFunctions();
+    return nullptr;
+  }
+
+  return impl_handle;
 }
 
 // Initializes memory allocation framework once per process.
 static void malloc_init_impl(libc_globals* globals) {
-  char value[PROP_VALUE_MAX];
-
-  // If DEBUG_MALLOC_ENV_OPTIONS is set then it overrides the system properties.
-  const char* options = getenv(DEBUG_MALLOC_ENV_OPTIONS);
-  if (options == nullptr || options[0] == '\0') {
-    if (__system_property_get(DEBUG_MALLOC_PROPERTY_OPTIONS, value) == 0 || value[0] == '\0') {
-      return;
-    }
-    options = value;
-
-    // Check to see if only a specific program should have debug malloc enabled.
-    char program[PROP_VALUE_MAX];
-    if (__system_property_get(DEBUG_MALLOC_PROPERTY_PROGRAM, program) != 0 &&
-        strstr(getprogname(), program) == nullptr) {
-      return;
-    }
-  }
-
-  // Load the debug malloc shared library.
-  void* malloc_impl_handle = dlopen(DEBUG_SHARED_LIB, RTLD_NOW | RTLD_LOCAL);
-  if (malloc_impl_handle == nullptr) {
-    error_log("%s: Unable to open debug malloc shared library %s: %s",
-              getprogname(), DEBUG_SHARED_LIB, dlerror());
+  const char* prefix;
+  const char* shared_lib;
+  char prop[PROP_VALUE_MAX];
+  char* options = prop;
+  // Prefer malloc debug since it existed first and is a more complete
+  // malloc interceptor than the hooks.
+  if (CheckLoadMallocDebug(&options)) {
+    prefix = "debug";
+    shared_lib = DEBUG_SHARED_LIB;
+  } else if (CheckLoadMallocHooks(&options)) {
+    prefix = "hooks";
+    shared_lib = HOOKS_SHARED_LIB;
+  } else {
     return;
   }
 
-  // Initialize malloc debugging in the loaded module.
-  auto init_func = reinterpret_cast<bool (*)(const MallocDispatch*, int*, const char*)>(
-      dlsym(malloc_impl_handle, "debug_initialize"));
-  if (init_func == nullptr) {
-    error_log("%s: debug_initialize routine not found in %s", getprogname(), DEBUG_SHARED_LIB);
-    dlclose(malloc_impl_handle);
+  MallocDispatch dispatch_table;
+  void* impl_handle = LoadSharedLibrary(shared_lib, prefix, &dispatch_table);
+  if (impl_handle == nullptr) {
     return;
   }
 
-  // Get the syms for the external functions.
-  void* finalize_sym = dlsym(malloc_impl_handle, "debug_finalize");
-  if (finalize_sym == nullptr) {
-    error_log("%s: debug_finalize routine not found in %s", getprogname(), DEBUG_SHARED_LIB);
-    dlclose(malloc_impl_handle);
-    return;
-  }
-
-  void* get_leak_info_sym = dlsym(malloc_impl_handle, "debug_get_malloc_leak_info");
-  if (get_leak_info_sym == nullptr) {
-    error_log("%s: debug_get_malloc_leak_info routine not found in %s", getprogname(),
-              DEBUG_SHARED_LIB);
-    dlclose(malloc_impl_handle);
-    return;
-  }
-
-  void* free_leak_info_sym = dlsym(malloc_impl_handle, "debug_free_malloc_leak_info");
-  if (free_leak_info_sym == nullptr) {
-    error_log("%s: debug_free_malloc_leak_info routine not found in %s", getprogname(),
-              DEBUG_SHARED_LIB);
-    dlclose(malloc_impl_handle);
-    return;
-  }
-
-  void* malloc_backtrace_sym = dlsym(malloc_impl_handle, "debug_malloc_backtrace");
-  if (malloc_backtrace_sym == nullptr) {
-    error_log("%s: debug_malloc_backtrace routine not found in %s", getprogname(),
-              DEBUG_SHARED_LIB);
-    dlclose(malloc_impl_handle);
-    return;
-  }
-
+  init_func_t init_func = reinterpret_cast<init_func_t>(g_functions[FUNC_INITIALIZE]);
   if (!init_func(&__libc_malloc_default_dispatch, &gMallocLeakZygoteChild, options)) {
-    dlclose(malloc_impl_handle);
+    dlclose(impl_handle);
+    ClearGlobalFunctions();
     return;
   }
 
-  MallocDispatch malloc_dispatch_table;
-  if (!InitMalloc(malloc_impl_handle, &malloc_dispatch_table, "debug")) {
-    auto finalize_func = reinterpret_cast<void (*)()>(finalize_sym);
-    finalize_func();
-    dlclose(malloc_impl_handle);
-    return;
-  }
+  globals->malloc_dispatch = dispatch_table;
 
-  g_debug_finalize_func = reinterpret_cast<void (*)()>(finalize_sym);
-  g_debug_get_malloc_leak_info_func = reinterpret_cast<void (*)(
-      uint8_t**, size_t*, size_t*, size_t*, size_t*)>(get_leak_info_sym);
-  g_debug_free_malloc_leak_info_func = reinterpret_cast<void (*)(uint8_t*)>(free_leak_info_sym);
-  g_debug_malloc_backtrace_func = reinterpret_cast<ssize_t (*)(
-      void*, uintptr_t*, size_t)>(malloc_backtrace_sym);
-
-  globals->malloc_dispatch = malloc_dispatch_table;
-  libc_malloc_impl_handle = malloc_impl_handle;
-
-  info_log("%s: malloc debug enabled", getprogname());
+  info_log("%s: malloc %s enabled", getprogname(), prefix);
 
   // Use atexit to trigger the cleanup function. This avoids a problem
   // where another atexit function is used to cleanup allocated memory,
@@ -465,10 +502,11 @@
 
 #ifndef LIBC_STATIC
 extern "C" ssize_t malloc_backtrace(void* pointer, uintptr_t* frames, size_t frame_count) {
-  if (g_debug_malloc_backtrace_func == nullptr) {
+  void* func = g_functions[FUNC_MALLOC_BACKTRACE];
+  if (func == nullptr) {
     return 0;
   }
-  return g_debug_malloc_backtrace_func(pointer, frames, frame_count);
+  return reinterpret_cast<malloc_backtrace_func_t>(func)(pointer, frames, frame_count);
 }
 #else
 extern "C" ssize_t malloc_backtrace(void*, uintptr_t*, size_t) {
diff --git a/libc/bionic/malloc_info.h b/libc/bionic/malloc_info.h
index 5fffae9..257fec1 100644
--- a/libc/bionic/malloc_info.h
+++ b/libc/bionic/malloc_info.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef LIBC_BIONIC_MALLOC_INFO_H_
-#define LIBC_BIONIC_MALLOC_INFO_H_
+#pragma once
 
 #include <malloc.h>
 #include <sys/cdefs.h>
@@ -28,5 +27,3 @@
 __LIBC_HIDDEN__ struct mallinfo __mallinfo_bin_info(size_t, size_t);
 
 __END_DECLS
-
-#endif // LIBC_BIONIC_MALLOC_INFO_H_
diff --git a/libc/bionic/pause.cpp b/libc/bionic/pause.cpp
index 2a0779a..534a804 100644
--- a/libc/bionic/pause.cpp
+++ b/libc/bionic/pause.cpp
@@ -26,12 +26,10 @@
  * SUCH DAMAGE.
  */
 
+#include <signal.h>
 #include <unistd.h>
 
-#include "private/kernel_sigset_t.h"
-
 int pause() {
-  kernel_sigset_t mask;
-  if (__rt_sigprocmask(SIG_SETMASK, nullptr, &mask, sizeof(mask)) == -1) return -1;
-  return __rt_sigsuspend(&mask, sizeof(mask));
+  sigset64_t mask = {};
+  return sigsuspend64(&mask);
 }
diff --git a/libc/bionic/poll.cpp b/libc/bionic/poll.cpp
index dbc9584..3df8b18 100644
--- a/libc/bionic/poll.cpp
+++ b/libc/bionic/poll.cpp
@@ -31,51 +31,65 @@
 #include <sys/select.h>
 
 #include "private/bionic_time_conversions.h"
-#include "private/kernel_sigset_t.h"
+#include "private/sigrtmin.h"
+#include "private/SigSetConverter.h"
 
-extern "C" int __ppoll(pollfd*, unsigned int, timespec*, const kernel_sigset_t*, size_t);
+extern "C" int __ppoll(pollfd*, unsigned int, timespec*, const sigset64_t*, size_t);
 extern "C" int __pselect6(int, fd_set*, fd_set*, fd_set*, timespec*, void*);
 
-int poll(pollfd* fds, nfds_t fd_count, int ms) __overloadable {
+int poll(pollfd* fds, nfds_t fd_count, int ms) {
   timespec ts;
-  timespec* ts_ptr = NULL;
+  timespec* ts_ptr = nullptr;
   if (ms >= 0) {
     timespec_from_ms(ts, ms);
     ts_ptr = &ts;
   }
-  return __ppoll(fds, fd_count, ts_ptr, NULL, 0);
+  return __ppoll(fds, fd_count, ts_ptr, nullptr, 0);
 }
 
-int ppoll(pollfd* fds, nfds_t fd_count, const timespec* ts, const sigset_t* ss) __overloadable {
+int ppoll(pollfd* fds, nfds_t fd_count, const timespec* ts, const sigset_t* ss) {
+  // The underlying `__ppoll` system call only takes `sigset64_t`.
+  SigSetConverter set;
+  sigset64_t* ss_ptr = nullptr;
+  if (ss != nullptr) {
+    set = {};
+    set.sigset = *ss;
+    ss_ptr = &set.sigset64;
+  }
+  return ppoll64(fds, fd_count, ts, ss_ptr);
+}
+
+int ppoll64(pollfd* fds, nfds_t fd_count, const timespec* ts, const sigset64_t* ss) {
+  // The underlying __ppoll system call modifies its `struct timespec` argument.
   timespec mutable_ts;
-  timespec* mutable_ts_ptr = NULL;
-  if (ts != NULL) {
+  timespec* mutable_ts_ptr = nullptr;
+  if (ts != nullptr) {
     mutable_ts = *ts;
     mutable_ts_ptr = &mutable_ts;
   }
 
-  kernel_sigset_t kernel_ss;
-  kernel_sigset_t* kernel_ss_ptr = NULL;
-  if (ss != NULL) {
-    kernel_ss.set(ss);
-    kernel_ss_ptr = &kernel_ss;
+  sigset64_t mutable_ss;
+  sigset64_t* mutable_ss_ptr = nullptr;
+  if (ss != nullptr) {
+    mutable_ss = filter_reserved_signals(*ss);
+    mutable_ss_ptr = &mutable_ss;
   }
 
-  return __ppoll(fds, fd_count, mutable_ts_ptr, kernel_ss_ptr, sizeof(kernel_ss));
+  return __ppoll(fds, fd_count, mutable_ts_ptr, mutable_ss_ptr, sizeof(*mutable_ss_ptr));
 }
 
 int select(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_fds, timeval* tv) {
   timespec ts;
-  timespec* ts_ptr = NULL;
-  if (tv != NULL) {
+  timespec* ts_ptr = nullptr;
+  if (tv != nullptr) {
     if (!timespec_from_timeval(ts, *tv)) {
       errno = EINVAL;
       return -1;
     }
     ts_ptr = &ts;
   }
-  int result = __pselect6(fd_count, read_fds, write_fds, error_fds, ts_ptr, NULL);
-  if (tv != NULL) {
+  int result = __pselect6(fd_count, read_fds, write_fds, error_fds, ts_ptr, nullptr);
+  if (tv != nullptr) {
     timeval_from_timespec(*tv, ts);
   }
   return result;
@@ -83,18 +97,32 @@
 
 int pselect(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_fds,
             const timespec* ts, const sigset_t* ss) {
+  // The underlying `__pselect6` system call only takes `sigset64_t`.
+  SigSetConverter set;
+  sigset64_t* ss_ptr = nullptr;
+  if (ss != nullptr) {
+    set = {};
+    set.sigset = *ss;
+    ss_ptr = &set.sigset64;
+  }
+  return pselect64(fd_count, read_fds, write_fds, error_fds, ts, ss_ptr);
+}
+
+int pselect64(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_fds,
+              const timespec* ts, const sigset64_t* ss) {
+  // The underlying __pselect6 system call modifies its `struct timespec` argument.
   timespec mutable_ts;
-  timespec* mutable_ts_ptr = NULL;
-  if (ts != NULL) {
+  timespec* mutable_ts_ptr = nullptr;
+  if (ts != nullptr) {
     mutable_ts = *ts;
     mutable_ts_ptr = &mutable_ts;
   }
 
-  kernel_sigset_t kernel_ss;
-  kernel_sigset_t* kernel_ss_ptr = NULL;
-  if (ss != NULL) {
-    kernel_ss.set(ss);
-    kernel_ss_ptr = &kernel_ss;
+  sigset64_t mutable_ss;
+  sigset64_t* mutable_ss_ptr = nullptr;
+  if (ss != nullptr) {
+    mutable_ss = filter_reserved_signals(*ss);
+    mutable_ss_ptr = &mutable_ss;
   }
 
   // The Linux kernel only handles 6 arguments and this system call really needs 7,
@@ -104,8 +132,8 @@
     size_t ss_len;
   };
   pselect6_extra_data_t extra_data;
-  extra_data.ss_addr = reinterpret_cast<uintptr_t>(kernel_ss_ptr);
-  extra_data.ss_len = sizeof(kernel_ss);
+  extra_data.ss_addr = reinterpret_cast<uintptr_t>(mutable_ss_ptr);
+  extra_data.ss_len = sizeof(*mutable_ss_ptr);
 
   return __pselect6(fd_count, read_fds, write_fds, error_fds, mutable_ts_ptr, &extra_data);
 }
diff --git a/libc/bionic/posix_timers.cpp b/libc/bionic/posix_timers.cpp
index e3bb112..1abeb1f 100644
--- a/libc/bionic/posix_timers.cpp
+++ b/libc/bionic/posix_timers.cpp
@@ -26,8 +26,6 @@
  * SUCH DAMAGE.
  */
 
-#include "private/kernel_sigset_t.h"
-
 #include <errno.h>
 #include <malloc.h>
 #include <pthread.h>
@@ -37,7 +35,8 @@
 #include <time.h>
 
 // System calls.
-extern "C" int __rt_sigtimedwait(const sigset_t*, siginfo_t*, const timespec*, size_t);
+extern "C" int __rt_sigprocmask(int, const sigset64_t*, sigset64_t*, size_t);
+extern "C" int __rt_sigtimedwait(const sigset64_t*, siginfo_t*, const timespec*, size_t);
 extern "C" int __timer_create(clockid_t, sigevent*, __kernel_timer_t*);
 extern "C" int __timer_delete(__kernel_timer_t);
 extern "C" int __timer_getoverrun(__kernel_timer_t);
@@ -74,16 +73,13 @@
 static void* __timer_thread_start(void* arg) {
   PosixTimer* timer = reinterpret_cast<PosixTimer*>(arg);
 
-  kernel_sigset_t sigset{TIMER_SIGNAL};
+  sigset64_t sigset = {};
+  sigaddset64(&sigset, TIMER_SIGNAL);
 
   while (true) {
     // Wait for a signal...
-    siginfo_t si;
-    memset(&si, 0, sizeof(si));
-    int rc = __rt_sigtimedwait(sigset.get(), &si, NULL, sizeof(sigset));
-    if (rc == -1) {
-      continue;
-    }
+    siginfo_t si = {};
+    if (__rt_sigtimedwait(&sigset, &si, nullptr, sizeof(sigset)) == -1) continue;
 
     if (si.si_code == SI_TIMER) {
       // This signal was sent because a timer fired, so call the callback.
@@ -149,13 +145,16 @@
 
   // We start the thread with TIMER_SIGNAL blocked by blocking the signal here and letting it
   // inherit. If it tried to block the signal itself, there would be a race.
-  kernel_sigset_t sigset{TIMER_SIGNAL};
-  kernel_sigset_t old_sigset;
+  sigset64_t sigset = {};
+  sigaddset64(&sigset, TIMER_SIGNAL);
+  sigset64_t old_sigset;
+
+  // Use __rt_sigprocmask instead of sigprocmask64 to avoid filtering out TIMER_SIGNAL.
   __rt_sigprocmask(SIG_BLOCK, &sigset, &old_sigset, sizeof(sigset));
 
   int rc = pthread_create(&timer->callback_thread, &thread_attributes, __timer_thread_start, timer);
 
-  __rt_sigprocmask(SIG_SETMASK, &old_sigset, nullptr, sizeof(sigset));
+  __rt_sigprocmask(SIG_BLOCK, &old_sigset, nullptr, sizeof(old_sigset));
 
   if (rc != 0) {
     free(timer);
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index a4cba87..18f5aee 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -25,8 +25,8 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#ifndef _PTHREAD_INTERNAL_H_
-#define _PTHREAD_INTERNAL_H_
+
+#pragma once
 
 #include <pthread.h>
 #include <stdatomic.h>
@@ -172,5 +172,3 @@
 __LIBC_HIDDEN__ extern void __bionic_atfork_run_prepare();
 __LIBC_HIDDEN__ extern void __bionic_atfork_run_child();
 __LIBC_HIDDEN__ extern void __bionic_atfork_run_parent();
-
-#endif /* _PTHREAD_INTERNAL_H_ */
diff --git a/libc/bionic/pthread_mutex.cpp b/libc/bionic/pthread_mutex.cpp
index ed90639..f1f7294 100644
--- a/libc/bionic/pthread_mutex.cpp
+++ b/libc/bionic/pthread_mutex.cpp
@@ -31,6 +31,7 @@
 #include <errno.h>
 #include <limits.h>
 #include <stdatomic.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/cdefs.h>
 #include <sys/mman.h>
@@ -130,8 +131,6 @@
     return 0;
 }
 
-#if defined(__LP64__)
-
 // Priority Inheritance mutex implementation
 struct PIMutex {
   // mutex type, can be 0 (normal), 1 (recursive), 2 (errorcheck), constant during lifetime
@@ -172,12 +171,16 @@
     return EBUSY;
 }
 
-static int PIMutexTimedLock(PIMutex& mutex, const timespec* abs_timeout) {
+// Inlining this function in pthread_mutex_lock() add the cost of stack frame instructions on
+// ARM/ARM64, which increases at most 20 percent overhead. So make it noinline.
+static int  __attribute__((noinline)) PIMutexTimedLock(PIMutex& mutex,
+                                                       const timespec* abs_timeout) {
     int ret = PIMutexTryLock(mutex);
     if (__predict_true(ret == 0)) {
         return 0;
     }
     if (ret == EBUSY) {
+        ScopedTrace trace("Contending for pthread mutex");
         ret = -__futex_pi_lock_ex(&mutex.owner_tid, mutex.shared, true, abs_timeout);
     }
     return ret;
@@ -228,7 +231,97 @@
     }
     return EBUSY;
 }
-#endif  // defined(__LP64__)
+
+#if !defined(__LP64__)
+
+namespace PIMutexAllocator {
+// pthread_mutex_t has only 4 bytes in 32-bit programs, which are not enough to hold PIMutex.
+// So we use malloc to allocate PIMutexes and use 16-bit of pthread_mutex_t as indexes to find
+// the allocated PIMutexes. This allows at most 65536 PI mutexes.
+// When calling operations like pthread_mutex_lock/unlock, the 16-bit index is mapped to the
+// corresponding PIMutex. To make the map operation fast, we use a lockless mapping method:
+//   Once a PIMutex is allocated, all the data used to map index to the PIMutex isn't changed until
+//   it is destroyed.
+// Below are the data structures:
+//   // struct Node contains a PIMutex.
+//   typedef Node NodeArray[256];
+//   typedef NodeArray* NodeArrayP;
+//   NodeArrayP nodes[256];
+//
+// A 16-bit index is mapped to Node as below:
+//   (*nodes[index >> 8])[index & 0xff]
+//
+// Also use a free list to allow O(1) finding recycled PIMutexes.
+
+union Node {
+    PIMutex mutex;
+    int next_free_id;  // If not -1, refer to the next node in the free PIMutex list.
+};
+typedef Node NodeArray[256];
+typedef NodeArray* NodeArrayP;
+
+// lock_ protects below items.
+static Lock lock;
+static NodeArrayP* nodes;
+static int next_to_alloc_id;
+static int first_free_id = -1;  // If not -1, refer to the first node in the free PIMutex list.
+
+static inline __always_inline Node& IdToNode(int id) {
+    return (*nodes[id >> 8])[id & 0xff];
+}
+
+static inline __always_inline PIMutex& IdToPIMutex(int id) {
+    return IdToNode(id).mutex;
+}
+
+static int AllocIdLocked() {
+    if (first_free_id != -1) {
+        int result = first_free_id;
+        first_free_id = IdToNode(result).next_free_id;
+        return result;
+    }
+    if (next_to_alloc_id >= 0x10000) {
+        return -1;
+    }
+    int array_pos = next_to_alloc_id >> 8;
+    int node_pos = next_to_alloc_id & 0xff;
+    if (node_pos == 0) {
+        if (array_pos == 0) {
+            nodes = static_cast<NodeArray**>(calloc(256, sizeof(NodeArray*)));
+            if (nodes == nullptr) {
+                return -1;
+            }
+        }
+        nodes[array_pos] = static_cast<NodeArray*>(malloc(sizeof(NodeArray)));
+        if (nodes[array_pos] == nullptr) {
+            return -1;
+        }
+    }
+    return next_to_alloc_id++;
+}
+
+// If succeed, return an id referring to a PIMutex, otherwise return -1.
+// A valid id is in range [0, 0xffff].
+static int AllocId() {
+    lock.lock();
+    int result = AllocIdLocked();
+    lock.unlock();
+    if (result != -1) {
+        memset(&IdToPIMutex(result), 0, sizeof(PIMutex));
+    }
+    return result;
+}
+
+static void FreeId(int id) {
+    lock.lock();
+    IdToNode(id).next_free_id = first_free_id;
+    first_free_id = id;
+    lock.unlock();
+}
+
+}  // namespace PIMutexAllocator
+
+#endif  // !defined(__LP64__)
 
 
 /* Convenience macro, creates a mask of 'bits' bits that starts from
@@ -324,7 +417,7 @@
 
 // For a PI mutex, it includes below fields:
 //   Atomic(uint16_t) state;
-//   PIMutex pi_mutex;
+//   PIMutex pi_mutex;  // uint16_t pi_mutex_id in 32-bit programs
 //
 //   state holds the following fields:
 //
@@ -332,6 +425,7 @@
 //   15-14   type    mutex type, should be 3
 //
 //   pi_mutex holds the state of a PI mutex.
+//   pi_mutex_id holds an integer to find the state of a PI mutex.
 //
 // For a Non-PI mutex, it includes below fields:
 //   Atomic(uint16_t) state;
@@ -351,20 +445,42 @@
 //   thread id.
 //
 // PI mutexes and Non-PI mutexes are distinguished by checking type field in state.
-struct pthread_mutex_internal_t {
-  _Atomic(uint16_t) state;
 #if defined(__LP64__)
-  uint16_t __pad;
-  union {
-    atomic_int owner_tid;
-    PIMutex pi_mutex;
-  };
-  char __reserved[28];
-#else
-  _Atomic(uint16_t) owner_tid;
-#endif
+struct pthread_mutex_internal_t {
+    _Atomic(uint16_t) state;
+    uint16_t __pad;
+    union {
+        atomic_int owner_tid;
+        PIMutex pi_mutex;
+    };
+    char __reserved[28];
+
+    PIMutex& ToPIMutex() {
+        return pi_mutex;
+    }
+
+    void FreePIMutex() {
+    }
 } __attribute__((aligned(4)));
 
+#else
+struct pthread_mutex_internal_t {
+    _Atomic(uint16_t) state;
+    union {
+        _Atomic(uint16_t) owner_tid;
+        uint16_t pi_mutex_id;
+    };
+
+    PIMutex& ToPIMutex() {
+        return PIMutexAllocator::IdToPIMutex(pi_mutex_id);
+    }
+
+    void FreePIMutex() {
+        PIMutexAllocator::FreeId(pi_mutex_id);
+    }
+} __attribute__((aligned(4)));
+#endif
+
 static_assert(sizeof(pthread_mutex_t) == sizeof(pthread_mutex_internal_t),
               "pthread_mutex_t should actually be pthread_mutex_internal_t in implementation.");
 
@@ -407,13 +523,20 @@
     }
 
     if (((*attr & MUTEXATTR_PROTOCOL_MASK) >> MUTEXATTR_PROTOCOL_SHIFT) == PTHREAD_PRIO_INHERIT) {
-#if defined(__LP64__)
-        atomic_init(&mutex->state, MUTEX_TYPE_BITS_WITH_PI);
-        mutex->pi_mutex.type = *attr & MUTEXATTR_TYPE_MASK;
-        mutex->pi_mutex.shared = (*attr & MUTEXATTR_SHARED_MASK) != 0;
-#else
-        return EINVAL;
+#if !defined(__LP64__)
+        if (state & MUTEX_SHARED_MASK) {
+            return EINVAL;
+        }
+        int id = PIMutexAllocator::AllocId();
+        if (id == -1) {
+            return ENOMEM;
+        }
+        mutex->pi_mutex_id = id;
 #endif
+        atomic_init(&mutex->state, MUTEX_TYPE_BITS_WITH_PI);
+        PIMutex& pi_mutex = mutex->ToPIMutex();
+        pi_mutex.type = *attr & MUTEXATTR_TYPE_MASK;
+        pi_mutex.shared = (*attr & MUTEXATTR_SHARED_MASK) != 0;
     } else {
         atomic_init(&mutex->state, state);
         atomic_init(&mutex->owner_tid, 0);
@@ -668,18 +791,20 @@
 
     uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
     uint16_t mtype = (old_state & MUTEX_TYPE_MASK);
-    uint16_t shared = (old_state & MUTEX_SHARED_MASK);
     // Avoid slowing down fast path of normal mutex lock operation.
     if (__predict_true(mtype == MUTEX_TYPE_BITS_NORMAL)) {
-      if (__predict_true(NonPI::NormalMutexTryLock(mutex, shared) == 0)) {
-        return 0;
-      }
+        uint16_t shared = (old_state & MUTEX_SHARED_MASK);
+        if (__predict_true(NonPI::NormalMutexTryLock(mutex, shared) == 0)) {
+            return 0;
+        }
+    } else if (mtype == MUTEX_TYPE_BITS_WITH_PI) {
+        PIMutex& m = mutex->ToPIMutex();
+        // Handle common case first.
+        if (__predict_true(PIMutexTryLock(m) == 0)) {
+            return 0;
+        }
+        return PIMutexTimedLock(mutex->ToPIMutex(), nullptr);
     }
-#if defined(__LP64__)
-    if (mtype == MUTEX_TYPE_BITS_WITH_PI) {
-        return PIMutexTimedLock(mutex->pi_mutex, nullptr);
-    }
-#endif
     return NonPI::MutexLockWithTimeout(mutex, false, nullptr);
 }
 
@@ -704,11 +829,9 @@
         NonPI::NormalMutexUnlock(mutex, shared);
         return 0;
     }
-#if defined(__LP64__)
     if (mtype == MUTEX_TYPE_BITS_WITH_PI) {
-        return PIMutexUnlock(mutex->pi_mutex);
+        return PIMutexUnlock(mutex->ToPIMutex());
     }
-#endif
 
     // Do we already own this recursive or error-check mutex?
     pid_t tid = __get_thread()->tid;
@@ -752,11 +875,9 @@
         uint16_t shared = (old_state & MUTEX_SHARED_MASK);
         return NonPI::NormalMutexTryLock(mutex, shared);
     }
-#if defined(__LP64__)
     if (mtype == MUTEX_TYPE_BITS_WITH_PI) {
-        return PIMutexTryLock(mutex->pi_mutex);
+        return PIMutexTryLock(mutex->ToPIMutex());
     }
-#endif
 
     // Do we already own this recursive or error-check mutex?
     pid_t tid = __get_thread()->tid;
@@ -813,23 +934,28 @@
             return 0;
         }
     }
-#if defined(__LP64__)
     if (mtype == MUTEX_TYPE_BITS_WITH_PI) {
-        return PIMutexTimedLock(mutex->pi_mutex, abs_timeout);
+        return PIMutexTimedLock(mutex->ToPIMutex(), abs_timeout);
     }
-#endif
     return NonPI::MutexLockWithTimeout(mutex, true, abs_timeout);
 }
 
 int pthread_mutex_destroy(pthread_mutex_t* mutex_interface) {
     pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);
     uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
-#if defined(__LP64__)
+    if (old_state == 0xffff) {
+        // The mutex has been destroyed.
+        return EBUSY;
+    }
     uint16_t mtype  = (old_state & MUTEX_TYPE_MASK);
     if (mtype == MUTEX_TYPE_BITS_WITH_PI) {
-        return PIMutexDestroy(mutex->pi_mutex);
+        int result = PIMutexDestroy(mutex->ToPIMutex());
+        if (result == 0) {
+            mutex->FreePIMutex();
+            atomic_store(&mutex->state, 0xffff);
+        }
+        return result;
     }
-#endif
     // Store 0xffff to make the mutex unusable. Although POSIX standard says it is undefined
     // behavior to destroy a locked mutex, we prefer not to change mutex->state in that situation.
     if (MUTEX_STATE_BITS_IS_UNLOCKED(old_state) &&
diff --git a/libc/bionic/send.cpp b/libc/bionic/send.cpp
index 8f175d3..2e5d457 100644
--- a/libc/bionic/send.cpp
+++ b/libc/bionic/send.cpp
@@ -28,6 +28,6 @@
 
 #include <sys/socket.h>
 
-ssize_t send(int socket, const void* buf, size_t len, int flags) __overloadable {
+ssize_t send(int socket, const void* buf, size_t len, int flags) {
   return sendto(socket, buf, len, flags, NULL, 0);
 }
diff --git a/libc/bionic/sigaction.cpp b/libc/bionic/sigaction.cpp
index 0633748..41923cf 100644
--- a/libc/bionic/sigaction.cpp
+++ b/libc/bionic/sigaction.cpp
@@ -27,6 +27,9 @@
  */
 
 #include <signal.h>
+#include <string.h>
+
+#include "private/sigrtmin.h"
 
 extern "C" void __restore_rt(void);
 extern "C" void __restore(void);
@@ -40,7 +43,7 @@
   if (bionic_new_action != NULL) {
     kernel_new_action.sa_flags = bionic_new_action->sa_flags;
     kernel_new_action.sa_handler = bionic_new_action->sa_handler;
-    kernel_new_action.sa_mask = bionic_new_action->sa_mask;
+    kernel_new_action.sa_mask = filter_reserved_signals(bionic_new_action->sa_mask);
 #if defined(SA_RESTORER)
     kernel_new_action.sa_restorer = bionic_new_action->sa_restorer;
 #if defined(__aarch64__)
@@ -75,28 +78,57 @@
   return result;
 }
 
+__strong_alias(sigaction64, sigaction);
+
 #else
 
-extern "C" int __sigaction(int, const struct sigaction*, struct sigaction*);
+extern "C" int __rt_sigaction(int, const struct sigaction64*, struct sigaction64*, size_t);
 
-int sigaction(int signal, const struct sigaction* bionic_new_action, struct sigaction* bionic_old_action) {
+int sigaction(int signal, const struct sigaction* bionic_new, struct sigaction* bionic_old) {
   // The 32-bit ABI is broken. struct sigaction includes a too-small sigset_t,
-  // so we have to use sigaction(2) rather than rt_sigaction(2).
-  struct sigaction kernel_new_action;
-  if (bionic_new_action != NULL) {
-    kernel_new_action.sa_flags = bionic_new_action->sa_flags;
-    kernel_new_action.sa_handler = bionic_new_action->sa_handler;
-    kernel_new_action.sa_mask = bionic_new_action->sa_mask;
+  // so we have to translate to struct sigaction64 first.
+  struct sigaction64 kernel_new;
+  if (bionic_new) {
+    kernel_new = {};
+    kernel_new.sa_flags = bionic_new->sa_flags;
+    kernel_new.sa_handler = bionic_new->sa_handler;
 #if defined(SA_RESTORER)
-    kernel_new_action.sa_restorer = bionic_new_action->sa_restorer;
+    kernel_new.sa_restorer = bionic_new->sa_restorer;
+#endif
+    memcpy(&kernel_new.sa_mask, &bionic_new->sa_mask, sizeof(bionic_new->sa_mask));
+  }
 
-    if (!(kernel_new_action.sa_flags & SA_RESTORER)) {
-      kernel_new_action.sa_flags |= SA_RESTORER;
-      kernel_new_action.sa_restorer = (kernel_new_action.sa_flags & SA_SIGINFO) ? &__restore_rt : &__restore;
+  struct sigaction64 kernel_old;
+  int result = sigaction64(signal, bionic_new ? &kernel_new : nullptr, &kernel_old);
+  if (bionic_old) {
+    *bionic_old = {};
+    bionic_old->sa_flags = kernel_old.sa_flags;
+    bionic_old->sa_handler = kernel_old.sa_handler;
+#if defined(SA_RESTORER)
+    bionic_old->sa_restorer = kernel_old.sa_restorer;
+#endif
+    memcpy(&bionic_old->sa_mask, &kernel_old.sa_mask, sizeof(bionic_old->sa_mask));
+  }
+  return result;
+}
+
+int sigaction64(int signal, const struct sigaction64* bionic_new, struct sigaction64* bionic_old) {
+  struct sigaction64 kernel_new;
+  if (bionic_new) {
+    kernel_new = *bionic_new;
+#if defined(SA_RESTORER)
+    if (!(kernel_new.sa_flags & SA_RESTORER)) {
+      kernel_new.sa_flags |= SA_RESTORER;
+      kernel_new.sa_restorer = (kernel_new.sa_flags & SA_SIGINFO) ? &__restore_rt : &__restore;
     }
 #endif
+    kernel_new.sa_mask = filter_reserved_signals(kernel_new.sa_mask);
   }
-  return __sigaction(signal, (bionic_new_action != NULL) ? &kernel_new_action : NULL, bionic_old_action);
+
+  return __rt_sigaction(signal,
+                        bionic_new ? &kernel_new : nullptr,
+                        bionic_old,
+                        sizeof(kernel_new.sa_mask));
 }
 
 #endif
diff --git a/libc/bionic/signal.cpp b/libc/bionic/signal.cpp
index 9a23416..175182b 100644
--- a/libc/bionic/signal.cpp
+++ b/libc/bionic/signal.cpp
@@ -30,19 +30,36 @@
 #include <pthread.h>
 #include <signal.h>
 #include <string.h>
+#include <sys/epoll.h>
+#include <sys/signalfd.h>
 #include <sys/types.h>
 #include <time.h>
 #include <unistd.h>
 
-#include "private/kernel_sigset_t.h"
+#include "private/ErrnoRestorer.h"
+#include "private/SigSetConverter.h"
+#include "private/sigrtmin.h"
 
+extern "C" int __rt_sigpending(const sigset64_t*, size_t);
 extern "C" int ___rt_sigqueueinfo(pid_t, int, siginfo_t*);
-extern "C" int __rt_sigtimedwait(const sigset_t*, siginfo_t*, const timespec*, size_t);
+extern "C" int __rt_sigsuspend(const sigset64_t*, size_t);
+extern "C" int __rt_sigtimedwait(const sigset64_t*, siginfo_t*, const timespec*, size_t);
 
-int sigaddset(sigset_t* set, int signum) {
-  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+int pthread_sigmask(int how, const sigset_t* new_set, sigset_t* old_set) {
+  ErrnoRestorer errno_restorer;
+  return (sigprocmask(how, new_set, old_set) == -1) ? errno : 0;
+}
+
+int pthread_sigmask64(int how, const sigset64_t* new_set, sigset64_t* old_set) {
+  ErrnoRestorer errno_restorer;
+  return (sigprocmask64(how, new_set, old_set) == -1) ? errno : 0;
+}
+
+template <typename SigSetT>
+int SigAddSet(SigSetT* set, int sig) {
+  int bit = sig - 1; // Signal numbers start at 1, but bit positions start at 0.
   unsigned long* local_set = reinterpret_cast<unsigned long*>(set);
-  if (set == NULL || bit < 0 || bit >= static_cast<int>(8*sizeof(sigset_t))) {
+  if (set == nullptr || bit < 0 || bit >= static_cast<int>(8*sizeof(*set))) {
     errno = EINVAL;
     return -1;
   }
@@ -50,24 +67,28 @@
   return 0;
 }
 
-// This isn't in our header files, but is exposed on all architectures.
-extern "C" int sigblock(int mask) {
-  union {
-    int mask;
-    sigset_t set;
-  } in, out;
-
-  sigemptyset(&in.set);
-  in.mask = mask;
-
-  if (sigprocmask(SIG_BLOCK, &in.set, &out.set) == -1) return -1;
-  return out.mask;
+int sigaddset(sigset_t* set, int sig) {
+  return SigAddSet(set, sig);
 }
 
-int sigdelset(sigset_t* set, int signum) {
-  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+int sigaddset64(sigset64_t* set, int sig) {
+  return SigAddSet(set, sig);
+}
+
+// This isn't in our header files, but is exposed on all architectures.
+extern "C" int sigblock(int mask) {
+  SigSetConverter in, out;
+  sigemptyset(&in.sigset);
+  in.bsd = mask;
+  if (sigprocmask(SIG_BLOCK, &in.sigset, &out.sigset) == -1) return -1;
+  return out.bsd;
+}
+
+template <typename SigSetT>
+int SigDelSet(SigSetT* set, int sig) {
+  int bit = sig - 1; // Signal numbers start at 1, but bit positions start at 0.
   unsigned long* local_set = reinterpret_cast<unsigned long*>(set);
-  if (set == NULL || bit < 0 || bit >= static_cast<int>(8*sizeof(sigset_t))) {
+  if (set == nullptr || bit < 0 || bit >= static_cast<int>(8*sizeof(*set))) {
     errno = EINVAL;
     return -1;
   }
@@ -75,197 +96,218 @@
   return 0;
 }
 
-int sigemptyset(sigset_t* set) {
-  if (set == NULL) {
+int sigdelset(sigset_t* set, int sig) {
+  return SigDelSet(set, sig);
+}
+
+int sigdelset64(sigset64_t* set, int sig) {
+  return SigDelSet(set, sig);
+}
+
+template <typename SigSetT>
+int SigEmptySet(SigSetT* set) {
+  if (set == nullptr) {
     errno = EINVAL;
     return -1;
   }
-  memset(set, 0, sizeof(sigset_t));
+  memset(set, 0, sizeof(*set));
+  return 0;
+}
+
+int sigemptyset(sigset_t* set) {
+  return SigEmptySet(set);
+}
+
+int sigemptyset64(sigset64_t* set) {
+  return SigEmptySet(set);
+}
+
+template <typename SigSetT>
+int SigFillSet(SigSetT* set) {
+  if (set == nullptr) {
+    errno = EINVAL;
+    return -1;
+  }
+  memset(set, 0xff, sizeof(*set));
   return 0;
 }
 
 int sigfillset(sigset_t* set) {
-  if (set == NULL) {
-    errno = EINVAL;
-    return -1;
-  }
-  memset(set, ~0, sizeof(sigset_t));
-  return 0;
+  return SigFillSet(set);
+}
+
+int sigfillset64(sigset64_t* set) {
+  return SigFillSet(set);
 }
 
 int sighold(int sig) {
-  kernel_sigset_t set;
-  set.clear();
-  if (!set.set(sig)) return -1;
-  return __rt_sigprocmask(SIG_BLOCK, &set, nullptr, sizeof(set));
+  sigset64_t set = {};
+  if (sigaddset64(&set, sig) == -1) return -1;
+  return sigprocmask64(SIG_BLOCK, &set, nullptr);
 }
 
 int sigignore(int sig) {
-  struct sigaction sa;
-  memset(&sa, 0, sizeof(sa));
-  if (sigemptyset(&sa.sa_mask) == -1) return -1;
-  sa.sa_handler = SIG_IGN;
-  return sigaction(sig, &sa, nullptr);
+  struct sigaction64 sa = { .sa_handler = SIG_IGN };
+  return sigaction64(sig, &sa, nullptr);
 }
 
 int siginterrupt(int sig, int flag) {
-  struct sigaction act;
-  sigaction(sig, nullptr, &act);
+  struct sigaction64 act;
+  sigaction64(sig, nullptr, &act);
   if (flag) {
     act.sa_flags &= ~SA_RESTART;
   } else {
     act.sa_flags |= SA_RESTART;
   }
-  return sigaction(sig, &act, nullptr);
+  return sigaction64(sig, &act, nullptr);
 }
 
-int sigismember(const sigset_t* set, int signum) {
-  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+template <typename SigSetT>
+int SigIsMember(const SigSetT* set, int sig) {
+  int bit = sig - 1; // Signal numbers start at 1, but bit positions start at 0.
   const unsigned long* local_set = reinterpret_cast<const unsigned long*>(set);
-  if (set == NULL || bit < 0 || bit >= static_cast<int>(8*sizeof(sigset_t))) {
+  if (set == nullptr || bit < 0 || bit >= static_cast<int>(8*sizeof(*set))) {
     errno = EINVAL;
     return -1;
   }
   return static_cast<int>((local_set[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1);
 }
 
-__LIBC_HIDDEN__ sighandler_t _signal(int signum, sighandler_t handler, int flags) {
-  struct sigaction sa;
-  sigemptyset(&sa.sa_mask);
-  sa.sa_handler = handler;
-  sa.sa_flags = flags;
-
-  if (sigaction(signum, &sa, &sa) == -1) {
-    return SIG_ERR;
-  }
-
-  return sa.sa_handler;
+int sigismember(const sigset_t* set, int sig) {
+  return SigIsMember(set, sig);
 }
 
-sighandler_t signal(int signum, sighandler_t handler) {
-  return _signal(signum, handler, SA_RESTART);
+int sigismember64(const sigset64_t* set, int sig) {
+  return SigIsMember(set, sig);
+}
+
+__LIBC_HIDDEN__ sighandler_t _signal(int sig, sighandler_t handler, int flags) {
+  struct sigaction64 sa = { .sa_handler = handler, .sa_flags = flags };
+  return (sigaction64(sig, &sa, &sa) == -1) ? SIG_ERR : sa.sa_handler;
+}
+
+sighandler_t signal(int sig, sighandler_t handler) {
+  return _signal(sig, handler, SA_RESTART);
 }
 
 int sigpause(int sig) {
-  kernel_sigset_t set;
-  set.clear();
-  if (__rt_sigprocmask(SIG_SETMASK, nullptr, &set, sizeof(set)) == -1) return -1;
-  if (!set.clear(sig)) return -1;
-  return __rt_sigsuspend(&set, sizeof(set));
+  sigset64_t set = {};
+  if (sigprocmask64(SIG_SETMASK, nullptr, &set) == -1 || sigdelset64(&set, sig) == -1) return -1;
+  return sigsuspend64(&set);
 }
 
 int sigpending(sigset_t* bionic_set) {
-  kernel_sigset_t set;
-  int result = __rt_sigpending(&set, sizeof(set));
-  if (result != -1) {
-    *bionic_set = set.bionic;
-  }
-  return result;
-}
-
-int sigprocmask(int how, const sigset_t* bionic_new_set, sigset_t* bionic_old_set) {
-  kernel_sigset_t new_set;
-  kernel_sigset_t* new_set_ptr = NULL;
-  if (bionic_new_set != NULL) {
-    new_set.set(bionic_new_set);
-    new_set_ptr = &new_set;
-  }
-
-  kernel_sigset_t old_set;
-  if (__rt_sigprocmask(how, new_set_ptr, &old_set, sizeof(old_set)) == -1) {
-    return -1;
-  }
-
-  if (bionic_old_set != NULL) {
-    *bionic_old_set = old_set.bionic;
-  }
-
+  SigSetConverter set = {};
+  set.sigset = *bionic_set;
+  if (__rt_sigpending(&set.sigset64, sizeof(set.sigset64)) == -1) return -1;
+  *bionic_set = set.sigset;
   return 0;
 }
 
-int sigqueue(pid_t pid, int signo, const sigval value) {
+int sigpending64(sigset64_t* set) {
+  return __rt_sigpending(set, sizeof(*set));
+}
+
+int sigqueue(pid_t pid, int sig, const sigval value) {
   siginfo_t info;
   memset(&info, 0, sizeof(siginfo_t));
-  info.si_signo = signo;
+  info.si_signo = sig;
   info.si_code = SI_QUEUE;
   info.si_pid = getpid();
   info.si_uid = getuid();
   info.si_value = value;
-
-  return ___rt_sigqueueinfo(pid, signo, &info);
+  return ___rt_sigqueueinfo(pid, sig, &info);
 }
 
 int sigrelse(int sig) {
-  kernel_sigset_t set;
-  set.clear();
-  if (!set.set(sig)) return -1;
-  return __rt_sigprocmask(SIG_UNBLOCK, &set, nullptr, sizeof(set));
+  sigset64_t set = {};
+  if (sigaddset64(&set, sig) == -1) return -1;
+  return sigprocmask64(SIG_UNBLOCK, &set, nullptr);
 }
 
 sighandler_t sigset(int sig, sighandler_t disp) {
-  struct sigaction new_sa;
-  if (disp != SIG_HOLD) {
-    memset(&new_sa, 0, sizeof(new_sa));
-    new_sa.sa_handler = disp;
-    sigemptyset(&new_sa.sa_mask);
-  }
+  struct sigaction64 new_sa;
+  if (disp != SIG_HOLD) new_sa = { .sa_handler = disp };
 
-  struct sigaction old_sa;
-  if (sigaction(sig, (disp == SIG_HOLD) ? nullptr : &new_sa, &old_sa) == -1) {
+  struct sigaction64 old_sa;
+  if (sigaction64(sig, (disp == SIG_HOLD) ? nullptr : &new_sa, &old_sa) == -1) {
     return SIG_ERR;
   }
 
-  kernel_sigset_t new_mask{sig};
-  kernel_sigset_t old_mask;
-  if (__rt_sigprocmask(disp == SIG_HOLD ? SIG_BLOCK : SIG_UNBLOCK, &new_mask, &old_mask,
-                       sizeof(new_mask)) == -1) {
+  sigset64_t new_mask = {};
+  sigaddset64(&new_mask, sig);
+  sigset64_t old_mask;
+  if (sigprocmask64(disp == SIG_HOLD ? SIG_BLOCK : SIG_UNBLOCK, &new_mask, &old_mask) == -1) {
     return SIG_ERR;
   }
 
-  return old_mask.is_set(sig) ? SIG_HOLD : old_sa.sa_handler;
+  return sigismember64(&old_mask, sig) ? SIG_HOLD : old_sa.sa_handler;
 }
 
 // This isn't in our header files, but is exposed on all architectures.
 extern "C" int sigsetmask(int mask) {
-  union {
-    int mask;
-    sigset_t set;
-  } in, out;
-
-  sigemptyset(&in.set);
-  in.mask = mask;
-
-  if (sigprocmask(SIG_SETMASK, &in.set, &out.set) == -1) return -1;
-  return out.mask;
+  SigSetConverter in, out;
+  sigemptyset(&in.sigset);
+  in.bsd = mask;
+  if (sigprocmask(SIG_SETMASK, &in.sigset, &out.sigset) == -1) return -1;
+  return out.bsd;
 }
 
 int sigsuspend(const sigset_t* bionic_set) {
-  kernel_sigset_t set(bionic_set);
-  return __rt_sigsuspend(&set, sizeof(set));
+  SigSetConverter set = {};
+  set.sigset = *bionic_set;
+  return sigsuspend64(&set.sigset64);
 }
 
-int sigtimedwait(const sigset_t* set, siginfo_t* info, const timespec* timeout) {
-  kernel_sigset_t sigset(set);
-  return __rt_sigtimedwait(sigset.get(), info, timeout, sizeof(sigset));
+int sigsuspend64(const sigset64_t* set) {
+  sigset64_t mutable_set;
+  sigset64_t* mutable_set_ptr = nullptr;
+  if (set) {
+    mutable_set = filter_reserved_signals(*set);
+    mutable_set_ptr = &mutable_set;
+  }
+  return __rt_sigsuspend(mutable_set_ptr, sizeof(*set));
 }
 
-int sigwait(const sigset_t* set, int* sig) {
-  kernel_sigset_t sigset(set);
+int sigtimedwait(const sigset_t* bionic_set, siginfo_t* info, const timespec* timeout) {
+  SigSetConverter set = {};
+  set.sigset = *bionic_set;
+  return sigtimedwait64(&set.sigset64, info, timeout);
+}
+
+int sigtimedwait64(const sigset64_t* set, siginfo_t* info, const timespec* timeout) {
+  sigset64_t mutable_set;
+  sigset64_t* mutable_set_ptr = nullptr;
+  if (set) {
+    mutable_set = filter_reserved_signals(*set);
+    mutable_set_ptr = &mutable_set;
+  }
+  return __rt_sigtimedwait(mutable_set_ptr, info, timeout, sizeof(*set));
+}
+
+int sigwait(const sigset_t* bionic_set, int* sig) {
+  SigSetConverter set = {};
+  set.sigset = *bionic_set;
+  return sigwait64(&set.sigset64, sig);
+}
+
+int sigwait64(const sigset64_t* set, int* sig) {
   while (true) {
     // __rt_sigtimedwait can return EAGAIN or EINTR, we need to loop
     // around them since sigwait is only allowed to return EINVAL.
-    int result = __rt_sigtimedwait(sigset.get(), NULL, NULL, sizeof(sigset));
+    int result = sigtimedwait64(set, nullptr, nullptr);
     if (result >= 0) {
       *sig = result;
       return 0;
     }
-
-    if (errno != EAGAIN && errno != EINTR) {
-      return errno;
-    }
+    if (errno != EAGAIN && errno != EINTR) return errno;
   }
 }
 
 int sigwaitinfo(const sigset_t* set, siginfo_t* info) {
-  return sigtimedwait(set, info, NULL);
+  return sigtimedwait(set, info, nullptr);
+}
+
+int sigwaitinfo64(const sigset64_t* set, siginfo_t* info) {
+  return sigtimedwait64(set, info, nullptr);
 }
diff --git a/libc/bionic/sigprocmask.cpp b/libc/bionic/sigprocmask.cpp
new file mode 100644
index 0000000..36866f3
--- /dev/null
+++ b/libc/bionic/sigprocmask.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 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 <signal.h>
+
+#include "private/sigrtmin.h"
+#include "private/SigSetConverter.h"
+
+extern "C" int __rt_sigprocmask(int, const sigset64_t*, sigset64_t*, size_t);
+
+//
+// These need to be kept separate from pthread_sigmask, sigblock, sigsetmask,
+// sighold, and sigset because libsigchain only intercepts sigprocmask so we
+// can't allow clang to decide to inline sigprocmask.
+//
+
+int sigprocmask(int how,
+                const sigset_t* bionic_new_set,
+                sigset_t* bionic_old_set) __attribute__((__noinline__)) {
+  SigSetConverter new_set;
+  sigset64_t* new_set_ptr = nullptr;
+  if (bionic_new_set != nullptr) {
+    sigemptyset64(&new_set.sigset64);
+    new_set.sigset = *bionic_new_set;
+    new_set_ptr = &new_set.sigset64;
+  }
+
+  SigSetConverter old_set;
+  if (sigprocmask64(how, new_set_ptr, &old_set.sigset64) == -1) {
+    return -1;
+  }
+
+  if (bionic_old_set != nullptr) {
+    *bionic_old_set = old_set.sigset;
+  }
+
+  return 0;
+}
+
+int sigprocmask64(int how,
+                  const sigset64_t* new_set,
+                  sigset64_t* old_set) __attribute__((__noinline__)) {
+  sigset64_t mutable_new_set;
+  sigset64_t* mutable_new_set_ptr = nullptr;
+  if (new_set) {
+    mutable_new_set = filter_reserved_signals(*new_set);
+    mutable_new_set_ptr = &mutable_new_set;
+  }
+  return __rt_sigprocmask(how, mutable_new_set_ptr, old_set, sizeof(*new_set));
+}
diff --git a/libc/bionic/spawn.cpp b/libc/bionic/spawn.cpp
index e5075f5..fde102c 100644
--- a/libc/bionic/spawn.cpp
+++ b/libc/bionic/spawn.cpp
@@ -36,6 +36,7 @@
 #include <unistd.h>
 
 #include "private/ScopedSignalBlocker.h"
+#include "private/SigSetConverter.h"
 
 enum Action {
   kOpen,
@@ -87,8 +88,8 @@
   pid_t pgroup;
   sched_param schedparam;
   int schedpolicy;
-  sigset_t sigmask;
-  sigset_t sigdefault;
+  SigSetConverter sigmask;
+  SigSetConverter sigdefault;
 };
 
 static void ApplyAttrs(short flags, const posix_spawnattr_t* attr) {
@@ -97,17 +98,17 @@
   // POSIX: "Signals set to be caught by the calling process shall be
   // set to the default action in the child process."
   bool use_sigdefault = ((flags & POSIX_SPAWN_SETSIGDEF) != 0);
-  const struct sigaction default_sa = { .sa_handler = SIG_DFL };
+  const struct sigaction64 default_sa = { .sa_handler = SIG_DFL };
   for (int s = 1; s < _NSIG; ++s) {
     bool reset = false;
-    if (use_sigdefault && sigismember(&(*attr)->sigdefault, s)) {
+    if (use_sigdefault && sigismember64(&(*attr)->sigdefault.sigset64, s)) {
       reset = true;
     } else {
-      struct sigaction current;
-      if (sigaction(s, nullptr, &current) == -1) _exit(127);
+      struct sigaction64 current;
+      if (sigaction64(s, nullptr, &current) == -1) _exit(127);
       reset = (current.sa_handler != SIG_IGN && current.sa_handler != SIG_DFL);
     }
-    if (reset && sigaction(s, &default_sa, nullptr) == -1) _exit(127);
+    if (reset && sigaction64(s, &default_sa, nullptr) == -1) _exit(127);
   }
 
   if ((flags & POSIX_SPAWN_SETPGROUP) != 0 && setpgid(0, (*attr)->pgroup) == -1) _exit(127);
@@ -126,7 +127,7 @@
   }
 
   if ((flags & POSIX_SPAWN_SETSIGMASK) != 0) {
-    if (sigprocmask(SIG_SETMASK, &(*attr)->sigmask, nullptr)) _exit(127);
+    if (sigprocmask64(SIG_SETMASK, &(*attr)->sigmask.sigset64, nullptr)) _exit(127);
   }
 }
 
@@ -209,22 +210,42 @@
 }
 
 int posix_spawnattr_setsigmask(posix_spawnattr_t* attr, const sigset_t* mask) {
-  (*attr)->sigmask = *mask;
+  (*attr)->sigmask.sigset = *mask;
+  return 0;
+}
+
+int posix_spawnattr_setsigmask64(posix_spawnattr_t* attr, const sigset64_t* mask) {
+  (*attr)->sigmask.sigset64 = *mask;
   return 0;
 }
 
 int posix_spawnattr_getsigmask(const posix_spawnattr_t* attr, sigset_t* mask) {
-  *mask = (*attr)->sigmask;
+  *mask = (*attr)->sigmask.sigset;
+  return 0;
+}
+
+int posix_spawnattr_getsigmask64(const posix_spawnattr_t* attr, sigset64_t* mask) {
+  *mask = (*attr)->sigmask.sigset64;
   return 0;
 }
 
 int posix_spawnattr_setsigdefault(posix_spawnattr_t* attr, const sigset_t* mask) {
-  (*attr)->sigdefault = *mask;
+  (*attr)->sigdefault.sigset = *mask;
+  return 0;
+}
+
+int posix_spawnattr_setsigdefault64(posix_spawnattr_t* attr, const sigset64_t* mask) {
+  (*attr)->sigdefault.sigset64 = *mask;
   return 0;
 }
 
 int posix_spawnattr_getsigdefault(const posix_spawnattr_t* attr, sigset_t* mask) {
-  *mask = (*attr)->sigdefault;
+  *mask = (*attr)->sigdefault.sigset;
+  return 0;
+}
+
+int posix_spawnattr_getsigdefault64(const posix_spawnattr_t* attr, sigset64_t* mask) {
+  *mask = (*attr)->sigdefault.sigset64;
   return 0;
 }
 
diff --git a/libc/bionic/epoll_pwait.cpp b/libc/bionic/sys_epoll.cpp
similarity index 68%
rename from libc/bionic/epoll_pwait.cpp
rename to libc/bionic/sys_epoll.cpp
index f3af93e..9f82912 100644
--- a/libc/bionic/epoll_pwait.cpp
+++ b/libc/bionic/sys_epoll.cpp
@@ -26,18 +26,36 @@
  * SUCH DAMAGE.
  */
 
+#include <errno.h>
 #include <sys/epoll.h>
 
-#include "private/kernel_sigset_t.h"
+#include "private/SigSetConverter.h"
 
-extern "C" int __epoll_pwait(int, epoll_event*, int, int, const kernel_sigset_t*, size_t);
+extern "C" int __epoll_pwait(int, epoll_event*, int, int, const sigset64_t*, size_t);
+
+int epoll_create(int size) {
+  if (size <= 0) {
+    errno = EINVAL;
+    return -1;
+  }
+  return epoll_create1(0);
+}
 
 int epoll_pwait(int fd, epoll_event* events, int max_events, int timeout, const sigset_t* ss) {
-  kernel_sigset_t kernel_ss;
-  kernel_sigset_t* kernel_ss_ptr = NULL;
-  if (ss != NULL) {
-    kernel_ss.set(ss);
-    kernel_ss_ptr = &kernel_ss;
+  SigSetConverter set;
+  sigset64_t* ss_ptr = nullptr;
+  if (ss != nullptr) {
+    set = {};
+    set.sigset = *ss;
+    ss_ptr = &set.sigset64;
   }
-  return __epoll_pwait(fd, events, max_events, timeout, kernel_ss_ptr, sizeof(kernel_ss));
+  return epoll_pwait64(fd, events, max_events, timeout, ss_ptr);
+}
+
+int epoll_pwait64(int fd, epoll_event* events, int max_events, int timeout, const sigset64_t* ss) {
+  return __epoll_pwait(fd, events, max_events, timeout, ss, sizeof(*ss));
+}
+
+int epoll_wait(int fd, struct epoll_event* events, int max_events, int timeout) {
+  return epoll_pwait64(fd, events, max_events, timeout, nullptr);
 }
diff --git a/libc/bionic/sys_signalfd.cpp b/libc/bionic/sys_signalfd.cpp
index 63e1db4..53d1f25 100644
--- a/libc/bionic/sys_signalfd.cpp
+++ b/libc/bionic/sys_signalfd.cpp
@@ -28,11 +28,16 @@
 
 #include <sys/signalfd.h>
 
-#include "private/kernel_sigset_t.h"
+#include "private/SigSetConverter.h"
 
-extern "C" int __signalfd4(int fd, kernel_sigset_t* mask, size_t sizemask, int flags);
+extern "C" int __signalfd4(int, const sigset64_t*, size_t, int);
 
 int signalfd(int fd, const sigset_t* mask, int flags) {
-  kernel_sigset_t in_set(mask);
-  return __signalfd4(fd, &in_set, sizeof(in_set), flags);
+  SigSetConverter set = {};
+  set.sigset = *mask;
+  return signalfd64(fd, &set.sigset64, flags);
+}
+
+int signalfd64(int fd, const sigset64_t* mask, int flags) {
+  return __signalfd4(fd, mask, sizeof(*mask), flags);
 }
diff --git a/libc/bionic/system_property_api.cpp b/libc/bionic/system_property_api.cpp
index f2e1032..10d1bb3 100644
--- a/libc/bionic/system_property_api.cpp
+++ b/libc/bionic/system_property_api.cpp
@@ -35,6 +35,8 @@
 #include "private/bionic_defs.h"
 
 static SystemProperties system_properties;
+static_assert(__is_trivially_constructible(SystemProperties),
+              "System Properties must be trivially constructable");
 
 // This is public because it was exposed in the NDK. As of 2017-01, ~60 apps reference this symbol.
 // It is set to nullptr and never modified.
diff --git a/libc/bionic/wchar_l.cpp b/libc/bionic/wchar_l.cpp
index 6c39e8d..a86961f 100644
--- a/libc/bionic/wchar_l.cpp
+++ b/libc/bionic/wchar_l.cpp
@@ -37,24 +37,42 @@
   return wcsncasecmp(ws1, ws2, n);
 }
 
-int wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t) {
+int wcscoll_l(const wchar_t* ws1, const wchar_t* ws2, locale_t) {
   return wcscoll(ws1, ws2);
 }
 
-size_t wcsxfrm_l(wchar_t *dest, const wchar_t *src, size_t n, locale_t) {
-  return wcsxfrm(dest, src, n);
+size_t wcsftime_l(wchar_t* buf, size_t n, const wchar_t* fmt, const struct tm* tm, locale_t) {
+  return wcsftime(buf, n, fmt, tm);
 }
 
-long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr, int base,
-                    locale_t) {
-  return wcstoll(nptr, endptr, base);
+size_t wcsxfrm_l(wchar_t* dst, const wchar_t* src, size_t n, locale_t) {
+  return wcsxfrm(dst, src, n);
 }
 
-unsigned long long wcstoull_l(const wchar_t *nptr, wchar_t **endptr,
-                              int base, locale_t) {
-  return wcstoull(nptr, endptr, base);
+double wcstod_l(const wchar_t* s, wchar_t** end_ptr, locale_t) {
+  return wcstod(s, end_ptr);
 }
 
-long double wcstold_l(const wchar_t *nptr, wchar_t **endptr, locale_t) {
-  return wcstold(nptr, endptr);
+float wcstof_l(const wchar_t* s, wchar_t** end_ptr, locale_t) {
+  return wcstof(s, end_ptr);
+}
+
+long wcstol_l(const wchar_t* s, wchar_t** end_ptr, int base, locale_t) {
+  return wcstol(s, end_ptr, base);
+}
+
+long long wcstoll_l(const wchar_t* s, wchar_t** end_ptr, int base, locale_t) {
+  return wcstoll(s, end_ptr, base);
+}
+
+unsigned long wcstoul_l(const wchar_t* s, wchar_t** end_ptr, int base, locale_t) {
+  return wcstoul(s, end_ptr, base);
+}
+
+unsigned long long wcstoull_l(const wchar_t* s, wchar_t** end_ptr, int base, locale_t) {
+  return wcstoull(s, end_ptr, base);
+}
+
+long double wcstold_l(const wchar_t* s, wchar_t** end_ptr, locale_t) {
+  return wcstold(s, end_ptr);
 }
diff --git a/libc/include/android/api-level.h b/libc/include/android/api-level.h
index 18825e7..7a909d7 100644
--- a/libc/include/android/api-level.h
+++ b/libc/include/android/api-level.h
@@ -58,5 +58,6 @@
 #define __ANDROID_API_N_MR1__ 25
 #define __ANDROID_API_O__ 26
 #define __ANDROID_API_O_MR1__ 27
+#define __ANDROID_API_P__ 28
 
-#endif /* ANDROID_API_LEVEL_H */
+#endif
diff --git a/libc/include/android/legacy_stdlib_inlines.h b/libc/include/android/legacy_stdlib_inlines.h
index 4896d2e..439b486 100644
--- a/libc/include/android/legacy_stdlib_inlines.h
+++ b/libc/include/android/legacy_stdlib_inlines.h
@@ -45,7 +45,7 @@
 
 __END_DECLS
 
-#endif
+#endif  /* __ANDROID_API__ < __ANDROID_API_K__ */
 
 #if __ANDROID_API__ < __ANDROID_API_L__
 
@@ -83,5 +83,29 @@
 
 __END_DECLS
 
-#endif
+#endif  /* __ANDROID_API__ < __ANDROID_API_L__ */
+
+#if __ANDROID_API__ < __ANDROID_API_O__
+
+#include <stdlib.h>
+#include <xlocale.h>
+
+__BEGIN_DECLS
+
+static __inline double strtod_l(const char* __s, char** __end_ptr, locale_t __l) {
+  return strtod(__s, __end_ptr);
+}
+
+static __inline float strtof_l(const char* __s, char** __end_ptr, locale_t __l) {
+  return strtof(__s, __end_ptr);
+}
+
+static __inline long strtol_l(const char* __s, char** __end_ptr, int __base, locale_t __l) {
+  return strtol(__s, __end_ptr, __base);
+}
+
+__END_DECLS
+
+#endif  /* __ANDROID_API__ < __ANDROID_API_O__ */
+
 #endif /* _ANDROID_LEGACY_STDLIB_INLINES_H_ */
diff --git a/libc/include/bits/signal_types.h b/libc/include/bits/signal_types.h
new file mode 100644
index 0000000..881ac58
--- /dev/null
+++ b/libc/include/bits/signal_types.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#ifndef _BITS_SIGNAL_TYPES_H_
+#define _BITS_SIGNAL_TYPES_H_
+
+#include <limits.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+/* For 64-bit (and mips), the kernel's struct sigaction doesn't match the
+ * POSIX one, so we need to expose our own and translate behind the scenes.
+ * For 32-bit, we're stuck with the definitions we already shipped,
+ * even though they contain a sigset_t that's too small. See sigaction64.
+ */
+#define sigaction __kernel_sigaction
+#include <linux/signal.h>
+#undef sigaction
+
+/* The arm and x86 kernel header files don't define _NSIG. */
+#ifndef _KERNEL__NSIG
+#define _KERNEL__NSIG 64
+#endif
+
+/* Userspace's NSIG is the kernel's _NSIG + 1. */
+#define _NSIG (_KERNEL__NSIG + 1)
+#define NSIG _NSIG
+
+typedef int sig_atomic_t;
+
+typedef __sighandler_t sig_t; /* BSD compatibility. */
+typedef __sighandler_t sighandler_t; /* glibc compatibility. */
+
+/* sigset_t is already large enough on LP64 and mips, but other LP32's sigset_t
+ * is just `unsigned long`.
+ */
+#if defined(__LP64__) || defined(__mips__)
+typedef sigset_t sigset64_t;
+#else
+typedef struct { unsigned long __bits[_KERNEL__NSIG/LONG_BIT]; } sigset64_t;
+#endif
+
+#if defined(__LP64__)
+
+#define __SIGACTION_BODY \
+  int sa_flags; \
+  union { \
+    sighandler_t sa_handler; \
+    void (*sa_sigaction)(int, struct siginfo*, void*); \
+  }; \
+  sigset_t sa_mask; \
+  void (*sa_restorer)(void); \
+
+struct sigaction { __SIGACTION_BODY };
+struct sigaction64 { __SIGACTION_BODY };
+
+#undef __SIGACTION_BODY
+
+#elif defined(__mips__)
+
+#define __SIGACTION_BODY \
+  int sa_flags; \
+  union { \
+    sighandler_t sa_handler; \
+    void (*sa_sigaction)(int, struct siginfo*, void*); \
+  }; \
+  sigset_t sa_mask; \
+
+struct sigaction { __SIGACTION_BODY };
+struct sigaction64 { __SIGACTION_BODY };
+
+#undef __SIGACTION_BODY
+
+#else
+
+#undef sa_handler
+#undef sa_sigaction
+
+struct sigaction {
+  union {
+    sighandler_t sa_handler;
+    void (*sa_sigaction)(int, struct siginfo*, void*);
+  };
+  sigset_t sa_mask;
+  int sa_flags;
+  void (*sa_restorer)(void);
+};
+
+/* This matches the kernel's internal structure. */
+struct sigaction64 {
+  union {
+    sighandler_t sa_handler;
+    void (*sa_sigaction)(int, struct siginfo*, void*);
+  };
+  int sa_flags;
+  void (*sa_restorer)(void);
+  sigset64_t sa_mask;
+};
+
+#endif
+
+#endif
diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h
index 4852f5f..1c5d64c 100644
--- a/libc/include/fcntl.h
+++ b/libc/include/fcntl.h
@@ -71,9 +71,9 @@
 
 int creat(const char* __path, mode_t __mode);
 int creat64(const char* __path, mode_t __mode) __INTRODUCED_IN(21);
-int openat(int __dir_fd, const char* __path, int __flags, ...) __overloadable __RENAME_CLANG(openat);
+int openat(int __dir_fd, const char* __path, int __flags, ...);
 int openat64(int __dir_fd, const char* __path, int __flags, ...) __INTRODUCED_IN(21);
-int open(const char* __path, int __flags, ...) __overloadable __RENAME_CLANG(open);
+int open(const char* __path, int __flags, ...);
 int open64(const char* __path, int __flags, ...) __INTRODUCED_IN(21);
 ssize_t splice(int __in_fd, off64_t* __in_offset, int __out_fd, off64_t* __out_offset, size_t __length, unsigned int __flags) __INTRODUCED_IN(21);
 ssize_t tee(int __in_fd, int __out_fd, size_t __length, unsigned int __flags) __INTRODUCED_IN(21);
diff --git a/libc/include/ftw.h b/libc/include/ftw.h
index 300f624..a289643 100644
--- a/libc/include/ftw.h
+++ b/libc/include/ftw.h
@@ -56,11 +56,9 @@
 
 __BEGIN_DECLS
 int ftw(const char* __dir_path, int (*__callback)(const char*, const struct stat*, int), int __max_fd_count) __INTRODUCED_IN(17);
-int nftw(const char* __dir_path, int (*__callback)(const char*, const struct stat*, int, struct FTW*), int __max_fd_count, int __flags)
-  __INTRODUCED_IN(17);
-int ftw64(const char* __dir_path, int (*__callback)(const char*, const struct stat64*, int), int __max_fd_count) __INTRODUCED_IN(21);
-int nftw64(const char* __dir_path, int (*__callback)(const char*, const struct stat64*, int, struct FTW*), int __max_fd_count, int __flags)
-  __INTRODUCED_IN(21);
+int nftw(const char* __dir_path, int (*__callback)(const char*, const struct stat*, int, struct FTW*), int __max_fd_count, int __flags) __INTRODUCED_IN(17);
+int ftw64(const char* __dir_path, int (*__callback)(const char*, const struct stat64*, int), int __max_fd_count) __RENAME_STAT64(ftw, 17, 21);
+int nftw64(const char* __dir_path, int (*__callback)(const char*, const struct stat64*, int, struct FTW*), int __max_fd_count, int __flags) __RENAME_STAT64(nftw, 17, 21);
 __END_DECLS
 
 #endif
diff --git a/libc/include/glob.h b/libc/include/glob.h
index 6ae8573..0ba2848 100644
--- a/libc/include/glob.h
+++ b/libc/include/glob.h
@@ -90,8 +90,8 @@
 
 __BEGIN_DECLS
 
-int glob(const char* __pattern, int __flags, int (*__error_callback)(const char* __failure_path, int __failure_errno), glob_t* __result_ptr) __INTRODUCED_IN_FUTURE;
-void globfree(glob_t* __result_ptr) __INTRODUCED_IN_FUTURE;
+int glob(const char* __pattern, int __flags, int (*__error_callback)(const char* __failure_path, int __failure_errno), glob_t* __result_ptr) __INTRODUCED_IN(28);
+void globfree(glob_t* __result_ptr) __INTRODUCED_IN(28);
 
 __END_DECLS
 
diff --git a/libc/include/iconv.h b/libc/include/iconv.h
index 4b05bae..df8fa6d 100644
--- a/libc/include/iconv.h
+++ b/libc/include/iconv.h
@@ -37,9 +37,9 @@
 struct __iconv_t;
 typedef struct __iconv_t* iconv_t;
 
-iconv_t iconv_open(const char* __src_encoding, const char* __dst_encoding) __INTRODUCED_IN_FUTURE;
-size_t iconv(iconv_t __converter, char** __src_buf, size_t* __src_bytes_left, char** __dst_buf, size_t* __dst_bytes_left) __INTRODUCED_IN_FUTURE;
-int iconv_close(iconv_t __converter) __INTRODUCED_IN_FUTURE;
+iconv_t iconv_open(const char* __src_encoding, const char* __dst_encoding) __INTRODUCED_IN(28);
+size_t iconv(iconv_t __converter, char** __src_buf, size_t* __src_bytes_left, char** __dst_buf, size_t* __dst_bytes_left) __INTRODUCED_IN(28);
+int iconv_close(iconv_t __converter) __INTRODUCED_IN(28);
 
 __END_DECLS
 
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index 80b08f6..3a678a9 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -81,6 +81,14 @@
 #define M_DECAY_TIME -100
 int mallopt(int __option, int __value) __INTRODUCED_IN(26);
 
+/*
+ * Memory Allocation Hooks
+ */
+extern void* (*volatile __malloc_hook)(size_t, const void*) __INTRODUCED_IN(28);
+extern void* (*volatile __realloc_hook)(void*, size_t, const void*) __INTRODUCED_IN(28);
+extern void (*volatile __free_hook)(void*, const void*) __INTRODUCED_IN(28);
+extern void* (*volatile __memalign_hook)(size_t, size_t, const void*) __INTRODUCED_IN(28);
+
 __END_DECLS
 
 #endif  /* LIBC_INCLUDE_MALLOC_H_ */
diff --git a/libc/include/netdb.h b/libc/include/netdb.h
index 4ee0ce2..7a1987e 100644
--- a/libc/include/netdb.h
+++ b/libc/include/netdb.h
@@ -214,23 +214,23 @@
 int gethostbyname_r(const char* __name, struct hostent* __ret, char* __buf, size_t __buf_size, struct hostent** __result, int* __h_errno_ptr);
 struct hostent* gethostbyname2(const char* __name, int __af);
 int gethostbyname2_r(const char* __name, int __af, struct hostent* __ret, char* __buf, size_t __buf_size, struct hostent** __result, int* __h_errno_ptr) __INTRODUCED_IN(23);
-void endhostent(void) __INTRODUCED_IN_FUTURE;
+void endhostent(void) __INTRODUCED_IN(28);
 struct hostent* gethostent(void);
-void sethostent(int __stay_open) __INTRODUCED_IN_FUTURE;
+void sethostent(int __stay_open) __INTRODUCED_IN(28);
 
 /* These functions are obsolete. None of these functions return anything but nullptr. */
-void endnetent(void) __INTRODUCED_IN_FUTURE;
+void endnetent(void) __INTRODUCED_IN(28);
 struct netent* getnetbyaddr(uint32_t __net, int __type);
 struct netent* getnetbyname(const char* __name);
-struct netent* getnetent(void) __INTRODUCED_IN_FUTURE;
-void setnetent(int __stay_open) __INTRODUCED_IN_FUTURE;
+struct netent* getnetent(void) __INTRODUCED_IN(28);
+void setnetent(int __stay_open) __INTRODUCED_IN(28);
 
 /* None of these functions return anything but nullptr. */
-void endprotoent(void) __INTRODUCED_IN_FUTURE;
+void endprotoent(void) __INTRODUCED_IN(28);
 struct protoent* getprotobyname(const char* __name);
 struct protoent* getprotobynumber(int __proto);
-struct protoent* getprotoent(void) __INTRODUCED_IN_FUTURE;
-void setprotoent(int __stay_open) __INTRODUCED_IN_FUTURE;
+struct protoent* getprotoent(void) __INTRODUCED_IN(28);
+void setprotoent(int __stay_open) __INTRODUCED_IN(28);
 
 /* These functions return entries from a built-in database. */
 void endservent(void);
diff --git a/libc/include/poll.h b/libc/include/poll.h
index 8517dc6..6a8f757 100644
--- a/libc/include/poll.h
+++ b/libc/include/poll.h
@@ -38,8 +38,9 @@
 
 typedef unsigned int nfds_t;
 
-int poll(struct pollfd* __fds, nfds_t __count, int __timeout_ms) __overloadable __RENAME_CLANG(poll);
-int ppoll(struct pollfd* __fds, nfds_t __count, const struct timespec* __timeout, const sigset_t* __mask) __overloadable __RENAME_CLANG(ppoll) __INTRODUCED_IN(21);
+int poll(struct pollfd* __fds, nfds_t __count, int __timeout_ms);
+int ppoll(struct pollfd* __fds, nfds_t __count, const struct timespec* __timeout, const sigset_t* __mask) __INTRODUCED_IN(21);
+int ppoll64(struct pollfd* __fds, nfds_t __count, const struct timespec* __timeout, const sigset64_t* __mask) __INTRODUCED_IN(28);
 
 #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
 #include <bits/fortify/poll.h>
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 97f023d..8d95a3b 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -230,7 +230,7 @@
 int pthread_setname_np(pthread_t __pthread, const char* __name);
 
 int pthread_setschedparam(pthread_t __pthread, int __policy, const struct sched_param* __param);
-int pthread_setschedprio(pthread_t __pthread, int __priority) __INTRODUCED_IN_FUTURE;
+int pthread_setschedprio(pthread_t __pthread, int __priority) __INTRODUCED_IN(28);
 
 int pthread_setspecific(pthread_key_t __key, const void* __value);
 
diff --git a/libc/include/search.h b/libc/include/search.h
index 5930bcd..97fdeda 100644
--- a/libc/include/search.h
+++ b/libc/include/search.h
@@ -40,14 +40,14 @@
 void insque(void* __element, void* __previous) __INTRODUCED_IN(21);
 void remque(void* __element) __INTRODUCED_IN(21);
 
-int hcreate(size_t) __INTRODUCED_IN_FUTURE;
-void hdestroy(void) __INTRODUCED_IN_FUTURE;
-ENTRY* hsearch(ENTRY, ACTION) __INTRODUCED_IN_FUTURE;
+int hcreate(size_t) __INTRODUCED_IN(28);
+void hdestroy(void) __INTRODUCED_IN(28);
+ENTRY* hsearch(ENTRY, ACTION) __INTRODUCED_IN(28);
 
 #if defined(__USE_BSD) || defined(__USE_GNU)
-int hcreate_r(size_t, struct hsearch_data*) __INTRODUCED_IN_FUTURE;
-void hdestroy_r(struct hsearch_data*) __INTRODUCED_IN_FUTURE;
-int hsearch_r(ENTRY, ACTION, ENTRY**, struct hsearch_data*) __INTRODUCED_IN_FUTURE;
+int hcreate_r(size_t, struct hsearch_data*) __INTRODUCED_IN(28);
+void hdestroy_r(struct hsearch_data*) __INTRODUCED_IN(28);
+int hsearch_r(ENTRY, ACTION, ENTRY**, struct hsearch_data*) __INTRODUCED_IN(28);
 #endif
 
 void* lfind(const void* __key, const void* __base, size_t* __count, size_t __size, int (*__comparator)(const void*, const void*))
diff --git a/libc/include/signal.h b/libc/include/signal.h
index d9c9ee2..00860d5 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -34,33 +34,15 @@
 
 #include <asm/sigcontext.h>
 #include <bits/pthread_types.h>
+#include <bits/signal_types.h>
 #include <bits/timespec.h>
 #include <limits.h>
 
-/* For 64-bit (and mips), the kernel's struct sigaction doesn't match the
- * POSIX one, so we need to expose our own and translate behind the scenes.
- * For 32-bit, we're stuck with the definitions we already shipped,
- * even though they contain a sigset_t that's too small. */
-#define sigaction __kernel_sigaction
-#include <linux/signal.h>
-#undef sigaction
-
 #include <sys/ucontext.h>
 #define __BIONIC_HAVE_UCONTEXT_T
 
 __BEGIN_DECLS
 
-typedef int sig_atomic_t;
-
-/* The arm and x86 kernel header files don't define _NSIG. */
-#ifndef _KERNEL__NSIG
-#define _KERNEL__NSIG 64
-#endif
-
-/* Userspace's NSIG is the kernel's _NSIG + 1. */
-#define _NSIG (_KERNEL__NSIG + 1)
-#define NSIG _NSIG
-
 /* The kernel headers define SIG_DFL (0) and SIG_IGN (1) but not SIG_HOLD, since
  * SIG_HOLD is only used by the deprecated SysV signal API.
  */
@@ -75,67 +57,37 @@
 extern const char* const sys_siglist[_NSIG];
 extern const char* const sys_signame[_NSIG]; /* BSD compatibility. */
 
-typedef __sighandler_t sig_t; /* BSD compatibility. */
-typedef __sighandler_t sighandler_t; /* glibc compatibility. */
-
 #define si_timerid si_tid /* glibc compatibility. */
 
-#if defined(__LP64__)
-
-struct sigaction {
-  int sa_flags;
-  union {
-    sighandler_t sa_handler;
-    void (*sa_sigaction)(int, struct siginfo*, void*);
-  };
-  sigset_t sa_mask;
-  void (*sa_restorer)(void);
-};
-
-#elif defined(__mips__)
-
-struct sigaction {
-  int sa_flags;
-  union {
-    sighandler_t sa_handler;
-    void (*sa_sigaction) (int, struct siginfo*, void*);
-  };
-  sigset_t sa_mask;
-};
-
-#else
-
-struct sigaction {
-  union {
-    sighandler_t _sa_handler;
-    void (*_sa_sigaction)(int, struct siginfo*, void*);
-  } _u;
-  sigset_t sa_mask;
-  int sa_flags;
-  void (*sa_restorer)(void);
-};
-
-#endif
-
 int sigaction(int __signal, const struct sigaction* __new_action, struct sigaction* __old_action);
+int sigaction64(int __signal, const struct sigaction64* __new_action, struct sigaction64* __old_action) __INTRODUCED_IN(28);
 
 int siginterrupt(int __signal, int __flag);
 
 #if __ANDROID_API__ >= __ANDROID_API_L__
 sighandler_t signal(int __signal, sighandler_t __handler) __INTRODUCED_IN(21);
 int sigaddset(sigset_t* __set, int __signal) __INTRODUCED_IN(21);
+int sigaddset64(sigset64_t* __set, int __signal) __INTRODUCED_IN(28);
 int sigdelset(sigset_t* __set, int __signal) __INTRODUCED_IN(21);
+int sigdelset64(sigset64_t* __set, int __signal) __INTRODUCED_IN(28);
 int sigemptyset(sigset_t* __set) __INTRODUCED_IN(21);
+int sigemptyset64(sigset64_t* __set) __INTRODUCED_IN(28);
 int sigfillset(sigset_t* __set) __INTRODUCED_IN(21);
+int sigfillset64(sigset64_t* __set) __INTRODUCED_IN(28);
 int sigismember(const sigset_t* __set, int __signal) __INTRODUCED_IN(21);
+int sigismember64(const sigset64_t* __set, int __signal) __INTRODUCED_IN(28);
 #else
 // Implemented as static inlines before 21.
 #endif
 
 int sigpending(sigset_t* __set);
+int sigpending64(sigset64_t* __set) __INTRODUCED_IN(28);
 int sigprocmask(int __how, const sigset_t* __new_set, sigset_t* __old_set);
+int sigprocmask64(int __how, const sigset64_t* __new_set, sigset64_t* __old_set) __INTRODUCED_IN(28);
 int sigsuspend(const sigset_t* __mask);
+int sigsuspend64(const sigset64_t* __mask) __INTRODUCED_IN(28);
 int sigwait(const sigset_t* __set, int* __signal);
+int sigwait64(const sigset64_t* __set, int* __signal) __INTRODUCED_IN(28);
 
 int sighold(int __signal)
   __attribute__((deprecated("use sigprocmask() or pthread_sigmask() instead")))
@@ -162,13 +114,16 @@
 
 int pthread_kill(pthread_t __pthread, int __signal);
 int pthread_sigmask(int __how, const sigset_t* __new_set, sigset_t* __old_set);
+int pthread_sigmask64(int __how, const sigset64_t* __new_set, sigset64_t* __old_set) __INTRODUCED_IN(28);
 
 int sigqueue(pid_t __pid, int __signal, const union sigval __value) __INTRODUCED_IN(23);
 int sigtimedwait(const sigset_t* __set, siginfo_t* __info, const struct timespec* __timeout) __INTRODUCED_IN(23);
+int sigtimedwait64(const sigset64_t* __set, siginfo_t* __info, const struct timespec* __timeout) __INTRODUCED_IN(28);
 int sigwaitinfo(const sigset_t* __set, siginfo_t* __info) __INTRODUCED_IN(23);
+int sigwaitinfo64(const sigset64_t* __set, siginfo_t* __info) __INTRODUCED_IN(28);
 
 __END_DECLS
 
 #include <android/legacy_signal_inlines.h>
 
-#endif /* _SIGNAL_H_ */
+#endif
diff --git a/libc/include/spawn.h b/libc/include/spawn.h
index ea4bb19..2e239bf 100644
--- a/libc/include/spawn.h
+++ b/libc/include/spawn.h
@@ -50,36 +50,40 @@
 typedef struct __posix_spawnattr* posix_spawnattr_t;
 typedef struct __posix_spawn_file_actions* posix_spawn_file_actions_t;
 
-int posix_spawn(pid_t* __pid, const char* __path, const posix_spawn_file_actions_t* __actions, const posix_spawnattr_t* __attr, char* const __argv[], char* const __env[]) __INTRODUCED_IN_FUTURE;
-int posix_spawnp(pid_t* __pid, const char* __file, const posix_spawn_file_actions_t* __actions, const posix_spawnattr_t* __attr, char* const __argv[], char* const __env[]) __INTRODUCED_IN_FUTURE;
+int posix_spawn(pid_t* __pid, const char* __path, const posix_spawn_file_actions_t* __actions, const posix_spawnattr_t* __attr, char* const __argv[], char* const __env[]) __INTRODUCED_IN(28);
+int posix_spawnp(pid_t* __pid, const char* __file, const posix_spawn_file_actions_t* __actions, const posix_spawnattr_t* __attr, char* const __argv[], char* const __env[]) __INTRODUCED_IN(28);
 
-int posix_spawnattr_init(posix_spawnattr_t* __attr) __INTRODUCED_IN_FUTURE;
-int posix_spawnattr_destroy(posix_spawnattr_t* __attr) __INTRODUCED_IN_FUTURE;
+int posix_spawnattr_init(posix_spawnattr_t* __attr) __INTRODUCED_IN(28);
+int posix_spawnattr_destroy(posix_spawnattr_t* __attr) __INTRODUCED_IN(28);
 
-int posix_spawnattr_setflags(posix_spawnattr_t* __attr, short __flags) __INTRODUCED_IN_FUTURE;
-int posix_spawnattr_getflags(const posix_spawnattr_t* __attr, short* __flags) __INTRODUCED_IN_FUTURE;
+int posix_spawnattr_setflags(posix_spawnattr_t* __attr, short __flags) __INTRODUCED_IN(28);
+int posix_spawnattr_getflags(const posix_spawnattr_t* __attr, short* __flags) __INTRODUCED_IN(28);
 
-int posix_spawnattr_setpgroup(posix_spawnattr_t* __attr, pid_t __pgroup) __INTRODUCED_IN_FUTURE;
-int posix_spawnattr_getpgroup(const posix_spawnattr_t* __attr, pid_t* __pgroup) __INTRODUCED_IN_FUTURE;
+int posix_spawnattr_setpgroup(posix_spawnattr_t* __attr, pid_t __pgroup) __INTRODUCED_IN(28);
+int posix_spawnattr_getpgroup(const posix_spawnattr_t* __attr, pid_t* __pgroup) __INTRODUCED_IN(28);
 
-int posix_spawnattr_setsigmask(posix_spawnattr_t* __attr, const sigset_t* __mask) __INTRODUCED_IN_FUTURE;
-int posix_spawnattr_getsigmask(const posix_spawnattr_t* __attr, sigset_t* __mask) __INTRODUCED_IN_FUTURE;
+int posix_spawnattr_setsigmask(posix_spawnattr_t* __attr, const sigset_t* __mask) __INTRODUCED_IN(28);
+int posix_spawnattr_setsigmask64(posix_spawnattr_t* __attr, const sigset64_t* __mask) __INTRODUCED_IN(28);
+int posix_spawnattr_getsigmask(const posix_spawnattr_t* __attr, sigset_t* __mask) __INTRODUCED_IN(28);
+int posix_spawnattr_getsigmask64(const posix_spawnattr_t* __attr, sigset64_t* __mask) __INTRODUCED_IN(28);
 
-int posix_spawnattr_setsigdefault(posix_spawnattr_t* __attr, const sigset_t* __mask) __INTRODUCED_IN_FUTURE;
-int posix_spawnattr_getsigdefault(const posix_spawnattr_t* __attr, sigset_t* __mask) __INTRODUCED_IN_FUTURE;
+int posix_spawnattr_setsigdefault(posix_spawnattr_t* __attr, const sigset_t* __mask) __INTRODUCED_IN(28);
+int posix_spawnattr_setsigdefault64(posix_spawnattr_t* __attr, const sigset64_t* __mask) __INTRODUCED_IN(28);
+int posix_spawnattr_getsigdefault(const posix_spawnattr_t* __attr, sigset_t* __mask) __INTRODUCED_IN(28);
+int posix_spawnattr_getsigdefault64(const posix_spawnattr_t* __attr, sigset64_t* __mask) __INTRODUCED_IN(28);
 
-int posix_spawnattr_setschedparam(posix_spawnattr_t* __attr, const struct sched_param* __param) __INTRODUCED_IN_FUTURE;
-int posix_spawnattr_getschedparam(const posix_spawnattr_t* __attr, struct sched_param* __param) __INTRODUCED_IN_FUTURE;
+int posix_spawnattr_setschedparam(posix_spawnattr_t* __attr, const struct sched_param* __param) __INTRODUCED_IN(28);
+int posix_spawnattr_getschedparam(const posix_spawnattr_t* __attr, struct sched_param* __param) __INTRODUCED_IN(28);
 
-int posix_spawnattr_setschedpolicy(posix_spawnattr_t* __attr, int __policy) __INTRODUCED_IN_FUTURE;
-int posix_spawnattr_getschedpolicy(const posix_spawnattr_t* __attr, int* __policy) __INTRODUCED_IN_FUTURE;
+int posix_spawnattr_setschedpolicy(posix_spawnattr_t* __attr, int __policy) __INTRODUCED_IN(28);
+int posix_spawnattr_getschedpolicy(const posix_spawnattr_t* __attr, int* __policy) __INTRODUCED_IN(28);
 
-int posix_spawn_file_actions_init(posix_spawn_file_actions_t* __actions) __INTRODUCED_IN_FUTURE;
-int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t* __actions) __INTRODUCED_IN_FUTURE;
+int posix_spawn_file_actions_init(posix_spawn_file_actions_t* __actions) __INTRODUCED_IN(28);
+int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t* __actions) __INTRODUCED_IN(28);
 
-int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t* __actions, int __fd, const char* __path, int __flags, mode_t __mode) __INTRODUCED_IN_FUTURE;
-int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t* __actions, int __fd) __INTRODUCED_IN_FUTURE;
-int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t* __actions, int __fd, int __new_fd) __INTRODUCED_IN_FUTURE;
+int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t* __actions, int __fd, const char* __path, int __flags, mode_t __mode) __INTRODUCED_IN(28);
+int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t* __actions, int __fd) __INTRODUCED_IN(28);
+int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t* __actions, int __fd, int __new_fd) __INTRODUCED_IN(28);
 
 __END_DECLS
 
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index e02a371..8bd690f 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -109,13 +109,13 @@
 int ferror(FILE* __fp);
 int fflush(FILE* __fp);
 int fgetc(FILE* __fp);
-char* fgets(char* __buf, int __size, FILE* __fp) __overloadable __RENAME_CLANG(fgets);
+char* fgets(char* __buf, int __size, FILE* __fp);
 int fprintf(FILE* __fp , const char* __fmt, ...) __printflike(2, 3);
 int fputc(int __ch, FILE* __fp);
 int fputs(const char* __s, FILE* __fp);
-size_t fread(void* __buf, size_t __size, size_t __count, FILE* __fp) __overloadable __RENAME_CLANG(fread);
+size_t fread(void* __buf, size_t __size, size_t __count, FILE* __fp);
 int fscanf(FILE* __fp, const char* __fmt, ...) __scanflike(2, 3);
-size_t fwrite(const void* __buf, size_t __size, size_t __count, FILE* __fp) __overloadable __RENAME_CLANG(fwrite);
+size_t fwrite(const void* __buf, size_t __size, size_t __count, FILE* __fp);
 int getc(FILE* __fp);
 int getchar(void);
 ssize_t getdelim(char** __line_ptr, size_t* __line_length_ptr, int __delimiter, FILE* __fp) __INTRODUCED_IN(18);
@@ -156,11 +156,9 @@
 char* gets(char* __buf) __attribute__((deprecated("gets is unsafe, use fgets instead")));
 #endif
 int sprintf(char* __s, const char* __fmt, ...)
-    __printflike(2, 3) __warnattr_strict("sprintf is often misused; please use snprintf")
-    __overloadable __RENAME_CLANG(sprintf);
+    __printflike(2, 3) __warnattr_strict("sprintf is often misused; please use snprintf");
 int vsprintf(char* __s, const char* __fmt, va_list __args)
-    __overloadable __printflike(2, 0) __RENAME_CLANG(vsprintf)
-    __warnattr_strict("vsprintf is often misused; please use vsnprintf");
+    __printflike(2, 0) __warnattr_strict("vsprintf is often misused; please use vsnprintf");
 char* tmpnam(char* __s)
     __warnattr("tempnam is unsafe, use mkstemp or tmpfile instead");
 #define P_tmpdir "/tmp/" /* deprecated */
@@ -218,12 +216,10 @@
 FILE* tmpfile(void);
 FILE* tmpfile64(void) __INTRODUCED_IN(24);
 
-int snprintf(char* __buf, size_t __size, const char* __fmt, ...)
-    __printflike(3, 4) __overloadable __RENAME_CLANG(snprintf);
+int snprintf(char* __buf, size_t __size, const char* __fmt, ...) __printflike(3, 4);
 int vfscanf(FILE* __fp, const char* __fmt, va_list __args) __scanflike(2, 0);
 int vscanf(const char* __fmt , va_list __args) __scanflike(1, 0);
-int vsnprintf(char* __buf, size_t __size, const char* __fmt, va_list __args)
-    __printflike(3, 0) __overloadable __RENAME_CLANG(vsnprintf);
+int vsnprintf(char* __buf, size_t __size, const char* __fmt, va_list __args) __printflike(3, 0);
 int vsscanf(const char* __s, const char* __fmt, va_list __args) __scanflike(2, 0);
 
 #define L_ctermid 1024 /* size for ctermid() */
@@ -260,16 +256,16 @@
 #endif
 
 #if defined(__USE_BSD)
-int fflush_unlocked(FILE* __fp) __INTRODUCED_IN_FUTURE;
-int fgetc_unlocked(FILE* __fp) __INTRODUCED_IN_FUTURE;
-int fputc_unlocked(int __ch, FILE* __fp) __INTRODUCED_IN_FUTURE;
-size_t fread_unlocked(void* __buf, size_t __size, size_t __count, FILE* __fp) __INTRODUCED_IN_FUTURE;
-size_t fwrite_unlocked(const void* __buf, size_t __size, size_t __count, FILE* __fp) __INTRODUCED_IN_FUTURE;
+int fflush_unlocked(FILE* __fp) __INTRODUCED_IN(28);
+int fgetc_unlocked(FILE* __fp) __INTRODUCED_IN(28);
+int fputc_unlocked(int __ch, FILE* __fp) __INTRODUCED_IN(28);
+size_t fread_unlocked(void* __buf, size_t __size, size_t __count, FILE* __fp) __INTRODUCED_IN(28);
+size_t fwrite_unlocked(const void* __buf, size_t __size, size_t __count, FILE* __fp) __INTRODUCED_IN(28);
 #endif
 
 #if defined(__USE_GNU)
-int fputs_unlocked(const char* __s, FILE* __fp) __INTRODUCED_IN_FUTURE;
-char* fgets_unlocked(char* __buf, int __size, FILE* __fp) __INTRODUCED_IN_FUTURE;
+int fputs_unlocked(const char* __s, FILE* __fp) __INTRODUCED_IN(28);
+char* fgets_unlocked(char* __buf, int __size, FILE* __fp) __INTRODUCED_IN(28);
 #endif
 
 #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
diff --git a/libc/include/stdio_ext.h b/libc/include/stdio_ext.h
index 66a3ab9..b8aa68d 100644
--- a/libc/include/stdio_ext.h
+++ b/libc/include/stdio_ext.h
@@ -37,14 +37,16 @@
 
 size_t __fbufsize(FILE* __fp) __INTRODUCED_IN(23);
 int __freadable(FILE* __fp) __INTRODUCED_IN(23);
-int __freading(FILE* __fp) __INTRODUCED_IN_FUTURE;
+int __freading(FILE* __fp) __INTRODUCED_IN(28);
 int __fwritable(FILE* __fp) __INTRODUCED_IN(23);
-int __fwriting(FILE* __fp) __INTRODUCED_IN_FUTURE;
+int __fwriting(FILE* __fp) __INTRODUCED_IN(28);
 int __flbf(FILE* __fp) __INTRODUCED_IN(23);
 void __fpurge(FILE* __fp) __INTRODUCED_IN(23);
 size_t __fpending(FILE* __fp) __INTRODUCED_IN(23);
 void _flushlbf(void) __INTRODUCED_IN(23);
 
+void __fseterr(FILE* __fp) __INTRODUCED_IN(28);
+
 #define FSETLOCKING_QUERY 0
 #define FSETLOCKING_INTERNAL 1
 #define FSETLOCKING_BYCALLER 2
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 944d72b..ef97538 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -79,6 +79,8 @@
 
 int posix_memalign(void** __memptr, size_t __alignment, size_t __size) __INTRODUCED_IN(16);
 
+void* aligned_alloc(size_t __alignment, size_t __size) __INTRODUCED_IN(28);
+
 double strtod(const char* __s, char** __end_ptr);
 long double strtold(const char* __s, char** __end_ptr) __RENAME_LDBL(strtod, 3, 21);
 
diff --git a/libc/include/string.h b/libc/include/string.h
index 226566c..54d5e1c 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -42,24 +42,23 @@
 #endif
 
 void* memccpy(void* __dst, const void* __src, int __stop_char, size_t __n);
-void* memchr(const void* __s, int __ch, size_t __n) __attribute_pure__ __overloadable __RENAME_CLANG(memchr);
+void* memchr(const void* __s, int __ch, size_t __n) __attribute_pure__;
 #if defined(__cplusplus)
 extern "C++" void* memrchr(void* __s, int __ch, size_t __n) __RENAME(memrchr) __attribute_pure__;
 extern "C++" const void* memrchr(const void* __s, int __ch, size_t __n) __RENAME(memrchr) __attribute_pure__;
 #else
-void* memrchr(const void* __s, int __ch, size_t __n) __attribute_pure__ __overloadable __RENAME_CLANG(memrchr);
+void* memrchr(const void* __s, int __ch, size_t __n) __attribute_pure__;
 #endif
 int memcmp(const void* __lhs, const void* __rhs, size_t __n) __attribute_pure__;
-void* memcpy(void*, const void*, size_t)
-        __overloadable __RENAME_CLANG(memcpy);
+void* memcpy(void*, const void*, size_t);
 #if defined(__USE_GNU)
 void* mempcpy(void* __dst, const void* __src, size_t __n) __INTRODUCED_IN(23);
 #endif
-void* memmove(void* __dst, const void* __src, size_t __n) __overloadable __RENAME_CLANG(memmove);
-void* memset(void* __dst, int __ch, size_t __n) __overloadable __RENAME_CLANG(memset);
+void* memmove(void* __dst, const void* __src, size_t __n);
+void* memset(void* __dst, int __ch, size_t __n);
 void* memmem(const void* __haystack, size_t __haystack_size, const void* __needle, size_t __needle_size) __attribute_pure__;
 
-char* strchr(const char* __s, int __ch) __attribute_pure__ __overloadable __RENAME_CLANG(strchr);
+char* strchr(const char* __s, int __ch) __attribute_pure__;
 char* __strchr_chk(const char* __s, int __ch, size_t __n) __INTRODUCED_IN(18);
 #if defined(__USE_GNU)
 #if defined(__cplusplus)
@@ -70,16 +69,16 @@
 #endif
 #endif
 
-char* strrchr(const char* __s, int __ch) __attribute_pure__ __overloadable __RENAME_CLANG(strrchr);
+char* strrchr(const char* __s, int __ch) __attribute_pure__;
 char* __strrchr_chk(const char* __s, int __ch, size_t __n) __INTRODUCED_IN(18);
 
-size_t strlen(const char* __s) __attribute_pure__ __overloadable __RENAME_CLANG(strlen);
+size_t strlen(const char* __s) __attribute_pure__;
 size_t __strlen_chk(const char* __s, size_t __n) __INTRODUCED_IN(17);
 
 int strcmp(const char* __lhs, const char* __rhs) __attribute_pure__;
-char* stpcpy(char* __dst, const char* __src) __overloadable __RENAME_CLANG(stpcpy) __INTRODUCED_IN(21);
-char* strcpy(char* __dst, const char* __src) __overloadable __RENAME_CLANG(strcpy);
-char* strcat(char* __dst, const char* __src) __overloadable __RENAME_CLANG(strcat);
+char* stpcpy(char* __dst, const char* __src) __INTRODUCED_IN(21);
+char* strcpy(char* __dst, const char* __src);
+char* strcat(char* __dst, const char* __src);
 char* strdup(const char* __s);
 
 char* strstr(const char* __haystack, const char* __needle) __attribute_pure__;
@@ -101,14 +100,14 @@
 #endif
 
 size_t strnlen(const char* __s, size_t __n) __attribute_pure__;
-char* strncat(char* __dst, const char* __src, size_t __n) __overloadable __RENAME_CLANG(strncat);
+char* strncat(char* __dst, const char* __src, size_t __n);
 char* strndup(const char* __s, size_t __n);
 int strncmp(const char* __lhs, const char* __rhs, size_t __n) __attribute_pure__;
-char* stpncpy(char* __dst, const char* __src, size_t __n) __overloadable __RENAME_CLANG(stpncpy) __INTRODUCED_IN(21);
-char* strncpy(char* __dst, const char* __src, size_t __n) __overloadable __RENAME_CLANG(strncpy);
+char* stpncpy(char* __dst, const char* __src, size_t __n) __INTRODUCED_IN(21);
+char* strncpy(char* __dst, const char* __src, size_t __n);
 
-size_t strlcat(char* __dst, const char* __src, size_t __n) __overloadable __RENAME_CLANG(strlcat);
-size_t strlcpy(char* __dst, const char* __src, size_t __n) __overloadable __RENAME_CLANG(strlcpy);
+size_t strlcat(char* __dst, const char* __src, size_t __n);
+size_t strlcpy(char* __dst, const char* __src, size_t __n);
 
 size_t strcspn(const char* __s, const char* __reject) __attribute_pure__;
 char* strpbrk(const char* __s, const char* __accept) __attribute_pure__;
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index be07007..c270bb5 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -120,6 +120,7 @@
 
 #define __printflike(x, y) __attribute__((__format__(printf, x, y)))
 #define __scanflike(x, y) __attribute__((__format__(scanf, x, y)))
+#define __strftimelike(x) __attribute__((__format__(strftime, x, 0)))
 
 /*
  * GNU C version 2.96 added explicit branch prediction so that
@@ -245,6 +246,16 @@
 #define __RENAME_LDBL(rewrite,rewrite_api_level,regular_api_level) __RENAME(rewrite) __INTRODUCED_IN(rewrite_api_level)
 #endif
 
+/*
+ * On all architectures, `struct stat` == `struct stat64`, but LP32 didn't gain the *64 functions
+ * until API level 21.
+ */
+#if defined(__LP64__) || defined(__BIONIC_LP32_USE_STAT64)
+#define __RENAME_STAT64(rewrite,rewrite_api_level,regular_api_level) __INTRODUCED_IN(regular_api_level)
+#else
+#define __RENAME_STAT64(rewrite,rewrite_api_level,regular_api_level) __RENAME(rewrite) __INTRODUCED_IN(rewrite_api_level)
+#endif
+
 /* glibc compatibility. */
 #if defined(__LP64__)
 #define __WORDSIZE 64
@@ -348,11 +359,8 @@
  */
 #if defined(__clang__) && defined(__BIONIC_FORTIFY)
 #  define __overloadable __attribute__((overloadable))
-/* We don't use __RENAME directly because on gcc this could result in unnecessary renames. */
-#  define __RENAME_CLANG(x) __RENAME(x)
 #else
 #  define __overloadable
-#  define __RENAME_CLANG(x)
 #endif
 
 /* Used to tag non-static symbols that are private and never exposed by the shared library. */
diff --git a/libc/include/sys/epoll.h b/libc/include/sys/epoll.h
index 2bc16f5..a213a90 100644
--- a/libc/include/sys/epoll.h
+++ b/libc/include/sys/epoll.h
@@ -58,6 +58,7 @@
 int epoll_ctl(int __epoll_fd, int __op, int __fd, struct epoll_event* __event);
 int epoll_wait(int __epoll_fd, struct epoll_event* __events, int __event_count, int __timeout_ms);
 int epoll_pwait(int __epoll_fd, struct epoll_event* __events, int __event_count, int __timeout_ms, const sigset_t* __mask) __INTRODUCED_IN(21);
+int epoll_pwait64(int __epoll_fd, struct epoll_event* __events, int __event_count, int __timeout_ms, const sigset64_t* __mask) __INTRODUCED_IN(28);
 
 __END_DECLS
 
diff --git a/libc/include/sys/random.h b/libc/include/sys/random.h
index 3475652..4b849f3 100644
--- a/libc/include/sys/random.h
+++ b/libc/include/sys/random.h
@@ -38,9 +38,9 @@
 
 /* See also arc4random_buf in <stdlib.h>, which is available in all API levels. */
 
-int getentropy(void* __buffer, size_t __buffer_size) __wur __INTRODUCED_IN_FUTURE;
+int getentropy(void* __buffer, size_t __buffer_size) __wur __INTRODUCED_IN(28);
 
-ssize_t getrandom(void* __buffer, size_t __buffer_size, unsigned int __flags) __wur __INTRODUCED_IN_FUTURE;
+ssize_t getrandom(void* __buffer, size_t __buffer_size, unsigned int __flags) __wur __INTRODUCED_IN(28);
 
 __END_DECLS
 
diff --git a/libc/include/sys/select.h b/libc/include/sys/select.h
index ac51d3f..603a5a6 100644
--- a/libc/include/sys/select.h
+++ b/libc/include/sys/select.h
@@ -75,6 +75,7 @@
 
 int select(int __fd_count, fd_set* __read_fds, fd_set* __write_fds, fd_set* __exception_fds, struct timeval* __timeout);
 int pselect(int __fd_count, fd_set* __read_fds, fd_set* __write_fds, fd_set* __exception_fds, const struct timespec* __timeout, const sigset_t* __mask);
+int pselect64(int __fd_count, fd_set* __read_fds, fd_set* __write_fds, fd_set* __exception_fds, const struct timespec* __timeout, const sigset64_t* __mask);
 
 __END_DECLS
 
diff --git a/libc/include/sys/signalfd.h b/libc/include/sys/signalfd.h
index 315622c..2337cd7 100644
--- a/libc/include/sys/signalfd.h
+++ b/libc/include/sys/signalfd.h
@@ -37,6 +37,7 @@
 __BEGIN_DECLS
 
 int signalfd(int __fd, const sigset_t* __mask, int __flags) __INTRODUCED_IN(18);
+int signalfd64(int __fd, const sigset64_t* __mask, int __flags) __INTRODUCED_IN(28);
 
 __END_DECLS
 
diff --git a/libc/include/sys/socket.h b/libc/include/sys/socket.h
index 152f39d..bbde88b 100644
--- a/libc/include/sys/socket.h
+++ b/libc/include/sys/socket.h
@@ -315,12 +315,11 @@
 __socketcall int socket(int __af, int __type, int __protocol);
 __socketcall int socketpair(int __af, int __type, int __protocol, int __fds[2]);
 
-ssize_t recv(int __fd, void* __buf, size_t __n, int __flags) __overloadable __RENAME_CLANG(recv);
-ssize_t send(int __fd, const void* __buf, size_t __n, int __flags) __overloadable __RENAME_CLANG(send);
+ssize_t recv(int __fd, void* __buf, size_t __n, int __flags);
+ssize_t send(int __fd, const void* __buf, size_t __n, int __flags);
 
-__socketcall ssize_t sendto(int __fd, const void* __buf, size_t __n, int __flags, const struct sockaddr* __dst_addr, socklen_t __dst_addr_length)
-        __overloadable __RENAME_CLANG(sendto);
-__socketcall ssize_t recvfrom(int __fd, void* __buf, size_t __n, int __flags, struct sockaddr* __src_addr, socklen_t* __src_addr_length) __overloadable __RENAME_CLANG(recvfrom);
+__socketcall ssize_t sendto(int __fd, const void* __buf, size_t __n, int __flags, const struct sockaddr* __dst_addr, socklen_t __dst_addr_length);
+__socketcall ssize_t recvfrom(int __fd, void* __buf, size_t __n, int __flags, struct sockaddr* __src_addr, socklen_t* __src_addr_length);
 
 #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
 #include <bits/fortify/socket.h>
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index 14b5224..84a5015 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -156,16 +156,16 @@
 int mkdir(const char* __path, mode_t __mode);
 
 int fstat(int __fd, struct stat* __buf);
-int fstat64(int __fd, struct stat64* __buf) __INTRODUCED_IN(21);
+int fstat64(int __fd, struct stat64* __buf) __RENAME_STAT64(fstat, 3, 21);
 int fstatat(int __dir_fd, const char* __path, struct stat* __buf, int __flags);
-int fstatat64(int __dir_fd, const char* __path, struct stat64* __buf, int __flags) __INTRODUCED_IN(21);
+int fstatat64(int __dir_fd, const char* __path, struct stat64* __buf, int __flags) __RENAME_STAT64(fstatat, 3, 21);
 int lstat(const char* __path, struct stat* __buf);
-int lstat64(const char* __path, struct stat64* __buf) __INTRODUCED_IN(21);
+int lstat64(const char* __path, struct stat64* __buf) __RENAME_STAT64(lstat, 3, 21);
 int stat(const char* __path, struct stat* __buf);
-int stat64(const char* __path, struct stat64* __buf) __INTRODUCED_IN(21);
+int stat64(const char* __path, struct stat64* __buf) __RENAME_STAT64(stat, 3, 21);
 
 int mknod(const char* __path, mode_t __mode, dev_t __dev);
-mode_t umask(mode_t __mask) __overloadable __RENAME_CLANG(umask);
+mode_t umask(mode_t __mask);
 
 #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
 #include <bits/fortify/stat.h>
diff --git a/libc/include/sys/ucontext.h b/libc/include/sys/ucontext.h
index 4cc66eb..730ac69 100644
--- a/libc/include/sys/ucontext.h
+++ b/libc/include/sys/ucontext.h
@@ -87,9 +87,14 @@
   struct ucontext* uc_link;
   stack_t uc_stack;
   mcontext_t uc_mcontext;
-  sigset_t uc_sigmask;
-  /* Android has a wrong (smaller) sigset_t on ARM. */
-  uint32_t __padding_rt_sigset;
+  union {
+    struct {
+      sigset_t uc_sigmask;
+      /* Android has a wrong (smaller) sigset_t on ARM. */
+      uint32_t __padding_rt_sigset;
+    };
+    sigset64_t uc_sigmask64;
+  };
   /* The kernel adds extra padding after uc_sigmask to match glibc sigset_t on ARM. */
   char __padding[120];
   unsigned long uc_regspace[128] __attribute__((__aligned__(8)));
@@ -109,7 +114,10 @@
   unsigned long uc_flags;
   struct ucontext *uc_link;
   stack_t uc_stack;
-  sigset_t uc_sigmask;
+  union {
+    sigset_t uc_sigmask;
+    sigset64_t uc_sigmask64;
+  };
   /* The kernel adds extra padding after uc_sigmask to match glibc sigset_t on ARM64. */
   char __padding[128 - sizeof(sigset_t)];
   mcontext_t uc_mcontext;
@@ -194,9 +202,14 @@
   struct ucontext* uc_link;
   stack_t uc_stack;
   mcontext_t uc_mcontext;
-  sigset_t uc_sigmask;
-  /* Android has a wrong (smaller) sigset_t on x86. */
-  uint32_t __padding_rt_sigset;
+  union {
+    struct {
+      sigset_t uc_sigmask;
+      /* Android has a wrong (smaller) sigset_t on x86. */
+      uint32_t __padding_rt_sigset;
+    };
+    sigset64_t uc_sigmask64;
+  };
   struct _libc_fpstate __fpregs_mem;
 } ucontext_t;
 
@@ -266,7 +279,10 @@
   struct ucontext* uc_link;
   stack_t uc_stack;
   mcontext_t uc_mcontext;
-  sigset_t uc_sigmask;
+  union {
+    sigset_t uc_sigmask;
+    sigset64_t uc_sigmask64;
+  };
 } ucontext_t;
 
 #elif defined(__x86_64__)
@@ -362,7 +378,10 @@
   struct ucontext* uc_link;
   stack_t uc_stack;
   mcontext_t uc_mcontext;
-  sigset_t uc_sigmask;
+  union {
+    sigset_t uc_sigmask;
+    sigset64_t uc_sigmask64;
+  };
   struct _libc_fpstate __fpregs_mem;
 } ucontext_t;
 
diff --git a/libc/include/time.h b/libc/include/time.h
index 8e78949..17751d7 100644
--- a/libc/include/time.h
+++ b/libc/include/time.h
@@ -74,11 +74,12 @@
 struct tm* gmtime(const time_t* __t);
 struct tm* gmtime_r(const time_t* __t, struct tm* __tm);
 
-char* strptime(const char* __s, const char* __fmt, struct tm* __tm);
-size_t strftime(char* __buf, size_t __n, const char* __fmt, const struct tm* __tm);
+char* strptime(const char* __s, const char* __fmt, struct tm* __tm) __strftimelike(2);
+char* strptime_l(const char* __s, const char* __fmt, struct tm* __tm, locale_t __l) __strftimelike(2) __INTRODUCED_IN(28);
 
+size_t strftime(char* __buf, size_t __n, const char* __fmt, const struct tm* __tm) __strftimelike(3);
 #if __ANDROID_API__ >= __ANDROID_API_L__
-size_t strftime_l(char* __buf, size_t __n, const char* __fmt, const struct tm* __tm, locale_t __l) __INTRODUCED_IN(21);
+size_t strftime_l(char* __buf, size_t __n, const char* __fmt, const struct tm* __tm, locale_t __l) __strftimelike(3) __INTRODUCED_IN(21);
 #else
 // Implemented as static inline before 21.
 #endif
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index ef75c84..e0f8b43 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -98,7 +98,7 @@
 int execlp(const char* __file, const char* __arg0, ...) __attribute__((__sentinel__));
 int execle(const char* __path, const char* __arg0, ... /*,  char* const* __envp */)
     __attribute__((__sentinel__(1)));
-int fexecve(int __fd, char* const* __argv, char* const* __envp) __INTRODUCED_IN_FUTURE;
+int fexecve(int __fd, char* const* __argv, char* const* __envp) __INTRODUCED_IN(28);
 
 int nice(int __incr);
 
@@ -119,7 +119,7 @@
 int getresuid(uid_t* __ruid, uid_t* __euid, uid_t* __suid);
 int getresgid(gid_t* __rgid, gid_t* __egid, gid_t* __sgid);
 char* getlogin(void);
-int getlogin_r(char* __buffer, size_t __buffer_size) __INTRODUCED_IN_FUTURE;
+int getlogin_r(char* __buffer, size_t __buffer_size) __INTRODUCED_IN(28);
 
 long fpathconf(int __fd, int __name);
 long pathconf(const char* __path, int __name);
@@ -140,27 +140,24 @@
 int chroot(const char* __path);
 int symlink(const char* __old_path, const char* __new_path);
 int symlinkat(const char* __old_path, int __new_dir_fd, const char* __new_path) __INTRODUCED_IN(21);
-ssize_t readlink(const char* __path, char* __buf, size_t __buf_size)
-    __overloadable __RENAME_CLANG(readlink);
+ssize_t readlink(const char* __path, char* __buf, size_t __buf_size);
 ssize_t readlinkat(int __dir_fd, const char* __path, char* __buf, size_t __buf_size)
-    __INTRODUCED_IN(21) __overloadable __RENAME_CLANG(readlinkat);
+    __INTRODUCED_IN(21);
 int chown(const char* __path, uid_t __owner, gid_t __group);
 int fchown(int __fd, uid_t __owner, gid_t __group);
 int fchownat(int __dir_fd, const char* __path, uid_t __owner, gid_t __group, int __flags);
 int lchown(const char* __path, uid_t __owner, gid_t __group);
-char* getcwd(char* __buf, size_t __size) __overloadable __RENAME_CLANG(getcwd);
+char* getcwd(char* __buf, size_t __size);
 
 void sync(void);
 #if defined(__USE_GNU)
-int syncfs(int __fd) __INTRODUCED_IN_FUTURE;
+int syncfs(int __fd) __INTRODUCED_IN(28);
 #endif
 
 int close(int __fd);
 
-ssize_t read(int __fd, void* __buf, size_t __count) __overloadable
-    __RENAME_CLANG(read);
-ssize_t write(int __fd, const void* __buf, size_t __count) __overloadable
-    __RENAME_CLANG(write);
+ssize_t read(int __fd, void* __buf, size_t __count);
+ssize_t write(int __fd, const void* __buf, size_t __count);
 
 int dup(int __old_fd);
 int dup2(int __old_fd, int __new_fd);
@@ -173,26 +170,22 @@
 int truncate(const char* __path, off_t __length) __RENAME(truncate64) __INTRODUCED_IN(21);
 off_t lseek(int __fd, off_t __offset, int __whence) __RENAME(lseek64);
 ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset)
-  __overloadable __RENAME(pread64) __INTRODUCED_IN(12);
+  __RENAME(pread64) __INTRODUCED_IN(12);
 ssize_t pwrite(int __fd, const void* __buf, size_t __count, off_t __offset)
-  __overloadable __RENAME(pwrite64) __INTRODUCED_IN(12);
+  __RENAME(pwrite64) __INTRODUCED_IN(12);
 int ftruncate(int __fd, off_t __length) __RENAME(ftruncate64) __INTRODUCED_IN(12);
 #else
 int truncate(const char* __path, off_t __length);
 off_t lseek(int __fd, off_t __offset, int __whence);
-ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset)
-    __overloadable __RENAME_CLANG(pread);
-ssize_t pwrite(int __fd, const void* __buf, size_t __count, off_t __offset)
-    __overloadable __RENAME_CLANG(pwrite);
+ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset);
+ssize_t pwrite(int __fd, const void* __buf, size_t __count, off_t __offset);
 int ftruncate(int __fd, off_t __length);
 #endif
 
 int truncate64(const char* __path, off64_t __length) __INTRODUCED_IN(21);
 off64_t lseek64(int __fd, off64_t __offset, int __whence);
-ssize_t pread64(int __fd, void* __buf, size_t __count, off64_t __offset)
-    __INTRODUCED_IN(12) __overloadable __RENAME_CLANG(pread64);
-ssize_t pwrite64(int __fd, const void* __buf, size_t __count, off64_t __offset)
-    __INTRODUCED_IN(12) __overloadable __RENAME_CLANG(pwrite64);
+ssize_t pread64(int __fd, void* __buf, size_t __count, off64_t __offset) __INTRODUCED_IN(12);
+ssize_t pwrite64(int __fd, const void* __buf, size_t __count, off64_t __offset) __INTRODUCED_IN(12);
 int ftruncate64(int __fd, off64_t __length) __INTRODUCED_IN(12);
 
 int pause(void);
@@ -243,7 +236,7 @@
 int getdomainname(char* __buf, size_t __buf_size) __INTRODUCED_IN(26);
 int setdomainname(const char* __name, size_t __n) __INTRODUCED_IN(26);
 
-void swab(const void* __src, void* __dst, ssize_t __byte_count) __INTRODUCED_IN_FUTURE;
+void swab(const void* __src, void* __dst, ssize_t __byte_count) __INTRODUCED_IN(28);
 
 #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
 #include <bits/fortify/unistd.h>
@@ -251,4 +244,4 @@
 
 __END_DECLS
 
-#endif /* _UNISTD_H_ */
+#endif
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index 1cf498c83..f33af5f 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -81,6 +81,7 @@
 wchar_t* wcscpy(wchar_t* __dst, const wchar_t* __src);
 size_t wcscspn(const wchar_t* __s, const wchar_t* __accept);
 size_t wcsftime(wchar_t* __buf, size_t __n, const wchar_t* __fmt, const struct tm* __tm);
+size_t wcsftime_l(wchar_t* __buf, size_t __n, const wchar_t* __fmt, const struct tm* __tm, locale_t __l) __INTRODUCED_IN(28);
 size_t wcslen(const wchar_t* __s);
 int wcsncasecmp(const wchar_t* __lhs, const wchar_t* __rhs, size_t __n);
 int wcsncasecmp_l(const wchar_t* __lhs, const wchar_t* __rhs, size_t __n, locale_t __l) __INTRODUCED_IN(23);
@@ -94,12 +95,16 @@
 size_t wcsspn(const wchar_t* __s, const wchar_t* __accept);
 wchar_t* wcsstr(const wchar_t* __haystack, const wchar_t* __needle);
 double wcstod(const wchar_t* __s, wchar_t** __end_ptr);
+double wcstod_l(const wchar_t* __s, wchar_t** __end_ptr, locale_t __l) __INTRODUCED_IN(28);
 float wcstof(const wchar_t* __s, wchar_t** __end_ptr) __INTRODUCED_IN(21);
+float wcstof_l(const wchar_t* __s, wchar_t** __end_ptr, locale_t __l) __INTRODUCED_IN(28);
 wchar_t* wcstok(wchar_t* __s, const wchar_t* __delimiter, wchar_t** __ptr);
 long wcstol(const wchar_t* __s, wchar_t** __end_ptr, int __base);
+long wcstol_l(const wchar_t* __s, wchar_t** __end_ptr, int __base, locale_t __l) __INTRODUCED_IN(28);
 long long wcstoll(const wchar_t* __s, wchar_t** __end_ptr, int __base) __INTRODUCED_IN(21);
 long double wcstold(const wchar_t* __s, wchar_t** __end_ptr) __RENAME_LDBL(wcstod, 3, 21);
 unsigned long wcstoul(const wchar_t* __s, wchar_t** __end_ptr, int __base);
+unsigned long wcstoul_l(const wchar_t* __s, wchar_t** __end_ptr, int __base, locale_t __l) __INTRODUCED_IN(28);
 unsigned long long wcstoull(const wchar_t* __s, wchar_t** __end_ptr, int __base) __INTRODUCED_IN(21);
 int wcswidth(const wchar_t* __s, size_t __n);
 size_t wcsxfrm(wchar_t* __dst, const wchar_t* __src, size_t __n);
diff --git a/libc/kernel/android/scsi/scsi/scsi_proto.h b/libc/kernel/android/scsi/scsi/scsi_proto.h
index 7f3abd9..1b56ecb 100644
--- a/libc/kernel/android/scsi/scsi/scsi_proto.h
+++ b/libc/kernel/android/scsi/scsi/scsi_proto.h
@@ -176,17 +176,32 @@
 #define SCSI_ACCESS_STATE_MASK 0x0f
 #define SCSI_ACCESS_STATE_PREFERRED 0x80
 enum zbc_zone_reporting_options {
-  ZBC_ZONE_REPORTING_OPTION_ALL = 0,
-  ZBC_ZONE_REPORTING_OPTION_EMPTY,
-  ZBC_ZONE_REPORTING_OPTION_IMPLICIT_OPEN,
-  ZBC_ZONE_REPORTING_OPTION_EXPLICIT_OPEN,
-  ZBC_ZONE_REPORTING_OPTION_CLOSED,
-  ZBC_ZONE_REPORTING_OPTION_FULL,
-  ZBC_ZONE_REPORTING_OPTION_READONLY,
-  ZBC_ZONE_REPORTING_OPTION_OFFLINE,
+  ZBC_ZONE_REPORTING_OPTION_ALL = 0x00,
+  ZBC_ZONE_REPORTING_OPTION_EMPTY = 0x01,
+  ZBC_ZONE_REPORTING_OPTION_IMPLICIT_OPEN = 0x02,
+  ZBC_ZONE_REPORTING_OPTION_EXPLICIT_OPEN = 0x03,
+  ZBC_ZONE_REPORTING_OPTION_CLOSED = 0x04,
+  ZBC_ZONE_REPORTING_OPTION_FULL = 0x05,
+  ZBC_ZONE_REPORTING_OPTION_READONLY = 0x06,
+  ZBC_ZONE_REPORTING_OPTION_OFFLINE = 0x07,
   ZBC_ZONE_REPORTING_OPTION_NEED_RESET_WP = 0x10,
-  ZBC_ZONE_REPORTING_OPTION_NON_SEQWRITE,
+  ZBC_ZONE_REPORTING_OPTION_NON_SEQWRITE = 0x11,
   ZBC_ZONE_REPORTING_OPTION_NON_WP = 0x3f,
 };
 #define ZBC_REPORT_ZONE_PARTIAL 0x80
+enum zbc_zone_type {
+  ZBC_ZONE_TYPE_CONV = 0x1,
+  ZBC_ZONE_TYPE_SEQWRITE_REQ = 0x2,
+  ZBC_ZONE_TYPE_SEQWRITE_PREF = 0x3,
+};
+enum zbc_zone_cond {
+  ZBC_ZONE_COND_NO_WP = 0x0,
+  ZBC_ZONE_COND_EMPTY = 0x1,
+  ZBC_ZONE_COND_IMP_OPEN = 0x2,
+  ZBC_ZONE_COND_EXP_OPEN = 0x3,
+  ZBC_ZONE_COND_CLOSED = 0x4,
+  ZBC_ZONE_COND_READONLY = 0xd,
+  ZBC_ZONE_COND_FULL = 0xe,
+  ZBC_ZONE_COND_OFFLINE = 0xf,
+};
 #endif
diff --git a/libc/kernel/android/uapi/linux/compiler_types.h b/libc/kernel/android/uapi/linux/compiler_types.h
new file mode 100644
index 0000000..94f4fbe
--- /dev/null
+++ b/libc/kernel/android/uapi/linux/compiler_types.h
@@ -0,0 +1,5 @@
+/*
+ * The compiler.h file has been split into compiler.h and compiler_types.h.
+ * However, to compile bionic we only need the compiler.h.
+ */
+#include <linux/compiler.h>
diff --git a/libc/kernel/uapi/asm-arm/asm/bpf_perf_event.h b/libc/kernel/uapi/asm-arm/asm/bpf_perf_event.h
new file mode 100644
index 0000000..fa7bc48
--- /dev/null
+++ b/libc/kernel/uapi/asm-arm/asm/bpf_perf_event.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/bpf_perf_event.h>
diff --git a/libc/kernel/uapi/asm-arm/asm/kvm.h b/libc/kernel/uapi/asm-arm/asm/kvm.h
index 2332ae2..448a773 100644
--- a/libc/kernel/uapi/asm-arm/asm/kvm.h
+++ b/libc/kernel/uapi/asm-arm/asm/kvm.h
@@ -106,6 +106,9 @@
 #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)
@@ -157,6 +160,7 @@
 #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_TYPE_SHIFT 24
 #define KVM_ARM_IRQ_TYPE_MASK 0xff
 #define KVM_ARM_IRQ_VCPU_SHIFT 16
diff --git a/libc/kernel/uapi/asm-arm/asm/ptrace.h b/libc/kernel/uapi/asm-arm/asm/ptrace.h
index dcc3826..b0291dc 100644
--- a/libc/kernel/uapi/asm-arm/asm/ptrace.h
+++ b/libc/kernel/uapi/asm-arm/asm/ptrace.h
@@ -34,6 +34,9 @@
 #define PTRACE_SETVFPREGS 28
 #define PTRACE_GETHBPREGS 29
 #define PTRACE_SETHBPREGS 30
+#define PTRACE_GETFDPIC 31
+#define PTRACE_GETFDPIC_EXEC 0
+#define PTRACE_GETFDPIC_INTERP 1
 #define USR26_MODE 0x00000000
 #define FIQ26_MODE 0x00000001
 #define IRQ26_MODE 0x00000002
@@ -42,6 +45,7 @@
 #define SVC_MODE 0x00000013
 #define FIQ_MODE 0x00000011
 #define IRQ_MODE 0x00000012
+#define MON_MODE 0x00000016
 #define ABT_MODE 0x00000017
 #define HYP_MODE 0x0000001a
 #define UND_MODE 0x0000001b
diff --git a/libc/kernel/uapi/asm-arm/asm/unistd.h b/libc/kernel/uapi/asm-arm/asm/unistd.h
index d14fd73..f4b1f3a 100644
--- a/libc/kernel/uapi/asm-arm/asm/unistd.h
+++ b/libc/kernel/uapi/asm-arm/asm/unistd.h
@@ -29,4 +29,5 @@
 #define __ARM_NR_usr26 (__ARM_NR_BASE + 3)
 #define __ARM_NR_usr32 (__ARM_NR_BASE + 4)
 #define __ARM_NR_set_tls (__ARM_NR_BASE + 5)
+#define __ARM_NR_get_tls (__ARM_NR_BASE + 6)
 #endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/bpf_perf_event.h b/libc/kernel/uapi/asm-arm64/asm/bpf_perf_event.h
new file mode 100644
index 0000000..cad04bf
--- /dev/null
+++ b/libc/kernel/uapi/asm-arm64/asm/bpf_perf_event.h
@@ -0,0 +1,23 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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 _UAPI__ASM_BPF_PERF_EVENT_H__
+#define _UAPI__ASM_BPF_PERF_EVENT_H__
+#include <asm/ptrace.h>
+typedef struct user_pt_regs bpf_user_pt_regs_t;
+#endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/hwcap.h b/libc/kernel/uapi/asm-arm64/asm/hwcap.h
index 60b8305..4e95b95 100644
--- a/libc/kernel/uapi/asm-arm64/asm/hwcap.h
+++ b/libc/kernel/uapi/asm-arm64/asm/hwcap.h
@@ -35,4 +35,10 @@
 #define HWCAP_FCMA (1 << 14)
 #define HWCAP_LRCPC (1 << 15)
 #define HWCAP_DCPOP (1 << 16)
+#define HWCAP_SHA3 (1 << 17)
+#define HWCAP_SM3 (1 << 18)
+#define HWCAP_SM4 (1 << 19)
+#define HWCAP_ASIMDDP (1 << 20)
+#define HWCAP_SHA512 (1 << 21)
+#define HWCAP_SVE (1 << 22)
 #endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/kvm.h b/libc/kernel/uapi/asm-arm64/asm/kvm.h
index a68a8a2..c4178a1 100644
--- a/libc/kernel/uapi/asm-arm64/asm/kvm.h
+++ b/libc/kernel/uapi/asm-arm64/asm/kvm.h
@@ -117,6 +117,9 @@
 #define ARM64_SYS_REG_SHIFT_MASK(x,n) (((x) << KVM_REG_ARM64_SYSREG_ ##n ##_SHIFT) & KVM_REG_ARM64_SYSREG_ ##n ##_MASK)
 #define __ARM64_SYS_REG(op0,op1,crn,crm,op2) (KVM_REG_ARM64 | KVM_REG_ARM64_SYSREG | ARM64_SYS_REG_SHIFT_MASK(op0, OP0) | ARM64_SYS_REG_SHIFT_MASK(op1, OP1) | ARM64_SYS_REG_SHIFT_MASK(crn, CRN) | ARM64_SYS_REG_SHIFT_MASK(crm, CRM) | ARM64_SYS_REG_SHIFT_MASK(op2, OP2))
 #define ARM64_SYS_REG(...) (__ARM64_SYS_REG(__VA_ARGS__) | KVM_REG_SIZE_U64)
+#define KVM_REG_ARM_PTIMER_CTL ARM64_SYS_REG(3, 3, 14, 2, 1)
+#define KVM_REG_ARM_PTIMER_CVAL ARM64_SYS_REG(3, 3, 14, 2, 2)
+#define KVM_REG_ARM_PTIMER_CNT ARM64_SYS_REG(3, 3, 14, 0, 1)
 #define KVM_REG_ARM_TIMER_CTL ARM64_SYS_REG(3, 3, 14, 3, 1)
 #define KVM_REG_ARM_TIMER_CNT ARM64_SYS_REG(3, 3, 14, 3, 2)
 #define KVM_REG_ARM_TIMER_CVAL ARM64_SYS_REG(3, 3, 14, 0, 2)
@@ -144,6 +147,7 @@
 #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_VCPU_PMU_V3_CTRL 0
 #define KVM_ARM_VCPU_PMU_V3_IRQ 0
 #define KVM_ARM_VCPU_PMU_V3_INIT 1
diff --git a/libc/kernel/uapi/asm-arm64/asm/ptrace.h b/libc/kernel/uapi/asm-arm64/asm/ptrace.h
index 0eccf79..4e6c755 100644
--- a/libc/kernel/uapi/asm-arm64/asm/ptrace.h
+++ b/libc/kernel/uapi/asm-arm64/asm/ptrace.h
@@ -20,6 +20,7 @@
 #define _UAPI__ASM_PTRACE_H
 #include <linux/types.h>
 #include <asm/hwcap.h>
+#include <asm/sigcontext.h>
 #define PSR_MODE_EL0t 0x00000000
 #define PSR_MODE_EL1t 0x00000004
 #define PSR_MODE_EL1h 0x00000005
@@ -35,7 +36,6 @@
 #define PSR_D_BIT 0x00000200
 #define PSR_PAN_BIT 0x00400000
 #define PSR_UAO_BIT 0x00800000
-#define PSR_Q_BIT 0x08000000
 #define PSR_V_BIT 0x10000000
 #define PSR_C_BIT 0x20000000
 #define PSR_Z_BIT 0x40000000
@@ -45,6 +45,7 @@
 #define PSR_x 0x0000ff00
 #define PSR_c 0x000000ff
 #ifndef __ASSEMBLY__
+#include <linux/prctl.h>
 struct user_pt_regs {
   __u64 regs[31];
   __u64 sp;
@@ -66,5 +67,39 @@
     __u32 pad;
   } dbg_regs[16];
 };
+struct user_sve_header {
+  __u32 size;
+  __u32 max_size;
+  __u16 vl;
+  __u16 max_vl;
+  __u16 flags;
+  __u16 __reserved;
+};
+#define SVE_PT_REGS_MASK (1 << 0)
+#define SVE_PT_REGS_FPSIMD 0
+#define SVE_PT_REGS_SVE SVE_PT_REGS_MASK
+#define SVE_PT_VL_INHERIT (PR_SVE_VL_INHERIT >> 16)
+#define SVE_PT_VL_ONEXEC (PR_SVE_SET_VL_ONEXEC >> 16)
+#define SVE_PT_REGS_OFFSET ((sizeof(struct sve_context) + (SVE_VQ_BYTES - 1)) / SVE_VQ_BYTES * SVE_VQ_BYTES)
+#define SVE_PT_FPSIMD_OFFSET SVE_PT_REGS_OFFSET
+#define SVE_PT_FPSIMD_SIZE(vq,flags) (sizeof(struct user_fpsimd_state))
+#define SVE_PT_SVE_ZREG_SIZE(vq) SVE_SIG_ZREG_SIZE(vq)
+#define SVE_PT_SVE_PREG_SIZE(vq) SVE_SIG_PREG_SIZE(vq)
+#define SVE_PT_SVE_FFR_SIZE(vq) SVE_SIG_FFR_SIZE(vq)
+#define SVE_PT_SVE_FPSR_SIZE sizeof(__u32)
+#define SVE_PT_SVE_FPCR_SIZE sizeof(__u32)
+#define __SVE_SIG_TO_PT(offset) ((offset) - SVE_SIG_REGS_OFFSET + SVE_PT_REGS_OFFSET)
+#define SVE_PT_SVE_OFFSET SVE_PT_REGS_OFFSET
+#define SVE_PT_SVE_ZREGS_OFFSET __SVE_SIG_TO_PT(SVE_SIG_ZREGS_OFFSET)
+#define SVE_PT_SVE_ZREG_OFFSET(vq,n) __SVE_SIG_TO_PT(SVE_SIG_ZREG_OFFSET(vq, n))
+#define SVE_PT_SVE_ZREGS_SIZE(vq) (SVE_PT_SVE_ZREG_OFFSET(vq, SVE_NUM_ZREGS) - SVE_PT_SVE_ZREGS_OFFSET)
+#define SVE_PT_SVE_PREGS_OFFSET(vq) __SVE_SIG_TO_PT(SVE_SIG_PREGS_OFFSET(vq))
+#define SVE_PT_SVE_PREG_OFFSET(vq,n) __SVE_SIG_TO_PT(SVE_SIG_PREG_OFFSET(vq, n))
+#define SVE_PT_SVE_PREGS_SIZE(vq) (SVE_PT_SVE_PREG_OFFSET(vq, SVE_NUM_PREGS) - SVE_PT_SVE_PREGS_OFFSET(vq))
+#define SVE_PT_SVE_FFR_OFFSET(vq) __SVE_SIG_TO_PT(SVE_SIG_FFR_OFFSET(vq))
+#define SVE_PT_SVE_FPSR_OFFSET(vq) ((SVE_PT_SVE_FFR_OFFSET(vq) + SVE_PT_SVE_FFR_SIZE(vq) + (SVE_VQ_BYTES - 1)) / SVE_VQ_BYTES * SVE_VQ_BYTES)
+#define SVE_PT_SVE_FPCR_OFFSET(vq) (SVE_PT_SVE_FPSR_OFFSET(vq) + SVE_PT_SVE_FPSR_SIZE)
+#define SVE_PT_SVE_SIZE(vq,flags) ((SVE_PT_SVE_FPCR_OFFSET(vq) + SVE_PT_SVE_FPCR_SIZE - SVE_PT_SVE_OFFSET + (SVE_VQ_BYTES - 1)) / SVE_VQ_BYTES * SVE_VQ_BYTES)
+#define SVE_PT_SIZE(vq,flags) (((flags) & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE ? SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, flags) : SVE_PT_FPSIMD_OFFSET + SVE_PT_FPSIMD_SIZE(vq, flags))
 #endif
 #endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/sigcontext.h b/libc/kernel/uapi/asm-arm64/asm/sigcontext.h
index be2464e..b0617de 100644
--- a/libc/kernel/uapi/asm-arm64/asm/sigcontext.h
+++ b/libc/kernel/uapi/asm-arm64/asm/sigcontext.h
@@ -18,6 +18,7 @@
  ****************************************************************************/
 #ifndef _UAPI__ASM_SIGCONTEXT_H
 #define _UAPI__ASM_SIGCONTEXT_H
+#ifndef __ASSEMBLY__
 #include <linux/types.h>
 struct sigcontext {
   __u64 fault_address;
@@ -50,4 +51,34 @@
   __u32 size;
   __u32 __reserved[3];
 };
+#define SVE_MAGIC 0x53564501
+struct sve_context {
+  struct _aarch64_ctx head;
+  __u16 vl;
+  __u16 __reserved[3];
+};
+#endif
+#define SVE_VQ_BYTES 16
+#define SVE_VQ_MIN 1
+#define SVE_VQ_MAX 512
+#define SVE_VL_MIN (SVE_VQ_MIN * SVE_VQ_BYTES)
+#define SVE_VL_MAX (SVE_VQ_MAX * SVE_VQ_BYTES)
+#define SVE_NUM_ZREGS 32
+#define SVE_NUM_PREGS 16
+#define sve_vl_valid(vl) ((vl) % SVE_VQ_BYTES == 0 && (vl) >= SVE_VL_MIN && (vl) <= SVE_VL_MAX)
+#define sve_vq_from_vl(vl) ((vl) / SVE_VQ_BYTES)
+#define sve_vl_from_vq(vq) ((vq) * SVE_VQ_BYTES)
+#define SVE_SIG_ZREG_SIZE(vq) ((__u32) (vq) * SVE_VQ_BYTES)
+#define SVE_SIG_PREG_SIZE(vq) ((__u32) (vq) * (SVE_VQ_BYTES / 8))
+#define SVE_SIG_FFR_SIZE(vq) SVE_SIG_PREG_SIZE(vq)
+#define SVE_SIG_REGS_OFFSET ((sizeof(struct sve_context) + (SVE_VQ_BYTES - 1)) / SVE_VQ_BYTES * SVE_VQ_BYTES)
+#define SVE_SIG_ZREGS_OFFSET SVE_SIG_REGS_OFFSET
+#define SVE_SIG_ZREG_OFFSET(vq,n) (SVE_SIG_ZREGS_OFFSET + SVE_SIG_ZREG_SIZE(vq) * (n))
+#define SVE_SIG_ZREGS_SIZE(vq) (SVE_SIG_ZREG_OFFSET(vq, SVE_NUM_ZREGS) - SVE_SIG_ZREGS_OFFSET)
+#define SVE_SIG_PREGS_OFFSET(vq) (SVE_SIG_ZREGS_OFFSET + SVE_SIG_ZREGS_SIZE(vq))
+#define SVE_SIG_PREG_OFFSET(vq,n) (SVE_SIG_PREGS_OFFSET(vq) + SVE_SIG_PREG_SIZE(vq) * (n))
+#define SVE_SIG_PREGS_SIZE(vq) (SVE_SIG_PREG_OFFSET(vq, SVE_NUM_PREGS) - SVE_SIG_PREGS_OFFSET(vq))
+#define SVE_SIG_FFR_OFFSET(vq) (SVE_SIG_PREGS_OFFSET(vq) + SVE_SIG_PREGS_SIZE(vq))
+#define SVE_SIG_REGS_SIZE(vq) (SVE_SIG_FFR_OFFSET(vq) + SVE_SIG_FFR_SIZE(vq) - SVE_SIG_REGS_OFFSET)
+#define SVE_SIG_CONTEXT_SIZE(vq) (SVE_SIG_REGS_OFFSET + SVE_SIG_REGS_SIZE(vq))
 #endif
diff --git a/libc/kernel/uapi/asm-generic/bpf_perf_event.h b/libc/kernel/uapi/asm-generic/bpf_perf_event.h
new file mode 100644
index 0000000..794927b
--- /dev/null
+++ b/libc/kernel/uapi/asm-generic/bpf_perf_event.h
@@ -0,0 +1,23 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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 _UAPI__ASM_GENERIC_BPF_PERF_EVENT_H__
+#define _UAPI__ASM_GENERIC_BPF_PERF_EVENT_H__
+#include <linux/ptrace.h>
+typedef struct pt_regs bpf_user_pt_regs_t;
+#endif
diff --git a/libc/kernel/uapi/asm-generic/mman-common.h b/libc/kernel/uapi/asm-generic/mman-common.h
index a15624a..e752bb6 100644
--- a/libc/kernel/uapi/asm-generic/mman-common.h
+++ b/libc/kernel/uapi/asm-generic/mman-common.h
@@ -27,6 +27,7 @@
 #define PROT_GROWSUP 0x02000000
 #define MAP_SHARED 0x01
 #define MAP_PRIVATE 0x02
+#define MAP_SHARED_VALIDATE 0x03
 #define MAP_TYPE 0x0f
 #define MAP_FIXED 0x10
 #define MAP_ANONYMOUS 0x20
diff --git a/libc/kernel/uapi/asm-generic/mman.h b/libc/kernel/uapi/asm-generic/mman.h
index 0452237..84caab7 100644
--- a/libc/kernel/uapi/asm-generic/mman.h
+++ b/libc/kernel/uapi/asm-generic/mman.h
@@ -28,6 +28,7 @@
 #define MAP_NONBLOCK 0x10000
 #define MAP_STACK 0x20000
 #define MAP_HUGETLB 0x40000
+#define MAP_SYNC 0x80000
 #define MCL_CURRENT 1
 #define MCL_FUTURE 2
 #define MCL_ONFAULT 4
diff --git a/libc/kernel/uapi/asm-mips/asm/bpf_perf_event.h b/libc/kernel/uapi/asm-mips/asm/bpf_perf_event.h
new file mode 100644
index 0000000..fa7bc48
--- /dev/null
+++ b/libc/kernel/uapi/asm-mips/asm/bpf_perf_event.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/bpf_perf_event.h>
diff --git a/libc/kernel/uapi/asm-mips/asm/mman.h b/libc/kernel/uapi/asm-mips/asm/mman.h
index b976885..5e8e28a 100644
--- a/libc/kernel/uapi/asm-mips/asm/mman.h
+++ b/libc/kernel/uapi/asm-mips/asm/mman.h
@@ -27,6 +27,7 @@
 #define PROT_GROWSUP 0x02000000
 #define MAP_SHARED 0x001
 #define MAP_PRIVATE 0x002
+#define MAP_SHARED_VALIDATE 0x003
 #define MAP_TYPE 0x00f
 #define MAP_FIXED 0x010
 #define MAP_RENAME 0x020
diff --git a/libc/kernel/uapi/asm-x86/asm/bpf_perf_event.h b/libc/kernel/uapi/asm-x86/asm/bpf_perf_event.h
new file mode 100644
index 0000000..fa7bc48
--- /dev/null
+++ b/libc/kernel/uapi/asm-x86/asm/bpf_perf_event.h
@@ -0,0 +1,19 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#include <asm-generic/bpf_perf_event.h>
diff --git a/libc/kernel/uapi/asm-x86/asm/processor-flags.h b/libc/kernel/uapi/asm-x86/asm/processor-flags.h
index f0f8dd2..85f9d7e 100644
--- a/libc/kernel/uapi/asm-x86/asm/processor-flags.h
+++ b/libc/kernel/uapi/asm-x86/asm/processor-flags.h
@@ -81,7 +81,10 @@
 #define X86_CR3_PWT _BITUL(X86_CR3_PWT_BIT)
 #define X86_CR3_PCD_BIT 4
 #define X86_CR3_PCD _BITUL(X86_CR3_PCD_BIT)
-#define X86_CR3_PCID_MASK _AC(0x00000fff, UL)
+#define X86_CR3_PCID_BITS 12
+#define X86_CR3_PCID_MASK (_AC((1UL << X86_CR3_PCID_BITS) - 1, UL))
+#define X86_CR3_PCID_NOFLUSH_BIT 63
+#define X86_CR3_PCID_NOFLUSH _BITULL(X86_CR3_PCID_NOFLUSH_BIT)
 #define X86_CR4_VME_BIT 0
 #define X86_CR4_VME _BITUL(X86_CR4_VME_BIT)
 #define X86_CR4_PVI_BIT 1
@@ -104,6 +107,8 @@
 #define X86_CR4_OSFXSR _BITUL(X86_CR4_OSFXSR_BIT)
 #define X86_CR4_OSXMMEXCPT_BIT 10
 #define X86_CR4_OSXMMEXCPT _BITUL(X86_CR4_OSXMMEXCPT_BIT)
+#define X86_CR4_UMIP_BIT 11
+#define X86_CR4_UMIP _BITUL(X86_CR4_UMIP_BIT)
 #define X86_CR4_LA57_BIT 12
 #define X86_CR4_LA57 _BITUL(X86_CR4_LA57_BIT)
 #define X86_CR4_VMXE_BIT 13
@@ -138,4 +143,5 @@
 #define CX86_DIR1 0xff
 #define CX86_ARR_BASE 0xc4
 #define CX86_RCR_BASE 0xdc
+#define CR0_STATE (X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | X86_CR0_NE | X86_CR0_WP | X86_CR0_AM | X86_CR0_PG)
 #endif
diff --git a/libc/kernel/uapi/drm/amdgpu_drm.h b/libc/kernel/uapi/drm/amdgpu_drm.h
index 6ae9c9c..1cdae16 100644
--- a/libc/kernel/uapi/drm/amdgpu_drm.h
+++ b/libc/kernel/uapi/drm/amdgpu_drm.h
@@ -35,6 +35,8 @@
 #define DRM_AMDGPU_GEM_USERPTR 0x11
 #define DRM_AMDGPU_WAIT_FENCES 0x12
 #define DRM_AMDGPU_VM 0x13
+#define DRM_AMDGPU_FENCE_TO_HANDLE 0x14
+#define DRM_AMDGPU_SCHED 0x15
 #define DRM_IOCTL_AMDGPU_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create)
 #define DRM_IOCTL_AMDGPU_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap)
 #define DRM_IOCTL_AMDGPU_CTX DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_CTX, union drm_amdgpu_ctx)
@@ -49,6 +51,8 @@
 #define DRM_IOCTL_AMDGPU_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_GEM_USERPTR, struct drm_amdgpu_gem_userptr)
 #define DRM_IOCTL_AMDGPU_WAIT_FENCES DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_WAIT_FENCES, union drm_amdgpu_wait_fences)
 #define DRM_IOCTL_AMDGPU_VM DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_VM, union drm_amdgpu_vm)
+#define DRM_IOCTL_AMDGPU_FENCE_TO_HANDLE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_FENCE_TO_HANDLE, union drm_amdgpu_fence_to_handle)
+#define DRM_IOCTL_AMDGPU_SCHED DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_SCHED, union drm_amdgpu_sched)
 #define AMDGPU_GEM_DOMAIN_CPU 0x1
 #define AMDGPU_GEM_DOMAIN_GTT 0x2
 #define AMDGPU_GEM_DOMAIN_VRAM 0x4
@@ -61,6 +65,8 @@
 #define AMDGPU_GEM_CREATE_VRAM_CLEARED (1 << 3)
 #define AMDGPU_GEM_CREATE_SHADOW (1 << 4)
 #define AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS (1 << 5)
+#define AMDGPU_GEM_CREATE_VM_ALWAYS_VALID (1 << 6)
+#define AMDGPU_GEM_CREATE_EXPLICIT_SYNC (1 << 7)
 struct drm_amdgpu_gem_create_in {
   __u64 bo_size;
   __u64 alignment;
@@ -104,11 +110,17 @@
 #define AMDGPU_CTX_GUILTY_RESET 1
 #define AMDGPU_CTX_INNOCENT_RESET 2
 #define AMDGPU_CTX_UNKNOWN_RESET 3
+#define AMDGPU_CTX_PRIORITY_UNSET - 2048
+#define AMDGPU_CTX_PRIORITY_VERY_LOW - 1023
+#define AMDGPU_CTX_PRIORITY_LOW - 512
+#define AMDGPU_CTX_PRIORITY_NORMAL 0
+#define AMDGPU_CTX_PRIORITY_HIGH 512
+#define AMDGPU_CTX_PRIORITY_VERY_HIGH 1023
 struct drm_amdgpu_ctx_in {
   __u32 op;
   __u32 flags;
   __u32 ctx_id;
-  __u32 _pad;
+  __s32 priority;
 };
 union drm_amdgpu_ctx_out {
   struct {
@@ -138,6 +150,16 @@
   struct drm_amdgpu_vm_in in;
   struct drm_amdgpu_vm_out out;
 };
+#define AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE 1
+struct drm_amdgpu_sched_in {
+  __u32 op;
+  __u32 fd;
+  __s32 priority;
+  __u32 flags;
+};
+union drm_amdgpu_sched {
+  struct drm_amdgpu_sched_in in;
+};
 #define AMDGPU_GEM_USERPTR_READONLY (1 << 0)
 #define AMDGPU_GEM_USERPTR_ANONONLY (1 << 1)
 #define AMDGPU_GEM_USERPTR_VALIDATE (1 << 2)
@@ -331,6 +353,19 @@
 struct drm_amdgpu_cs_chunk_sem {
   __u32 handle;
 };
+#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ 0
+#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ_FD 1
+#define AMDGPU_FENCE_TO_HANDLE_GET_SYNC_FILE_FD 2
+union drm_amdgpu_fence_to_handle {
+  struct {
+    struct drm_amdgpu_fence fence;
+    __u32 what;
+    __u32 pad;
+  } in;
+  struct {
+    __u32 handle;
+  } out;
+};
 struct drm_amdgpu_cs_chunk_data {
   union {
     struct drm_amdgpu_cs_chunk_ib ib_data;
@@ -381,6 +416,7 @@
 #define AMDGPU_INFO_SENSOR_VDDNB 0x6
 #define AMDGPU_INFO_SENSOR_VDDGFX 0x7
 #define AMDGPU_INFO_NUM_VRAM_CPU_PAGE_FAULTS 0x1E
+#define AMDGPU_INFO_VRAM_LOST_COUNTER 0x1F
 #define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0
 #define AMDGPU_INFO_MMR_SE_INDEX_MASK 0xff
 #define AMDGPU_INFO_MMR_SH_INDEX_SHIFT 8
diff --git a/libc/kernel/uapi/drm/drm.h b/libc/kernel/uapi/drm/drm.h
index 6863dc1..ec0c1fa 100644
--- a/libc/kernel/uapi/drm/drm.h
+++ b/libc/kernel/uapi/drm/drm.h
@@ -412,6 +412,20 @@
   __u32 count_handles;
   __u32 pad;
 };
+struct drm_crtc_get_sequence {
+  __u32 crtc_id;
+  __u32 active;
+  __u64 sequence;
+  __s64 sequence_ns;
+};
+#define DRM_CRTC_SEQUENCE_RELATIVE 0x00000001
+#define DRM_CRTC_SEQUENCE_NEXT_ON_MISS 0x00000002
+struct drm_crtc_queue_sequence {
+  __u32 crtc_id;
+  __u32 flags;
+  __u64 sequence;
+  __u64 user_data;
+};
 #ifdef __cplusplus
 #endif
 #include "drm_mode.h"
@@ -478,6 +492,8 @@
 #define DRM_IOCTL_SG_ALLOC DRM_IOWR(0x38, struct drm_scatter_gather)
 #define DRM_IOCTL_SG_FREE DRM_IOW(0x39, struct drm_scatter_gather)
 #define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, union drm_wait_vblank)
+#define DRM_IOCTL_CRTC_GET_SEQUENCE DRM_IOWR(0x3b, struct drm_crtc_get_sequence)
+#define DRM_IOCTL_CRTC_QUEUE_SEQUENCE DRM_IOWR(0x3c, struct drm_crtc_queue_sequence)
 #define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw)
 #define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res)
 #define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc)
@@ -517,6 +533,10 @@
 #define DRM_IOCTL_SYNCOBJ_WAIT DRM_IOWR(0xC3, struct drm_syncobj_wait)
 #define DRM_IOCTL_SYNCOBJ_RESET DRM_IOWR(0xC4, struct drm_syncobj_array)
 #define DRM_IOCTL_SYNCOBJ_SIGNAL DRM_IOWR(0xC5, struct drm_syncobj_array)
+#define DRM_IOCTL_MODE_CREATE_LEASE DRM_IOWR(0xC6, struct drm_mode_create_lease)
+#define DRM_IOCTL_MODE_LIST_LESSEES DRM_IOWR(0xC7, struct drm_mode_list_lessees)
+#define DRM_IOCTL_MODE_GET_LEASE DRM_IOWR(0xC8, struct drm_mode_get_lease)
+#define DRM_IOCTL_MODE_REVOKE_LEASE DRM_IOWR(0xC9, struct drm_mode_revoke_lease)
 #define DRM_COMMAND_BASE 0x40
 #define DRM_COMMAND_END 0xA0
 struct drm_event {
@@ -525,6 +545,7 @@
 };
 #define DRM_EVENT_VBLANK 0x01
 #define DRM_EVENT_FLIP_COMPLETE 0x02
+#define DRM_EVENT_CRTC_SEQUENCE 0x03
 struct drm_event_vblank {
   struct drm_event base;
   __u64 user_data;
@@ -533,6 +554,12 @@
   __u32 sequence;
   __u32 crtc_id;
 };
+struct drm_event_crtc_sequence {
+  struct drm_event base;
+  __u64 user_data;
+  __s64 time_ns;
+  __u64 sequence;
+};
 typedef struct drm_clip_rect drm_clip_rect_t;
 typedef struct drm_drawable_info drm_drawable_info_t;
 typedef struct drm_tex_region drm_tex_region_t;
diff --git a/libc/kernel/uapi/drm/drm_mode.h b/libc/kernel/uapi/drm/drm_mode.h
index 5e97a72..2c9defb 100644
--- a/libc/kernel/uapi/drm/drm_mode.h
+++ b/libc/kernel/uapi/drm/drm_mode.h
@@ -427,6 +427,26 @@
 struct drm_mode_destroy_blob {
   __u32 blob_id;
 };
+struct drm_mode_create_lease {
+  __u64 object_ids;
+  __u32 object_count;
+  __u32 flags;
+  __u32 lessee_id;
+  __u32 fd;
+};
+struct drm_mode_list_lessees {
+  __u32 count_lessees;
+  __u32 pad;
+  __u64 lessees_ptr;
+};
+struct drm_mode_get_lease {
+  __u32 count_objects;
+  __u32 pad;
+  __u64 objects_ptr;
+};
+struct drm_mode_revoke_lease {
+  __u32 lessee_id;
+};
 #ifdef __cplusplus
 #endif
 #endif
diff --git a/libc/kernel/uapi/drm/etnaviv_drm.h b/libc/kernel/uapi/drm/etnaviv_drm.h
index 6376e25..58bd536 100644
--- a/libc/kernel/uapi/drm/etnaviv_drm.h
+++ b/libc/kernel/uapi/drm/etnaviv_drm.h
@@ -91,6 +91,17 @@
   __u32 handle;
   __u64 presumed;
 };
+#define ETNA_PM_PROCESS_PRE 0x0001
+#define ETNA_PM_PROCESS_POST 0x0002
+struct drm_etnaviv_gem_submit_pmr {
+  __u32 flags;
+  __u8 domain;
+  __u8 pad;
+  __u16 signal;
+  __u32 sequence;
+  __u32 read_offset;
+  __u32 read_idx;
+};
 #define ETNA_SUBMIT_NO_IMPLICIT 0x0001
 #define ETNA_SUBMIT_FENCE_FD_IN 0x0002
 #define ETNA_SUBMIT_FENCE_FD_OUT 0x0004
@@ -110,6 +121,9 @@
   __u64 stream;
   __u32 flags;
   __s32 fence_fd;
+  __u64 pmrs;
+  __u32 nr_pmrs;
+  __u32 pad;
 };
 #define ETNA_WAIT_NONBLOCK 0x01
 struct drm_etnaviv_wait_fence {
@@ -134,6 +148,21 @@
   __u32 pad;
   struct drm_etnaviv_timespec timeout;
 };
+struct drm_etnaviv_pm_domain {
+  __u32 pipe;
+  __u8 iter;
+  __u8 id;
+  __u16 nr_signals;
+  char name[64];
+};
+struct drm_etnaviv_pm_signal {
+  __u32 pipe;
+  __u8 domain;
+  __u8 pad;
+  __u16 iter;
+  __u16 id;
+  char name[64];
+};
 #define DRM_ETNAVIV_GET_PARAM 0x00
 #define DRM_ETNAVIV_GEM_NEW 0x02
 #define DRM_ETNAVIV_GEM_INFO 0x03
@@ -143,7 +172,9 @@
 #define DRM_ETNAVIV_WAIT_FENCE 0x07
 #define DRM_ETNAVIV_GEM_USERPTR 0x08
 #define DRM_ETNAVIV_GEM_WAIT 0x09
-#define DRM_ETNAVIV_NUM_IOCTLS 0x0a
+#define DRM_ETNAVIV_PM_QUERY_DOM 0x0a
+#define DRM_ETNAVIV_PM_QUERY_SIG 0x0b
+#define DRM_ETNAVIV_NUM_IOCTLS 0x0c
 #define DRM_IOCTL_ETNAVIV_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GET_PARAM, struct drm_etnaviv_param)
 #define DRM_IOCTL_ETNAVIV_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_NEW, struct drm_etnaviv_gem_new)
 #define DRM_IOCTL_ETNAVIV_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_INFO, struct drm_etnaviv_gem_info)
@@ -153,6 +184,8 @@
 #define DRM_IOCTL_ETNAVIV_WAIT_FENCE DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_WAIT_FENCE, struct drm_etnaviv_wait_fence)
 #define DRM_IOCTL_ETNAVIV_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_USERPTR, struct drm_etnaviv_gem_userptr)
 #define DRM_IOCTL_ETNAVIV_GEM_WAIT DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_WAIT, struct drm_etnaviv_gem_wait)
+#define DRM_IOCTL_ETNAVIV_PM_QUERY_DOM DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_PM_QUERY_DOM, struct drm_etnaviv_pm_domain)
+#define DRM_IOCTL_ETNAVIV_PM_QUERY_SIG DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_PM_QUERY_SIG, struct drm_etnaviv_pm_signal)
 #ifdef __cplusplus
 #endif
 #endif
diff --git a/libc/kernel/uapi/drm/i915_drm.h b/libc/kernel/uapi/drm/i915_drm.h
index 50ea43a..34342bf 100644
--- a/libc/kernel/uapi/drm/i915_drm.h
+++ b/libc/kernel/uapi/drm/i915_drm.h
@@ -293,6 +293,9 @@
 #define I915_PARAM_MIN_EU_IN_POOL 39
 #define I915_PARAM_MMAP_GTT_VERSION 40
 #define I915_PARAM_HAS_SCHEDULER 41
+#define I915_SCHEDULER_CAP_ENABLED (1ul << 0)
+#define I915_SCHEDULER_CAP_PRIORITY (1ul << 1)
+#define I915_SCHEDULER_CAP_PREEMPTION (1ul << 2)
 #define I915_PARAM_HUC_STATUS 42
 #define I915_PARAM_HAS_EXEC_ASYNC 43
 #define I915_PARAM_HAS_EXEC_FENCE 44
@@ -633,6 +636,7 @@
 };
 struct drm_i915_reg_read {
   __u64 offset;
+#define I915_REG_READ_8B_WA (1ul << 0)
   __u64 val;
 };
 struct drm_i915_reset_stats {
@@ -660,6 +664,10 @@
 #define I915_CONTEXT_PARAM_GTT_SIZE 0x3
 #define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE 0x4
 #define I915_CONTEXT_PARAM_BANNABLE 0x5
+#define I915_CONTEXT_PARAM_PRIORITY 0x6
+#define I915_CONTEXT_MAX_USER_PRIORITY 1023
+#define I915_CONTEXT_DEFAULT_PRIORITY 0
+#define I915_CONTEXT_MIN_USER_PRIORITY - 1023
   __u64 value;
 };
 enum drm_i915_oa_format {
@@ -709,9 +717,9 @@
   __u32 n_mux_regs;
   __u32 n_boolean_regs;
   __u32 n_flex_regs;
-  __u64 __user mux_regs_ptr;
-  __u64 __user boolean_regs_ptr;
-  __u64 __user flex_regs_ptr;
+  __u64 mux_regs_ptr;
+  __u64 boolean_regs_ptr;
+  __u64 flex_regs_ptr;
 };
 #ifdef __cplusplus
 #endif
diff --git a/libc/kernel/uapi/drm/msm_drm.h b/libc/kernel/uapi/drm/msm_drm.h
index 4f1a423..d2f1b57 100644
--- a/libc/kernel/uapi/drm/msm_drm.h
+++ b/libc/kernel/uapi/drm/msm_drm.h
@@ -38,6 +38,7 @@
 #define MSM_PARAM_MAX_FREQ 0x04
 #define MSM_PARAM_TIMESTAMP 0x05
 #define MSM_PARAM_GMEM_BASE 0x06
+#define MSM_PARAM_NR_RINGS 0x07
 struct drm_msm_param {
   __u32 pipe;
   __u32 param;
@@ -113,11 +114,13 @@
   __u64 bos;
   __u64 cmds;
   __s32 fence_fd;
+  __u32 queueid;
 };
 struct drm_msm_wait_fence {
   __u32 fence;
   __u32 pad;
   struct drm_msm_timespec timeout;
+  __u32 queueid;
 };
 #define MSM_MADV_WILLNEED 0
 #define MSM_MADV_DONTNEED 1
@@ -127,6 +130,12 @@
   __u32 madv;
   __u32 retained;
 };
+#define MSM_SUBMITQUEUE_FLAGS (0)
+struct drm_msm_submitqueue {
+  __u32 flags;
+  __u32 prio;
+  __u32 id;
+};
 #define DRM_MSM_GET_PARAM 0x00
 #define DRM_MSM_GEM_NEW 0x02
 #define DRM_MSM_GEM_INFO 0x03
@@ -135,6 +144,8 @@
 #define DRM_MSM_GEM_SUBMIT 0x06
 #define DRM_MSM_WAIT_FENCE 0x07
 #define DRM_MSM_GEM_MADVISE 0x08
+#define DRM_MSM_SUBMITQUEUE_NEW 0x0A
+#define DRM_MSM_SUBMITQUEUE_CLOSE 0x0B
 #define DRM_IOCTL_MSM_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GET_PARAM, struct drm_msm_param)
 #define DRM_IOCTL_MSM_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_NEW, struct drm_msm_gem_new)
 #define DRM_IOCTL_MSM_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_INFO, struct drm_msm_gem_info)
@@ -143,6 +154,8 @@
 #define DRM_IOCTL_MSM_GEM_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_SUBMIT, struct drm_msm_gem_submit)
 #define DRM_IOCTL_MSM_WAIT_FENCE DRM_IOW(DRM_COMMAND_BASE + DRM_MSM_WAIT_FENCE, struct drm_msm_wait_fence)
 #define DRM_IOCTL_MSM_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_MADVISE, struct drm_msm_gem_madvise)
+#define DRM_IOCTL_MSM_SUBMITQUEUE_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_NEW, struct drm_msm_submitqueue)
+#define DRM_IOCTL_MSM_SUBMITQUEUE_CLOSE DRM_IOW(DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_CLOSE, __u32)
 #ifdef __cplusplus
 #endif
 #endif
diff --git a/libc/kernel/uapi/drm/vc4_drm.h b/libc/kernel/uapi/drm/vc4_drm.h
index d96c49d..3ca378f 100644
--- a/libc/kernel/uapi/drm/vc4_drm.h
+++ b/libc/kernel/uapi/drm/vc4_drm.h
@@ -32,6 +32,7 @@
 #define DRM_VC4_SET_TILING 0x08
 #define DRM_VC4_GET_TILING 0x09
 #define DRM_VC4_LABEL_BO 0x0a
+#define DRM_VC4_GEM_MADVISE 0x0b
 #define DRM_IOCTL_VC4_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SUBMIT_CL, struct drm_vc4_submit_cl)
 #define DRM_IOCTL_VC4_WAIT_SEQNO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_SEQNO, struct drm_vc4_wait_seqno)
 #define DRM_IOCTL_VC4_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_BO, struct drm_vc4_wait_bo)
@@ -43,6 +44,7 @@
 #define DRM_IOCTL_VC4_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SET_TILING, struct drm_vc4_set_tiling)
 #define DRM_IOCTL_VC4_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_TILING, struct drm_vc4_get_tiling)
 #define DRM_IOCTL_VC4_LABEL_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_LABEL_BO, struct drm_vc4_label_bo)
+#define DRM_IOCTL_VC4_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GEM_MADVISE, struct drm_vc4_gem_madvise)
 struct drm_vc4_submit_rcl_surface {
   __u32 hindex;
   __u32 offset;
@@ -142,6 +144,7 @@
 #define DRM_VC4_PARAM_SUPPORTS_ETC1 4
 #define DRM_VC4_PARAM_SUPPORTS_THREADED_FS 5
 #define DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER 6
+#define DRM_VC4_PARAM_SUPPORTS_MADVISE 7
 struct drm_vc4_get_param {
   __u32 param;
   __u32 pad;
@@ -162,6 +165,16 @@
   __u32 len;
   __u64 name;
 };
+#define VC4_MADV_WILLNEED 0
+#define VC4_MADV_DONTNEED 1
+#define __VC4_MADV_PURGED 2
+#define __VC4_MADV_NOTSUPP 3
+struct drm_vc4_gem_madvise {
+  __u32 handle;
+  __u32 madv;
+  __u32 retained;
+  __u32 pad;
+};
 #ifdef __cplusplus
 #endif
 #endif
diff --git a/libc/kernel/uapi/linux/audit.h b/libc/kernel/uapi/linux/audit.h
index 3edd1d4..be48b44 100644
--- a/libc/kernel/uapi/linux/audit.h
+++ b/libc/kernel/uapi/linux/audit.h
@@ -78,6 +78,7 @@
 #define AUDIT_FEATURE_CHANGE 1328
 #define AUDIT_REPLACE 1329
 #define AUDIT_KERN_MODULE 1330
+#define AUDIT_FANOTIFY 1331
 #define AUDIT_AVC 1400
 #define AUDIT_SELINUX_ERR 1401
 #define AUDIT_AVC_PATH 1402
@@ -116,7 +117,8 @@
 #define AUDIT_FILTER_WATCH 0x03
 #define AUDIT_FILTER_EXIT 0x04
 #define AUDIT_FILTER_TYPE 0x05
-#define AUDIT_NR_FILTERS 6
+#define AUDIT_FILTER_FS 0x06
+#define AUDIT_NR_FILTERS 7
 #define AUDIT_FILTER_PREPEND 0x10
 #define AUDIT_NEVER 0
 #define AUDIT_POSSIBLE 1
@@ -190,6 +192,7 @@
 #define AUDIT_OBJ_LEV_HIGH 23
 #define AUDIT_LOGINUID_SET 24
 #define AUDIT_SESSIONID 25
+#define AUDIT_FSTYPE 26
 #define AUDIT_DEVMAJOR 100
 #define AUDIT_DEVMINOR 101
 #define AUDIT_INODE 102
@@ -242,7 +245,8 @@
 #define AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND 0x00000008
 #define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER 0x00000010
 #define AUDIT_FEATURE_BITMAP_LOST_RESET 0x00000020
-#define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | AUDIT_FEATURE_BITMAP_EXECUTABLE_PATH | AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | AUDIT_FEATURE_BITMAP_LOST_RESET)
+#define AUDIT_FEATURE_BITMAP_FILTER_FS 0x00000040
+#define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | AUDIT_FEATURE_BITMAP_EXECUTABLE_PATH | AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | AUDIT_FEATURE_BITMAP_LOST_RESET | AUDIT_FEATURE_BITMAP_FILTER_FS)
 #define AUDIT_VERSION_LATEST AUDIT_FEATURE_BITMAP_ALL
 #define AUDIT_VERSION_BACKLOG_LIMIT AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT
 #define AUDIT_VERSION_BACKLOG_WAIT_TIME AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME
diff --git a/libc/kernel/uapi/linux/bcache.h b/libc/kernel/uapi/linux/bcache.h
index 0933d51..4c7e32a 100644
--- a/libc/kernel/uapi/linux/bcache.h
+++ b/libc/kernel/uapi/linux/bcache.h
@@ -46,7 +46,7 @@
 #define START_KEY(k) KEY(KEY_INODE(k), KEY_START(k), 0)
 #define PTR_DEV_BITS 12
 #define PTR_CHECK_DEV ((1 << PTR_DEV_BITS) - 1)
-#define PTR(gen,offset,dev) ((((__u64) dev) << 51) | ((__u64) offset) << 8 | gen)
+#define MAKE_PTR(gen,offset,dev) ((((__u64) dev) << 51) | ((__u64) offset) << 8 | gen)
 #define bkey_copy(_dest,_src) memcpy(_dest, _src, bkey_bytes(_src))
 #define BKEY_PAD 8
 #define BKEY_PADDED(key) union { struct bkey key; __u64 key ##_pad[BKEY_PAD]; }
diff --git a/libc/kernel/uapi/linux/bfs_fs.h b/libc/kernel/uapi/linux/bfs_fs.h
index e828ce3..4a11e8a 100644
--- a/libc/kernel/uapi/linux/bfs_fs.h
+++ b/libc/kernel/uapi/linux/bfs_fs.h
@@ -66,5 +66,5 @@
 #define BFS_NZFILESIZE(ip) ((le32_to_cpu((ip)->i_eoffset) + 1) - le32_to_cpu((ip)->i_sblock) * BFS_BSIZE)
 #define BFS_FILESIZE(ip) ((ip)->i_sblock == 0 ? 0 : BFS_NZFILESIZE(ip))
 #define BFS_FILEBLOCKS(ip) ((ip)->i_sblock == 0 ? 0 : (le32_to_cpu((ip)->i_eblock) + 1) - le32_to_cpu((ip)->i_sblock))
-#define BFS_UNCLEAN(bfs_sb,sb) ((le32_to_cpu(bfs_sb->s_from) != - 1) && (le32_to_cpu(bfs_sb->s_to) != - 1) && ! (sb->s_flags & MS_RDONLY))
+#define BFS_UNCLEAN(bfs_sb,sb) ((le32_to_cpu(bfs_sb->s_from) != - 1) && (le32_to_cpu(bfs_sb->s_to) != - 1) && ! (sb->s_flags & SB_RDONLY))
 #endif
diff --git a/libc/kernel/uapi/linux/bpf.h b/libc/kernel/uapi/linux/bpf.h
index 1dfb99f..9ac0729 100644
--- a/libc/kernel/uapi/linux/bpf.h
+++ b/libc/kernel/uapi/linux/bpf.h
@@ -82,6 +82,7 @@
   BPF_PROG_GET_FD_BY_ID,
   BPF_MAP_GET_FD_BY_ID,
   BPF_OBJ_GET_INFO_BY_FD,
+  BPF_PROG_QUERY,
 };
 enum bpf_map_type {
   BPF_MAP_TYPE_UNSPEC,
@@ -100,6 +101,7 @@
   BPF_MAP_TYPE_HASH_OF_MAPS,
   BPF_MAP_TYPE_DEVMAP,
   BPF_MAP_TYPE_SOCKMAP,
+  BPF_MAP_TYPE_CPUMAP,
 };
 enum bpf_prog_type {
   BPF_PROG_TYPE_UNSPEC,
@@ -117,6 +119,7 @@
   BPF_PROG_TYPE_LWT_XMIT,
   BPF_PROG_TYPE_SOCK_OPS,
   BPF_PROG_TYPE_SK_SKB,
+  BPF_PROG_TYPE_CGROUP_DEVICE,
 };
 enum bpf_attach_type {
   BPF_CGROUP_INET_INGRESS,
@@ -125,10 +128,12 @@
   BPF_CGROUP_SOCK_OPS,
   BPF_SK_SKB_STREAM_PARSER,
   BPF_SK_SKB_STREAM_VERDICT,
+  BPF_CGROUP_DEVICE,
   __MAX_BPF_ATTACH_TYPE
 };
 #define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
 #define BPF_F_ALLOW_OVERRIDE (1U << 0)
+#define BPF_F_ALLOW_MULTI (1U << 1)
 #define BPF_F_STRICT_ALIGNMENT (1U << 0)
 #define BPF_PSEUDO_MAP_FD 1
 #define BPF_ANY 0
@@ -137,6 +142,10 @@
 #define BPF_F_NO_PREALLOC (1U << 0)
 #define BPF_F_NO_COMMON_LRU (1U << 1)
 #define BPF_F_NUMA_NODE (1U << 2)
+#define BPF_F_QUERY_EFFECTIVE (1U << 0)
+#define BPF_OBJ_NAME_LEN 16U
+#define BPF_F_RDONLY (1U << 3)
+#define BPF_F_WRONLY (1U << 4)
 union bpf_attr {
   struct {
     __u32 map_type;
@@ -146,6 +155,7 @@
     __u32 map_flags;
     __u32 inner_map_fd;
     __u32 numa_node;
+    char map_name[BPF_OBJ_NAME_LEN];
   };
   struct {
     __u32 map_fd;
@@ -166,10 +176,13 @@
     __aligned_u64 log_buf;
     __u32 kern_version;
     __u32 prog_flags;
+    char prog_name[BPF_OBJ_NAME_LEN];
+    __u32 prog_ifindex;
   };
   struct {
     __aligned_u64 pathname;
     __u32 bpf_fd;
+    __u32 file_flags;
   };
   struct {
     __u32 target_fd;
@@ -194,14 +207,23 @@
       __u32 map_id;
     };
     __u32 next_id;
+    __u32 open_flags;
   };
   struct {
     __u32 bpf_fd;
     __u32 info_len;
     __aligned_u64 info;
   } info;
+  struct {
+    __u32 target_fd;
+    __u32 attach_type;
+    __u32 query_flags;
+    __u32 attach_flags;
+    __aligned_u64 prog_ids;
+    __u32 prog_cnt;
+  } query;
 } __attribute__((aligned(8)));
-#define __BPF_FUNC_MAPPER(FN) FN(unspec), FN(map_lookup_elem), FN(map_update_elem), FN(map_delete_elem), FN(probe_read), FN(ktime_get_ns), FN(trace_printk), FN(get_prandom_u32), FN(get_smp_processor_id), FN(skb_store_bytes), FN(l3_csum_replace), FN(l4_csum_replace), FN(tail_call), FN(clone_redirect), FN(get_current_pid_tgid), FN(get_current_uid_gid), FN(get_current_comm), FN(get_cgroup_classid), FN(skb_vlan_push), FN(skb_vlan_pop), FN(skb_get_tunnel_key), FN(skb_set_tunnel_key), FN(perf_event_read), FN(redirect), FN(get_route_realm), FN(perf_event_output), FN(skb_load_bytes), FN(get_stackid), FN(csum_diff), FN(skb_get_tunnel_opt), FN(skb_set_tunnel_opt), FN(skb_change_proto), FN(skb_change_type), FN(skb_under_cgroup), FN(get_hash_recalc), FN(get_current_task), FN(probe_write_user), FN(current_task_under_cgroup), FN(skb_change_tail), FN(skb_pull_data), FN(csum_update), FN(set_hash_invalid), FN(get_numa_node_id), FN(skb_change_head), FN(xdp_adjust_head), FN(probe_read_str), FN(get_socket_cookie), FN(get_socket_uid), FN(set_hash), FN(setsockopt), FN(skb_adjust_room), FN(redirect_map), FN(sk_redirect_map), FN(sock_map_update),
+#define __BPF_FUNC_MAPPER(FN) FN(unspec), FN(map_lookup_elem), FN(map_update_elem), FN(map_delete_elem), FN(probe_read), FN(ktime_get_ns), FN(trace_printk), FN(get_prandom_u32), FN(get_smp_processor_id), FN(skb_store_bytes), FN(l3_csum_replace), FN(l4_csum_replace), FN(tail_call), FN(clone_redirect), FN(get_current_pid_tgid), FN(get_current_uid_gid), FN(get_current_comm), FN(get_cgroup_classid), FN(skb_vlan_push), FN(skb_vlan_pop), FN(skb_get_tunnel_key), FN(skb_set_tunnel_key), FN(perf_event_read), FN(redirect), FN(get_route_realm), FN(perf_event_output), FN(skb_load_bytes), FN(get_stackid), FN(csum_diff), FN(skb_get_tunnel_opt), FN(skb_set_tunnel_opt), FN(skb_change_proto), FN(skb_change_type), FN(skb_under_cgroup), FN(get_hash_recalc), FN(get_current_task), FN(probe_write_user), FN(current_task_under_cgroup), FN(skb_change_tail), FN(skb_pull_data), FN(csum_update), FN(set_hash_invalid), FN(get_numa_node_id), FN(skb_change_head), FN(xdp_adjust_head), FN(probe_read_str), FN(get_socket_cookie), FN(get_socket_uid), FN(set_hash), FN(setsockopt), FN(skb_adjust_room), FN(redirect_map), FN(sk_redirect_map), FN(sock_map_update), FN(xdp_adjust_meta), FN(perf_event_read_value), FN(perf_prog_read_value), FN(getsockopt),
 #define __BPF_ENUM_FN(x) BPF_FUNC_ ##x
 enum bpf_func_id {
   __BPF_FUNC_MAPPER(__BPF_ENUM_FN) __BPF_FUNC_MAX_ID,
@@ -253,6 +275,7 @@
   __u32 local_ip6[4];
   __u32 remote_port;
   __u32 local_port;
+  __u32 data_meta;
 };
 struct bpf_tunnel_key {
   __u32 tunnel_id;
@@ -289,6 +312,7 @@
 struct xdp_md {
   __u32 data;
   __u32 data_end;
+  __u32 data_meta;
 };
 enum sk_action {
   SK_DROP = 0,
@@ -303,6 +327,11 @@
   __u32 xlated_prog_len;
   __aligned_u64 jited_prog_insns;
   __aligned_u64 xlated_prog_insns;
+  __u64 load_time;
+  __u32 created_by_uid;
+  __u32 nr_map_ids;
+  __aligned_u64 map_ids;
+  char name[BPF_OBJ_NAME_LEN];
 } __attribute__((aligned(8)));
 struct bpf_map_info {
   __u32 type;
@@ -311,6 +340,7 @@
   __u32 value_size;
   __u32 max_entries;
   __u32 map_flags;
+  char name[BPF_OBJ_NAME_LEN];
 } __attribute__((aligned(8)));
 struct bpf_sock_ops {
   __u32 op;
@@ -334,7 +364,23 @@
   BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB,
   BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB,
   BPF_SOCK_OPS_NEEDS_ECN,
+  BPF_SOCK_OPS_BASE_RTT,
 };
 #define TCP_BPF_IW 1001
 #define TCP_BPF_SNDCWND_CLAMP 1002
+struct bpf_perf_event_value {
+  __u64 counter;
+  __u64 enabled;
+  __u64 running;
+};
+#define BPF_DEVCG_ACC_MKNOD (1ULL << 0)
+#define BPF_DEVCG_ACC_READ (1ULL << 1)
+#define BPF_DEVCG_ACC_WRITE (1ULL << 2)
+#define BPF_DEVCG_DEV_BLOCK (1ULL << 0)
+#define BPF_DEVCG_DEV_CHAR (1ULL << 1)
+struct bpf_cgroup_dev_ctx {
+  __u32 access_type;
+  __u32 major;
+  __u32 minor;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/bpf_perf_event.h b/libc/kernel/uapi/linux/bpf_perf_event.h
index ef7bd18..7a8d212 100644
--- a/libc/kernel/uapi/linux/bpf_perf_event.h
+++ b/libc/kernel/uapi/linux/bpf_perf_event.h
@@ -18,10 +18,9 @@
  ****************************************************************************/
 #ifndef _UAPI__LINUX_BPF_PERF_EVENT_H__
 #define _UAPI__LINUX_BPF_PERF_EVENT_H__
-#include <linux/types.h>
-#include <linux/ptrace.h>
+#include <asm/bpf_perf_event.h>
 struct bpf_perf_event_data {
-  struct pt_regs regs;
+  bpf_user_pt_regs_t regs;
   __u64 sample_period;
 };
 #endif
diff --git a/libc/kernel/uapi/linux/btrfs.h b/libc/kernel/uapi/linux/btrfs.h
index a23ab58..aa7c105 100644
--- a/libc/kernel/uapi/linux/btrfs.h
+++ b/libc/kernel/uapi/linux/btrfs.h
@@ -339,9 +339,11 @@
 struct btrfs_ioctl_logical_ino_args {
   __u64 logical;
   __u64 size;
-  __u64 reserved[4];
+  __u64 reserved[3];
+  __u64 flags;
   __u64 inodes;
 };
+#define BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET (1ULL << 0)
 enum btrfs_dev_stat_values {
   BTRFS_DEV_STAT_WRITE_ERRS,
   BTRFS_DEV_STAT_READ_ERRS,
@@ -469,4 +471,5 @@
 #define BTRFS_IOC_SET_FEATURES _IOW(BTRFS_IOCTL_MAGIC, 57, struct btrfs_ioctl_feature_flags[2])
 #define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, struct btrfs_ioctl_feature_flags[3])
 #define BTRFS_IOC_RM_DEV_V2 _IOW(BTRFS_IOCTL_MAGIC, 58, struct btrfs_ioctl_vol_args_v2)
+#define BTRFS_IOC_LOGICAL_INO_V2 _IOWR(BTRFS_IOCTL_MAGIC, 59, struct btrfs_ioctl_logical_ino_args)
 #endif
diff --git a/libc/kernel/uapi/linux/btrfs_tree.h b/libc/kernel/uapi/linux/btrfs_tree.h
index c75732e..c2fbd40 100644
--- a/libc/kernel/uapi/linux/btrfs_tree.h
+++ b/libc/kernel/uapi/linux/btrfs_tree.h
@@ -320,6 +320,7 @@
 #define BTRFS_FILE_EXTENT_INLINE 0
 #define BTRFS_FILE_EXTENT_REG 1
 #define BTRFS_FILE_EXTENT_PREALLOC 2
+#define BTRFS_FILE_EXTENT_TYPES 2
 struct btrfs_file_extent_item {
   __le64 generation;
   __le64 ram_bytes;
diff --git a/libc/kernel/uapi/linux/cec.h b/libc/kernel/uapi/linux/cec.h
index 3fcee96..98892f7 100644
--- a/libc/kernel/uapi/linux/cec.h
+++ b/libc/kernel/uapi/linux/cec.h
@@ -130,6 +130,8 @@
 #define CEC_EVENT_LOST_MSGS 2
 #define CEC_EVENT_PIN_CEC_LOW 3
 #define CEC_EVENT_PIN_CEC_HIGH 4
+#define CEC_EVENT_PIN_HPD_LOW 5
+#define CEC_EVENT_PIN_HPD_HIGH 6
 #define CEC_EVENT_FL_INITIAL_STATE (1 << 0)
 #define CEC_EVENT_FL_DROPPED_EVENTS (1 << 1)
 struct cec_event_state_change {
diff --git a/libc/kernel/uapi/linux/cramfs_fs.h b/libc/kernel/uapi/linux/cramfs_fs.h
index 5d119ba..8872914 100644
--- a/libc/kernel/uapi/linux/cramfs_fs.h
+++ b/libc/kernel/uapi/linux/cramfs_fs.h
@@ -54,5 +54,10 @@
 #define CRAMFS_FLAG_HOLES 0x00000100
 #define CRAMFS_FLAG_WRONG_SIGNATURE 0x00000200
 #define CRAMFS_FLAG_SHIFTED_ROOT_OFFSET 0x00000400
-#define CRAMFS_SUPPORTED_FLAGS (0x000000ff | CRAMFS_FLAG_HOLES | CRAMFS_FLAG_WRONG_SIGNATURE | CRAMFS_FLAG_SHIFTED_ROOT_OFFSET)
+#define CRAMFS_FLAG_EXT_BLOCK_POINTERS 0x00000800
+#define CRAMFS_SUPPORTED_FLAGS (0x000000ff | CRAMFS_FLAG_HOLES | CRAMFS_FLAG_WRONG_SIGNATURE | CRAMFS_FLAG_SHIFTED_ROOT_OFFSET | CRAMFS_FLAG_EXT_BLOCK_POINTERS)
+#define CRAMFS_BLK_FLAG_UNCOMPRESSED (1 << 31)
+#define CRAMFS_BLK_FLAG_DIRECT_PTR (1 << 30)
+#define CRAMFS_BLK_FLAGS (CRAMFS_BLK_FLAG_UNCOMPRESSED | CRAMFS_BLK_FLAG_DIRECT_PTR)
+#define CRAMFS_BLK_DIRECT_PTR_SHIFT 2
 #endif
diff --git a/libc/kernel/uapi/linux/dcbnl.h b/libc/kernel/uapi/linux/dcbnl.h
index 569efdd..2fe4cce 100644
--- a/libc/kernel/uapi/linux/dcbnl.h
+++ b/libc/kernel/uapi/linux/dcbnl.h
@@ -91,6 +91,7 @@
 #define IEEE_8021QAZ_APP_SEL_STREAM 2
 #define IEEE_8021QAZ_APP_SEL_DGRAM 3
 #define IEEE_8021QAZ_APP_SEL_ANY 4
+#define IEEE_8021QAZ_APP_SEL_DSCP 5
 struct dcb_app {
   __u8 selector;
   __u8 priority;
diff --git a/libc/kernel/uapi/linux/elf.h b/libc/kernel/uapi/linux/elf.h
index 8aa1011..bf35f6c 100644
--- a/libc/kernel/uapi/linux/elf.h
+++ b/libc/kernel/uapi/linux/elf.h
@@ -347,11 +347,13 @@
 #define NT_S390_VXRS_HIGH 0x30a
 #define NT_S390_GS_CB 0x30b
 #define NT_S390_GS_BC 0x30c
+#define NT_S390_RI_CB 0x30d
 #define NT_ARM_VFP 0x400
 #define NT_ARM_TLS 0x401
 #define NT_ARM_HW_BREAK 0x402
 #define NT_ARM_HW_WATCH 0x403
 #define NT_ARM_SYSTEM_CALL 0x404
+#define NT_ARM_SVE 0x405
 #define NT_METAG_CBUF 0x500
 #define NT_METAG_RPIPE 0x501
 #define NT_METAG_TLS 0x502
diff --git a/libc/kernel/uapi/linux/fanotify.h b/libc/kernel/uapi/linux/fanotify.h
index b10106e..73d92ca 100644
--- a/libc/kernel/uapi/linux/fanotify.h
+++ b/libc/kernel/uapi/linux/fanotify.h
@@ -38,6 +38,7 @@
 #define FAN_ALL_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | FAN_CLASS_PRE_CONTENT)
 #define FAN_UNLIMITED_QUEUE 0x00000010
 #define FAN_UNLIMITED_MARKS 0x00000020
+#define FAN_ENABLE_AUDIT 0x00000040
 #define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS)
 #define FAN_MARK_ADD 0x00000001
 #define FAN_MARK_REMOVE 0x00000002
@@ -67,6 +68,7 @@
 };
 #define FAN_ALLOW 0x01
 #define FAN_DENY 0x02
+#define FAN_AUDIT 0x10
 #define FAN_NOFD - 1
 #define FAN_EVENT_METADATA_LEN (sizeof(struct fanotify_event_metadata))
 #define FAN_EVENT_NEXT(meta,len) ((len) -= (meta)->event_len, (struct fanotify_event_metadata *) (((char *) (meta)) + (meta)->event_len))
diff --git a/libc/kernel/uapi/linux/if_ether.h b/libc/kernel/uapi/linux/if_ether.h
index f40321e..04b6dae 100644
--- a/libc/kernel/uapi/linux/if_ether.h
+++ b/libc/kernel/uapi/linux/if_ether.h
@@ -19,6 +19,7 @@
 #ifndef _UAPI_LINUX_IF_ETHER_H
 #define _UAPI_LINUX_IF_ETHER_H
 #include <linux/types.h>
+#include <linux/libc-compat.h>
 #define ETH_ALEN 6
 #define ETH_HLEN 14
 #define ETH_ZLEN 60
@@ -116,9 +117,11 @@
 #define ETH_P_CAIF 0x00F7
 #define ETH_P_XDSA 0x00F8
 #define ETH_P_MAP 0x00F9
+#if __UAPI_DEF_ETHHDR
 struct ethhdr {
   unsigned char h_dest[ETH_ALEN];
   unsigned char h_source[ETH_ALEN];
   __be16 h_proto;
 } __attribute__((packed));
 #endif
+#endif
diff --git a/libc/kernel/uapi/linux/if_link.h b/libc/kernel/uapi/linux/if_link.h
index c041c82..a43eaf7 100644
--- a/libc/kernel/uapi/linux/if_link.h
+++ b/libc/kernel/uapi/linux/if_link.h
@@ -136,6 +136,8 @@
   IFLA_PAD,
   IFLA_XDP,
   IFLA_EVENT,
+  IFLA_NEW_NETNSID,
+  IFLA_IF_NETNSID,
   __IFLA_MAX
 };
 #define IFLA_MAX (__IFLA_MAX - 1)
@@ -255,6 +257,8 @@
   IFLA_BRPORT_MCAST_TO_UCAST,
   IFLA_BRPORT_VLAN_TUNNEL,
   IFLA_BRPORT_BCAST_FLOOD,
+  IFLA_BRPORT_GROUP_FWD_MASK,
+  IFLA_BRPORT_NEIGH_SUPPRESS,
   __IFLA_BRPORT_MAX
 };
 #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
@@ -364,6 +368,7 @@
 enum {
   IFLA_IPVLAN_UNSPEC,
   IFLA_IPVLAN_MODE,
+  IFLA_IPVLAN_FLAGS,
   __IFLA_IPVLAN_MAX
 };
 #define IFLA_IPVLAN_MAX (__IFLA_IPVLAN_MAX - 1)
@@ -373,6 +378,8 @@
   IPVLAN_MODE_L3S,
   IPVLAN_MODE_MAX
 };
+#define IPVLAN_F_PRIVATE 0x01
+#define IPVLAN_F_VEPA 0x02
 enum {
   IFLA_VXLAN_UNSPEC,
   IFLA_VXLAN_ID,
diff --git a/libc/kernel/uapi/linux/if_tun.h b/libc/kernel/uapi/linux/if_tun.h
index 4912d7b..d8757a1 100644
--- a/libc/kernel/uapi/linux/if_tun.h
+++ b/libc/kernel/uapi/linux/if_tun.h
@@ -51,6 +51,8 @@
 #define TUNGETVNETBE _IOR('T', 223, int)
 #define IFF_TUN 0x0001
 #define IFF_TAP 0x0002
+#define IFF_NAPI 0x0010
+#define IFF_NAPI_FRAGS 0x0020
 #define IFF_NO_PI 0x1000
 #define IFF_ONE_QUEUE 0x2000
 #define IFF_VNET_HDR 0x4000
diff --git a/libc/kernel/uapi/linux/if_tunnel.h b/libc/kernel/uapi/linux/if_tunnel.h
index bfc6479..8edc956 100644
--- a/libc/kernel/uapi/linux/if_tunnel.h
+++ b/libc/kernel/uapi/linux/if_tunnel.h
@@ -93,6 +93,7 @@
   TUNNEL_ENCAP_NONE,
   TUNNEL_ENCAP_FOU,
   TUNNEL_ENCAP_GUE,
+  TUNNEL_ENCAP_MPLS,
 };
 #define TUNNEL_ENCAP_FLAG_CSUM (1 << 0)
 #define TUNNEL_ENCAP_FLAG_CSUM6 (1 << 1)
diff --git a/libc/kernel/uapi/linux/ila.h b/libc/kernel/uapi/linux/ila.h
index 38386be..a5af23a 100644
--- a/libc/kernel/uapi/linux/ila.h
+++ b/libc/kernel/uapi/linux/ila.h
@@ -29,6 +29,8 @@
   ILA_ATTR_DIR,
   ILA_ATTR_PAD,
   ILA_ATTR_CSUM_MODE,
+  ILA_ATTR_IDENT_TYPE,
+  ILA_ATTR_HOOK_TYPE,
   __ILA_ATTR_MAX,
 };
 #define ILA_ATTR_MAX (__ILA_ATTR_MAX - 1)
@@ -46,5 +48,21 @@
   ILA_CSUM_ADJUST_TRANSPORT,
   ILA_CSUM_NEUTRAL_MAP,
   ILA_CSUM_NO_ACTION,
+  ILA_CSUM_NEUTRAL_MAP_AUTO,
+};
+enum {
+  ILA_ATYPE_IID = 0,
+  ILA_ATYPE_LUID,
+  ILA_ATYPE_VIRT_V4,
+  ILA_ATYPE_VIRT_UNI_V6,
+  ILA_ATYPE_VIRT_MULTI_V6,
+  ILA_ATYPE_NONLOCAL_ADDR,
+  ILA_ATYPE_RSVD_1,
+  ILA_ATYPE_RSVD_2,
+  ILA_ATYPE_USE_FORMAT = 32,
+};
+enum {
+  ILA_HOOK_ROUTE_OUTPUT,
+  ILA_HOOK_ROUTE_INPUT,
 };
 #endif
diff --git a/libc/kernel/uapi/linux/in6.h b/libc/kernel/uapi/linux/in6.h
index 1e3b49d..9da111c 100644
--- a/libc/kernel/uapi/linux/in6.h
+++ b/libc/kernel/uapi/linux/in6.h
@@ -175,4 +175,5 @@
 #define IPV6_TRANSPARENT 75
 #define IPV6_UNICAST_IF 76
 #define IPV6_RECVFRAGSIZE 77
+#define IPV6_FREEBIND 78
 #endif
diff --git a/libc/kernel/uapi/linux/input-event-codes.h b/libc/kernel/uapi/linux/input-event-codes.h
index 346ec91..da90f1c 100644
--- a/libc/kernel/uapi/linux/input-event-codes.h
+++ b/libc/kernel/uapi/linux/input-event-codes.h
@@ -359,6 +359,7 @@
 #define BTN_TOOL_MOUSE 0x146
 #define BTN_TOOL_LENS 0x147
 #define BTN_TOOL_QUINTTAP 0x148
+#define BTN_STYLUS3 0x149
 #define BTN_TOUCH 0x14a
 #define BTN_STYLUS 0x14b
 #define BTN_STYLUS2 0x14c
diff --git a/libc/kernel/uapi/linux/ip6_tunnel.h b/libc/kernel/uapi/linux/ip6_tunnel.h
index b7df956..ba59235 100644
--- a/libc/kernel/uapi/linux/ip6_tunnel.h
+++ b/libc/kernel/uapi/linux/ip6_tunnel.h
@@ -29,6 +29,7 @@
 #define IP6_TNL_F_MIP6_DEV 0x8
 #define IP6_TNL_F_RCV_DSCP_COPY 0x10
 #define IP6_TNL_F_USE_ORIG_FWMARK 0x20
+#define IP6_TNL_F_ALLOW_LOCAL_REMOTE 0x40
 struct ip6_tnl_parm {
   char name[IFNAMSIZ];
   int link;
diff --git a/libc/kernel/uapi/linux/ipv6.h b/libc/kernel/uapi/linux/ipv6.h
index d07fa06..ff345a6 100644
--- a/libc/kernel/uapi/linux/ipv6.h
+++ b/libc/kernel/uapi/linux/ipv6.h
@@ -140,6 +140,7 @@
   DEVCONF_ADDR_GEN_MODE,
   DEVCONF_DISABLE_POLICY,
   DEVCONF_ACCEPT_RA_RT_INFO_MIN_PLEN,
+  DEVCONF_NDISC_TCLASS,
   DEVCONF_MAX
 };
 #endif
diff --git a/libc/kernel/uapi/linux/iso_fs.h b/libc/kernel/uapi/linux/iso_fs.h
index d88d646..8227031 100644
--- a/libc/kernel/uapi/linux/iso_fs.h
+++ b/libc/kernel/uapi/linux/iso_fs.h
@@ -22,34 +22,34 @@
 #include <linux/magic.h>
 #define ISODCL(from,to) (to - from + 1)
 struct iso_volume_descriptor {
-  char type[ISODCL(1, 1)];
+  __u8 type[ISODCL(1, 1)];
   char id[ISODCL(2, 6)];
-  char version[ISODCL(7, 7)];
-  char data[ISODCL(8, 2048)];
+  __u8 version[ISODCL(7, 7)];
+  __u8 data[ISODCL(8, 2048)];
 };
 #define ISO_VD_PRIMARY 1
 #define ISO_VD_SUPPLEMENTARY 2
 #define ISO_VD_END 255
 #define ISO_STANDARD_ID "CD001"
 struct iso_primary_descriptor {
-  char type[ISODCL(1, 1)];
+  __u8 type[ISODCL(1, 1)];
   char id[ISODCL(2, 6)];
-  char version[ISODCL(7, 7)];
-  char unused1[ISODCL(8, 8)];
+  __u8 version[ISODCL(7, 7)];
+  __u8 unused1[ISODCL(8, 8)];
   char system_id[ISODCL(9, 40)];
   char volume_id[ISODCL(41, 72)];
-  char unused2[ISODCL(73, 80)];
-  char volume_space_size[ISODCL(81, 88)];
-  char unused3[ISODCL(89, 120)];
-  char volume_set_size[ISODCL(121, 124)];
-  char volume_sequence_number[ISODCL(125, 128)];
-  char logical_block_size[ISODCL(129, 132)];
-  char path_table_size[ISODCL(133, 140)];
-  char type_l_path_table[ISODCL(141, 144)];
-  char opt_type_l_path_table[ISODCL(145, 148)];
-  char type_m_path_table[ISODCL(149, 152)];
-  char opt_type_m_path_table[ISODCL(153, 156)];
-  char root_directory_record[ISODCL(157, 190)];
+  __u8 unused2[ISODCL(73, 80)];
+  __u8 volume_space_size[ISODCL(81, 88)];
+  __u8 unused3[ISODCL(89, 120)];
+  __u8 volume_set_size[ISODCL(121, 124)];
+  __u8 volume_sequence_number[ISODCL(125, 128)];
+  __u8 logical_block_size[ISODCL(129, 132)];
+  __u8 path_table_size[ISODCL(133, 140)];
+  __u8 type_l_path_table[ISODCL(141, 144)];
+  __u8 opt_type_l_path_table[ISODCL(145, 148)];
+  __u8 type_m_path_table[ISODCL(149, 152)];
+  __u8 opt_type_m_path_table[ISODCL(153, 156)];
+  __u8 root_directory_record[ISODCL(157, 190)];
   char volume_set_id[ISODCL(191, 318)];
   char publisher_id[ISODCL(319, 446)];
   char preparer_id[ISODCL(447, 574)];
@@ -57,34 +57,34 @@
   char copyright_file_id[ISODCL(703, 739)];
   char abstract_file_id[ISODCL(740, 776)];
   char bibliographic_file_id[ISODCL(777, 813)];
-  char creation_date[ISODCL(814, 830)];
-  char modification_date[ISODCL(831, 847)];
-  char expiration_date[ISODCL(848, 864)];
-  char effective_date[ISODCL(865, 881)];
-  char file_structure_version[ISODCL(882, 882)];
-  char unused4[ISODCL(883, 883)];
-  char application_data[ISODCL(884, 1395)];
-  char unused5[ISODCL(1396, 2048)];
+  __u8 creation_date[ISODCL(814, 830)];
+  __u8 modification_date[ISODCL(831, 847)];
+  __u8 expiration_date[ISODCL(848, 864)];
+  __u8 effective_date[ISODCL(865, 881)];
+  __u8 file_structure_version[ISODCL(882, 882)];
+  __u8 unused4[ISODCL(883, 883)];
+  __u8 application_data[ISODCL(884, 1395)];
+  __u8 unused5[ISODCL(1396, 2048)];
 };
 struct iso_supplementary_descriptor {
-  char type[ISODCL(1, 1)];
+  __u8 type[ISODCL(1, 1)];
   char id[ISODCL(2, 6)];
-  char version[ISODCL(7, 7)];
-  char flags[ISODCL(8, 8)];
+  __u8 version[ISODCL(7, 7)];
+  __u8 flags[ISODCL(8, 8)];
   char system_id[ISODCL(9, 40)];
   char volume_id[ISODCL(41, 72)];
-  char unused2[ISODCL(73, 80)];
-  char volume_space_size[ISODCL(81, 88)];
-  char escape[ISODCL(89, 120)];
-  char volume_set_size[ISODCL(121, 124)];
-  char volume_sequence_number[ISODCL(125, 128)];
-  char logical_block_size[ISODCL(129, 132)];
-  char path_table_size[ISODCL(133, 140)];
-  char type_l_path_table[ISODCL(141, 144)];
-  char opt_type_l_path_table[ISODCL(145, 148)];
-  char type_m_path_table[ISODCL(149, 152)];
-  char opt_type_m_path_table[ISODCL(153, 156)];
-  char root_directory_record[ISODCL(157, 190)];
+  __u8 unused2[ISODCL(73, 80)];
+  __u8 volume_space_size[ISODCL(81, 88)];
+  __u8 escape[ISODCL(89, 120)];
+  __u8 volume_set_size[ISODCL(121, 124)];
+  __u8 volume_sequence_number[ISODCL(125, 128)];
+  __u8 logical_block_size[ISODCL(129, 132)];
+  __u8 path_table_size[ISODCL(133, 140)];
+  __u8 type_l_path_table[ISODCL(141, 144)];
+  __u8 opt_type_l_path_table[ISODCL(145, 148)];
+  __u8 type_m_path_table[ISODCL(149, 152)];
+  __u8 opt_type_m_path_table[ISODCL(153, 156)];
+  __u8 root_directory_record[ISODCL(157, 190)];
   char volume_set_id[ISODCL(191, 318)];
   char publisher_id[ISODCL(319, 446)];
   char preparer_id[ISODCL(447, 574)];
@@ -92,59 +92,59 @@
   char copyright_file_id[ISODCL(703, 739)];
   char abstract_file_id[ISODCL(740, 776)];
   char bibliographic_file_id[ISODCL(777, 813)];
-  char creation_date[ISODCL(814, 830)];
-  char modification_date[ISODCL(831, 847)];
-  char expiration_date[ISODCL(848, 864)];
-  char effective_date[ISODCL(865, 881)];
-  char file_structure_version[ISODCL(882, 882)];
-  char unused4[ISODCL(883, 883)];
-  char application_data[ISODCL(884, 1395)];
-  char unused5[ISODCL(1396, 2048)];
+  __u8 creation_date[ISODCL(814, 830)];
+  __u8 modification_date[ISODCL(831, 847)];
+  __u8 expiration_date[ISODCL(848, 864)];
+  __u8 effective_date[ISODCL(865, 881)];
+  __u8 file_structure_version[ISODCL(882, 882)];
+  __u8 unused4[ISODCL(883, 883)];
+  __u8 application_data[ISODCL(884, 1395)];
+  __u8 unused5[ISODCL(1396, 2048)];
 };
 #define HS_STANDARD_ID "CDROM"
 struct hs_volume_descriptor {
-  char foo[ISODCL(1, 8)];
-  char type[ISODCL(9, 9)];
+  __u8 foo[ISODCL(1, 8)];
+  __u8 type[ISODCL(9, 9)];
   char id[ISODCL(10, 14)];
-  char version[ISODCL(15, 15)];
-  char data[ISODCL(16, 2048)];
+  __u8 version[ISODCL(15, 15)];
+  __u8 data[ISODCL(16, 2048)];
 };
 struct hs_primary_descriptor {
-  char foo[ISODCL(1, 8)];
-  char type[ISODCL(9, 9)];
-  char id[ISODCL(10, 14)];
-  char version[ISODCL(15, 15)];
-  char unused1[ISODCL(16, 16)];
+  __u8 foo[ISODCL(1, 8)];
+  __u8 type[ISODCL(9, 9)];
+  __u8 id[ISODCL(10, 14)];
+  __u8 version[ISODCL(15, 15)];
+  __u8 unused1[ISODCL(16, 16)];
   char system_id[ISODCL(17, 48)];
   char volume_id[ISODCL(49, 80)];
-  char unused2[ISODCL(81, 88)];
-  char volume_space_size[ISODCL(89, 96)];
-  char unused3[ISODCL(97, 128)];
-  char volume_set_size[ISODCL(129, 132)];
-  char volume_sequence_number[ISODCL(133, 136)];
-  char logical_block_size[ISODCL(137, 140)];
-  char path_table_size[ISODCL(141, 148)];
-  char type_l_path_table[ISODCL(149, 152)];
-  char unused4[ISODCL(153, 180)];
-  char root_directory_record[ISODCL(181, 214)];
+  __u8 unused2[ISODCL(81, 88)];
+  __u8 volume_space_size[ISODCL(89, 96)];
+  __u8 unused3[ISODCL(97, 128)];
+  __u8 volume_set_size[ISODCL(129, 132)];
+  __u8 volume_sequence_number[ISODCL(133, 136)];
+  __u8 logical_block_size[ISODCL(137, 140)];
+  __u8 path_table_size[ISODCL(141, 148)];
+  __u8 type_l_path_table[ISODCL(149, 152)];
+  __u8 unused4[ISODCL(153, 180)];
+  __u8 root_directory_record[ISODCL(181, 214)];
 };
 struct iso_path_table {
-  unsigned char name_len[2];
-  char extent[4];
-  char parent[2];
+  __u8 name_len[2];
+  __u8 extent[4];
+  __u8 parent[2];
   char name[0];
 } __attribute__((packed));
 struct iso_directory_record {
-  char length[ISODCL(1, 1)];
-  char ext_attr_length[ISODCL(2, 2)];
-  char extent[ISODCL(3, 10)];
-  char size[ISODCL(11, 18)];
-  char date[ISODCL(19, 25)];
-  char flags[ISODCL(26, 26)];
-  char file_unit_size[ISODCL(27, 27)];
-  char interleave[ISODCL(28, 28)];
-  char volume_sequence_number[ISODCL(29, 32)];
-  unsigned char name_len[ISODCL(33, 33)];
+  __u8 length[ISODCL(1, 1)];
+  __u8 ext_attr_length[ISODCL(2, 2)];
+  __u8 extent[ISODCL(3, 10)];
+  __u8 size[ISODCL(11, 18)];
+  __u8 date[ISODCL(19, 25)];
+  __u8 flags[ISODCL(26, 26)];
+  __u8 file_unit_size[ISODCL(27, 27)];
+  __u8 interleave[ISODCL(28, 28)];
+  __u8 volume_sequence_number[ISODCL(29, 32)];
+  __u8 name_len[ISODCL(33, 33)];
   char name[0];
 } __attribute__((packed));
 #define ISOFS_BLOCK_BITS 11
diff --git a/libc/kernel/uapi/linux/kcov.h b/libc/kernel/uapi/linux/kcov.h
index 9688c38..40f9912 100644
--- a/libc/kernel/uapi/linux/kcov.h
+++ b/libc/kernel/uapi/linux/kcov.h
@@ -22,4 +22,11 @@
 #define KCOV_INIT_TRACE _IOR('c', 1, unsigned long)
 #define KCOV_ENABLE _IO('c', 100)
 #define KCOV_DISABLE _IO('c', 101)
+enum {
+  KCOV_TRACE_PC = 0,
+  KCOV_TRACE_CMP = 1,
+};
+#define KCOV_CMP_CONST (1 << 0)
+#define KCOV_CMP_SIZE(n) ((n) << 1)
+#define KCOV_CMP_MASK KCOV_CMP_SIZE(3)
 #endif
diff --git a/libc/kernel/uapi/linux/kfd_ioctl.h b/libc/kernel/uapi/linux/kfd_ioctl.h
index f870cd6..d4582a1 100644
--- a/libc/kernel/uapi/linux/kfd_ioctl.h
+++ b/libc/kernel/uapi/linux/kfd_ioctl.h
@@ -125,7 +125,7 @@
 #define KFD_IOC_WAIT_RESULT_COMPLETE 0
 #define KFD_IOC_WAIT_RESULT_TIMEOUT 1
 #define KFD_IOC_WAIT_RESULT_FAIL 2
-#define KFD_SIGNAL_EVENT_LIMIT 256
+#define KFD_SIGNAL_EVENT_LIMIT 4096
 struct kfd_ioctl_create_event_args {
   __u64 event_page_offset;
   __u32 event_trigger_data;
@@ -175,19 +175,19 @@
   __u32 wait_result;
 };
 struct kfd_ioctl_set_scratch_backing_va_args {
-  uint64_t va_addr;
-  uint32_t gpu_id;
-  uint32_t pad;
+  __u64 va_addr;
+  __u32 gpu_id;
+  __u32 pad;
 };
 struct kfd_ioctl_get_tile_config_args {
-  uint64_t tile_config_ptr;
-  uint64_t macro_tile_config_ptr;
-  uint32_t num_tile_configs;
-  uint32_t num_macro_tile_configs;
-  uint32_t gpu_id;
-  uint32_t gb_addr_config;
-  uint32_t num_banks;
-  uint32_t num_ranks;
+  __u64 tile_config_ptr;
+  __u64 macro_tile_config_ptr;
+  __u32 num_tile_configs;
+  __u32 num_macro_tile_configs;
+  __u32 gpu_id;
+  __u32 gb_addr_config;
+  __u32 num_banks;
+  __u32 num_ranks;
 };
 #define AMDKFD_IOCTL_BASE 'K'
 #define AMDKFD_IO(nr) _IO(AMDKFD_IOCTL_BASE, nr)
diff --git a/libc/kernel/uapi/linux/kvm.h b/libc/kernel/uapi/linux/kvm.h
index 6bd4701..d04832a 100644
--- a/libc/kernel/uapi/linux/kvm.h
+++ b/libc/kernel/uapi/linux/kvm.h
@@ -728,6 +728,9 @@
 #define KVM_CAP_PPC_SMT_POSSIBLE 147
 #define KVM_CAP_HYPERV_SYNIC2 148
 #define KVM_CAP_HYPERV_VP_INDEX 149
+#define KVM_CAP_S390_AIS_MIGRATION 150
+#define KVM_CAP_PPC_GET_CPU_CHAR 151
+#define KVM_CAP_S390_BPB 152
 #ifdef KVM_CAP_IRQ_ROUTING
 struct kvm_irq_routing_irqchip {
   __u32 irqchip;
@@ -966,6 +969,7 @@
 #define KVM_PPC_RESIZE_HPT_COMMIT _IOR(KVMIO, 0xae, struct kvm_ppc_resize_hpt)
 #define KVM_PPC_CONFIGURE_V3_MMU _IOW(KVMIO, 0xaf, struct kvm_ppc_mmuv3_cfg)
 #define KVM_PPC_GET_RMMU_INFO _IOW(KVMIO, 0xb0, struct kvm_ppc_rmmu_info)
+#define KVM_PPC_GET_CPU_CHAR _IOR(KVMIO, 0xb1, struct kvm_ppc_cpu_char)
 #define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device)
 #define KVM_SET_DEVICE_ATTR _IOW(KVMIO, 0xe1, struct kvm_device_attr)
 #define KVM_GET_DEVICE_ATTR _IOW(KVMIO, 0xe2, struct kvm_device_attr)
diff --git a/libc/kernel/uapi/linux/libc-compat.h b/libc/kernel/uapi/linux/libc-compat.h
index e5a2b03..c9a8b74 100644
--- a/libc/kernel/uapi/linux/libc-compat.h
+++ b/libc/kernel/uapi/linux/libc-compat.h
@@ -90,31 +90,86 @@
 #define __UAPI_DEF_XATTR 1
 #endif
 #else
+#ifndef __UAPI_DEF_IF_IFCONF
 #define __UAPI_DEF_IF_IFCONF 1
+#endif
+#ifndef __UAPI_DEF_IF_IFMAP
 #define __UAPI_DEF_IF_IFMAP 1
+#endif
+#ifndef __UAPI_DEF_IF_IFNAMSIZ
 #define __UAPI_DEF_IF_IFNAMSIZ 1
+#endif
+#ifndef __UAPI_DEF_IF_IFREQ
 #define __UAPI_DEF_IF_IFREQ 1
+#endif
+#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS
 #define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1
+#endif
+#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
 #define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
+#endif
+#ifndef __UAPI_DEF_IN_ADDR
 #define __UAPI_DEF_IN_ADDR 1
+#endif
+#ifndef __UAPI_DEF_IN_IPPROTO
 #define __UAPI_DEF_IN_IPPROTO 1
+#endif
+#ifndef __UAPI_DEF_IN_PKTINFO
 #define __UAPI_DEF_IN_PKTINFO 1
+#endif
+#ifndef __UAPI_DEF_IP_MREQ
 #define __UAPI_DEF_IP_MREQ 1
+#endif
+#ifndef __UAPI_DEF_SOCKADDR_IN
 #define __UAPI_DEF_SOCKADDR_IN 1
+#endif
+#ifndef __UAPI_DEF_IN_CLASS
 #define __UAPI_DEF_IN_CLASS 1
+#endif
+#ifndef __UAPI_DEF_IN6_ADDR
 #define __UAPI_DEF_IN6_ADDR 1
+#endif
+#ifndef __UAPI_DEF_IN6_ADDR_ALT
 #define __UAPI_DEF_IN6_ADDR_ALT 1
+#endif
+#ifndef __UAPI_DEF_SOCKADDR_IN6
 #define __UAPI_DEF_SOCKADDR_IN6 1
+#endif
+#ifndef __UAPI_DEF_IPV6_MREQ
 #define __UAPI_DEF_IPV6_MREQ 1
+#endif
+#ifndef __UAPI_DEF_IPPROTO_V6
 #define __UAPI_DEF_IPPROTO_V6 1
+#endif
+#ifndef __UAPI_DEF_IPV6_OPTIONS
 #define __UAPI_DEF_IPV6_OPTIONS 1
+#endif
+#ifndef __UAPI_DEF_IN6_PKTINFO
 #define __UAPI_DEF_IN6_PKTINFO 1
+#endif
+#ifndef __UAPI_DEF_IP6_MTUINFO
 #define __UAPI_DEF_IP6_MTUINFO 1
+#endif
+#ifndef __UAPI_DEF_SOCKADDR_IPX
 #define __UAPI_DEF_SOCKADDR_IPX 1
+#endif
+#ifndef __UAPI_DEF_IPX_ROUTE_DEFINITION
 #define __UAPI_DEF_IPX_ROUTE_DEFINITION 1
+#endif
+#ifndef __UAPI_DEF_IPX_INTERFACE_DEFINITION
 #define __UAPI_DEF_IPX_INTERFACE_DEFINITION 1
+#endif
+#ifndef __UAPI_DEF_IPX_CONFIG_DATA
 #define __UAPI_DEF_IPX_CONFIG_DATA 1
+#endif
+#ifndef __UAPI_DEF_IPX_ROUTE_DEF
 #define __UAPI_DEF_IPX_ROUTE_DEF 1
+#endif
+#ifndef __UAPI_DEF_XATTR
 #define __UAPI_DEF_XATTR 1
 #endif
 #endif
+#ifndef __UAPI_DEF_ETHHDR
+#define __UAPI_DEF_ETHHDR 1
+#endif
+#endif
diff --git a/libc/kernel/uapi/linux/magic.h b/libc/kernel/uapi/linux/magic.h
index 6e0ddf7..68b4c65 100644
--- a/libc/kernel/uapi/linux/magic.h
+++ b/libc/kernel/uapi/linux/magic.h
@@ -61,6 +61,7 @@
 #define OPENPROM_SUPER_MAGIC 0x9fa1
 #define QNX4_SUPER_MAGIC 0x002f
 #define QNX6_SUPER_MAGIC 0x68191122
+#define AFS_FS_MAGIC 0x6B414653
 #define REISERFS_SUPER_MAGIC 0x52654973
 #define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"
 #define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
diff --git a/libc/kernel/uapi/linux/netfilter/nf_conntrack_common.h b/libc/kernel/uapi/linux/netfilter/nf_conntrack_common.h
index 5192a54..0d35c15 100644
--- a/libc/kernel/uapi/linux/netfilter/nf_conntrack_common.h
+++ b/libc/kernel/uapi/linux/netfilter/nf_conntrack_common.h
@@ -30,7 +30,7 @@
 };
 #define NF_CT_STATE_INVALID_BIT (1 << 0)
 #define NF_CT_STATE_BIT(ctinfo) (1 << ((ctinfo) % IP_CT_IS_REPLY + 1))
-#define NF_CT_STATE_UNTRACKED_BIT (1 << (IP_CT_UNTRACKED + 1))
+#define NF_CT_STATE_UNTRACKED_BIT (1 << 6)
 enum ip_conntrack_status {
   IPS_EXPECTED_BIT = 0,
   IPS_EXPECTED = (1 << IPS_EXPECTED_BIT),
diff --git a/libc/kernel/uapi/linux/nfc.h b/libc/kernel/uapi/linux/nfc.h
index e212b31..72e3520 100644
--- a/libc/kernel/uapi/linux/nfc.h
+++ b/libc/kernel/uapi/linux/nfc.h
@@ -54,6 +54,7 @@
   NFC_CMD_SE_IO,
   NFC_CMD_ACTIVATE_TARGET,
   NFC_CMD_VENDOR,
+  NFC_CMD_DEACTIVATE_TARGET,
   __NFC_CMD_AFTER_LAST
 };
 #define NFC_CMD_MAX (__NFC_CMD_AFTER_LAST - 1)
diff --git a/libc/kernel/uapi/linux/nl80211.h b/libc/kernel/uapi/linux/nl80211.h
index bb9a835..ebf9448 100644
--- a/libc/kernel/uapi/linux/nl80211.h
+++ b/libc/kernel/uapi/linux/nl80211.h
@@ -158,6 +158,8 @@
   NL80211_CMD_UPDATE_CONNECT_PARAMS,
   NL80211_CMD_SET_PMK,
   NL80211_CMD_DEL_PMK,
+  NL80211_CMD_PORT_AUTHORIZED,
+  NL80211_CMD_RELOAD_REGDB,
   __NL80211_CMD_AFTER_LAST,
   NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1
 };
@@ -904,6 +906,7 @@
 enum nl80211_mfp {
   NL80211_MFP_NO,
   NL80211_MFP_REQUIRED,
+  NL80211_MFP_OPTIONAL,
 };
 enum nl80211_wpa_versions {
   NL80211_WPA_VERSION_1 = 1 << 0,
@@ -1194,6 +1197,11 @@
   NL80211_EXT_FEATURE_FILS_SK_OFFLOAD,
   NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK,
   NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X,
+  NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME,
+  NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP,
+  NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE,
+  NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION,
+  NL80211_EXT_FEATURE_MFP_OPTIONAL,
   NUM_NL80211_EXT_FEATURES,
   MAX_NL80211_EXT_FEATURES = NUM_NL80211_EXT_FEATURES - 1
 };
@@ -1218,6 +1226,10 @@
   NL80211_SCAN_FLAG_FLUSH = 1 << 1,
   NL80211_SCAN_FLAG_AP = 1 << 2,
   NL80211_SCAN_FLAG_RANDOM_ADDR = 1 << 3,
+  NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME = 1 << 4,
+  NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP = 1 << 5,
+  NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE = 1 << 6,
+  NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION = 1 << 7,
 };
 enum nl80211_acl_policy {
   NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED,
diff --git a/libc/kernel/uapi/linux/openvswitch.h b/libc/kernel/uapi/linux/openvswitch.h
index 7247171..bea44d0 100644
--- a/libc/kernel/uapi/linux/openvswitch.h
+++ b/libc/kernel/uapi/linux/openvswitch.h
@@ -123,6 +123,8 @@
   OVS_VPORT_ATTR_UPCALL_PID,
   OVS_VPORT_ATTR_STATS,
   OVS_VPORT_ATTR_PAD,
+  OVS_VPORT_ATTR_IFINDEX,
+  OVS_VPORT_ATTR_NETNSID,
   __OVS_VPORT_ATTR_MAX
 };
 #define OVS_VPORT_ATTR_MAX (__OVS_VPORT_ATTR_MAX - 1)
@@ -182,6 +184,7 @@
   OVS_KEY_ATTR_CT_LABELS,
   OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4,
   OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6,
+  OVS_KEY_ATTR_NSH,
   __OVS_KEY_ATTR_MAX
 };
 #define OVS_KEY_ATTR_MAX (__OVS_KEY_ATTR_MAX - 1)
@@ -298,6 +301,25 @@
   __be16 dst_port;
   __u8 ipv6_proto;
 };
+enum ovs_nsh_key_attr {
+  OVS_NSH_KEY_ATTR_UNSPEC,
+  OVS_NSH_KEY_ATTR_BASE,
+  OVS_NSH_KEY_ATTR_MD1,
+  OVS_NSH_KEY_ATTR_MD2,
+  __OVS_NSH_KEY_ATTR_MAX
+};
+#define OVS_NSH_KEY_ATTR_MAX (__OVS_NSH_KEY_ATTR_MAX - 1)
+struct ovs_nsh_key_base {
+  __u8 flags;
+  __u8 ttl;
+  __u8 mdtype;
+  __u8 np;
+  __be32 path_hdr;
+};
+#define NSH_MD1_CONTEXT_SIZE 4
+struct ovs_nsh_key_md1 {
+  __be32 context[NSH_MD1_CONTEXT_SIZE];
+};
 enum ovs_flow_attr {
   OVS_FLOW_ATTR_UNSPEC,
   OVS_FLOW_ATTR_KEY,
@@ -398,7 +420,50 @@
   OVS_ACTION_ATTR_TRUNC,
   OVS_ACTION_ATTR_PUSH_ETH,
   OVS_ACTION_ATTR_POP_ETH,
+  OVS_ACTION_ATTR_CT_CLEAR,
+  OVS_ACTION_ATTR_PUSH_NSH,
+  OVS_ACTION_ATTR_POP_NSH,
+  OVS_ACTION_ATTR_METER,
   __OVS_ACTION_ATTR_MAX,
 };
 #define OVS_ACTION_ATTR_MAX (__OVS_ACTION_ATTR_MAX - 1)
+#define OVS_METER_FAMILY "ovs_meter"
+#define OVS_METER_MCGROUP "ovs_meter"
+#define OVS_METER_VERSION 0x1
+enum ovs_meter_cmd {
+  OVS_METER_CMD_UNSPEC,
+  OVS_METER_CMD_FEATURES,
+  OVS_METER_CMD_SET,
+  OVS_METER_CMD_DEL,
+  OVS_METER_CMD_GET
+};
+enum ovs_meter_attr {
+  OVS_METER_ATTR_UNSPEC,
+  OVS_METER_ATTR_ID,
+  OVS_METER_ATTR_KBPS,
+  OVS_METER_ATTR_STATS,
+  OVS_METER_ATTR_BANDS,
+  OVS_METER_ATTR_USED,
+  OVS_METER_ATTR_CLEAR,
+  OVS_METER_ATTR_MAX_METERS,
+  OVS_METER_ATTR_MAX_BANDS,
+  OVS_METER_ATTR_PAD,
+  __OVS_METER_ATTR_MAX
+};
+#define OVS_METER_ATTR_MAX (__OVS_METER_ATTR_MAX - 1)
+enum ovs_band_attr {
+  OVS_BAND_ATTR_UNSPEC,
+  OVS_BAND_ATTR_TYPE,
+  OVS_BAND_ATTR_RATE,
+  OVS_BAND_ATTR_BURST,
+  OVS_BAND_ATTR_STATS,
+  __OVS_BAND_ATTR_MAX
+};
+#define OVS_BAND_ATTR_MAX (__OVS_BAND_ATTR_MAX - 1)
+enum ovs_meter_band_type {
+  OVS_METER_BAND_TYPE_UNSPEC,
+  OVS_METER_BAND_TYPE_DROP,
+  __OVS_METER_BAND_TYPE_MAX
+};
+#define OVS_METER_BAND_TYPE_MAX (__OVS_METER_BAND_TYPE_MAX - 1)
 #endif
diff --git a/libc/kernel/uapi/linux/pci_regs.h b/libc/kernel/uapi/linux/pci_regs.h
index c7f8381..148f2b4 100644
--- a/libc/kernel/uapi/linux/pci_regs.h
+++ b/libc/kernel/uapi/linux/pci_regs.h
@@ -640,6 +640,7 @@
 #define PCI_ERR_ROOT_FIRST_FATAL 0x00000010
 #define PCI_ERR_ROOT_NONFATAL_RCV 0x00000020
 #define PCI_ERR_ROOT_FATAL_RCV 0x00000040
+#define PCI_ERR_ROOT_AER_IRQ 0xf8000000
 #define PCI_ERR_ROOT_ERR_SRC 52
 #define PCI_VC_PORT_CAP1 4
 #define PCI_VC_CAP1_EVCC 0x00000007
@@ -799,9 +800,13 @@
 #define PCI_SATA_REGS_INLINE 0xF
 #define PCI_SATA_SIZEOF_SHORT 8
 #define PCI_SATA_SIZEOF_LONG 16
+#define PCI_REBAR_CAP 4
+#define PCI_REBAR_CAP_SIZES 0x00FFFFF0
 #define PCI_REBAR_CTRL 8
-#define PCI_REBAR_CTRL_NBAR_MASK (7 << 5)
+#define PCI_REBAR_CTRL_BAR_IDX 0x00000007
+#define PCI_REBAR_CTRL_NBAR_MASK 0x000000E0
 #define PCI_REBAR_CTRL_NBAR_SHIFT 5
+#define PCI_REBAR_CTRL_BAR_SIZE 0x00001F00
 #define PCI_DPA_CAP 4
 #define PCI_DPA_CAP_SUBSTATE_MASK 0x1F
 #define PCI_DPA_BASE_SIZEOF 16
@@ -814,6 +819,7 @@
 #define PCI_TPH_CAP_ST_SHIFT 16
 #define PCI_TPH_BASE_SIZEOF 12
 #define PCI_EXP_DPC_CAP 4
+#define PCI_EXP_DPC_IRQ 0x1f
 #define PCI_EXP_DPC_CAP_RP_EXT 0x20
 #define PCI_EXP_DPC_CAP_POISONED_TLP 0x40
 #define PCI_EXP_DPC_CAP_SW_TRIGGER 0x80
@@ -842,17 +848,23 @@
 #define PCI_PTM_CTRL 0x08
 #define PCI_PTM_CTRL_ENABLE 0x00000001
 #define PCI_PTM_CTRL_ROOT 0x00000002
-#define PCI_L1SS_CAP 4
-#define PCI_L1SS_CAP_PCIPM_L1_2 1
-#define PCI_L1SS_CAP_PCIPM_L1_1 2
-#define PCI_L1SS_CAP_ASPM_L1_2 4
-#define PCI_L1SS_CAP_ASPM_L1_1 8
-#define PCI_L1SS_CAP_L1_PM_SS 16
-#define PCI_L1SS_CTL1 8
-#define PCI_L1SS_CTL1_PCIPM_L1_2 1
-#define PCI_L1SS_CTL1_PCIPM_L1_1 2
-#define PCI_L1SS_CTL1_ASPM_L1_2 4
-#define PCI_L1SS_CTL1_ASPM_L1_1 8
-#define PCI_L1SS_CTL1_L1SS_MASK 0x0000000F
-#define PCI_L1SS_CTL2 0xC
+#define PCI_L1SS_CAP 0x04
+#define PCI_L1SS_CAP_PCIPM_L1_2 0x00000001
+#define PCI_L1SS_CAP_PCIPM_L1_1 0x00000002
+#define PCI_L1SS_CAP_ASPM_L1_2 0x00000004
+#define PCI_L1SS_CAP_ASPM_L1_1 0x00000008
+#define PCI_L1SS_CAP_L1_PM_SS 0x00000010
+#define PCI_L1SS_CAP_CM_RESTORE_TIME 0x0000ff00
+#define PCI_L1SS_CAP_P_PWR_ON_SCALE 0x00030000
+#define PCI_L1SS_CAP_P_PWR_ON_VALUE 0x00f80000
+#define PCI_L1SS_CTL1 0x08
+#define PCI_L1SS_CTL1_PCIPM_L1_2 0x00000001
+#define PCI_L1SS_CTL1_PCIPM_L1_1 0x00000002
+#define PCI_L1SS_CTL1_ASPM_L1_2 0x00000004
+#define PCI_L1SS_CTL1_ASPM_L1_1 0x00000008
+#define PCI_L1SS_CTL1_L1SS_MASK 0x0000000f
+#define PCI_L1SS_CTL1_CM_RESTORE_TIME 0x0000ff00
+#define PCI_L1SS_CTL1_LTR_L12_TH_VALUE 0x03ff0000
+#define PCI_L1SS_CTL1_LTR_L12_TH_SCALE 0xe0000000
+#define PCI_L1SS_CTL2 0x0c
 #endif
diff --git a/libc/kernel/uapi/linux/perf_event.h b/libc/kernel/uapi/linux/perf_event.h
index 326827e..97a2e99 100644
--- a/libc/kernel/uapi/linux/perf_event.h
+++ b/libc/kernel/uapi/linux/perf_event.h
@@ -329,6 +329,7 @@
 #define PERF_AUX_FLAG_TRUNCATED 0x01
 #define PERF_AUX_FLAG_OVERWRITE 0x02
 #define PERF_AUX_FLAG_PARTIAL 0x04
+#define PERF_AUX_FLAG_COLLISION 0x08
 #define PERF_FLAG_FD_NO_GROUP (1UL << 0)
 #define PERF_FLAG_FD_OUTPUT (1UL << 1)
 #define PERF_FLAG_PID_CGROUP (1UL << 2)
diff --git a/libc/kernel/uapi/linux/pkt_sched.h b/libc/kernel/uapi/linux/pkt_sched.h
index 7d3ff96..a3f2adf 100644
--- a/libc/kernel/uapi/linux/pkt_sched.h
+++ b/libc/kernel/uapi/linux/pkt_sched.h
@@ -49,6 +49,7 @@
 #define TC_H_ROOT (0xFFFFFFFFU)
 #define TC_H_INGRESS (0xFFFFFFF1U)
 #define TC_H_CLSACT TC_H_INGRESS
+#define TC_H_MIN_PRIORITY 0xFFE0U
 #define TC_H_MIN_INGRESS 0xFFF2U
 #define TC_H_MIN_EGRESS 0xFFF3U
 enum tc_link_layer {
@@ -403,6 +404,9 @@
   TCA_NETEM_ECN,
   TCA_NETEM_RATE64,
   TCA_NETEM_PAD,
+  TCA_NETEM_LATENCY64,
+  TCA_NETEM_JITTER64,
+  TCA_NETEM_SLOT,
   __TCA_NETEM_MAX,
 };
 #define TCA_NETEM_MAX (__TCA_NETEM_MAX - 1)
@@ -433,6 +437,12 @@
   __u32 cell_size;
   __s32 cell_overhead;
 };
+struct tc_netem_slot {
+  __s64 min_delay;
+  __s64 max_delay;
+  __s32 max_packets;
+  __s32 max_bytes;
+};
 enum {
   NETEM_LOSS_UNSPEC,
   NETEM_LOSS_GI,
@@ -472,6 +482,18 @@
   __TC_MQPRIO_HW_OFFLOAD_MAX
 };
 #define TC_MQPRIO_HW_OFFLOAD_MAX (__TC_MQPRIO_HW_OFFLOAD_MAX - 1)
+enum {
+  TC_MQPRIO_MODE_DCB,
+  TC_MQPRIO_MODE_CHANNEL,
+  __TC_MQPRIO_MODE_MAX
+};
+#define __TC_MQPRIO_MODE_MAX (__TC_MQPRIO_MODE_MAX - 1)
+enum {
+  TC_MQPRIO_SHAPER_DCB,
+  TC_MQPRIO_SHAPER_BW_RATE,
+  __TC_MQPRIO_SHAPER_MAX
+};
+#define __TC_MQPRIO_SHAPER_MAX (__TC_MQPRIO_SHAPER_MAX - 1)
 struct tc_mqprio_qopt {
   __u8 num_tc;
   __u8 prio_tc_map[TC_QOPT_BITMASK + 1];
@@ -479,6 +501,19 @@
   __u16 count[TC_QOPT_MAX_QUEUE];
   __u16 offset[TC_QOPT_MAX_QUEUE];
 };
+#define TC_MQPRIO_F_MODE 0x1
+#define TC_MQPRIO_F_SHAPER 0x2
+#define TC_MQPRIO_F_MIN_RATE 0x4
+#define TC_MQPRIO_F_MAX_RATE 0x8
+enum {
+  TCA_MQPRIO_UNSPEC,
+  TCA_MQPRIO_MODE,
+  TCA_MQPRIO_SHAPER,
+  TCA_MQPRIO_MIN_RATE64,
+  TCA_MQPRIO_MAX_RATE64,
+  __TCA_MQPRIO_MAX,
+};
+#define TCA_MQPRIO_MAX (__TCA_MQPRIO_MAX - 1)
 enum {
   TCA_SFB_UNSPEC,
   TCA_SFB_PARMS,
@@ -654,4 +689,18 @@
   __u32 maxq;
   __u32 ecn_mark;
 };
+struct tc_cbs_qopt {
+  __u8 offload;
+  __u8 _pad[3];
+  __s32 hicredit;
+  __s32 locredit;
+  __s32 idleslope;
+  __s32 sendslope;
+};
+enum {
+  TCA_CBS_UNSPEC,
+  TCA_CBS_PARMS,
+  __TCA_CBS_MAX,
+};
+#define TCA_CBS_MAX (__TCA_CBS_MAX - 1)
 #endif
diff --git a/libc/kernel/uapi/linux/prctl.h b/libc/kernel/uapi/linux/prctl.h
index a30fe17..55098f5 100644
--- a/libc/kernel/uapi/linux/prctl.h
+++ b/libc/kernel/uapi/linux/prctl.h
@@ -129,4 +129,9 @@
 #define PR_CAP_AMBIENT_RAISE 2
 #define PR_CAP_AMBIENT_LOWER 3
 #define PR_CAP_AMBIENT_CLEAR_ALL 4
+#define PR_SVE_SET_VL 50
+#define PR_SVE_SET_VL_ONEXEC (1 << 18)
+#define PR_SVE_GET_VL 51
+#define PR_SVE_VL_LEN_MASK 0xffff
+#define PR_SVE_VL_INHERIT (1 << 17)
 #endif
diff --git a/libc/kernel/uapi/linux/qrtr.h b/libc/kernel/uapi/linux/qrtr.h
index 4040b4c..c0a4c72 100644
--- a/libc/kernel/uapi/linux/qrtr.h
+++ b/libc/kernel/uapi/linux/qrtr.h
@@ -20,9 +20,39 @@
 #define _LINUX_QRTR_H
 #include <linux/socket.h>
 #include <linux/types.h>
+#define QRTR_NODE_BCAST 0xffffffffu
+#define QRTR_PORT_CTRL 0xfffffffeu
 struct sockaddr_qrtr {
   __kernel_sa_family_t sq_family;
   __u32 sq_node;
   __u32 sq_port;
 };
+enum qrtr_pkt_type {
+  QRTR_TYPE_DATA = 1,
+  QRTR_TYPE_HELLO = 2,
+  QRTR_TYPE_BYE = 3,
+  QRTR_TYPE_NEW_SERVER = 4,
+  QRTR_TYPE_DEL_SERVER = 5,
+  QRTR_TYPE_DEL_CLIENT = 6,
+  QRTR_TYPE_RESUME_TX = 7,
+  QRTR_TYPE_EXIT = 8,
+  QRTR_TYPE_PING = 9,
+  QRTR_TYPE_NEW_LOOKUP = 10,
+  QRTR_TYPE_DEL_LOOKUP = 11,
+};
+struct qrtr_ctrl_pkt {
+  __le32 cmd;
+  union {
+    struct {
+      __le32 service;
+      __le32 instance;
+      __le32 node;
+      __le32 port;
+    } server;
+    struct {
+      __le32 node;
+      __le32 port;
+    } client;
+  };
+} __packed;
 #endif
diff --git a/libc/kernel/uapi/linux/rtnetlink.h b/libc/kernel/uapi/linux/rtnetlink.h
index c363e34..80ba16e 100644
--- a/libc/kernel/uapi/linux/rtnetlink.h
+++ b/libc/kernel/uapi/linux/rtnetlink.h
@@ -318,6 +318,8 @@
 #define RTAX_QUICKACK RTAX_QUICKACK
   RTAX_CC_ALGO,
 #define RTAX_CC_ALGO RTAX_CC_ALGO
+  RTAX_FASTOPEN_NO_COOKIE,
+#define RTAX_FASTOPEN_NO_COOKIE RTAX_FASTOPEN_NO_COOKIE
   __RTAX_MAX
 };
 #define RTAX_MAX (__RTAX_MAX - 1)
@@ -402,6 +404,7 @@
   TCA_PAD,
   TCA_DUMP_INVISIBLE,
   TCA_CHAIN,
+  TCA_HW_OFFLOAD,
   __TCA_MAX
 };
 #define TCA_MAX (__TCA_MAX - 1)
diff --git a/libc/kernel/uapi/linux/rxrpc.h b/libc/kernel/uapi/linux/rxrpc.h
index b8b7b04..1690111 100644
--- a/libc/kernel/uapi/linux/rxrpc.h
+++ b/libc/kernel/uapi/linux/rxrpc.h
@@ -22,12 +22,12 @@
 #include <linux/in.h>
 #include <linux/in6.h>
 struct sockaddr_rxrpc {
-  sa_family_t srx_family;
-  u16 srx_service;
-  u16 transport_type;
-  u16 transport_len;
+  __kernel_sa_family_t srx_family;
+  __u16 srx_service;
+  __u16 transport_type;
+  __u16 transport_len;
   union {
-    sa_family_t family;
+    __kernel_sa_family_t family;
     struct sockaddr_in sin;
     struct sockaddr_in6 sin6;
   } transport;
@@ -50,6 +50,7 @@
   RXRPC_EXCLUSIVE_CALL = 10,
   RXRPC_UPGRADE_SERVICE = 11,
   RXRPC_TX_LENGTH = 12,
+  RXRPC_SET_CALL_TIMEOUT = 13,
   RXRPC__SUPPORTED
 };
 #define RXRPC_SECURITY_PLAIN 0
diff --git a/libc/kernel/uapi/linux/sctp.h b/libc/kernel/uapi/linux/sctp.h
index 9a55459..cc714ff 100644
--- a/libc/kernel/uapi/linux/sctp.h
+++ b/libc/kernel/uapi/linux/sctp.h
@@ -77,6 +77,8 @@
 #define SCTP_RESET_ASSOC 120
 #define SCTP_ADD_STREAMS 121
 #define SCTP_SOCKOPT_PEELOFF_FLAGS 122
+#define SCTP_STREAM_SCHEDULER 123
+#define SCTP_STREAM_SCHEDULER_VALUE 124
 #define SCTP_PR_SCTP_NONE 0x0000
 #define SCTP_PR_SCTP_TTL 0x0010
 #define SCTP_PR_SCTP_RTX 0x0020
@@ -443,6 +445,11 @@
   sctp_assoc_t assoc_id;
   uint32_t assoc_value;
 };
+struct sctp_stream_value {
+  sctp_assoc_t assoc_id;
+  uint16_t stream_id;
+  uint16_t stream_value;
+};
 struct sctp_paddrinfo {
   sctp_assoc_t spinfo_assoc_id;
   struct sockaddr_storage spinfo_address;
@@ -616,4 +623,10 @@
   uint16_t sas_instrms;
   uint16_t sas_outstrms;
 };
+enum sctp_sched_type {
+  SCTP_SS_FCFS,
+  SCTP_SS_PRIO,
+  SCTP_SS_RR,
+  SCTP_SS_MAX = SCTP_SS_RR
+};
 #endif
diff --git a/libc/kernel/uapi/linux/seg6.h b/libc/kernel/uapi/linux/seg6.h
index 6f7b8dd..f180485 100644
--- a/libc/kernel/uapi/linux/seg6.h
+++ b/libc/kernel/uapi/linux/seg6.h
@@ -27,7 +27,7 @@
   __u8 segments_left;
   __u8 first_segment;
   __u8 flags;
-  __u16 reserved;
+  __u16 tag;
   struct in6_addr segments[0];
 };
 #define SR6_FLAG1_PROTECTED (1 << 6)
diff --git a/libc/kernel/uapi/linux/serial_reg.h b/libc/kernel/uapi/linux/serial_reg.h
index 95c9956..b6648f8 100644
--- a/libc/kernel/uapi/linux/serial_reg.h
+++ b/libc/kernel/uapi/linux/serial_reg.h
@@ -113,6 +113,7 @@
 #define UART_SCR 7
 #define UART_DLL 0
 #define UART_DLM 1
+#define UART_DIV_MAX 0xFFFF
 #define UART_EFR 2
 #define UART_XR_EFR 9
 #define UART_EFR_CTS 0x80
diff --git a/libc/kernel/uapi/linux/snmp.h b/libc/kernel/uapi/linux/snmp.h
index 467a27a..b9f0c3e 100644
--- a/libc/kernel/uapi/linux/snmp.h
+++ b/libc/kernel/uapi/linux/snmp.h
@@ -158,7 +158,6 @@
   LINUX_MIB_TCPRENORECOVERY,
   LINUX_MIB_TCPSACKRECOVERY,
   LINUX_MIB_TCPSACKRENEGING,
-  LINUX_MIB_TCPFACKREORDER,
   LINUX_MIB_TCPSACKREORDER,
   LINUX_MIB_TCPRENOREORDER,
   LINUX_MIB_TCPTSREORDER,
diff --git a/libc/kernel/uapi/linux/stddef.h b/libc/kernel/uapi/linux/stddef.h
index a04729b..2a5fd95 100644
--- a/libc/kernel/uapi/linux/stddef.h
+++ b/libc/kernel/uapi/linux/stddef.h
@@ -16,7 +16,7 @@
  ***
  ****************************************************************************
  ****************************************************************************/
-#include <linux/compiler.h>
+#include <linux/compiler_types.h>
 #ifndef __always_inline
 #define __always_inline inline
 #endif
diff --git a/libc/kernel/uapi/linux/tcp.h b/libc/kernel/uapi/linux/tcp.h
index 13354e6..0bf9559 100644
--- a/libc/kernel/uapi/linux/tcp.h
+++ b/libc/kernel/uapi/linux/tcp.h
@@ -87,6 +87,8 @@
 #define TCP_FASTOPEN_CONNECT 30
 #define TCP_ULP 31
 #define TCP_MD5SIG_EXT 32
+#define TCP_FASTOPEN_KEY 33
+#define TCP_FASTOPEN_NO_COOKIE 34
 struct tcp_repair_opt {
   __u32 opt_code;
   __u32 opt_val;
diff --git a/libc/kernel/uapi/linux/tipc.h b/libc/kernel/uapi/linux/tipc.h
index cf16725..b8b4965 100644
--- a/libc/kernel/uapi/linux/tipc.h
+++ b/libc/kernel/uapi/linux/tipc.h
@@ -121,6 +121,16 @@
 #define TIPC_SOCK_RECVQ_DEPTH 132
 #define TIPC_MCAST_BROADCAST 133
 #define TIPC_MCAST_REPLICAST 134
+#define TIPC_GROUP_JOIN 135
+#define TIPC_GROUP_LEAVE 136
+#define TIPC_GROUP_LOOPBACK 0x1
+#define TIPC_GROUP_MEMBER_EVTS 0x2
+struct tipc_group_req {
+  __u32 type;
+  __u32 instance;
+  __u32 scope;
+  __u32 flags;
+};
 #define TIPC_MAX_MEDIA_NAME 16
 #define TIPC_MAX_IF_NAME 16
 #define TIPC_MAX_BEARER_NAME 32
diff --git a/libc/kernel/uapi/linux/tls.h b/libc/kernel/uapi/linux/tls.h
index 73618e0..925cf80 100644
--- a/libc/kernel/uapi/linux/tls.h
+++ b/libc/kernel/uapi/linux/tls.h
@@ -19,10 +19,6 @@
 #ifndef _UAPI_LINUX_TLS_H
 #define _UAPI_LINUX_TLS_H
 #include <linux/types.h>
-#include <asm/byteorder.h>
-#include <linux/socket.h>
-#include <linux/tcp.h>
-#include <net/tcp.h>
 #define TLS_TX 1
 #define TLS_VERSION_MINOR(ver) ((ver) & 0xFF)
 #define TLS_VERSION_MAJOR(ver) (((ver) >> 8) & 0xFF)
diff --git a/libc/kernel/uapi/linux/usb/ch9.h b/libc/kernel/uapi/linux/usb/ch9.h
index 38e7ae7..a7cf43a 100644
--- a/libc/kernel/uapi/linux/usb/ch9.h
+++ b/libc/kernel/uapi/linux/usb/ch9.h
@@ -79,6 +79,8 @@
 #define TEST_SE0_NAK 3
 #define TEST_PACKET 4
 #define TEST_FORCE_EN 5
+#define USB_STATUS_TYPE_STANDARD 0
+#define USB_STATUS_TYPE_PTM 1
 #define USB_DEVICE_U1_ENABLE 48
 #define USB_DEVICE_U2_ENABLE 49
 #define USB_DEVICE_LTM_ENABLE 50
@@ -367,6 +369,7 @@
   __le16 bmBandGroup;
   __u8 bReserved;
 } __attribute__((packed));
+#define USB_DT_USB_WIRELESS_CAP_SIZE 11
 #define USB_CAP_TYPE_EXT 2
 struct usb_ext_cap_descriptor {
   __u8 bLength;
@@ -504,6 +507,7 @@
   __u8 bDescriptorType;
   __u8 bDevCapabilityType;
 } __attribute__((packed));
+#define USB_DT_USB_PTM_ID_SIZE 3
 #define USB_DT_USB_SSP_CAP_SIZE(ssac) (16 + ssac * 4)
 struct usb_wireless_ep_comp_descriptor {
   __u8 bLength;
diff --git a/libc/kernel/uapi/linux/version.h b/libc/kernel/uapi/linux/version.h
index 7714cb7..70b6963 100644
--- a/libc/kernel/uapi/linux/version.h
+++ b/libc/kernel/uapi/linux/version.h
@@ -16,5 +16,5 @@
  ***
  ****************************************************************************
  ****************************************************************************/
-#define LINUX_VERSION_CODE 265728
+#define LINUX_VERSION_CODE 265984
 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
diff --git a/libc/kernel/uapi/linux/vm_sockets_diag.h b/libc/kernel/uapi/linux/vm_sockets_diag.h
new file mode 100644
index 0000000..2f9840b
--- /dev/null
+++ b/libc/kernel/uapi/linux/vm_sockets_diag.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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 _UAPI__VM_SOCKETS_DIAG_H__
+#define _UAPI__VM_SOCKETS_DIAG_H__
+#include <linux/types.h>
+struct vsock_diag_req {
+  __u8 sdiag_family;
+  __u8 sdiag_protocol;
+  __u16 pad;
+  __u32 vdiag_states;
+  __u32 vdiag_ino;
+  __u32 vdiag_show;
+  __u32 vdiag_cookie[2];
+};
+struct vsock_diag_msg {
+  __u8 vdiag_family;
+  __u8 vdiag_type;
+  __u8 vdiag_state;
+  __u8 vdiag_shutdown;
+  __u32 vdiag_src_cid;
+  __u32 vdiag_src_port;
+  __u32 vdiag_dst_cid;
+  __u32 vdiag_dst_port;
+  __u32 vdiag_ino;
+  __u32 vdiag_cookie[2];
+};
+#endif
diff --git a/libc/kernel/uapi/linux/wmi.h b/libc/kernel/uapi/linux/wmi.h
new file mode 100644
index 0000000..26f54d9
--- /dev/null
+++ b/libc/kernel/uapi/linux/wmi.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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 _UAPI_LINUX_WMI_H
+#define _UAPI_LINUX_WMI_H
+#include <linux/ioctl.h>
+#include <linux/types.h>
+#define WMI_IOC 'W'
+struct wmi_ioctl_buffer {
+  __u64 length;
+  __u8 data[];
+};
+struct calling_interface_buffer {
+  __u16 cmd_class;
+  __u16 cmd_select;
+  volatile __u32 input[4];
+  volatile __u32 output[4];
+} __packed;
+struct dell_wmi_extensions {
+  __u32 argattrib;
+  __u32 blength;
+  __u8 data[];
+} __packed;
+struct dell_wmi_smbios_buffer {
+  __u64 length;
+  struct calling_interface_buffer std;
+  struct dell_wmi_extensions ext;
+} __packed;
+#define CLASS_TOKEN_READ 0
+#define CLASS_TOKEN_WRITE 1
+#define SELECT_TOKEN_STD 0
+#define SELECT_TOKEN_BAT 1
+#define SELECT_TOKEN_AC 2
+#define CLASS_FLASH_INTERFACE 7
+#define SELECT_FLASH_INTERFACE 3
+#define CLASS_ADMIN_PROP 10
+#define SELECT_ADMIN_PROP 3
+#define CLASS_INFO 17
+#define SELECT_RFKILL 11
+#define SELECT_APP_REGISTRATION 3
+#define SELECT_DOCK 22
+#define CAPSULE_EN_TOKEN 0x0461
+#define CAPSULE_DIS_TOKEN 0x0462
+#define WSMT_EN_TOKEN 0x04EC
+#define WSMT_DIS_TOKEN 0x04ED
+#define DELL_WMI_SMBIOS_CMD _IOWR(WMI_IOC, 0, struct dell_wmi_smbios_buffer)
+#endif
diff --git a/libc/kernel/uapi/linux/xattr.h b/libc/kernel/uapi/linux/xattr.h
index efa99e7..7c098f4 100644
--- a/libc/kernel/uapi/linux/xattr.h
+++ b/libc/kernel/uapi/linux/xattr.h
@@ -56,6 +56,8 @@
 #define XATTR_NAME_SMACKEXEC XATTR_SECURITY_PREFIX XATTR_SMACK_EXEC
 #define XATTR_NAME_SMACKTRANSMUTE XATTR_SECURITY_PREFIX XATTR_SMACK_TRANSMUTE
 #define XATTR_NAME_SMACKMMAP XATTR_SECURITY_PREFIX XATTR_SMACK_MMAP
+#define XATTR_APPARMOR_SUFFIX "apparmor"
+#define XATTR_NAME_APPARMOR XATTR_SECURITY_PREFIX XATTR_APPARMOR_SUFFIX
 #define XATTR_CAPS_SUFFIX "capability"
 #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX
 #define XATTR_POSIX_ACL_ACCESS "posix_acl_access"
diff --git a/libc/kernel/uapi/rdma/ib_user_verbs.h b/libc/kernel/uapi/rdma/ib_user_verbs.h
index ff3ebcb..03a2fcd 100644
--- a/libc/kernel/uapi/rdma/ib_user_verbs.h
+++ b/libc/kernel/uapi/rdma/ib_user_verbs.h
@@ -75,7 +75,8 @@
   IB_USER_VERBS_EX_CMD_MODIFY_WQ,
   IB_USER_VERBS_EX_CMD_DESTROY_WQ,
   IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL,
-  IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL
+  IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL,
+  IB_USER_VERBS_EX_CMD_MODIFY_CQ
 };
 struct ib_uverbs_async_event_desc {
   __u64 element;
@@ -85,6 +86,11 @@
 struct ib_uverbs_comp_event_desc {
   __u64 cq_handle;
 };
+struct ib_uverbs_cq_moderation_caps {
+  __u16 max_cq_moderation_count;
+  __u16 max_cq_moderation_period;
+  __u32 reserved;
+};
 #define IB_USER_VERBS_CMD_COMMAND_MASK 0xff
 #define IB_USER_VERBS_CMD_FLAGS_MASK 0xff000000u
 #define IB_USER_VERBS_CMD_FLAGS_SHIFT 24
@@ -194,6 +200,7 @@
   __u32 max_wq_type_rq;
   __u32 raw_packet_caps;
   struct ib_uverbs_tm_caps tm_caps;
+  struct ib_uverbs_cq_moderation_caps cq_moderation_caps;
 };
 struct ib_uverbs_query_port {
   __u64 response;
@@ -952,5 +959,15 @@
   __u32 comp_mask;
   __u32 ind_tbl_handle;
 };
+struct ib_uverbs_cq_moderation {
+  __u16 cq_count;
+  __u16 cq_period;
+};
+struct ib_uverbs_ex_modify_cq {
+  __u32 cq_handle;
+  __u32 attr_mask;
+  struct ib_uverbs_cq_moderation attr;
+  __u32 reserved;
+};
 #define IB_DEVICE_NAME_MAX 64
 #endif
diff --git a/libc/kernel/uapi/rdma/mlx5-abi.h b/libc/kernel/uapi/rdma/mlx5-abi.h
index b51ff4e..9347cf3 100644
--- a/libc/kernel/uapi/rdma/mlx5-abi.h
+++ b/libc/kernel/uapi/rdma/mlx5-abi.h
@@ -23,6 +23,7 @@
 enum {
   MLX5_QP_FLAG_SIGNATURE = 1 << 0,
   MLX5_QP_FLAG_SCATTER_CQE = 1 << 1,
+  MLX5_QP_FLAG_TUNNEL_OFFLOADS = 1 << 2,
 };
 enum {
   MLX5_SRQ_FLAG_SIGNATURE = 1 << 0,
@@ -126,6 +127,23 @@
   __u32 sw_parsing_offloads;
   __u32 supported_qpts;
 };
+struct mlx5_ib_striding_rq_caps {
+  __u32 min_single_stride_log_num_of_bytes;
+  __u32 max_single_stride_log_num_of_bytes;
+  __u32 min_single_wqe_log_num_of_strides;
+  __u32 max_single_wqe_log_num_of_strides;
+  __u32 supported_qpts;
+  __u32 reserved;
+};
+enum mlx5_ib_query_dev_resp_flags {
+  MLX5_IB_QUERY_DEV_RESP_FLAGS_CQE_128B_COMP = 1 << 0,
+  MLX5_IB_QUERY_DEV_RESP_FLAGS_CQE_128B_PAD = 1 << 1,
+};
+enum mlx5_ib_tunnel_offloads {
+  MLX5_IB_TUNNELED_OFFLOADS_VXLAN = 1 << 0,
+  MLX5_IB_TUNNELED_OFFLOADS_GRE = 1 << 1,
+  MLX5_IB_TUNNELED_OFFLOADS_GENEVE = 1 << 2
+};
 struct mlx5_ib_query_device_resp {
   __u32 comp_mask;
   __u32 response_length;
@@ -134,8 +152,14 @@
   struct mlx5_ib_cqe_comp_caps cqe_comp_caps;
   struct mlx5_packet_pacing_caps packet_pacing_caps;
   __u32 mlx5_ib_support_multi_pkt_send_wqes;
-  __u32 reserved;
+  __u32 flags;
   struct mlx5_ib_sw_parsing_caps sw_parsing_caps;
+  struct mlx5_ib_striding_rq_caps striding_rq_caps;
+  __u32 tunnel_offloads_caps;
+  __u32 reserved;
+};
+enum mlx5_ib_create_cq_flags {
+  MLX5_IB_CREATE_CQ_FLAGS_CQE_128B_PAD = 1 << 0,
 };
 struct mlx5_ib_create_cq {
   __u64 buf_addr;
@@ -143,7 +167,7 @@
   __u32 cqe_size;
   __u8 cqe_comp_en;
   __u8 cqe_comp_res_format;
-  __u16 reserved;
+  __u16 flags;
 };
 struct mlx5_ib_create_cq_resp {
   __u32 cqn;
@@ -189,7 +213,8 @@
   MLX5_RX_HASH_SRC_PORT_TCP = 1 << 4,
   MLX5_RX_HASH_DST_PORT_TCP = 1 << 5,
   MLX5_RX_HASH_SRC_PORT_UDP = 1 << 6,
-  MLX5_RX_HASH_DST_PORT_UDP = 1 << 7
+  MLX5_RX_HASH_DST_PORT_UDP = 1 << 7,
+  MLX5_RX_HASH_INNER = 1 << 31
 };
 struct mlx5_ib_create_qp_rss {
   __u64 rx_hash_fields_mask;
@@ -198,7 +223,7 @@
   __u8 reserved[6];
   __u8 rx_hash_key[128];
   __u32 comp_mask;
-  __u32 reserved1;
+  __u32 flags;
 };
 struct mlx5_ib_create_qp_resp {
   __u32 bfreg_index;
@@ -209,6 +234,9 @@
   __u8 reserved1;
   __u16 reserved2;
 };
+enum mlx5_ib_create_wq_mask {
+  MLX5_IB_CREATE_WQ_STRIDING_RQ = (1 << 0),
+};
 struct mlx5_ib_create_wq {
   __u64 buf_addr;
   __u64 db_addr;
@@ -217,7 +245,9 @@
   __u32 user_index;
   __u32 flags;
   __u32 comp_mask;
-  __u32 reserved;
+  __u32 single_stride_log_num_of_bytes;
+  __u32 single_wqe_log_num_of_strides;
+  __u32 two_byte_shift_en;
 };
 struct mlx5_ib_create_ah_resp {
   __u32 response_length;
diff --git a/libc/kernel/uapi/rdma/vmw_pvrdma-abi.h b/libc/kernel/uapi/rdma/vmw_pvrdma-abi.h
index 2062366..7c13680 100644
--- a/libc/kernel/uapi/rdma/vmw_pvrdma-abi.h
+++ b/libc/kernel/uapi/rdma/vmw_pvrdma-abi.h
@@ -119,6 +119,8 @@
 };
 struct pvrdma_create_srq {
   __u64 buf_addr;
+  __u32 buf_size;
+  __u32 reserved;
 };
 struct pvrdma_create_srq_resp {
   __u32 srqn;
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 1ed4ec6..19c80b7 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1321,10 +1321,17 @@
 LIBC_P { # introduced=P
   global:
     __freading;
+    __free_hook;
+    __fseterr;
     __fwriting;
+    __malloc_hook;
+    __memalign_hook;
+    __realloc_hook;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
+    epoll_pwait64;
     fexecve;
     fflush_unlocked;
     fgetc_unlocked;
@@ -1356,30 +1363,56 @@
     posix_spawnattr_getschedparam;
     posix_spawnattr_getschedpolicy;
     posix_spawnattr_getsigdefault;
+    posix_spawnattr_getsigdefault64;
     posix_spawnattr_getsigmask;
+    posix_spawnattr_getsigmask64;
     posix_spawnattr_init;
     posix_spawnattr_setflags;
     posix_spawnattr_setpgroup;
     posix_spawnattr_setschedparam;
     posix_spawnattr_setschedpolicy;
     posix_spawnattr_setsigdefault;
+    posix_spawnattr_setsigdefault64;
     posix_spawnattr_setsigmask;
+    posix_spawnattr_setsigmask64;
     posix_spawn_file_actions_addclose;
     posix_spawn_file_actions_adddup2;
     posix_spawn_file_actions_addopen;
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    ppoll64;
+    pselect64;
     pthread_attr_getinheritsched;
     pthread_attr_setinheritsched;
     pthread_mutexattr_getprotocol;
     pthread_mutexattr_setprotocol;
     pthread_setschedprio;
+    pthread_sigmask64;
     sethostent;
     setnetent;
     setprotoent;
+    sigaction64;
+    sigaddset64;
+    sigdelset64;
+    sigemptyset64;
+    sigfillset64;
+    sigismember64;
+    signalfd64;
+    sigpending64;
+    sigprocmask64;
+    sigsuspend64;
+    sigtimedwait64;
+    sigwait64;
+    sigwaitinfo64;
+    strptime_l;
     swab;
     syncfs;
+    wcsftime_l;
+    wcstod_l;
+    wcstof_l;
+    wcstol_l;
+    wcstoul_l;
 } LIBC_O;
 
 LIBC_PRIVATE {
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index f511707..cab66e6 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1241,10 +1241,17 @@
 LIBC_P { # introduced=P
   global:
     __freading;
+    __free_hook;
+    __fseterr;
     __fwriting;
+    __malloc_hook;
+    __memalign_hook;
+    __realloc_hook;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
+    epoll_pwait64;
     fexecve;
     fflush_unlocked;
     fgetc_unlocked;
@@ -1276,30 +1283,56 @@
     posix_spawnattr_getschedparam;
     posix_spawnattr_getschedpolicy;
     posix_spawnattr_getsigdefault;
+    posix_spawnattr_getsigdefault64;
     posix_spawnattr_getsigmask;
+    posix_spawnattr_getsigmask64;
     posix_spawnattr_init;
     posix_spawnattr_setflags;
     posix_spawnattr_setpgroup;
     posix_spawnattr_setschedparam;
     posix_spawnattr_setschedpolicy;
     posix_spawnattr_setsigdefault;
+    posix_spawnattr_setsigdefault64;
     posix_spawnattr_setsigmask;
+    posix_spawnattr_setsigmask64;
     posix_spawn_file_actions_addclose;
     posix_spawn_file_actions_adddup2;
     posix_spawn_file_actions_addopen;
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    ppoll64;
+    pselect64;
     pthread_attr_getinheritsched;
     pthread_attr_setinheritsched;
     pthread_mutexattr_getprotocol;
     pthread_mutexattr_setprotocol;
     pthread_setschedprio;
+    pthread_sigmask64;
     sethostent;
     setnetent;
     setprotoent;
+    sigaction64;
+    sigaddset64;
+    sigdelset64;
+    sigemptyset64;
+    sigfillset64;
+    sigismember64;
+    signalfd64;
+    sigpending64;
+    sigprocmask64;
+    sigsuspend64;
+    sigtimedwait64;
+    sigwait64;
+    sigwaitinfo64;
+    strptime_l;
     swab;
     syncfs;
+    wcsftime_l;
+    wcstod_l;
+    wcstof_l;
+    wcstol_l;
+    wcstoul_l;
 } LIBC_O;
 
 LIBC_PRIVATE {
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 0960560..65e4802 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1346,10 +1346,17 @@
 LIBC_P { # introduced=P
   global:
     __freading;
+    __free_hook;
+    __fseterr;
     __fwriting;
+    __malloc_hook;
+    __memalign_hook;
+    __realloc_hook;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
+    epoll_pwait64;
     fexecve;
     fflush_unlocked;
     fgetc_unlocked;
@@ -1381,30 +1388,56 @@
     posix_spawnattr_getschedparam;
     posix_spawnattr_getschedpolicy;
     posix_spawnattr_getsigdefault;
+    posix_spawnattr_getsigdefault64;
     posix_spawnattr_getsigmask;
+    posix_spawnattr_getsigmask64;
     posix_spawnattr_init;
     posix_spawnattr_setflags;
     posix_spawnattr_setpgroup;
     posix_spawnattr_setschedparam;
     posix_spawnattr_setschedpolicy;
     posix_spawnattr_setsigdefault;
+    posix_spawnattr_setsigdefault64;
     posix_spawnattr_setsigmask;
+    posix_spawnattr_setsigmask64;
     posix_spawn_file_actions_addclose;
     posix_spawn_file_actions_adddup2;
     posix_spawn_file_actions_addopen;
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    ppoll64;
+    pselect64;
     pthread_attr_getinheritsched;
     pthread_attr_setinheritsched;
     pthread_mutexattr_getprotocol;
     pthread_mutexattr_setprotocol;
     pthread_setschedprio;
+    pthread_sigmask64;
     sethostent;
     setnetent;
     setprotoent;
+    sigaction64;
+    sigaddset64;
+    sigdelset64;
+    sigemptyset64;
+    sigfillset64;
+    sigismember64;
+    signalfd64;
+    sigpending64;
+    sigprocmask64;
+    sigsuspend64;
+    sigtimedwait64;
+    sigwait64;
+    sigwaitinfo64;
+    strptime_l;
     swab;
     syncfs;
+    wcsftime_l;
+    wcstod_l;
+    wcstof_l;
+    wcstol_l;
+    wcstoul_l;
 } LIBC_O;
 
 LIBC_PRIVATE {
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index 1160f87..363a55a 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1305,10 +1305,17 @@
 LIBC_P { # introduced=P
   global:
     __freading;
+    __free_hook;
+    __fseterr;
     __fwriting;
+    __malloc_hook;
+    __memalign_hook;
+    __realloc_hook;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
+    epoll_pwait64;
     fexecve;
     fflush_unlocked;
     fgetc_unlocked;
@@ -1340,30 +1347,56 @@
     posix_spawnattr_getschedparam;
     posix_spawnattr_getschedpolicy;
     posix_spawnattr_getsigdefault;
+    posix_spawnattr_getsigdefault64;
     posix_spawnattr_getsigmask;
+    posix_spawnattr_getsigmask64;
     posix_spawnattr_init;
     posix_spawnattr_setflags;
     posix_spawnattr_setpgroup;
     posix_spawnattr_setschedparam;
     posix_spawnattr_setschedpolicy;
     posix_spawnattr_setsigdefault;
+    posix_spawnattr_setsigdefault64;
     posix_spawnattr_setsigmask;
+    posix_spawnattr_setsigmask64;
     posix_spawn_file_actions_addclose;
     posix_spawn_file_actions_adddup2;
     posix_spawn_file_actions_addopen;
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    ppoll64;
+    pselect64;
     pthread_attr_getinheritsched;
     pthread_attr_setinheritsched;
     pthread_mutexattr_getprotocol;
     pthread_mutexattr_setprotocol;
     pthread_setschedprio;
+    pthread_sigmask64;
     sethostent;
     setnetent;
     setprotoent;
+    sigaction64;
+    sigaddset64;
+    sigdelset64;
+    sigemptyset64;
+    sigfillset64;
+    sigismember64;
+    signalfd64;
+    sigpending64;
+    sigprocmask64;
+    sigsuspend64;
+    sigtimedwait64;
+    sigwait64;
+    sigwaitinfo64;
+    strptime_l;
     swab;
     syncfs;
+    wcsftime_l;
+    wcstod_l;
+    wcstof_l;
+    wcstol_l;
+    wcstoul_l;
 } LIBC_O;
 
 LIBC_PRIVATE {
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index f511707..cab66e6 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1241,10 +1241,17 @@
 LIBC_P { # introduced=P
   global:
     __freading;
+    __free_hook;
+    __fseterr;
     __fwriting;
+    __malloc_hook;
+    __memalign_hook;
+    __realloc_hook;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
+    epoll_pwait64;
     fexecve;
     fflush_unlocked;
     fgetc_unlocked;
@@ -1276,30 +1283,56 @@
     posix_spawnattr_getschedparam;
     posix_spawnattr_getschedpolicy;
     posix_spawnattr_getsigdefault;
+    posix_spawnattr_getsigdefault64;
     posix_spawnattr_getsigmask;
+    posix_spawnattr_getsigmask64;
     posix_spawnattr_init;
     posix_spawnattr_setflags;
     posix_spawnattr_setpgroup;
     posix_spawnattr_setschedparam;
     posix_spawnattr_setschedpolicy;
     posix_spawnattr_setsigdefault;
+    posix_spawnattr_setsigdefault64;
     posix_spawnattr_setsigmask;
+    posix_spawnattr_setsigmask64;
     posix_spawn_file_actions_addclose;
     posix_spawn_file_actions_adddup2;
     posix_spawn_file_actions_addopen;
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    ppoll64;
+    pselect64;
     pthread_attr_getinheritsched;
     pthread_attr_setinheritsched;
     pthread_mutexattr_getprotocol;
     pthread_mutexattr_setprotocol;
     pthread_setschedprio;
+    pthread_sigmask64;
     sethostent;
     setnetent;
     setprotoent;
+    sigaction64;
+    sigaddset64;
+    sigdelset64;
+    sigemptyset64;
+    sigfillset64;
+    sigismember64;
+    signalfd64;
+    sigpending64;
+    sigprocmask64;
+    sigsuspend64;
+    sigtimedwait64;
+    sigwait64;
+    sigwaitinfo64;
+    strptime_l;
     swab;
     syncfs;
+    wcsftime_l;
+    wcstod_l;
+    wcstof_l;
+    wcstol_l;
+    wcstoul_l;
 } LIBC_O;
 
 LIBC_PRIVATE {
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index b0b4b16..fc5e463 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1303,10 +1303,17 @@
 LIBC_P { # introduced=P
   global:
     __freading;
+    __free_hook;
+    __fseterr;
     __fwriting;
+    __malloc_hook;
+    __memalign_hook;
+    __realloc_hook;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
+    epoll_pwait64;
     fexecve;
     fflush_unlocked;
     fgetc_unlocked;
@@ -1338,30 +1345,56 @@
     posix_spawnattr_getschedparam;
     posix_spawnattr_getschedpolicy;
     posix_spawnattr_getsigdefault;
+    posix_spawnattr_getsigdefault64;
     posix_spawnattr_getsigmask;
+    posix_spawnattr_getsigmask64;
     posix_spawnattr_init;
     posix_spawnattr_setflags;
     posix_spawnattr_setpgroup;
     posix_spawnattr_setschedparam;
     posix_spawnattr_setschedpolicy;
     posix_spawnattr_setsigdefault;
+    posix_spawnattr_setsigdefault64;
     posix_spawnattr_setsigmask;
+    posix_spawnattr_setsigmask64;
     posix_spawn_file_actions_addclose;
     posix_spawn_file_actions_adddup2;
     posix_spawn_file_actions_addopen;
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    ppoll64;
+    pselect64;
     pthread_attr_getinheritsched;
     pthread_attr_setinheritsched;
     pthread_mutexattr_getprotocol;
     pthread_mutexattr_setprotocol;
     pthread_setschedprio;
+    pthread_sigmask64;
     sethostent;
     setnetent;
     setprotoent;
+    sigaction64;
+    sigaddset64;
+    sigdelset64;
+    sigemptyset64;
+    sigfillset64;
+    sigismember64;
+    signalfd64;
+    sigpending64;
+    sigprocmask64;
+    sigsuspend64;
+    sigtimedwait64;
+    sigwait64;
+    sigwaitinfo64;
+    strptime_l;
     swab;
     syncfs;
+    wcsftime_l;
+    wcstod_l;
+    wcstof_l;
+    wcstol_l;
+    wcstoul_l;
 } LIBC_O;
 
 LIBC_PRIVATE {
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index f511707..cab66e6 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1241,10 +1241,17 @@
 LIBC_P { # introduced=P
   global:
     __freading;
+    __free_hook;
+    __fseterr;
     __fwriting;
+    __malloc_hook;
+    __memalign_hook;
+    __realloc_hook;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
+    epoll_pwait64;
     fexecve;
     fflush_unlocked;
     fgetc_unlocked;
@@ -1276,30 +1283,56 @@
     posix_spawnattr_getschedparam;
     posix_spawnattr_getschedpolicy;
     posix_spawnattr_getsigdefault;
+    posix_spawnattr_getsigdefault64;
     posix_spawnattr_getsigmask;
+    posix_spawnattr_getsigmask64;
     posix_spawnattr_init;
     posix_spawnattr_setflags;
     posix_spawnattr_setpgroup;
     posix_spawnattr_setschedparam;
     posix_spawnattr_setschedpolicy;
     posix_spawnattr_setsigdefault;
+    posix_spawnattr_setsigdefault64;
     posix_spawnattr_setsigmask;
+    posix_spawnattr_setsigmask64;
     posix_spawn_file_actions_addclose;
     posix_spawn_file_actions_adddup2;
     posix_spawn_file_actions_addopen;
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    ppoll64;
+    pselect64;
     pthread_attr_getinheritsched;
     pthread_attr_setinheritsched;
     pthread_mutexattr_getprotocol;
     pthread_mutexattr_setprotocol;
     pthread_setschedprio;
+    pthread_sigmask64;
     sethostent;
     setnetent;
     setprotoent;
+    sigaction64;
+    sigaddset64;
+    sigdelset64;
+    sigemptyset64;
+    sigfillset64;
+    sigismember64;
+    signalfd64;
+    sigpending64;
+    sigprocmask64;
+    sigsuspend64;
+    sigtimedwait64;
+    sigwait64;
+    sigwaitinfo64;
+    strptime_l;
     swab;
     syncfs;
+    wcsftime_l;
+    wcstod_l;
+    wcstof_l;
+    wcstol_l;
+    wcstoul_l;
 } LIBC_O;
 
 LIBC_PRIVATE {
diff --git a/libc/malloc_debug/Android.bp b/libc/malloc_debug/Android.bp
index 06fc426..ede2431 100644
--- a/libc/malloc_debug/Android.bp
+++ b/libc/malloc_debug/Android.bp
@@ -13,7 +13,10 @@
 
     stl: "libc++_static",
 
-    whole_static_libs: ["libasync_safe", "libdemangle"],
+    whole_static_libs: [
+        "libasync_safe",
+        "libdemangle",
+    ],
 
     include_dirs: ["bionic/libc"],
 
@@ -117,7 +120,10 @@
     whole_static_libs: ["libc_malloc_debug"],
 
     local_include_dirs: ["tests"],
-    include_dirs: ["bionic/libc", "bionic/libc/async_safe/include"],
+    include_dirs: [
+        "bionic/libc",
+        "bionic/libc/async_safe/include",
+    ],
 
     shared_libs: ["libbase"],
 
diff --git a/libc/malloc_debug/BacktraceData.cpp b/libc/malloc_debug/BacktraceData.cpp
index d597280..57d8f2a 100644
--- a/libc/malloc_debug/BacktraceData.cpp
+++ b/libc/malloc_debug/BacktraceData.cpp
@@ -59,13 +59,10 @@
 bool BacktraceData::Initialize(const Config& config) {
   enabled_ = config.backtrace_enabled();
   if (config.backtrace_enable_on_signal()) {
-    struct sigaction enable_act;
-    memset(&enable_act, 0, sizeof(enable_act));
-
+    struct sigaction64 enable_act = {};
     enable_act.sa_sigaction = ToggleBacktraceEnable;
     enable_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
-    sigemptyset(&enable_act.sa_mask);
-    if (sigaction(config.backtrace_signal(), &enable_act, nullptr) != 0) {
+    if (sigaction64(config.backtrace_signal(), &enable_act, nullptr) != 0) {
       error_log("Unable to set up backtrace signal enable function: %s", strerror(errno));
       return false;
     }
@@ -73,13 +70,10 @@
              config.backtrace_signal(), getpid());
   }
 
-  struct sigaction act;
-  memset(&act, 0, sizeof(act));
-
+  struct sigaction64 act = {};
   act.sa_sigaction = EnableDump;
   act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
-  sigemptyset(&act.sa_mask);
-  if (sigaction(config.backtrace_dump_signal(), &act, nullptr) != 0) {
+  if (sigaction64(config.backtrace_dump_signal(), &act, nullptr) != 0) {
     error_log("Unable to set up backtrace dump signal function: %s", strerror(errno));
     return false;
   }
diff --git a/libc/malloc_debug/BacktraceData.h b/libc/malloc_debug/BacktraceData.h
index c8234dc..3c15348 100644
--- a/libc/malloc_debug/BacktraceData.h
+++ b/libc/malloc_debug/BacktraceData.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef DEBUG_MALLOC_BACKTRACEDATA_H
-#define DEBUG_MALLOC_BACKTRACEDATA_H
+#pragma once
 
 #include <stdint.h>
 
@@ -67,5 +66,3 @@
 
   DISALLOW_COPY_AND_ASSIGN(BacktraceData);
 };
-
-#endif // DEBUG_MALLOC_BACKTRACEDATA_H
diff --git a/libc/malloc_debug/Config.h b/libc/malloc_debug/Config.h
index 349ad77..a310e09 100644
--- a/libc/malloc_debug/Config.h
+++ b/libc/malloc_debug/Config.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef MALLOC_DEBUG_CONFIG_H
-#define MALLOC_DEBUG_CONFIG_H
+#pragma once
 
 #include <stdint.h>
 
@@ -159,5 +158,3 @@
   uint8_t front_guard_value_;
   uint8_t rear_guard_value_;
 };
-
-#endif  // MALLOC_DEBUG_CONFIG_H
diff --git a/libc/malloc_debug/DebugData.h b/libc/malloc_debug/DebugData.h
index 7228a72..9aece0b 100644
--- a/libc/malloc_debug/DebugData.h
+++ b/libc/malloc_debug/DebugData.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef DEBUG_MALLOC_DEBUGDATA_H
-#define DEBUG_MALLOC_DEBUGDATA_H
+#pragma once
 
 #include <stdint.h>
 
@@ -106,5 +105,3 @@
 };
 
 extern DebugData* g_debug;
-
-#endif // MALLOC_DEBUG_DEBUGDATA_H
diff --git a/libc/malloc_debug/FreeTrackData.h b/libc/malloc_debug/FreeTrackData.h
index 0e8c177..bd3497d 100644
--- a/libc/malloc_debug/FreeTrackData.h
+++ b/libc/malloc_debug/FreeTrackData.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef DEBUG_MALLOC_FREETRACKDATA_H
-#define DEBUG_MALLOC_FREETRACKDATA_H
+#pragma once
 
 #include <stdint.h>
 #include <pthread.h>
@@ -75,5 +74,3 @@
 
   DISALLOW_COPY_AND_ASSIGN(FreeTrackData);
 };
-
-#endif // DEBUG_MALLOC_FREETRACKDATA_H
diff --git a/libc/malloc_debug/GuardData.h b/libc/malloc_debug/GuardData.h
index ddf6ce1..7b21671 100644
--- a/libc/malloc_debug/GuardData.h
+++ b/libc/malloc_debug/GuardData.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef DEBUG_MALLOC_GUARDDATA_H
-#define DEBUG_MALLOC_GUARDDATA_H
+#pragma once
 
 #include <stdint.h>
 #include <string.h>
@@ -93,5 +92,3 @@
 
   DISALLOW_COPY_AND_ASSIGN(RearGuardData);
 };
-
-#endif // DEBUG_MALLOC_GUARDDATA_H
diff --git a/libc/malloc_debug/MapData.h b/libc/malloc_debug/MapData.h
index 895f78f..a71f96d 100644
--- a/libc/malloc_debug/MapData.h
+++ b/libc/malloc_debug/MapData.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef DEBUG_MALLOC_MAPDATA_H
-#define DEBUG_MALLOC_MAPDATA_H
+#pragma once
 
 #include <sys/cdefs.h>
 
@@ -74,5 +73,3 @@
 
   DISALLOW_COPY_AND_ASSIGN(MapData);
 };
-
-#endif  // DEBUG_MALLOC_MAPDATA_H
diff --git a/libc/malloc_debug/OptionData.h b/libc/malloc_debug/OptionData.h
index 5c2d272..3fa8e14 100644
--- a/libc/malloc_debug/OptionData.h
+++ b/libc/malloc_debug/OptionData.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef DEBUG_MALLOC_OPTIONDATA_H
-#define DEBUG_MALLOC_OPTIONDATA_H
+#pragma once
 
 // Forward Declarations
 class DebugData;
@@ -42,5 +41,3 @@
 
   DISALLOW_COPY_AND_ASSIGN(OptionData);
 };
-
-#endif // MALLOC_DEBUG_OPTIONDATA_H
diff --git a/libc/malloc_debug/README.md b/libc/malloc_debug/README.md
index b7a12a5..69d0648 100644
--- a/libc/malloc_debug/README.md
+++ b/libc/malloc_debug/README.md
@@ -23,6 +23,7 @@
 * `realloc`
 * `posix_memalign`
 * `memalign`
+* `aligned_alloc`
 * `malloc_usable_size`
 
 On 32 bit systems, these two deprecated functions are also replaced:
@@ -324,6 +325,10 @@
 
 **THREAD\_ID**: memalign pointer alignment size
 
+pointer = aligned\_alloc(alignment, size)
+
+**THREAD\_ID**: memalign pointer alignment size
+
 posix\_memalign(&pointer, alignment, size)
 
 **THREAD\_ID**: memalign pointer alignment size
diff --git a/libc/malloc_debug/README_marshmallow_and_earlier.md b/libc/malloc_debug/README_marshmallow_and_earlier.md
index 3513711..c8be656 100644
--- a/libc/malloc_debug/README_marshmallow_and_earlier.md
+++ b/libc/malloc_debug/README_marshmallow_and_earlier.md
@@ -4,10 +4,10 @@
 Malloc debug is a method of debugging native memory problems. It can help
 detect memory corruption, memory leaks, and use after free issues.
 
-This documentation describes how to enable this feature on versions of
-the Android OS, Marshmallow or older. Note: malloc debug was full of bugs
-and was not fully functional until KitKat, so using it on a version older
-than that is not guaranteed to work at all.
+This documentation describes how to enable this feature on API level
+23 or older. Note: malloc debug was full of bugs and was not fully
+functional until API level 19, so using it on a version older than that
+is not guaranteed to work at all.
 
 The documentation for malloc debug on newer versions of Android is
 [here](README.md).
diff --git a/libc/malloc_debug/RecordData.cpp b/libc/malloc_debug/RecordData.cpp
index 5a68deb..8e9c671 100644
--- a/libc/malloc_debug/RecordData.cpp
+++ b/libc/malloc_debug/RecordData.cpp
@@ -86,7 +86,7 @@
                                      old_pointer_, size_);
 }
 
-// posix_memalign, memalgin, pvalloc, valloc all recorded with this class.
+// aligned_alloc, posix_memalign, memalign, pvalloc, valloc all recorded with this class.
 MemalignEntry::MemalignEntry(void* pointer, size_t size, size_t alignment)
     : MallocEntry(pointer, size), alignment_(alignment) {
 }
@@ -179,13 +179,10 @@
 }
 
 bool RecordData::Initialize(const Config& config) {
-  struct sigaction dump_act;
-  memset(&dump_act, 0, sizeof(dump_act));
-
+  struct sigaction64 dump_act = {};
   dump_act.sa_sigaction = RecordDump;
   dump_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
-  sigemptyset(&dump_act.sa_mask);
-  if (sigaction(config.record_allocs_signal(), &dump_act, nullptr) != 0) {
+  if (sigaction64(config.record_allocs_signal(), &dump_act, nullptr) != 0) {
     error_log("Unable to set up record dump signal function: %s", strerror(errno));
     return false;
   }
diff --git a/libc/malloc_debug/RecordData.h b/libc/malloc_debug/RecordData.h
index ccabac2..021a299 100644
--- a/libc/malloc_debug/RecordData.h
+++ b/libc/malloc_debug/RecordData.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef DEBUG_MALLOC_RECORDDATA_H
-#define DEBUG_MALLOC_RECORDDATA_H
+#pragma once
 
 #include <stdint.h>
 #include <pthread.h>
@@ -129,7 +128,7 @@
   DISALLOW_COPY_AND_ASSIGN(ReallocEntry);
 };
 
-// posix_memalign, memalign, pvalloc, valloc all recorded with this class.
+// aligned_alloc, posix_memalign, memalign, pvalloc, valloc all recorded with this class.
 class MemalignEntry : public MallocEntry {
  public:
   MemalignEntry(void* pointer, size_t size, size_t alignment);
@@ -173,5 +172,3 @@
 
   DISALLOW_COPY_AND_ASSIGN(RecordData);
 };
-
-#endif // DEBUG_MALLOC_RECORDDATA_H
diff --git a/libc/malloc_debug/TrackData.h b/libc/malloc_debug/TrackData.h
index 9a649b9..7201c49 100644
--- a/libc/malloc_debug/TrackData.h
+++ b/libc/malloc_debug/TrackData.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef DEBUG_MALLOC_TRACKDATA_H
-#define DEBUG_MALLOC_TRACKDATA_H
+#pragma once
 
 #include <stdint.h>
 #include <pthread.h>
@@ -75,5 +74,3 @@
 
   DISALLOW_COPY_AND_ASSIGN(TrackData);
 };
-
-#endif // DEBUG_MALLOC_TRACKDATA_H
diff --git a/libc/malloc_debug/backtrace.h b/libc/malloc_debug/backtrace.h
index f570873..92ea237 100644
--- a/libc/malloc_debug/backtrace.h
+++ b/libc/malloc_debug/backtrace.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef MALLOC_DEBUG_BACKTRACE_H
-#define MALLOC_DEBUG_BACKTRACE_H
+#pragma once
 
 #include <stdint.h>
 #include <sys/cdefs.h>
@@ -39,5 +38,3 @@
 size_t backtrace_get(uintptr_t* frames, size_t frame_count);
 void backtrace_log(const uintptr_t* frames, size_t frame_count);
 std::string backtrace_string(const uintptr_t* frames, size_t frame_count);
-
-#endif // MALLOC_DEBUG_BACKTRACE_H
diff --git a/libc/malloc_debug/debug_disable.h b/libc/malloc_debug/debug_disable.h
index 9edb4df..0049595 100644
--- a/libc/malloc_debug/debug_disable.h
+++ b/libc/malloc_debug/debug_disable.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef MALLOC_DEBUG_DISABLE_H
-#define MALLOC_DEBUG_DISABLE_H
+#pragma once
 
 #include <sys/cdefs.h>
 
@@ -60,5 +59,3 @@
 
   DISALLOW_COPY_AND_ASSIGN(ScopedDisableDebugCalls);
 };
-
-#endif  // MALLOC_DEBUG_DISABLE_H
diff --git a/libc/malloc_debug/debug_log.h b/libc/malloc_debug/debug_log.h
index ed4b541..54dd221 100644
--- a/libc/malloc_debug/debug_log.h
+++ b/libc/malloc_debug/debug_log.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef MALLOC_DEBUG_LOG_H
-#define MALLOC_DEBUG_LOG_H
+#pragma once
 
 #include <async_safe/log.h>
 
@@ -42,5 +41,3 @@
     async_safe_write_log(ANDROID_LOG_ERROR, "malloc_debug", (str))
 #define info_log(format, ...)  \
     async_safe_format_log(ANDROID_LOG_INFO, "malloc_debug", (format), ##__VA_ARGS__ )
-
-#endif  // MALLOC_DEBUG_LOG_H
diff --git a/libc/malloc_debug/exported32.map b/libc/malloc_debug/exported32.map
index e92a7cf..78a6990 100644
--- a/libc/malloc_debug/exported32.map
+++ b/libc/malloc_debug/exported32.map
@@ -1,5 +1,6 @@
 LIBC_MALLOC_DEBUG {
   global:
+    debug_aligned_alloc;
     debug_calloc;
     debug_dump_heap;
     debug_finalize;
diff --git a/libc/malloc_debug/exported64.map b/libc/malloc_debug/exported64.map
index 94104b0..2bfc38b 100644
--- a/libc/malloc_debug/exported64.map
+++ b/libc/malloc_debug/exported64.map
@@ -1,5 +1,6 @@
 LIBC_MALLOC_DEBUG {
   global:
+    debug_aligned_alloc;
     debug_calloc;
     debug_dump_heap;
     debug_finalize;
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index a2ada2f..ecfbd71 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -77,6 +77,7 @@
 size_t debug_malloc_usable_size(void* pointer);
 void* debug_malloc(size_t size);
 void debug_free(void* pointer);
+void* debug_aligned_alloc(size_t alignment, size_t size);
 void* debug_memalign(size_t alignment, size_t bytes);
 void* debug_realloc(void* pointer, size_t bytes);
 void* debug_calloc(size_t nmemb, size_t bytes);
@@ -669,6 +670,17 @@
   return g_dispatch->mallopt(param, value);
 }
 
+void* debug_aligned_alloc(size_t alignment, size_t size) {
+  if (DebugCallsDisabled()) {
+    return g_dispatch->aligned_alloc(alignment, size);
+  }
+  if (!powerof2(alignment)) {
+    errno = EINVAL;
+    return nullptr;
+  }
+  return debug_memalign(alignment, size);
+}
+
 int debug_posix_memalign(void** memptr, size_t alignment, size_t size) {
   if (DebugCallsDisabled()) {
     return g_dispatch->posix_memalign(memptr, alignment, size);
diff --git a/libc/malloc_debug/malloc_debug.h b/libc/malloc_debug/malloc_debug.h
index 4a1e8da..18a6c2c 100644
--- a/libc/malloc_debug/malloc_debug.h
+++ b/libc/malloc_debug/malloc_debug.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef MALLOC_DEBUG_H
-#define MALLOC_DEBUG_H
+#pragma once
 
 #include <stdint.h>
 
@@ -70,5 +69,3 @@
 constexpr size_t FREE_TRACK_MEM_BUFFER_SIZE = 4096;
 
 extern const MallocDispatch* g_dispatch;
-
-#endif // MALLOC_DEBUG_H
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 4e90668..0e4a7d8 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -54,6 +54,7 @@
 void* debug_realloc(void*, size_t);
 int debug_posix_memalign(void**, size_t, size_t);
 void* debug_memalign(size_t, size_t);
+void* debug_aligned_alloc(size_t, size_t);
 size_t debug_malloc_usable_size(void*);
 void debug_get_malloc_leak_info(uint8_t**, size_t*, size_t*, size_t*, size_t*);
 void debug_free_malloc_leak_info(uint8_t*);
@@ -136,6 +137,7 @@
   nullptr,
   nullptr,
   mallopt,
+  aligned_alloc,
 };
 
 void VerifyAllocCalls(bool backtrace_enabled) {
@@ -308,6 +310,11 @@
   ASSERT_LE(1039U, debug_malloc_usable_size(pointer));
   debug_free(pointer);
 
+  pointer = debug_aligned_alloc(128, 15);
+  ASSERT_TRUE(pointer != nullptr);
+  ASSERT_LE(1039U, debug_malloc_usable_size(pointer));
+  debug_free(pointer);
+
   pointer = debug_realloc(nullptr, 30);
   ASSERT_TRUE(pointer != nullptr);
   ASSERT_LE(1054U, debug_malloc_usable_size(pointer));
@@ -1772,6 +1779,12 @@
   debug_free(pointer);
   expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
 
+  pointer = debug_aligned_alloc(32, 50);
+  ASSERT_TRUE(pointer != nullptr);
+  expected += android::base::StringPrintf("%d: memalign %p 32 50\n", getpid(), pointer);
+  debug_free(pointer);
+  expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
+
   ASSERT_EQ(0, debug_posix_memalign(&pointer, 32, 50));
   ASSERT_TRUE(pointer != nullptr);
   expected += android::base::StringPrintf("%d: memalign %p 32 50\n", getpid(), pointer);
diff --git a/libc/malloc_hooks/Android.bp b/libc/malloc_hooks/Android.bp
new file mode 100644
index 0000000..d4b5a2a
--- /dev/null
+++ b/libc/malloc_hooks/Android.bp
@@ -0,0 +1,66 @@
+// ==============================================================
+// libc_malloc_hooks.so
+// ==============================================================
+cc_library {
+    name: "libc_malloc_hooks",
+
+    srcs: [
+        "malloc_hooks.cpp",
+    ],
+
+    static_libs: [
+        "libasync_safe",
+    ],
+
+    multilib: {
+        lib32: {
+            version_script: "exported32.map",
+        },
+        lib64: {
+            version_script: "exported64.map",
+        },
+    },
+    include_dirs: ["bionic/libc"],
+
+    sanitize: {
+        never: true,
+    },
+    native_coverage: false,
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-fno-stack-protector",
+    ],
+}
+
+// ==============================================================
+// Unit Tests
+// ==============================================================
+cc_test {
+    name: "malloc_hooks_unit_tests",
+    multilib: {
+        lib32: {
+            suffix: "32",
+        },
+        lib64: {
+            suffix: "64",
+        },
+    },
+
+    srcs: [
+        "tests/malloc_hooks_tests.cpp",
+    ],
+
+    whole_static_libs: ["libc_malloc_hooks"],
+
+    shared_libs: ["libbase"],
+
+    local_include_dirs: ["tests"],
+    include_dirs: ["bionic/libc", "bionic"],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+}
diff --git a/libc/malloc_hooks/README.md b/libc/malloc_hooks/README.md
new file mode 100644
index 0000000..85b2769
--- /dev/null
+++ b/libc/malloc_hooks/README.md
@@ -0,0 +1,118 @@
+Malloc Hooks
+============
+
+Malloc hooks allows a program to intercept all allocation/free calls that
+happen during execution. It is only available in Android P and newer versions
+of the OS.
+
+There are two ways to enable these hooks, set a special system
+property, or set a special environment variable and run your app/program.
+
+When malloc hooks is enabled, it works by adding a shim layer that replaces
+the normal allocation calls. The replaced calls are:
+
+* `malloc`
+* `free`
+* `calloc`
+* `realloc`
+* `posix_memalign`
+* `memalign`
+* `aligned_alloc`
+* `malloc_usable_size`
+
+On 32 bit systems, these two deprecated functions are also replaced:
+
+* `pvalloc`
+* `valloc`
+
+These four hooks are defined in malloc.h:
+
+    void* (*volatile __malloc_hook)(size_t, const void*);
+    void* (*volatile __realloc_hook)(void*, size_t, const void*);
+    void (*volatile __free_hook)(void*, const void*);
+    void* (*volatile __memalign_hook)(size_t, size_t, const void*);
+
+When malloc is called and \_\_malloc\_hook has been set, then the hook
+function is called instead.
+
+When realloc is called and \_\_realloc\_hook has been set, then the hook
+function is called instead.
+
+When free is called and \_\_free\_hook has been set, then the hook
+function is called instead.
+
+When memalign is called and \_\_memalign\_hook has been set, then the hook
+function is called instead.
+
+For posix\_memalign, if \_\_memalign\_hook has been set, then the hook is
+called, but only if alignment is a power of 2.
+
+For aligned\_alloc, if \_\_memalign\_hook has been set, then the hook is
+called, but only if alignment is a power of 2.
+
+For calloc, if \_\_malloc\_hook has been set, then the hook function is
+called, then the allocated memory is set to zero.
+
+For the two deprecated functions pvalloc and valloc, if \_\_memalign\_hook
+has been set, then the hook is called with an appropriate alignment value.
+
+There is no hook for malloc\_usable\_size as of now.
+
+These hooks can be set at any time, but there is no thread safety, so
+the caller must guarantee that it does not depend on allocations/frees
+occurring at the same time.
+
+Implementation Details
+======================
+When malloc hooks is enabled, then the hook pointers are set to
+the current default allocation functions. It is expected that if an
+app does intercept the allocation/free calls, it will eventually call
+the original hook function to do allocations. If the app does not do this,
+it runs the risk of crashing whenever a malloc\_usable\_size call is made.
+
+Example Implementation
+======================
+Below is a simple implementation intercepting only malloc/calloc calls.
+
+    void* new_malloc_hook(size_t bytes, const char* arg) {
+      return orig_malloc_hook(bytes, arg);
+    }
+
+    void orig_malloc_hook = __malloc_hook;
+    __malloc_hook = new_malloc_hook;
+
+Enabling Examples
+=================
+
+### For platform developers
+
+Enable the hooks for all processes:
+
+    adb shell stop
+    adb shell setprop libc.debug.malloc.hooks 1
+    adb shell start
+
+Enable malloc debug using an environment variable:
+
+    adb shell
+    # export LIBC_HOOK_ENABLE=1
+    # ls
+
+Any process spawned from this shell will run with malloc hooks enabled.
+
+### For app developers
+
+Enable malloc hooks for a specific program/application:
+
+    adb shell setprop wrap.<APP> '"LIBC_HOOKS_ENABLE=1"'
+
+For example, to enable malloc hooks for the google search box:
+
+    adb shell setprop wrap.com.google.android.googlequicksearchbox '"LIBC_HOOKS_ENABLE=1 logwrapper"'
+    adb shell am force-stop com.google.android.googlequicksearchbox
+
+NOTE: On pre-O versions of the Android OS, property names had a length limit
+of 32. This meant that to create a wrap property with the name of the app, it
+was necessary to truncate the name to fit. On O, property names can be
+an order of magnitude larger, so there should be no need to truncate the name
+at all.
diff --git a/libc/malloc_hooks/exported32.map b/libc/malloc_hooks/exported32.map
new file mode 100644
index 0000000..2cf5b8c
--- /dev/null
+++ b/libc/malloc_hooks/exported32.map
@@ -0,0 +1,26 @@
+LIBC_MALLOC_HOOKS {
+  global:
+    hooks_aligned_alloc;
+    hooks_calloc;
+    hooks_finalize;
+    hooks_free;
+    hooks_free_malloc_leak_info;
+    hooks_get_malloc_leak_info;
+    hooks_initialize;
+    hooks_iterate;
+    hooks_mallinfo;
+    hooks_malloc;
+    hooks_malloc_backtrace;
+    hooks_malloc_disable;
+    hooks_malloc_enable;
+    hooks_malloc_usable_size;
+    hooks_mallopt;
+    hooks_memalign;
+    hooks_posix_memalign;
+    hooks_pvalloc;
+    hooks_realloc;
+    hooks_valloc;
+
+  local:
+    *;
+};
diff --git a/libc/malloc_hooks/exported64.map b/libc/malloc_hooks/exported64.map
new file mode 100644
index 0000000..5ebcf9f
--- /dev/null
+++ b/libc/malloc_hooks/exported64.map
@@ -0,0 +1,24 @@
+LIBC_MALLOC_HOOKS {
+  global:
+    hooks_aligned_alloc;
+    hooks_calloc;
+    hooks_finalize;
+    hooks_free;
+    hooks_free_malloc_leak_info;
+    hooks_get_malloc_leak_info;
+    hooks_initialize;
+    hooks_iterate;
+    hooks_mallinfo;
+    hooks_malloc;
+    hooks_malloc_backtrace;
+    hooks_malloc_disable;
+    hooks_malloc_enable;
+    hooks_malloc_usable_size;
+    hooks_mallopt;
+    hooks_memalign;
+    hooks_posix_memalign;
+    hooks_realloc;
+
+  local:
+    *;
+};
diff --git a/libc/malloc_hooks/malloc_hooks.cpp b/libc/malloc_hooks/malloc_hooks.cpp
new file mode 100644
index 0000000..662520c
--- /dev/null
+++ b/libc/malloc_hooks/malloc_hooks.cpp
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2018 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 <errno.h>
+#include <malloc.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/param.h>
+#include <unistd.h>
+
+#include <private/bionic_malloc_dispatch.h>
+
+// ------------------------------------------------------------------------
+// Global Data
+// ------------------------------------------------------------------------
+const MallocDispatch* g_dispatch;
+// ------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------
+// Use C style prototypes for all exported functions. This makes it easy
+// to do dlsym lookups during libc initialization when hooks are enabled.
+// ------------------------------------------------------------------------
+__BEGIN_DECLS
+
+bool hooks_initialize(const MallocDispatch* malloc_dispatch, int* malloc_zygote_child,
+    const char* options);
+void hooks_finalize();
+void hooks_get_malloc_leak_info(
+    uint8_t** info, size_t* overall_size, size_t* info_size, size_t* total_memory,
+    size_t* backtrace_size);
+ssize_t hooks_malloc_backtrace(void* pointer, uintptr_t* frames, size_t frame_count);
+void hooks_free_malloc_leak_info(uint8_t* info);
+size_t hooks_malloc_usable_size(void* pointer);
+void* hooks_malloc(size_t size);
+void hooks_free(void* pointer);
+void* hooks_memalign(size_t alignment, size_t bytes);
+void* hooks_aligned_alloc(size_t alignment, size_t bytes);
+void* hooks_realloc(void* pointer, size_t bytes);
+void* hooks_calloc(size_t nmemb, size_t bytes);
+struct mallinfo hooks_mallinfo();
+int hooks_mallopt(int param, int value);
+int hooks_posix_memalign(void** memptr, size_t alignment, size_t size);
+int hooks_iterate(uintptr_t base, size_t size,
+    void (*callback)(uintptr_t base, size_t size, void* arg), void* arg);
+void hooks_malloc_disable();
+void hooks_malloc_enable();
+
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+void* hooks_pvalloc(size_t bytes);
+void* hooks_valloc(size_t size);
+#endif
+
+static void* default_malloc_hook(size_t bytes, const void*) {
+  return g_dispatch->malloc(bytes);
+}
+
+static void* default_realloc_hook(void* pointer, size_t bytes, const void*) {
+  return g_dispatch->realloc(pointer, bytes);
+}
+
+static void default_free_hook(void* pointer, const void*) {
+  g_dispatch->free(pointer);
+}
+
+static void* default_memalign_hook(size_t alignment, size_t bytes, const void*) {
+  return g_dispatch->memalign(alignment, bytes);
+}
+
+__END_DECLS
+// ------------------------------------------------------------------------
+
+bool hooks_initialize(const MallocDispatch* malloc_dispatch, int*, const char*) {
+  g_dispatch = malloc_dispatch;
+  __malloc_hook = default_malloc_hook;
+  __realloc_hook = default_realloc_hook;
+  __free_hook = default_free_hook;
+  __memalign_hook = default_memalign_hook;
+  return true;
+}
+
+void hooks_finalize() {
+}
+
+void hooks_get_malloc_leak_info(uint8_t** info, size_t* overall_size,
+    size_t* info_size, size_t* total_memory, size_t* backtrace_size) {
+  *info = nullptr;
+  *overall_size = 0;
+  *info_size = 0;
+  *total_memory = 0;
+  *backtrace_size = 0;
+}
+
+void hooks_free_malloc_leak_info(uint8_t*) {
+}
+
+size_t hooks_malloc_usable_size(void* pointer) {
+  return g_dispatch->malloc_usable_size(pointer);
+}
+
+void* hooks_malloc(size_t size) {
+  if (__malloc_hook != nullptr && __malloc_hook != default_malloc_hook) {
+    return __malloc_hook(size, __builtin_return_address(0));
+  }
+  return g_dispatch->malloc(size);
+}
+
+void hooks_free(void* pointer) {
+  if (__free_hook != nullptr && __free_hook != default_free_hook) {
+    return __free_hook(pointer, __builtin_return_address(0));
+  }
+  return g_dispatch->free(pointer);
+}
+
+void* hooks_memalign(size_t alignment, size_t bytes) {
+  if (__memalign_hook != nullptr && __memalign_hook != default_memalign_hook) {
+    return __memalign_hook(alignment, bytes, __builtin_return_address(0));
+  }
+  return g_dispatch->memalign(alignment, bytes);
+}
+
+void* hooks_realloc(void* pointer, size_t bytes) {
+  if (__realloc_hook != nullptr && __realloc_hook != default_realloc_hook) {
+    return __realloc_hook(pointer, bytes, __builtin_return_address(0));
+  }
+  return g_dispatch->realloc(pointer, bytes);
+}
+
+void* hooks_calloc(size_t nmemb, size_t bytes) {
+  if (__malloc_hook != nullptr && __malloc_hook != default_malloc_hook) {
+    size_t size;
+    if (__builtin_mul_overflow(nmemb, bytes, &size)) {
+      return nullptr;
+    }
+    void* ptr = __malloc_hook(size, __builtin_return_address(0));
+    if (ptr != nullptr) {
+      memset(ptr, 0, size);
+    }
+    return ptr;
+  }
+  return g_dispatch->calloc(nmemb, bytes);
+}
+
+struct mallinfo hooks_mallinfo() {
+  return g_dispatch->mallinfo();
+}
+
+int hooks_mallopt(int param, int value) {
+  return g_dispatch->mallopt(param, value);
+}
+
+void* hooks_aligned_alloc(size_t alignment, size_t size) {
+  if (__memalign_hook != nullptr && __memalign_hook != default_memalign_hook) {
+    if (!powerof2(alignment)) {
+      errno = EINVAL;
+      return nullptr;
+    }
+    void* ptr = __memalign_hook(alignment, size, __builtin_return_address(0));
+    if (ptr == nullptr) {
+      errno = ENOMEM;
+    }
+    return ptr;
+  }
+  return g_dispatch->aligned_alloc(alignment, size);
+}
+
+int hooks_posix_memalign(void** memptr, size_t alignment, size_t size) {
+  if (__memalign_hook != nullptr && __memalign_hook != default_memalign_hook) {
+    if (!powerof2(alignment)) {
+      return EINVAL;
+    }
+    *memptr = __memalign_hook(alignment, size, __builtin_return_address(0));
+    if (*memptr == nullptr) {
+      return ENOMEM;
+    }
+    return 0;
+  }
+  return g_dispatch->posix_memalign(memptr, alignment, size);
+}
+
+int hooks_iterate(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*) {
+  return 0;
+}
+
+void hooks_malloc_disable() {
+}
+
+void hooks_malloc_enable() {
+}
+
+ssize_t hooks_malloc_backtrace(void*, uintptr_t*, size_t) {
+  return 0;
+}
+
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
+void* hooks_pvalloc(size_t bytes) {
+  size_t pagesize = getpagesize();
+  size_t size = __BIONIC_ALIGN(bytes, pagesize);
+  if (size < bytes) {
+    // Overflow
+    errno = ENOMEM;
+    return nullptr;
+  }
+  return hooks_memalign(pagesize, size);
+}
+
+void* hooks_valloc(size_t size) {
+  return hooks_memalign(getpagesize(), size);
+}
+#endif
diff --git a/libc/malloc_hooks/tests/malloc_hooks_tests.cpp b/libc/malloc_hooks/tests/malloc_hooks_tests.cpp
new file mode 100644
index 0000000..0d23a6a
--- /dev/null
+++ b/libc/malloc_hooks/tests/malloc_hooks_tests.cpp
@@ -0,0 +1,412 @@
+/*
+ * Copyright (C) 2018 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 <fcntl.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include <private/bionic_malloc_dispatch.h>
+#include <tests/utils.h>
+
+__BEGIN_DECLS
+
+void get_malloc_leak_info(uint8_t**, size_t*, size_t*, size_t*, size_t*);
+void free_malloc_leak_info(uint8_t*);
+int malloc_iterate(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*);
+void malloc_enable();
+void malloc_disable();
+ssize_t malloc_backtrace(void*, uintptr_t*, size_t);
+
+__END_DECLS
+
+class MallocHooksTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    ASSERT_EQ(0, setenv("LIBC_HOOKS_ENABLE", "1", true));
+    initialized_ = false;
+  }
+
+  void TearDown() override {
+    if (initialized_) {
+      Reset();
+    }
+    ASSERT_EQ(0, unsetenv("LIBC_HOOKS_ENABLE"));
+  }
+
+  void Init() {
+    initialized_ = true;
+    malloc_hook_called_ = false;
+    free_hook_called_ = false;
+    realloc_hook_called_ = false;
+    memalign_hook_called_ = false;
+
+    void_arg_ = nullptr;
+
+    orig_malloc_hook_ = __malloc_hook;
+    orig_free_hook_ = __free_hook;
+    orig_realloc_hook_ = __realloc_hook;
+    orig_memalign_hook_ = __memalign_hook;
+  }
+
+  void Reset() {
+    __malloc_hook = orig_malloc_hook_;
+    __free_hook = orig_free_hook_;
+    __realloc_hook = orig_realloc_hook_;
+    __memalign_hook = orig_memalign_hook_;
+  }
+
+  void Exec(std::vector<const char*> args);
+  void RunTest(std::string test_name);
+
+ public:
+  bool initialized_;
+
+  int fd_;
+  std::string raw_output_;
+  pid_t pid_;
+
+  static bool malloc_hook_called_;
+  static bool free_hook_called_;
+  static bool realloc_hook_called_;
+  static bool memalign_hook_called_;
+  static const void* void_arg_;
+
+  static void* (*orig_malloc_hook_)(size_t, const void*);
+  static void (*orig_free_hook_)(void*, const void*);
+  static void* (*orig_realloc_hook_)(void*, size_t, const void*);
+  static void* (*orig_memalign_hook_)(size_t, size_t, const void*);
+
+  static void* test_malloc_hook(size_t, const void*);
+  static void* test_realloc_hook(void* ptr, size_t, const void*);
+  static void* test_memalign_hook(size_t, size_t, const void*);
+  static void test_free_hook(void*, const void*);
+};
+
+bool MallocHooksTest::malloc_hook_called_;
+bool MallocHooksTest::free_hook_called_;
+bool MallocHooksTest::realloc_hook_called_;
+bool MallocHooksTest::memalign_hook_called_;
+const void* MallocHooksTest::void_arg_;
+
+void* (*MallocHooksTest::orig_malloc_hook_)(size_t, const void*);
+void (*MallocHooksTest::orig_free_hook_)(void*, const void*);
+void* (*MallocHooksTest::orig_realloc_hook_)(void*, size_t, const void*);
+void* (*MallocHooksTest::orig_memalign_hook_)(size_t, size_t, const void*);
+
+static void GetExe(std::string* exe_name) {
+  char path[PATH_MAX];
+  ssize_t path_len = readlink("/proc/self/exe", path, sizeof(path));
+  ASSERT_TRUE(path_len >= 0);
+  *exe_name = std::string(path, path_len);
+}
+
+void MallocHooksTest::RunTest(std::string test_name) {
+  std::vector<const char*> args;
+  args.push_back("--gtest_also_run_disabled_tests");
+  std::string filter_arg("--gtest_filter=" + test_name);
+  args.push_back(filter_arg.c_str());
+
+  ExecTestHelper test;
+  test.Run(
+      [&]() {
+        std::string exe_name;
+        GetExe(&exe_name);
+        args.insert(args.begin(), exe_name.c_str());
+        args.push_back(nullptr);
+        execv(args[0], reinterpret_cast<char* const*>(const_cast<char**>(args.data())));
+        exit(1);
+      },
+      0, nullptr);
+}
+
+void* MallocHooksTest::test_malloc_hook(size_t size, const void* arg) {
+  malloc_hook_called_ = true;
+  void_arg_ = arg;
+  return orig_malloc_hook_(size, arg);
+}
+
+void* MallocHooksTest::test_realloc_hook(void* ptr, size_t size, const void* arg) {
+  realloc_hook_called_ = true;
+  void_arg_ = arg;
+  return orig_realloc_hook_(ptr, size, arg);
+}
+
+void* MallocHooksTest::test_memalign_hook(size_t alignment, size_t size, const void* arg) {
+  memalign_hook_called_ = true;
+  void_arg_ = arg;
+  return orig_memalign_hook_(alignment, size, arg);
+}
+
+void MallocHooksTest::test_free_hook(void* ptr, const void* arg) {
+  free_hook_called_ = true;
+  void_arg_ = arg;
+  return orig_free_hook_(ptr, arg);
+}
+
+TEST_F(MallocHooksTest, other_malloc_functions) {
+  RunTest("*.DISABLED_other_malloc_functions");
+}
+
+// Call other intercepted functions to make sure there are no crashes.
+TEST_F(MallocHooksTest, DISABLED_other_malloc_functions) {
+  struct mallinfo info = mallinfo();
+  EXPECT_NE(0U, info.uordblks);
+
+  EXPECT_EQ(0, mallopt(-1000, -1000));
+
+  void* ptr = malloc(1024);
+  EXPECT_LE(1024U, malloc_usable_size(ptr));
+  free(ptr);
+}
+
+TEST_F(MallocHooksTest, extended_functions) {
+  RunTest("*.DISABLED_extended_functions");
+}
+
+TEST_F(MallocHooksTest, DISABLED_extended_functions) {
+  uint8_t* info = nullptr;
+  size_t overall_size = 100;
+  size_t info_size = 200;
+  size_t total_memory = 300;
+  size_t backtrace_size = 400;
+  get_malloc_leak_info(&info, &overall_size, &info_size, &total_memory, &backtrace_size);
+  EXPECT_EQ(nullptr, info);
+  EXPECT_EQ(0U, overall_size);
+  EXPECT_EQ(0U, info_size);
+  EXPECT_EQ(0U, total_memory);
+  EXPECT_EQ(0U, backtrace_size);
+
+  free_malloc_leak_info(info);
+
+  malloc_enable();
+  malloc_disable();
+
+  EXPECT_EQ(0, malloc_iterate(0, 0, nullptr, nullptr));
+
+  // Malloc hooks doesn't support any backtracing.
+  EXPECT_EQ(0, malloc_backtrace(nullptr, nullptr, 10));
+}
+
+TEST_F(MallocHooksTest, malloc_hook) {
+  RunTest("*.DISABLED_malloc_hook");
+}
+
+TEST_F(MallocHooksTest, DISABLED_malloc_hook) {
+  Init();
+  ASSERT_TRUE(__malloc_hook != nullptr);
+  __malloc_hook = test_malloc_hook;
+
+  void* ptr = malloc(1024);
+  ASSERT_TRUE(ptr != nullptr);
+  write(0, ptr, 0);
+  free(ptr);
+
+  EXPECT_TRUE(malloc_hook_called_) << "The malloc hook was not called.";
+  EXPECT_TRUE(void_arg_ != nullptr) << "The malloc hook was called with a nullptr.";
+}
+
+TEST_F(MallocHooksTest, free_hook) {
+  RunTest("*.DISABLED_free_hook");
+}
+
+TEST_F(MallocHooksTest, DISABLED_free_hook) {
+  Init();
+  ASSERT_TRUE(__free_hook != nullptr);
+  __free_hook = test_free_hook;
+
+  void* ptr = malloc(1024);
+  ASSERT_TRUE(ptr != nullptr);
+  free(ptr);
+  write(0, ptr, 0);
+
+  EXPECT_TRUE(free_hook_called_) << "The free hook was not called.";
+  EXPECT_TRUE(void_arg_ != nullptr) << "The free hook was called with a nullptr.";
+}
+
+TEST_F(MallocHooksTest, realloc_hook) {
+  RunTest("*.DISABLED_realloc_hook");
+}
+
+TEST_F(MallocHooksTest, DISABLED_realloc_hook) {
+  Init();
+  ASSERT_TRUE(__realloc_hook != nullptr);
+  __realloc_hook = test_realloc_hook;
+
+  void* ptr = malloc(1024);
+  ASSERT_TRUE(ptr != nullptr);
+  ptr = realloc(ptr, 2048);
+  free(ptr);
+  write(0, ptr, 0);
+
+  EXPECT_TRUE(realloc_hook_called_) << "The realloc hook was not called.";
+  EXPECT_TRUE(void_arg_ != nullptr) << "The realloc hook was called with a nullptr.";
+}
+
+TEST_F(MallocHooksTest, memalign_hook) {
+  RunTest("*.DISABLED_memalign_hook");
+}
+
+TEST_F(MallocHooksTest, DISABLED_memalign_hook) {
+  Init();
+  ASSERT_TRUE(__memalign_hook != nullptr);
+  __memalign_hook = test_memalign_hook;
+
+  void* ptr = memalign(32, 1024);
+  ASSERT_TRUE(ptr != nullptr);
+  free(ptr);
+  write(0, ptr, 0);
+
+  EXPECT_TRUE(memalign_hook_called_) << "The memalign hook was not called.";
+  EXPECT_TRUE(void_arg_ != nullptr) << "The memalign hook was called with a nullptr.";
+}
+
+TEST_F(MallocHooksTest, posix_memalign_hook) {
+  RunTest("*.DISABLED_posix_memalign_hook");
+}
+
+TEST_F(MallocHooksTest, DISABLED_posix_memalign_hook) {
+  Init();
+  ASSERT_TRUE(__memalign_hook != nullptr);
+  __memalign_hook = test_memalign_hook;
+
+  void* ptr;
+  ASSERT_EQ(0, posix_memalign(&ptr, 32, 1024));
+  ASSERT_TRUE(ptr != nullptr);
+  free(ptr);
+  write(0, ptr, 0);
+
+  EXPECT_TRUE(memalign_hook_called_) << "The memalign hook was not called when running posix_memalign.";
+  EXPECT_TRUE(void_arg_ != nullptr) << "The memalign hook was called with a nullptr.";
+}
+
+TEST_F(MallocHooksTest, posix_memalign_hook_error) {
+  RunTest("*.DISABLED_posix_memalign_hook_error");
+}
+
+TEST_F(MallocHooksTest, DISABLED_posix_memalign_hook_error) {
+  Init();
+  ASSERT_TRUE(__memalign_hook != nullptr);
+  __memalign_hook = test_memalign_hook;
+
+  void* ptr;
+  ASSERT_EQ(EINVAL, posix_memalign(&ptr, 11, 1024));
+  write(0, ptr, 0);
+
+  EXPECT_FALSE(memalign_hook_called_)
+      << "The memalign hook was called when running posix_memalign with an error.";
+  EXPECT_FALSE(void_arg_ != nullptr)
+      << "The memalign hook was called with a nullptr with an error.";
+}
+
+TEST_F(MallocHooksTest, aligned_alloc_hook) {
+  RunTest("*.DISABLED_aligned_alloc_hook");
+}
+
+TEST_F(MallocHooksTest, DISABLED_aligned_alloc_hook) {
+  Init();
+  ASSERT_TRUE(__memalign_hook != nullptr);
+  __memalign_hook = test_memalign_hook;
+
+  void* ptr = aligned_alloc(32, 1024);
+  ASSERT_TRUE(ptr != nullptr);
+  free(ptr);
+  write(0, ptr, 0);
+
+  EXPECT_TRUE(memalign_hook_called_) << "The memalign hook was not called when running aligned_alloc.";
+  EXPECT_TRUE(void_arg_ != nullptr) << "The memalign hook was called with a nullptr.";
+}
+
+TEST_F(MallocHooksTest, aligned_alloc_hook_error) {
+  RunTest("*.DISABLED_aligned_alloc_hook_error");
+}
+
+TEST_F(MallocHooksTest, DISABLED_aligned_alloc_hook_error) {
+  Init();
+  ASSERT_TRUE(__memalign_hook != nullptr);
+  __memalign_hook = test_memalign_hook;
+
+  void* ptr = aligned_alloc(11, 1024);
+  ASSERT_TRUE(ptr == nullptr);
+  EXPECT_EQ(EINVAL, errno);
+  write(0, ptr, 0);
+
+  EXPECT_FALSE(memalign_hook_called_)
+      << "The memalign hook was called when running aligned_alloc with an error.";
+  EXPECT_FALSE(void_arg_ != nullptr)
+      << "The memalign hook was called with a nullptr with an error.";
+}
+
+#if !defined(__LP64__)
+TEST_F(MallocHooksTest, pvalloc_hook) {
+  RunTest("*.DISABLED_pvalloc_hook");
+}
+
+extern "C" void* pvalloc(size_t);
+
+TEST_F(MallocHooksTest, DISABLED_pvalloc_hook) {
+  Init();
+  ASSERT_TRUE(__memalign_hook != nullptr);
+  __memalign_hook = test_memalign_hook;
+
+  void* ptr = pvalloc(1024);
+  ASSERT_TRUE(ptr != nullptr);
+  write(0, ptr, 0);
+  free(ptr);
+
+  EXPECT_TRUE(memalign_hook_called_) << "The memalign hook was not called for pvalloc.";
+  EXPECT_TRUE(void_arg_ != nullptr) << "The memalign hook was called with a nullptr.";
+}
+
+TEST_F(MallocHooksTest, valloc_hook) {
+  RunTest("*.DISABLED_valloc_hook");
+}
+
+extern "C" void* valloc(size_t);
+
+TEST_F(MallocHooksTest, DISABLED_valloc_hook) {
+  Init();
+  ASSERT_TRUE(__memalign_hook != nullptr);
+  __memalign_hook = test_memalign_hook;
+
+  void* ptr = valloc(1024);
+  ASSERT_TRUE(ptr != nullptr);
+  write(0, ptr, 0);
+  free(ptr);
+
+  EXPECT_TRUE(memalign_hook_called_) << "The memalign hook was not called for valloc.";
+  EXPECT_TRUE(void_arg_ != nullptr) << "The memalign hook was called with a nullptr.";
+}
+#endif
diff --git a/libc/private/ScopedSignalBlocker.h b/libc/private/ScopedSignalBlocker.h
index c3ab307..7582068 100644
--- a/libc/private/ScopedSignalBlocker.h
+++ b/libc/private/ScopedSignalBlocker.h
@@ -20,14 +20,13 @@
 #include <signal.h>
 
 #include "bionic_macros.h"
-#include "kernel_sigset_t.h"
 
 class ScopedSignalBlocker {
  public:
   explicit ScopedSignalBlocker() {
-    kernel_sigset_t set;
-    set.fill();
-    __rt_sigprocmask(SIG_SETMASK, &set, &old_set_, sizeof(set));
+    sigset64_t set;
+    sigfillset64(&set);
+    sigprocmask64(SIG_SETMASK, &set, &old_set_);
   }
 
   ~ScopedSignalBlocker() {
@@ -35,11 +34,11 @@
   }
 
   void reset() {
-    __rt_sigprocmask(SIG_SETMASK, &old_set_, nullptr, sizeof(old_set_));
+    sigprocmask64(SIG_SETMASK, &old_set_, nullptr);
   }
 
  private:
-  kernel_sigset_t old_set_;
+  sigset64_t old_set_;
 
   DISALLOW_COPY_AND_ASSIGN(ScopedSignalBlocker);
 };
diff --git a/libc/bionic/epoll_create.cpp b/libc/private/SigSetConverter.h
similarity index 85%
rename from libc/bionic/epoll_create.cpp
rename to libc/private/SigSetConverter.h
index 74f664f..7d0b215 100644
--- a/libc/bionic/epoll_create.cpp
+++ b/libc/private/SigSetConverter.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,13 +26,10 @@
  * SUCH DAMAGE.
  */
 
-#include <errno.h>
-#include <sys/epoll.h>
+#pragma once
 
-int epoll_create(int size) {
-  if (size <= 0) {
-    errno = EINVAL;
-    return -1;
-  }
-  return epoll_create1(0);
-}
+union SigSetConverter {
+  int bsd;
+  sigset_t sigset;
+  sigset64_t sigset64;
+};
diff --git a/libc/private/bionic_arc4random.h b/libc/private/bionic_arc4random.h
index b51f818..0e9376e 100644
--- a/libc/private/bionic_arc4random.h
+++ b/libc/private/bionic_arc4random.h
@@ -33,18 +33,11 @@
 
 #include "private/KernelArgumentBlock.h"
 
-/*
- * arc4random aborts if it's unable to fetch entropy, which is always the case
- * for init on devices without getrandom(2), since /dev/random hasn't been
- * created yet. Provide a wrapper function that falls back to AT_RANDOM if
- * we don't have getrandom and /dev/urandom is missing.
- */
+// arc4random(3) aborts if it's unable to fetch entropy, which is always
+// the case for init on devices. GCE kernels have a workaround to ensure
+// sufficient entropy during early boot, but no device kernels do. This
+// wrapper falls back to AT_RANDOM if the kernel doesn't have enough
+// entropy for getrandom(2) or /dev/urandom.
 void __libc_safe_arc4random_buf(void* buf, size_t n, KernelArgumentBlock& args);
 
-/*
- * Return true if libc has an unlimited entropy source (something other than
- * AT_RANDOM), and arc4random* calls will always succeed.
- */
-bool __libc_arc4random_has_unlimited_entropy();
-
 #endif
diff --git a/libc/private/bionic_lock.h b/libc/private/bionic_lock.h
index b389247..54168d3 100644
--- a/libc/private/bionic_lock.h
+++ b/libc/private/bionic_lock.h
@@ -76,4 +76,19 @@
   }
 };
 
+class LockGuard {
+ public:
+  LockGuard(Lock& lock) : lock_(lock) {
+    lock_.lock();
+  }
+  ~LockGuard() {
+    lock_.unlock();
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(LockGuard);
+
+ private:
+  Lock& lock_;
+};
+
 #endif  // _BIONIC_LOCK_H
diff --git a/libc/private/bionic_malloc_dispatch.h b/libc/private/bionic_malloc_dispatch.h
index cdae466..0dce03d 100644
--- a/libc/private/bionic_malloc_dispatch.h
+++ b/libc/private/bionic_malloc_dispatch.h
@@ -46,6 +46,7 @@
 typedef void (*MallocMallocDisable)();
 typedef void (*MallocMallocEnable)();
 typedef int (*MallocMallopt)(int, int);
+typedef void* (*MallocAlignedAlloc)(size_t, size_t);
 
 #if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
 typedef void* (*MallocPvalloc)(size_t);
@@ -71,6 +72,7 @@
   MallocMallocDisable malloc_disable;
   MallocMallocEnable malloc_enable;
   MallocMallopt mallopt;
+  MallocAlignedAlloc aligned_alloc;
 } __attribute__((aligned(32)));
 
 #endif
diff --git a/libc/private/kernel_sigset_t.h b/libc/private/kernel_sigset_t.h
deleted file mode 100644
index bdfb729..0000000
--- a/libc/private/kernel_sigset_t.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2013 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 LIBC_PRIVATE_KERNEL_SIGSET_T_H_
-#define LIBC_PRIVATE_KERNEL_SIGSET_T_H_
-
-#include <errno.h>
-#include <signal.h>
-
-#include <async_safe/log.h>
-
-// Our sigset_t is wrong for ARM and x86. It's 32-bit but the kernel expects 64 bits.
-// This means we can't support real-time signals correctly without breaking the ABI.
-// In the meantime, we can use this union to pass an appropriately-sized block of memory
-// to the kernel, at the cost of not being able to refer to real-time signals when
-// initializing from a sigset_t on LP32.
-union kernel_sigset_t {
- public:
-  kernel_sigset_t() {
-  }
-
-  explicit kernel_sigset_t(int signal_number) {
-    clear();
-    if (!set(signal_number)) async_safe_fatal("kernel_sigset_t(%d)", signal_number);
-  }
-
-  explicit kernel_sigset_t(const sigset_t* value) {
-    clear();
-    set(value);
-  }
-
-  void clear() {
-    __builtin_memset(this, 0, sizeof(*this));
-  }
-
-  bool clear(int signal_number) {
-    int bit = bit_of(signal_number);
-    if (bit == -1) return false;
-    bits[bit / LONG_BIT] &= ~(1UL << (bit % LONG_BIT));
-    return true;
-  }
-
-  void fill() {
-    __builtin_memset(this, 0xff, sizeof(*this));
-  }
-
-  bool is_set(int signal_number) {
-    int bit = bit_of(signal_number);
-    if (bit == -1) return false;
-    return ((bits[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1) == 1;
-  }
-
-  bool set(int signal_number) {
-    int bit = bit_of(signal_number);
-    if (bit == -1) return false;
-    bits[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
-    return true;
-  }
-
-  void set(const sigset_t* value) {
-    clear();
-    bionic = *value;
-  }
-
-  sigset_t* get() {
-    return &bionic;
-  }
-
-  sigset_t bionic;
-  unsigned long bits[_KERNEL__NSIG/LONG_BIT];
-
- private:
-  int bit_of(int signal_number) {
-    int bit = signal_number - 1; // Signal numbers start at 1, but bit positions start at 0.
-    if (bit < 0 || bit >= static_cast<int>(8*sizeof(*this))) {
-      errno = EINVAL;
-      return -1;
-    }
-    return bit;
-  }
-};
-
-extern "C" int __rt_sigpending(const kernel_sigset_t*, size_t);
-extern "C" int __rt_sigprocmask(int, const kernel_sigset_t*, kernel_sigset_t*, size_t);
-extern "C" int __rt_sigsuspend(const kernel_sigset_t*, size_t);
-
-#endif
diff --git a/libc/bionic/pthread_sigmask.cpp b/libc/private/sigrtmin.h
similarity index 66%
copy from libc/bionic/pthread_sigmask.cpp
copy to libc/private/sigrtmin.h
index 79f31a1..ea8673d 100644
--- a/libc/bionic/pthread_sigmask.cpp
+++ b/libc/private/sigrtmin.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,14 +26,25 @@
  * SUCH DAMAGE.
  */
 
-#include <errno.h>
-#include <pthread.h>
+#pragma once
+
+#include <sys/cdefs.h>
+
 #include <signal.h>
 
-#include "private/ErrnoRestorer.h"
+// Realtime signals reserved for internal use:
+//   32 (__SIGRTMIN + 0)        POSIX timers
+//   33 (__SIGRTMIN + 1)        libbacktrace
+//   34 (__SIGRTMIN + 2)        libcore
+//   35 (__SIGRTMIN + 3)        debuggerd -b
+//
+// If you change this, also change __ndk_legacy___libc_current_sigrtmin
+// in <android/legacy_signal_inlines.h> to match.
 
-int pthread_sigmask(int how, const sigset_t* new_set, sigset_t* old_set) {
-  ErrnoRestorer errno_restorer;
-  int result = sigprocmask(how, new_set, old_set);
-  return (result == -1) ? errno : 0;
+#define __SIGRT_RESERVED 4
+static inline __always_inline sigset64_t filter_reserved_signals(sigset64_t sigset) {
+  for (int signo = __SIGRTMIN; signo < __SIGRTMIN + __SIGRT_RESERVED; ++signo) {
+    sigdelset64(&sigset, signo);
+  }
+  return sigset;
 }
diff --git a/libc/seccomp/Android.bp b/libc/seccomp/Android.bp
index bb91849..ae99857 100644
--- a/libc/seccomp/Android.bp
+++ b/libc/seccomp/Android.bp
@@ -22,7 +22,10 @@
         "mips64_system_policy.cpp",
     ],
     export_include_dirs: ["include"],
-    cflags: ["-Wall", "-Werror"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
     shared: {
         shared_libs: ["libbase"],
     },
diff --git a/libc/seccomp/include/seccomp_policy.h b/libc/seccomp/include/seccomp_policy.h
index add17b9..49280f4 100644
--- a/libc/seccomp/include/seccomp_policy.h
+++ b/libc/seccomp/include/seccomp_policy.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef SECCOMP_POLICY_H
-#define SECCOMP_POLICY_H
+#pragma once
 
 #include <stddef.h>
 #include <linux/filter.h>
@@ -23,5 +22,3 @@
 bool set_app_seccomp_filter();
 bool set_system_seccomp_filter();
 bool set_global_seccomp_filter();
-
-#endif
diff --git a/libc/seccomp/seccomp_bpfs.h b/libc/seccomp/seccomp_bpfs.h
index 8728c36..797dfc5 100644
--- a/libc/seccomp/seccomp_bpfs.h
+++ b/libc/seccomp/seccomp_bpfs.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef SECCOMP_BPFS_H
-#define SECCOMP_BPFS_H
+#pragma once
 
 #include <stddef.h>
 #include <linux/seccomp.h>
@@ -61,5 +60,3 @@
 extern const size_t mips64_system_filter_size;
 extern const struct sock_filter mips64_global_filter[];
 extern const size_t mips64_global_filter_size;
-
-#endif
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
index 517935b..11b136d 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -32,8 +32,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef __BIONIC_STDIO_LOCAL_H__
-#define __BIONIC_STDIO_LOCAL_H__
+#pragma once
 
 #include <pthread.h>
 #include <stdbool.h>
@@ -166,11 +165,10 @@
     _EXT(fp)->_caller_handles_locking = true; \
   } while (0)
 
-/*
- * Android <= KitKat had getc/putc macros in <stdio.h> that referred
- * to __srget/__swbuf, so those symbols need to be public for LP32
- * but can be hidden for LP64.
- */
+// Android <= 19 had getc/putc macros in <stdio.h> that referred
+// to __srget/__swbuf, so those symbols need to be public for LP32
+// but can be hidden for LP64. Moreover, the NDK continued to ship
+// those macros until r15 made unified headers the default.
 __LIBC32_LEGACY_PUBLIC__ int __srget(FILE*);
 __LIBC32_LEGACY_PUBLIC__ int __swbuf(int, FILE*);
 __LIBC32_LEGACY_PUBLIC__ int __srefill(FILE*);
@@ -279,5 +277,3 @@
 char* __ldtoa(long double*, int, int, int*, int*, char**);
 
 __END_DECLS
-
-#endif
diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp
index d3ac043..e066e5b 100644
--- a/libc/stdio/stdio.cpp
+++ b/libc/stdio/stdio.cpp
@@ -713,7 +713,7 @@
  * Return first argument, or NULL if no characters were read.
  * Do not return NULL if n == 1.
  */
-char* fgets(char* buf, int n, FILE* fp) __overloadable {
+char* fgets(char* buf, int n, FILE* fp) {
   CHECK_FP(fp);
   ScopedFileLock sfl(fp);
   return fgets_unlocked(buf, n, fp);
@@ -1031,7 +1031,7 @@
   return __sflush(fp);
 }
 
-size_t fread(void* buf, size_t size, size_t count, FILE* fp) __overloadable {
+size_t fread(void* buf, size_t size, size_t count, FILE* fp) {
   CHECK_FP(fp);
   ScopedFileLock sfl(fp);
   return fread_unlocked(buf, size, count, fp);
diff --git a/libc/stdio/stdio_ext.cpp b/libc/stdio/stdio_ext.cpp
index 8cf4f4b..e17b62a 100644
--- a/libc/stdio/stdio_ext.cpp
+++ b/libc/stdio/stdio_ext.cpp
@@ -72,6 +72,10 @@
   fflush(NULL);
 }
 
+void __fseterr(FILE* fp) {
+  fp->_flags |= __SERR;
+}
+
 int __fsetlocking(FILE* fp, int type) {
   int old_state = _EXT(fp)->_caller_handles_locking ? FSETLOCKING_BYCALLER : FSETLOCKING_INTERNAL;
   if (type == FSETLOCKING_QUERY) {
diff --git a/libc/stdio/wcio.h b/libc/stdio/wcio.h
index 3c4f7a4..047eb77 100644
--- a/libc/stdio/wcio.h
+++ b/libc/stdio/wcio.h
@@ -29,8 +29,7 @@
  * $Citrus$
  */
 
-#ifndef _WCIO_H_
-#define _WCIO_H_
+#pragma once
 
 #include <sys/cdefs.h>
 
@@ -80,5 +79,3 @@
 } while (0)
 
 __END_DECLS
-
-#endif /*_WCIO_H_*/
diff --git a/libc/system_properties/contexts_split.cpp b/libc/system_properties/contexts_split.cpp
index b8afa29..92baedd 100644
--- a/libc/system_properties/contexts_split.cpp
+++ b/libc/system_properties/contexts_split.cpp
@@ -274,12 +274,22 @@
     // Don't check for failure here, so we always have a sane list of properties.
     // E.g. In case of recovery, the vendor partition will not have mounted and we
     // still need the system / platform properties to function.
-    InitializePropertiesFromFile("/vendor/etc/selinux/nonplat_property_contexts");
+    if (access("/vendor/etc/selinux/vendor_property_contexts", R_OK) != -1) {
+      InitializePropertiesFromFile("/vendor/etc/selinux/vendor_property_contexts");
+    } else {
+      // Fallback to nonplat_* if vendor_* doesn't exist.
+      InitializePropertiesFromFile("/vendor/etc/selinux/nonplat_property_contexts");
+    }
   } else {
     if (!InitializePropertiesFromFile("/plat_property_contexts")) {
       return false;
     }
-    InitializePropertiesFromFile("/nonplat_property_contexts");
+    if (access("/vendor_property_contexts", R_OK) != -1) {
+      InitializePropertiesFromFile("/vendor_property_contexts");
+    } else {
+      // Fallback to nonplat_* if vendor_* doesn't exist.
+      InitializePropertiesFromFile("/nonplat_property_contexts");
+    }
   }
 
   return true;
diff --git a/libc/system_properties/include/system_properties/context_node.h b/libc/system_properties/include/system_properties/context_node.h
index 6a3bbcd..35d0e92 100644
--- a/libc/system_properties/include/system_properties/context_node.h
+++ b/libc/system_properties/include/system_properties/context_node.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef SYSTEM_PROPERTIES_CONTEXT_NODE_H
-#define SYSTEM_PROPERTIES_CONTEXT_NODE_H
+#pragma once
 
 #include "private/bionic_lock.h"
 
@@ -66,5 +65,3 @@
   bool no_access_;
   const char* filename_;
 };
-
-#endif
diff --git a/libc/system_properties/include/system_properties/contexts.h b/libc/system_properties/include/system_properties/contexts.h
index 8f154ed..670f808 100644
--- a/libc/system_properties/include/system_properties/contexts.h
+++ b/libc/system_properties/include/system_properties/contexts.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef SYSTEM_PROPERTIES_CONTEXTS_H
-#define SYSTEM_PROPERTIES_CONTEXTS_H
+#pragma once
 
 #include "prop_area.h"
 #include "prop_info.h"
@@ -44,5 +43,3 @@
   virtual void ResetAccess() = 0;
   virtual void FreeAndUnmap() = 0;
 };
-
-#endif
diff --git a/libc/system_properties/include/system_properties/contexts_pre_split.h b/libc/system_properties/include/system_properties/contexts_pre_split.h
index 14b00f1..6e695e9 100644
--- a/libc/system_properties/include/system_properties/contexts_pre_split.h
+++ b/libc/system_properties/include/system_properties/contexts_pre_split.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef SYSTEM_PROPERTIES_CONTEXTS_PRE_SPLIT_H
-#define SYSTEM_PROPERTIES_CONTEXTS_PRE_SPLIT_H
+#pragma once
 
 #include "contexts.h"
 #include "prop_area.h"
@@ -68,5 +67,3 @@
  private:
   prop_area* pre_split_prop_area_ = nullptr;
 };
-
-#endif
diff --git a/libc/system_properties/include/system_properties/contexts_serialized.h b/libc/system_properties/include/system_properties/contexts_serialized.h
index 010730a..93d6ac1 100644
--- a/libc/system_properties/include/system_properties/contexts_serialized.h
+++ b/libc/system_properties/include/system_properties/contexts_serialized.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef SYSTEM_PROPERTIES_CONTEXTS_SERIALIZED_H
-#define SYSTEM_PROPERTIES_CONTEXTS_SERIALIZED_H
+#pragma once
 
 #include <property_info_parser/property_info_parser.h>
 
@@ -60,5 +59,3 @@
   size_t context_nodes_mmap_size_ = 0;
   prop_area* serial_prop_area_ = nullptr;
 };
-
-#endif
diff --git a/libc/system_properties/include/system_properties/contexts_split.h b/libc/system_properties/include/system_properties/contexts_split.h
index 06c405a..acb18e3 100644
--- a/libc/system_properties/include/system_properties/contexts_split.h
+++ b/libc/system_properties/include/system_properties/contexts_split.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef SYSTEM_PROPERTIES_CONTEXTS_SPLIT_H
-#define SYSTEM_PROPERTIES_CONTEXTS_SPLIT_H
+#pragma once
 
 #include "contexts.h"
 
@@ -58,5 +57,3 @@
   prop_area* serial_prop_area_ = nullptr;
   const char* filename_ = nullptr;
 };
-
-#endif
diff --git a/libc/system_properties/include/system_properties/prop_area.h b/libc/system_properties/include/system_properties/prop_area.h
index a7d5d22..2c25337 100644
--- a/libc/system_properties/include/system_properties/prop_area.h
+++ b/libc/system_properties/include/system_properties/prop_area.h
@@ -26,6 +26,8 @@
  * SUCH DAMAGE.
  */
 
+#pragma once
+
 #include <stdatomic.h>
 #include <stdint.h>
 #include <string.h>
@@ -35,9 +37,6 @@
 
 #include "prop_info.h"
 
-#ifndef SYSTEM_PROPERTIES_PROP_AREA_H
-#define SYSTEM_PROPERTIES_PROP_AREA_H
-
 // Properties are stored in a hybrid trie/binary tree structure.
 // Each property's name is delimited at '.' characters, and the tokens are put
 // into a trie structure.  Siblings at each level of the trie are stored in a
@@ -161,5 +160,3 @@
 
   DISALLOW_COPY_AND_ASSIGN(prop_area);
 };
-
-#endif
diff --git a/libc/system_properties/include/system_properties/prop_info.h b/libc/system_properties/include/system_properties/prop_info.h
index 99bcaaf..a127550 100644
--- a/libc/system_properties/include/system_properties/prop_info.h
+++ b/libc/system_properties/include/system_properties/prop_info.h
@@ -26,15 +26,14 @@
  * SUCH DAMAGE.
  */
 
+#pragma once
+
 #include <stdatomic.h>
 #include <stdint.h>
 #include <sys/system_properties.h>
 
 #include "private/bionic_macros.h"
 
-#ifndef SYSTEM_PROPERTIES_PROP_INFO_H
-#define SYSTEM_PROPERTIES_PROP_INFO_H
-
 // The C11 standard doesn't allow atomic loads from const fields,
 // though C++11 does.  Fudge it until standards get straightened out.
 static inline uint_least32_t load_const_atomic(const atomic_uint_least32_t* s, memory_order mo) {
@@ -88,5 +87,3 @@
 };
 
 static_assert(sizeof(prop_info) == 96, "sizeof struct prop_info must be 96 bytes");
-
-#endif
diff --git a/libc/system_properties/include/system_properties/system_properties.h b/libc/system_properties/include/system_properties/system_properties.h
index 83ac00c..52ffcaf 100644
--- a/libc/system_properties/include/system_properties/system_properties.h
+++ b/libc/system_properties/include/system_properties/system_properties.h
@@ -26,10 +26,10 @@
  * SUCH DAMAGE.
  */
 
-#ifndef SYSTEM_PROPERTIES_SYSTEM_PROPERTIES_H
-#define SYSTEM_PROPERTIES_SYSTEM_PROPERTIES_H
+#pragma once
 
 #include <stdint.h>
+#include <sys/param.h>
 #include <sys/system_properties.h>
 
 #include "contexts.h"
@@ -41,12 +41,13 @@
 
 class SystemProperties {
  public:
+  friend struct LocalPropertyTestState;
+  friend class SystemPropertiesTest;
   // Note that system properties are initialized before libc calls static initializers, so
   // doing any initialization in this constructor is an error.  Even a Constructor that zero
   // initializes this class will clobber the previous property initialization.
   // We rely on the static SystemProperties in libc to be placed in .bss and zero initialized.
-  SystemProperties() {
-  }
+  SystemProperties() = default;
   // Special constructor for testing that also zero initializes the important members.
   explicit SystemProperties(bool initialized) : initialized_(initialized) {
   }
@@ -72,25 +73,17 @@
   const prop_info* FindNth(unsigned n);
   int Foreach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie);
 
-  Contexts* contexts() {
-    return reinterpret_cast<Contexts*>(&contexts_union_);
-  }
-
  private:
-  // We don't want to use new or malloc in properties (b/31659220), and since these classes
-  // are small enough and we place them in a union.  See the above note about Constructors
-  // for why there is a no-op constructor here.
-  union ContextsUnion {
-    ContextsUnion() {
-    }
-    ~ContextsUnion() {
-    }
-    ContextsSerialized contexts_serialized;
-    ContextsSplit contexts_split;
-    ContextsPreSplit contexts_pre_split;
-  } contexts_union_;
+  // We don't want to use new or malloc in properties (b/31659220), and we don't want to waste a
+  // full page by using mmap(), so we set aside enough space to create any context of the three
+  // contexts.
+  static constexpr size_t kMaxContextsAlign =
+      MAX(alignof(ContextsSerialized), MAX(alignof(ContextsSplit), alignof(ContextsPreSplit)));
+  static constexpr size_t kMaxContextsSize =
+      MAX(sizeof(ContextsSerialized), MAX(sizeof(ContextsSplit), sizeof(ContextsPreSplit)));
+  alignas(kMaxContextsAlign) char contexts_data_[kMaxContextsSize];
+  Contexts* contexts_;
+
   bool initialized_;
   char property_filename_[PROP_FILENAME_MAX];
 };
-
-#endif
diff --git a/libc/system_properties/system_properties.cpp b/libc/system_properties/system_properties.cpp
index c610df2..7c48b8e 100644
--- a/libc/system_properties/system_properties.cpp
+++ b/libc/system_properties/system_properties.cpp
@@ -63,7 +63,7 @@
   ErrnoRestorer errno_restorer;
 
   if (initialized_) {
-    contexts()->ResetAccess();
+    contexts_->ResetAccess();
     return true;
   }
 
@@ -74,19 +74,19 @@
 
   if (is_dir(property_filename_)) {
     if (access("/dev/__properties__/property_info", R_OK) == 0) {
-      new (&contexts_union_.contexts_serialized) ContextsSerialized();
-      if (!contexts_union_.contexts_serialized.Initialize(false, property_filename_, nullptr)) {
+      contexts_ = new (contexts_data_) ContextsSerialized();
+      if (!contexts_->Initialize(false, property_filename_, nullptr)) {
         return false;
       }
     } else {
-      new (&contexts_union_.contexts_split) ContextsSplit();
-      if (!contexts_union_.contexts_split.Initialize(false, property_filename_, nullptr)) {
+      contexts_ = new (contexts_data_) ContextsSplit();
+      if (!contexts_->Initialize(false, property_filename_, nullptr)) {
         return false;
       }
     }
   } else {
-    new (&contexts_union_.contexts_pre_split) ContextsPreSplit();
-    if (!contexts_union_.contexts_pre_split.Initialize(false, property_filename_, nullptr)) {
+    contexts_ = new (contexts_data_) ContextsPreSplit();
+    if (!contexts_->Initialize(false, property_filename_, nullptr)) {
       return false;
     }
   }
@@ -100,8 +100,8 @@
   }
   strcpy(property_filename_, filename);
 
-  new (&contexts_union_.contexts_serialized) ContextsSerialized();
-  if (!contexts_union_.contexts_serialized.Initialize(true, property_filename_, fsetxattr_failed)) {
+  contexts_ = new (contexts_data_) ContextsSerialized();
+  if (!contexts_->Initialize(true, property_filename_, fsetxattr_failed)) {
     return false;
   }
   initialized_ = true;
@@ -113,7 +113,7 @@
     return -1;
   }
 
-  prop_area* pa = contexts()->GetSerialPropArea();
+  prop_area* pa = contexts_->GetSerialPropArea();
   if (!pa) {
     return -1;
   }
@@ -127,7 +127,7 @@
     return nullptr;
   }
 
-  prop_area* pa = contexts()->GetPropAreaForName(name);
+  prop_area* pa = contexts_->GetPropAreaForName(name);
   if (!pa) {
     async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied finding property \"%s\"", name);
     return nullptr;
@@ -231,7 +231,7 @@
     return -1;
   }
 
-  prop_area* pa = contexts()->GetSerialPropArea();
+  prop_area* pa = contexts_->GetSerialPropArea();
   if (!pa) {
     return -1;
   }
@@ -269,12 +269,12 @@
     return -1;
   }
 
-  prop_area* serial_pa = contexts()->GetSerialPropArea();
+  prop_area* serial_pa = contexts_->GetSerialPropArea();
   if (serial_pa == nullptr) {
     return -1;
   }
 
-  prop_area* pa = contexts()->GetPropAreaForName(name);
+  prop_area* pa = contexts_->GetPropAreaForName(name);
   if (!pa) {
     async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied adding property \"%s\"", name);
     return -1;
@@ -319,7 +319,7 @@
       return -1;
     }
 
-    prop_area* serial_pa = contexts()->GetSerialPropArea();
+    prop_area* serial_pa = contexts_->GetSerialPropArea();
     if (serial_pa == nullptr) {
       return -1;
     }
@@ -364,7 +364,7 @@
     return -1;
   }
 
-  contexts()->ForEach(propfn, cookie);
+  contexts_->ForEach(propfn, cookie);
 
   return 0;
 }
diff --git a/libc/tzcode/strptime.c b/libc/tzcode/strptime.c
index 0567aa4..2100630 100644
--- a/libc/tzcode/strptime.c
+++ b/libc/tzcode/strptime.c
@@ -430,3 +430,7 @@
     *dest = result;
     return (1);
 }
+
+char* strptime_l(const char* buf, const char* fmt, struct tm* tm, locale_t l) {
+  return strptime(buf, fmt, tm);
+}
diff --git a/libc/upstream-openbsd/lib/libc/string/memchr.c b/libc/upstream-openbsd/lib/libc/string/memchr.c
index 976ed21..a6a4bd6 100644
--- a/libc/upstream-openbsd/lib/libc/string/memchr.c
+++ b/libc/upstream-openbsd/lib/libc/string/memchr.c
@@ -34,7 +34,7 @@
 #include <string.h>
 
 void *
-memchr(const void *s, int c, size_t n) __overloadable
+memchr(const void *s, int c, size_t n)
 {
 	if (n != 0) {
 		const unsigned char *p = s;
diff --git a/libc/upstream-openbsd/lib/libc/string/memmove.c b/libc/upstream-openbsd/lib/libc/string/memmove.c
index 6b5db47..2f1deb2 100644
--- a/libc/upstream-openbsd/lib/libc/string/memmove.c
+++ b/libc/upstream-openbsd/lib/libc/string/memmove.c
@@ -46,7 +46,7 @@
  * Copy a block of memory, handling overlap.
  */
 void *
-memmove(void *dst0, const void *src0, size_t length) __overloadable
+memmove(void *dst0, const void *src0, size_t length)
 {
 	char *dst = dst0;
 	const char *src = src0;
diff --git a/libc/upstream-openbsd/lib/libc/string/memrchr.c b/libc/upstream-openbsd/lib/libc/string/memrchr.c
index 4b67503..26a3399 100644
--- a/libc/upstream-openbsd/lib/libc/string/memrchr.c
+++ b/libc/upstream-openbsd/lib/libc/string/memrchr.c
@@ -23,7 +23,7 @@
  * Find the last occurrence of 'c' in the buffer 's' of size 'n'.
  */
 void *
-memrchr(const void *s, int c, size_t n) __overloadable
+memrchr(const void *s, int c, size_t n)
 {
 	const unsigned char *cp;
 
diff --git a/libc/upstream-openbsd/lib/libc/string/stpcpy.c b/libc/upstream-openbsd/lib/libc/string/stpcpy.c
index 3ed5782..d88afac 100644
--- a/libc/upstream-openbsd/lib/libc/string/stpcpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/stpcpy.c
@@ -37,7 +37,7 @@
 #endif
 
 char *
-stpcpy(char *to, const char *from) __overloadable
+stpcpy(char *to, const char *from)
 {
 	for (; (*to = *from) != '\0'; ++from, ++to);
 	return(to);
diff --git a/libc/upstream-openbsd/lib/libc/string/stpncpy.c b/libc/upstream-openbsd/lib/libc/string/stpncpy.c
index f30bf15..6bdee5d 100644
--- a/libc/upstream-openbsd/lib/libc/string/stpncpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/stpncpy.c
@@ -35,7 +35,7 @@
 #include <string.h>
 
 char *
-stpncpy(char *dst, const char *src, size_t n) __overloadable
+stpncpy(char *dst, const char *src, size_t n)
 {
 	if (n != 0) {
 		char *d = dst;
diff --git a/libc/upstream-openbsd/lib/libc/string/strcat.c b/libc/upstream-openbsd/lib/libc/string/strcat.c
index 7872a2d..646c9c2 100644
--- a/libc/upstream-openbsd/lib/libc/string/strcat.c
+++ b/libc/upstream-openbsd/lib/libc/string/strcat.c
@@ -37,7 +37,7 @@
 #endif
 
 char *
-strcat(char *s, const char *append) __overloadable
+strcat(char *s, const char *append)
 {
 	char *save = s;
 
diff --git a/libc/upstream-openbsd/lib/libc/string/strcpy.c b/libc/upstream-openbsd/lib/libc/string/strcpy.c
index 1b1169c..5a9001e 100644
--- a/libc/upstream-openbsd/lib/libc/string/strcpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/strcpy.c
@@ -37,7 +37,7 @@
 #endif
 
 char *
-strcpy(char *to, const char *from) __overloadable
+strcpy(char *to, const char *from)
 {
 	char *save = to;
 
diff --git a/libc/upstream-openbsd/lib/libc/string/strlcat.c b/libc/upstream-openbsd/lib/libc/string/strlcat.c
index 8a950f5..6bf2a41 100644
--- a/libc/upstream-openbsd/lib/libc/string/strlcat.c
+++ b/libc/upstream-openbsd/lib/libc/string/strlcat.c
@@ -27,7 +27,7 @@
  * If retval >= dsize, truncation occurred.
  */
 size_t
-strlcat(char *dst, const char *src, size_t dsize) __overloadable
+strlcat(char *dst, const char *src, size_t dsize)
 {
 	const char *odst = dst;
 	const char *osrc = src;
diff --git a/libc/upstream-openbsd/lib/libc/string/strlcpy.c b/libc/upstream-openbsd/lib/libc/string/strlcpy.c
index 647b18b..3677689 100644
--- a/libc/upstream-openbsd/lib/libc/string/strlcpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/strlcpy.c
@@ -25,7 +25,7 @@
  * Returns strlen(src); if retval >= dsize, truncation occurred.
  */
 size_t
-strlcpy(char *dst, const char *src, size_t dsize) __overloadable
+strlcpy(char *dst, const char *src, size_t dsize)
 {
 	const char *osrc = src;
 	size_t nleft = dsize;
diff --git a/libc/upstream-openbsd/lib/libc/string/strncat.c b/libc/upstream-openbsd/lib/libc/string/strncat.c
index 5b07749..b3388ac 100644
--- a/libc/upstream-openbsd/lib/libc/string/strncat.c
+++ b/libc/upstream-openbsd/lib/libc/string/strncat.c
@@ -38,7 +38,7 @@
  * are written at dst (at most n+1 bytes being appended).  Return dst.
  */
 char *
-strncat(char *dst, const char *src, size_t n) __overloadable
+strncat(char *dst, const char *src, size_t n)
 {
 	if (n != 0) {
 		char *d = dst;
diff --git a/libc/upstream-openbsd/lib/libc/string/strncpy.c b/libc/upstream-openbsd/lib/libc/string/strncpy.c
index ad9dc84..d6d8647 100644
--- a/libc/upstream-openbsd/lib/libc/string/strncpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/strncpy.c
@@ -39,7 +39,7 @@
  * Return dst.
  */
 char *
-strncpy(char *dst, const char *src, size_t n) __overloadable
+strncpy(char *dst, const char *src, size_t n)
 {
 	if (n != 0) {
 		char *d = dst;
diff --git a/libdl/Android.bp b/libdl/Android.bp
index 0603d06..082cdea 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -4,7 +4,10 @@
 cc_library_static {
     name: "libdl_static",
 
-    srcs: ["libdl.cpp", "libdl_cfi.cpp"],
+    srcs: [
+        "libdl.cpp",
+        "libdl_cfi.cpp",
+    ],
 
     cflags: [
         "-Wall",
@@ -71,7 +74,7 @@
         whole_static_libs: ["libdl_static"],
     },
     static: {
-        srcs: [ "libdl_static.c" ],
+        srcs: ["libdl_static.c"],
     },
     cflags: [
         "-Wall",
@@ -91,7 +94,7 @@
 
     // This is placeholder library the actual implementation is (currently)
     // provided by the linker.
-    shared_libs: [ "ld-android" ],
+    shared_libs: ["ld-android"],
 
     sanitize: {
         never: true,
diff --git a/libdl/libdl.arm.map b/libdl/libdl.arm.map
index 7ed9503..1fcfc58 100644
--- a/libdl/libdl.arm.map
+++ b/libdl/libdl.arm.map
@@ -41,11 +41,6 @@
     __cfi_slowpath_diag;
 } LIBC_N;
 
-LIBC_PRIVATE {
-  global:
-    android_link_namespaces_all_libs;
-} LIBC_OMR1;
-
 LIBC_PLATFORM {
   global:
     __cfi_init;
diff --git a/libdl/libdl.arm64.map b/libdl/libdl.arm64.map
index 199f2e3..8d4019c 100644
--- a/libdl/libdl.arm64.map
+++ b/libdl/libdl.arm64.map
@@ -40,11 +40,6 @@
     __cfi_slowpath_diag;
 } LIBC_N;
 
-LIBC_PRIVATE {
-  global:
-    android_link_namespaces_all_libs;
-} LIBC_OMR1;
-
 LIBC_PLATFORM {
   global:
     __cfi_init;
diff --git a/libdl/libdl.cpp b/libdl/libdl.cpp
index 4c2415f..c834088 100644
--- a/libdl/libdl.cpp
+++ b/libdl/libdl.cpp
@@ -93,11 +93,6 @@
                                 const char* shared_libs_sonames);
 
 __attribute__((__weak__, visibility("default")))
-bool __loader_android_link_namespaces_all_libs(
-                                struct android_namespace_t* namespace_from,
-                                struct android_namespace_t* namespace_to);
-
-__attribute__((__weak__, visibility("default")))
 void __loader_android_dlwarning(void* obj, void (*f)(void*, const char*));
 
 __attribute__((__weak__, visibility("default")))
@@ -210,12 +205,6 @@
 }
 
 __attribute__((__weak__))
-bool android_link_namespaces_all_libs(struct android_namespace_t* namespace_from,
-                                      struct android_namespace_t* namespace_to) {
-  return __loader_android_link_namespaces_all_libs(namespace_from, namespace_to);
-}
-
-__attribute__((__weak__))
 void android_dlwarning(void* obj, void (*f)(void*, const char*)) {
   __loader_android_dlwarning(obj, f);
 }
diff --git a/libdl/libdl.map.txt b/libdl/libdl.map.txt
index 579ffa7..002e9f8 100644
--- a/libdl/libdl.map.txt
+++ b/libdl/libdl.map.txt
@@ -40,11 +40,6 @@
     __cfi_slowpath_diag;
 } LIBC_N;
 
-LIBC_PRIVATE {
-  global:
-    android_link_namespaces_all_libs;
-} LIBC_OMR1;
-
 LIBC_PLATFORM {
   global:
     __cfi_init;
diff --git a/libdl/libdl.mips.map b/libdl/libdl.mips.map
index 199f2e3..8d4019c 100644
--- a/libdl/libdl.mips.map
+++ b/libdl/libdl.mips.map
@@ -40,11 +40,6 @@
     __cfi_slowpath_diag;
 } LIBC_N;
 
-LIBC_PRIVATE {
-  global:
-    android_link_namespaces_all_libs;
-} LIBC_OMR1;
-
 LIBC_PLATFORM {
   global:
     __cfi_init;
diff --git a/libdl/libdl.mips64.map b/libdl/libdl.mips64.map
index 199f2e3..8d4019c 100644
--- a/libdl/libdl.mips64.map
+++ b/libdl/libdl.mips64.map
@@ -40,11 +40,6 @@
     __cfi_slowpath_diag;
 } LIBC_N;
 
-LIBC_PRIVATE {
-  global:
-    android_link_namespaces_all_libs;
-} LIBC_OMR1;
-
 LIBC_PLATFORM {
   global:
     __cfi_init;
diff --git a/libdl/libdl.x86.map b/libdl/libdl.x86.map
index 199f2e3..8d4019c 100644
--- a/libdl/libdl.x86.map
+++ b/libdl/libdl.x86.map
@@ -40,11 +40,6 @@
     __cfi_slowpath_diag;
 } LIBC_N;
 
-LIBC_PRIVATE {
-  global:
-    android_link_namespaces_all_libs;
-} LIBC_OMR1;
-
 LIBC_PLATFORM {
   global:
     __cfi_init;
diff --git a/libdl/libdl.x86_64.map b/libdl/libdl.x86_64.map
index 199f2e3..8d4019c 100644
--- a/libdl/libdl.x86_64.map
+++ b/libdl/libdl.x86_64.map
@@ -40,11 +40,6 @@
     __cfi_slowpath_diag;
 } LIBC_N;
 
-LIBC_PRIVATE {
-  global:
-    android_link_namespaces_all_libs;
-} LIBC_OMR1;
-
 LIBC_PLATFORM {
   global:
     __cfi_init;
diff --git a/libm/fpmath.h b/libm/fpmath.h
index 80420e5..854ba11 100644
--- a/libm/fpmath.h
+++ b/libm/fpmath.h
@@ -33,8 +33,7 @@
 // - android uses 128 bits long doubles for LP64, so the structure and macros
 //   were reworked for the quad precision ieee representation.
 
-#ifndef _FPMATH_
-#define _FPMATH_
+#pragma once
 
 #include <endian.h>
 
@@ -92,5 +91,3 @@
 } while(0)
 
 #endif // __LP64__
-
-#endif // _FPMATH_
diff --git a/libm/freebsd-compat.h b/libm/freebsd-compat.h
index ee41e45..0bcc40d 100644
--- a/libm/freebsd-compat.h
+++ b/libm/freebsd-compat.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef _BIONIC_LIBM_FREEBSD_COMPAT_H_included
-#define _BIONIC_LIBM_FREEBSD_COMPAT_H_included
+#pragma once
 
 #include <float.h>
 
@@ -38,5 +37,3 @@
 
 // Similarly rename _scan_nan.
 #define _scan_nan __libm_scan_nan
-
-#endif
diff --git a/linker/Android.bp b/linker/Android.bp
index 8d7fae5..2fcf369 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -6,7 +6,10 @@
         "linker_allocator.cpp",
         "linker_memory.cpp",
     ],
-    cflags: ["-Wall", "-Werror"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
 
     // We need to access Bionic private headers in the linker.
     include_dirs: ["bionic/libc"],
@@ -26,9 +29,15 @@
     host_supported: true,
     device_supported: false,
     target: {
-        linux_bionic: { enabled: true },
-        linux_glibc: { enabled: false },
-        darwin: { enabled: false },
+        linux_bionic: {
+            enabled: true,
+        },
+        linux_glibc: {
+            enabled: false,
+        },
+        darwin: {
+            enabled: false,
+        },
     },
 
     cflags: [
@@ -95,9 +104,7 @@
             version_script: "linker.generic.map",
         },
         x86: {
-            srcs: ["arch/x86/begin.c"],
-
-            cflags: ["-D__work_around_b_24465209__"],
+            srcs: ["arch/x86/begin.S"],
             version_script: "linker.generic.map",
         },
         x86_64: {
@@ -187,7 +194,7 @@
 
         // Important: The liblinker_malloc should be the last library in the list
         // to overwrite any other malloc implementations by other static libraries.
-        "liblinker_malloc"
+        "liblinker_malloc",
     ],
     static_executable: true,
 
@@ -202,12 +209,6 @@
         android: {
             static_libs: ["libdebuggerd_handler_fallback"],
         },
-        android64: {
-            cflags: ["-DTARGET_IS_64_BIT"],
-        },
-        linux_bionic: {
-            cflags: ["-DTARGET_IS_64_BIT"],
-        },
     },
     compile_multilib: "both",
 
diff --git a/libc/bionic/pthread_sigmask.cpp b/linker/arch/x86/begin.S
similarity index 74%
rename from libc/bionic/pthread_sigmask.cpp
rename to linker/arch/x86/begin.S
index 79f31a1..3812646 100644
--- a/libc/bionic/pthread_sigmask.cpp
+++ b/linker/arch/x86/begin.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,14 +26,18 @@
  * SUCH DAMAGE.
  */
 
-#include <errno.h>
-#include <pthread.h>
-#include <signal.h>
+#include <private/bionic_asm.h>
 
-#include "private/ErrnoRestorer.h"
+ENTRY(_start)
+  // Force unwinds to end in this function.
+  .cfi_undefined %eip
 
-int pthread_sigmask(int how, const sigset_t* new_set, sigset_t* old_set) {
-  ErrnoRestorer errno_restorer;
-  int result = sigprocmask(how, new_set, old_set);
-  return (result == -1) ? errno : 0;
-}
+  movl %esp, %eax         // %esp is aligned to 16 here.
+  subl $12, %esp
+  pushl %eax
+  call __linker_init      // %esp is aligned to 16 before the call.
+  addl $16, %esp
+
+  /* linker init returns (%eax) the _entry address in the main image */
+  jmp *%eax
+END(_start)
diff --git a/linker/arch/x86/begin.c b/linker/arch/x86/begin.c
deleted file mode 100644
index 331b79e..0000000
--- a/linker/arch/x86/begin.c
+++ /dev/null
@@ -1,53 +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 <stdint.h>
-#include <sys/cdefs.h>
-
-extern unsigned __linker_init(void* raw_args);
-
-__LIBC_HIDDEN__ void _start() {
-  // Force unwinds to end in this function.
-  asm volatile(".cfi_undefined \%eip");
-
-  void (*start)(void);
-
-  void* raw_args = (void*) ((uintptr_t) __builtin_frame_address(0) + sizeof(void*));
-  start = (void(*)(void))__linker_init(raw_args);
-
-  /* linker init returns (%eax) the _entry address in the main image */
-  /* entry point expects sp to point to raw_args */
-
-  __asm__ (
-     "mov %0, %%esp\n\t"
-     "jmp *%1\n\t"
-     : : "r"(raw_args), "r"(start) :
-  );
-
-  /* Unreachable */
-}
diff --git a/linker/ld_android.cpp b/linker/ld_android.cpp
index 4a05772..e2499b3 100644
--- a/linker/ld_android.cpp
+++ b/linker/ld_android.cpp
@@ -29,14 +29,6 @@
 #include <stdlib.h>
 #include <sys/cdefs.h>
 
-extern "C" void __somehow_you_managed_to_not_get_the_actual_symbols_from_the_linker();
-
-extern "C" void __ld_android_init() __attribute__((constructor));
-
-void __ld_android_init() {
-  __somehow_you_managed_to_not_get_the_actual_symbols_from_the_linker();
-}
-
 extern "C" void __internal_linker_error() {
   abort();
 }
diff --git a/linker/linked_list.h b/linker/linked_list.h
index ed2b150..048ea4d 100644
--- a/linker/linked_list.h
+++ b/linker/linked_list.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef __LINKED_LIST_H
-#define __LINKED_LIST_H
+#pragma once
 
 #include "private/bionic_macros.h"
 
@@ -259,5 +258,3 @@
   LinkedListEntry<T>* tail_;
   DISALLOW_COPY_AND_ASSIGN(LinkedList);
 };
-
-#endif // __LINKED_LIST_H
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 3f898ba..ff2a7e6 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -863,11 +863,8 @@
     }
   }
 
-  // If not found - use dlsym_handle_lookup for caller's
-  // local_group unless it is part of the global group in which
-  // case we already did it.
-  if (s == nullptr && caller != nullptr &&
-      (caller->get_rtld_flags() & RTLD_GLOBAL) == 0) {
+  // If not found - use dlsym_handle_lookup for caller's local_group
+  if (s == nullptr && caller != nullptr) {
     soinfo* local_group_root = caller->get_local_group_root();
 
     return dlsym_handle_lookup(local_group_root->get_primary_namespace(),
diff --git a/linker/linker.h b/linker/linker.h
index 29d40fa..260c89d 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _LINKER_H_
-#define _LINKER_H_
+#pragma once
 
 #include <dlfcn.h>
 #include <android/dlext.h>
@@ -187,5 +186,3 @@
 
 void increment_dso_handle_reference_counter(void* dso_handle);
 void decrement_dso_handle_reference_counter(void* dso_handle);
-
-#endif
diff --git a/linker/linker_allocator.h b/linker/linker_allocator.h
index 7fc6cbf..82e4ef4 100644
--- a/linker/linker_allocator.h
+++ b/linker/linker_allocator.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef __LINKER_ALLOCATOR_H
-#define __LINKER_ALLOCATOR_H
+#pragma once
 
 #include <errno.h>
 #include <stdlib.h>
@@ -152,6 +151,3 @@
   LinkerSmallObjectAllocator* allocators_;
   uint8_t allocators_buf_[sizeof(LinkerSmallObjectAllocator)*kSmallObjectAllocatorsCount];
 };
-
-
-#endif  /* __LINKER_ALLOCATOR_H */
diff --git a/linker/linker_block_allocator.h b/linker/linker_block_allocator.h
index eba1db2..b501659 100644
--- a/linker/linker_block_allocator.h
+++ b/linker/linker_block_allocator.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef __LINKER_BLOCK_ALLOCATOR_H
-#define __LINKER_BLOCK_ALLOCATOR_H
+#pragma once
 
 #include <stdlib.h>
 #include <limits.h>
@@ -89,5 +88,3 @@
   LinkerBlockAllocator block_allocator_;
   DISALLOW_COPY_AND_ASSIGN(LinkerTypeAllocator);
 };
-
-#endif // __LINKER_BLOCK_ALLOCATOR_H
diff --git a/linker/linker_cfi.h b/linker/linker_cfi.h
index e54554f..f3300d6 100644
--- a/linker/linker_cfi.h
+++ b/linker/linker_cfi.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _LINKER_CFI_H_
-#define _LINKER_CFI_H_
+#pragma once
 
 #include "linker.h"
 #include "linker_debug.h"
@@ -103,5 +102,3 @@
 };
 
 CFIShadowWriter* get_cfi_shadow();
-
-#endif // _LINKER_CFI_H_
diff --git a/linker/linker_common_types.h b/linker/linker_common_types.h
index 6afd950..ffa4066 100644
--- a/linker/linker_common_types.h
+++ b/linker/linker_common_types.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef __LINKER_COMMON_TYPES_H
-#define __LINKER_COMMON_TYPES_H
+#pragma once
 
 #include <android/dlext.h>
 #include "linked_list.h"
@@ -65,5 +64,3 @@
 
 typedef LinkedList<soinfo, SoinfoListAllocator> soinfo_list_t;
 typedef LinkedList<android_namespace_t, NamespaceListAllocator> android_namespace_list_t;
-
-#endif  /* __LINKER_COMMON_TYPES_H */
diff --git a/linker/linker_config.h b/linker/linker_config.h
index 0c50d57..e117aea 100644
--- a/linker/linker_config.h
+++ b/linker/linker_config.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _LINKER_CONFIG_H_
-#define _LINKER_CONFIG_H_
+#pragma once
 
 #include <android/api-level.h>
 
@@ -171,5 +170,3 @@
 
   DISALLOW_COPY_AND_ASSIGN(Config);
 };
-
-#endif /* _LINKER_CONFIG_H_ */
diff --git a/linker/linker_debug.h b/linker/linker_debug.h
index 7ceab08..862ea12 100644
--- a/linker/linker_debug.h
+++ b/linker/linker_debug.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _LINKER_DEBUG_H_
-#define _LINKER_DEBUG_H_
+#pragma once
 
 // You can increase the verbosity of debug traces by defining the LD_DEBUG
 // environment variable to a numeric value from 0 to 2 (corresponding to
@@ -102,5 +101,3 @@
 #define MARK(x) do {} while (0)
 
 #endif
-
-#endif /* _LINKER_DEBUG_H_ */
diff --git a/linker/linker_dlwarning.h b/linker/linker_dlwarning.h
index 68827f7..af26824 100644
--- a/linker/linker_dlwarning.h
+++ b/linker/linker_dlwarning.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef __LINKER_DLWARNING_H
-#define __LINKER_DLWARNING_H
+#pragma once
 
 void add_dlwarning(const char* sopath, const char* message, const char* value = nullptr);
 
@@ -36,5 +35,3 @@
 // is used to avoid forcing user into saving the message
 // to a global variable.
 void get_dlwarning(void* user_data, void (*f)(void*, const char*));
-
-#endif  /* __LINKER_DLWARNING_H */
diff --git a/linker/linker_gdb_support.h b/linker/linker_gdb_support.h
index 6709da1..4ae18ee 100644
--- a/linker/linker_gdb_support.h
+++ b/linker/linker_gdb_support.h
@@ -25,8 +25,8 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#ifndef __LINKER_GDB_SUPPORT_H
-#define __LINKER_GDB_SUPPORT_H
+
+#pragma once
 
 #include <link.h>
 #include <sys/cdefs.h>
@@ -42,5 +42,3 @@
 extern struct r_debug _r_debug;
 
 __END_DECLS
-
-#endif
diff --git a/linker/linker_globals.h b/linker/linker_globals.h
index 11ccbd5..b470918 100644
--- a/linker/linker_globals.h
+++ b/linker/linker_globals.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef __LINKER_GLOBALS_H
-#define __LINKER_GLOBALS_H
+#pragma once
 
 #include <link.h>
 #include <stddef.h>
@@ -86,5 +85,3 @@
  private:
   std::string saved_error_msg_;
 };
-
-#endif  /* __LINKER_GLOBALS_H */
diff --git a/linker/linker_logger.h b/linker/linker_logger.h
index 3e53f74..9ce438e 100644
--- a/linker/linker_logger.h
+++ b/linker/linker_logger.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _LINKER_LOGGER_H_
-#define _LINKER_LOGGER_H_
+#pragma once
 
 #include <stdlib.h>
 #include <limits.h>
@@ -61,5 +60,3 @@
 // If the system property debug.ld.greylist_disabled is true, we'll not use the greylist
 // regardless of API level.
 extern bool g_greylist_disabled;
-
-#endif /* _LINKER_LOGGER_H_ */
diff --git a/linker/linker_main.h b/linker/linker_main.h
index 5641696..8d486e8 100644
--- a/linker/linker_main.h
+++ b/linker/linker_main.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef __LINKER_MAIN_H
-#define __LINKER_MAIN_H
+#pragma once
 
 #include <android/dlext.h>
 
@@ -71,5 +70,3 @@
 bool solist_remove_soinfo(soinfo* si);
 soinfo* solist_get_head();
 soinfo* solist_get_somain();
-
-#endif
diff --git a/linker/linker_mapped_file_fragment.h b/linker/linker_mapped_file_fragment.h
index 0bfc7a3..f7872bd 100644
--- a/linker/linker_mapped_file_fragment.h
+++ b/linker/linker_mapped_file_fragment.h
@@ -25,8 +25,8 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#ifndef LINKER_MAPPED_FILE_FRAGMENT_H
-#define LINKER_MAPPED_FILE_FRAGMENT_H
+
+#pragma once
 
 #include <unistd.h>
 
@@ -49,5 +49,3 @@
 
   DISALLOW_COPY_AND_ASSIGN(MappedFileFragment);
 };
-
-#endif /* LINKER_MAPPED_FILE_FRAGMENT_H */
diff --git a/linker/linker_memory.cpp b/linker/linker_memory.cpp
index 472c4e8..6a54c13 100644
--- a/linker/linker_memory.cpp
+++ b/linker/linker_memory.cpp
@@ -32,27 +32,28 @@
 #include <sys/cdefs.h>
 #include <unistd.h>
 
+#include <atomic>
+
 #include <async_safe/log.h>
 
 static LinkerMemoryAllocator g_linker_allocator;
-static pid_t fallback_tid = 0;
+static std::atomic<pid_t> fallback_tid(0);
 
 // Used by libdebuggerd_handler to switch allocators during a crash dump, in
 // case the linker heap is corrupted. Do not use this function.
-extern "C" void __linker_enable_fallback_allocator() {
-  if (fallback_tid != 0) {
-    async_safe_fatal("attempted to use currently-in-use fallback allocator");
-  }
-
-  fallback_tid = gettid();
+extern "C" bool __linker_enable_fallback_allocator() {
+  pid_t expected = 0;
+  return fallback_tid.compare_exchange_strong(expected, gettid());
 }
 
 extern "C" void __linker_disable_fallback_allocator() {
-  if (fallback_tid == 0) {
+  pid_t previous = fallback_tid.exchange(0);
+  if (previous == 0) {
     async_safe_fatal("attempted to disable unused fallback allocator");
+  } else if (previous != gettid()) {
+    async_safe_fatal("attempted to disable fallback allocator in use by another thread (%d)",
+                     previous);
   }
-
-  fallback_tid = 0;
 }
 
 static LinkerMemoryAllocator& get_fallback_allocator() {
diff --git a/linker/linker_namespaces.h b/linker/linker_namespaces.h
index a7fe0d5..03520d7 100644
--- a/linker/linker_namespaces.h
+++ b/linker/linker_namespaces.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef __LINKER_NAMESPACES_H
-#define __LINKER_NAMESPACES_H
+#pragma once
 
 #include "linker_common_types.h"
 
@@ -164,5 +163,3 @@
 
   DISALLOW_COPY_AND_ASSIGN(android_namespace_t);
 };
-
-#endif  /* __LINKER_NAMESPACES_H */
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index d6276ed..9b9ce94 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -25,8 +25,8 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#ifndef LINKER_PHDR_H
-#define LINKER_PHDR_H
+
+#pragma once
 
 /* Declarations related to the ELF program header table and segments.
  *
@@ -134,5 +134,3 @@
 
 const char* phdr_table_get_interpreter_name(const ElfW(Phdr) * phdr_table, size_t phdr_count,
                                             ElfW(Addr) load_bias);
-
-#endif /* LINKER_PHDR_H */
diff --git a/linker/linker_reloc_iterators.h b/linker/linker_reloc_iterators.h
index 6340924..b162684 100644
--- a/linker/linker_reloc_iterators.h
+++ b/linker/linker_reloc_iterators.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef __LINKER_RELOC_ITERATORS_H
-#define __LINKER_RELOC_ITERATORS_H
+#pragma once
 
 #include "linker.h"
 
@@ -173,5 +172,3 @@
   size_t relocation_group_index_;
   rel_t reloc_;
 };
-
-#endif  // __LINKER_RELOC_ITERATORS_H
diff --git a/linker/linker_relocs.h b/linker/linker_relocs.h
index ed00594..4bab0e0 100644
--- a/linker/linker_relocs.h
+++ b/linker/linker_relocs.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef __LINKER_RELOCS_H
-#define __LINKER_RELOCS_H
+#pragma once
 
 #include <elf.h>
 
@@ -62,5 +61,3 @@
 #define R_GENERIC_IRELATIVE R_X86_64_IRELATIVE
 
 #endif
-
-#endif // __LINKER_RELOCS_H
diff --git a/linker/linker_sleb128.h b/linker/linker_sleb128.h
index 01e127d..6bb3199 100644
--- a/linker/linker_sleb128.h
+++ b/linker/linker_sleb128.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _LINKER_SLEB128_H
-#define _LINKER_SLEB128_H
+#pragma once
 
 #include <stdint.h>
 
@@ -70,5 +69,3 @@
   const uint8_t* current_;
   const uint8_t* const end_;
 };
-
-#endif // __LINKER_SLEB128_H
diff --git a/linker/linker_soinfo.h b/linker/linker_soinfo.h
index 447c7c3..6e1f005 100644
--- a/linker/linker_soinfo.h
+++ b/linker/linker_soinfo.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef __LINKER_SOINFO_H
-#define __LINKER_SOINFO_H
+#pragma once
 
 #include <link.h>
 
@@ -386,5 +385,3 @@
     }
   }
 }
-
-#endif  /* __LINKER_SOINFO_H */
diff --git a/linker/linker_utils.h b/linker/linker_utils.h
index e104a25..214646c 100644
--- a/linker/linker_utils.h
+++ b/linker/linker_utils.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef __LINKER_UTILS_H
-#define __LINKER_UTILS_H
+#pragma once
 
 #include <string>
 #include <vector>
@@ -56,5 +55,3 @@
 off64_t page_start(off64_t offset);
 size_t page_offset(off64_t offset);
 bool safe_add(off64_t* out, off64_t a, size_t b);
-
-#endif
diff --git a/tests/Android.bp b/tests/Android.bp
index 1521b73..ec90296 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -17,6 +17,7 @@
 cc_defaults {
     name: "bionic_tests_defaults",
     host_supported: true,
+    cpp_std: "experimental",
     target: {
         darwin: {
             enabled: false,
@@ -75,6 +76,7 @@
         "getcwd_test.cpp",
         "glob_test.cpp",
         "grp_pwd_test.cpp",
+        "grp_pwd_file_test.cpp",
         "iconv_test.cpp",
         "ifaddrs_test.cpp",
         "inttypes_test.cpp",
@@ -140,6 +142,7 @@
         "sys_sem_test.cpp",
         "sys_sendfile_test.cpp",
         "sys_shm_test.cpp",
+        "sys_signalfd_test.cpp",
         "sys_socket_test.cpp",
         "sys_stat_test.cpp",
         "sys_statvfs_test.cpp",
@@ -244,10 +247,13 @@
 
 cc_test_library {
     name: "libfortify1-tests-clang",
-    defaults: ["bionic_fortify_tests_defaults", "bionic_tests_defaults"],
+    defaults: [
+        "bionic_fortify_tests_defaults",
+        "bionic_tests_defaults",
+    ],
     cflags: [
         "-D_FORTIFY_SOURCE=1",
-        "-DTEST_NAME=Fortify1_clang"
+        "-DTEST_NAME=Fortify1_clang",
     ],
     shared: {
         enabled: false,
@@ -256,10 +262,13 @@
 
 cc_test_library {
     name: "libfortify2-tests-clang",
-    defaults: ["bionic_fortify_tests_defaults", "bionic_tests_defaults"],
+    defaults: [
+        "bionic_fortify_tests_defaults",
+        "bionic_tests_defaults",
+    ],
     cflags: [
         "-D_FORTIFY_SOURCE=2",
-        "-DTEST_NAME=Fortify2_clang"
+        "-DTEST_NAME=Fortify2_clang",
     ],
     shared: {
         enabled: false,
@@ -311,7 +320,10 @@
 
 cc_test_library {
     name: "libBionicLoaderTests",
-    defaults: ["bionic_tests_defaults", "llvm-defaults"],
+    defaults: [
+        "bionic_tests_defaults",
+        "llvm-defaults",
+    ],
     srcs: [
         "atexit_test.cpp",
         "dl_test.cpp",
@@ -346,7 +358,7 @@
                 "libLLVMCore",
                 "libLLVMSupport",
             ],
-        }
+        },
     },
 }
 
@@ -413,6 +425,7 @@
     target: {
         android: {
             shared_libs: [
+                "ld-android",
                 "libdl",
                 "libdl_preempt_test_1",
                 "libdl_preempt_test_2",
@@ -437,12 +450,15 @@
                 "-Wl,--enable-new-dtags",
             ],
         },
-    }
+    },
 }
 
 cc_test {
     name: "bionic-unit-tests",
-    defaults: ["bionic_unit_tests_defaults", "bionic_tests_defaults"],
+    defaults: [
+        "bionic_unit_tests_defaults",
+        "bionic_tests_defaults",
+    ],
 
     target: {
         android: {
diff --git a/tests/BionicDeathTest.h b/tests/BionicDeathTest.h
index 3e8d7b2..6826ab7 100644
--- a/tests/BionicDeathTest.h
+++ b/tests/BionicDeathTest.h
@@ -21,25 +21,28 @@
 
 #include <gtest/gtest.h>
 
+#if !defined(__BIONIC__)
+#define sigaction64 sigaction
+#endif
+
 class BionicDeathTest : public testing::Test {
  protected:
   virtual void SetUp() {
     // Suppress debuggerd stack traces. Too slow.
     for (int signo : { SIGABRT, SIGBUS, SIGSEGV, SIGSYS }) {
-      struct sigaction action = {};
-      action.sa_handler = SIG_DFL;
-      sigaction(signo, &action, &previous_);
+      struct sigaction64 action = { .sa_handler = SIG_DFL };
+      sigaction64(signo, &action, &previous_);
     }
   }
 
   virtual void TearDown() {
     for (int signo : { SIGABRT, SIGBUS, SIGSEGV, SIGSYS }) {
-      sigaction(signo, &previous_, nullptr);
+      sigaction64(signo, &previous_, nullptr);
     }
   }
 
  private:
-  struct sigaction previous_;
+  struct sigaction64 previous_;
 };
 
 #endif // BIONIC_TESTS_BIONIC_DEATH_TEST_H_
diff --git a/tests/ScopedSignalHandler.h b/tests/ScopedSignalHandler.h
index 71f22dc..36bbf10 100644
--- a/tests/ScopedSignalHandler.h
+++ b/tests/ScopedSignalHandler.h
@@ -20,6 +20,27 @@
 #include <signal.h>
 #include <string.h>
 
+#if defined(__GLIBC__)
+#define posix_spawnattr_getsigdefault64 posix_spawnattr_getsigdefault
+#define posix_spawnattr_getsigmask64 posix_spawnattr_getsigmask
+#define posix_spawnattr_setsigdefault64 posix_spawnattr_setsigdefault
+#define posix_spawnattr_setsigmask64 posix_spawnattr_setsigmask
+#define pthread_sigmask64 pthread_sigmask
+#define sigaction64 sigaction
+#define sigaddset64 sigaddset
+#define sigdelset64 sigdelset
+#define sigemptyset64 sigemptyset
+#define sigfillset64 sigfillset
+#define sigismember64 sigismember
+#define sigpending64 sigpending
+#define sigprocmask64 sigprocmask
+#define sigset64_t sigset_t
+#define sigsuspend64 sigsuspend
+#define sigtimedwait64 sigtimedwait
+#define sigwait64 sigwait
+#define sigwaitinfo64 sigwaitinfo
+#endif
+
 class ScopedSignalHandler {
  public:
   ScopedSignalHandler(int signal_number, void (*handler)(int), int sa_flags = 0)
@@ -27,7 +48,7 @@
     memset(&action_, 0, sizeof(action_));
     action_.sa_flags = sa_flags;
     action_.sa_handler = handler;
-    sigaction(signal_number_, &action_, &old_action_);
+    sigaction64(signal_number_, &action_, &old_action_);
   }
 
   ScopedSignalHandler(int signal_number, void (*action)(int, siginfo_t*, void*),
@@ -36,35 +57,35 @@
     memset(&action_, 0, sizeof(action_));
     action_.sa_flags = sa_flags;
     action_.sa_sigaction = action;
-    sigaction(signal_number_, &action_, &old_action_);
+    sigaction64(signal_number_, &action_, &old_action_);
   }
 
   ScopedSignalHandler(int signal_number) : signal_number_(signal_number) {
-    sigaction(signal_number, nullptr, &old_action_);
+    sigaction64(signal_number, nullptr, &old_action_);
   }
 
   ~ScopedSignalHandler() {
-    sigaction(signal_number_, &old_action_, NULL);
+    sigaction64(signal_number_, &old_action_, NULL);
   }
 
  private:
-  struct sigaction action_;
-  struct sigaction old_action_;
+  struct sigaction64 action_;
+  struct sigaction64 old_action_;
   const int signal_number_;
 };
 
 class SignalMaskRestorer {
  public:
   SignalMaskRestorer() {
-    sigprocmask(SIG_SETMASK, nullptr, &old_mask_);
+    sigprocmask64(SIG_SETMASK, nullptr, &old_mask_);
   }
 
   ~SignalMaskRestorer() {
-    sigprocmask(SIG_SETMASK, &old_mask_, nullptr);
+    sigprocmask64(SIG_SETMASK, &old_mask_, nullptr);
   }
 
  private:
-  sigset_t old_mask_;
+  sigset64_t old_mask_;
 };
 
 #endif // _BIONIC_TESTS_SCOPED_SIGNAL_HANDLER_H
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index bb2d8a3..9ed1a56 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -1737,6 +1737,9 @@
   ASSERT_EQ(expected_dlerror, dlerror());
 }
 
+extern "C" bool __loader_android_link_namespaces_all_libs(android_namespace_t* namespace_from,
+                                                          android_namespace_t* namespace_to);
+
 TEST(dlext, ns_link_namespaces_invalid_arguments) {
   ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
 
@@ -1764,16 +1767,16 @@
                "error linking namespaces \"private\"->\"(default)\": "
                "the list of shared libraries is empty.", dlerror());
 
-  // Test android_link_namespaces_all_libs()
-  ASSERT_FALSE(android_link_namespaces_all_libs(nullptr, nullptr));
+  // Test __loader_android_link_namespaces_all_libs()
+  ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, nullptr));
   ASSERT_STREQ("android_link_namespaces_all_libs failed: "
                "error linking namespaces: namespace_from is null.", dlerror());
 
-  ASSERT_FALSE(android_link_namespaces_all_libs(nullptr, ns));
+  ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, ns));
   ASSERT_STREQ("android_link_namespaces_all_libs failed: "
                "error linking namespaces: namespace_from is null.", dlerror());
 
-  ASSERT_FALSE(android_link_namespaces_all_libs(ns, nullptr));
+  ASSERT_FALSE(__loader_android_link_namespaces_all_libs(ns, nullptr));
   ASSERT_STREQ("android_link_namespaces_all_libs failed: "
                "error linking namespaces: namespace_to is null.", dlerror());
 }
@@ -1802,7 +1805,7 @@
   ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
 
   ASSERT_TRUE(android_link_namespaces(ns_b, ns_a, "libnstest_ns_a_public1.so")) << dlerror();
-  ASSERT_TRUE(android_link_namespaces_all_libs(ns_a, ns_b)) << dlerror();
+  ASSERT_TRUE(__loader_android_link_namespaces_all_libs(ns_a, ns_b)) << dlerror();
 
   // Load libs with android_dlopen_ext() from namespace b
   android_dlextinfo extinfo;
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 000d1f7..c40a35b 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -256,7 +256,12 @@
     return;
   }
 #endif
-  void* handle = dlopen("linux-vdso.so.1", RTLD_NOW);
+
+  const char* vdso_name = "linux-vdso.so.1";
+#if defined(__i386__)
+  vdso_name = "linux-gate.so.1";
+#endif
+  void* handle = dlopen(vdso_name, RTLD_NOW);
   ASSERT_TRUE(handle != nullptr) << dlerror();
   dlclose(handle);
 }
@@ -1118,7 +1123,7 @@
 
 // Check that RTLD_NEXT of a libc symbol works in dlopened library
 TEST(dlfcn, rtld_next_from_library) {
-  void* library_with_fclose = dlopen("libtest_check_rtld_next_from_library.so", RTLD_NOW);
+  void* library_with_fclose = dlopen("libtest_check_rtld_next_from_library.so", RTLD_NOW | RTLD_GLOBAL);
   ASSERT_TRUE(library_with_fclose != nullptr) << dlerror();
   void* expected_addr = dlsym(RTLD_DEFAULT, "fclose");
   ASSERT_TRUE(expected_addr != nullptr) << dlerror();
diff --git a/tests/grp_pwd_file_test.cpp b/tests/grp_pwd_file_test.cpp
new file mode 100644
index 0000000..d6f3c9f
--- /dev/null
+++ b/tests/grp_pwd_file_test.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2018 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 <unistd.h>
+
+#include <gtest/gtest.h>
+
+#include "TemporaryFile.h"
+
+#if defined(__BIONIC__)
+#include "../libc/bionic/grp_pwd_file.cpp"
+
+template <typename T>
+class FileUnmapper {
+ public:
+  FileUnmapper(T& file) : file_(file) {
+  }
+  ~FileUnmapper() {
+    file_.Unmap();
+  }
+
+ private:
+  T& file_;
+};
+
+void FindAndCheckPasswdEntry(PasswdFile* file, const char* name, uid_t uid, gid_t gid,
+                             const char* dir, const char* shell) {
+  passwd_state_t name_passwd_state;
+  ASSERT_TRUE(file->FindByName(name, &name_passwd_state)) << name;
+
+  passwd& name_passwd = name_passwd_state.passwd_;
+  EXPECT_STREQ(name, name_passwd.pw_name);
+  EXPECT_EQ(nullptr, name_passwd.pw_passwd);
+  EXPECT_EQ(uid, name_passwd.pw_uid);
+  EXPECT_EQ(gid, name_passwd.pw_gid);
+  EXPECT_EQ(nullptr, name_passwd.pw_gecos);
+  EXPECT_STREQ(dir, name_passwd.pw_dir);
+  EXPECT_STREQ(shell, name_passwd.pw_shell);
+
+  passwd_state_t id_passwd_state;
+  ASSERT_TRUE(file->FindById(uid, &id_passwd_state)) << uid;
+
+  passwd& id_passwd = id_passwd_state.passwd_;
+  EXPECT_STREQ(name, id_passwd.pw_name);
+  EXPECT_EQ(nullptr, id_passwd.pw_passwd);
+  EXPECT_EQ(uid, id_passwd.pw_uid);
+  EXPECT_EQ(gid, id_passwd.pw_gid);
+  EXPECT_EQ(nullptr, id_passwd.pw_gecos);
+  EXPECT_STREQ(dir, id_passwd.pw_dir);
+  EXPECT_STREQ(shell, id_passwd.pw_shell);
+}
+
+void FindAndCheckGroupEntry(GroupFile* file, const char* name, gid_t gid) {
+  group_state_t name_group_state;
+  ASSERT_TRUE(file->FindByName(name, &name_group_state)) << name;
+
+  group& name_group = name_group_state.group_;
+  EXPECT_STREQ(name, name_group.gr_name);
+  EXPECT_EQ(nullptr, name_group.gr_passwd);
+  EXPECT_EQ(gid, name_group.gr_gid);
+  EXPECT_EQ(name_group.gr_name, name_group.gr_mem[0]);
+  EXPECT_EQ(nullptr, name_group.gr_mem[1]);
+
+  group_state_t id_group_state;
+  ASSERT_TRUE(file->FindById(gid, &id_group_state)) << gid;
+
+  group& id_group = id_group_state.group_;
+  EXPECT_STREQ(name, id_group.gr_name);
+  EXPECT_EQ(nullptr, id_group.gr_passwd);
+  EXPECT_EQ(gid, id_group.gr_gid);
+  EXPECT_EQ(id_group.gr_name, id_group.gr_mem[0]);
+  EXPECT_EQ(nullptr, id_group.gr_mem[1]);
+}
+
+#endif  // __BIONIC__
+
+TEST(grp_pwd_file, passwd_file_one_entry) {
+#if defined(__BIONIC__)
+  TemporaryFile file;
+  ASSERT_NE(-1, file.fd);
+  static const char test_string[] = "name:password:1:2:user_info:dir:shell\n";
+  write(file.fd, test_string, sizeof(test_string) - 1);
+
+  PasswdFile passwd_file(file.filename);
+  FileUnmapper unmapper(passwd_file);
+
+  FindAndCheckPasswdEntry(&passwd_file, "name", 1, 2, "dir", "shell");
+
+  EXPECT_FALSE(passwd_file.FindByName("not_name", nullptr));
+  EXPECT_FALSE(passwd_file.FindById(3, nullptr));
+
+#else   // __BIONIC__
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif  // __BIONIC__
+}
+
+TEST(grp_pwd_file, group_file_one_entry) {
+#if defined(__BIONIC__)
+  TemporaryFile file;
+  ASSERT_NE(-1, file.fd);
+  static const char test_string[] = "name:password:1:one,two,three\n";
+  write(file.fd, test_string, sizeof(test_string) - 1);
+
+  GroupFile group_file(file.filename);
+  FileUnmapper unmapper(group_file);
+
+  FindAndCheckGroupEntry(&group_file, "name", 1);
+
+  EXPECT_FALSE(group_file.FindByName("not_name", nullptr));
+  EXPECT_FALSE(group_file.FindById(3, nullptr));
+
+#else   // __BIONIC__
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif  // __BIONIC__
+}
+
+TEST(grp_pwd_file, passwd_file_many_entries) {
+#if defined(__BIONIC__)
+  TemporaryFile file;
+  ASSERT_NE(-1, file.fd);
+  static const char test_string[] =
+      "first:x:1:2::dir:shell\n"
+      "abc1::3:4::def:abc\n"
+      "abc2::5:4:abc::abc\n"
+      "abc3::7:4:abc:def:\n"
+      "abc4::9:4:::abc\n"
+      "abc5::11:4:abc:def:abc\n"
+      "middle-ish::13:4::/:/system/bin/sh\n"
+      "abc7::15:4:abc::\n"
+      "abc8::17:4:::\n"
+      "abc9::19:4:abc:def:abc\n"
+      "abc10::21:4:abc:def:abc\n"
+      "abc11::23:4:abc:def:abc\n"
+      "abc12::25:4:abc:def:abc\n"
+      "abc13::27:4:abc:def:abc\n"
+      "last::29:4::last_user_dir:last_user_shell\n";
+
+  write(file.fd, test_string, sizeof(test_string) - 1);
+
+  PasswdFile passwd_file(file.filename);
+  FileUnmapper unmapper(passwd_file);
+
+  FindAndCheckPasswdEntry(&passwd_file, "first", 1, 2, "dir", "shell");
+  FindAndCheckPasswdEntry(&passwd_file, "middle-ish", 13, 4, "/", "/system/bin/sh");
+  FindAndCheckPasswdEntry(&passwd_file, "last", 29, 4, "last_user_dir", "last_user_shell");
+
+  EXPECT_FALSE(passwd_file.FindByName("not_name", nullptr));
+  EXPECT_FALSE(passwd_file.FindById(50, nullptr));
+
+#else   // __BIONIC__
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif  // __BIONIC__
+}
+
+TEST(grp_pwd_file, group_file_many_entries) {
+#if defined(__BIONIC__)
+  TemporaryFile file;
+  ASSERT_NE(-1, file.fd);
+  static const char test_string[] =
+      "first:password:1:one,two,three\n"
+      "abc:def:2:group1,group2,group3\n"
+      "abc:def:3:\n"
+      "abc:def:4:\n"
+      "abc:def:5:\n"
+      "middle-ish:def_a_password_that_is_over_32_characters_long:6:\n"
+      "abc:def:7:\n"
+      "abc:def:8:\n"
+      "abc:def:20:\n"
+      "abc:def:25:\n"
+      "abc:def:27:\n"
+      "abc:def:52:\n"
+      "last::800:\n";
+
+  write(file.fd, test_string, sizeof(test_string) - 1);
+
+  GroupFile group_file(file.filename);
+  FileUnmapper unmapper(group_file);
+
+  FindAndCheckGroupEntry(&group_file, "first", 1);
+  FindAndCheckGroupEntry(&group_file, "middle-ish", 6);
+  FindAndCheckGroupEntry(&group_file, "last", 800);
+
+  EXPECT_FALSE(group_file.FindByName("not_name", nullptr));
+  EXPECT_FALSE(group_file.FindById(799, nullptr));
+
+#else   // __BIONIC__
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif  // __BIONIC__
+}
diff --git a/tests/grp_pwd_test.cpp b/tests/grp_pwd_test.cpp
index 61748c8..12d4b7f 100644
--- a/tests/grp_pwd_test.cpp
+++ b/tests/grp_pwd_test.cpp
@@ -115,10 +115,14 @@
 
 #else // !defined(__BIONIC__)
 
-static void check_get_passwd(const char* /* username */, uid_t /* uid */, uid_type_t /* uid_type */) {
+static void print_no_getpwnam_test_info() {
   GTEST_LOG_(INFO) << "This test is about uid/username translation for Android, which does nothing on libc other than bionic.\n";
 }
 
+static void check_get_passwd(const char* /* username */, uid_t /* uid */, uid_type_t /* uid_type */) {
+  print_no_getpwnam_test_info();
+}
+
 #endif
 
 TEST(pwd, getpwnam_system_id_root) {
@@ -238,6 +242,7 @@
 }
 
 TEST(pwd, getpwent_iterate) {
+#if defined(__BIONIC__)
   passwd* pwd;
   std::set<uid_t> uids;
 
@@ -257,19 +262,15 @@
       EXPECT_STREQ("/data", pwd->pw_dir) << "pwd->pw_uid: " << pwd->pw_uid;
     }
 
-    // TODO(b/27999086): fix this check with the OEM range
-    // If OEMs add their own AIDs to private/android_filesystem_config.h, this check will fail.
-    // Long term we want to create a better solution for OEMs adding AIDs, but we're not there
-    // yet, so therefore we do not check for uid's in the OEM range.
-    if (!(pwd->pw_uid >= 2900 && pwd->pw_uid <= 2999) &&
-        !(pwd->pw_uid >= 5000 && pwd->pw_uid <= 5999)) {
-      EXPECT_EQ(0U, uids.count(pwd->pw_uid)) << "pwd->pw_uid: " << pwd->pw_uid;
-    }
+    EXPECT_EQ(0U, uids.count(pwd->pw_uid)) << "pwd->pw_uid: " << pwd->pw_uid;
     uids.emplace(pwd->pw_uid);
   }
   endpwent();
 
   expect_ids(uids);
+#else
+  print_no_getpwnam_test_info();
+#endif
 }
 
 static void check_group(const group* grp, const char* group_name, gid_t gid) {
@@ -484,6 +485,7 @@
 }
 
 TEST(grp, getgrent_iterate) {
+#if defined(__BIONIC__)
   group* grp;
   std::set<gid_t> gids;
 
@@ -494,17 +496,13 @@
     EXPECT_STREQ(grp->gr_name, grp->gr_mem[0]) << "grp->gr_gid: " << grp->gr_gid;
     EXPECT_TRUE(grp->gr_mem[1] == NULL) << "grp->gr_gid: " << grp->gr_gid;
 
-    // TODO(b/27999086): fix this check with the OEM range
-    // If OEMs add their own AIDs to private/android_filesystem_config.h, this check will fail.
-    // Long term we want to create a better solution for OEMs adding AIDs, but we're not there
-    // yet, so therefore we do not check for gid's in the OEM range.
-    if (!(grp->gr_gid >= 2900 && grp->gr_gid <= 2999) &&
-        !(grp->gr_gid >= 5000 && grp->gr_gid <= 5999)) {
-      EXPECT_EQ(0U, gids.count(grp->gr_gid)) << "grp->gr_gid: " << grp->gr_gid;
-    }
+    EXPECT_EQ(0U, gids.count(grp->gr_gid)) << "grp->gr_gid: " << grp->gr_gid;
     gids.emplace(grp->gr_gid);
   }
   endgrent();
 
   expect_ids(gids);
+#else
+  print_no_getgrnam_test_info();
+#endif
 }
diff --git a/tests/headers/posix/Android.bp b/tests/headers/posix/Android.bp
index 682627f..8f3a2f2 100644
--- a/tests/headers/posix/Android.bp
+++ b/tests/headers/posix/Android.bp
@@ -18,11 +18,11 @@
     name: "libbionic_tests_headers_posix",
     srcs: ["*.c"],
     cflags: [
-      "-Wno-absolute-value", // broken clang diagnostic that doesn't understand <tgmath.h>
-      "-Wno-deprecated",
-      "-Werror",
-      "-D_POSIX_C_SOURCE=200809L",
-      "-D_XOPEN_SOURCE=700",
+        "-Wno-absolute-value", // broken clang diagnostic that doesn't understand <tgmath.h>
+        "-Wno-deprecated",
+        "-Werror",
+        "-D_POSIX_C_SOURCE=200809L",
+        "-D_XOPEN_SOURCE=700",
     ],
     host_supported: true,
     target: {
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index cae30b5..3afda67 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -80,7 +80,7 @@
     defaults: ["bionic_testlib_defaults"],
     srcs: ["dlext_test_library.cpp"],
     ldflags: ["-Wl,-z,norelro"],
-    shared_libs = ["libtest_simple"],
+    shared_libs: ["libtest_simple"],
 }
 
 // -----------------------------------------------------------------------------
@@ -123,7 +123,6 @@
     relative_install_path: "bionic-loader-test-libs/public_namespace_libs",
 }
 
-
 // -----------------------------------------------------------------------------
 // Library used by dlext indirect unload on the namespace boundary tests
 //
@@ -407,7 +406,6 @@
 // +-> libtest_relo_check_dt_needed_order_2.so
 // -----------------------------------------------------------------------------
 
-
 cc_test_library {
     name: "libtest_relo_check_dt_needed_order",
     defaults: ["bionic_testlib_defaults"],
@@ -457,7 +455,7 @@
     name: "libtest_ifunc_variable",
     defaults: ["bionic_testlib_defaults"],
     srcs: ["dlopen_testlib_ifunc_variable.cpp"],
-    shared_libs: [ "libtest_ifunc_variable_impl" ],
+    shared_libs: ["libtest_ifunc_variable_impl"],
 
     arch: {
         mips: {
@@ -560,7 +558,6 @@
     },
 }
 
-
 // -----------------------------------------------------------------------------
 // Library with weak function
 // -----------------------------------------------------------------------------
@@ -696,7 +693,6 @@
     srcs: ["thread_local_dtor.cpp"],
 }
 
-
 // -----------------------------------------------------------------------------
 // Tool to use to align the shared libraries in a zip file.
 // -----------------------------------------------------------------------------
diff --git a/tests/math_test.cpp b/tests/math_test.cpp
index d029311..1e7e58d 100644
--- a/tests/math_test.cpp
+++ b/tests/math_test.cpp
@@ -225,7 +225,9 @@
 // Historical BSD cruft that isn't exposed in <math.h> any more.
 extern "C" int __isfinite(double);
 extern "C" int __isfinitef(float);
+extern "C" int isfinitef(float);
 extern "C" int __isfinitel(long double);
+extern "C" int isfinitel(long double);
 
 TEST(MATH_TEST, __isfinite) {
 #if defined(__GLIBC__)
@@ -243,6 +245,14 @@
   ASSERT_FALSE(__isfinitef(HUGE_VALF));
 }
 
+TEST(MATH_TEST, isfinitef) {
+#if defined(__GLIBC__)
+#define isfinitef __finitef
+#endif
+  ASSERT_TRUE(isfinitef(123.0f));
+  ASSERT_FALSE(isfinitef(HUGE_VALF));
+}
+
 TEST(MATH_TEST, __isfinitel) {
 #if defined(__GLIBC__)
 #define __isfinitel __finitel
@@ -251,6 +261,14 @@
   ASSERT_FALSE(__isfinitel(HUGE_VALL));
 }
 
+TEST(MATH_TEST, isfinitel) {
+#if defined(__GLIBC__)
+#define isfinitel __finitel
+#endif
+  ASSERT_TRUE(isfinitel(123.0L));
+  ASSERT_FALSE(isfinitel(HUGE_VALL));
+}
+
 TEST(MATH_TEST, finite) {
   ASSERT_TRUE(finite(123.0));
   ASSERT_FALSE(finite(HUGE_VAL));
@@ -265,7 +283,9 @@
 // Historical BSD cruft that isn't exposed in <math.h> any more.
 extern "C" int __isinf(double);
 extern "C" int __isinff(float);
+extern "C" int isinff(float);
 extern "C" int __isinfl(long double);
+extern "C" int isinfl(long double);
 
 TEST(MATH_TEST, __isinf) {
   ASSERT_FALSE(__isinf(123.0));
@@ -277,11 +297,21 @@
   ASSERT_TRUE(__isinff(HUGE_VALF));
 }
 
+TEST(MATH_TEST, isinff) {
+  ASSERT_FALSE(isinff(123.0f));
+  ASSERT_TRUE(isinff(HUGE_VALF));
+}
+
 TEST(MATH_TEST, __isinfl) {
   ASSERT_FALSE(__isinfl(123.0L));
   ASSERT_TRUE(__isinfl(HUGE_VALL));
 }
 
+TEST(MATH_TEST, isinfl) {
+  ASSERT_FALSE(isinfl(123.0L));
+  ASSERT_TRUE(isinfl(HUGE_VALL));
+}
+
 TEST(MATH_TEST, isnan_function) {
   // The isnan macro deals with all three types; the isnan function is for doubles.
   ASSERT_FALSE((isnan)(123.0));
@@ -291,7 +321,9 @@
 // Historical BSD cruft that isn't exposed in <math.h> any more.
 extern "C" int __isnan(double);
 extern "C" int __isnanf(float);
+extern "C" int isnanf(float);
 extern "C" int __isnanl(long double);
+extern "C" int isnanl(long double);
 
 TEST(MATH_TEST, __isnan) {
   ASSERT_FALSE(__isnan(123.0));
@@ -303,20 +335,27 @@
   ASSERT_TRUE(__isnanf(nanf("")));
 }
 
-TEST(MATH_TEST, __isnanl) {
-  ASSERT_FALSE(__isnanl(123.0L));
-  ASSERT_TRUE(__isnanl(nanl("")));
-}
-
 TEST(MATH_TEST, isnanf) {
   ASSERT_FALSE(isnanf(123.0f));
   ASSERT_TRUE(isnanf(nanf("")));
 }
 
+TEST(MATH_TEST, __isnanl) {
+  ASSERT_FALSE(__isnanl(123.0L));
+  ASSERT_TRUE(__isnanl(nanl("")));
+}
+
+TEST(MATH_TEST, isnanl) {
+  ASSERT_FALSE(isnanl(123.0L));
+  ASSERT_TRUE(isnanl(nanl("")));
+}
+
 // Historical BSD cruft that isn't exposed in <math.h> any more.
 extern "C" int __isnormal(double);
 extern "C" int __isnormalf(float);
+extern "C" int isnormalf(float);
 extern "C" int __isnormall(long double);
+extern "C" int isnormall(long double);
 
 TEST(MATH_TEST, __isnormal) {
 #if defined(__BIONIC__)
@@ -336,6 +375,15 @@
 #endif // __BIONIC__
 }
 
+TEST(MATH_TEST, isnormalf) {
+#if defined(__BIONIC__)
+  ASSERT_TRUE(isnormalf(123.0f));
+  ASSERT_FALSE(isnormalf(float_subnormal()));
+#else // __BIONIC__
+  GTEST_LOG_(INFO) << "glibc doesn't have isnormalf.\n";
+#endif // __BIONIC__
+}
+
 TEST(MATH_TEST, __isnormall) {
 #if defined(__BIONIC__)
   ASSERT_TRUE(__isnormall(123.0L));
@@ -345,6 +393,15 @@
 #endif // __BIONIC__
 }
 
+TEST(MATH_TEST, isnormall) {
+#if defined(__BIONIC__)
+  ASSERT_TRUE(isnormall(123.0L));
+  ASSERT_FALSE(isnormall(ldouble_subnormal()));
+#else // __BIONIC__
+  GTEST_LOG_(INFO) << "glibc doesn't have isnormall.\n";
+#endif // __BIONIC__
+}
+
 // Historical BSD cruft that isn't exposed in <math.h> any more.
 extern "C" int __signbit(double);
 extern "C" int __signbitf(float);
@@ -957,7 +1014,7 @@
 TEST(MATH_TEST, logbf) {
   ASSERT_EQ(-HUGE_VALF, logbf(0.0f));
   ASSERT_TRUE(isnanf(logbf(nanf(""))));
-  ASSERT_TRUE(__isinff(logbf(HUGE_VALF)));
+  ASSERT_TRUE(isinff(logbf(HUGE_VALF)));
   ASSERT_EQ(0.0f, logbf(1.0f));
   ASSERT_EQ(3.0f, logbf(10.0f));
 }
@@ -980,7 +1037,7 @@
 TEST(MATH_TEST, log1pf) {
   ASSERT_EQ(-HUGE_VALF, log1pf(-1.0f));
   ASSERT_TRUE(isnanf(log1pf(nanf(""))));
-  ASSERT_TRUE(__isinff(log1pf(HUGE_VALF)));
+  ASSERT_TRUE(isinff(log1pf(HUGE_VALF)));
   ASSERT_FLOAT_EQ(1.0f, log1pf(static_cast<float>(M_E) - 1.0f));
 }
 
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 9ecb10c..dd7879c 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -356,9 +356,9 @@
 }
 
 static void* SignalHandlerFn(void* arg) {
-  sigset_t wait_set;
-  sigfillset(&wait_set);
-  return reinterpret_cast<void*>(sigwait(&wait_set, reinterpret_cast<int*>(arg)));
+  sigset64_t wait_set;
+  sigfillset64(&wait_set);
+  return reinterpret_cast<void*>(sigwait64(&wait_set, reinterpret_cast<int*>(arg)));
 }
 
 TEST(pthread, pthread_sigmask) {
@@ -402,6 +402,47 @@
   ASSERT_EQ(0, pthread_sigmask(SIG_SETMASK, &original_set, NULL));
 }
 
+TEST(pthread, pthread_sigmask64_SIGTRMIN) {
+  // Check that SIGRTMIN isn't blocked.
+  sigset64_t original_set;
+  sigemptyset64(&original_set);
+  ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, NULL, &original_set));
+  ASSERT_FALSE(sigismember64(&original_set, SIGRTMIN));
+
+  // Block SIGRTMIN.
+  sigset64_t set;
+  sigemptyset64(&set);
+  sigaddset64(&set, SIGRTMIN);
+  ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, &set, NULL));
+
+  // Check that SIGRTMIN is blocked.
+  sigset64_t final_set;
+  sigemptyset64(&final_set);
+  ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, NULL, &final_set));
+  ASSERT_TRUE(sigismember64(&final_set, SIGRTMIN));
+  // ...and that sigprocmask64 agrees with pthread_sigmask64.
+  sigemptyset64(&final_set);
+  ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, NULL, &final_set));
+  ASSERT_TRUE(sigismember64(&final_set, SIGRTMIN));
+
+  // Spawn a thread that calls sigwait64 and tells us what it received.
+  pthread_t signal_thread;
+  int received_signal = -1;
+  ASSERT_EQ(0, pthread_create(&signal_thread, NULL, SignalHandlerFn, &received_signal));
+
+  // Send that thread SIGRTMIN.
+  pthread_kill(signal_thread, SIGRTMIN);
+
+  // See what it got.
+  void* join_result;
+  ASSERT_EQ(0, pthread_join(signal_thread, &join_result));
+  ASSERT_EQ(SIGRTMIN, received_signal);
+  ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(join_result));
+
+  // Restore the original signal mask.
+  ASSERT_EQ(0, pthread_sigmask64(SIG_SETMASK, &original_set, NULL));
+}
+
 static void test_pthread_setname_np__pthread_getname_np(pthread_t t) {
   ASSERT_EQ(0, pthread_setname_np(t, "short"));
   char name[32];
@@ -873,7 +914,7 @@
   ASSERT_EQ(0, pthread_rwlock_rdlock(&wakeup_arg.lock));
   wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_INITIALIZED;
   wakeup_arg.tid = 0;
-  wakeup_arg.trylock_function = pthread_rwlock_trywrlock;
+  wakeup_arg.trylock_function = &pthread_rwlock_trywrlock;
   wakeup_arg.lock_function = lock_function;
 
   pthread_t thread;
@@ -909,7 +950,7 @@
   ASSERT_EQ(0, pthread_rwlock_wrlock(&wakeup_arg.lock));
   wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_INITIALIZED;
   wakeup_arg.tid = 0;
-  wakeup_arg.trylock_function = pthread_rwlock_tryrdlock;
+  wakeup_arg.trylock_function = &pthread_rwlock_tryrdlock;
   wakeup_arg.lock_function = lock_function;
 
   pthread_t thread;
@@ -969,8 +1010,8 @@
   ASSERT_EQ(0, pthread_rwlock_wrlock(&wakeup_arg.lock));
   wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_INITIALIZED;
   wakeup_arg.tid = 0;
-  wakeup_arg.trylock_function = pthread_rwlock_tryrdlock;
-  wakeup_arg.timed_lock_function = pthread_rwlock_timedrdlock;
+  wakeup_arg.trylock_function = &pthread_rwlock_tryrdlock;
+  wakeup_arg.timed_lock_function = &pthread_rwlock_timedrdlock;
 
   pthread_t thread;
   ASSERT_EQ(0, pthread_create(&thread, nullptr,
@@ -990,8 +1031,8 @@
   ASSERT_EQ(0, pthread_rwlock_rdlock(&wakeup_arg.lock));
   wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_INITIALIZED;
   wakeup_arg.tid = 0;
-  wakeup_arg.trylock_function = pthread_rwlock_trywrlock;
-  wakeup_arg.timed_lock_function = pthread_rwlock_timedwrlock;
+  wakeup_arg.trylock_function = &pthread_rwlock_trywrlock;
+  wakeup_arg.timed_lock_function = &pthread_rwlock_timedwrlock;
 
   pthread_t thread;
   ASSERT_EQ(0, pthread_create(&thread, nullptr,
@@ -1378,18 +1419,23 @@
   EXPECT_EQ(stack_size, stack_size2);
 
 #if defined(__BIONIC__)
-  // What does /proc/self/maps' [stack] line say?
+  // Find stack in /proc/self/maps using a pointer to the stack.
+  //
+  // We do not use "[stack]" label because in native-bridge environment it is not
+  // guaranteed to point to the right stack. A native bridge implementation may
+  // keep separate stack for the guest code.
   void* maps_stack_hi = NULL;
   std::vector<map_record> maps;
   ASSERT_TRUE(Maps::parse_maps(&maps));
+  uintptr_t stack_address = reinterpret_cast<uintptr_t>(&maps_stack_hi);
   for (const auto& map : maps) {
-    if (map.pathname == "[stack]") {
+    if (map.addr_start <= stack_address && map.addr_end > stack_address){
       maps_stack_hi = reinterpret_cast<void*>(map.addr_end);
       break;
     }
   }
 
-  // The high address of the /proc/self/maps [stack] region should equal stack_base + stack_size.
+  // The high address of the /proc/self/maps stack region should equal stack_base + stack_size.
   // Remember that the stack grows down (and is mapped in on demand), so the low address of the
   // region isn't very interesting.
   EXPECT_EQ(maps_stack_hi, reinterpret_cast<uint8_t*>(stack_base) + stack_size);
@@ -1672,6 +1718,7 @@
 
   void destroy() {
     ASSERT_EQ(0, pthread_mutex_destroy(&lock));
+    ASSERT_EQ(EBUSY, pthread_mutex_destroy(&lock));
   }
 
   DISALLOW_COPY_AND_ASSIGN(PthreadMutex);
@@ -1730,15 +1777,42 @@
 }
 
 TEST(pthread, pthread_mutex_lock_pi) {
-#if defined(__BIONIC__) && !defined(__LP64__)
-  GTEST_LOG_(INFO) << "PTHREAD_PRIO_INHERIT isn't supported in 32bit programs, skipping test";
-  return;
-#endif
   TestPthreadMutexLockNormal(PTHREAD_PRIO_INHERIT);
   TestPthreadMutexLockErrorCheck(PTHREAD_PRIO_INHERIT);
   TestPthreadMutexLockRecursive(PTHREAD_PRIO_INHERIT);
 }
 
+TEST(pthread, pthread_mutex_pi_count_limit) {
+#if defined(__BIONIC__) && !defined(__LP64__)
+  // Bionic only supports 65536 pi mutexes in 32-bit programs.
+  pthread_mutexattr_t attr;
+  ASSERT_EQ(0, pthread_mutexattr_init(&attr));
+  ASSERT_EQ(0, pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT));
+  std::vector<pthread_mutex_t> mutexes(65536);
+  // Test if we can use 65536 pi mutexes at the same time.
+  // Run 2 times to check if freed pi mutexes can be recycled.
+  for (int repeat = 0; repeat < 2; ++repeat) {
+    for (auto& m : mutexes) {
+      ASSERT_EQ(0, pthread_mutex_init(&m, &attr));
+    }
+    pthread_mutex_t m;
+    ASSERT_EQ(ENOMEM, pthread_mutex_init(&m, &attr));
+    for (auto& m : mutexes) {
+      ASSERT_EQ(0, pthread_mutex_lock(&m));
+    }
+    for (auto& m : mutexes) {
+      ASSERT_EQ(0, pthread_mutex_unlock(&m));
+    }
+    for (auto& m : mutexes) {
+      ASSERT_EQ(0, pthread_mutex_destroy(&m));
+    }
+  }
+  ASSERT_EQ(0, pthread_mutexattr_destroy(&attr));
+#else
+  GTEST_LOG_(INFO) << "This test does nothing as pi mutex count isn't limited.\n";
+#endif
+}
+
 TEST(pthread, pthread_mutex_init_same_as_static_initializers) {
   pthread_mutex_t lock_normal = PTHREAD_MUTEX_INITIALIZER;
   PthreadMutex m1(PTHREAD_MUTEX_NORMAL);
@@ -1755,6 +1829,7 @@
   ASSERT_EQ(0, memcmp(&lock_recursive, &m3.lock, sizeof(pthread_mutex_t)));
   ASSERT_EQ(0, pthread_mutex_destroy(&lock_recursive));
 }
+
 class MutexWakeupHelper {
  private:
   PthreadMutex m;
@@ -1903,10 +1978,6 @@
 };
 
 TEST(pthread, pthread_mutex_pi_wakeup) {
-#if defined(__BIONIC__) && !defined(__LP64__)
-  GTEST_LOG_(INFO) << "PTHREAD_PRIO_INHERIT isn't supported in 32bit programs, skipping test";
-  return;
-#endif
   for (int type : {PTHREAD_MUTEX_NORMAL, PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK}) {
     for (int protocol : {PTHREAD_PRIO_INHERIT}) {
       PIMutexWakeupHelper helper(type, protocol);
@@ -1959,10 +2030,6 @@
 }
 
 TEST(pthread, pthread_mutex_timedlock_pi) {
-#if defined(__BIONIC__) && !defined(__LP64__)
-  GTEST_LOG_(INFO) << "PTHREAD_PRIO_INHERIT isn't supported in 32bit programs, skipping test";
-  return;
-#endif
   PthreadMutex m(PTHREAD_MUTEX_NORMAL, PTHREAD_PRIO_INHERIT);
   timespec ts;
   clock_gettime(CLOCK_REALTIME, &ts);
diff --git a/tests/setjmp_test.cpp b/tests/setjmp_test.cpp
index bb01601..4f5e60c 100644
--- a/tests/setjmp_test.cpp
+++ b/tests/setjmp_test.cpp
@@ -19,6 +19,8 @@
 #include <setjmp.h>
 #include <stdlib.h>
 
+#include "ScopedSignalHandler.h"
+
 TEST(setjmp, setjmp_smoke) {
   int value;
   jmp_buf jb;
@@ -63,61 +65,59 @@
   }
 }
 
-// Two distinct signal sets, pipu
+// Two distinct signal sets.
 struct SigSets {
   SigSets() : one(MakeSigSet(0)), two(MakeSigSet(1)) {
   }
 
-  static sigset_t MakeSigSet(int offset) {
-    sigset_t ss;
-    sigemptyset(&ss);
-    sigaddset(&ss, SIGUSR1 + offset);
-#if defined(__LP64__)
-    // For arm and x86, sigset_t was too small for the RT signals.
-    // For mips, sigset_t was large enough but jmp_buf wasn't.
-    sigaddset(&ss, SIGRTMIN + offset);
-#endif
+  static sigset64_t MakeSigSet(int offset) {
+    sigset64_t ss;
+    sigemptyset64(&ss);
+    sigaddset64(&ss, SIGUSR1 + offset);
+    sigaddset64(&ss, SIGRTMIN + offset);
     return ss;
   }
 
-  sigset_t one;
-  sigset_t two;
-  sigset_t original;
+  sigset64_t one;
+  sigset64_t two;
 };
 
-void AssertSigmaskEquals(const sigset_t& expected) {
-  sigset_t actual;
-  sigprocmask(0 /* ignored */, NULL, &actual);
-  size_t end = sizeof(sigset_t) * 8;
+void AssertSigmaskEquals(const sigset64_t& expected) {
+  sigset64_t actual;
+  sigprocmask64(SIG_SETMASK, NULL, &actual);
+  size_t end = sizeof(expected) * 8;
   for (size_t i = 1; i <= end; ++i) {
-    EXPECT_EQ(sigismember(&expected, i), sigismember(&actual, i)) << i;
+    EXPECT_EQ(sigismember64(&expected, i), sigismember64(&actual, i)) << i;
   }
 }
 
 TEST(setjmp, _setjmp_signal_mask) {
+  SignalMaskRestorer smr;
+
   // _setjmp/_longjmp do not save/restore the signal mask.
   SigSets ss;
-  sigprocmask(SIG_SETMASK, &ss.one, &ss.original);
+  sigprocmask64(SIG_SETMASK, &ss.one, nullptr);
   jmp_buf jb;
   if (_setjmp(jb) == 0) {
-    sigprocmask(SIG_SETMASK, &ss.two, NULL);
+    sigprocmask64(SIG_SETMASK, &ss.two, NULL);
     _longjmp(jb, 1);
     FAIL(); // Unreachable.
   } else {
     AssertSigmaskEquals(ss.two);
   }
-  sigprocmask(SIG_SETMASK, &ss.original, NULL);
 }
 
 TEST(setjmp, setjmp_signal_mask) {
+  SignalMaskRestorer smr;
+
   // setjmp/longjmp do save/restore the signal mask on bionic, but not on glibc.
   // This is a BSD versus System V historical accident. POSIX leaves the
   // behavior unspecified, so any code that cares needs to use sigsetjmp.
   SigSets ss;
-  sigprocmask(SIG_SETMASK, &ss.one, &ss.original);
+  sigprocmask64(SIG_SETMASK, &ss.one, nullptr);
   jmp_buf jb;
   if (setjmp(jb) == 0) {
-    sigprocmask(SIG_SETMASK, &ss.two, NULL);
+    sigprocmask64(SIG_SETMASK, &ss.two, NULL);
     longjmp(jb, 1);
     FAIL(); // Unreachable.
   } else {
@@ -129,37 +129,38 @@
     AssertSigmaskEquals(ss.two);
 #endif
   }
-  sigprocmask(SIG_SETMASK, &ss.original, NULL);
 }
 
 TEST(setjmp, sigsetjmp_0_signal_mask) {
+  SignalMaskRestorer smr;
+
   // sigsetjmp(0)/siglongjmp do not save/restore the signal mask.
   SigSets ss;
-  sigprocmask(SIG_SETMASK, &ss.one, &ss.original);
+  sigprocmask64(SIG_SETMASK, &ss.one, nullptr);
   sigjmp_buf sjb;
   if (sigsetjmp(sjb, 0) == 0) {
-    sigprocmask(SIG_SETMASK, &ss.two, NULL);
+    sigprocmask64(SIG_SETMASK, &ss.two, NULL);
     siglongjmp(sjb, 1);
     FAIL(); // Unreachable.
   } else {
     AssertSigmaskEquals(ss.two);
   }
-  sigprocmask(SIG_SETMASK, &ss.original, NULL);
 }
 
 TEST(setjmp, sigsetjmp_1_signal_mask) {
+  SignalMaskRestorer smr;
+
   // sigsetjmp(1)/siglongjmp does save/restore the signal mask.
   SigSets ss;
-  sigprocmask(SIG_SETMASK, &ss.one, &ss.original);
+  sigprocmask64(SIG_SETMASK, &ss.one, nullptr);
   sigjmp_buf sjb;
   if (sigsetjmp(sjb, 1) == 0) {
-    sigprocmask(SIG_SETMASK, &ss.two, NULL);
+    sigprocmask64(SIG_SETMASK, &ss.two, NULL);
     siglongjmp(sjb, 1);
     FAIL(); // Unreachable.
   } else {
     AssertSigmaskEquals(ss.one);
   }
-  sigprocmask(SIG_SETMASK, &ss.original, NULL);
 }
 
 #if defined(__aarch64__)
@@ -218,7 +219,7 @@
 #elif defined(__aarch64__)
 #define __JB_SIGFLAG 0
 #elif defined(__i386__)
-#define __JB_SIGFLAG 7
+#define __JB_SIGFLAG 8
 #elif defined(__x86_64)
 #define __JB_SIGFLAG 8
 #elif defined(__mips__) && defined(__LP64__)
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index 5cbec88..b37d06f 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -20,57 +20,45 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <thread>
+
 #include <gtest/gtest.h>
 
 #include "ScopedSignalHandler.h"
 
-static size_t SIGNAL_MIN() {
+static int SIGNAL_MIN() {
   return 1; // Signals start at 1 (SIGHUP), not 0.
 }
 
-static size_t SIGNAL_MAX() {
-  size_t result = SIGRTMAX;
-
-#if defined(__BIONIC__) && !defined(__mips__) && !defined(__LP64__)
-  // 32-bit bionic's sigset_t is too small for ARM and x86: 32 bits instead of 64.
-  // This means you can't refer to any of the real-time signals.
-  // See http://b/3038348 and http://b/5828899.
-  result = 32;
-#else
-  // Otherwise, C libraries should be perfectly capable of using their largest signal.
-  if (sizeof(sigset_t) * 8 < static_cast<size_t>(SIGRTMAX)) {
-    abort();
-  }
-#endif
-
-  return result;
+template <typename SigSetT>
+static int SIGNAL_MAX(SigSetT* set) {
+  return sizeof(*set) * 8;
 }
 
-template <typename Fn>
-static void TestSigSet1(Fn fn) {
-  // NULL sigset_t*.
-  sigset_t* set_ptr = NULL;
+template <typename SigSetT>
+static void TestSigSet1(int (fn)(SigSetT*)) {
+  // NULL sigset_t*/sigset64_t*.
+  SigSetT* set_ptr = NULL;
   errno = 0;
   ASSERT_EQ(-1, fn(set_ptr));
   ASSERT_EQ(EINVAL, errno);
 
   // Non-NULL.
-  sigset_t set;
+  SigSetT set = {};
   errno = 0;
   ASSERT_EQ(0, fn(&set));
   ASSERT_EQ(0, errno);
 }
 
-template <typename Fn>
-static void TestSigSet2(Fn fn) {
-  // NULL sigset_t*.
-  sigset_t* set_ptr = NULL;
+template <typename SigSetT>
+static void TestSigSet2(int (fn)(SigSetT*, int)) {
+  // NULL sigset_t*/sigset64_t*.
+  SigSetT* set_ptr = NULL;
   errno = 0;
   ASSERT_EQ(-1, fn(set_ptr, SIGSEGV));
   ASSERT_EQ(EINVAL, errno);
 
-  sigset_t set;
-  sigemptyset(&set);
+  SigSetT set = {};
 
   // Bad signal number: too small.
   errno = 0;
@@ -79,37 +67,67 @@
 
   // Bad signal number: too high.
   errno = 0;
-  ASSERT_EQ(-1, fn(&set, SIGNAL_MAX() + 1));
+  ASSERT_EQ(-1, fn(&set, SIGNAL_MAX(&set) + 1));
   ASSERT_EQ(EINVAL, errno);
 
   // Good signal numbers, low and high ends of range.
   errno = 0;
   ASSERT_EQ(0, fn(&set, SIGNAL_MIN()));
   ASSERT_EQ(0, errno);
-  ASSERT_EQ(0, fn(&set, SIGNAL_MAX()));
+  ASSERT_EQ(0, fn(&set, SIGNAL_MAX(&set)));
   ASSERT_EQ(0, errno);
 }
 
-TEST(signal, sigismember_invalid) {
-  TestSigSet2(sigismember);
-}
-
 TEST(signal, sigaddset_invalid) {
   TestSigSet2(sigaddset);
 }
 
+TEST(signal, sigaddset64_invalid) {
+#if defined(__BIONIC__)
+  TestSigSet2(sigaddset64);
+#endif
+}
+
 TEST(signal, sigdelset_invalid) {
   TestSigSet2(sigdelset);
 }
 
+TEST(signal, sigdelset64_invalid) {
+#if defined(__BIONIC__)
+  TestSigSet2(sigdelset64);
+#endif
+}
+
 TEST(signal, sigemptyset_invalid) {
   TestSigSet1(sigemptyset);
 }
 
+TEST(signal, sigemptyset64_invalid) {
+#if defined(__BIONIC__)
+  TestSigSet1(sigemptyset64);
+#endif
+}
+
 TEST(signal, sigfillset_invalid) {
   TestSigSet1(sigfillset);
 }
 
+TEST(signal, sigfillset64_invalid) {
+#if defined(__BIONIC__)
+  TestSigSet1(sigfillset64);
+#endif
+}
+
+TEST(signal, sigismember_invalid) {
+  TestSigSet2(sigismember);
+}
+
+TEST(signal, sigismember64_invalid) {
+#if defined(__BIONIC__)
+  TestSigSet2(sigismember64);
+#endif
+}
+
 TEST(signal, raise_invalid) {
   errno = 0;
   ASSERT_EQ(-1, raise(-1));
@@ -129,12 +147,8 @@
   raise(SIGALRM);
 }
 
-static void HandleSIGALRM(int signal_number) {
-  ASSERT_EQ(SIGALRM, signal_number);
-}
-
-TEST(signal, sigwait) {
-  ScopedSignalHandler ssh(SIGALRM, HandleSIGALRM);
+TEST(signal, sigwait_SIGALRM) {
+  ScopedSignalHandler ssh(SIGALRM, [](int sig) { ASSERT_EQ(SIGALRM, sig); });
 
   sigset_t wait_set;
   sigemptyset(&wait_set);
@@ -149,38 +163,57 @@
   ASSERT_EQ(SIGALRM, received_signal);
 }
 
-static int g_sigsuspend_test_helper_call_count = 0;
+TEST(signal, sigwait64_SIGRTMIN) {
+  ScopedSignalHandler ssh(SIGRTMIN, [](int sig) { ASSERT_EQ(SIGRTMIN, sig); });
 
-static void SigSuspendTestHelper(int) {
-  ++g_sigsuspend_test_helper_call_count;
+  sigset64_t wait_set;
+  sigemptyset64(&wait_set);
+  sigaddset64(&wait_set, SIGRTMIN);
+
+  pid_t pid = getpid();
+  std::thread thread([&pid]() {
+    usleep(5000);
+    kill(pid, SIGRTMIN);
+  });
+
+  int received_signal;
+  errno = 0;
+  ASSERT_EQ(0, sigwait64(&wait_set, &received_signal));
+  ASSERT_EQ(0, errno);
+  ASSERT_EQ(SIGRTMIN, received_signal);
+
+  thread.join();
 }
 
+static int g_sigsuspend_signal_handler_call_count = 0;
+
 TEST(signal, sigsuspend_sigpending) {
+  SignalMaskRestorer smr;
+
   // Block SIGALRM.
   sigset_t just_SIGALRM;
   sigemptyset(&just_SIGALRM);
   sigaddset(&just_SIGALRM, SIGALRM);
-  sigset_t original_set;
-  ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set));
+  ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr));
 
-  ScopedSignalHandler ssh(SIGALRM, SigSuspendTestHelper);
+  ScopedSignalHandler ssh(SIGALRM, [](int) { ++g_sigsuspend_signal_handler_call_count; });
 
   // There should be no pending signals.
   sigset_t pending;
   sigemptyset(&pending);
   ASSERT_EQ(0, sigpending(&pending));
-  for (size_t i = SIGNAL_MIN(); i <= SIGNAL_MAX(); ++i) {
+  for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) {
     EXPECT_FALSE(sigismember(&pending, i)) << i;
   }
 
   // Raise SIGALRM and check our signal handler wasn't called.
   raise(SIGALRM);
-  ASSERT_EQ(0, g_sigsuspend_test_helper_call_count);
+  ASSERT_EQ(0, g_sigsuspend_signal_handler_call_count);
 
   // We should now have a pending SIGALRM but nothing else.
   sigemptyset(&pending);
   ASSERT_EQ(0, sigpending(&pending));
-  for (size_t i = SIGNAL_MIN(); i <= SIGNAL_MAX(); ++i) {
+  for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) {
     EXPECT_EQ((i == SIGALRM), sigismember(&pending, i));
   }
 
@@ -191,61 +224,325 @@
   ASSERT_EQ(-1, sigsuspend(&not_SIGALRM));
   ASSERT_EQ(EINTR, errno);
   // ...and check that we now receive our pending SIGALRM.
-  ASSERT_EQ(1, g_sigsuspend_test_helper_call_count);
-
-  // Restore the original set.
-  ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL));
+  ASSERT_EQ(1, g_sigsuspend_signal_handler_call_count);
 }
 
-static void EmptySignalHandler(int) {}
-static void EmptySignalAction(int, siginfo_t*, void*) {}
+static int g_sigsuspend64_signal_handler_call_count = 0;
 
-TEST(signal, sigaction) {
+TEST(signal, sigsuspend64_sigpending64) {
+  SignalMaskRestorer smr;
+
+  // Block SIGRTMIN.
+  sigset64_t just_SIGRTMIN;
+  sigemptyset64(&just_SIGRTMIN);
+  sigaddset64(&just_SIGRTMIN, SIGRTMIN);
+  ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr));
+
+  ScopedSignalHandler ssh(SIGRTMIN, [](int) { ++g_sigsuspend64_signal_handler_call_count; });
+
+  // There should be no pending signals.
+  sigset64_t pending;
+  sigemptyset64(&pending);
+  ASSERT_EQ(0, sigpending64(&pending));
+  for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) {
+    EXPECT_FALSE(sigismember64(&pending, i)) << i;
+  }
+
+  // Raise SIGRTMIN and check our signal handler wasn't called.
+  raise(SIGRTMIN);
+  ASSERT_EQ(0, g_sigsuspend64_signal_handler_call_count);
+
+  // We should now have a pending SIGRTMIN but nothing else.
+  sigemptyset64(&pending);
+  ASSERT_EQ(0, sigpending64(&pending));
+  for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) {
+    EXPECT_EQ((i == SIGRTMIN), sigismember64(&pending, i));
+  }
+
+  // Use sigsuspend64 to block everything except SIGRTMIN...
+  sigset64_t not_SIGRTMIN;
+  sigfillset64(&not_SIGRTMIN);
+  sigdelset64(&not_SIGRTMIN, SIGRTMIN);
+  ASSERT_EQ(-1, sigsuspend64(&not_SIGRTMIN));
+  ASSERT_EQ(EINTR, errno);
+  // ...and check that we now receive our pending SIGRTMIN.
+  ASSERT_EQ(1, g_sigsuspend64_signal_handler_call_count);
+}
+
+template <typename SigActionT, typename SigSetT>
+static void TestSigAction(int (sigaction_fn)(int, const SigActionT*, SigActionT*),
+                          int (sigaddset_fn)(SigSetT*, int),
+                          int sig) {
   // Both bionic and glibc set SA_RESTORER when talking to the kernel on arm,
   // arm64, x86, and x86-64. The version of glibc we're using also doesn't
   // define SA_RESTORER, but luckily it's the same value everywhere, and mips
   // doesn't use the bit for anything.
   static const unsigned sa_restorer = 0x4000000;
 
-  // See what's currently set for SIGALRM.
-  struct sigaction original_sa;
-  memset(&original_sa, 0, sizeof(original_sa));
-  ASSERT_EQ(0, sigaction(SIGALRM, NULL, &original_sa));
+  // See what's currently set for this signal.
+  SigActionT original_sa = {};
+  ASSERT_EQ(0, sigaction_fn(sig, NULL, &original_sa));
   ASSERT_TRUE(original_sa.sa_handler == NULL);
   ASSERT_TRUE(original_sa.sa_sigaction == NULL);
   ASSERT_EQ(0U, original_sa.sa_flags & ~sa_restorer);
+#ifdef SA_RESTORER
+  ASSERT_EQ(bool(original_sa.sa_flags & sa_restorer), bool(original_sa.sa_restorer));
+#endif
 
   // Set a traditional sa_handler signal handler.
-  struct sigaction sa;
-  memset(&sa, 0, sizeof(sa));
-  sigaddset(&sa.sa_mask, SIGALRM);
+  auto no_op_signal_handler = [](int) {};
+  SigActionT sa = {};
+  sigaddset_fn(&sa.sa_mask, sig);
   sa.sa_flags = SA_ONSTACK;
-  sa.sa_handler = EmptySignalHandler;
-  ASSERT_EQ(0, sigaction(SIGALRM, &sa, NULL));
+  sa.sa_handler = no_op_signal_handler;
+  ASSERT_EQ(0, sigaction_fn(sig, &sa, NULL));
 
   // Check that we can read it back.
-  memset(&sa, 0, sizeof(sa));
-  ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa));
-  ASSERT_TRUE(sa.sa_handler == EmptySignalHandler);
+  sa = {};
+  ASSERT_EQ(0, sigaction_fn(sig, NULL, &sa));
+  ASSERT_TRUE(sa.sa_handler == no_op_signal_handler);
   ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler);
   ASSERT_EQ(static_cast<unsigned>(SA_ONSTACK), sa.sa_flags & ~sa_restorer);
+#ifdef SA_RESTORER
+  ASSERT_EQ(bool(sa.sa_flags & sa_restorer), bool(sa.sa_restorer));
+#endif
 
   // Set a new-style sa_sigaction signal handler.
-  memset(&sa, 0, sizeof(sa));
-  sigaddset(&sa.sa_mask, SIGALRM);
+  auto no_op_sigaction = [](int, siginfo_t*, void*) {};
+  sa = {};
+  sigaddset_fn(&sa.sa_mask, sig);
   sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
-  sa.sa_sigaction = EmptySignalAction;
-  ASSERT_EQ(0, sigaction(SIGALRM, &sa, NULL));
+  sa.sa_sigaction = no_op_sigaction;
+  ASSERT_EQ(0, sigaction_fn(sig, &sa, NULL));
 
   // Check that we can read it back.
-  memset(&sa, 0, sizeof(sa));
-  ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa));
-  ASSERT_TRUE(sa.sa_sigaction == EmptySignalAction);
+  sa = {};
+  ASSERT_EQ(0, sigaction_fn(sig, NULL, &sa));
+  ASSERT_TRUE(sa.sa_sigaction == no_op_sigaction);
   ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler);
   ASSERT_EQ(static_cast<unsigned>(SA_ONSTACK | SA_SIGINFO), sa.sa_flags & ~sa_restorer);
+#ifdef SA_RESTORER
+  ASSERT_EQ(bool(sa.sa_flags & sa_restorer), bool(sa.sa_restorer));
+#endif
 
   // Put everything back how it was.
-  ASSERT_EQ(0, sigaction(SIGALRM, &original_sa, NULL));
+  ASSERT_EQ(0, sigaction_fn(sig, &original_sa, NULL));
+}
+
+TEST(signal, sigaction) {
+  TestSigAction(sigaction, sigaddset, SIGALRM);
+}
+
+TEST(signal, sigaction64_SIGRTMIN) {
+  TestSigAction(sigaction64, sigaddset64, SIGRTMIN);
+}
+
+static void ClearSignalMask() {
+  uint64_t sigset = 0;
+  if (syscall(__NR_rt_sigprocmask, SIG_SETMASK, &sigset, nullptr, sizeof(sigset)) != 0) {
+    abort();
+  }
+}
+
+static uint64_t GetSignalMask() {
+  uint64_t sigset;
+  if (syscall(__NR_rt_sigprocmask, SIG_SETMASK, nullptr, &sigset, sizeof(sigset)) != 0) {
+    abort();
+  }
+  return sigset;
+}
+
+enum class SignalMaskFunctionType {
+  RtAware,
+  RtNonaware,
+};
+
+#if defined(__LP64__) || !defined(__BIONIC__)
+constexpr SignalMaskFunctionType sigset_type = SignalMaskFunctionType::RtAware;
+#else
+constexpr SignalMaskFunctionType sigset_type = SignalMaskFunctionType::RtNonaware;
+#endif
+
+static void TestSignalMaskFiltered(uint64_t sigset, SignalMaskFunctionType type) {
+  for (int signo = 1; signo <= 64; ++signo) {
+    bool signal_blocked = sigset & (1ULL << (signo - 1));
+    if (signo == SIGKILL || signo == SIGSTOP) {
+      // SIGKILL and SIGSTOP shouldn't be blocked.
+      EXPECT_EQ(false, signal_blocked) << "signal " << signo;
+    } else if (signo < __SIGRTMIN) {
+      // Everything else should be blocked.
+      EXPECT_EQ(true, signal_blocked) << "signal " << signo;
+    } else if (signo >= __SIGRTMIN && signo < SIGRTMIN) {
+      // Reserved signals must not be blocked.
+      EXPECT_EQ(false, signal_blocked) << "signal " << signo;
+    } else if (type == SignalMaskFunctionType::RtAware) {
+      // Realtime signals should be blocked, unless we blocked using a non-rt aware function.
+      EXPECT_EQ(true, signal_blocked) << "signal " << signo;
+    }
+  }
+}
+
+static void TestSignalMaskFunction(std::function<void()> fn, SignalMaskFunctionType fn_type) {
+  ClearSignalMask();
+  fn();
+  TestSignalMaskFiltered(GetSignalMask(), fn_type);
+}
+
+TEST(signal, sigaction_filter) {
+  ClearSignalMask();
+  static uint64_t sigset;
+  struct sigaction sa = {};
+  sa.sa_handler = [](int) { sigset = GetSignalMask(); };
+  sigfillset(&sa.sa_mask);
+  sigaction(SIGUSR1, &sa, nullptr);
+  raise(SIGUSR1);
+  ASSERT_NE(0ULL, sigset);
+  TestSignalMaskFiltered(sigset, sigset_type);
+}
+
+TEST(signal, sigaction64_filter) {
+  ClearSignalMask();
+  static uint64_t sigset;
+  struct sigaction64 sa = {};
+  sa.sa_handler = [](int) { sigset = GetSignalMask(); };
+  sigfillset64(&sa.sa_mask);
+  sigaction64(SIGUSR1, &sa, nullptr);
+  raise(SIGUSR1);
+  ASSERT_NE(0ULL, sigset);
+  TestSignalMaskFiltered(sigset, SignalMaskFunctionType::RtAware);
+}
+
+TEST(signal, sigprocmask_setmask_filter) {
+  TestSignalMaskFunction(
+      []() {
+        sigset_t sigset_libc;
+        sigfillset(&sigset_libc);
+        ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &sigset_libc, nullptr));
+      },
+      sigset_type);
+}
+
+TEST(signal, sigprocmask64_setmask_filter) {
+  TestSignalMaskFunction(
+      []() {
+        sigset64_t sigset_libc;
+        sigfillset64(&sigset_libc);
+        ASSERT_EQ(0, sigprocmask64(SIG_SETMASK, &sigset_libc, nullptr));
+      },
+      SignalMaskFunctionType::RtAware);
+}
+
+TEST(signal, pthread_sigmask_setmask_filter) {
+  TestSignalMaskFunction(
+      []() {
+        sigset_t sigset_libc;
+        sigfillset(&sigset_libc);
+        ASSERT_EQ(0, pthread_sigmask(SIG_SETMASK, &sigset_libc, nullptr));
+      },
+      sigset_type);
+}
+
+TEST(signal, pthread_sigmask64_setmask_filter) {
+  TestSignalMaskFunction(
+      []() {
+        sigset64_t sigset_libc;
+        sigfillset64(&sigset_libc);
+        ASSERT_EQ(0, pthread_sigmask64(SIG_SETMASK, &sigset_libc, nullptr));
+      },
+      SignalMaskFunctionType::RtAware);
+}
+
+TEST(signal, sigprocmask_block_filter) {
+  TestSignalMaskFunction(
+      []() {
+        sigset_t sigset_libc;
+        sigfillset(&sigset_libc);
+        ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &sigset_libc, nullptr));
+      },
+      sigset_type);
+}
+
+TEST(signal, sigprocmask64_block_filter) {
+  TestSignalMaskFunction(
+      []() {
+        sigset64_t sigset_libc;
+        sigfillset64(&sigset_libc);
+        ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &sigset_libc, nullptr));
+      },
+      SignalMaskFunctionType::RtAware);
+}
+
+TEST(signal, pthread_sigmask_block_filter) {
+  TestSignalMaskFunction(
+      []() {
+        sigset_t sigset_libc;
+        sigfillset(&sigset_libc);
+        ASSERT_EQ(0, pthread_sigmask(SIG_BLOCK, &sigset_libc, nullptr));
+      },
+      sigset_type);
+}
+
+TEST(signal, pthread_sigmask64_block_filter) {
+  TestSignalMaskFunction(
+      []() {
+        sigset64_t sigset_libc;
+        sigfillset64(&sigset_libc);
+        ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, &sigset_libc, nullptr));
+      },
+      SignalMaskFunctionType::RtAware);
+}
+
+// glibc filters out signals via sigfillset, not the actual underlying functions.
+TEST(signal, sigset_filter) {
+#if defined(__BIONIC__)
+  TestSignalMaskFunction(
+      []() {
+        for (int i = 1; i <= 64; ++i) {
+          sigset(i, SIG_HOLD);
+        }
+      },
+      SignalMaskFunctionType::RtAware);
+#endif
+}
+
+TEST(signal, sighold_filter) {
+#if defined(__BIONIC__)
+  TestSignalMaskFunction(
+      []() {
+        for (int i = 1; i <= 64; ++i) {
+          sighold(i);
+        }
+      },
+      SignalMaskFunctionType::RtAware);
+#endif
+}
+
+#if defined(__BIONIC__)
+// Not exposed via headers, but the symbols are available if you declare them yourself.
+extern "C" int sigblock(int);
+extern "C" int sigsetmask(int);
+#endif
+
+TEST(signal, sigblock_filter) {
+#if defined(__BIONIC__)
+  TestSignalMaskFunction(
+      []() {
+        int mask = ~0U;
+        ASSERT_EQ(0, sigblock(mask));
+      },
+      SignalMaskFunctionType::RtNonaware);
+#endif
+}
+
+TEST(signal, sigsetmask_filter) {
+#if defined(__BIONIC__)
+  TestSignalMaskFunction(
+      []() {
+        int mask = ~0U;
+        ASSERT_EQ(0, sigsetmask(mask));
+      },
+      SignalMaskFunctionType::RtNonaware);
+#endif
 }
 
 TEST(signal, sys_signame) {
@@ -301,12 +598,13 @@
 }
 
 TEST(signal, sigwaitinfo) {
+  SignalMaskRestorer smr;
+
   // Block SIGALRM.
   sigset_t just_SIGALRM;
   sigemptyset(&just_SIGALRM);
   sigaddset(&just_SIGALRM, SIGALRM);
-  sigset_t original_set;
-  ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set));
+  ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr));
 
   // Raise SIGALRM.
   sigval_t sigval;
@@ -320,38 +618,75 @@
   ASSERT_EQ(0, errno);
   ASSERT_EQ(SIGALRM, info.si_signo);
   ASSERT_EQ(1, info.si_value.sival_int);
+}
 
-  ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL));
+TEST(signal, sigwaitinfo64_SIGRTMIN) {
+  SignalMaskRestorer smr;
+
+  // Block SIGRTMIN.
+  sigset64_t just_SIGRTMIN;
+  sigemptyset64(&just_SIGRTMIN);
+  sigaddset64(&just_SIGRTMIN, SIGRTMIN);
+  ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr));
+
+  // Raise SIGRTMIN.
+  sigval_t sigval;
+  sigval.sival_int = 1;
+  ASSERT_EQ(0, sigqueue(getpid(), SIGRTMIN, sigval));
+
+  // Get pending SIGRTMIN.
+  siginfo_t info;
+  errno = 0;
+  ASSERT_EQ(SIGRTMIN, sigwaitinfo64(&just_SIGRTMIN, &info));
+  ASSERT_EQ(0, errno);
+  ASSERT_EQ(SIGRTMIN, info.si_signo);
+  ASSERT_EQ(1, info.si_value.sival_int);
 }
 
 TEST(signal, sigtimedwait) {
+  SignalMaskRestorer smr;
+
   // Block SIGALRM.
   sigset_t just_SIGALRM;
   sigemptyset(&just_SIGALRM);
   sigaddset(&just_SIGALRM, SIGALRM);
-  sigset_t original_set;
-  ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set));
+  ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr));
 
   // Raise SIGALRM.
-  sigval_t sigval;
-  sigval.sival_int = 1;
+  sigval_t sigval = { .sival_int = 1 };
   ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval));
 
   // Get pending SIGALRM.
   siginfo_t info;
-  struct timespec timeout;
-  timeout.tv_sec = 2;
-  timeout.tv_nsec = 0;
+  timespec timeout = { .tv_sec = 2, .tv_nsec = 0 };
   errno = 0;
   ASSERT_EQ(SIGALRM, sigtimedwait(&just_SIGALRM, &info, &timeout));
   ASSERT_EQ(0, errno);
+}
 
-  ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL));
+TEST(signal, sigtimedwait64_SIGRTMIN) {
+  SignalMaskRestorer smr;
+
+  // Block SIGRTMIN.
+  sigset64_t just_SIGRTMIN;
+  sigemptyset64(&just_SIGRTMIN);
+  sigaddset64(&just_SIGRTMIN, SIGRTMIN);
+  ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr));
+
+  // Raise SIGALRM.
+  sigval_t sigval = { .sival_int = 1 };
+  ASSERT_EQ(0, sigqueue(getpid(), SIGRTMIN, sigval));
+
+  // Get pending SIGALRM.
+  siginfo_t info;
+  timespec timeout = { .tv_sec = 2, .tv_nsec = 0 };
+  errno = 0;
+  ASSERT_EQ(SIGRTMIN, sigtimedwait64(&just_SIGRTMIN, &info, &timeout));
+  ASSERT_EQ(0, errno);
 }
 
 static int64_t NanoTime() {
-  struct timespec t;
-  t.tv_sec = t.tv_nsec = 0;
+  timespec t;
   clock_gettime(CLOCK_MONOTONIC, &t);
   return static_cast<int64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
 }
@@ -367,9 +702,7 @@
   // Wait timeout.
   int64_t start_time = NanoTime();
   siginfo_t info;
-  struct timespec timeout;
-  timeout.tv_sec = 0;
-  timeout.tv_nsec = 1000000;
+  timespec timeout = { .tv_sec = 0, .tv_nsec = 1000000 };
   errno = 0;
   ASSERT_EQ(-1, sigtimedwait(&just_SIGALRM, &info, &timeout));
   ASSERT_EQ(EAGAIN, errno);
@@ -387,8 +720,7 @@
     "* https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=66dd34ad31e5963d72a700ec3f2449291d322921\n";
   static siginfo received;
 
-  struct sigaction handler;
-  memset(&handler, 0, sizeof(handler));
+  struct sigaction handler = {};
   handler.sa_sigaction = [](int, siginfo_t* siginfo, void*) { received = *siginfo; };
   handler.sa_flags = SA_SIGINFO;
 
@@ -411,18 +743,20 @@
                                             << sent.si_code << ", received " << received.si_code
                                             << error_msg;
 }
+#endif
 
-#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__)
 TEST(signal, sigset_size) {
   // The setjmp implementations for ARM, AArch64, x86, and x86_64 assume that sigset_t can fit in a
   // long. This is true because ARM and x86 have broken rt signal support, and AArch64 and x86_64
   // both have a SIGRTMAX defined as 64.
+#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__)
+#if defined(__BIONIC__)
   static_assert(sizeof(sigset_t) <= sizeof(long), "sigset_t doesn't fit in a long");
+#endif
+  static_assert(sizeof(sigset64_t)*8 >= 64, "sigset64_t too small for real-time signals");
+#endif
 }
 
-#endif
-#endif
-
 TEST(signal, sigignore_EINVAL) {
   errno = 0;
   ASSERT_EQ(-1, sigignore(99999));
diff --git a/tests/spawn_test.cpp b/tests/spawn_test.cpp
index dfce0dc..84df16d 100644
--- a/tests/spawn_test.cpp
+++ b/tests/spawn_test.cpp
@@ -96,6 +96,25 @@
   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
 }
 
+TEST(spawn, posix_spawnattr_setsigmask64_posix_spawnattr_getsigmask64) {
+  posix_spawnattr_t sa;
+  ASSERT_EQ(0, posix_spawnattr_init(&sa));
+
+  sigset64_t sigs;
+  ASSERT_EQ(0, posix_spawnattr_getsigmask64(&sa, &sigs));
+  ASSERT_FALSE(sigismember64(&sigs, SIGRTMIN));
+
+  sigset64_t just_SIGRTMIN;
+  sigemptyset64(&just_SIGRTMIN);
+  sigaddset64(&just_SIGRTMIN, SIGRTMIN);
+  ASSERT_EQ(0, posix_spawnattr_setsigmask64(&sa, &just_SIGRTMIN));
+
+  ASSERT_EQ(0, posix_spawnattr_getsigmask64(&sa, &sigs));
+  ASSERT_TRUE(sigismember64(&sigs, SIGRTMIN));
+
+  ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
+}
+
 TEST(spawn, posix_spawnattr_setsigdefault_posix_spawnattr_getsigdefault) {
   posix_spawnattr_t sa;
   ASSERT_EQ(0, posix_spawnattr_init(&sa));
@@ -115,6 +134,25 @@
   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
 }
 
+TEST(spawn, posix_spawnattr_setsigdefault64_posix_spawnattr_getsigdefault64) {
+  posix_spawnattr_t sa;
+  ASSERT_EQ(0, posix_spawnattr_init(&sa));
+
+  sigset64_t sigs;
+  ASSERT_EQ(0, posix_spawnattr_getsigdefault64(&sa, &sigs));
+  ASSERT_FALSE(sigismember64(&sigs, SIGRTMIN));
+
+  sigset64_t just_SIGRTMIN;
+  sigemptyset64(&just_SIGRTMIN);
+  sigaddset64(&just_SIGRTMIN, SIGRTMIN);
+  ASSERT_EQ(0, posix_spawnattr_setsigdefault64(&sa, &just_SIGRTMIN));
+
+  ASSERT_EQ(0, posix_spawnattr_getsigdefault64(&sa, &sigs));
+  ASSERT_TRUE(sigismember64(&sigs, SIGRTMIN));
+
+  ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
+}
+
 TEST(spawn, posix_spawnattr_setsschedparam_posix_spawnattr_getsschedparam) {
   posix_spawnattr_t sa;
   ASSERT_EQ(0, posix_spawnattr_init(&sa));
diff --git a/tests/stdio_ext_test.cpp b/tests/stdio_ext_test.cpp
index 128e255..849bf0b 100644
--- a/tests/stdio_ext_test.cpp
+++ b/tests/stdio_ext_test.cpp
@@ -190,6 +190,22 @@
   }
 }
 
+TEST(stdio_ext, __fseterr) {
+#if defined(__GLIBC__)
+  GTEST_LOG_(INFO) << "glibc doesn't have __fseterr, but gnulib will use it";
+#else
+  FILE* fp = fopen("/dev/null", "w");
+
+  ASSERT_FALSE(ferror(fp));
+  __fseterr(fp);
+  ASSERT_TRUE(ferror(fp));
+  clearerr(fp);
+  ASSERT_FALSE(ferror(fp));
+
+  fclose(fp);
+#endif
+}
+
 TEST(stdio_ext, __fsetlocking) {
   FILE* fp = fopen("/proc/version", "r");
   ASSERT_EQ(FSETLOCKING_INTERNAL, __fsetlocking(fp, FSETLOCKING_QUERY));
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index caa7a85..2fbd937 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -35,6 +35,14 @@
 #include <limits>
 #include <string>
 
+#if defined(__BIONIC__)
+  #define ALIGNED_ALLOC_AVAILABLE 1
+#elif defined(__GLIBC_PREREQ)
+  #if __GLIBC_PREREQ(2, 16)
+    #define ALIGNED_ALLOC_AVAILABLE 1
+  #endif
+#endif
+
 // The random number generator tests all set the seed, get four values, reset the seed and check
 // that they get the first two values repeated, and then reset the seed and check two more values
 // to rule out the possibility that we're just going round a cycle of four values.
@@ -226,6 +234,50 @@
   ASSERT_NE(0, posix_memalign(&ptr, 16, SIZE_MAX));
 }
 
+TEST(stdlib, aligned_alloc_sweep) {
+#if defined(ALIGNED_ALLOC_AVAILABLE)
+  // Verify powers of 2 up to 2048 allocate, and verify that all other
+  // alignment values between the powers of 2 fail.
+  size_t last_align = 1;
+  for (size_t align = 1; align <= 2048; align <<= 1) {
+    // Try all of the non power of 2 values from the last until this value.
+    for (size_t fail_align = last_align + 1; fail_align < align; fail_align++) {
+      ASSERT_TRUE(aligned_alloc(fail_align, 256) == nullptr)
+          << "Unexpected success at align " << fail_align;
+      ASSERT_EQ(EINVAL, errno) << "Unexpected errno at align " << fail_align;
+    }
+    void* ptr = aligned_alloc(align, 256);
+    ASSERT_TRUE(ptr != nullptr) << "Unexpected failure at align " << align;
+    ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
+        << "Did not return a valid aligned ptr " << ptr << " expected alignment " << align;
+    free(ptr);
+    last_align = align;
+  }
+#else
+  GTEST_LOG_(INFO) << "This test requires a C library that has aligned_alloc.\n";
+#endif
+}
+
+TEST(stdlib, aligned_alloc_overflow) {
+#if defined(ALIGNED_ALLOC_AVAILABLE)
+  ASSERT_TRUE(aligned_alloc(16, SIZE_MAX) == nullptr);
+#else
+  GTEST_LOG_(INFO) << "This test requires a C library that has aligned_alloc.\n";
+#endif
+}
+
+TEST(stdlib, aligned_alloc_size_not_multiple_of_alignment) {
+#if defined(ALIGNED_ALLOC_AVAILABLE)
+  for (size_t size = 1; size <= 2048; size++) {
+    void* ptr = aligned_alloc(2048, size);
+    ASSERT_TRUE(ptr != nullptr) << "Failed at size " << std::to_string(size);
+    free(ptr);
+  }
+#else
+  GTEST_LOG_(INFO) << "This test requires a C library that has aligned_alloc.\n";
+#endif
+}
+
 TEST(stdlib, realpath__NULL_filename) {
   errno = 0;
   // Work around the compile-time error generated by FORTIFY here.
diff --git a/tests/sys_epoll_test.cpp b/tests/sys_epoll_test.cpp
index d1b411a..7233ccc 100644
--- a/tests/sys_epoll_test.cpp
+++ b/tests/sys_epoll_test.cpp
@@ -35,6 +35,11 @@
   // epoll_pwait without a sigset (which is equivalent to epoll_wait).
   ASSERT_EQ(0, epoll_pwait(epoll_fd, events, 1, 1, NULL));
 
+#if defined(__BIONIC__)
+  // epoll_pwait64 without a sigset (which is equivalent to epoll_wait).
+  ASSERT_EQ(0, epoll_pwait64(epoll_fd, events, 1, 1, NULL));
+#endif
+
   // epoll_pwait with a sigset.
   sigset_t ss;
   sigemptyset(&ss);
diff --git a/tests/sys_signalfd_test.cpp b/tests/sys_signalfd_test.cpp
new file mode 100644
index 0000000..67a72e0
--- /dev/null
+++ b/tests/sys_signalfd_test.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2018 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 <gtest/gtest.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/signalfd.h>
+#include <unistd.h>
+
+#include <thread>
+
+#include "ScopedSignalHandler.h"
+
+static void TestSignalFd(int fd, int signal) {
+  ASSERT_NE(-1, fd) << strerror(errno);
+
+  ASSERT_EQ(0, raise(signal));
+
+  signalfd_siginfo sfd_si;
+  ASSERT_EQ(static_cast<ssize_t>(sizeof(sfd_si)), read(fd, &sfd_si, sizeof(sfd_si)));
+
+  ASSERT_EQ(signal, static_cast<int>(sfd_si.ssi_signo));
+
+  close(fd);
+}
+
+TEST(sys_signalfd, signalfd) {
+  SignalMaskRestorer smr;
+
+  sigset_t mask = {};
+  sigaddset(&mask, SIGALRM);
+  ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &mask, nullptr));
+
+  TestSignalFd(signalfd(-1, &mask, SFD_CLOEXEC), SIGALRM);
+}
+
+TEST(sys_signalfd, signalfd64) {
+#if defined(__BIONIC__)
+  SignalMaskRestorer smr;
+
+  sigset64_t mask = {};
+  sigaddset64(&mask, SIGRTMIN);
+  ASSERT_EQ(0, sigprocmask64(SIG_SETMASK, &mask, nullptr));
+
+  TestSignalFd(signalfd64(-1, &mask, SFD_CLOEXEC), SIGRTMIN);
+#endif
+}
diff --git a/tests/system_properties_test.cpp b/tests/system_properties_test.cpp
index f2151e1..949019f 100644
--- a/tests/system_properties_test.cpp
+++ b/tests/system_properties_test.cpp
@@ -42,7 +42,7 @@
   }
   ~SystemPropertiesTest() {
     if (valid_) {
-      contexts()->FreeAndUnmap();
+      contexts_->FreeAndUnmap();
     }
   }
 
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index fccff67..2b9935a 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -279,6 +279,23 @@
   EXPECT_STREQ("09:41:53", buf);
 }
 
+TEST(time, strptime_l) {
+  setenv("TZ", "UTC", 1);
+
+  struct tm t;
+  char buf[64];
+
+  memset(&t, 0, sizeof(t));
+  strptime_l("11:14", "%R", &t, LC_GLOBAL_LOCALE);
+  strftime_l(buf, sizeof(buf), "%H:%M", &t, LC_GLOBAL_LOCALE);
+  EXPECT_STREQ("11:14", buf);
+
+  memset(&t, 0, sizeof(t));
+  strptime_l("09:41:53", "%T", &t, LC_GLOBAL_LOCALE);
+  strftime_l(buf, sizeof(buf), "%H:%M:%S", &t, LC_GLOBAL_LOCALE);
+  EXPECT_STREQ("09:41:53", buf);
+}
+
 void SetTime(timer_t t, time_t value_s, time_t value_ns, time_t interval_s, time_t interval_ns) {
   itimerspec ts;
   ts.it_value.tv_sec = value_s;
diff --git a/tests/utils.h b/tests/utils.h
index 3f4218e..f07bd58 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -140,15 +140,20 @@
   }
 }
 
-static inline void AssertChildExited(int pid, int expected_exit_status) {
+static inline void AssertChildExited(int pid, int expected_exit_status,
+                                     const std::string* error_msg = nullptr) {
   int status;
-  ASSERT_EQ(pid, TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)));
+  std::string error;
+  if (error_msg == nullptr) {
+    error_msg = &error;
+  }
+  ASSERT_EQ(pid, TEMP_FAILURE_RETRY(waitpid(pid, &status, 0))) << *error_msg;
   if (expected_exit_status >= 0) {
-    ASSERT_TRUE(WIFEXITED(status));
-    ASSERT_EQ(expected_exit_status, WEXITSTATUS(status));
+    ASSERT_TRUE(WIFEXITED(status)) << *error_msg;
+    ASSERT_EQ(expected_exit_status, WEXITSTATUS(status)) << *error_msg;
   } else {
-    ASSERT_TRUE(WIFSIGNALED(status));
-    ASSERT_EQ(-expected_exit_status, WTERMSIG(status));
+    ASSERT_TRUE(WIFSIGNALED(status)) << *error_msg;
+    ASSERT_EQ(-expected_exit_status, WTERMSIG(status)) << *error_msg;
   }
 }
 
@@ -215,7 +220,8 @@
     }
     close(fds[0]);
 
-    AssertChildExited(pid, expected_exit_status);
+    std::string error_msg("Test output:\n" + output);
+    AssertChildExited(pid, expected_exit_status, &error_msg);
     if (expected_output != nullptr) {
       ASSERT_EQ(expected_output, output);
     }
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index 6f90c6c..b42e13c 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -539,7 +539,7 @@
   ASSERT_EQ(EILSEQ, errno);
 }
 
-TEST(wchar, wcsftime) {
+TEST(wchar, wcsftime__wcsftime_l) {
   setenv("TZ", "UTC", 1);
 
   struct tm t;
@@ -552,6 +552,8 @@
 
   EXPECT_EQ(24U, wcsftime(buf, sizeof(buf), L"%c", &t));
   EXPECT_STREQ(L"Sun Mar 10 00:00:00 2100", buf);
+  EXPECT_EQ(24U, wcsftime_l(buf, sizeof(buf), L"%c", &t, LC_GLOBAL_LOCALE));
+  EXPECT_STREQ(L"Sun Mar 10 00:00:00 2100", buf);
 }
 
 TEST(wchar, wmemmove_smoke) {
@@ -878,6 +880,34 @@
   TestWcsToFloatInfNan(wcstold);
 }
 
+TEST(wchar, wcstod_l) {
+  EXPECT_EQ(1.23, wcstod_l(L"1.23", nullptr, LC_GLOBAL_LOCALE));
+}
+
+TEST(wchar, wcstof_l) {
+  EXPECT_EQ(1.23f, wcstof_l(L"1.23", nullptr, LC_GLOBAL_LOCALE));
+}
+
+TEST(wchar, wcstol_l) {
+  EXPECT_EQ(123L, wcstol_l(L"123", nullptr, 10, LC_GLOBAL_LOCALE));
+}
+
+TEST(wchar, wcstold_l) {
+  EXPECT_EQ(1.23L, wcstold_l(L"1.23", nullptr, LC_GLOBAL_LOCALE));
+}
+
+TEST(wchar, wcstoll_l) {
+  EXPECT_EQ(123LL, wcstoll_l(L"123", nullptr, 10, LC_GLOBAL_LOCALE));
+}
+
+TEST(wchar, wcstoul_l) {
+  EXPECT_EQ(123UL, wcstoul_l(L"123", nullptr, 10, LC_GLOBAL_LOCALE));
+}
+
+TEST(wchar, wcstoull_l) {
+  EXPECT_EQ(123ULL, wcstoul_l(L"123", nullptr, 10, LC_GLOBAL_LOCALE));
+}
+
 static void AssertWcwidthRange(wchar_t begin, wchar_t end, int expected) {
   for (wchar_t i = begin; i < end; ++i) {
     EXPECT_EQ(expected, wcwidth(i)) << static_cast<int>(i);