Merge "Lay the groundwork for enabling EDNS0 in queries."
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 21f9b71..0ea94d4 100644
--- a/docs/32-bit-abi.md
+++ b/docs/32-bit-abi.md
@@ -59,6 +59,9 @@
 
 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
 
@@ -68,8 +71,15 @@
 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
 
diff --git a/docs/status.md b/docs/status.md
index 8cef5b7..a0e6824 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -49,11 +49,15 @@
   * `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.
+
+New libc behavior in P:
+  * `%C` and `%S` support in the printf family (previously only the wprintf family supported these)
+  * `%mc`/`%ms`/`%m[` support in the scanf family
+  * `%s` support in strptime (strftime already supported it)
 
 New libc functions in O:
   * `sendto` FORTIFY support
diff --git a/libc/Android.bp b/libc/Android.bp
index 0f58204..20df52c 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
@@ -476,7 +481,6 @@
         "upstream-openbsd/lib/libc/stdlib/reallocarray.c",
         "upstream-openbsd/lib/libc/stdlib/remque.c",
         "upstream-openbsd/lib/libc/stdlib/setenv.c",
-        "upstream-openbsd/lib/libc/stdlib/system.c",
         "upstream-openbsd/lib/libc/stdlib/tfind.c",
         "upstream-openbsd/lib/libc/stdlib/tsearch.c",
         "upstream-openbsd/lib/libc/string/strcasecmp.c",
@@ -538,7 +542,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 +713,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 +725,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 +827,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",
@@ -1266,6 +1274,7 @@
         "bionic/futimens.cpp",
         "bionic/getcwd.cpp",
         "bionic/getdomainname.cpp",
+        "bionic/getentropy.cpp",
         "bionic/gethostname.cpp",
         "bionic/getpagesize.cpp",
         "bionic/getpgrp.cpp",
@@ -1273,6 +1282,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",
@@ -1331,6 +1341,7 @@
         "bionic/setpgrp.cpp",
         "bionic/sigaction.cpp",
         "bionic/signal.cpp",
+        "bionic/sigprocmask.cpp",
         "bionic/socket.cpp",
         "bionic/spawn.cpp",
         "bionic/stat.cpp",
@@ -1357,6 +1368,7 @@
         "bionic/sys_time.cpp",
         "bionic/sysinfo.cpp",
         "bionic/syslog.cpp",
+        "bionic/system.cpp",
         "bionic/system_property_api.cpp",
         "bionic/system_property_set.cpp",
         "bionic/tdestroy.cpp",
@@ -1696,7 +1708,10 @@
         "ld-android",
         "libdl",
     ],
-    whole_static_libs: ["libc_common", "libjemalloc"],
+    whole_static_libs: [
+        "libc_common",
+        "libjemalloc",
+    ],
 
     nocrt: true,
 
@@ -1794,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/SECCOMP_WHITELIST_APP.TXT b/libc/SECCOMP_WHITELIST_APP.TXT
index 2f3618c..21839a6 100644
--- a/libc/SECCOMP_WHITELIST_APP.TXT
+++ b/libc/SECCOMP_WHITELIST_APP.TXT
@@ -24,3 +24,57 @@
 #      - Each parameter type is assumed to be stored in 32 bits.
 #
 # This file is processed by a python script named genseccomp.py.
+
+# Needed for debugging 32-bit Chrome
+int	pipe:pipe(int pipefd[2])	arm,x86,mips
+
+# b/34651972
+int	access:access(const char *pathname, int mode)	arm,x86,mips
+int	stat64:stat64(const char*, struct stat64*)	arm,x86,mips
+
+# b/34813887
+int	open:open(const char *path, int oflag, ... ) arm,x86,mips
+int	getdents:getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count) arm,x86,mips
+
+# b/34719286
+int	eventfd:eventfd(unsigned int initval, int flags)	arm,x86,mips
+
+# b/34817266
+int	epoll_wait:epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)	arm,x86,mips
+
+# b/34908783
+int	epoll_create:epoll_create(int size)	arm,x86,mips
+
+# b/34979910
+int	creat:creat(const char *pathname, mode_t mode)	arm,x86,mips
+int	unlink:unlink(const char *pathname)	arm,x86,mips
+
+# b/35059702
+int	lstat64:lstat64(const char*, struct stat64*)	arm,x86,mips
+
+# b/35217603
+int	fcntl:fcntl(int fd, int cmd, ... /* arg */ )	arm,x86,mips
+pid_t	fork:fork()	arm,x86,mips
+int	poll:poll(struct pollfd *fds, nfds_t nfds, int timeout)	arm,x86,mips
+
+# b/35906875. Note mips already has getuid from SYSCALLS.TXT
+int	inotify_init()	arm,x86,mips
+uid_t	getuid()	arm,x86
+
+# b/36435222
+int	remap_file_pages(void *addr, size_t size, int prot, size_t pgoff, int flags)	arm,x86,mips
+
+# b/36449658
+int	rename(const char *oldpath, const char *newpath)	arm,x86,mips
+
+# b/36726183. Note arm does not support mmap
+void*	mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)	x86,mips
+
+# b/37769298
+int dup2(int oldfd, int newfd)	arm,x86,mips
+
+# b/62779795
+int compat_select:_newselect(int n, unsigned long* inp, unsigned long* outp, unsigned long* exp, struct timeval* timeout) arm,x86,mips
+
+# b/62090571
+int mkdir(const char *pathname, mode_t mode)	arm,x86,mips
diff --git a/libc/SECCOMP_WHITELIST_COMMON.TXT b/libc/SECCOMP_WHITELIST_COMMON.TXT
index a620b44..08a2c2b 100644
--- a/libc/SECCOMP_WHITELIST_COMMON.TXT
+++ b/libc/SECCOMP_WHITELIST_COMMON.TXT
@@ -39,6 +39,9 @@
 int	fstat64|fstat:fstat(int, struct stat*)	mips64
 int	_flush_cache:cacheflush(char* addr, const int nbytes, const int op)	mips64
 
+# vfork is used by java.lang.ProcessBuilder
+pid_t	vfork:vfork()	arm,x86,x86_64
+
 # Needed for performance tools
 int	perf_event_open:perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu, int group_fd, unsigned long flags)	all
 
@@ -51,59 +54,11 @@
 # syscalls needed to boot android
 int	sigreturn:sigreturn(unsigned long __unused)	arm,x86,mips
 
-# Syscalls needed to run GFXBenchmark
-pid_t	vfork:vfork()	arm,x86,x86_64
-
-# Needed for debugging 32-bit Chrome
-int	pipe:pipe(int pipefd[2])	arm,x86,mips
-
-# b/34651972
-int	access:access(const char *pathname, int mode)	arm,x86,mips
-int	stat64:stat64(const char*, struct stat64*)	arm,x86,mips
-
-# b/34813887
-int	open:open(const char *path, int oflag, ... ) arm,x86,mips
-int	getdents:getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count) arm,x86,mips
-
-# b/34719286
-int	eventfd:eventfd(unsigned int initval, int flags)	arm,x86,mips
-
-# b/34817266
-int	epoll_wait:epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)	arm,x86,mips
-
 # Needed by sanitizers (b/34606909)
 # 5 (__NR_open) and 195 (__NR_stat64) are also required, but they are
 # already allowed.
 ssize_t	readlink:readlink(const char *path, char *buf, size_t bufsiz)	arm,x86,mips
 
-# b/34908783
-int	epoll_create:epoll_create(int size)	arm,x86,mips
-
-# b/34979910
-int	creat:creat(const char *pathname, mode_t mode)	arm,x86,mips
-int	unlink:unlink(const char *pathname)	arm,x86,mips
-
-# b/35059702
-int	lstat64:lstat64(const char*, struct stat64*)	arm,x86,mips
-
-# b/35217603
-int	fcntl:fcntl(int fd, int cmd, ... /* arg */ )	arm,x86,mips
-pid_t	fork:fork()	arm,x86,mips
-int	poll:poll(struct pollfd *fds, nfds_t nfds, int timeout)	arm,x86,mips
-
-# b/35906875. Note mips already has getuid from SYSCALLS.TXT
-int	inotify_init()	arm,x86,mips
-uid_t	getuid()	arm,x86
-
-# b/36435222
-int	remap_file_pages(void *addr, size_t size, int prot, size_t pgoff, int flags)	arm,x86,mips
-
-# b/36449658
-int	rename(const char *oldpath, const char *newpath)	arm,x86,mips
-
-# b/36726183. Note arm does not support mmap
-void*	mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)	x86,mips
-
 # Useful new syscalls which we don't yet use in bionic.
 int sched_getattr(pid_t pid, struct sched_attr* attr, unsigned int flags) all
 int sched_setattr(pid_t pid, struct sched_attr* attr, unsigned int size, unsigned int flags) all
@@ -119,12 +74,3 @@
 int io_submit(aio_context_t ctx, long nr,  struct iocb **iocbpp) all
 int io_getevents(aio_context_t ctx, long min_nr, long max_nr, struct io_event *events, struct timespec *timeout) all
 int io_cancel(aio_context_t ctx, struct iocb *, struct io_event *result) all
-
-# b/37769298
-int dup2(int oldfd, int newfd)	arm,x86,mips
-
-# b/62779795
-int compat_select:_newselect(int n, unsigned long* inp, unsigned long* outp, unsigned long* exp, struct timeval* timeout) arm,x86,mips
-
-# b/62090571
-int mkdir(const char *pathname, mode_t mode)	arm,x86,mips
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 30e7e23..5fbcaf3 100644
--- a/libc/arch-arm/bionic/setjmp.S
+++ b/libc/arch-arm/bionic/setjmp.S
@@ -58,17 +58,15 @@
 // 0      sigflag/cookie  setjmp cookie in top 31 bits, signal mask flag in low bit
 // 1      sigmask         64-bit signal mask (not used with _setjmp / _longjmp)
 // 2      "               "
-// 3      reserved        (unused to allow float_base to be maximally aligned)
+// 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.
+// 31     checksum        checksum of all of the core registers, to give better error messages
 // 32     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.
+// ...
+// 63     "               "
 
 #define _JB_SIGFLAG     0
 #define _JB_SIGMASK     (_JB_SIGFLAG + 1)
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/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 ec26a50..d2c99a5 100644
--- a/libc/bionic/abort.cpp
+++ b/libc/bionic/abort.cpp
@@ -67,13 +67,10 @@
   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);
+  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);
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/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/legacy_32_bit_support.cpp b/libc/bionic/legacy_32_bit_support.cpp
index 983fb32..ba59e8e 100644
--- a/libc/bionic/legacy_32_bit_support.cpp
+++ b/libc/bionic/legacy_32_bit_support.cpp
@@ -85,13 +85,13 @@
 // to implement all four functions because the two system calls don't match any
 // of the userspace functions. Unlike llseek, the pair is split lo-hi, not hi-lo.
 ssize_t preadv(int fd, const struct iovec* ios, int count, off_t offset) {
-  return __preadv64(fd, ios, count, offset, 0);
+  return preadv64(fd, ios, count, offset);
 }
 ssize_t preadv64(int fd, const struct iovec* ios, int count, off64_t offset) {
   return __preadv64(fd, ios, count, offset, offset >> 32);
 }
 ssize_t pwritev(int fd, const struct iovec* ios, int count, off_t offset) {
-  return __pwritev64(fd, ios, count, offset, 0);
+  return pwritev64(fd, ios, count, offset);
 }
 ssize_t pwritev64(int fd, const struct iovec* ios, int count, off64_t offset) {
   return __pwritev64(fd, ios, count, offset, offset >> 32);
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/poll.cpp b/libc/bionic/poll.cpp
index 1d72fe5..3df8b18 100644
--- a/libc/bionic/poll.cpp
+++ b/libc/bionic/poll.cpp
@@ -31,12 +31,13 @@
 #include <sys/select.h>
 
 #include "private/bionic_time_conversions.h"
+#include "private/sigrtmin.h"
 #include "private/SigSetConverter.h"
 
 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 = nullptr;
   if (ms >= 0) {
@@ -46,7 +47,7 @@
   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;
@@ -66,7 +67,15 @@
     mutable_ts = *ts;
     mutable_ts_ptr = &mutable_ts;
   }
-  return __ppoll(fds, fd_count, mutable_ts_ptr, ss, sizeof(*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, 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) {
@@ -109,6 +118,13 @@
     mutable_ts_ptr = &mutable_ts;
   }
 
+  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,
   // so the last argument is a void* pointing to:
   struct pselect6_extra_data_t {
@@ -116,8 +132,8 @@
     size_t ss_len;
   };
   pselect6_extra_data_t extra_data;
-  extra_data.ss_addr = reinterpret_cast<uintptr_t>(ss);
-  extra_data.ss_len = sizeof(*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 2edfe97..1abeb1f 100644
--- a/libc/bionic/posix_timers.cpp
+++ b/libc/bionic/posix_timers.cpp
@@ -35,6 +35,8 @@
 #include <time.h>
 
 // System calls.
+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);
@@ -77,7 +79,7 @@
   while (true) {
     // Wait for a signal...
     siginfo_t si = {};
-    if (sigtimedwait64(&sigset, &si, nullptr) == -1) continue;
+    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.
@@ -146,11 +148,13 @@
   sigset64_t sigset = {};
   sigaddset64(&sigset, TIMER_SIGNAL);
   sigset64_t old_sigset;
-  sigprocmask64(SIG_BLOCK, &sigset, &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);
 
-  sigprocmask64(SIG_SETMASK, &old_sigset, nullptr);
+  __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 099944a..175182b 100644
--- a/libc/bionic/signal.cpp
+++ b/libc/bionic/signal.cpp
@@ -38,9 +38,9 @@
 
 #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_sigprocmask(int, const sigset64_t*, sigset64_t*, size_t);
 extern "C" int ___rt_sigqueueinfo(pid_t, int, siginfo_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);
@@ -147,22 +147,19 @@
 }
 
 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);
 }
 
 template <typename SigSetT>
@@ -185,16 +182,8 @@
 }
 
 __LIBC_HIDDEN__ sighandler_t _signal(int sig, sighandler_t handler, int flags) {
-  struct sigaction sa;
-  sigemptyset(&sa.sa_mask);
-  sa.sa_handler = handler;
-  sa.sa_flags = flags;
-
-  if (sigaction(sig, &sa, &sa) == -1) {
-    return SIG_ERR;
-  }
-
-  return sa.sa_handler;
+  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) {
@@ -219,31 +208,6 @@
   return __rt_sigpending(set, sizeof(*set));
 }
 
-int sigprocmask(int how, const sigset_t* bionic_new_set, sigset_t* bionic_old_set) {
-  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) {
-  return __rt_sigprocmask(how, new_set, old_set, sizeof(*new_set));
-}
-
 int sigqueue(pid_t pid, int sig, const sigval value) {
   siginfo_t info;
   memset(&info, 0, sizeof(siginfo_t));
@@ -262,15 +226,11 @@
 }
 
 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;
   }
 
@@ -296,21 +256,33 @@
 int sigsuspend(const sigset_t* bionic_set) {
   SigSetConverter set = {};
   set.sigset = *bionic_set;
-  return __rt_sigsuspend(&set.sigset64, sizeof(set.sigset64));
+  return sigsuspend64(&set.sigset64);
 }
 
 int sigsuspend64(const sigset64_t* set) {
-  return __rt_sigsuspend(set, sizeof(*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 sigtimedwait(const sigset_t* bionic_set, siginfo_t* info, const timespec* timeout) {
   SigSetConverter set = {};
   set.sigset = *bionic_set;
-  return __rt_sigtimedwait(&set.sigset64, info, timeout, sizeof(set.sigset64));
+  return sigtimedwait64(&set.sigset64, info, timeout);
 }
 
 int sigtimedwait64(const sigset64_t* set, siginfo_t* info, const timespec* timeout) {
-  return __rt_sigtimedwait(set, info, timeout, sizeof(*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_sigtimedwait(mutable_set_ptr, info, timeout, sizeof(*set));
 }
 
 int sigwait(const sigset_t* bionic_set, int* sig) {
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 7422a0b..fde102c 100644
--- a/libc/bionic/spawn.cpp
+++ b/libc/bionic/spawn.cpp
@@ -98,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 && 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);
diff --git a/libc/bionic/system.cpp b/libc/bionic/system.cpp
new file mode 100644
index 0000000..7411ae5
--- /dev/null
+++ b/libc/bionic/system.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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 <paths.h>
+#include <stdlib.h>
+#include <spawn.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "private/ScopedSignalBlocker.h"
+#include "private/ScopedSignalHandler.h"
+
+int system(const char* command) {
+  // "The system() function shall always return non-zero when command is NULL."
+  // http://pubs.opengroup.org/onlinepubs/9699919799/functions/system.html
+  if (command == nullptr) return 1;
+
+  ScopedSignalBlocker sigchld_blocker(SIGCHLD);
+  ScopedSignalHandler sigint_ignorer(SIGINT, SIG_IGN);
+  ScopedSignalHandler sigquit_ignorer(SIGQUIT, SIG_IGN);
+
+  sigset64_t default_mask = {};
+  if (sigint_ignorer.old_action_.sa_handler != SIG_IGN) sigaddset64(&default_mask, SIGINT);
+  if (sigquit_ignorer.old_action_.sa_handler != SIG_IGN) sigaddset64(&default_mask, SIGQUIT);
+
+  static constexpr int flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
+  posix_spawnattr_t attributes;
+  if ((errno = posix_spawnattr_init(&attributes))) return -1;
+  if ((errno = posix_spawnattr_setsigdefault64(&attributes, &default_mask))) return -1;
+  if ((errno = posix_spawnattr_setsigmask64(&attributes, &sigchld_blocker.old_set_))) return -1;
+  if ((errno = posix_spawnattr_setflags(&attributes, flags))) return -1;
+
+  const char* argv[] = { "sh", "-c", command, nullptr };
+  pid_t child;
+  if ((errno = posix_spawn(&child, _PATH_BSHELL, nullptr, &attributes,
+                           const_cast<char**>(argv), environ)) != 0) {
+    return -1;
+  }
+
+  posix_spawnattr_destroy(&attributes);
+
+  int status;
+  pid_t pid = TEMP_FAILURE_RETRY(waitpid(child, &status, 0));
+  return (pid == -1 ? -1 : status);
+}
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/dns/include/resolv_netid.h b/libc/dns/include/resolv_netid.h
index 3b2f4da..c7e2823 100644
--- a/libc/dns/include/resolv_netid.h
+++ b/libc/dns/include/resolv_netid.h
@@ -72,11 +72,15 @@
     unsigned dns_netid;
     unsigned dns_mark;
     uid_t uid;
+    unsigned flags;
     res_send_qhook qhook;
 };
 
 #define NET_CONTEXT_INVALID_UID ((uid_t)-1)
 
+#define NET_CONTEXT_FLAG_USE_LOCAL_NAMESERVERS  0x00000001
+#define NET_CONTEXT_FLAG_USE_EDNS               0x00000002
+
 struct hostent *android_gethostbyaddrfornet(const void *, socklen_t, int, unsigned, unsigned) __used_in_netd;
 struct hostent *android_gethostbynamefornet(const char *, int, unsigned, unsigned) __used_in_netd;
 int android_getaddrinfofornet(const char *, const char *, const struct addrinfo *, unsigned,
diff --git a/libc/dns/net/getaddrinfo.c b/libc/dns/net/getaddrinfo.c
index c0a2fdb..47b3308 100644
--- a/libc/dns/net/getaddrinfo.c
+++ b/libc/dns/net/getaddrinfo.c
@@ -198,7 +198,7 @@
 	{ 0, 0 }
 };
 
-#define MAXPACKET	(64*1024)
+#define MAXPACKET	(8*1024)
 
 typedef union {
 	HEADER hdr;
diff --git a/libc/dns/net/gethnamaddr.c b/libc/dns/net/gethnamaddr.c
index 7118a29..7589380 100644
--- a/libc/dns/net/gethnamaddr.c
+++ b/libc/dns/net/gethnamaddr.c
@@ -127,7 +127,7 @@
 	.uid = NET_CONTEXT_INVALID_UID
 };
 
-#define	MAXPACKET	(64*1024)
+#define	MAXPACKET	(8*1024)
 
 typedef union {
     HEADER hdr;
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/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/poll.h b/libc/include/poll.h
index 9ca1cf8..6a8f757 100644
--- a/libc/include/poll.h
+++ b/libc/include/poll.h
@@ -38,8 +38,8 @@
 
 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)
diff --git a/libc/include/signal.h b/libc/include/signal.h
index 61bb395..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,57 +57,10 @@
 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. */
 
-/* sigset_t is already large enough on LP64, but LP32's sigset_t is just `unsigned long`. */
-#if defined(__LP64__)
-typedef sigset_t sigset64_t;
-#else
-typedef struct { unsigned long __bits[_KERNEL__NSIG/LONG_BIT]; } sigset64_t;
-#endif
-
-#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
-
-// TODO: sigaction contains a sigset_t that's too small on LP32.
 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);
 
@@ -191,4 +126,4 @@
 
 #include <android/legacy_signal_inlines.h>
 
-#endif /* _SIGNAL_H_ */
+#endif
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index 2d9cc31..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() */
diff --git a/libc/include/stdio_ext.h b/libc/include/stdio_ext.h
index 2f0f438..b8aa68d 100644
--- a/libc/include/stdio_ext.h
+++ b/libc/include/stdio_ext.h
@@ -45,6 +45,8 @@
 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/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 f191028..e0f8b43 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -140,15 +140,14 @@
 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)
@@ -157,10 +156,8 @@
 
 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);
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 c345ba6..19c80b7 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1321,7 +1321,13 @@
 LIBC_P { # introduced=P
   global:
     __freading;
+    __free_hook;
+    __fseterr;
     __fwriting;
+    __malloc_hook;
+    __memalign_hook;
+    __realloc_hook;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
@@ -1386,6 +1392,7 @@
     sethostent;
     setnetent;
     setprotoent;
+    sigaction64;
     sigaddset64;
     sigdelset64;
     sigemptyset64;
@@ -1398,8 +1405,14 @@
     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 3af0d42..cab66e6 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1241,7 +1241,13 @@
 LIBC_P { # introduced=P
   global:
     __freading;
+    __free_hook;
+    __fseterr;
     __fwriting;
+    __malloc_hook;
+    __memalign_hook;
+    __realloc_hook;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
@@ -1306,6 +1312,7 @@
     sethostent;
     setnetent;
     setprotoent;
+    sigaction64;
     sigaddset64;
     sigdelset64;
     sigemptyset64;
@@ -1318,8 +1325,14 @@
     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 5c54ba1..65e4802 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1346,7 +1346,13 @@
 LIBC_P { # introduced=P
   global:
     __freading;
+    __free_hook;
+    __fseterr;
     __fwriting;
+    __malloc_hook;
+    __memalign_hook;
+    __realloc_hook;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
@@ -1411,6 +1417,7 @@
     sethostent;
     setnetent;
     setprotoent;
+    sigaction64;
     sigaddset64;
     sigdelset64;
     sigemptyset64;
@@ -1423,8 +1430,14 @@
     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 c364608..363a55a 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1305,7 +1305,13 @@
 LIBC_P { # introduced=P
   global:
     __freading;
+    __free_hook;
+    __fseterr;
     __fwriting;
+    __malloc_hook;
+    __memalign_hook;
+    __realloc_hook;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
@@ -1370,6 +1376,7 @@
     sethostent;
     setnetent;
     setprotoent;
+    sigaction64;
     sigaddset64;
     sigdelset64;
     sigemptyset64;
@@ -1382,8 +1389,14 @@
     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 3af0d42..cab66e6 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1241,7 +1241,13 @@
 LIBC_P { # introduced=P
   global:
     __freading;
+    __free_hook;
+    __fseterr;
     __fwriting;
+    __malloc_hook;
+    __memalign_hook;
+    __realloc_hook;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
@@ -1306,6 +1312,7 @@
     sethostent;
     setnetent;
     setprotoent;
+    sigaction64;
     sigaddset64;
     sigdelset64;
     sigemptyset64;
@@ -1318,8 +1325,14 @@
     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 eec2c19..fc5e463 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1303,7 +1303,13 @@
 LIBC_P { # introduced=P
   global:
     __freading;
+    __free_hook;
+    __fseterr;
     __fwriting;
+    __malloc_hook;
+    __memalign_hook;
+    __realloc_hook;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
@@ -1368,6 +1374,7 @@
     sethostent;
     setnetent;
     setprotoent;
+    sigaction64;
     sigaddset64;
     sigdelset64;
     sigemptyset64;
@@ -1380,8 +1387,14 @@
     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 3af0d42..cab66e6 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1241,7 +1241,13 @@
 LIBC_P { # introduced=P
   global:
     __freading;
+    __free_hook;
+    __fseterr;
     __fwriting;
+    __malloc_hook;
+    __memalign_hook;
+    __realloc_hook;
+    aligned_alloc;
     endhostent;
     endnetent;
     endprotoent;
@@ -1306,6 +1312,7 @@
     sethostent;
     setnetent;
     setprotoent;
+    sigaction64;
     sigaddset64;
     sigdelset64;
     sigemptyset64;
@@ -1318,8 +1325,14 @@
     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 7582068..d1cf629 100644
--- a/libc/private/ScopedSignalBlocker.h
+++ b/libc/private/ScopedSignalBlocker.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef SCOPED_SIGNAL_BLOCKER_H
-#define SCOPED_SIGNAL_BLOCKER_H
+#pragma once
 
 #include <signal.h>
 
@@ -23,10 +22,18 @@
 
 class ScopedSignalBlocker {
  public:
+  // Block all signals.
   explicit ScopedSignalBlocker() {
     sigset64_t set;
     sigfillset64(&set);
-    sigprocmask64(SIG_SETMASK, &set, &old_set_);
+    sigprocmask64(SIG_BLOCK, &set, &old_set_);
+  }
+
+  // Block just the specified signal.
+  explicit ScopedSignalBlocker(int signal) {
+    sigset64_t set = {};
+    sigaddset64(&set, signal);
+    sigprocmask64(SIG_BLOCK, &set, &old_set_);
   }
 
   ~ScopedSignalBlocker() {
@@ -37,10 +44,7 @@
     sigprocmask64(SIG_SETMASK, &old_set_, nullptr);
   }
 
- private:
   sigset64_t old_set_;
 
   DISALLOW_COPY_AND_ASSIGN(ScopedSignalBlocker);
 };
-
-#endif
diff --git a/libc/private/ScopedSignalHandler.h b/libc/private/ScopedSignalHandler.h
new file mode 100644
index 0000000..dd5823f
--- /dev/null
+++ b/libc/private/ScopedSignalHandler.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma once
+
+#include <signal.h>
+
+class ScopedSignalHandler {
+ public:
+  ScopedSignalHandler(int signal_number, void (*handler)(int), int sa_flags = 0)
+      : signal_number_(signal_number) {
+    action_ = { .sa_flags = sa_flags, .sa_handler = handler };
+    sigaction64(signal_number_, &action_, &old_action_);
+  }
+
+  ScopedSignalHandler(int signal_number, void (*action)(int, siginfo_t*, void*),
+                      int sa_flags = SA_SIGINFO)
+      : signal_number_(signal_number) {
+    action_ = { .sa_flags = sa_flags, .sa_sigaction = action };
+    sigaction64(signal_number_, &action_, &old_action_);
+  }
+
+  ScopedSignalHandler(int signal_number) : signal_number_(signal_number) {
+    sigaction64(signal_number, nullptr, &old_action_);
+  }
+
+  ~ScopedSignalHandler() {
+    sigaction64(signal_number_, &old_action_, nullptr);
+  }
+
+  struct sigaction64 action_;
+  struct sigaction64 old_action_;
+  const int signal_number_;
+};
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/linker/arch/x86/begin.c b/libc/private/sigrtmin.h
similarity index 66%
copy from linker/arch/x86/begin.c
copy to libc/private/sigrtmin.h
index 331b79e..ea8673d 100644
--- a/linker/arch/x86/begin.c
+++ b/libc/private/sigrtmin.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 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,28 +26,25 @@
  * SUCH DAMAGE.
  */
 
-#include <stdint.h>
+#pragma once
+
 #include <sys/cdefs.h>
 
-extern unsigned __linker_init(void* raw_args);
+#include <signal.h>
 
-__LIBC_HIDDEN__ void _start() {
-  // Force unwinds to end in this function.
-  asm volatile(".cfi_undefined \%eip");
+// 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.
 
-  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 */
+#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/arm_system_policy.cpp b/libc/seccomp/arm_system_policy.cpp
index 18df03b..8887f4d 100644
--- a/libc/seccomp/arm_system_policy.cpp
+++ b/libc/seccomp/arm_system_policy.cpp
@@ -5,128 +5,132 @@
 
 #include "seccomp_bpfs.h"
 const sock_filter arm_system_filter[] = {
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 0, 0, 124),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 138, 61, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 0, 0, 128),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 143, 63, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 74, 31, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 41, 15, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 24, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 10, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 8, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 7, 117, 116), //restart_syscall|exit|fork|read|write|open|close
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 9, 116, 115), //creat
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 19, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 13, 114, 113), //unlink|execve|chdir
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 22, 113, 112), //lseek|getpid|mount
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 33, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 43, 15, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 19, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 6, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 3, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 2, 121, 120), //restart_syscall|exit
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5, 120, 119), //read|write
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 11, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 7, 118, 117), //close
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 13, 117, 116), //execve|chdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 36, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 26, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 25, 110, 109), //getuid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 27, 109, 108), //ptrace
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 36, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 34, 107, 106), //access
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 40, 106, 105), //sync|kill|rename|mkdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 22, 114, 113), //lseek|getpid|mount
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 27, 113, 112), //ptrace
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 41, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 38, 111, 110), //sync|kill
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 42, 110, 109), //dup
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 57, 7, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 51, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 45, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 44, 102, 101), //dup|pipe|times
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 46, 101, 100), //brk
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 44, 106, 105), //times
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 46, 105, 104), //brk
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 54, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 53, 99, 98), //acct|umount2
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 56, 98, 97), //ioctl|fcntl
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 63, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 53, 103, 102), //acct|umount2
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 55, 102, 101), //ioctl
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 64, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 60, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 58, 95, 94), //setpgid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 62, 94, 93), //umask|chroot
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 58, 99, 98), //setpgid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 62, 98, 97), //umask|chroot
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 66, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 65, 92, 91), //dup2|getppid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 68, 91, 90), //setsid|sigaction
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 65, 96, 95), //getppid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 68, 95, 94), //setsid|sigaction
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 114, 15, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 91, 7, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 85, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 77, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 76, 86, 85), //sethostname|setrlimit
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 80, 85, 84), //getrusage|gettimeofday|settimeofday
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 76, 90, 89), //sethostname|setrlimit
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 80, 89, 88), //getrusage|gettimeofday|settimeofday
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 88, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 86, 83, 82), //readlink
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 89, 82, 81), //reboot
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 86, 87, 86), //readlink
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 89, 86, 85), //reboot
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 96, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 94, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 93, 79, 78), //munmap|truncate
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 95, 78, 77), //fchmod
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 93, 83, 82), //munmap|truncate
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 95, 82, 81), //fchmod
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 103, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 98, 76, 75), //getpriority|setpriority
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 106, 75, 74), //syslog|setitimer|getitimer
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 98, 80, 79), //getpriority|setpriority
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 106, 79, 78), //syslog|setitimer|getitimer
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 128, 7, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 118, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 116, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 115, 71, 70), //wait4
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 117, 70, 69), //sysinfo
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 115, 75, 74), //wait4
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 117, 74, 73), //sysinfo
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 124, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 123, 68, 67), //fsync|sigreturn|clone|setdomainname|uname
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 126, 67, 66), //adjtimex|mprotect
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 123, 72, 71), //fsync|sigreturn|clone|setdomainname|uname
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 126, 71, 70), //adjtimex|mprotect
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 136, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 131, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 130, 64, 63), //init_module|delete_module
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 134, 63, 62), //quotactl|getpgid|fchdir
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 137, 62, 61), //personality
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 130, 68, 67), //init_module|delete_module
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 134, 67, 66), //quotactl|getpgid|fchdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 138, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 137, 65, 64), //personality
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 141, 64, 63), //setfsuid|setfsgid|_llseek
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 290, 31, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 217, 15, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 183, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 168, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 190, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 172, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 150, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 149, 56, 55), //setfsuid|setfsgid|_llseek|getdents|_newselect|flock|msync|readv|writev|getsid|fdatasync
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 164, 55, 54), //mlock|munlock|mlockall|munlockall|sched_setparam|sched_getparam|sched_setscheduler|sched_getscheduler|sched_yield|sched_get_priority_max|sched_get_priority_min|sched_rr_get_interval|nanosleep|mremap
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 172, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 169, 53, 52), //poll
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 182, 52, 51), //prctl|rt_sigreturn|rt_sigaction|rt_sigprocmask|rt_sigpending|rt_sigtimedwait|rt_sigqueueinfo|rt_sigsuspend|pread64|pwrite64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 149, 58, 57), //flock|msync|readv|writev|getsid|fdatasync
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 164, 57, 56), //mlock|munlock|mlockall|munlockall|sched_setparam|sched_getparam|sched_setscheduler|sched_getscheduler|sched_yield|sched_get_priority_max|sched_get_priority_min|sched_rr_get_interval|nanosleep|mremap
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 183, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 182, 55, 54), //prctl|rt_sigreturn|rt_sigaction|rt_sigprocmask|rt_sigpending|rt_sigtimedwait|rt_sigqueueinfo|rt_sigsuspend|pread64|pwrite64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 188, 54, 53), //getcwd|capget|capset|sigaltstack|sendfile
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 199, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 190, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 188, 49, 48), //getcwd|capget|capset|sigaltstack|sendfile
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 198, 48, 47), //vfork|ugetrlimit|mmap2|truncate64|ftruncate64|stat64|lstat64|fstat64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 197, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 195, 51, 50), //vfork|ugetrlimit|mmap2|truncate64|ftruncate64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 198, 50, 49), //fstat64
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 213, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 212, 46, 45), //getuid32|getgid32|geteuid32|getegid32|setreuid32|setregid32|getgroups32|setgroups32|fchown32|setresuid32|getresuid32|setresgid32|getresgid32
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 215, 45, 44), //setuid32|setgid32
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 212, 48, 47), //getuid32|getgid32|geteuid32|getegid32|setreuid32|setregid32|getgroups32|setgroups32|fchown32|setresuid32|getresuid32|setresgid32|getresgid32
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 215, 47, 46), //setuid32|setgid32
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 256, 7, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 224, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 219, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 218, 41, 40), //getdents64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 222, 40, 39), //mincore|madvise|fcntl64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 250, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 249, 38, 37), //gettid|readahead|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|tkill|sendfile64|futex|sched_setaffinity|sched_getaffinity|io_setup|io_destroy|io_getevents|io_submit|io_cancel|exit_group
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 254, 37, 36), //epoll_create|epoll_ctl|epoll_wait|remap_file_pages
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 218, 43, 42), //getdents64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 222, 42, 41), //mincore|madvise|fcntl64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 251, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 249, 40, 39), //gettid|readahead|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|tkill|sendfile64|futex|sched_setaffinity|sched_getaffinity|io_setup|io_destroy|io_getevents|io_submit|io_cancel|exit_group
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 252, 39, 38), //epoll_ctl
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 280, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 270, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 269, 34, 33), //set_tid_address|timer_create|timer_settime|timer_gettime|timer_getoverrun|timer_delete|clock_settime|clock_gettime|clock_getres|clock_nanosleep|statfs64|fstatfs64|tgkill
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 271, 33, 32), //arm_fadvise64_64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 269, 36, 35), //set_tid_address|timer_create|timer_settime|timer_gettime|timer_getoverrun|timer_delete|clock_settime|clock_gettime|clock_getres|clock_nanosleep|statfs64|fstatfs64|tgkill
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 271, 35, 34), //arm_fadvise64_64
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 286, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 285, 31, 30), //waitid|socket|bind|connect|listen
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 289, 30, 29), //getsockname|getpeername|socketpair
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 285, 33, 32), //waitid|socket|bind|connect|listen
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 289, 32, 31), //getsockname|getpeername|socketpair
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 350, 15, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 327, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 316, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 317, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 292, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 291, 25, 24), //sendto
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 298, 24, 23), //recvfrom|shutdown|setsockopt|getsockopt|sendmsg|recvmsg
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 291, 27, 26), //sendto
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 298, 26, 25), //recvfrom|shutdown|setsockopt|getsockopt|sendmsg|recvmsg
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 322, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 319, 22, 21), //inotify_init|inotify_add_watch|inotify_rm_watch
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 326, 21, 20), //openat|mkdirat|mknodat|fchownat
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 319, 24, 23), //inotify_add_watch|inotify_rm_watch
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 326, 23, 22), //openat|mkdirat|mknodat|fchownat
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 345, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 340, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 338, 18, 17), //fstatat64|unlinkat|renameat|linkat|symlinkat|readlinkat|fchmodat|faccessat|pselect6|ppoll|unshare
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 344, 17, 16), //splice|sync_file_range2|tee|vmsplice
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 338, 20, 19), //fstatat64|unlinkat|renameat|linkat|symlinkat|readlinkat|fchmodat|faccessat|pselect6|ppoll|unshare
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 344, 19, 18), //splice|sync_file_range2|tee|vmsplice
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 348, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 347, 15, 14), //getcpu|epoll_pwait
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 349, 14, 13), //utimensat
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 390, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 372, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 369, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 367, 10, 9), //timerfd_create|eventfd|fallocate|timerfd_settime|timerfd_gettime|signalfd4|eventfd2|epoll_create1|dup3|pipe2|inotify_init1|preadv|pwritev|rt_tgsigqueueinfo|perf_event_open|recvmmsg|accept4
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 347, 17, 16), //getcpu|epoll_pwait
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 349, 16, 15), //utimensat
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 380, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 369, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 352, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 351, 12, 11), //timerfd_create
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 367, 11, 10), //fallocate|timerfd_settime|timerfd_gettime|signalfd4|eventfd2|epoll_create1|dup3|pipe2|inotify_init1|preadv|pwritev|rt_tgsigqueueinfo|perf_event_open|recvmmsg|accept4
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 372, 1, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 370, 9, 8), //prlimit64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 380, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 378, 7, 6), //clock_adjtime|syncfs|sendmmsg|setns|process_vm_readv|process_vm_writev
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 388, 6, 5), //sched_setattr|sched_getattr|renameat2|seccomp|getrandom|memfd_create|bpf|execveat
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 983045, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 983042, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 394, 3, 2), //mlock2|copy_file_range|preadv2|pwritev2
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 378, 8, 7), //clock_adjtime|syncfs|sendmmsg|setns|process_vm_readv|process_vm_writev
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 983042, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 390, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 388, 5, 4), //sched_setattr|sched_getattr|renameat2|seccomp|getrandom|memfd_create|bpf|execveat
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 394, 4, 3), //mlock2|copy_file_range|preadv2|pwritev2
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 983045, 1, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 983043, 2, 1), //__ARM_NR_cacheflush
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 983046, 1, 0), //__ARM_NR_set_tls
 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
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/mips_system_policy.cpp b/libc/seccomp/mips_system_policy.cpp
index a88a6e3..32ed567 100644
--- a/libc/seccomp/mips_system_policy.cpp
+++ b/libc/seccomp/mips_system_policy.cpp
@@ -5,108 +5,116 @@
 
 #include "seccomp_bpfs.h"
 const sock_filter mips_system_filter[] = {
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4001, 0, 108),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4128, 53, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4063, 27, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4036, 13, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4023, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4010, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4008, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4007, 101, 100), //exit|fork|read|write|open|close
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4009, 100, 99), //creat
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4019, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4013, 98, 97), //unlink|execve|chdir
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4022, 97, 96), //lseek|getpid|mount
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4033, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4026, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4025, 94, 93), //setuid|getuid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4027, 93, 92), //ptrace
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4034, 92, 91), //access
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4001, 0, 116),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4131, 57, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4064, 29, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4041, 15, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4019, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4006, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4003, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4002, 109, 108), //exit
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4005, 108, 107), //read|write
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4011, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4007, 106, 105), //close
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4013, 105, 104), //execve|chdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4026, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4023, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4022, 102, 101), //lseek|getpid|mount
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4025, 101, 100), //setuid|getuid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4036, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4027, 99, 98), //ptrace
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4038, 98, 97), //sync|kill
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4054, 7, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4045, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4041, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4040, 88, 87), //sync|kill|rename|mkdir
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4044, 87, 86), //dup|pipe|times
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4043, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4042, 94, 93), //dup
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4044, 93, 92), //times
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4049, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4048, 85, 84), //brk|setgid|getgid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4053, 84, 83), //geteuid|getegid|acct|umount2
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4048, 91, 90), //brk|setgid|getgid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4053, 90, 89), //geteuid|getegid|acct|umount2
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4060, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4057, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4056, 81, 80), //ioctl|fcntl
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4058, 80, 79), //setpgid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4062, 79, 78), //umask|chroot
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4055, 87, 86), //ioctl
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4058, 86, 85), //setpgid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4062, 85, 84), //umask|chroot
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4094, 13, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4085, 7, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4070, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4066, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4065, 74, 73), //dup2|getppid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4068, 73, 72), //setsid|sigaction
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4065, 80, 79), //getppid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4068, 79, 78), //setsid|sigaction
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4074, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4072, 71, 70), //setreuid|setregid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4082, 70, 69), //sethostname|setrlimit|getrlimit|getrusage|gettimeofday|settimeofday|getgroups|setgroups
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4090, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4072, 77, 76), //setreuid|setregid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4082, 76, 75), //sethostname|setrlimit|getrlimit|getrusage|gettimeofday|settimeofday|getgroups|setgroups
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4091, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4088, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4086, 67, 66), //readlink
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4089, 66, 65), //reboot
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4093, 65, 64), //mmap|munmap|truncate
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4116, 5, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4086, 73, 72), //readlink
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4089, 72, 71), //reboot
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4093, 71, 70), //munmap|truncate
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4118, 7, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4114, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4103, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4098, 61, 60), //fchmod|fchown|getpriority|setpriority
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4106, 60, 59), //syslog|setitimer|getitimer
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4115, 59, 58), //wait4
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4124, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4118, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4117, 56, 55), //sysinfo
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4123, 55, 54), //fsync|sigreturn|clone|setdomainname|uname
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4126, 54, 53), //adjtimex|mprotect
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4222, 27, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4176, 13, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4098, 67, 66), //fchmod|fchown|getpriority|setpriority
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4106, 66, 65), //syslog|setitimer|getitimer
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4116, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4115, 64, 63), //wait4
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4117, 63, 62), //sysinfo
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4128, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4124, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4123, 60, 59), //fsync|sigreturn|clone|setdomainname|uname
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4126, 59, 58), //adjtimex|mprotect
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4130, 58, 57), //init_module|delete_module
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4249, 29, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4179, 15, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4151, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4136, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4131, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4130, 48, 47), //init_module|delete_module
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4134, 47, 46), //quotactl|getpgid|fchdir
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4138, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4137, 45, 44), //personality
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4148, 44, 43), //setfsuid|setfsgid|_llseek|getdents|_newselect|flock|msync|readv|writev|cacheflush
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4138, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4136, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4134, 52, 51), //quotactl|getpgid|fchdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4137, 51, 50), //personality
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4143, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4141, 49, 48), //setfsuid|setfsgid|_llseek
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4148, 48, 47), //flock|msync|readv|writev|cacheflush
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4169, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4154, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4153, 41, 40), //getsid|fdatasync
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4168, 40, 39), //mlock|munlock|mlockall|munlockall|sched_setparam|sched_getparam|sched_setscheduler|sched_getscheduler|sched_yield|sched_get_priority_max|sched_get_priority_min|sched_rr_get_interval|nanosleep|mremap
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4175, 39, 38), //bind|connect|getpeername|getsockname|getsockopt|listen
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4203, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4188, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4179, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4178, 35, 34), //recvfrom|recvmsg
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4187, 34, 33), //sendmsg|sendto|setsockopt|shutdown|socket|socketpair|setresuid|getresuid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4153, 45, 44), //getsid|fdatasync
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4168, 44, 43), //mlock|munlock|mlockall|munlockall|sched_setparam|sched_getparam|sched_setscheduler|sched_getscheduler|sched_yield|sched_get_priority_max|sched_get_priority_min|sched_rr_get_interval|nanosleep|mremap
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4176, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4175, 42, 41), //bind|connect|getpeername|getsockname|getsockopt|listen
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4178, 41, 40), //recvfrom|recvmsg
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4215, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4203, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4190, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4189, 32, 31), //poll
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4202, 31, 30), //setresgid|getresgid|prctl|rt_sigreturn|rt_sigaction|rt_sigprocmask|rt_sigpending|rt_sigtimedwait|rt_sigqueueinfo|rt_sigsuspend|pread64|pwrite64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4217, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4187, 37, 36), //sendmsg|sendto|setsockopt|shutdown|socket|socketpair|setresuid|getresuid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4202, 36, 35), //setresgid|getresgid|prctl|rt_sigreturn|rt_sigaction|rt_sigprocmask|rt_sigpending|rt_sigtimedwait|rt_sigqueueinfo|rt_sigsuspend|pread64|pwrite64
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4210, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4208, 28, 27), //getcwd|capget|capset|sigaltstack|sendfile
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4216, 27, 26), //mmap2|truncate64|ftruncate64|stat64|lstat64|fstat64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4221, 26, 25), //mincore|madvise|getdents64|fcntl64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4316, 13, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4288, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4208, 34, 33), //getcwd|capget|capset|sigaltstack|sendfile
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4213, 33, 32), //mmap2|truncate64|ftruncate64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4222, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4217, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4216, 30, 29), //fstat64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4221, 29, 28), //mincore|madvise|getdents64|fcntl64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4247, 28, 27), //gettid|readahead|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|tkill|sendfile64|futex|sched_setaffinity|sched_getaffinity|io_setup|io_destroy|io_getevents|io_submit|io_cancel|exit_group
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4312, 13, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4285, 7, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4278, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4248, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4247, 21, 20), //gettid|readahead|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|tkill|sendfile64|futex|sched_setaffinity|sched_getaffinity|io_setup|io_destroy|io_getevents|io_submit|io_cancel|exit_group
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4267, 20, 19), //epoll_create|epoll_ctl|epoll_wait|remap_file_pages|set_tid_address|restart_syscall|fadvise64|statfs64|fstatfs64|timer_create|timer_settime|timer_gettime|timer_getoverrun|timer_delete|clock_settime|clock_gettime|clock_getres|clock_nanosleep|tgkill
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4252, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4250, 23, 22), //epoll_ctl
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4267, 22, 21), //set_tid_address|restart_syscall|fadvise64|statfs64|fstatfs64|timer_create|timer_settime|timer_gettime|timer_getoverrun|timer_delete|clock_settime|clock_gettime|clock_getres|clock_nanosleep|tgkill
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4283, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4279, 18, 17), //waitid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4287, 17, 16), //set_thread_area|inotify_init|inotify_add_watch|inotify_rm_watch
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4312, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4293, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4292, 14, 13), //openat|mkdirat|mknodat|fchownat
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4308, 13, 12), //fstatat64|unlinkat|renameat|linkat|symlinkat|readlinkat|fchmodat|faccessat|pselect6|ppoll|unshare|splice|sync_file_range|tee|vmsplice
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4314, 12, 11), //getcpu|epoll_pwait
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4341, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4338, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4319, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4317, 8, 7), //utimensat
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4336, 7, 6), //eventfd|fallocate|timerfd_create|timerfd_gettime|timerfd_settime|signalfd4|eventfd2|epoll_create1|dup3|pipe2|inotify_init1|preadv|pwritev|rt_tgsigqueueinfo|perf_event_open|accept4|recvmmsg
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4279, 20, 19), //waitid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4284, 19, 18), //set_thread_area
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4293, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4288, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4287, 16, 15), //inotify_add_watch|inotify_rm_watch
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4292, 15, 14), //openat|mkdirat|mknodat|fchownat
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4308, 14, 13), //fstatat64|unlinkat|renameat|linkat|symlinkat|readlinkat|fchmodat|faccessat|pselect6|ppoll|unshare|splice|sync_file_range|tee|vmsplice
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4341, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4320, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4316, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4314, 10, 9), //getcpu|epoll_pwait
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4317, 9, 8), //utimensat
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4338, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4336, 7, 6), //fallocate|timerfd_create|timerfd_gettime|timerfd_settime|signalfd4|eventfd2|epoll_create1|dup3|pipe2|inotify_init1|preadv|pwritev|rt_tgsigqueueinfo|perf_event_open|accept4|recvmmsg
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4339, 6, 5), //prlimit64
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4359, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4349, 1, 0),
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/seccomp/x86_system_policy.cpp b/libc/seccomp/x86_system_policy.cpp
index 3a34c69..af1b14f 100644
--- a/libc/seccomp/x86_system_policy.cpp
+++ b/libc/seccomp/x86_system_policy.cpp
@@ -5,112 +5,118 @@
 
 #include "seccomp_bpfs.h"
 const sock_filter x86_system_filter[] = {
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 0, 0, 114),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 131, 57, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 0, 0, 120),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 136, 59, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 66, 29, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 41, 15, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 24, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 10, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 8, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 7, 107, 106), //restart_syscall|exit|fork|read|write|open|close
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 9, 106, 105), //creat
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 19, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 13, 104, 103), //unlink|execve|chdir
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 22, 103, 102), //lseek|getpid|mount
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 33, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 43, 15, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 19, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 6, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 3, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 2, 113, 112), //restart_syscall|exit
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5, 112, 111), //read|write
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 11, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 7, 110, 109), //close
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 13, 109, 108), //execve|chdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 36, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 26, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 25, 100, 99), //getuid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 27, 99, 98), //ptrace
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 36, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 34, 97, 96), //access
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 40, 96, 95), //sync|kill|rename|mkdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 22, 106, 105), //lseek|getpid|mount
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 27, 105, 104), //ptrace
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 41, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 38, 103, 102), //sync|kill
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 42, 102, 101), //dup
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 57, 7, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 51, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 45, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 44, 92, 91), //dup|pipe|times
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 46, 91, 90), //brk
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 44, 98, 97), //times
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 46, 97, 96), //brk
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 54, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 53, 89, 88), //acct|umount2
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 56, 88, 87), //ioctl|fcntl
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 63, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 53, 95, 94), //acct|umount2
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 55, 94, 93), //ioctl
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 64, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 60, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 58, 85, 84), //setpgid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 62, 84, 83), //umask|chroot
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 65, 83, 82), //dup2|getppid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 96, 13, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 58, 91, 90), //setpgid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 62, 90, 89), //umask|chroot
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 65, 89, 88), //getppid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 102, 15, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 88, 7, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 77, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 74, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 68, 78, 77), //setsid|sigaction
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 76, 77, 76), //sethostname|setrlimit
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 68, 84, 83), //setsid|sigaction
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 76, 83, 82), //sethostname|setrlimit
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 85, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 80, 75, 74), //getrusage|gettimeofday|settimeofday
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 86, 74, 73), //readlink
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 80, 81, 80), //getrusage|gettimeofday|settimeofday
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 86, 80, 79), //readlink
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 94, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 90, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 89, 71, 70), //reboot
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 93, 70, 69), //mmap|munmap|truncate
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 95, 69, 68), //fchmod
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 118, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 114, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 102, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 98, 65, 64), //getpriority|setpriority
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 106, 64, 63), //socketcall|syslog|setitimer|getitimer
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 116, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 115, 62, 61), //wait4
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 117, 61, 60), //sysinfo
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 128, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 124, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 123, 58, 57), //fsync|sigreturn|clone|setdomainname|uname
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 126, 57, 56), //adjtimex|mprotect
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 130, 56, 55), //init_module|delete_module
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 254, 27, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 190, 13, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 168, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 138, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 136, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 134, 50, 49), //quotactl|getpgid|fchdir
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 137, 49, 48), //personality
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 91, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 89, 77, 76), //reboot
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 93, 76, 75), //munmap|truncate
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 96, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 95, 74, 73), //fchmod
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 98, 73, 72), //getpriority|setpriority
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 124, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 116, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 114, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 106, 69, 68), //socketcall|syslog|setitimer|getitimer
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 115, 68, 67), //wait4
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 118, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 117, 66, 65), //sysinfo
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 123, 65, 64), //fsync|sigreturn|clone|setdomainname|uname
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 131, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 128, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 126, 62, 61), //adjtimex|mprotect
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 130, 61, 60), //init_module|delete_module
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 134, 60, 59), //quotactl|getpgid|fchdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 258, 29, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 199, 15, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 172, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 143, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 138, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 137, 54, 53), //personality
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 141, 53, 52), //setfsuid|setfsgid|_llseek
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 150, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 149, 47, 46), //setfsuid|setfsgid|_llseek|getdents|_newselect|flock|msync|readv|writev|getsid|fdatasync
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 164, 46, 45), //mlock|munlock|mlockall|munlockall|sched_setparam|sched_getparam|sched_setscheduler|sched_getscheduler|sched_yield|sched_get_priority_max|sched_get_priority_min|sched_rr_get_interval|nanosleep|mremap
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 183, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 172, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 169, 43, 42), //poll
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 182, 42, 41), //prctl|rt_sigreturn|rt_sigaction|rt_sigprocmask|rt_sigpending|rt_sigtimedwait|rt_sigqueueinfo|rt_sigsuspend|pread64|pwrite64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 188, 41, 40), //getcwd|capget|capset|sigaltstack|sendfile
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 224, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 213, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 199, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 198, 37, 36), //vfork|ugetrlimit|mmap2|truncate64|ftruncate64|stat64|lstat64|fstat64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 212, 36, 35), //getuid32|getgid32|geteuid32|getegid32|setreuid32|setregid32|getgroups32|setgroups32|fchown32|setresuid32|getresuid32|setresgid32|getresgid32
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 218, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 215, 34, 33), //setuid32|setgid32
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 222, 33, 32), //mincore|madvise|getdents64|fcntl64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 252, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 245, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 244, 30, 29), //gettid|readahead|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|tkill|sendfile64|futex|sched_setaffinity|sched_getaffinity|set_thread_area
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 250, 29, 28), //io_setup|io_destroy|io_getevents|io_submit|io_cancel
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 253, 28, 27), //exit_group
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 318, 13, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 149, 51, 50), //flock|msync|readv|writev|getsid|fdatasync
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 164, 50, 49), //mlock|munlock|mlockall|munlockall|sched_setparam|sched_getparam|sched_setscheduler|sched_getscheduler|sched_yield|sched_get_priority_max|sched_get_priority_min|sched_rr_get_interval|nanosleep|mremap
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 190, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 183, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 182, 47, 46), //prctl|rt_sigreturn|rt_sigaction|rt_sigprocmask|rt_sigpending|rt_sigtimedwait|rt_sigqueueinfo|rt_sigsuspend|pread64|pwrite64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 188, 46, 45), //getcwd|capget|capset|sigaltstack|sendfile
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 197, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 195, 44, 43), //vfork|ugetrlimit|mmap2|truncate64|ftruncate64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 198, 43, 42), //fstat64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 245, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 218, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 213, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 212, 39, 38), //getuid32|getgid32|geteuid32|getegid32|setreuid32|setregid32|getgroups32|setgroups32|fchown32|setresuid32|getresuid32|setresgid32|getresgid32
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 215, 38, 37), //setuid32|setgid32
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 224, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 222, 36, 35), //mincore|madvise|getdents64|fcntl64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 244, 35, 34), //gettid|readahead|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|tkill|sendfile64|futex|sched_setaffinity|sched_getaffinity|set_thread_area
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 255, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 252, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 250, 32, 31), //io_setup|io_destroy|io_getevents|io_submit|io_cancel
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 253, 31, 30), //exit_group
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 256, 30, 29), //epoll_ctl
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 322, 15, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 295, 7, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 284, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 272, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 271, 23, 22), //epoll_create|epoll_ctl|epoll_wait|remap_file_pages|set_tid_address|timer_create|timer_settime|timer_gettime|timer_getoverrun|timer_delete|clock_settime|clock_gettime|clock_getres|clock_nanosleep|statfs64|fstatfs64|tgkill
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 273, 22, 21), //fadvise64_64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 291, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 285, 20, 19), //waitid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 294, 19, 18), //inotify_init|inotify_add_watch|inotify_rm_watch
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 271, 25, 24), //set_tid_address|timer_create|timer_settime|timer_gettime|timer_getoverrun|timer_delete|clock_settime|clock_gettime|clock_getres|clock_nanosleep|statfs64|fstatfs64|tgkill
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 273, 24, 23), //fadvise64_64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 292, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 285, 22, 21), //waitid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 294, 21, 20), //inotify_add_watch|inotify_rm_watch
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 313, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 300, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 299, 16, 15), //openat|mkdirat|mknodat|fchownat
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 311, 15, 14), //fstatat64|unlinkat|renameat|linkat|symlinkat|readlinkat|fchmodat|faccessat|pselect6|ppoll|unshare
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 317, 14, 13), //splice|sync_file_range|tee|vmsplice
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 299, 18, 17), //openat|mkdirat|mknodat|fchownat
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 311, 17, 16), //fstatat64|unlinkat|renameat|linkat|symlinkat|readlinkat|fchmodat|faccessat|pselect6|ppoll|unshare
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 318, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 317, 15, 14), //splice|sync_file_range|tee|vmsplice
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 321, 14, 13), //getcpu|epoll_pwait|utimensat
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 346, 7, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 340, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 322, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 321, 10, 9), //getcpu|epoll_pwait|utimensat
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 337, 9, 8), //timerfd_create|eventfd|fallocate|timerfd_settime|timerfd_gettime|signalfd4|eventfd2|epoll_create1|dup3|pipe2|inotify_init1|preadv|pwritev|rt_tgsigqueueinfo|perf_event_open
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 324, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 323, 10, 9), //timerfd_create
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 337, 9, 8), //fallocate|timerfd_settime|timerfd_gettime|signalfd4|eventfd2|epoll_create1|dup3|pipe2|inotify_init1|preadv|pwritev|rt_tgsigqueueinfo|perf_event_open
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 343, 1, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 341, 7, 6), //prlimit64
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 345, 6, 5), //clock_adjtime|syncfs
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
index 517935b..441fcfe 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -32,19 +32,16 @@
  * SUCH DAMAGE.
  */
 
-#ifndef __BIONIC_STDIO_LOCAL_H__
-#define __BIONIC_STDIO_LOCAL_H__
+#pragma once
 
 #include <pthread.h>
 #include <stdbool.h>
 #include <wchar.h>
 
-#if defined(__cplusplus) // Until we fork all of stdio...
+#if defined(__cplusplus)  // Until we fork all of stdio...
 #include "private/bionic_fortify.h"
 #endif
 
-#include "wcio.h"
-
 /*
  * Information local to this implementation of stdio,
  * in particular, macros and private variables.
@@ -62,53 +59,66 @@
 };
 
 struct __sFILE {
-	unsigned char *_p;	/* current position in (some) buffer */
-	int	_r;		/* read space left for getc() */
-	int	_w;		/* write space left for putc() */
+  unsigned char* _p; /* current position in (some) buffer */
+  int _r;            /* read space left for getc() */
+  int _w;            /* write space left for putc() */
 #if defined(__LP64__)
-	int	_flags;		/* flags, below; this FILE is free if 0 */
-	int	_file;		/* fileno, if Unix descriptor, else -1 */
+  int _flags; /* flags, below; this FILE is free if 0 */
+  int _file;  /* fileno, if Unix descriptor, else -1 */
 #else
-	short	_flags;		/* flags, below; this FILE is free if 0 */
-	short	_file;		/* fileno, if Unix descriptor, else -1 */
+  short _flags; /* flags, below; this FILE is free if 0 */
+  short _file;  /* fileno, if Unix descriptor, else -1 */
 #endif
-	struct	__sbuf _bf;	/* the buffer (at least 1 byte, if !NULL) */
-	int	_lbfsize;	/* 0 or -_bf._size, for inline putc */
+  struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */
+  int _lbfsize;      /* 0 or -_bf._size, for inline putc */
 
-	// Function pointers used by `funopen`.
-	// Note that `_seek` is ignored if `_seek64` (in __sfileext) is set.
-	// TODO: NetBSD has `funopen2` which corrects the `int`s to `size_t`s.
-	// TODO: glibc has `fopencookie` which passes the function pointers in a struct.
-	void* _cookie;	/* cookie passed to io functions */
-	int (*_close)(void*);
-	int (*_read)(void*, char*, int);
-	fpos_t (*_seek)(void*, fpos_t, int);
-	int (*_write)(void*, const char*, int);
+  // Function pointers used by `funopen`.
+  // Note that `_seek` is ignored if `_seek64` (in __sfileext) is set.
+  // TODO: NetBSD has `funopen2` which corrects the `int`s to `size_t`s.
+  // TODO: glibc has `fopencookie` which passes the function pointers in a struct.
+  void* _cookie; /* cookie passed to io functions */
+  int (*_close)(void*);
+  int (*_read)(void*, char*, int);
+  fpos_t (*_seek)(void*, fpos_t, int);
+  int (*_write)(void*, const char*, int);
 
-	/* extension data, to avoid further ABI breakage */
-	struct	__sbuf _ext;
-	/* data for long sequences of ungetc() */
-	unsigned char *_up;	/* saved _p when _p is doing ungetc data */
-	int	_ur;		/* saved _r when _r is counting ungetc data */
+  /* extension data, to avoid further ABI breakage */
+  struct __sbuf _ext;
+  /* data for long sequences of ungetc() */
+  unsigned char* _up; /* saved _p when _p is doing ungetc data */
+  int _ur;            /* saved _r when _r is counting ungetc data */
 
-	/* tricks to meet minimum requirements even when malloc() fails */
-	unsigned char _ubuf[3];	/* guarantee an ungetc() buffer */
-	unsigned char _nbuf[1];	/* guarantee a getc() buffer */
+  /* tricks to meet minimum requirements even when malloc() fails */
+  unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */
+  unsigned char _nbuf[1]; /* guarantee a getc() buffer */
 
-	/* separate buffer for fgetln() when line crosses buffer boundary */
-	struct	__sbuf _lb;	/* buffer for fgetln() */
+  /* separate buffer for fgetln() when line crosses buffer boundary */
+  struct __sbuf _lb; /* buffer for fgetln() */
 
-	/* Unix stdio files get aligned to block boundaries on fseek() */
-	int	_blksize;	/* stat.st_blksize (may be != _bf._size) */
+  /* Unix stdio files get aligned to block boundaries on fseek() */
+  int _blksize; /* stat.st_blksize (may be != _bf._size) */
 
-	fpos_t _unused_0; // This was the `_offset` field (see below).
+  fpos_t _unused_0;  // This was the `_offset` field (see below).
 
-	// Do not add new fields here. (Or remove or change the size of any above.)
-	// Although bionic currently exports `stdin`, `stdout`, and `stderr` symbols,
-	// that still hasn't made it to the NDK. All NDK-built apps index directly
-	// into an array of this struct (which was in <stdio.h> historically), so if
-	// you need to make any changes, they need to be in the `__sfileext` struct
-	// below, and accessed via `_EXT`.
+  // Do not add new fields here. (Or remove or change the size of any above.)
+  // Although bionic currently exports `stdin`, `stdout`, and `stderr` symbols,
+  // that still hasn't made it to the NDK. All NDK-built apps index directly
+  // into an array of this struct (which was in <stdio.h> historically), so if
+  // you need to make any changes, they need to be in the `__sfileext` struct
+  // below, and accessed via `_EXT`.
+};
+
+/* minimal requirement of SUSv2 */
+#define WCIO_UNGETWC_BUFSIZE 1
+
+struct wchar_io_data {
+  mbstate_t wcio_mbstate_in;
+  mbstate_t wcio_mbstate_out;
+
+  wchar_t wcio_ungetwc_buf[WCIO_UNGETWC_BUFSIZE];
+  size_t wcio_ungetwc_inbuf;
+
+  int wcio_mode; /* orientation */
 };
 
 struct __sfileext {
@@ -134,9 +144,9 @@
 #define __SNBF 0x0002  // Unbuffered.
 // __SRD and __SWR are mutually exclusive because they indicate what we did last.
 // If you want to know whether we were opened read-write, check __SRW instead.
-#define __SRD  0x0004  // Last operation was read.
-#define __SWR  0x0008  // Last operation was write.
-#define __SRW  0x0010  // Was opened for reading & writing.
+#define __SRD 0x0004   // Last operation was read.
+#define __SWR 0x0008   // Last operation was write.
+#define __SRW 0x0010   // Was opened for reading & writing.
 #define __SEOF 0x0020  // Found EOF.
 #define __SERR 0x0040  // Found error.
 #define __SMBF 0x0080  // `_buf` is from malloc.
@@ -157,20 +167,19 @@
 #define _EXT(fp) __BIONIC_CAST(reinterpret_cast, struct __sfileext*, (fp)->_ext._base)
 
 #define _UB(fp) _EXT(fp)->_ub
-#define _FLOCK(fp)  _EXT(fp)->_lock
+#define _FLOCK(fp) _EXT(fp)->_lock
 
-#define _FILEEXT_SETUP(fp, fext) \
-  do { \
+#define _FILEEXT_SETUP(fp, fext)                                              \
+  do {                                                                        \
     (fp)->_ext._base = __BIONIC_CAST(reinterpret_cast, unsigned char*, fext); \
-    memset(_EXT(fp), 0, sizeof(struct __sfileext)); \
-    _EXT(fp)->_caller_handles_locking = true; \
+    memset(_EXT(fp), 0, sizeof(struct __sfileext));                           \
+    _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*);
@@ -184,49 +193,47 @@
 __LIBC32_LEGACY_PUBLIC__ void __smakebuf(FILE*);
 
 /* These are referenced by the Greed for Glory franchise. */
-__LIBC32_LEGACY_PUBLIC__ int __sflush(FILE *);
-__LIBC32_LEGACY_PUBLIC__ int __sread(void *, char *, int);
-__LIBC32_LEGACY_PUBLIC__ int __swrite(void *, const char *, int);
-__LIBC32_LEGACY_PUBLIC__ fpos_t __sseek(void *, fpos_t, int);
-__LIBC32_LEGACY_PUBLIC__ int __sclose(void *);
-__LIBC32_LEGACY_PUBLIC__ int _fwalk(int (*)(FILE *));
+__LIBC32_LEGACY_PUBLIC__ int __sflush(FILE*);
+__LIBC32_LEGACY_PUBLIC__ int __sread(void*, char*, int);
+__LIBC32_LEGACY_PUBLIC__ int __swrite(void*, const char*, int);
+__LIBC32_LEGACY_PUBLIC__ fpos_t __sseek(void*, fpos_t, int);
+__LIBC32_LEGACY_PUBLIC__ int __sclose(void*);
+__LIBC32_LEGACY_PUBLIC__ int _fwalk(int (*)(FILE*));
 
 off64_t __sseek64(void*, off64_t, int);
-int	__sflush_locked(FILE *);
-int	__swhatbuf(FILE *, size_t *, int *);
-wint_t __fgetwc_unlock(FILE *);
-wint_t	__ungetwc(wint_t, FILE *);
-int	__vfprintf(FILE *, const char *, va_list);
-int	__svfscanf(FILE *, const char *, va_list);
-int	__vfwprintf(FILE *, const wchar_t *, va_list);
-int	__vfwscanf(FILE *, const wchar_t *, va_list);
+int __sflush_locked(FILE*);
+int __swhatbuf(FILE*, size_t*, int*);
+wint_t __fgetwc_unlock(FILE*);
+wint_t __ungetwc(wint_t, FILE*);
+int __vfprintf(FILE*, const char*, va_list);
+int __svfscanf(FILE*, const char*, va_list);
+int __vfwprintf(FILE*, const wchar_t*, va_list);
+int __vfwscanf(FILE*, const wchar_t*, va_list);
 
 /*
  * Return true if the given FILE cannot be written now.
  */
-#define	cantwrite(fp) \
-	((((fp)->_flags & __SWR) == 0 || (fp)->_bf._base == NULL) && \
-	 __swsetup(fp))
+#define cantwrite(fp) ((((fp)->_flags & __SWR) == 0 || (fp)->_bf._base == NULL) && __swsetup(fp))
 
 /*
  * Test whether the given stdio file has an active ungetc buffer;
  * release such a buffer, without restoring ordinary unread data.
  */
-#define	HASUB(fp) (_UB(fp)._base != NULL)
-#define	FREEUB(fp) { \
-	if (_UB(fp)._base != (fp)->_ubuf) \
-		free(_UB(fp)._base); \
-	_UB(fp)._base = NULL; \
-}
+#define HASUB(fp) (_UB(fp)._base != NULL)
+#define FREEUB(fp)                                         \
+  {                                                        \
+    if (_UB(fp)._base != (fp)->_ubuf) free(_UB(fp)._base); \
+    _UB(fp)._base = NULL;                                  \
+  }
 
-#define FLOCKFILE(fp)   if (!_EXT(fp)->_caller_handles_locking) flockfile(fp)
-#define FUNLOCKFILE(fp) if (!_EXT(fp)->_caller_handles_locking) funlockfile(fp)
-
-#define NO_PRINTF_PERCENT_N
+#define FLOCKFILE(fp) \
+  if (!_EXT(fp)->_caller_handles_locking) flockfile(fp)
+#define FUNLOCKFILE(fp) \
+  if (!_EXT(fp)->_caller_handles_locking) funlockfile(fp)
 
 /* OpenBSD exposes these in <stdio.h>, but we only want them exposed to the implementation. */
-#define __sferror(p)   (((p)->_flags & __SERR) != 0)
-#define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR|__SEOF)))
+#define __sferror(p) (((p)->_flags & __SERR) != 0)
+#define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR | __SEOF)))
 #define __sgetc(p) (--(p)->_r < 0 ? __srget(p) : (int)(*(p)->_p++))
 
 /* OpenBSD declares these in fvwrite.h, but we share them with C++ parts of the implementation. */
@@ -243,7 +250,7 @@
 wint_t __fputwc_unlock(wchar_t wc, FILE* fp);
 
 /* Remove the if (!__sdidinit) __sinit() idiom from untouched upstream stdio code. */
-extern void __sinit(void); // Not actually implemented.
+extern void __sinit(void);  // Not actually implemented.
 #define __sdidinit 1
 
 size_t parsefloat(FILE*, char*, char*);
@@ -251,7 +258,8 @@
 
 // Sanity check a FILE* for nullptr, so we can emit a message while crashing
 // instead of doing a blind null-dereference.
-#define CHECK_FP(fp) if (fp == nullptr) __fortify_fatal("%s: null FILE*", __FUNCTION__)
+#define CHECK_FP(fp) \
+  if (fp == nullptr) __fortify_fatal("%s: null FILE*", __FUNCTION__)
 
 /*
  * Floating point scanf/printf (input/output) definitions.
@@ -278,6 +286,21 @@
 char* __hldtoa(long double, const char*, int, int*, int*, char**);
 char* __ldtoa(long double*, int, int, int*, int*, char**);
 
-__END_DECLS
+#define WCIO_GET(fp) (_EXT(fp) ? &(_EXT(fp)->_wcio) : (struct wchar_io_data*)0)
 
-#endif
+#define _SET_ORIENTATION(fp, mode)                                 \
+  do {                                                             \
+    struct wchar_io_data* _wcio = WCIO_GET(fp);                    \
+    if (_wcio && _wcio->wcio_mode == 0) _wcio->wcio_mode = (mode); \
+  } while (0)
+
+#define WCIO_FREE(fp)                           \
+  do {                                          \
+    struct wchar_io_data* _wcio = WCIO_GET(fp); \
+    if (_wcio) {                                \
+      _wcio->wcio_mode = 0;                     \
+      _wcio->wcio_ungetwc_inbuf = 0;            \
+    }                                           \
+  } while (0)
+
+__END_DECLS
diff --git a/libc/stdio/printf_common.h b/libc/stdio/printf_common.h
index 050120e..85c91de 100644
--- a/libc/stdio/printf_common.h
+++ b/libc/stdio/printf_common.h
@@ -499,24 +499,8 @@
         else
           ADDTYPE(T_DOUBLE);
         break;
-#ifndef NO_PRINTF_PERCENT_N
       case 'n':
-        if (flags & LLONGINT)
-          ADDTYPE(TP_LLONG);
-        else if (flags & LONGINT)
-          ADDTYPE(TP_LONG);
-        else if (flags & SHORTINT)
-          ADDTYPE(TP_SHORT);
-        else if (flags & PTRINT)
-          ADDTYPE(TP_PTRINT);
-        else if (flags & SIZEINT)
-          ADDTYPE(TP_SSIZEINT);
-        else if (flags & MAXINT)
-          ADDTYPE(TP_MAXINT);
-        else
-          ADDTYPE(TP_INT);
-        continue; /* no output */
-#endif            /* NO_PRINTF_PERCENT_N */
+        __fortify_fatal("%%n not allowed on Android");
       case 'O':
         flags |= LONGINT;
         /*FALLTHROUGH*/
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/vfprintf.cpp b/libc/stdio/vfprintf.cpp
index 9182880..17e4372 100644
--- a/libc/stdio/vfprintf.cpp
+++ b/libc/stdio/vfprintf.cpp
@@ -449,26 +449,8 @@
           lead = expt;
         }
         break;
-#ifndef NO_PRINTF_PERCENT_N
       case 'n':
-        if (flags & LLONGINT)
-          *GETARG(long long*) = ret;
-        else if (flags & LONGINT)
-          *GETARG(long*) = ret;
-        else if (flags & SHORTINT)
-          *GETARG(short*) = ret;
-        else if (flags & CHARINT)
-          *GETARG(signed char*) = ret;
-        else if (flags & PTRINT)
-          *GETARG(ptrdiff_t*) = ret;
-        else if (flags & SIZEINT)
-          *GETARG(ssize_t*) = ret;
-        else if (flags & MAXINT)
-          *GETARG(intmax_t*) = ret;
-        else
-          *GETARG(int*) = ret;
-        continue; /* no output */
-#endif            /* NO_PRINTF_PERCENT_N */
+        __fortify_fatal("%%n not allowed on Android");
       case 'O':
         flags |= LONGINT;
         /*FALLTHROUGH*/
diff --git a/libc/stdio/vfwprintf.cpp b/libc/stdio/vfwprintf.cpp
index 7a00202..46b6233 100644
--- a/libc/stdio/vfwprintf.cpp
+++ b/libc/stdio/vfwprintf.cpp
@@ -434,26 +434,8 @@
           lead = expt;
         }
         break;
-#ifndef NO_PRINTF_PERCENT_N
       case 'n':
-        if (flags & LLONGINT)
-          *GETARG(long long*) = ret;
-        else if (flags & LONGINT)
-          *GETARG(long*) = ret;
-        else if (flags & SHORTINT)
-          *GETARG(short*) = ret;
-        else if (flags & CHARINT)
-          *GETARG(signed char*) = ret;
-        else if (flags & PTRINT)
-          *GETARG(ptrdiff_t*) = ret;
-        else if (flags & SIZEINT)
-          *GETARG(ssize_t*) = ret;
-        else if (flags & MAXINT)
-          *GETARG(intmax_t*) = ret;
-        else
-          *GETARG(int*) = ret;
-        continue; /* no output */
-#endif            /* NO_PRINTF_PERCENT_N */
+        __fortify_fatal("%%n not allowed on Android");
       case 'O':
         flags |= LONGINT;
         /*FALLTHROUGH*/
diff --git a/libc/stdio/wcio.h b/libc/stdio/wcio.h
deleted file mode 100644
index 3c4f7a4..0000000
--- a/libc/stdio/wcio.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*	$OpenBSD: wcio.h,v 1.2 2013/04/17 17:40:35 tedu Exp $	*/
-/* $NetBSD: wcio.h,v 1.3 2003/01/18 11:30:00 thorpej Exp $ */
-
-/*-
- * Copyright (c)2001 Citrus 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:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
- *
- * $Citrus$
- */
-
-#ifndef _WCIO_H_
-#define _WCIO_H_
-
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-
-/* minimal requirement of SUSv2 */
-#define WCIO_UNGETWC_BUFSIZE 1
-
-struct wchar_io_data {
-	mbstate_t wcio_mbstate_in;
-	mbstate_t wcio_mbstate_out;
-
-	wchar_t wcio_ungetwc_buf[WCIO_UNGETWC_BUFSIZE];
-	size_t wcio_ungetwc_inbuf;
-
-	int wcio_mode; /* orientation */
-};
-
-#define WCIO_GET(fp) \
-	(_EXT(fp) ? &(_EXT(fp)->_wcio) : (struct wchar_io_data *)0)
-
-#define _SET_ORIENTATION(fp, mode) \
-do {\
-	struct wchar_io_data *_wcio = WCIO_GET(fp); \
-	if (_wcio && _wcio->wcio_mode == 0) \
-		_wcio->wcio_mode = (mode);\
-} while (0)
-
-/*
- * WCIO_FREE should be called by fclose
- */
-#define WCIO_FREE(fp) \
-do {\
-	struct wchar_io_data *_wcio = WCIO_GET(fp); \
-	if (_wcio) { \
-		_wcio->wcio_mode = 0;\
-		_wcio->wcio_ungetwc_inbuf = 0;\
-	} \
-} while (0)
-
-#define WCIO_FREEUB(fp) \
-do {\
-	struct wchar_io_data *_wcio = WCIO_GET(fp); \
-	if (_wcio) { \
-		_wcio->wcio_ungetwc_inbuf = 0;\
-	} \
-} 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..0e9a7d3 100644
--- a/libc/tzcode/strptime.c
+++ b/libc/tzcode/strptime.c
@@ -38,7 +38,9 @@
 
 //#include <sys/localedef.h>
 #include <ctype.h>
+#include <errno.h>
 #include <locale.h>
+#include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include "tzfile.h"
@@ -128,7 +130,7 @@
             fmt++;
             continue;
         }
-                
+
         if ((c = *fmt++) != '%')
             goto literal;
 
@@ -154,7 +156,7 @@
             _LEGAL_ALT(0);
             alt_format |= _ALT_O;
             goto again;
-            
+
         /*
          * "Complex" conversion rules, implemented through recursion.
          */
@@ -169,7 +171,7 @@
             if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
                 return (NULL);
             break;
-    
+
         case 'R':   /* The time as "%H:%M". */
             _LEGAL_ALT(0);
             if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
@@ -337,6 +339,25 @@
                 return (NULL);
             break;
 
+        case 's':
+            {
+                // Android addition, based on FreeBSD's implementation.
+                int saved_errno = errno;
+                errno = 0;
+                const unsigned char* old_bp = bp;
+                long n = strtol((const char*) bp, (char**) &bp, 10);
+                time_t t = n;
+                if (bp == old_bp || errno == ERANGE || ((long) t) != n) {
+                    errno = saved_errno;
+                    return NULL;
+                }
+                errno = saved_errno;
+
+                if (localtime_r(&t, tm) == NULL) return NULL;
+            }
+            break;
+
+
         case 'U':   /* The week of year, beginning on sunday. */
         case 'W':   /* The week of year, beginning on monday. */
             _LEGAL_ALT(_ALT_O);
@@ -430,3 +451,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/stdlib/system.c b/libc/upstream-openbsd/lib/libc/stdlib/system.c
deleted file mode 100644
index de32d43..0000000
--- a/libc/upstream-openbsd/lib/libc/stdlib/system.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*	$OpenBSD: system.c,v 1.11 2015/10/23 04:44:41 guenther Exp $ */
-/*
- * Copyright (c) 1988 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <paths.h>
-
-extern char **environ;
-
-int
-system(const char *command)
-{
-	pid_t pid, cpid;
-	struct sigaction intsave, quitsave;
-	sigset_t mask, omask;
-	int pstat;
-	char *argp[] = {"sh", "-c", NULL, NULL};
-
-	if (!command)		/* just checking... */
-		return(1);
-
-	argp[2] = (char *)command;
-
-	sigemptyset(&mask);
-	sigaddset(&mask, SIGCHLD);
-	sigprocmask(SIG_BLOCK, &mask, &omask);
-	switch (cpid = vfork()) {
-	case -1:			/* error */
-		sigprocmask(SIG_SETMASK, &omask, NULL);
-		return(-1);
-	case 0:				/* child */
-		sigprocmask(SIG_SETMASK, &omask, NULL);
-		execve(_PATH_BSHELL, argp, environ);
-		_exit(127);
-	}
-
-	sigaction(SIGINT, NULL, &intsave);
-	sigaction(SIGQUIT, NULL, &quitsave);
-	do {
-		pid = waitpid(cpid, &pstat, 0);
-	} while (pid == -1 && errno == EINTR);
-	sigprocmask(SIG_SETMASK, &omask, NULL);
-	sigaction(SIGINT, &intsave, NULL);
-	sigaction(SIGQUIT, &quitsave, NULL);
-	return (pid == -1 ? -1 : pstat);
-}
-DEF_STRONG(system);
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/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/linker/arch/x86/begin.c b/linker/arch/x86/begin.S
similarity index 72%
rename from linker/arch/x86/begin.c
rename to linker/arch/x86/begin.S
index 331b79e..3812646 100644
--- a/linker/arch/x86/begin.c
+++ b/linker/arch/x86/begin.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 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,28 +26,18 @@
  * SUCH DAMAGE.
  */
 
-#include <stdint.h>
-#include <sys/cdefs.h>
+#include <private/bionic_asm.h>
 
-extern unsigned __linker_init(void* raw_args);
-
-__LIBC_HIDDEN__ void _start() {
+ENTRY(_start)
   // Force unwinds to end in this function.
-  asm volatile(".cfi_undefined \%eip");
+  .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);
+  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 */
-  /* 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 */
-}
+  jmp *%eax
+END(_start)
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..dd700fe 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(),
@@ -1108,10 +1105,14 @@
 const char* fix_dt_needed(const char* dt_needed, const char* sopath __unused) {
 #if !defined(__LP64__)
   // Work around incorrect DT_NEEDED entries for old apps: http://b/21364029
-  if (get_application_target_sdk_version() < __ANDROID_API_M__) {
+  int app_target_api_level = get_application_target_sdk_version();
+  if (app_target_api_level < __ANDROID_API_M__) {
     const char* bname = basename(dt_needed);
     if (bname != dt_needed) {
-      DL_WARN("library \"%s\" has invalid DT_NEEDED entry \"%s\"", sopath, dt_needed);
+      DL_WARN_documented_change(__ANDROID_API_M__,
+                                "invalid-dt_needed-entries-enforced-for-api-level-23",
+                                "library \"%s\" has invalid DT_NEEDED entry \"%s\"",
+                                sopath, dt_needed, app_target_api_level);
       add_dlwarning(sopath, "invalid DT_NEEDED entry",  dt_needed);
     }
 
@@ -1249,10 +1250,11 @@
         const soinfo* needed_or_dlopened_by = task->get_needed_by();
         const char* sopath = needed_or_dlopened_by == nullptr ? "(unknown)" :
                                                       needed_or_dlopened_by->get_realpath();
-        DL_WARN("library \"%s\" (\"%s\") needed or dlopened by \"%s\" is not accessible for the namespace \"%s\""
-                " - the access is temporarily granted as a workaround for http://b/26394120, note that the access"
-                " will be removed in future releases of Android.",
-                name, realpath.c_str(), sopath, ns->get_name());
+        DL_WARN_documented_change(__ANDROID_API_N__,
+                                  "private-api-enforced-for-api-level-24",
+                                  "library \"%s\" (\"%s\") needed or dlopened by \"%s\" "
+                                  "is not accessible by namespace \"%s\"",
+                                  name, realpath.c_str(), sopath, ns->get_name());
         add_dlwarning(sopath, "unauthorized access to",  name);
       }
     } else {
@@ -3366,7 +3368,9 @@
         set_dt_flags_1(d->d_un.d_val);
 
         if ((d->d_un.d_val & ~SUPPORTED_DT_FLAGS_1) != 0) {
-          DL_WARN("\"%s\" has unsupported flags DT_FLAGS_1=%p", get_realpath(), reinterpret_cast<void*>(d->d_un.d_val));
+          DL_WARN("Warning: \"%s\" has unsupported flags DT_FLAGS_1=%p "
+                  "(ignoring unsupported flags)",
+                  get_realpath(), reinterpret_cast<void*>(d->d_un.d_val));
         }
         break;
 #if defined(__mips__)
@@ -3445,7 +3449,7 @@
           } else {
             tag_name = "unknown";
           }
-          DL_WARN("\"%s\" unused DT entry: %s (type %p arg %p)",
+          DL_WARN("Warning: \"%s\" unused DT entry: %s (type %p arg %p) (ignoring)",
                   get_realpath(),
                   tag_name,
                   reinterpret_cast<void*>(d->d_tag),
@@ -3498,16 +3502,20 @@
   // Before M release linker was using basename in place of soname.
   // In the case when dt_soname is absent some apps stop working
   // because they can't find dt_needed library by soname.
-  // This workaround should keep them working. (applies only
-  // for apps targeting sdk version < M). Make an exception for
-  // the main executable and linker; they do not need to have dt_soname
+  // This workaround should keep them working. (Applies only
+  // for apps targeting sdk version < M.) Make an exception for
+  // the main executable and linker; they do not need to have dt_soname.
+  // TODO: >= O the linker doesn't need this workaround.
   if (soname_ == nullptr &&
       this != solist_get_somain() &&
       (flags_ & FLAG_LINKER) == 0 &&
       get_application_target_sdk_version() < __ANDROID_API_M__) {
     soname_ = basename(realpath_.c_str());
-    DL_WARN("%s: is missing DT_SONAME will use basename as a replacement: \"%s\"",
-        get_realpath(), soname_);
+    DL_WARN_documented_change(__ANDROID_API_M__,
+                              "missing-soname-enforced-for-api-level-23",
+                              "\"%s\" has no DT_SONAME (will use %s instead)",
+                              get_realpath(), soname_);
+
     // Don't call add_dlwarning because a missing DT_SONAME isn't important enough to show in the UI
   }
   return true;
@@ -3538,7 +3546,8 @@
 #if !defined(__LP64__)
   if (has_text_relocations) {
     // Fail if app is targeting M or above.
-    if (get_application_target_sdk_version() >= __ANDROID_API_M__) {
+    int app_target_api_level = get_application_target_sdk_version();
+    if (app_target_api_level >= __ANDROID_API_M__) {
       DL_ERR_AND_LOG("\"%s\" has text relocations (https://android.googlesource.com/platform/"
                      "bionic/+/master/android-changes-for-ndk-developers.md#Text-Relocations-"
                      "Enforced-for-API-level-23)", get_realpath());
@@ -3546,13 +3555,13 @@
     }
     // Make segments writable to allow text relocations to work properly. We will later call
     // phdr_table_protect_segments() after all of them are applied.
-    DL_WARN("\"%s\" has text relocations (https://android.googlesource.com/platform/"
-            "bionic/+/master/android-changes-for-ndk-developers.md#Text-Relocations-Enforced-"
-            "for-API-level-23)", get_realpath());
+    DL_WARN_documented_change(__ANDROID_API_M__,
+                              "Text-Relocations-Enforced-for-API-level-23",
+                              "\"%s\" has text relocations",
+                              get_realpath());
     add_dlwarning(get_realpath(), "text relocations");
     if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
-      DL_ERR("can't unprotect loadable segments for \"%s\": %s",
-             get_realpath(), strerror(errno));
+      DL_ERR("can't unprotect loadable segments for \"%s\": %s", get_realpath(), strerror(errno));
       return false;
     }
   }
@@ -3742,7 +3751,7 @@
                                   &config,
                                   &error_msg)) {
     if (!error_msg.empty()) {
-      DL_WARN("error reading config file \"%s\" for \"%s\" (will use default configuration): %s",
+      DL_WARN("Warning: couldn't read \"%s\" for \"%s\" (using default configuration instead): %s",
               config_file,
               executable_path,
               error_msg.c_str());
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.cpp b/linker/linker_config.cpp
index 83c2f36..c00b734 100644
--- a/linker/linker_config.cpp
+++ b/linker/linker_config.cpp
@@ -194,14 +194,14 @@
 
   std::string section_name;
 
-  while(true) {
+  while (true) {
     std::string name;
     std::string value;
     std::string error;
 
     int result = cp.next_token(&name, &value, &error);
     if (result == ConfigParser::kError) {
-      DL_WARN("error parsing %s:%zd: %s (ignoring this line)",
+      DL_WARN("%s:%zd: warning: couldn't parse %s (ignoring this line)",
               ld_config_file_path,
               cp.lineno(),
               error.c_str());
@@ -214,7 +214,7 @@
 
     if (result == ConfigParser::kPropertyAssign) {
       if (!android::base::StartsWith(name, "dir.")) {
-        DL_WARN("error parsing %s:%zd: unexpected property name \"%s\", "
+        DL_WARN("%s:%zd: warning: unexpected property name \"%s\", "
                 "expected format dir.<section_name> (ignoring this line)",
                 ld_config_file_path,
                 cp.lineno(),
@@ -228,7 +228,7 @@
       }
 
       if (value.empty()) {
-        DL_WARN("error parsing %s:%zd: property value is empty (ignoring this line)",
+        DL_WARN("%s:%zd: warning: property value is empty (ignoring this line)",
                 ld_config_file_path,
                 cp.lineno());
         continue;
@@ -275,7 +275,7 @@
 
     if (result == ConfigParser::kPropertyAssign) {
       if (properties->find(name) != properties->end()) {
-        DL_WARN("%s:%zd: warning: property \"%s\" redefinition",
+        DL_WARN("%s:%zd: warning: redefining property \"%s\" (overriding previous value)",
                 ld_config_file_path,
                 cp.lineno(),
                 name.c_str());
@@ -284,7 +284,7 @@
       (*properties)[name] = PropertyValue(std::move(value), cp.lineno());
     } else if (result == ConfigParser::kPropertyAppend) {
       if (properties->find(name) == properties->end()) {
-        DL_WARN("%s:%zd: warning: appending to property \"%s\" which isn't defined",
+        DL_WARN("%s:%zd: warning: appending to undefined property \"%s\" (treating as assignment)",
                 ld_config_file_path,
                 cp.lineno(),
                 name.c_str());
@@ -299,7 +299,7 @@
           value = ":" + value;
           (*properties)[name].append_value(std::move(value));
         } else {
-          DL_WARN("%s:%zd: warning: += isn't allowed to property \"%s\". Ignoring.",
+          DL_WARN("%s:%zd: warning: += isn't allowed for property \"%s\" (ignoring)",
                   ld_config_file_path,
                   cp.lineno(),
                   name.c_str());
@@ -308,7 +308,7 @@
     }
 
     if (result == ConfigParser::kError) {
-      DL_WARN("error parsing %s:%zd: %s (ignoring this line)",
+      DL_WARN("%s:%zd: warning: couldn't parse %s (ignoring this line)",
               ld_config_file_path,
               cp.lineno(),
               error.c_str());
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.cpp b/linker/linker_globals.cpp
index 155ebf4..bcc2a1e 100644
--- a/linker/linker_globals.cpp
+++ b/linker/linker_globals.cpp
@@ -26,10 +26,12 @@
  * SUCH DAMAGE.
  */
 
-
+#include "linker.h"
 #include "linker_globals.h"
 #include "linker_namespaces.h"
 
+#include "android-base/stringprintf.h"
+
 int g_argc = 0;
 char** g_argv = nullptr;
 char** g_envp = nullptr;
@@ -48,3 +50,18 @@
   return sizeof(__linker_dl_err_buf);
 }
 
+void DL_WARN_documented_change(int api_level, const char* doc_link, const char* fmt, ...) {
+  std::string result{"Warning: "};
+
+  va_list ap;
+  va_start(ap, fmt);
+  android::base::StringAppendV(&result, fmt, ap);
+  va_end(ap);
+
+  android::base::StringAppendF(&result,
+                               " and will not work when the app moves to API level %d or later "
+                               "(https://android.googlesource.com/platform/bionic/+/master/%s) "
+                               "(allowing for now because this app's target API level is still %d)",
+                               api_level, doc_link, get_application_target_sdk_version());
+  DL_WARN("%s", result.c_str());
+}
diff --git a/linker/linker_globals.h b/linker/linker_globals.h
index 11ccbd5..32aa09d 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>
@@ -50,6 +49,8 @@
       async_safe_format_fd(2, "\n"); \
     } while (false)
 
+void DL_WARN_documented_change(int api_level, const char* doc_link, const char* fmt, ...);
+
 #define DL_ERR_AND_LOG(fmt, x...) \
   do { \
     DL_ERR(fmt, x); \
@@ -86,5 +87,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.cpp b/linker/linker_namespaces.cpp
index 9fdf0b5..fd72cdc 100644
--- a/linker/linker_namespaces.cpp
+++ b/linker/linker_namespaces.cpp
@@ -64,7 +64,8 @@
     // This is workaround for apps hacking into soinfo list.
     // and inserting their own entries into it. (http://b/37191433)
     if (!si->has_min_version(3)) {
-      DL_WARN("invalid soinfo version for \"%s\"", si->get_soname());
+      DL_WARN("Warning: invalid soinfo version for \"%s\" (assuming inaccessible)",
+              si->get_soname());
       return false;
     }
 
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.cpp b/linker/linker_phdr.cpp
index a9873c4..a5eab44 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -268,8 +268,10 @@
                      name_.c_str(), header_.e_shentsize, sizeof(ElfW(Shdr)));
       return false;
     }
-    DL_WARN("\"%s\" has unsupported e_shentsize: 0x%x (expected 0x%zx)",
-            name_.c_str(), header_.e_shentsize, sizeof(ElfW(Shdr)));
+    DL_WARN_documented_change(__ANDROID_API_O__,
+                              "invalid-elf-header_section-headers-enforced-for-api-level-26",
+                              "\"%s\" has unsupported e_shentsize 0x%x (expected 0x%zx)",
+                              name_.c_str(), header_.e_shentsize, sizeof(ElfW(Shdr)));
     add_dlwarning(name_.c_str(), "has invalid ELF header");
   }
 
@@ -280,7 +282,9 @@
       return false;
     }
 
-    DL_WARN("\"%s\" has invalid e_shstrndx", name_.c_str());
+    DL_WARN_documented_change(__ANDROID_API_O__,
+                              "invalid-elf-header_section-headers-enforced-for-api-level-26",
+                              "\"%s\" has invalid e_shstrndx", name_.c_str());
     add_dlwarning(name_.c_str(), "has invalid ELF header");
   }
 
@@ -395,11 +399,13 @@
                      pt_dynamic_offset);
       return false;
     }
-    DL_WARN("\"%s\" .dynamic section has invalid offset: 0x%zx, "
-            "expected to match PT_DYNAMIC offset: 0x%zx",
-            name_.c_str(),
-            static_cast<size_t>(dynamic_shdr->sh_offset),
-            pt_dynamic_offset);
+    DL_WARN_documented_change(__ANDROID_API_O__,
+                              "invalid-elf-header_section-headers-enforced-for-api-level-26",
+                              "\"%s\" .dynamic section has invalid offset: 0x%zx "
+                              "(expected to match PT_DYNAMIC offset 0x%zx)",
+                              name_.c_str(),
+                              static_cast<size_t>(dynamic_shdr->sh_offset),
+                              pt_dynamic_offset);
     add_dlwarning(name_.c_str(), "invalid .dynamic section");
   }
 
@@ -412,11 +418,13 @@
                      pt_dynamic_filesz);
       return false;
     }
-    DL_WARN("\"%s\" .dynamic section has invalid size: 0x%zx, "
-            "expected to match PT_DYNAMIC filesz: 0x%zx",
-            name_.c_str(),
-            static_cast<size_t>(dynamic_shdr->sh_size),
-            pt_dynamic_filesz);
+    DL_WARN_documented_change(__ANDROID_API_O__,
+                              "invalid-elf-header_section-headers-enforced-for-api-level-26",
+                              "\"%s\" .dynamic section has invalid size: 0x%zx "
+                              "(expected to match PT_DYNAMIC filesz 0x%zx)",
+                              name_.c_str(),
+                              static_cast<size_t>(dynamic_shdr->sh_size),
+                              pt_dynamic_filesz);
     add_dlwarning(name_.c_str(), "invalid .dynamic section");
   }
 
@@ -651,10 +659,13 @@
       if ((prot & (PROT_EXEC | PROT_WRITE)) == (PROT_EXEC | PROT_WRITE)) {
         // W + E PT_LOAD segments are not allowed in O.
         if (get_application_target_sdk_version() >= __ANDROID_API_O__) {
-          DL_ERR_AND_LOG("\"%s\": W + E load segments are not allowed", name_.c_str());
+          DL_ERR_AND_LOG("\"%s\": W+E load segments are not allowed", name_.c_str());
           return false;
         }
-        DL_WARN("\"%s\": W + E load segments are not allowed", name_.c_str());
+        DL_WARN_documented_change(__ANDROID_API_O__,
+                                  "writable-and-executable-segments-enforced-for-api-level-26",
+                                  "\"%s\" has load segments that are both writable and executable",
+                                  name_.c_str());
         add_dlwarning(name_.c_str(), "W+E load segments");
       }
 
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.cpp b/linker/linker_soinfo.cpp
index 54bfcf0..731e8f5 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -152,7 +152,7 @@
       ELF_ST_BIND(s->st_info) == STB_WEAK) {
     return s->st_shndx != SHN_UNDEF;
   } else if (ELF_ST_BIND(s->st_info) != STB_LOCAL) {
-    DL_WARN("unexpected ST_BIND value: %d for \"%s\" in \"%s\"",
+    DL_WARN("Warning: unexpected ST_BIND value: %d for \"%s\" in \"%s\" (ignoring)",
             ELF_ST_BIND(s->st_info), si->get_string(s->st_name), si->get_realpath());
   }
 
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.cpp b/linker/linker_utils.cpp
index 5bf88e7..661e7cb 100644
--- a/linker/linker_utils.cpp
+++ b/linker/linker_utils.cpp
@@ -209,31 +209,28 @@
     const char* original_path = path.c_str();
     if (realpath(original_path, resolved_path) != nullptr) {
       struct stat s;
-      if (stat(resolved_path, &s) == 0) {
-        if (S_ISDIR(s.st_mode)) {
-          resolved_paths->push_back(resolved_path);
-        } else {
-          DL_WARN("Warning: \"%s\" is not a directory (excluding from path)", resolved_path);
-          continue;
-        }
-      } else {
-        DL_WARN("Warning: cannot stat file \"%s\": %s", resolved_path, strerror(errno));
+      if (stat(resolved_path, &s) == -1) {
+        DL_WARN("Warning: cannot stat file \"%s\": %s (ignoring)", resolved_path, strerror(errno));
         continue;
       }
+      if (!S_ISDIR(s.st_mode)) {
+        DL_WARN("Warning: \"%s\" is not a directory (ignoring)", resolved_path);
+        continue;
+      }
+      resolved_paths->push_back(resolved_path);
     } else {
+      std::string normalized_path;
+      if (!normalize_path(original_path, &normalized_path)) {
+        DL_WARN("Warning: unable to normalize \"%s\" (ignoring)", original_path);
+        continue;
+      }
+
       std::string zip_path;
       std::string entry_path;
-
-      std::string normalized_path;
-
-      if (!normalize_path(original_path, &normalized_path)) {
-        DL_WARN("Warning: unable to normalize \"%s\"", original_path);
-        continue;
-      }
-
       if (parse_zip_path(normalized_path.c_str(), &zip_path, &entry_path)) {
         if (realpath(zip_path.c_str(), resolved_path) == nullptr) {
-          DL_WARN("Warning: unable to resolve \"%s\": %s", zip_path.c_str(), strerror(errno));
+          DL_WARN("Warning: unable to resolve \"%s\": %s (ignoring)",
+                  zip_path.c_str(), strerror(errno));
           continue;
         }
 
@@ -242,4 +239,3 @@
     }
   }
 }
-
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 443fe8e..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",
@@ -245,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,
@@ -257,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,
@@ -312,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",
@@ -347,7 +358,7 @@
                 "libLLVMCore",
                 "libLLVMSupport",
             ],
-        }
+        },
     },
 }
 
@@ -439,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
deleted file mode 100644
index 85c41a8..0000000
--- a/tests/ScopedSignalHandler.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _BIONIC_TESTS_SCOPED_SIGNAL_HANDLER_H
-#define _BIONIC_TESTS_SCOPED_SIGNAL_HANDLER_H
-
-#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 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)
-      : signal_number_(signal_number) {
-    memset(&action_, 0, sizeof(action_));
-    action_.sa_flags = sa_flags;
-    action_.sa_handler = handler;
-    sigaction(signal_number_, &action_, &old_action_);
-  }
-
-  ScopedSignalHandler(int signal_number, void (*action)(int, siginfo_t*, void*),
-                      int sa_flags = SA_SIGINFO)
-      : signal_number_(signal_number) {
-    memset(&action_, 0, sizeof(action_));
-    action_.sa_flags = sa_flags;
-    action_.sa_sigaction = action;
-    sigaction(signal_number_, &action_, &old_action_);
-  }
-
-  ScopedSignalHandler(int signal_number) : signal_number_(signal_number) {
-    sigaction(signal_number, nullptr, &old_action_);
-  }
-
-  ~ScopedSignalHandler() {
-    sigaction(signal_number_, &old_action_, NULL);
-  }
-
- private:
-  struct sigaction action_;
-  struct sigaction old_action_;
-  const int signal_number_;
-};
-
-class SignalMaskRestorer {
- public:
-  SignalMaskRestorer() {
-    sigprocmask64(SIG_SETMASK, nullptr, &old_mask_);
-  }
-
-  ~SignalMaskRestorer() {
-    sigprocmask64(SIG_SETMASK, &old_mask_, nullptr);
-  }
-
- private:
-  sigset64_t old_mask_;
-};
-
-#endif // _BIONIC_TESTS_SCOPED_SIGNAL_HANDLER_H
diff --git a/tests/SignalUtils.h b/tests/SignalUtils.h
new file mode 100644
index 0000000..ece28ba
--- /dev/null
+++ b/tests/SignalUtils.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma once
+
+#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
+
+#include "private/ScopedSignalHandler.h"
+
+class SignalMaskRestorer {
+ public:
+  SignalMaskRestorer() {
+    sigprocmask64(SIG_SETMASK, nullptr, &old_mask_);
+  }
+
+  ~SignalMaskRestorer() {
+    sigprocmask64(SIG_SETMASK, &old_mask_, nullptr);
+  }
+
+ private:
+  sigset64_t old_mask_;
+};
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 000d1f7..46f5097 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();
@@ -1498,7 +1503,7 @@
                               "/libtest_invalid-rw_load_segment.so";
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
-  std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\": W + E load segments are not allowed";
+  std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\": W+E load segments are not allowed";
   ASSERT_STREQ(expected_dlerror.c_str(), dlerror());
 }
 
diff --git a/tests/fenv_test.cpp b/tests/fenv_test.cpp
index 9fc7d96..d27808f 100644
--- a/tests/fenv_test.cpp
+++ b/tests/fenv_test.cpp
@@ -16,7 +16,6 @@
 
 #include <gtest/gtest.h>
 
-#include "ScopedSignalHandler.h"
 #include "utils.h"
 
 #include <fenv.h>
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 f288612..523ed63 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -40,7 +40,7 @@
 #include "private/bionic_constants.h"
 #include "private/bionic_macros.h"
 #include "BionicDeathTest.h"
-#include "ScopedSignalHandler.h"
+#include "SignalUtils.h"
 #include "utils.h"
 
 TEST(pthread, pthread_key_create) {
@@ -914,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;
@@ -950,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;
@@ -1010,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,
@@ -1031,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,
@@ -1718,6 +1718,7 @@
 
   void destroy() {
     ASSERT_EQ(0, pthread_mutex_destroy(&lock));
+    ASSERT_EQ(EBUSY, pthread_mutex_destroy(&lock));
   }
 
   DISALLOW_COPY_AND_ASSIGN(PthreadMutex);
@@ -1776,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);
@@ -1801,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;
@@ -1949,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);
@@ -2005,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/semaphore_test.cpp b/tests/semaphore_test.cpp
index 24a2dbe..b216ec9 100644
--- a/tests/semaphore_test.cpp
+++ b/tests/semaphore_test.cpp
@@ -24,7 +24,7 @@
 #include <unistd.h>
 
 #include "private/bionic_constants.h"
-#include "ScopedSignalHandler.h"
+#include "SignalUtils.h"
 
 TEST(semaphore, sem_init) {
   sem_t s;
diff --git a/tests/setjmp_test.cpp b/tests/setjmp_test.cpp
index 4f5e60c..a49e910 100644
--- a/tests/setjmp_test.cpp
+++ b/tests/setjmp_test.cpp
@@ -19,7 +19,7 @@
 #include <setjmp.h>
 #include <stdlib.h>
 
-#include "ScopedSignalHandler.h"
+#include "SignalUtils.h"
 
 TEST(setjmp, setjmp_smoke) {
   int value;
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index ebc079e..53c91a2 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -24,7 +24,7 @@
 
 #include <gtest/gtest.h>
 
-#include "ScopedSignalHandler.h"
+#include "SignalUtils.h"
 
 static int SIGNAL_MIN() {
   return 1; // Signals start at 1 (SIGHUP), not 0.
@@ -269,55 +269,280 @@
   ASSERT_EQ(1, g_sigsuspend64_signal_handler_call_count);
 }
 
-static void EmptySignalHandler(int) {}
-static void EmptySignalAction(int, siginfo_t*, void*) {}
-
-TEST(signal, sigaction) {
+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) {
@@ -495,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;
 
diff --git a/tests/spawn_test.cpp b/tests/spawn_test.cpp
index 84df16d..86175f9 100644
--- a/tests/spawn_test.cpp
+++ b/tests/spawn_test.cpp
@@ -20,7 +20,7 @@
 #include <fcntl.h>
 #include <gtest/gtest.h>
 
-#include "ScopedSignalHandler.h"
+#include "SignalUtils.h"
 #include "utils.h"
 
 #include <android-base/file.h>
diff --git a/tests/stack_unwinding_test.cpp b/tests/stack_unwinding_test.cpp
index bb58ae4..0ff6f30 100644
--- a/tests/stack_unwinding_test.cpp
+++ b/tests/stack_unwinding_test.cpp
@@ -29,7 +29,7 @@
 #include <unistd.h>
 #include <unwind.h>
 
-#include "ScopedSignalHandler.h"
+#include "SignalUtils.h"
 
 #define noinline __attribute__((__noinline__))
 #define __unused __attribute__((__unused__))
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/stdio_test.cpp b/tests/stdio_test.cpp
index c1a51a8..33514d4 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -335,12 +335,10 @@
 
 TEST(STDIO_TEST, snprintf_n) {
 #if defined(__BIONIC__)
-  // http://b/14492135
+  // http://b/14492135 and http://b/31832608.
   char buf[32];
   int i = 1234;
-  EXPECT_EQ(5, snprintf(buf, sizeof(buf), "a %n b", &i));
-  EXPECT_EQ(1234, i);
-  EXPECT_STREQ("a n b", buf);
+  EXPECT_DEATH(snprintf(buf, sizeof(buf), "a %n b", &i), "%n not allowed on Android");
 #else
   GTEST_LOG_(INFO) << "This test does nothing on glibc.\n";
 #endif
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_signalfd_test.cpp b/tests/sys_signalfd_test.cpp
index 67a72e0..179fcf9 100644
--- a/tests/sys_signalfd_test.cpp
+++ b/tests/sys_signalfd_test.cpp
@@ -36,7 +36,7 @@
 
 #include <thread>
 
-#include "ScopedSignalHandler.h"
+#include "SignalUtils.h"
 
 static void TestSignalFd(int fd, int signal) {
   ASSERT_NE(-1, fd) << strerror(errno);
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..3196f34 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -26,7 +26,7 @@
 #include <unistd.h>
 #include <atomic>
 
-#include "ScopedSignalHandler.h"
+#include "SignalUtils.h"
 #include "utils.h"
 
 #include "private/bionic_constants.h"
@@ -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;
@@ -854,3 +871,54 @@
   ASSERT_EQ(buf, ctime_r(&t, buf));
   ASSERT_STREQ("Thu Jan  1 00:00:00 1970\n", buf);
 }
+
+// https://issuetracker.google.com/37128336
+TEST(time, strftime_strptime_s) {
+  char buf[32];
+  const struct tm tm0 = { .tm_year = 1982-1900, .tm_mon = 0, .tm_mday = 1 };
+
+  setenv("TZ", "America/Los_Angeles", 1);
+  strftime(buf, sizeof(buf), "<%s>", &tm0);
+  EXPECT_STREQ("<378720000>", buf);
+
+  setenv("TZ", "UTC", 1);
+  strftime(buf, sizeof(buf), "<%s>", &tm0);
+  EXPECT_STREQ("<378691200>", buf);
+
+  struct tm tm;
+
+  setenv("TZ", "America/Los_Angeles", 1);
+  tzset();
+  memset(&tm, 0xff, sizeof(tm));
+  char* p = strptime("378720000x", "%s", &tm);
+  ASSERT_EQ('x', *p);
+  EXPECT_EQ(0, tm.tm_sec);
+  EXPECT_EQ(0, tm.tm_min);
+  EXPECT_EQ(0, tm.tm_hour);
+  EXPECT_EQ(1, tm.tm_mday);
+  EXPECT_EQ(0, tm.tm_mon);
+  EXPECT_EQ(82, tm.tm_year);
+  EXPECT_EQ(5, tm.tm_wday);
+  EXPECT_EQ(0, tm.tm_yday);
+  EXPECT_EQ(0, tm.tm_isdst);
+
+  setenv("TZ", "UTC", 1);
+  tzset();
+  memset(&tm, 0xff, sizeof(tm));
+  p = strptime("378691200x", "%s", &tm);
+  ASSERT_EQ('x', *p);
+  EXPECT_EQ(0, tm.tm_sec);
+  EXPECT_EQ(0, tm.tm_min);
+  EXPECT_EQ(0, tm.tm_hour);
+  EXPECT_EQ(1, tm.tm_mday);
+  EXPECT_EQ(0, tm.tm_mon);
+  EXPECT_EQ(82, tm.tm_year);
+  EXPECT_EQ(5, tm.tm_wday);
+  EXPECT_EQ(0, tm.tm_yday);
+  EXPECT_EQ(0, tm.tm_isdst);
+}
+
+TEST(time, strptime_s_nothing) {
+  struct tm tm;
+  ASSERT_EQ(nullptr, strptime("x", "%s", &tm));
+}
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 912ea0c..db4859b 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -17,7 +17,7 @@
 #include <gtest/gtest.h>
 
 #include "BionicDeathTest.h"
-#include "ScopedSignalHandler.h"
+#include "SignalUtils.h"
 #include "TemporaryFile.h"
 #include "utils.h"
 
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);