Merge "Replace android_open_proxy with dns_open_proxy"
diff --git a/benchmarks/property_benchmark.cpp b/benchmarks/property_benchmark.cpp
index 9251a05..77814bf 100644
--- a/benchmarks/property_benchmark.cpp
+++ b/benchmarks/property_benchmark.cpp
@@ -21,7 +21,7 @@
 
 #include <string>
 
-#include <android-base/test_utils.h>
+#include <android-base/file.h>
 
 using namespace std::literals;
 
diff --git a/benchmarks/stdio_benchmark.cpp b/benchmarks/stdio_benchmark.cpp
index 21d9dc0..037bbd9 100644
--- a/benchmarks/stdio_benchmark.cpp
+++ b/benchmarks/stdio_benchmark.cpp
@@ -20,7 +20,7 @@
 #include <stdio_ext.h>
 #include <stdlib.h>
 
-#include <android-base/test_utils.h>
+#include <android-base/file.h>
 #include <benchmark/benchmark.h>
 #include "util.h"
 
diff --git a/benchmarks/tests/interface_test.cpp b/benchmarks/tests/interface_test.cpp
index ff4b255..301c294 100644
--- a/benchmarks/tests/interface_test.cpp
+++ b/benchmarks/tests/interface_test.cpp
@@ -63,7 +63,7 @@
 
 void SystemTests::SanitizeOutput() {
   // Cut off anything after the arguments, since that varies with time.
-  sanitized_output_ = std::regex_replace(raw_output_, std::regex(".+(BM_\\S+) +.+"), "$1");
+  sanitized_output_ = std::regex_replace(raw_output_, std::regex(".*(BM_\\S+)\\s+.+"), "$1");
 
   // Remove everything before the header.
   sanitized_output_.erase(0, sanitized_output_.find("------------------------------------------------"));
@@ -165,7 +165,8 @@
     "          [--benchmark_filter=<regex>]\n"
     "          [--benchmark_min_time=<min_time>]\n"
     "          [--benchmark_repetitions=<num_repetitions>]\n"
-    "          [--benchmark_report_aggregates_only={true|false}\n"
+    "          [--benchmark_report_aggregates_only={true|false}]\n"
+    "          [--benchmark_display_aggregates_only={true|false}]\n"
     "          [--benchmark_format=<console|json|csv>]\n"
     "          [--benchmark_out=<filename>]\n"
     "          [--benchmark_out_format=<json|console|csv>]\n"
diff --git a/docs/elf-tls.md b/docs/elf-tls.md
new file mode 100644
index 0000000..4a62793
--- /dev/null
+++ b/docs/elf-tls.md
@@ -0,0 +1,882 @@
+# Android ELF TLS (Draft)
+
+Internal links:
+ * [go/android-elf-tls](http://go/android-elf-tls)
+ * [One-pager](https://docs.google.com/document/d/1leyPTnwSs24P2LGiqnU6HetnN5YnDlZkihigi6qdf_M)
+ * Tracking bugs: http://b/110100012, http://b/78026329
+
+[TOC]
+
+# Overview
+
+ELF TLS is a system for automatically allocating thread-local variables with cooperation among the
+compiler, linker, dynamic loader, and libc.
+
+Thread-local variables are declared in C and C++ with a specifier, e.g.:
+
+```cpp
+thread_local int tls_var;
+```
+
+At run-time, TLS variables are allocated on a module-by-module basis, where a module is a shared
+object or executable. At program startup, TLS for all initially-loaded modules comprises the "Static
+TLS Block". TLS variables within the Static TLS Block exist at fixed offsets from an
+architecture-specific thread pointer (TP) and can be accessed very efficiently -- typically just a
+few instructions. TLS variables belonging to dlopen'ed shared objects, on the other hand, may be
+allocated lazily, and accessing them typically requires a function call.
+
+# Thread-Specific Memory Layout
+
+Ulrich Drepper's ELF TLS document specifies two ways of organizing memory pointed at by the
+architecture-specific thread-pointer ([`__get_tls()`] in Bionic):
+
+![TLS Variant 1 Layout](img/tls-variant1.png)
+
+![TLS Variant 2 Layout](img/tls-variant2.png)
+
+Variant 1 places the static TLS block after the TP, whereas variant 2 places it before the TP.
+According to Drepper, variant 2 was motivated by backwards compatibility, and variant 1 was designed
+for Itanium. The choice has effects on the toolchain, loader, and libc. In particular, when linking
+an executable, the linker needs to know where an executable's TLS segment is relative to the TP so
+it can correctly relocate TLS accesses. Both variants are incompatible with Bionic's current
+thread-specific data layout, but variant 1 is more problematic than variant 2.
+
+Each thread has a "Dynamic Thread Vector" (DTV) with a pointer to each module's TLS block (or NULL
+if it hasn't been allocated yet). If the executable has a TLS segment, then it will always be module
+1, and its storage will always be immediately after (or before) the TP. In variant 1, the TP is
+expected to point immediately at the DTV pointer, whereas in variant 2, the DTV pointer's offset
+from TP is implementation-defined.
+
+The DTV's "generation" field is used to lazily update/reallocate the DTV when new modules are loaded
+or unloaded.
+
+[`__get_tls()`]: https://android.googlesource.com/platform/bionic/+/7245c082658182c15d2a423fe770388fec707cbc/libc/private/__get_tls.h
+
+# Access Models
+
+When a C/C++ file references a TLS variable, the toolchain generates instructions to find its
+address using a TLS "access model". The access models trade generality against efficiency. The four
+models are:
+
+ * GD: General Dynamic (aka Global Dynamic)
+ * LD: Local Dynamic
+ * IE: Initial Exec
+ * LE: Local Exec
+
+A TLS variable may be in a different module than the reference.
+
+## General Dynamic (or Global Dynamic) (GD)
+
+A GD access can refer to a TLS variable anywhere. To access a variable `tls_var` using the
+"traditional" non-TLSDESC design described in Drepper's TLS document, the toolchain compiler emits a
+call to a `__tls_get_addr` function provided by libc.
+
+For example, if we have this C code in a shared object:
+
+```cpp
+extern thread_local char tls_var;
+char* get_tls_var() {
+  return &tls_var;
+}
+```
+
+The toolchain generates code like this:
+
+```cpp
+struct TlsIndex {
+  long module; // starts counting at 1
+  long offset;
+};
+
+char* get_tls_var() {
+  static TlsIndex tls_var_idx = { // allocated in the .got
+    R_TLS_DTPMOD(tls_var), // dynamic TP module ID
+    R_TLS_DTPOFF(tls_var), // dynamic TP offset
+  };
+  return __tls_get_addr(&tls_var_idx);
+}
+```
+
+`R_TLS_DTPMOD` is a dynamic relocation to the index of the module containing `tls_var`, and
+`R_TLS_DTPOFF` is a dynamic relocation to the offset of `tls_var` within its module's `PT_TLS`
+segment.
+
+`__tls_get_addr` looks up `TlsIndex::module`'s entry in the DTV and adds `TlsIndex::offset` to the
+module's TLS block. Before it can do this, it ensures that the module's TLS block is allocated. A
+simple approach is to allocate memory lazily:
+
+1. If the current thread's DTV generation count is less than the current global TLS generation, then
+   `__tls_get_addr` may reallocate the DTV or free blocks for unloaded modules.
+
+2. If the DTV's entry for the given module is `NULL`, then `__tls_get_addr` allocates the module's
+   memory.
+
+If an allocation fails, `__tls_get_addr` calls `abort` (like emutls).
+
+musl, on the other, preallocates TLS memory in `pthread_create` and in `dlopen`, and each can report
+out-of-memory.
+
+## Local Dynamic (LD)
+
+LD is a specialization of GD that's useful when a function has references to two or more TLS
+variables that are both part of the same module as the reference. Instead of a call to
+`__tls_get_addr` for each variable, the compiler calls `__tls_get_addr` once to get the current
+module's TLS block, then adds each variable's DTPOFF to the result.
+
+For example, suppose we have this C code:
+
+```cpp
+static thread_local int x;
+static thread_local int y;
+int sum() {
+  return x + y;
+}
+```
+
+The toolchain generates code like this:
+
+```cpp
+int sum() {
+  static TlsIndex tls_module_idx = { // allocated in the .got
+    // a dynamic relocation against symbol 0 => current module ID
+    R_TLS_DTPMOD(NULL),
+    0,
+  };
+  char* base = __tls_get_addr(&tls_module_idx);
+  // These R_TLS_DTPOFF() relocations are resolved at link-time.
+  int* px = base + R_TLS_DTPOFF(x);
+  int* py = base + R_TLS_DTPOFF(y);
+  return *px + *py;
+}
+```
+
+(XXX: LD might be important for C++ `thread_local` variables -- even a single `thread_local`
+variable with a dynamic initializer has an associated TLS guard variable.)
+
+## Initial Exec (IE)
+
+If the variable is part of the Static TLS Block (i.e. the executable or an initially-loaded shared
+object), then its offset from the TP is known at load-time. The variable can be accessed with a few
+loads.
+
+Example: a C file for an executable:
+
+```cpp
+// tls_var could be defined in the executable, or it could be defined
+// in a shared object the executable links against.
+extern thread_local char tls_var;
+char* get_addr() { return &tls_var; }
+```
+
+Compiles to:
+
+```cpp
+// allocated in the .got, resolved at load-time with a dynamic reloc.
+// Unlike DTPOFF, which is relative to the start of the module’s block,
+// TPOFF is directly relative to the thread pointer.
+static long tls_var_gotoff = R_TLS_TPOFF(tls_var);
+
+char* get_addr() {
+  return (char*)__get_tls() + tls_var_gotoff;
+}
+```
+
+## Local Exec (LE)
+
+LE is a specialization of IE. If the variable is not just part of the Static TLS Block, but is also
+part of the executable (and referenced from the executable), then a GOT access can be avoided. The
+IE example compiles to:
+
+```cpp
+char* get_addr() {
+  // R_TLS_TPOFF() is resolved at (static) link-time
+  return (char*)__get_tls() + R_TLS_TPOFF(tls_var);
+}
+```
+
+## Selecting an Access Model
+
+The compiler selects an access model for each variable reference using these factors:
+ * The absence of `-fpic` implies an executable, so use IE/LE.
+ * Code compiled with `-fpic` could be in a shared object, so use GD/LD.
+ * The per-file default can be overridden with `-ftls-model=<model>`.
+ * Specifiers on the variable (`static`, `extern`, ELF visibility attributes).
+ * A variable can be annotated with `__attribute__((tls_model(...)))`. Clang may still use a more
+   efficient model than the one specified.
+
+# Shared Objects with Static TLS
+
+Shared objects are sometimes compiled with `-ftls-model=initial-exec` (i.e. "static TLS") for better
+performance. On Ubuntu, for example, `libc.so.6` and `libOpenGL.so.0` are compiled this way. Shared
+objects using static TLS can't be loaded with `dlopen` unless libc has reserved enough surplus
+memory in the static TLS block. glibc reserves a kilobyte or two (`TLS_STATIC_SURPLUS`) with the
+intent that only a few core system libraries would use static TLS. Non-core libraries also sometimes
+use it, which can break `dlopen` if the surplus area is exhausted. See:
+ * https://bugzilla.redhat.com/show_bug.cgi?id=1124987
+ * web search: [`"dlopen: cannot load any more object with static TLS"`][glibc-static-tls-error]
+
+Neither musl nor the Bionic TLS prototype currently allocate any surplus TLS memory.
+
+In general, supporting surplus TLS memory probably requires maintaining a thread list so that
+`dlopen` can initialize the new static TLS memory in all existing threads. A thread list could be
+omitted if the loader only allowed zero-initialized TLS segments and didn't reclaim memory on
+`dlclose`.
+
+As long as a shared object is one of the initially-loaded modules, a better option is to use
+TLSDESC.
+
+[glibc-static-tls-error]: https://www.google.com/search?q=%22dlopen:+cannot+load+any+more+object+with+static+TLS%22
+
+# TLS Descriptors (TLSDESC)
+
+The code fragments above match the "traditional" TLS design from Drepper's document. For the GD and
+LD models, there is a newer, more efficient design that uses "TLS descriptors". Each TLS variable
+reference has a corresponding descriptor, which contains a resolver function address and an argument
+to pass to the resolver.
+
+For example, if we have this C code in a shared object:
+
+```cpp
+extern thread_local char tls_var;
+char* get_tls_var() {
+  return &tls_var;
+}
+```
+
+The toolchain generates code like this:
+
+```cpp
+struct TlsDescriptor { // NB: arm32 reverses these fields
+  long (*resolver)(long);
+  long arg;
+};
+
+char* get_tls_var() {
+  // allocated in the .got, uses a dynamic relocation
+  static TlsDescriptor desc = R_TLS_DESC(tls_var);
+  return (char*)__get_tls() + desc.resolver(desc.arg);
+}
+```
+
+The dynamic loader fills in the TLS descriptors. For a reference to a variable allocated in the
+Static TLS Block, it can use a simple resolver function:
+
+```cpp
+long static_tls_resolver(long arg) {
+  return arg;
+}
+```
+
+The loader writes `tls_var@TPOFF` into the descriptor's argument.
+
+To support modules loaded with `dlopen`, the loader must use a resolver function that calls
+`__tls_get_addr`. In principle, this simple implementation would work:
+
+```cpp
+long dynamic_tls_resolver(TlsIndex* arg) {
+  return (long)__tls_get_addr(arg) - (long)__get_tls();
+}
+```
+
+There are optimizations that complicate the design a little:
+ * Unlike `__tls_get_addr`, the resolver function has a special calling convention that preserves
+   almost all registers, reducing register pressure in the caller
+   ([example](https://godbolt.org/g/gywcxk)).
+ * In general, the resolver function must call `__tls_get_addr`, so it must save and restore all
+   registers.
+ * To keep the fast path fast, the resolver inlines the fast path of `__tls_get_addr`.
+ * By storing the module's initial generation alongside the TlsIndex, the resolver function doesn't
+   need to use an atomic or synchronized access of the global TLS generation counter.
+
+The resolver must be written in assembly, but in C, the function looks like so:
+
+```cpp
+struct TlsDescDynamicArg {
+  unsigned long first_generation;
+  TlsIndex idx;
+};
+
+struct TlsDtv { // DTV == dynamic thread vector
+  unsigned long generation;
+  char* modules[];
+};
+
+long dynamic_tls_resolver(TlsDescDynamicArg* arg) {
+  TlsDtv* dtv = __get_dtv();
+  char* addr;
+  if (dtv->generation >= arg->first_generation &&
+      dtv->modules[arg->idx.module] != nullptr) {
+    addr = dtv->modules[arg->idx.module] + arg->idx.offset;
+  } else {
+    addr = __tls_get_addr(&arg->idx);
+  }
+  return (long)addr - (long)__get_tls();
+}
+```
+
+The loader needs to allocate a table of `TlsDescDynamicArg` objects for each TLS module with dynamic
+TLSDESC relocations.
+
+The static linker can still relax a TLSDESC-based access to an IE/LE access.
+
+The traditional TLS design is implemented everywhere, but the TLSDESC design has less toolchain
+support:
+ * GCC and the BFD linker support both designs on all supported Android architectures (arm32, arm64,
+   x86, x86-64).
+ * GCC can select the design at run-time using `-mtls-dialect=<dialect>` (`trad`-vs-`desc` on arm64,
+   otherwise `gnu`-vs-`gnu2`). Clang always uses the default mode.
+ * GCC and Clang default to TLSDESC on arm64 and the traditional design on other architectures.
+ * Gold and LLD support for TLSDESC is spotty (except when targeting arm64).
+
+# Linker Relaxations
+
+The (static) linker frequently has more information about the location of a referenced TLS variable
+than the compiler, so it can "relax" TLS accesses to more efficient models. For example, if an
+object file compiled with `-fpic` is linked into an executable, the linker could relax GD accesses
+to IE or LE. To relax a TLS access, the linker looks for an expected sequences of instructions and
+static relocations, then replaces the sequence with a different one of equal size. It may need to
+add or remove no-op instructions.
+
+## Current Support for GD->LE Relaxations Across Linkers
+
+Versions tested:
+ * BFD and Gold linkers: version 2.30
+ * LLD version 6.0.0 (upstream)
+
+Linker support for GD->LE relaxation with `-mtls-dialect=gnu/trad` (traditional):
+
+Architecture    | BFD | Gold | LLD
+--------------- | --- | ---- | ---
+arm32           | no  | no   | no
+arm64 (unusual) | yes | yes  | no
+x86             | yes | yes  | yes
+x86_64          | yes | yes  | yes
+
+Linker support for GD->LE relaxation with `-mtls-dialect=gnu2/desc` (TLSDESC):
+
+Architecture          | BFD | Gold               | LLD
+--------------------- | --- | ------------------ | ------------------
+arm32 (experimental)  | yes | unsupported relocs | unsupported relocs
+arm64                 | yes | yes                | yes
+x86 (experimental)    | yes | yes                | unsupported relocs
+X86_64 (experimental) | yes | yes                | unsupported relocs
+
+arm32 linkers can't relax traditional TLS accesses. BFD can relax an arm32 TLSDESC access, but LLD
+can't link code using TLSDESC at all, except on arm64, where it's used by default.
+
+# dlsym
+
+Calling `dlsym` on a TLS variable returns the address of the current thread's variable.
+
+# Debugger Support
+
+## gdb
+
+gdb uses a libthread_db plugin library to retrieve thread-related information from a target. This
+library is typically a shared object, but for Android, we link our own `libthread_db.a` into
+gdbserver. We will need to implement at least 2 APIs in `libthread_db.a` to find TLS variables, and
+gdb provides APIs for looking up symbols, reading or writing memory, and retrieving the current
+thread pointer (e.g. `ps_get_thread_area`).
+ * Reference: [gdb_proc_service.h]: APIs gdb provides to libthread_db
+ * Reference: [Currently unimplemented TLS functions in Android's libthread_tb][libthread_db.c]
+
+[gdb_proc_service.h]: https://android.googlesource.com/toolchain/gdb/+/a7e49fd02c21a496095c828841f209eef8ae2985/gdb-8.0.1/gdb/gdb_proc_service.h#41
+[libthread_db.c]: https://android.googlesource.com/platform/ndk/+/e1f0ad12fc317c0ca3183529cc9625d3f084d981/sources/android/libthread_db/libthread_db.c#115
+
+## LLDB
+
+LLDB more-or-less implemented Linux TLS debugging in [r192922][rL192922] ([D1944]) for x86 and
+x86-64. [arm64 support came later][D5073]. However, the Linux TLS functionality no longer does
+anything: the `GetThreadPointer` function is no longer implemented. Code for reading the thread
+pointer was removed in [D10661] ([this function][r240543]). (arm32 was apparently never supported.)
+
+[rL192922]: https://reviews.llvm.org/rL192922
+[D1944]: https://reviews.llvm.org/D1944
+[D5073]: https://reviews.llvm.org/D5073
+[D10661]: https://reviews.llvm.org/D10661
+[r240543]: https://github.com/llvm-mirror/lldb/commit/79246050b0f8d6b54acb5366f153d07f235d2780#diff-52dee3d148892cccfcdab28bc2165548L962
+
+## Threading Library Metadata
+
+Both debuggers need metadata from the threading library (`libc.so` / `libpthread.so`) to find TLS
+variables. From [LLDB r192922][rL192922]'s commit message:
+
+> ... All OSes use basically the same algorithm (a per-module lookup table) as detailed in Ulrich
+> Drepper's TLS ELF ABI document, so we can easily write code to decode it ourselves. The only
+> question therefore is the exact field layouts required. Happily, the implementors of libpthread
+> expose the structure of the DTV via metadata exported as symbols from the .so itself, designed
+> exactly for this kind of thing. So this patch simply reads that metadata in, and re-implements
+> libthread_db's algorithm itself. We thereby get cross-platform TLS lookup without either requiring
+> third-party libraries, while still being independent of the version of libpthread being used.
+
+ LLDB uses these variables:
+
+Name                              | Notes
+--------------------------------- | ---------------------------------------------------------------------------------------
+`_thread_db_pthread_dtvp`         | Offset from TP to DTV pointer (0 for variant 1, implementation-defined for variant 2)
+`_thread_db_dtv_dtv`              | Size of a DTV slot (typically/always sizeof(void*))
+`_thread_db_dtv_t_pointer_val`    | Offset within a DTV slot to the pointer to the allocated TLS block (typically/always 0)
+`_thread_db_link_map_l_tls_modid` | Offset of a `link_map` field containing the module's 1-based TLS module ID
+
+The metadata variables are local symbols in glibc's `libpthread.so` symbol table (but not its
+dynamic symbol table). Debuggers can access them, but applications can't.
+
+The debugger lookup process is straightforward:
+ * Find the `link_map` object and module-relative offset for a TLS variable.
+ * Use `_thread_db_link_map_l_tls_modid` to find the TLS variable's module ID.
+ * Read the target thread pointer.
+ * Use `_thread_db_pthread_dtvp` to find the thread's DTV.
+ * Use `_thread_db_dtv_dtv` and `_thread_db_dtv_t_pointer_val` to find the desired module's block
+   within the DTV.
+ * Add the module-relative offset to the module pointer.
+
+This process doesn't appear robust in the face of lazy DTV initialization -- presumably it could
+read past the end of an out-of-date DTV or access an unloaded module. To be robust, it needs to
+compare a module's initial generation count against the DTV's generation count. (XXX: Does gdb have
+these sorts of problems with glibc's libpthread?)
+
+## Reading the Thread Pointer with Ptrace
+
+There are ptrace interfaces for reading the thread pointer for each of arm32, arm64, x86, and x86-64
+(XXX: check 32-vs-64-bit for inferiors, debuggers, and kernels):
+ * arm32: `PTRACE_GET_THREAD_AREA`
+ * arm64: `PTRACE_GETREGSET`, `NT_ARM_TLS`
+ * x86_32: `PTRACE_GET_THREAD_AREA`
+ * x86_64: use `PTRACE_PEEKUSER` to read the `{fs,gs}_base` fields of `user_regs_struct`
+
+# C/C++ Specifiers
+
+C/C++ TLS variables are declared with a specifier:
+
+Specifier       | Notes
+--------------- | -----------------------------------------------------------------------------------------------------------------------------
+`__thread`      |  - non-standard, but ubiquitous in GCC and Clang<br/> - cannot have dynamic initialization or destruction
+`_Thread_local` |  - a keyword standardized in C11<br/> - cannot have dynamic initialization or destruction
+`thread_local`  |  - C11: a macro for `_Thread_local` via `threads.h`<br/> - C++11: a keyword, allows dynamic initialization and/or destruction
+
+The dynamic initialization and destruction of C++ `thread_local` variables is layered on top of ELF
+TLS (or emutls), so this design document mostly ignores it. Like emutls, ELF TLS variables either
+have a static initializer or are zero-initialized.
+
+Aside: Because a `__thread` variable cannot have dynamic initialization, `__thread` is more
+efficient in C++ than `thread_local` when the compiler cannot see the definition of a declared TLS
+variable. The compiler assumes the variable could have a dynamic initializer and generates code, at
+each access, to call a function to initialize the variable.
+
+# Graceful Failure on Old Platforms
+
+ELF TLS isn't implemented on older Android platforms, so dynamic executables and shared objects
+using it generally won't work on them. Ideally, the older platforms would reject these binaries
+rather than experience memory corruption at run-time.
+
+Static executables aren't a problem--the necessary runtime support is part of the executable, so TLS
+just works.
+
+XXX: Shared objects are less of a problem.
+ * On arm32, x86, and x86_64, the loader [should reject a TLS relocation]. (XXX: I haven't verified
+   this.)
+ * On arm64, the primary TLS relocation (R_AARCH64_TLSDESC) is [confused with an obsolete
+   R_AARCH64_TLS_DTPREL32 relocation][R_AARCH64_TLS_DTPREL32] and is [quietly ignored].
+ * Android P [added compatibility checks] for TLS symbols and `DT_TLSDESC_{GOT|PLT}` entries.
+
+XXX: A dynamic executable using ELF TLS would have a PT_TLS segment and no other distinguishing
+marks, so running it on an older platform would result in memory corruption. Should we add something
+to these executables that only newer platforms recognize? (e.g. maybe an entry in .dynamic, a
+reference to a symbol only a new libc.so has...)
+
+[should reject a TLS relocation]: https://android.googlesource.com/platform/bionic/+/android-8.1.0_r48/linker/linker.cpp#2852
+[R_AARCH64_TLS_DTPREL32]: https://android-review.googlesource.com/c/platform/bionic/+/723696
+[quietly ignored]: https://android.googlesource.com/platform/bionic/+/android-8.1.0_r48/linker/linker.cpp#2784
+[added compatibility checks]: https://android-review.googlesource.com/c/platform/bionic/+/648760
+
+# Bionic Prototype Notes
+
+There is an [ELF TLS prototype] uploaded on Gerrit. It implements:
+ * Static TLS Block allocation for static and dynamic executables
+ * TLS for dynamically loaded and unloaded modules (`__tls_get_addr`)
+ * TLSDESC for arm64 only
+
+Missing:
+ * `dlsym` of a TLS variable
+ * debugger support
+
+[ELF TLS prototype]: https://android-review.googlesource.com/q/topic:%22elf-tls-prototype%22+(status:open%20OR%20status:merged)
+
+## Loader/libc Communication
+
+The loader exposes a list of TLS modules ([`struct TlsModules`][TlsModules]) to `libc.so` using the
+`__libc_shared_globals` variable (see `tls_modules()` in [linker_tls.cpp][tls_modules-linker] and
+[elf_tls.cpp][tls_modules-libc]). `__tls_get_addr` in libc.so acquires the `TlsModules::mutex` and
+iterates its module list to lazily allocate and free TLS blocks.
+
+[TlsModules]: https://android-review.googlesource.com/c/platform/bionic/+/723698/1/libc/bionic/elf_tls.h#53
+[tls_modules-linker]: https://android-review.googlesource.com/c/platform/bionic/+/723698/1/linker/linker_tls.cpp#45
+[tls_modules-libc]: https://android-review.googlesource.com/c/platform/bionic/+/723698/1/libc/bionic/elf_tls.cpp#49
+
+## TLS Allocator
+
+The prototype currently allocates a `pthread_internal_t` object and static TLS in a single mmap'ed
+region, along with a thread's stack if it needs one allocated. It doesn't place TLS memory on a
+preallocated stack (either the main thread's stack or one provided with `pthread_attr_setstack`).
+
+The DTV and blocks for dlopen'ed modules are instead allocated using the Bionic loader's
+`LinkerMemoryAllocator`, adapted to avoid the STL and to provide `memalign`. The prototype tries to
+achieve async-signal safety by blocking signals and acquiring a lock.
+
+There are three "entry points" to dynamically locate a TLS variable's address:
+ * libc.so: `__tls_get_addr`
+ * loader: TLSDESC dynamic resolver
+ * loader: dlsym
+
+The loader's entry points need to call `__tls_get_addr`, which needs to allocate memory. Currently,
+the prototype uses a [special function pointer] to call libc.so's `__tls_get_addr` from the loader.
+(This should probably be removed.)
+
+The prototype currently allows for arbitrarily-large TLS variable alignment. IIRC, different
+implementations (glibc, musl, FreeBSD) vary in their level of respect for TLS alignment. It looks
+like the Bionic loader ignores segments' alignment and aligns loaded libraries to 256 KiB. See
+`ReserveAligned`.
+
+[special function pointer]: https://android-review.googlesource.com/c/platform/bionic/+/723698/1/libc/private/bionic_globals.h#52
+
+## Async-Signal Safety
+
+The prototype's `__tls_get_addr` might be async-signal safe. Making it AS-safe is a good idea if
+it's feasible. musl's function is AS-safe, but glibc's isn't (or wasn't). Google had a patch to make
+glibc AS-safe back in 2012-2013. See:
+ * https://sourceware.org/glibc/wiki/TLSandSignals
+ * https://sourceware.org/ml/libc-alpha/2012-06/msg00335.html
+ * https://sourceware.org/ml/libc-alpha/2013-09/msg00563.html
+
+## Out-of-Memory Handling (abort)
+
+The prototype lazily allocates TLS memory for dlopen'ed modules (see `__tls_get_addr`), and an
+out-of-memory error on a TLS access aborts the process. musl, on the other hand, preallocates TLS
+memory on `pthread_create` and `dlopen`, so either function can return out-of-memory. Both functions
+probably need to acquire the same lock.
+
+Maybe Bionic should do the same as musl? Perhaps musl's robustness argument holds for Bionic,
+though, because Bionic (at least the linker) probably already aborts on OOM. musl doesn't support
+`dlclose`/unloading, so it might have an easier time.
+
+On the other hand, maybe lazy allocation is a feature, because not all threads will use a dlopen'ed
+solib's TLS variables. Drepper makes this argument in his TLS document:
+
+> In addition the run-time support should avoid creating the thread-local storage if it is not
+> necessary. For instance, a loaded module might only be used by one thread of the many which make
+> up the process. It would be a waste of memory and time to allocate the storage for all threads. A
+> lazy method is wanted. This is not much extra burden since the requirement to handle dynamically
+> loaded objects already requires recognizing storage which is not yet allocated. This is the only
+> alternative to stopping all threads and allocating storage for all threads before letting them run
+> again.
+
+FWIW: emutls also aborts on out-of-memory.
+
+## ELF TLS Not Usable in libc
+
+The dynamic loader currently can't use ELF TLS, so any part of libc linked into the loader (i.e.
+most of it) also can't use ELF TLS. It might be possible to lift this restriction, perhaps with
+specialized `__tls_get_addr` and TLSDESC resolver functions.
+
+# Open Issues
+
+## Bionic Memory Layout Conflicts with Common TLS Layout
+
+Bionic already allocates thread-specific data in a way that conflicts with TLS variants 1 and 2:
+![Bionic TLS Layout in Android P](img/bionic-tls-layout-in-p.png)
+
+TLS variant 1 allocates everything after the TP to ELF TLS (except the first two words), and variant
+2 allocates everything before the TP. Bionic currently allocates memory before and after the TP to
+the `pthread_internal_t` struct.
+
+The `bionic_tls.h` header is marked with a warning:
+
+```cpp
+/** WARNING WARNING WARNING
+ **
+ ** This header file is *NOT* part of the public Bionic ABI/API
+ ** and should not be used/included by user-serviceable parts of
+ ** the system (e.g. applications).
+ **
+ ** It is only provided here for the benefit of the system dynamic
+ ** linker and the OpenGL sub-system (which needs to access the
+ ** pre-allocated slot directly for performance reason).
+ **/
+```
+
+There are issues with rearranging this memory:
+
+ * `TLS_SLOT_STACK_GUARD` is used for `-fstack-protector`. The location (word #5) was initially used
+   by GCC on x86 (and x86-64), where it is compatible with x86's TLS variant 2. We [modified Clang
+   to use this slot for arm64 in 2016][D18632], though, and the slot isn't compatible with ARM's
+   variant 1 layout. This change shipped in NDK r14, and the NDK's build systems (ndk-build and the
+   CMake toolchain file) enable `-fstack-protector-strong` by default.
+
+ * `TLS_SLOT_TSAN` is used for more than just TSAN -- it's also used by [HWASAN and
+   Scudo](https://reviews.llvm.org/D53906#1285002).
+
+ * The Go runtime allocates a thread-local "g" variable on Android by creating a pthread key and
+   searching for its TP-relative offset, which it assumes is nonnegative:
+    * On arm32/arm64, it creates a pthread key, sets it to a magic value, then scans forward from
+      the thread pointer looking for it. [The scan count was bumped to 384 to fix a reported
+      breakage happening with Android N.](https://go-review.googlesource.com/c/go/+/38636) (XXX: I
+      suspect the actual platform breakage happened with Android M's [lock-free pthread key
+      work][bionic-lockfree-keys].)
+    * On x86/x86-64, it uses a fixed offset from the thread pointer (TP+0xf8 or TP+0x1d0) and
+      creates pthread keys until one of them hits the fixed offset.
+    * CLs:
+       * arm32: https://codereview.appspot.com/106380043
+       * arm64: https://go-review.googlesource.com/c/go/+/17245
+       * x86: https://go-review.googlesource.com/c/go/+/16678
+       * x86-64: https://go-review.googlesource.com/c/go/+/15991
+    * Moving the pthread keys before the thread pointer breaks Go-based apps.
+    * It's unclear how many Android apps use Go. There are at least two with 1,000,000+ installs.
+    * [Some motivation for Go's design][golang-post], [runtime/HACKING.md][go-hacking]
+    * [On x86/x86-64 Darwin, Go uses a TLS slot reserved for both Go and Wine][go-darwin-x86] (On
+      [arm32][go-darwin-arm32]/[arm64][go-darwin-arm64] Darwin, Go scans for pthread keys like it
+      does on Android.)
+
+ * Android's "native bridge" system allows the Zygote to load an app solib of a non-native ABI. (For
+   example, it could be used to load an arm32 solib into an x86 Zygote.) The solib is translated
+   into the host architecture. TLS accesses in the app solib (whether ELF TLS, Bionic slots, or
+   `pthread_internal_t` fields) become host accesses. Laying out TLS memory differently across
+   architectures could complicate this translation.
+
+ * A `pthread_t` is practically just a `pthread_internal_t*`, and some apps directly access the
+   `pthread_internal_t::tid` field. Past examples: http://b/17389248, [aosp/107467]. Reorganizing
+   the initial `pthread_internal_t` fields could break those apps.
+
+It seems easy to fix the incompatibility for variant 2 (x86 and x86_64) by splitting out the Bionic
+slots into a new data structure. Variant 1 is a harder problem.
+
+The TLS prototype currently uses a patched LLD that uses a variant 1 TLS layout with a 16-word TCB
+on all architectures.
+
+Aside: gcc's arm64ilp32 target uses a 32-bit unsigned offset for a TLS IE access
+(https://godbolt.org/z/_NIXjF). If Android ever supports this target, and in a configuration with
+variant 2 TLS, we might need to change the compiler to emit a sign-extending load.
+
+[D18632]: https://reviews.llvm.org/D18632
+[bionic-lockfree-keys]: https://android-review.googlesource.com/c/platform/bionic/+/134202
+[golang-post]: https://groups.google.com/forum/#!msg/golang-nuts/EhndTzcPJxQ/i-w7kAMfBQAJ
+[go-hacking]: https://github.com/golang/go/blob/master/src/runtime/HACKING.md
+[go-darwin-x86]: https://github.com/golang/go/issues/23617
+[go-darwin-arm32]: https://github.com/golang/go/blob/15c106d99305411b587ec0d9e80c882e538c9d47/src/runtime/cgo/gcc_darwin_arm.c
+[go-darwin-arm64]: https://github.com/golang/go/blob/15c106d99305411b587ec0d9e80c882e538c9d47/src/runtime/cgo/gcc_darwin_arm64.c
+[aosp/107467]: https://android-review.googlesource.com/c/platform/bionic/+/107467
+
+### Workaround: Use Variant 2 on arm32/arm64
+
+Pros: simplifies Bionic
+
+Cons:
+ * arm64: requires either subtle reinterpretation of a TLS relocation or addition of a new
+   relocation
+ * arm64: a new TLS relocation reduces compiler/assembler compatibility with non-Android
+
+The point of variant 2 was backwards-compatibility, and ARM Android needs to remain
+backwards-compatible, so we could use variant 2 for ARM. Problems:
+
+ * When linking an executable, the static linker needs to know how TLS is allocated because it
+   writes TP-relative offsets for IE/LE-model accesses. Clang doesn't tell the linker to target
+   Android, so it could pass an `--tls-variant2` flag to configure lld.
+
+ * On arm64, there are different sets of static LE relocations accommodating different ranges of
+   offsets from TP:
+
+   Size | TP offset range   | Static LE relocation types
+   ---- | ----------------- | ---------------------------------------
+   12   | 0 <= x < 2^12     | `R_AARCH64_TLSLE_ADD_TPREL_LO12`
+   "    | "                 | `R_AARCH64_TLSLE_LDST8_TPREL_LO12`
+   "    | "                 | `R_AARCH64_TLSLE_LDST16_TPREL_LO12`
+   "    | "                 | `R_AARCH64_TLSLE_LDST32_TPREL_LO12`
+   "    | "                 | `R_AARCH64_TLSLE_LDST64_TPREL_LO12`
+   "    | "                 | `R_AARCH64_TLSLE_LDST128_TPREL_LO12`
+   16   | -2^16 <= x < 2^16 | `R_AARCH64_TLSLE_MOVW_TPREL_G0`
+   24   | 0 <= x < 2^24     | `R_AARCH64_TLSLE_ADD_TPREL_HI12`
+   "    | "                 | `R_AARCH64_TLSLE_ADD_TPREL_LO12_NC`
+   "    | "                 | `R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC`
+   "    | "                 | `R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC`
+   "    | "                 | `R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC`
+   "    | "                 | `R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC`
+   "    | "                 | `R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC`
+   32   | -2^32 <= x < 2^32 | `R_AARCH64_TLSLE_MOVW_TPREL_G1`
+   "    | "                 | `R_AARCH64_TLSLE_MOVW_TPREL_G0_NC`
+   48   | -2^48 <= x < 2^48 | `R_AARCH64_TLSLE_MOVW_TPREL_G2`
+   "    | "                 | `R_AARCH64_TLSLE_MOVW_TPREL_G1_NC`
+   "    | "                 | `R_AARCH64_TLSLE_MOVW_TPREL_G0_NC`
+
+   GCC for arm64 defaults to the 24-bit model and has an `-mtls-size=SIZE` option for setting other
+   supported sizes. (It supports 12, 24, 32, and 48.) Clang has only implemented the 24-bit model,
+   but that could change. (Clang [briefly used][D44355] load/store relocations, but it was reverted
+   because no linker supported them: [BFD], [Gold], [LLD]).
+
+   The 16-, 32-, and 48-bit models use a `movn/movz` instruction to set the highest 16 bits to a
+   positive or negative value, then `movk` to set the remaining 16 bit chunks. In principle, these
+   relocations should be able to accommodate a negative TP offset.
+
+   The 24-bit model uses `add` to set the high 12 bits, then places the low 12 bits into another
+   `add` or a load/store instruction.
+
+Maybe we could modify the `R_AARCH64_TLSLE_ADD_TPREL_HI12` relocation to allow a negative TP offset
+by converting the relocated `add` instruction to a `sub`. Alternately, we could add a new
+`R_AARCH64_TLSLE_SUB_TPREL_HI12` relocation, and Clang would use a different TLS LE instruction
+sequence when targeting Android/arm64.
+
+ * LLD's arm64 relaxations from GD and IE to LE would need to use `movn` instead of `movk` for
+   Android.
+
+ * Binaries linked with the flag crash on non-Bionic, and binaries without the flag crash on Bionic.
+   We might want to mark the binaries somehow to indicate the non-standard TLS ABI. Suggestion:
+    * Use an `--android-tls-variant2` flag (or `--bionic-tls-variant2`, we're trying to make [Bionic
+      run on the host](http://b/31559095))
+    * Add a `PT_ANDROID_TLS_TPOFF` segment?
+    * Add a [`.note.gnu.property`](https://reviews.llvm.org/D53906#1283425) with a
+      "`GNU_PROPERTY_TLS_TPOFF`" property value?
+
+[D44355]: https://reviews.llvm.org/D44355
+[BFD]: https://sourceware.org/bugzilla/show_bug.cgi?id=22970
+[Gold]: https://sourceware.org/bugzilla/show_bug.cgi?id=22969
+[LLD]: https://bugs.llvm.org/show_bug.cgi?id=36727
+
+### Workaround: Reserve an Extra-Large TCB on ARM
+
+Pros: Minimal linker change, no change to TLS relocations.
+Cons: The reserved amount becomes an arbitrary but immutable part of the Android ABI.
+
+Add an lld option: `--android-tls[-tcb=SIZE]`
+
+As with the first workaround, we'd probably want to mark the binary to indicate the non-standard
+TP-to-TLS-segment offset.
+
+Reservation amount:
+ * We would reserve at least 6 words to cover the stack guard
+ * Reserving 16 covers all the existing Bionic slots and gives a little room for expansion. (If we
+   ever needed more than 16 slots, we could allocate the space before TP.)
+ * 16 isn't enough for the pthread keys, so the Go runtime is still a problem.
+ * Reserving 138 words is enough for existing slots and pthread keys.
+
+### Workaround: Use Variant 1 Everywhere with an Extra-Large TCB
+
+Pros:
+ * memory layout is the same on all architectures, avoids native bridge complications
+ * x86/x86-64 relocations probably handle positive offsets without issue
+
+Cons:
+ * The reserved amount is still arbitrary.
+
+### Workaround: No LE Model in Android Executables
+
+Pros:
+ * Keeps options open. We can allow LE later if we want.
+ * Bionic's existing memory layout doesn't change, and arm32 and 32-bit x86 have the same layout
+ * Fixes everything but static executables
+
+Cons:
+ * more intrusive toolchain changes (affects both Clang and LLD)
+ * statically-linked executables still need another workaround
+ * somewhat larger/slower executables (they must use IE, not LE)
+
+The layout conflict is apparently only a problem because an executable assumes that its TLS segment
+is located at a statically-known offset from the TP (i.e. it uses the LE model). An initially-loaded
+shared object can still use the efficient IE access model, but its TLS segment offset is known at
+load-time, not link-time. If we can guarantee that Android's executables also use the IE model, not
+LE, then the Bionic loader can place the executable's TLS segment at any offset from the TP, leaving
+the existing thread-specific memory layout untouched.
+
+This workaround doesn't help with statically-linked executables, but they're probably less of a
+problem, because the linker and `libc.a` are usually packaged together.
+
+A likely problem: LD is normally relaxed to LE, not to IE. We'd either have to disable LD usage in
+the compiler (bad for performance) or add LD->IE relaxation. This relaxation requires that IE code
+sequences be no larger than LD code sequences, which may not be the case on some architectures.
+(XXX: In some past testing, it looked feasible for TLSDESC but not the traditional design.)
+
+To implement:
+ * Clang would need to stop generating LE accesses.
+ * LLD would need to relax GD and LD to IE instead of LE.
+ * LLD should abort if it sees a TLS LE relocation.
+ * LLD must not statically resolve an executable's IE relocation in the GOT. (It might assume that
+   it knows its value.)
+ * Perhaps LLD should mark executables specially, because a normal ELF linker's output would quietly
+   trample on `pthread_internal_t`. We need something like `DF_STATIC_TLS`, but instead of
+   indicating IE in an solib, we want to indicate the lack of LE in an executable.
+
+### (Non-)workaround for Go: Allocate a Slot with Go's Magic Values
+
+The Go runtime allocates its thread-local "g" variable by searching for a hard-coded magic constant
+(`0x23581321` for arm32 and `0x23581321345589` for arm64). As long as it finds its constant at a
+small positive offset from TP (within the first 384 words), it will think it has found the pthread
+key it allocated.
+
+As a temporary compatibility hack, we might try to keep these programs running by reserving a TLS
+slot with this magic value. This hack doesn't appear to work, however. The runtime finds its pthread
+key, but apps segfault. Perhaps the Go runtime expects its "g" variable to be zero-initialized ([one
+example][go-tlsg-zero]). With this hack, it's never zero, but with its current allocation strategy,
+it is typically zero. After [Bionic's pthread key system was rewritten to be
+lock-free][bionic-lockfree-keys] for Android M, though, it's not guaranteed, because a key could be
+recycled.
+
+[go-tlsg-zero]: https://go.googlesource.com/go/+/5bc1fd42f6d185b8ff0201db09fb82886978908b/src/runtime/asm_arm64.s#980
+
+### Workaround for Go: place pthread keys after the executable's TLS
+
+Most Android executables do not use any `thread_local` variables. In the current prototype, with the
+AOSP hikey960 build, only `/system/bin/netd` has a TLS segment, and it's only 32 bytes. As long as
+`/system/bin/app_process{32,64}` limits its use of TLS memory, then the pthread keys could be
+allocated after `app_process`' TLS segment, and Go will still find them.
+
+Go scans 384 words from the thread pointer. If there are at most 16 Bionic slots and 130 pthread
+keys (2 words per key), then `app_process` can use at most 108 words of TLS memory.
+
+Drawback: In principle, this might make pthread key accesses slower, because Bionic can't assume
+that pthread keys are at a fixed offset from the thread pointer anymore. It must load an offset from
+somewhere (a global variable, another TLS slot, ...). `__get_thread()` already uses a TLS slot to
+find `pthread_internal_t`, though, rather than assume a fixed offset. (XXX: I think it could be
+optimized.)
+
+## TODO: Memory Layout Querying APIs (Proposed)
+
+ * https://sourceware.org/glibc/wiki/ThreadPropertiesAPI
+ * http://b/30609580
+
+## TODO: Sanitizers
+
+XXX: Maybe a sanitizer would want to intercept allocations of TLS memory, and that could be hard if
+the loader is allocating it.
+ * It looks like glibc's ld.so re-relocates itself after loading a program, so a program's symbols
+   can interpose call in the loader: https://sourceware.org/ml/libc-alpha/2014-01/msg00501.html
+
+# References
+
+General (and x86/x86-64)
+ * Ulrich Drepper's TLS document, ["ELF Handling For Thread-Local Storage."][drepper] Describes the
+   overall ELF TLS design and ABI details for x86 and x86-64 (as well as several other architectures
+   that Android doesn't target).
+ * Alexandre Oliva's TLSDESC proposal with details for x86 and x86-64: ["Thread-Local Storage
+   Descriptors for IA32 and AMD64/EM64T."][tlsdesc-x86]
+ * [x86 and x86-64 SystemV psABIs][psabi-x86].
+
+arm32:
+ * Alexandre Oliva's TLSDESC proposal for arm32: ["Thread-Local Storage Descriptors for the ARM
+   platform."][tlsdesc-arm]
+ * ["Addenda to, and Errata in, the ABI for the ARM® Architecture."][arm-addenda] Section 3,
+   "Addendum: Thread Local Storage" has details for arm32 non-TLSDESC ELF TLS.
+ * ["Run-time ABI for the ARM® Architecture."][arm-rtabi] Documents `__aeabi_read_tp`.
+ * ["ELF for the ARM® Architecture."][arm-elf] List TLS relocations (traditional and TLSDESC).
+
+arm64:
+ * [2015 LLVM bugtracker comment][llvm22408] with an excerpt from an unnamed ARM draft specification
+   describing arm64 code sequences necessary for linker relaxation
+ * ["ELF for the ARM® 64-bit Architecture (AArch64)."][arm64-elf] Lists TLS relocations (traditional
+   and TLSDESC).
+
+[drepper]: https://www.akkadia.org/drepper/tls.pdf
+[tlsdesc-x86]: https://www.fsfla.org/~lxoliva/writeups/TLS/RFC-TLSDESC-x86.txt
+[psabi-x86]: https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI
+[tlsdesc-arm]: https://www.fsfla.org/~lxoliva/writeups/TLS/RFC-TLSDESC-ARM.txt
+[arm-addenda]: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0045e/IHI0045E_ABI_addenda.pdf
+[arm-rtabi]: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0043d/IHI0043D_rtabi.pdf
+[arm-elf]: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044f/IHI0044F_aaelf.pdf
+[llvm22408]: https://bugs.llvm.org/show_bug.cgi?id=22408#c10
+[arm64-elf]: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf
diff --git a/docs/img/bionic-tls-layout-in-p.png b/docs/img/bionic-tls-layout-in-p.png
new file mode 100644
index 0000000..4c810d6
--- /dev/null
+++ b/docs/img/bionic-tls-layout-in-p.png
Binary files differ
diff --git a/docs/img/tls-variant1.png b/docs/img/tls-variant1.png
new file mode 100644
index 0000000..bd92f16
--- /dev/null
+++ b/docs/img/tls-variant1.png
Binary files differ
diff --git a/docs/img/tls-variant2.png b/docs/img/tls-variant2.png
new file mode 100644
index 0000000..f941af7
--- /dev/null
+++ b/docs/img/tls-variant2.png
Binary files differ
diff --git a/libc/Android.bp b/libc/Android.bp
index 681394f..4c5b0b3 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -65,7 +65,7 @@
     cppflags: [],
     include_dirs: [
         "bionic/libc/async_safe/include",
-        "external/jemalloc/include",
+        "external/jemalloc_new/include",
     ],
 
     stl: "none",
@@ -76,6 +76,9 @@
     },
     native_coverage: false,
     recovery_available: true,
+
+    // TODO(ivanlozano): Remove after b/118321713
+    xom: false,
 }
 
 // ANDROIDMK TRANSLATION ERROR: unsupported directive
@@ -268,23 +271,11 @@
                 "upstream-freebsd/lib/libc/string/wcscmp.c",
                 "upstream-freebsd/lib/libc/string/wcslen.c",
                 "upstream-freebsd/lib/libc/string/wcsrchr.c",
+                "upstream-freebsd/lib/libc/string/wmemcmp.c",
+                "upstream-freebsd/lib/libc/string/wcscat.c",
+                "upstream-freebsd/lib/libc/string/wcscpy.c",
+                "upstream-freebsd/lib/libc/string/wmemcmp.c",
             ],
-            atom: {
-                exclude_srcs: [
-                    "upstream-freebsd/lib/libc/string/wmemcmp.c",
-                ],
-            },
-            ssse3: {
-                exclude_srcs: [
-                    "upstream-freebsd/lib/libc/string/wcscat.c",
-                    "upstream-freebsd/lib/libc/string/wcscpy.c",
-                ],
-            },
-            sse4: {
-                exclude_srcs: [
-                    "upstream-freebsd/lib/libc/string/wmemcmp.c",
-                ],
-            },
         },
     },
 
@@ -563,13 +554,9 @@
         arm: {
             exclude_srcs: [
                 "upstream-openbsd/lib/libc/string/strcpy.c",
+                "upstream-openbsd/lib/libc/string/stpcpy.c",
+                "upstream-openbsd/lib/libc/string/strcat.c",
             ],
-            neon: {
-                exclude_srcs: [
-                    "upstream-openbsd/lib/libc/string/stpcpy.c",
-                    "upstream-openbsd/lib/libc/string/strcat.c",
-                ],
-            },
         },
         arm64: {
             exclude_srcs: [
@@ -603,14 +590,10 @@
                 "upstream-openbsd/lib/libc/string/strcpy.c",
                 "upstream-openbsd/lib/libc/string/strncmp.c",
                 "upstream-openbsd/lib/libc/string/strncpy.c",
+                "upstream-openbsd/lib/libc/string/strlcat.c",
+                "upstream-openbsd/lib/libc/string/strlcpy.c",
+                "upstream-openbsd/lib/libc/string/strncat.c",
             ],
-            ssse3: {
-                exclude_srcs: [
-                    "upstream-openbsd/lib/libc/string/strlcat.c",
-                    "upstream-openbsd/lib/libc/string/strlcpy.c",
-                    "upstream-openbsd/lib/libc/string/strncat.c",
-                ],
-            },
         },
 
         x86_64: {
@@ -865,6 +848,8 @@
                 "arch-arm/generic/bionic/memcmp.S",
                 "arch-arm/generic/bionic/memmove.S",
                 "arch-arm/generic/bionic/memset.S",
+                "arch-arm/generic/bionic/stpcpy.c",
+                "arch-arm/generic/bionic/strcat.c",
                 "arch-arm/generic/bionic/strcmp.S",
                 "arch-arm/generic/bionic/strcpy.S",
                 "arch-arm/generic/bionic/strlen.c",
@@ -878,162 +863,44 @@
                 "arch-arm/bionic/setjmp.S",
                 "arch-arm/bionic/syscall.S",
                 "arch-arm/bionic/vfork.S",
+
+                "arch-arm/cortex-a15/bionic/memcpy.S",
+                "arch-arm/cortex-a15/bionic/memmove.S",
+                "arch-arm/cortex-a15/bionic/memset.S",
+                "arch-arm/cortex-a15/bionic/stpcpy.S",
+                "arch-arm/cortex-a15/bionic/strcat.S",
+                "arch-arm/cortex-a15/bionic/strcmp.S",
+                "arch-arm/cortex-a15/bionic/strcpy.S",
+                "arch-arm/cortex-a15/bionic/strlen.S",
+
+                "arch-arm/cortex-a7/bionic/memcpy.S",
+                "arch-arm/cortex-a7/bionic/memmove.S",
+                "arch-arm/cortex-a7/bionic/memset.S",
+
+                "arch-arm/cortex-a9/bionic/memcpy.S",
+                "arch-arm/cortex-a9/bionic/memmove.S",
+                "arch-arm/cortex-a9/bionic/memset.S",
+                "arch-arm/cortex-a9/bionic/stpcpy.S",
+                "arch-arm/cortex-a9/bionic/strcat.S",
+                "arch-arm/cortex-a9/bionic/strcmp.S",
+                "arch-arm/cortex-a9/bionic/strcpy.S",
+                "arch-arm/cortex-a9/bionic/strlen.S",
+
+                "arch-arm/krait/bionic/memcpy.S",
+                "arch-arm/krait/bionic/memmove.S",
+                "arch-arm/krait/bionic/memset.S",
+                "arch-arm/krait/bionic/strcmp.S",
+
+                "arch-arm/cortex-a53/bionic/memcpy.S",
+                "arch-arm/cortex-a53/bionic/memmove.S",
+
+                "arch-arm/denver/bionic/memcpy.S",
+                "arch-arm/denver/bionic/memmove.S",
+                "arch-arm/denver/bionic/memset.S",
+
+                "arch-arm/kryo/bionic/memcpy.S",
+                "arch-arm/kryo/bionic/memmove.S",
             ],
-            cortex_a7: {
-                srcs: [
-                    "arch-arm/cortex-a7/bionic/memcpy.S",
-                    "arch-arm/cortex-a7/bionic/memset.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/memcpy.S",
-                    "arch-arm/cortex-a15/bionic/memset.S",
-                ],
-            },
-            cortex_a9: {
-                srcs: [
-                    "arch-arm/cortex-a9/bionic/memcpy.S",
-                    "arch-arm/cortex-a9/bionic/memset.S",
-
-                    "arch-arm/cortex-a9/bionic/stpcpy.S",
-                    "arch-arm/cortex-a9/bionic/strcat.S",
-                    "arch-arm/cortex-a9/bionic/strcmp.S",
-                    "arch-arm/cortex-a9/bionic/strcpy.S",
-                    "arch-arm/cortex-a9/bionic/strlen.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/memcpy.S",
-                    "arch-arm/cortex-a15/bionic/memset.S",
-
-                    "arch-arm/cortex-a15/bionic/stpcpy.S",
-                    "arch-arm/cortex-a15/bionic/strcat.S",
-                    "arch-arm/cortex-a15/bionic/strcmp.S",
-                    "arch-arm/cortex-a15/bionic/strcpy.S",
-                    "arch-arm/cortex-a15/bionic/strlen.S",
-                ],
-            },
-            krait: {
-                srcs: [
-                    "arch-arm/krait/bionic/memcpy.S",
-                    "arch-arm/krait/bionic/memset.S",
-
-                    "arch-arm/krait/bionic/strcmp.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/memset.S",
-                    "arch-arm/cortex-a15/bionic/memcpy.S",
-
-                    "arch-arm/cortex-a15/bionic/strcmp.S",
-                ],
-            },
-            cortex_a53: {
-                srcs: [
-                    "arch-arm/cortex-a53/bionic/memcpy.S",
-                    "arch-arm/cortex-a7/bionic/memset.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/memset.S",
-                    "arch-arm/cortex-a15/bionic/memcpy.S",
-                ],
-            },
-            cortex_a55: {
-                srcs: [
-                    "arch-arm/cortex-a7/bionic/memset.S",
-                    "arch-arm/denver/bionic/memcpy.S",
-
-                    "arch-arm/krait/bionic/strcmp.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/memset.S",
-                    "arch-arm/cortex-a15/bionic/memcpy.S",
-                    "arch-arm/cortex-a15/bionic/strcmp.S",
-                ],
-            },
-            cortex_a73: {
-                srcs: [
-                    "arch-arm/cortex-a7/bionic/memset.S",
-                    "arch-arm/denver/bionic/memcpy.S",
-
-                    "arch-arm/krait/bionic/strcmp.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/memset.S",
-                    "arch-arm/cortex-a15/bionic/memcpy.S",
-                    "arch-arm/cortex-a15/bionic/strcmp.S",
-                ],
-            },
-            cortex_a75: {
-                srcs: [
-                    "arch-arm/cortex-a7/bionic/memset.S",
-                    "arch-arm/denver/bionic/memcpy.S",
-
-                    "arch-arm/krait/bionic/strcmp.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/memset.S",
-                    "arch-arm/cortex-a15/bionic/memcpy.S",
-                    "arch-arm/cortex-a15/bionic/strcmp.S",
-                ],
-            },
-            cortex_a76: {
-                srcs: [
-                    "arch-arm/cortex-a7/bionic/memset.S",
-                    "arch-arm/denver/bionic/memcpy.S",
-
-                    "arch-arm/krait/bionic/strcmp.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/memset.S",
-                    "arch-arm/cortex-a15/bionic/memcpy.S",
-                    "arch-arm/cortex-a15/bionic/strcmp.S",
-                ],
-            },
-            denver: {
-                srcs: [
-                    "arch-arm/denver/bionic/memcpy.S",
-                    "arch-arm/denver/bionic/memset.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/memset.S",
-                    "arch-arm/cortex-a15/bionic/memcpy.S",
-                ],
-            },
-            kryo: {
-                srcs: [
-                    "arch-arm/kryo/bionic/memcpy.S",
-                    "arch-arm/cortex-a7/bionic/memset.S",
-
-                    "arch-arm/krait/bionic/strcmp.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/cortex-a15/bionic/memset.S",
-                    "arch-arm/cortex-a15/bionic/memcpy.S",
-                    "arch-arm/cortex-a15/bionic/strcmp.S",
-                ],
-            },
-            // Cores not listed above (like cortex-a8, cortex-a15) or
-            // "generic" core will use the following implementation.
-            neon: {
-                srcs: [
-                    "arch-arm/cortex-a15/bionic/memcpy.S",
-                    "arch-arm/cortex-a15/bionic/memset.S",
-
-                    "arch-arm/cortex-a15/bionic/stpcpy.S",
-                    "arch-arm/cortex-a15/bionic/strcat.S",
-                    "arch-arm/cortex-a15/bionic/strcmp.S",
-                    "arch-arm/cortex-a15/bionic/strcpy.S",
-                    "arch-arm/cortex-a15/bionic/strlen.S",
-
-                    "arch-arm/denver/bionic/memmove.S",
-                ],
-                exclude_srcs: [
-                    "arch-arm/generic/bionic/memcpy.S",
-                    "arch-arm/generic/bionic/memmove.S",
-                    "arch-arm/generic/bionic/memset.S",
-                    "arch-arm/generic/bionic/strcmp.S",
-                    "arch-arm/generic/bionic/strcpy.S",
-                    "arch-arm/generic/bionic/strlen.c",
-                ],
-            },
         },
         arm64: {
             srcs: [
@@ -1136,6 +1003,14 @@
                 "arch-x86/generic/string/strcmp.S",
                 "arch-x86/generic/string/strncmp.S",
                 "arch-x86/generic/string/strcat.S",
+
+                "arch-x86/generic/string/strlcat.c",
+                "arch-x86/generic/string/strlcpy.c",
+                "arch-x86/generic/string/strncat.c",
+                "arch-x86/generic/string/wcscat.c",
+                "arch-x86/generic/string/wcscpy.c",
+                "arch-x86/generic/string/wmemcmp.c",
+
                 "arch-x86/atom/string/sse2-memchr-atom.S",
                 "arch-x86/atom/string/sse2-memrchr-atom.S",
                 "arch-x86/atom/string/sse2-strchr-atom.S",
@@ -1160,6 +1035,29 @@
                 "arch-x86/bionic/setjmp.S",
                 "arch-x86/bionic/syscall.S",
                 "arch-x86/bionic/vfork.S",
+
+                // ssse3 functions
+                "arch-x86/atom/string/ssse3-strcat-atom.S",
+                "arch-x86/atom/string/ssse3-strcmp-atom.S",
+                "arch-x86/atom/string/ssse3-strlcat-atom.S",
+                "arch-x86/atom/string/ssse3-strlcpy-atom.S",
+                "arch-x86/atom/string/ssse3-strncat-atom.S",
+                "arch-x86/atom/string/ssse3-strncmp-atom.S",
+                "arch-x86/atom/string/ssse3-wcscat-atom.S",
+                "arch-x86/atom/string/ssse3-wcscpy-atom.S",
+
+                // sse4 functions
+                "arch-x86/silvermont/string/sse4-memcmp-slm.S",
+                "arch-x86/silvermont/string/sse4-wmemcmp-slm.S",
+
+                // atom functions
+                "arch-x86/atom/string/sse2-memset-atom.S",
+                "arch-x86/atom/string/sse2-strlen-atom.S",
+                "arch-x86/atom/string/ssse3-memcmp-atom.S",
+                "arch-x86/atom/string/ssse3-memmove-atom.S",
+                "arch-x86/atom/string/ssse3-strcpy-atom.S",
+                "arch-x86/atom/string/ssse3-strncpy-atom.S",
+                "arch-x86/atom/string/ssse3-wmemcmp-atom.S",
             ],
 
             exclude_srcs: [
@@ -1167,51 +1065,6 @@
                 "bionic/strnlen.c",
                 "bionic/strrchr.cpp",
             ],
-            atom: {
-                srcs: [
-                    "arch-x86/atom/string/sse2-memset-atom.S",
-                    "arch-x86/atom/string/sse2-strlen-atom.S",
-                    "arch-x86/atom/string/ssse3-memcmp-atom.S",
-                    "arch-x86/atom/string/ssse3-memcpy-atom.S",
-                    "arch-x86/atom/string/ssse3-strcpy-atom.S",
-                    "arch-x86/atom/string/ssse3-strncpy-atom.S",
-                    "arch-x86/atom/string/ssse3-wmemcmp-atom.S",
-                ],
-                exclude_srcs: [
-                    "arch-x86/generic/string/memcmp.S",
-                    "arch-x86/silvermont/string/sse2-memmove-slm.S",
-                    "arch-x86/silvermont/string/sse2-memset-slm.S",
-                    "arch-x86/silvermont/string/sse2-strcpy-slm.S",
-                    "arch-x86/silvermont/string/sse2-strlen-slm.S",
-                    "arch-x86/silvermont/string/sse2-strncpy-slm.S",
-                ],
-            },
-            ssse3: {
-                srcs: [
-                    "arch-x86/atom/string/ssse3-strncat-atom.S",
-                    "arch-x86/atom/string/ssse3-strlcat-atom.S",
-                    "arch-x86/atom/string/ssse3-strlcpy-atom.S",
-                    "arch-x86/atom/string/ssse3-strcat-atom.S",
-                    "arch-x86/atom/string/ssse3-strcmp-atom.S",
-                    "arch-x86/atom/string/ssse3-strncmp-atom.S",
-                    "arch-x86/atom/string/ssse3-wcscat-atom.S",
-                    "arch-x86/atom/string/ssse3-wcscpy-atom.S",
-                ],
-                exclude_srcs: [
-                    "arch-x86/generic/string/strcmp.S",
-                    "arch-x86/generic/string/strncmp.S",
-                    "arch-x86/generic/string/strcat.S",
-                ],
-            },
-            sse4: {
-                srcs: [
-                    "arch-x86/silvermont/string/sse4-memcmp-slm.S",
-                    "arch-x86/silvermont/string/sse4-wmemcmp-slm.S",
-                ],
-                exclude_srcs: [
-                    "arch-x86/generic/string/memcmp.S",
-                ],
-            },
         },
         x86_64: {
             srcs: [
@@ -1597,7 +1450,7 @@
         "libc_syscalls",
         "libc_tzcode",
         "libm",
-        "libjemalloc",
+        "libjemalloc5",
         "libstdc++",
     ],
 }
@@ -1656,6 +1509,52 @@
 }
 
 // ========================================================
+// libc_common_static.a For static binaries.
+// ========================================================
+cc_library_static {
+    defaults: ["libc_defaults"],
+    name: "libc_common_static",
+
+    arch: {
+        x86: {
+            srcs: ["arch-x86/static_function_dispatch.S"],
+        },
+        arm: {
+            srcs: ["arch-arm/static_function_dispatch.S"],
+        },
+    },
+
+    whole_static_libs: [
+        "libc_common",
+    ],
+}
+
+// ========================================================
+// libc_common_shared.a For shared libraries.
+// ========================================================
+cc_library_static {
+    defaults: ["libc_defaults"],
+    name: "libc_common_shared",
+
+    cflags: [
+        "-fno-stack-protector",
+        "-fno-jump-tables",
+    ],
+    arch: {
+        x86: {
+            srcs: ["arch-x86/dynamic_function_dispatch.cpp"],
+        },
+        arm: {
+            srcs: ["arch-arm/dynamic_function_dispatch.cpp"],
+        },
+    },
+
+    whole_static_libs: [
+        "libc_common",
+    ],
+}
+
+// ========================================================
 // libc_nomalloc.a
 // ========================================================
 //
@@ -1679,7 +1578,7 @@
     cflags: ["-DLIBC_STATIC"],
 
     whole_static_libs: [
-        "libc_common",
+        "libc_common_static",
         "libc_init_static",
     ],
 }
@@ -1702,6 +1601,7 @@
     defaults: ["libc_defaults"],
     name: "libc",
     static_ndk_lib: true,
+    export_include_dirs: ["include"],
     product_variables: {
         platform_sdk_version: {
             asflags: ["-DPLATFORM_SDK_VERSION=%d"],
@@ -1713,7 +1613,10 @@
             "bionic/malloc_common.cpp",
         ],
         cflags: ["-DLIBC_STATIC"],
-        whole_static_libs: ["libc_init_static"],
+        whole_static_libs: [
+            "libc_init_static",
+            "libc_common_static",
+        ],
     },
     shared: {
         srcs: [
@@ -1724,7 +1627,10 @@
             "bionic/NetdClient.cpp",
             "arch-common/bionic/crtend_so.S",
         ],
-        whole_static_libs: ["libc_init_dynamic"],
+        whole_static_libs: [
+            "libc_init_dynamic",
+            "libc_common_shared",
+        ],
     },
 
     required: ["tzdata"],
@@ -1751,8 +1657,7 @@
         "libdl",
     ],
     whole_static_libs: [
-        "libc_common",
-        "libjemalloc",
+        "libjemalloc5",
     ],
 
     nocrt: true,
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 5c63c0f..772f0e7 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -5,7 +5,7 @@
 # return_type func_name[|alias_list][:syscall_name[:socketcall_id]]([parameter_list]) arch_list
 #
 # where:
-#       arch_list ::= "all" | arch+
+#       arch_list ::= "all" | "lp32" | "lp64" | arch+
 #       arch      ::= "arm" | "arm64" | "mips" | "mips64" | "x86" | "x86_64"
 #
 # Note:
@@ -68,11 +68,11 @@
 # On 32-bit systems we use prlimit64 to implement the rlimit64 functions.
 int getrlimit:ugetrlimit(int, struct rlimit*)  arm,x86
 int getrlimit(int, struct rlimit*)  mips
-int getrlimit|getrlimit64(int, struct rlimit*)  arm64,mips64,x86_64
-int setrlimit(int, const struct rlimit*)  arm,mips,x86
-int setrlimit|setrlimit64(int, const struct rlimit*)  arm64,mips64,x86_64
-int prlimit64|prlimit(pid_t, int, struct rlimit64*, const struct rlimit64*)  arm64,mips64,x86_64
-int prlimit64(pid_t, int, struct rlimit64*, const struct rlimit64*)  arm,mips,x86
+int getrlimit|getrlimit64(int, struct rlimit*)  lp64
+int setrlimit(int, const struct rlimit*)  lp32
+int setrlimit|setrlimit64(int, const struct rlimit*)  lp64
+int prlimit64|prlimit(pid_t, int, struct rlimit64*, const struct rlimit64*)  lp64
+int prlimit64(pid_t, int, struct rlimit64*, const struct rlimit64*)  lp32
 
 int     setgroups:setgroups32(int, const gid_t*)   arm,x86
 int     setgroups:setgroups(int, const gid_t*)     arm64,mips,mips64,x86_64
@@ -90,19 +90,19 @@
 # file descriptors
 ssize_t     read(int, void*, size_t)        all
 ssize_t     write(int, const void*, size_t)       all
-ssize_t     pread64(int, void*, size_t, off64_t) arm,mips,x86
-ssize_t     pread64|pread(int, void*, size_t, off_t) arm64,mips64,x86_64
-ssize_t     pwrite64(int, void*, size_t, off64_t) arm,mips,x86
-ssize_t     pwrite64|pwrite(int, void*, size_t, off_t) arm64,mips64,x86_64
+ssize_t     pread64(int, void*, size_t, off64_t) lp32
+ssize_t     pread64|pread(int, void*, size_t, off_t) lp64
+ssize_t     pwrite64(int, void*, size_t, off64_t) lp32
+ssize_t     pwrite64|pwrite(int, void*, size_t, off_t) lp64
 
 # On LP32, preadv/pwritev don't use off64_t --- they use pairs of 32-bit
 # arguments to avoid problems on architectures like ARM where 64-bit arguments
 # must be in a register pair starting with an even-numbered register.
 # See linux/fs/read_write.c and https://lwn.net/Articles/311630/.
-ssize_t     __preadv64:preadv(int, const struct iovec*, int, long, long) arm,mips,x86
-ssize_t     preadv|preadv64(int, const struct iovec*, int, off_t) arm64,mips64,x86_64
-ssize_t     __pwritev64:pwritev(int, const struct iovec*, int, long, long) arm,mips,x86
-ssize_t     pwritev|pwritev64(int, const struct iovec*, int, off_t) arm64,mips64,x86_64
+ssize_t     __preadv64:preadv(int, const struct iovec*, int, long, long) lp32
+ssize_t     preadv|preadv64(int, const struct iovec*, int, off_t) lp64
+ssize_t     __pwritev64:pwritev(int, const struct iovec*, int, long, long) lp32
+ssize_t     pwritev|pwritev64(int, const struct iovec*, int, off_t) lp64
 
 int         ___close:close(int)  all
 pid_t       __getpid:getpid()  all
@@ -119,8 +119,8 @@
 int         __ioctl:ioctl(int, int, void*)  all
 ssize_t     readv(int, const struct iovec*, int)   all
 ssize_t     writev(int, const struct iovec*, int)  all
-int         __fcntl64:fcntl64(int, int, void*)  arm,mips,x86
-int         fcntl(int, int, void*)  arm64,mips64,x86_64
+int         __fcntl64:fcntl64(int, int, void*)  lp32
+int         fcntl(int, int, void*)  lp64
 int         flock(int, int)   all
 int         ___fchmod:fchmod(int, mode_t)  all
 int         dup(int)  all
@@ -143,7 +143,7 @@
 int ___faccessat:faccessat(int, const char*, int)  all
 int ___fchmodat:fchmodat(int, const char*, mode_t)  all
 int fchownat(int, const char*, uid_t, gid_t, int)  all
-int fstatat64|fstatat:fstatat64(int, const char*, struct stat*, int)   arm,mips,x86
+int fstatat64|fstatat:fstatat64(int, const char*, struct stat*, int)   lp32
 int fstatat64|fstatat:newfstatat(int, const char*, struct stat*, int)  arm64,x86_64
 int linkat(int, const char*, int, const char*, int)  all
 int mkdirat(int, const char*, mode_t)  all
@@ -158,23 +158,23 @@
 # sizeof(off_t) == sizeof(off64_t), so there we emit two symbols that are
 # aliases. On 32-bit systems, we have two different system calls.
 # That means that every system call in this section should take three lines.
-off_t lseek(int, off_t, int) arm,mips,x86
-int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) arm,mips,x86
-off_t lseek|lseek64(int, off_t, int) arm64,mips64,x86_64
-int ftruncate64(int, off64_t) arm,mips,x86
-int ftruncate|ftruncate64(int, off_t) arm64,mips64,x86_64
-ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count) arm,mips,x86
-ssize_t sendfile64(int out_fd, int in_fd, off64_t* offset, size_t count) arm,mips,x86
-ssize_t sendfile|sendfile64(int out_fd, int in_fd, off_t* offset, size_t count) arm64,mips64,x86_64
-int truncate(const char*, off_t) arm,mips,x86
-int truncate64(const char*, off64_t) arm,mips,x86
-int truncate|truncate64(const char*, off_t) arm64,mips64,x86_64
+off_t lseek(int, off_t, int) lp32
+int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) lp32
+off_t lseek|lseek64(int, off_t, int) lp64
+int ftruncate64(int, off64_t) lp32
+int ftruncate|ftruncate64(int, off_t) lp64
+ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count) lp32
+ssize_t sendfile64(int out_fd, int in_fd, off64_t* offset, size_t count) lp32
+ssize_t sendfile|sendfile64(int out_fd, int in_fd, off_t* offset, size_t count) lp64
+int truncate(const char*, off_t) lp32
+int truncate64(const char*, off64_t) lp32
+int truncate|truncate64(const char*, off_t) lp64
 # (mmap only gets two lines because we only used the 64-bit variant on 32-bit systems.)
-void* __mmap2:mmap2(void*, size_t, int, int, int, long)   arm,mips,x86
-void* mmap|mmap64(void*, size_t, int, int, int, off_t)  arm64,mips64,x86_64
+void* __mmap2:mmap2(void*, size_t, int, int, int, long)   lp32
+void* mmap|mmap64(void*, size_t, int, int, int, off_t)  lp64
 # (fallocate only gets two lines because there is no 32-bit variant.)
-int fallocate64:fallocate(int, int, off64_t, off64_t) arm,mips,x86
-int fallocate|fallocate64(int, int, off_t, off_t) arm64,mips64,x86_64
+int fallocate64:fallocate(int, int, off64_t, off64_t) lp32
+int fallocate|fallocate64(int, int, off_t, off_t) lp64
 
 # posix_fadvise64 is awkward: arm has shuffled arguments,
 # the POSIX functions don't set errno, and no architecture has posix_fadvise.
@@ -182,12 +182,12 @@
 int __fadvise64:fadvise64_64(int, off64_t, off64_t, int) x86
 int __fadvise64:fadvise64(int, off64_t, off64_t, int) arm64,mips,mips64,x86_64
 
-int __fstatfs64:fstatfs64(int, size_t, struct statfs*)  arm,mips,x86
-int __fstatfs:fstatfs(int, struct statfs*)  arm64,mips64,x86_64
-int __statfs64:statfs64(const char*, size_t, struct statfs*)  arm,mips,x86
-int __statfs:statfs(const char*, struct statfs*)  arm64,mips64,x86_64
+int __fstatfs64:fstatfs64(int, size_t, struct statfs*)  lp32
+int __fstatfs:fstatfs(int, struct statfs*)  lp64
+int __statfs64:statfs64(const char*, size_t, struct statfs*)  lp32
+int __statfs:statfs(const char*, struct statfs*)  lp64
 
-int     fstat64|fstat:fstat64(int, struct stat*)    arm,mips,x86
+int     fstat64|fstat:fstat64(int, struct stat*)    lp32
 int     fstat64|fstat:fstat(int, struct stat*)    arm64,x86_64
 
 # file system
@@ -227,7 +227,7 @@
 int           clock_adjtime(clockid_t, struct timex*)   all
 
 # signals
-int     __sigaction:sigaction(int, const struct sigaction*, struct sigaction*)  arm,mips,x86
+int     __sigaction:sigaction(int, const struct sigaction*, struct sigaction*)  lp32
 int     __rt_sigaction:rt_sigaction(int, const struct sigaction*, struct sigaction*, size_t)  all
 int     __rt_sigpending:rt_sigpending(sigset64_t*, size_t)  all
 int     __rt_sigprocmask:rt_sigprocmask(int, const sigset64_t*, sigset64_t*, size_t)  all
diff --git a/libc/arch-arm/cortex-a15/bionic/memcpy.S b/libc/arch-arm/cortex-a15/bionic/memcpy.S
index 0bab6ee..a9dfaff 100644
--- a/libc/arch-arm/cortex-a15/bionic/memcpy.S
+++ b/libc/arch-arm/cortex-a15/bionic/memcpy.S
@@ -64,7 +64,7 @@
         .arch armv7-a
 
 // Prototype: void *memcpy (void *dst, const void *src, size_t count).
-ENTRY(__memcpy)
+ENTRY(__memcpy_a15)
         pld     [r1, #64]
         push    {r0, lr}
         .cfi_def_cfa_offset 8
@@ -72,4 +72,4 @@
         .cfi_rel_offset lr, 4
 
 #include "memcpy_base.S"
-END(__memcpy)
+END(__memcpy_a15)
diff --git a/libc/include/android/legacy_get_device_api_level_inlines.h b/libc/arch-arm/cortex-a15/bionic/memmove.S
similarity index 86%
copy from libc/include/android/legacy_get_device_api_level_inlines.h
copy to libc/arch-arm/cortex-a15/bionic/memmove.S
index b60123c..2b12de0 100644
--- a/libc/include/android/legacy_get_device_api_level_inlines.h
+++ b/libc/arch-arm/cortex-a15/bionic/memmove.S
@@ -26,13 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#define MEMMOVE memmove_a15
+#define MEMCPY __memcpy_a15
 
-#include <sys/cdefs.h>
-
-#if __ANDROID_API__ < __ANDROID_API_Q__
-
-#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
-#include <bits/get_device_api_level_inlines.h>
-
-#endif
+#include <arch-arm/denver/bionic/memmove.S>
diff --git a/libc/arch-arm/cortex-a15/bionic/memset.S b/libc/arch-arm/cortex-a15/bionic/memset.S
index 4b4388e..ead881e 100644
--- a/libc/arch-arm/cortex-a15/bionic/memset.S
+++ b/libc/arch-arm/cortex-a15/bionic/memset.S
@@ -41,7 +41,7 @@
         // arch. The code generated is exactly the same.
         .arch armv7-a
 
-ENTRY(__memset_chk)
+ENTRY(__memset_chk_a15)
         cmp         r2, r3
         bls         memset
 
@@ -51,9 +51,9 @@
         .cfi_rel_offset lr, 0
 
         bl          __memset_chk_fail
-END(__memset_chk)
+END(__memset_chk_a15)
 
-ENTRY(memset)
+ENTRY(memset_a15)
         stmfd       sp!, {r0}
         .cfi_def_cfa_offset 4
         .cfi_rel_offset r0, 0
@@ -171,4 +171,4 @@
         strbcs      r1, [r0], #1
         ldmfd       sp!, {r0}
         bx          lr
-END(memset)
+END(memset_a15)
diff --git a/libc/arch-arm/cortex-a15/bionic/strcat.S b/libc/arch-arm/cortex-a15/bionic/strcat.S
index 157cc9f..260926a 100644
--- a/libc/arch-arm/cortex-a15/bionic/strcat.S
+++ b/libc/arch-arm/cortex-a15/bionic/strcat.S
@@ -80,7 +80,7 @@
     \cmd    \reg, \label
     .endm // m_copy_byte
 
-ENTRY(strcat)
+ENTRY(strcat_a15)
     // Quick check to see if src is empty.
     ldrb    r2, [r1]
     pld     [r1, #0]
@@ -572,4 +572,4 @@
 .L_strcat_sub2:
     sub     r0, r0, #2
     b       .L_strcat_r0_scan_done
-END(strcat)
+END(strcat_a15)
diff --git a/libc/arch-arm/cortex-a15/bionic/strcmp.S b/libc/arch-arm/cortex-a15/bionic/strcmp.S
index d8993d5..58dbf17 100644
--- a/libc/arch-arm/cortex-a15/bionic/strcmp.S
+++ b/libc/arch-arm/cortex-a15/bionic/strcmp.S
@@ -61,7 +61,7 @@
         // arch. The code generated is exactly the same.
         .arch armv7-a
 
-ENTRY(strcmp)
+ENTRY(strcmp_a15)
       /* Use LDRD whenever possible.  */
 
 /* The main thing to look out for when comparing large blocks is that
@@ -376,4 +376,4 @@
         it      ls
         sbcls   r0, r0, r0
         bx      lr
-END(strcmp)
+END(strcmp_a15)
diff --git a/libc/arch-arm/cortex-a15/bionic/string_copy.S b/libc/arch-arm/cortex-a15/bionic/string_copy.S
index 92d1c98..affbc3b 100644
--- a/libc/arch-arm/cortex-a15/bionic/string_copy.S
+++ b/libc/arch-arm/cortex-a15/bionic/string_copy.S
@@ -100,9 +100,9 @@
     .endm // m_copy_byte
 
 #if defined(STPCPY)
-ENTRY(stpcpy)
+ENTRY(stpcpy_a15)
 #else
-ENTRY(strcpy)
+ENTRY(strcpy_a15)
 #endif
     // For short copies, hard-code checking the first 8 bytes since this
     // new code doesn't win until after about 8 bytes.
@@ -514,7 +514,7 @@
     strb    r4, [r0]
     m_pop
 #if defined(STPCPY)
-END(stpcpy)
+END(stpcpy_a15)
 #else
-END(strcpy)
+END(strcpy_a15)
 #endif
diff --git a/libc/arch-arm/cortex-a15/bionic/strlen.S b/libc/arch-arm/cortex-a15/bionic/strlen.S
index 4fd6284..9c5ed29 100644
--- a/libc/arch-arm/cortex-a15/bionic/strlen.S
+++ b/libc/arch-arm/cortex-a15/bionic/strlen.S
@@ -60,7 +60,7 @@
     .thumb
     .thumb_func
 
-ENTRY(strlen)
+ENTRY(strlen_a15)
     pld     [r0, #0]
     mov     r1, r0
 
@@ -162,4 +162,4 @@
 .L_sub2_and_return:
     sub     r0, r0, #2
     bx      lr
-END(strlen)
+END(strlen_a15)
diff --git a/libc/arch-arm/cortex-a53/bionic/memcpy.S b/libc/arch-arm/cortex-a53/bionic/memcpy.S
index 0bab6ee..ea748bd 100644
--- a/libc/arch-arm/cortex-a53/bionic/memcpy.S
+++ b/libc/arch-arm/cortex-a53/bionic/memcpy.S
@@ -64,7 +64,7 @@
         .arch armv7-a
 
 // Prototype: void *memcpy (void *dst, const void *src, size_t count).
-ENTRY(__memcpy)
+ENTRY(__memcpy_a53)
         pld     [r1, #64]
         push    {r0, lr}
         .cfi_def_cfa_offset 8
@@ -72,4 +72,4 @@
         .cfi_rel_offset lr, 4
 
 #include "memcpy_base.S"
-END(__memcpy)
+END(__memcpy_a53)
diff --git a/libc/include/android/legacy_get_device_api_level_inlines.h b/libc/arch-arm/cortex-a53/bionic/memmove.S
similarity index 86%
copy from libc/include/android/legacy_get_device_api_level_inlines.h
copy to libc/arch-arm/cortex-a53/bionic/memmove.S
index b60123c..741acb3 100644
--- a/libc/include/android/legacy_get_device_api_level_inlines.h
+++ b/libc/arch-arm/cortex-a53/bionic/memmove.S
@@ -26,13 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#define MEMMOVE memmove_a53
+#define MEMCPY __memcpy_a53
 
-#include <sys/cdefs.h>
-
-#if __ANDROID_API__ < __ANDROID_API_Q__
-
-#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
-#include <bits/get_device_api_level_inlines.h>
-
-#endif
+#include <arch-arm/denver/bionic/memmove.S>
diff --git a/libc/arch-arm/cortex-a7/bionic/memcpy.S b/libc/arch-arm/cortex-a7/bionic/memcpy.S
index 0bab6ee..2f32d2e 100644
--- a/libc/arch-arm/cortex-a7/bionic/memcpy.S
+++ b/libc/arch-arm/cortex-a7/bionic/memcpy.S
@@ -64,7 +64,7 @@
         .arch armv7-a
 
 // Prototype: void *memcpy (void *dst, const void *src, size_t count).
-ENTRY(__memcpy)
+ENTRY(__memcpy_a7)
         pld     [r1, #64]
         push    {r0, lr}
         .cfi_def_cfa_offset 8
@@ -72,4 +72,4 @@
         .cfi_rel_offset lr, 4
 
 #include "memcpy_base.S"
-END(__memcpy)
+END(__memcpy_a7)
diff --git a/libc/include/android/legacy_get_device_api_level_inlines.h b/libc/arch-arm/cortex-a7/bionic/memmove.S
similarity index 86%
copy from libc/include/android/legacy_get_device_api_level_inlines.h
copy to libc/arch-arm/cortex-a7/bionic/memmove.S
index b60123c..17ead5a 100644
--- a/libc/include/android/legacy_get_device_api_level_inlines.h
+++ b/libc/arch-arm/cortex-a7/bionic/memmove.S
@@ -26,13 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#define MEMMOVE memmove_a7
+#define MEMCPY __memcpy_a7
 
-#include <sys/cdefs.h>
-
-#if __ANDROID_API__ < __ANDROID_API_Q__
-
-#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
-#include <bits/get_device_api_level_inlines.h>
-
-#endif
+#include <arch-arm/denver/bionic/memmove.S>
diff --git a/libc/arch-arm/cortex-a7/bionic/memset.S b/libc/arch-arm/cortex-a7/bionic/memset.S
index 72ee613..d7d3b34 100644
--- a/libc/arch-arm/cortex-a7/bionic/memset.S
+++ b/libc/arch-arm/cortex-a7/bionic/memset.S
@@ -41,7 +41,7 @@
         // arch. The code generated is exactly the same.
         .arch armv7-a
 
-ENTRY(__memset_chk)
+ENTRY(__memset_chk_a7)
         cmp         r2, r3
         bls         memset
 
@@ -51,9 +51,9 @@
         .cfi_rel_offset lr, 0
 
         bl          __memset_chk_fail
-END(__memset_chk)
+END(__memset_chk_a7)
 
-ENTRY(memset)
+ENTRY(memset_a7)
         mov         r3, r0
         // At this point only d0, d1 are going to be used below.
         vdup.8      q0, r1
@@ -160,4 +160,4 @@
         strbcs      r1, [r3], #1
         strbcs      r1, [r3], #1
         bx          lr
-END(memset)
+END(memset_a7)
diff --git a/libc/arch-arm/cortex-a9/bionic/memcpy.S b/libc/arch-arm/cortex-a9/bionic/memcpy.S
index a71c9d2..e78a7da 100644
--- a/libc/arch-arm/cortex-a9/bionic/memcpy.S
+++ b/libc/arch-arm/cortex-a9/bionic/memcpy.S
@@ -39,15 +39,15 @@
         .thumb
         .thumb_func
 
-ENTRY(__memcpy)
+ENTRY(__memcpy_a9)
         pld     [r1, #0]
         stmfd   sp!, {r0, lr}
         .cfi_def_cfa_offset 8
         .cfi_rel_offset r0, 0
         .cfi_rel_offset lr, 4
         pld     [r1, #64]
-END(__memcpy)
+END(__memcpy_a9)
 
-#define MEMCPY_BASE         __memcpy_base
-#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
+#define MEMCPY_BASE         __memcpy_base_a9
+#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned_a9
 #include "memcpy_base.S"
diff --git a/libc/arch-arm/cortex-a9/bionic/memcpy_base.S b/libc/arch-arm/cortex-a9/bionic/memcpy_base.S
index 966b9b3..39da7ff 100644
--- a/libc/arch-arm/cortex-a9/bionic/memcpy_base.S
+++ b/libc/arch-arm/cortex-a9/bionic/memcpy_base.S
@@ -32,6 +32,12 @@
  * cache line.
  */
 
+        .syntax unified
+
+        // To avoid warning about deprecated instructions, add an explicit
+        // arch. The code generated is exactly the same.
+        .arch armv7-a
+
 ENTRY_PRIVATE(MEMCPY_BASE)
         .cfi_def_cfa_offset 8
         .cfi_rel_offset r0, 0
diff --git a/libc/include/android/legacy_get_device_api_level_inlines.h b/libc/arch-arm/cortex-a9/bionic/memmove.S
similarity index 86%
copy from libc/include/android/legacy_get_device_api_level_inlines.h
copy to libc/arch-arm/cortex-a9/bionic/memmove.S
index b60123c..a457633 100644
--- a/libc/include/android/legacy_get_device_api_level_inlines.h
+++ b/libc/arch-arm/cortex-a9/bionic/memmove.S
@@ -26,13 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#define MEMMOVE memmove_a9
+#define MEMCPY __memcpy_a9
 
-#include <sys/cdefs.h>
-
-#if __ANDROID_API__ < __ANDROID_API_Q__
-
-#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
-#include <bits/get_device_api_level_inlines.h>
-
-#endif
+#include <arch-arm/denver/bionic/memmove.S>
diff --git a/libc/arch-arm/cortex-a9/bionic/memset.S b/libc/arch-arm/cortex-a9/bionic/memset.S
index d00231b..cf66e86 100644
--- a/libc/arch-arm/cortex-a9/bionic/memset.S
+++ b/libc/arch-arm/cortex-a9/bionic/memset.S
@@ -36,7 +36,7 @@
     .fpu    neon
     .syntax unified
 
-ENTRY(__memset_chk)
+ENTRY(__memset_chk_a9)
         cmp         r2, r3
         bls         memset
 
@@ -46,10 +46,10 @@
         .cfi_rel_offset lr, 0
 
         bl          __memset_chk_fail
-END(__memset_chk)
+END(__memset_chk_a9)
 
 /* memset() returns its first argument.  */
-ENTRY(memset)
+ENTRY(memset_a9)
         // The neon memset only wins for less than 132.
         cmp         r2, #132
         bhi         .L_memset_large_copy
@@ -158,4 +158,4 @@
         movs        r2, r2, lsl #2
         strbcs      r1, [r0]
         ldmfd       sp!, {r0, r4-r7, pc}
-END(memset)
+END(memset_a9)
diff --git a/libc/arch-arm/cortex-a9/bionic/strcat.S b/libc/arch-arm/cortex-a9/bionic/strcat.S
index 9077a74..430748f 100644
--- a/libc/arch-arm/cortex-a9/bionic/strcat.S
+++ b/libc/arch-arm/cortex-a9/bionic/strcat.S
@@ -57,6 +57,10 @@
 
     .syntax unified
 
+    // To avoid warning about deprecated instructions, add an explicit
+    // arch. The code generated is exactly the same.
+    .arch armv7-a
+
     .thumb
     .thumb_func
 
@@ -80,7 +84,7 @@
     \cmd    \reg, \label
     .endm // m_copy_byte
 
-ENTRY(strcat)
+ENTRY(strcat_a9)
     // Quick check to see if src is empty.
     ldrb        r2, [r1]
     pld         [r1, #0]
@@ -552,4 +556,4 @@
 .Lstrcat_r0_update:
     sub     r0, r0, #1
     b .Lstrcat_r0_scan_done
-END(strcat)
+END(strcat_a9)
diff --git a/libc/arch-arm/cortex-a9/bionic/strcmp.S b/libc/arch-arm/cortex-a9/bionic/strcmp.S
index ba191d6..ba7ea13 100644
--- a/libc/arch-arm/cortex-a9/bionic/strcmp.S
+++ b/libc/arch-arm/cortex-a9/bionic/strcmp.S
@@ -52,12 +52,16 @@
 
 .syntax         unified
 
+// To avoid warning about deprecated instructions, add an explicit
+// arch. The code generated is exactly the same.
+.arch armv7-a
+
 #if defined (__thumb__)
         .thumb
         .thumb_func
 #endif
 
-ENTRY(strcmp)
+ENTRY(strcmp_a9)
       /* Use LDRD whenever possible.  */
 
 /* The main thing to look out for when comparing large blocks is that
@@ -544,4 +548,4 @@
     adds    sp, sp, #16
 
 	bx	lr
-END(strcmp)
+END(strcmp_a9)
diff --git a/libc/arch-arm/cortex-a9/bionic/string_copy.S b/libc/arch-arm/cortex-a9/bionic/string_copy.S
index 642db0f..3605b7a 100644
--- a/libc/arch-arm/cortex-a9/bionic/string_copy.S
+++ b/libc/arch-arm/cortex-a9/bionic/string_copy.S
@@ -64,6 +64,10 @@
     .thumb
     .thumb_func
 
+    // To avoid warning about deprecated instructions, add an explicit
+    // arch. The code generated is exactly the same.
+    .arch armv7-a
+
 #if defined(STPCPY)
     .macro m_push
     push    {r4, r5, lr}
@@ -100,9 +104,9 @@
     .endm // m_copy_byte
 
 #if defined(STPCPY)
-ENTRY(stpcpy)
+ENTRY(stpcpy_a9)
 #else
-ENTRY(strcpy)
+ENTRY(strcpy_a9)
 #endif
     // Unroll the first 8 bytes that will be copied.
     m_push
@@ -536,7 +540,7 @@
 #endif
     m_ret   inst=pop
 #if defined(STPCPY)
-END(stpcpy)
+END(stpcpy_a9)
 #else
-END(strcpy)
+END(strcpy_a9)
 #endif
diff --git a/libc/arch-arm/cortex-a9/bionic/strlen.S b/libc/arch-arm/cortex-a9/bionic/strlen.S
index b92b043..ffebc9d 100644
--- a/libc/arch-arm/cortex-a9/bionic/strlen.S
+++ b/libc/arch-arm/cortex-a9/bionic/strlen.S
@@ -57,10 +57,14 @@
 
     .syntax unified
 
+    // To avoid warning about deprecated instructions, add an explicit
+    // arch. The code generated is exactly the same.
+    .arch armv7-a
+
     .thumb
     .thumb_func
 
-ENTRY(strlen)
+ENTRY(strlen_a9)
     pld     [r0, #0]
     mov     r1, r0
 
@@ -164,4 +168,4 @@
     sub     r0, r1, r0
     sub     r0, r0, #1
     bx      lr
-END(strlen)
+END(strlen_a9)
diff --git a/libc/arch-arm/denver/bionic/memcpy.S b/libc/arch-arm/denver/bionic/memcpy.S
index f082542..5edee1e 100644
--- a/libc/arch-arm/denver/bionic/memcpy.S
+++ b/libc/arch-arm/denver/bionic/memcpy.S
@@ -65,14 +65,14 @@
         // arch. The code generated is exactly the same.
         .arch armv7-a
 
-ENTRY(__memcpy)
+ENTRY(__memcpy_denver)
         pld     [r1, #64]
         push    {r0, lr}
         .cfi_def_cfa_offset 8
         .cfi_rel_offset r0, 0
         .cfi_rel_offset lr, 4
-END(__memcpy)
+END(__memcpy_denver)
 
-#define MEMCPY_BASE         __memcpy_base
-#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
+#define MEMCPY_BASE         __memcpy_base_denver
+#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned_denver
 #include "memcpy_base.S"
diff --git a/libc/arch-arm/denver/bionic/memmove.S b/libc/arch-arm/denver/bionic/memmove.S
index 74d2b31..13c90ef 100644
--- a/libc/arch-arm/denver/bionic/memmove.S
+++ b/libc/arch-arm/denver/bionic/memmove.S
@@ -29,6 +29,14 @@
 
 #include <private/bionic_asm.h>
 
+#ifndef MEMMOVE
+# define MEMMOVE memmove_denver
+#endif
+
+#ifndef MEMCPY
+# define MEMCPY __memcpy_denver
+#endif
+
         .text
         .syntax unified
         .fpu    neon
@@ -40,7 +48,7 @@
 #define PREFETCH_DISTANCE_MID   (CACHE_LINE_SIZE*4)
 #define PREFETCH_DISTANCE_FAR   (CACHE_LINE_SIZE*16)
 
-ENTRY(memmove)
+ENTRY(MEMMOVE)
         cmp         r2, #0
         cmpne       r0, r1
         bxeq        lr
@@ -50,7 +58,7 @@
         bhi         .L_reversed_memcpy
 
 .L_jump_to_memcpy:
-        b           __memcpy
+        b           MEMCPY
 
 .L_reversed_memcpy:
         push        {r0, lr}
@@ -277,6 +285,4 @@
 
         pop         {r0, pc}
 
-END(memmove)
-
-ALIAS_SYMBOL(memcpy, memmove)
+END(MEMMOVE)
diff --git a/libc/arch-arm/denver/bionic/memset.S b/libc/arch-arm/denver/bionic/memset.S
index 88ffe5c..198ecf3 100644
--- a/libc/arch-arm/denver/bionic/memset.S
+++ b/libc/arch-arm/denver/bionic/memset.S
@@ -39,7 +39,7 @@
         .fpu        neon
         .syntax     unified
 
-ENTRY(__memset_chk)
+ENTRY(__memset_chk_denver)
         cmp         r2, r3
         bls         memset
 
@@ -49,9 +49,9 @@
         .cfi_rel_offset lr, 0
 
         bl          __memset_chk_fail
-END(__memset_chk)
+END(__memset_chk_denver)
 
-ENTRY(memset)
+ENTRY(memset_denver)
         pldw        [r0]
         mov         r3, r0
 
@@ -183,4 +183,4 @@
         strbcs      r1, [r3]
 2:
         bx          lr
-END(memset)
+END(memset_denver)
diff --git a/libc/arch-arm/dynamic_function_dispatch.cpp b/libc/arch-arm/dynamic_function_dispatch.cpp
new file mode 100644
index 0000000..17f0087
--- /dev/null
+++ b/libc/arch-arm/dynamic_function_dispatch.cpp
@@ -0,0 +1,267 @@
+/*
+ * 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 <sys/syscall.h>
+
+extern "C" {
+
+enum CpuVariant {
+    kUnknown = 0,
+    kGeneric,
+    kCortexA7,
+    kCortexA9,
+    kCortexA53,
+    kCortexA55,
+    kDenver,
+    kKrait,
+    kKryo,
+};
+
+static constexpr int MAX_CPU_NAME_LEN = 12;
+struct CpuVariantNames {
+    char name[MAX_CPU_NAME_LEN];
+    CpuVariant variant;
+};
+
+static constexpr CpuVariantNames cpu_variant_names[] = {
+    {"cortex-a76", kCortexA55},
+    {"cortex-a75", kCortexA55},
+    {"kryo", kKryo},
+    {"cortex-a73", kCortexA55},
+    {"cortex-a55", kCortexA55},
+    {"cortex-a53", kCortexA53},
+    {"krait", kKrait},
+    {"cortex-a9", kCortexA9},
+    {"cortex-a7", kCortexA7},
+    {"denver", kDenver},
+    // kUnknown indicates the end of this array.
+    {"", kUnknown},
+};
+
+static long ifunc_open(const char* pathname) {
+    register long r0 __asm__("r0") = AT_FDCWD;
+    register long r1 __asm__("r1") = reinterpret_cast<long>(pathname);
+    register long r2 __asm__("r2") = O_RDONLY;
+    register long r3 __asm__("r3") = 0;
+    register long r7 __asm__("r7") = __NR_openat;
+    __asm__ volatile("swi #0" : "=r"(r0) : "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r7));
+    return r0;
+}
+
+static ssize_t ifunc_read(int fd, void* buf, size_t count) {
+    register long r0 __asm__("r0") = fd;
+    register long r1 __asm__("r1") = reinterpret_cast<long>(buf);
+    register long r2 __asm__("r2") = count;
+    register long r7 __asm__("r7") = __NR_read;
+    __asm__ volatile("swi #0" : "=r"(r0) : "r"(r0), "r"(r1), "r"(r2), "r"(r7) : "memory");
+    return r0;
+}
+
+static int ifunc_close(int fd) {
+    register long r0 __asm__("r0") = fd;
+    register long r7 __asm__("r7") = __NR_close;
+    __asm__ volatile("swi #0" : "=r"(r0) : "r"(r0), "r"(r7));
+    return r0;
+}
+
+#define DEFINE_IFUNC(name) \
+    name##_func name __attribute__((ifunc(#name "_resolver"))); \
+    __attribute__((visibility("hidden"))) \
+    name##_func* name##_resolver()
+
+#define DECLARE_FUNC(type, name) \
+    __attribute__((visibility("hidden"))) \
+    type name
+
+#define RETURN_FUNC(type, name) { \
+        DECLARE_FUNC(type, name); \
+        return name; \
+    }
+
+static CpuVariant init_cpu_variant() {
+    int fd = ifunc_open("/dev/cpu_variant:arm");
+    if (fd < 0) return kGeneric;
+
+    char name[MAX_CPU_NAME_LEN];
+
+    int bytes_read, total_read = 0;
+    while (total_read < MAX_CPU_NAME_LEN - 1 &&
+           (bytes_read = ifunc_read(fd, name + total_read,
+                                    MAX_CPU_NAME_LEN - 1 - total_read)) > 0) {
+        total_read += bytes_read;
+    }
+    ifunc_close(fd);
+
+    if (bytes_read != 0) {
+        // The file is too big. We haven't reach the end. Or maybe there is an
+        // error when reading.
+        return kGeneric;
+    }
+    name[total_read] = 0;
+
+    typedef int strcmp_func(const char* __lhs, const char* __rhs);
+    DECLARE_FUNC(strcmp_func, strcmp_a15);
+
+    const CpuVariantNames* cpu_variant = cpu_variant_names;
+    while (cpu_variant->variant != kUnknown) {
+        if (strcmp_a15(cpu_variant->name, name) == 0) {
+            return cpu_variant->variant;
+        }
+        cpu_variant++;
+    }
+    return kGeneric;
+}
+
+static CpuVariant get_cpu_variant() {
+    static CpuVariant cpu_variant = kUnknown;
+    if (cpu_variant == kUnknown) {
+        cpu_variant = init_cpu_variant();
+    }
+    return cpu_variant;
+}
+
+typedef void* memmove_func(void* __dst, const void* __src, size_t __n);
+DEFINE_IFUNC(memmove) {
+    switch(get_cpu_variant()) {
+        case kCortexA7:
+            RETURN_FUNC(memmove_func, memmove_a7);
+        case kCortexA9:
+            RETURN_FUNC(memmove_func, memmove_a9);
+        case kKrait:
+            RETURN_FUNC(memmove_func, memmove_krait);
+        case kCortexA53:
+            RETURN_FUNC(memmove_func, memmove_a53);
+        case kCortexA55:
+        case kDenver:
+            RETURN_FUNC(memmove_func, memmove_denver);
+        case kKryo:
+            RETURN_FUNC(memmove_func, memmove_kryo);
+        default:
+            RETURN_FUNC(memmove_func, memmove_a15);
+    }
+}
+
+typedef void* memcpy_func(void*, const void*, size_t);
+DEFINE_IFUNC(memcpy) {
+    return memmove_resolver();
+}
+
+typedef void* __memset_chk_func(void* s, int c, size_t n, size_t n2);
+DEFINE_IFUNC(__memset_chk) {
+    switch(get_cpu_variant()) {
+        case kCortexA7:
+        case kCortexA53:
+        case kCortexA55:
+        case kKryo:
+            RETURN_FUNC(__memset_chk_func, __memset_chk_a7);
+        case kCortexA9:
+            RETURN_FUNC(__memset_chk_func, __memset_chk_a9);
+        case kKrait:
+            RETURN_FUNC(__memset_chk_func, __memset_chk_krait);
+        case kDenver:
+            RETURN_FUNC(__memset_chk_func, __memset_chk_denver);
+        default:
+            RETURN_FUNC(__memset_chk_func, __memset_chk_a15);
+    }
+}
+
+typedef void* memset_func(void* __dst, int __ch, size_t __n);
+DEFINE_IFUNC(memset) {
+    switch(get_cpu_variant()) {
+        case kCortexA7:
+        case kCortexA53:
+        case kCortexA55:
+        case kKryo:
+             RETURN_FUNC(memset_func, memset_a7);
+        case kCortexA9:
+             RETURN_FUNC(memset_func, memset_a9);
+        case kKrait:
+             RETURN_FUNC(memset_func, memset_krait);
+        case kDenver:
+             RETURN_FUNC(memset_func, memset_denver);
+        default:
+             RETURN_FUNC(memset_func, memset_a15);
+    }
+}
+
+typedef char* strcpy_func(char* __dst, const char* __src);
+DEFINE_IFUNC(strcpy) {
+    switch(get_cpu_variant()) {
+        case kCortexA9:
+            RETURN_FUNC(strcpy_func, strcpy_a9);
+        default:
+            RETURN_FUNC(strcpy_func, strcpy_a15);
+    }
+}
+
+typedef char* stpcpy_func(char* __dst, const char* __src);
+DEFINE_IFUNC(stpcpy) {
+    switch(get_cpu_variant()) {
+        case kCortexA9:
+            RETURN_FUNC(stpcpy_func, stpcpy_a9);
+        default:
+            RETURN_FUNC(stpcpy_func, stpcpy_a15);
+    }
+}
+
+typedef char* strcat_func(char* __dst, const char* __src);
+DEFINE_IFUNC(strcat) {
+    switch(get_cpu_variant()) {
+        case kCortexA9:
+            RETURN_FUNC(strcat_func, strcat_a9);
+        default:
+            RETURN_FUNC(strcat_func, strcat_a15);
+    }
+}
+
+typedef int strcmp_func(const char* __lhs, const char* __rhs);
+DEFINE_IFUNC(strcmp) {
+    switch(get_cpu_variant()) {
+        case kCortexA9:
+            RETURN_FUNC(strcmp_func, strcmp_a9);
+        case kCortexA55:
+        case kKrait:
+        case kKryo:
+            RETURN_FUNC(strcmp_func, strcmp_krait);
+        default:
+            RETURN_FUNC(strcmp_func, strcmp_a15);
+    }
+}
+
+typedef size_t strlen_func(const char* __s);
+DEFINE_IFUNC(strlen) {
+    switch(get_cpu_variant()) {
+        case kCortexA9:
+            RETURN_FUNC(strlen_func, strlen_a9);
+        default:
+            RETURN_FUNC(strlen_func, strlen_a15);
+    }
+}
+
+}  // extern "C"
diff --git a/libc/arch-arm/generic/bionic/memmove.S b/libc/arch-arm/generic/bionic/memmove.S
index c52e17e..0cf82d1 100644
--- a/libc/arch-arm/generic/bionic/memmove.S
+++ b/libc/arch-arm/generic/bionic/memmove.S
@@ -464,10 +464,8 @@
 	b	.Lmemcpy_bl4
 END(bsd_safe_memcpy)
 
-ENTRY(memmove)
+ENTRY(memmove_generic)
         stmfd   sp!, {r0, lr}
         bl      bsd_safe_memcpy
         ldmfd   sp!, {r0, pc}
-END(memmove)
-
-ALIAS_SYMBOL(memcpy, memmove)
+END(memmove_generic)
diff --git a/libc/arch-arm/generic/bionic/memset.S b/libc/arch-arm/generic/bionic/memset.S
index 1fd0de1..e70002f 100644
--- a/libc/arch-arm/generic/bionic/memset.S
+++ b/libc/arch-arm/generic/bionic/memset.S
@@ -36,14 +36,14 @@
 
          .syntax unified
 
-ENTRY(__memset_chk)
+ENTRY(__memset_chk_generic)
         cmp         r2, r3
         bls         memset
 
         bl          __memset_chk_fail
-END(__memset_chk)
+END(__memset_chk_generic)
 
-ENTRY(memset)
+ENTRY(memset_generic)
         /* compute the offset to align the destination
          * offset = (4-(src&3))&3 = -src & 3
          */
@@ -108,4 +108,4 @@
         movs        r2, r2, lsl #2
         strbcs      r1, [r0]
         ldmfd       sp!, {r0, r4-r7, pc}
-END(memset)
+END(memset_generic)
diff --git a/libc/include/android/legacy_get_device_api_level_inlines.h b/libc/arch-arm/generic/bionic/stpcpy.c
similarity index 86%
copy from libc/include/android/legacy_get_device_api_level_inlines.h
copy to libc/arch-arm/generic/bionic/stpcpy.c
index b60123c..0aabaa5 100644
--- a/libc/include/android/legacy_get_device_api_level_inlines.h
+++ b/libc/arch-arm/generic/bionic/stpcpy.c
@@ -26,13 +26,5 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
-
-#include <sys/cdefs.h>
-
-#if __ANDROID_API__ < __ANDROID_API_Q__
-
-#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
-#include <bits/get_device_api_level_inlines.h>
-
-#endif
+#define stpcpy stpcpy_generic
+#include <upstream-openbsd/lib/libc/string/stpcpy.c>
diff --git a/libc/include/android/legacy_get_device_api_level_inlines.h b/libc/arch-arm/generic/bionic/strcat.c
similarity index 86%
copy from libc/include/android/legacy_get_device_api_level_inlines.h
copy to libc/arch-arm/generic/bionic/strcat.c
index b60123c..8e70531 100644
--- a/libc/include/android/legacy_get_device_api_level_inlines.h
+++ b/libc/arch-arm/generic/bionic/strcat.c
@@ -26,13 +26,5 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
-
-#include <sys/cdefs.h>
-
-#if __ANDROID_API__ < __ANDROID_API_Q__
-
-#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
-#include <bits/get_device_api_level_inlines.h>
-
-#endif
+#define strcat strcat_generic
+#include <upstream-openbsd/lib/libc/string/strcat.c>
diff --git a/libc/arch-arm/generic/bionic/strcmp.S b/libc/arch-arm/generic/bionic/strcmp.S
index 10b6704..03225a0 100644
--- a/libc/arch-arm/generic/bionic/strcmp.S
+++ b/libc/arch-arm/generic/bionic/strcmp.S
@@ -31,6 +31,10 @@
 
 	.text
 
+        // To avoid warning about deprecated instructions, add an explicit
+        // arch. The code generated is exactly the same.
+        .arch armv7-a
+
 #ifdef __ARMEB__
 #define SHFT2LSB lsl
 #define SHFT2LSBEQ lsleq
@@ -50,7 +54,7 @@
 #define magic1(REG) REG
 #define magic2(REG) REG, lsl #7
 
-ENTRY(strcmp)
+ENTRY(strcmp_generic)
 	pld	[r0, #0]
 	pld	[r1, #0]
 	eor	r2, r0, r1
@@ -313,4 +317,4 @@
 	ldr	r4, [sp], #4
 	ldr	r5, [sp], #4
 	bx	lr
-END(strcmp)
+END(strcmp_generic)
diff --git a/libc/arch-arm/generic/bionic/strcpy.S b/libc/arch-arm/generic/bionic/strcpy.S
index c0ab9e5..89bd699 100644
--- a/libc/arch-arm/generic/bionic/strcpy.S
+++ b/libc/arch-arm/generic/bionic/strcpy.S
@@ -33,7 +33,11 @@
 
 .syntax unified
 
-ENTRY(strcpy)
+// To avoid warning about deprecated instructions, add an explicit
+// arch. The code generated is exactly the same.
+.arch armv7-a
+
+ENTRY(strcpy_generic)
 	pld	[r1, #0]
 	eor	r2, r0, r1
 	mov	ip, r0
@@ -131,4 +135,4 @@
 	cmp	r2, #0
 	bne	4b
 	bx	lr
-END(strcpy)
+END(strcpy_generic)
diff --git a/libc/arch-arm/generic/bionic/strlen.c b/libc/arch-arm/generic/bionic/strlen.c
index 44bd72f..43d9e51 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)
+size_t strlen_generic(const char *s)
 {
     __builtin_prefetch(s);
     __builtin_prefetch(s+32);
diff --git a/libc/arch-arm/krait/bionic/memcpy.S b/libc/arch-arm/krait/bionic/memcpy.S
index 49fd040..6618b3a 100644
--- a/libc/arch-arm/krait/bionic/memcpy.S
+++ b/libc/arch-arm/krait/bionic/memcpy.S
@@ -42,7 +42,7 @@
         .thumb
         .thumb_func
 
-ENTRY(__memcpy)
+ENTRY(__memcpy_krait)
         pld     [r1, #64]
         stmfd   sp!, {r0, lr}
         .cfi_adjust_cfa_offset 8
@@ -50,4 +50,4 @@
         .cfi_rel_offset lr, 4
 
 #include "memcpy_base.S"
-END(__memcpy)
+END(__memcpy_krait)
diff --git a/libc/arch-arm/krait/bionic/memcpy_base.S b/libc/arch-arm/krait/bionic/memcpy_base.S
index dc8ad2c..5b4b70d 100644
--- a/libc/arch-arm/krait/bionic/memcpy_base.S
+++ b/libc/arch-arm/krait/bionic/memcpy_base.S
@@ -41,8 +41,13 @@
 #endif
 
 	.text
+	.syntax unified
 	.fpu    neon
 
+	// To avoid warning about deprecated instructions, add an explicit
+	// arch. The code generated is exactly the same.
+	.arch armv7-a
+
 .L_memcpy_base:
 	cmp	r2, #4
 	blt	.L_neon_lt4
diff --git a/libc/include/android/legacy_get_device_api_level_inlines.h b/libc/arch-arm/krait/bionic/memmove.S
similarity index 86%
copy from libc/include/android/legacy_get_device_api_level_inlines.h
copy to libc/arch-arm/krait/bionic/memmove.S
index b60123c..af85ea6 100644
--- a/libc/include/android/legacy_get_device_api_level_inlines.h
+++ b/libc/arch-arm/krait/bionic/memmove.S
@@ -26,13 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#define MEMMOVE memmove_krait
+#define MEMCPY __memcpy_krait
 
-#include <sys/cdefs.h>
-
-#if __ANDROID_API__ < __ANDROID_API_Q__
-
-#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
-#include <bits/get_device_api_level_inlines.h>
-
-#endif
+#include <arch-arm/denver/bionic/memmove.S>
diff --git a/libc/arch-arm/krait/bionic/memset.S b/libc/arch-arm/krait/bionic/memset.S
index 228942c..675ab53 100644
--- a/libc/arch-arm/krait/bionic/memset.S
+++ b/libc/arch-arm/krait/bionic/memset.S
@@ -37,7 +37,7 @@
     .fpu    neon
     .syntax unified
 
-ENTRY(__memset_chk)
+ENTRY(__memset_chk_krait)
         cmp         r2, r3
         bls         memset
 
@@ -47,10 +47,10 @@
         .cfi_rel_offset lr, 0
 
         bl          __memset_chk_fail
-END(__memset_chk)
+END(__memset_chk_krait)
 
 /* memset() returns its first argument.  */
-ENTRY(memset)
+ENTRY(memset_krait)
         mov         r3, r0
         vdup.8      q0, r1
 
@@ -82,4 +82,4 @@
         strbcs      r1, [r3], #1
         strbcs      r1, [r3], #1
         bx          lr
-END(memset)
+END(memset_krait)
diff --git a/libc/arch-arm/krait/bionic/strcmp.S b/libc/arch-arm/krait/bionic/strcmp.S
index b871c76..ec692e5 100644
--- a/libc/arch-arm/krait/bionic/strcmp.S
+++ b/libc/arch-arm/krait/bionic/strcmp.S
@@ -52,12 +52,16 @@
 
 .syntax         unified
 
+// To avoid warning about deprecated instructions, add an explicit
+// arch. The code generated is exactly the same.
+.arch armv7-a
+
 #if defined (__thumb__)
         .thumb
         .thumb_func
 #endif
 
-ENTRY(strcmp)
+ENTRY(strcmp_krait)
       /* Use LDRD whenever possible.  */
 
 /* The main thing to look out for when comparing large blocks is that
@@ -482,4 +486,4 @@
     .cfi_restore r7
 
 	bx	lr
-END(strcmp)
+END(strcmp_krait)
diff --git a/libc/arch-arm/kryo/bionic/memcpy.S b/libc/arch-arm/kryo/bionic/memcpy.S
index 74036ef..250f7bc 100644
--- a/libc/arch-arm/kryo/bionic/memcpy.S
+++ b/libc/arch-arm/kryo/bionic/memcpy.S
@@ -33,8 +33,14 @@
 #define PLDOFFS (16)
 #define PLDSIZE (128) /* L2 cache line size */
 
+        .syntax unified
+
+        // To avoid warning about deprecated instructions, add an explicit
+        // arch. The code generated is exactly the same.
+        .arch armv7-a
+
         .code 32
-ENTRY(__memcpy)
+ENTRY(__memcpy_kryo)
         push            {r0}
         .cfi_def_cfa_offset 4
         .cfi_rel_offset r0, 0
@@ -123,4 +129,4 @@
         pop             {r0}
         bx              lr
 
-END(__memcpy)
+END(__memcpy_kryo)
diff --git a/libc/include/android/legacy_get_device_api_level_inlines.h b/libc/arch-arm/kryo/bionic/memmove.S
similarity index 86%
copy from libc/include/android/legacy_get_device_api_level_inlines.h
copy to libc/arch-arm/kryo/bionic/memmove.S
index b60123c..d0fdd8f 100644
--- a/libc/include/android/legacy_get_device_api_level_inlines.h
+++ b/libc/arch-arm/kryo/bionic/memmove.S
@@ -26,13 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#define MEMMOVE memmove_kryo
+#define MEMCPY __memcpy_kryo
 
-#include <sys/cdefs.h>
-
-#if __ANDROID_API__ < __ANDROID_API_Q__
-
-#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
-#include <bits/get_device_api_level_inlines.h>
-
-#endif
+#include <arch-arm/denver/bionic/memmove.S>
diff --git a/libc/include/android/legacy_get_device_api_level_inlines.h b/libc/arch-arm/static_function_dispatch.S
similarity index 72%
copy from libc/include/android/legacy_get_device_api_level_inlines.h
copy to libc/arch-arm/static_function_dispatch.S
index b60123c..f3dd741 100644
--- a/libc/include/android/legacy_get_device_api_level_inlines.h
+++ b/libc/arch-arm/static_function_dispatch.S
@@ -26,13 +26,19 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#include <private/bionic_asm.h>
 
-#include <sys/cdefs.h>
+#define FUNCTION_DELEGATE(name, impl) \
+ENTRY(name); \
+    b impl; \
+END(name)
 
-#if __ANDROID_API__ < __ANDROID_API_Q__
-
-#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
-#include <bits/get_device_api_level_inlines.h>
-
-#endif
+FUNCTION_DELEGATE(memmove, memmove_generic)
+FUNCTION_DELEGATE(memcpy, memmove_generic)
+FUNCTION_DELEGATE(memset, memset_generic)
+FUNCTION_DELEGATE(__memset_chk, __memset_chk_generic)
+FUNCTION_DELEGATE(strcpy, strcpy_generic)
+FUNCTION_DELEGATE(stpcpy, stpcpy_generic)
+FUNCTION_DELEGATE(strcat, strcat_generic)
+FUNCTION_DELEGATE(strcmp, strcmp_generic)
+FUNCTION_DELEGATE(strlen, strlen_generic)
diff --git a/libc/arch-arm64/bionic/setjmp.S b/libc/arch-arm64/bionic/setjmp.S
index 5e62c28..a2b2370 100644
--- a/libc/arch-arm64/bionic/setjmp.S
+++ b/libc/arch-arm64/bionic/setjmp.S
@@ -27,6 +27,7 @@
  */
 
 #include <private/bionic_asm.h>
+#include <private/bionic_constants.h>
 
 // According to AARCH64 PCS document we need to save the following
 // registers:
@@ -44,10 +45,12 @@
 // word   name            description
 // 0      sigflag/cookie  setjmp cookie in top 31 bits, signal mask flag in low bit
 // 1      sigmask         signal mask (not used with _setjmp / _longjmp)
-// 2      core_base       base of core registers (x19-x30, sp)
-// 15     float_base      base of float registers (d8-d15)
-// 23     checksum        checksum of core registers
-// 24     reserved        reserved entries (room to grow)
+// 2      core_base       base of core registers (x18-x30, sp)
+//                        (We only store the low bits of x18 to avoid leaking the
+//                        shadow call stack address into memory.)
+// 16     float_base      base of float registers (d8-d15)
+// 24     checksum        checksum of core registers
+// 25     reserved        reserved entries (room to grow)
 // 32
 
 #define _JB_SIGFLAG     0
@@ -58,18 +61,20 @@
 #define _JB_X24_X25     (_JB_X26_X27 + 2)
 #define _JB_X22_X23     (_JB_X24_X25 + 2)
 #define _JB_X20_X21     (_JB_X22_X23 + 2)
-#define _JB_X19         (_JB_X20_X21 + 2)
-#define _JB_D14_D15     (_JB_X19 + 1)
+#define _JB_SCS_X19     (_JB_X20_X21 + 2)
+#define _JB_D14_D15     (_JB_SCS_X19 + 2)
 #define _JB_D12_D13     (_JB_D14_D15 + 2)
 #define _JB_D10_D11     (_JB_D12_D13 + 2)
 #define _JB_D8_D9       (_JB_D10_D11 + 2)
 #define _JB_CHECKSUM    (_JB_D8_D9 + 2)
 
+#define SCS_MASK (SCS_SIZE - 1)
 #define MANGLE_REGISTERS 1
 #define USE_CHECKSUM 1
 
 .macro m_mangle_registers reg, sp_reg
 #if MANGLE_REGISTERS
+  eor x3, x3, \reg
   eor x19, x19, \reg
   eor x20, x20, \reg
   eor x21, x21, \reg
@@ -88,7 +93,7 @@
 
 .macro m_calculate_checksum dst, src, scratch
   mov \dst, #0
-  .irp i,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22
+  .irp i,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23
     ldr \scratch, [\src, #(\i * 8)]
     eor \dst, \dst, \scratch
   .endr
@@ -151,6 +156,9 @@
   // Mask off the signal flag bit.
   bic x1, x1, #1
 
+  // Mask off the high bits of the shadow call stack pointer.
+  and x3, x18, #SCS_MASK
+
   // Save core registers.
   mov x10, sp
   m_mangle_registers x1, sp_reg=x10
@@ -160,7 +168,7 @@
   stp x24, x25, [x0, #(_JB_X24_X25 * 8)]
   stp x22, x23, [x0, #(_JB_X22_X23 * 8)]
   stp x20, x21, [x0, #(_JB_X20_X21 * 8)]
-  str x19,      [x0, #(_JB_X19     * 8)]
+  stp x3,  x19, [x0, #(_JB_SCS_X19 * 8)]
   m_unmangle_registers x1, sp_reg=x10
 
   // Save floating point registers.
@@ -248,10 +256,14 @@
   ldp x24, x25, [x0, #(_JB_X24_X25 * 8)]
   ldp x22, x23, [x0, #(_JB_X22_X23 * 8)]
   ldp x20, x21, [x0, #(_JB_X20_X21 * 8)]
-  ldr x19,      [x0, #(_JB_X19     * 8)]
+  ldp x3,  x19, [x0, #(_JB_SCS_X19 * 8)]
   m_unmangle_registers x2, sp_reg=x10
   mov sp, x10
 
+  // Restore the low bits of the shadow call stack pointer.
+  and x18, x18, #~SCS_MASK
+  orr x18, x3, x18
+
   stp x0, x1, [sp, #-16]!
   .cfi_adjust_cfa_offset 16
   .cfi_rel_offset x0, 0
diff --git a/libc/arch-x86/atom/string/sse2-memset-atom.S b/libc/arch-x86/atom/string/sse2-memset-atom.S
index 4e211ca..016c49e 100644
--- a/libc/arch-x86/atom/string/sse2-memset-atom.S
+++ b/libc/arch-x86/atom/string/sse2-memset-atom.S
@@ -86,7 +86,7 @@
 	movl	(%esp), %ebx
 	ret
 
-ENTRY(__memset_chk)
+ENTRY(__memset_chk_atom)
   ENTRANCE
 
   movl LEN(%esp), %ecx
@@ -95,11 +95,11 @@
 
   POP(%ebx) // Undo ENTRANCE without returning.
   jmp __memset_chk_fail
-END(__memset_chk)
+END(__memset_chk_atom)
 
 	.section .text.sse2,"ax",@progbits
 	ALIGN(4)
-ENTRY(memset)
+ENTRY(memset_atom)
 	ENTRANCE
 
 	movl	LEN(%esp), %ecx
@@ -839,4 +839,4 @@
 	SETRTNVAL
 	RETURN_END
 
-END(memset)
+END(memset_atom)
diff --git a/libc/arch-x86/atom/string/sse2-strlen-atom.S b/libc/arch-x86/atom/string/sse2-strlen-atom.S
index 81768fb..6a1acfb 100644
--- a/libc/arch-x86/atom/string/sse2-strlen-atom.S
+++ b/libc/arch-x86/atom/string/sse2-strlen-atom.S
@@ -31,7 +31,7 @@
 #ifndef USE_AS_STRCAT
 
 # ifndef STRLEN
-#  define STRLEN strlen
+#  define STRLEN strlen_atom
 # endif
 
 # ifndef L
diff --git a/libc/arch-x86/atom/string/ssse3-memcmp-atom.S b/libc/arch-x86/atom/string/ssse3-memcmp-atom.S
index 0387084..be2c4f6 100644
--- a/libc/arch-x86/atom/string/ssse3-memcmp-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-memcmp-atom.S
@@ -76,7 +76,7 @@
 #endif
 
 #ifndef MEMCMP
-# define MEMCMP	memcmp
+# define MEMCMP	memcmp_atom
 #endif
 
 #define CFI_PUSH(REG)	\
diff --git a/libc/arch-x86/atom/string/ssse3-memcpy-atom.S b/libc/arch-x86/atom/string/ssse3-memcpy-atom.S
index 2b3b7a5..5532e2e 100644
--- a/libc/arch-x86/atom/string/ssse3-memcpy-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-memcpy-atom.S
@@ -31,11 +31,7 @@
 #include "cache.h"
 
 #ifndef MEMCPY
-# define MEMCPY	memcpy
-#endif
-
-#ifndef USE_AS_MEMMOVE
-# define USE_AS_MEMMOVE
+# define MEMCPY	memcpy_atom
 #endif
 
 #ifndef L
@@ -71,12 +67,6 @@
 	cfi_startproc
 #endif
 
-#ifndef ALIAS_SYMBOL
-# define ALIAS_SYMBOL(alias, original) \
-	.globl alias; \
-	.equ alias, original
-#endif
-
 #ifndef END
 # define END(name)		\
 	cfi_endproc;		\
@@ -3132,5 +3122,3 @@
 #endif
 
 END (MEMCPY)
-
-ALIAS_SYMBOL(memmove, MEMCPY)
diff --git a/libc/arch-x86/atom/string/ssse3-memmove-atom.S b/libc/arch-x86/atom/string/ssse3-memmove-atom.S
new file mode 100644
index 0000000..3572eac
--- /dev/null
+++ b/libc/arch-x86/atom/string/ssse3-memmove-atom.S
@@ -0,0 +1,34 @@
+/*
+Copyright (c) 2010, Intel Corporation
+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.
+
+    * Neither the name of Intel Corporation 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 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.
+*/
+
+
+#define MEMCPY memmove_atom
+#define USE_AS_MEMMOVE
+#include "ssse3-memcpy-atom.S"
diff --git a/libc/arch-x86/atom/string/ssse3-strcat-atom.S b/libc/arch-x86/atom/string/ssse3-strcat-atom.S
index d9b6129..8d8e89d 100644
--- a/libc/arch-x86/atom/string/ssse3-strcat-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-strcat-atom.S
@@ -87,7 +87,7 @@
 #define POP(REG)	popl REG; CFI_POP (REG)
 
 #ifndef STRCAT
-# define STRCAT	strcat
+# define STRCAT	strcat_ssse3
 #endif
 
 #define PARMS	4
@@ -617,4 +617,4 @@
 	RETURN1
 
 #endif
-END (STRCAT)
+END (STRCAT_ssse3)
diff --git a/libc/arch-x86/atom/string/ssse3-strcmp-atom.S b/libc/arch-x86/atom/string/ssse3-strcmp-atom.S
index ee253b9..08f6d4a 100644
--- a/libc/arch-x86/atom/string/ssse3-strcmp-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-strcmp-atom.S
@@ -108,7 +108,7 @@
 #endif
 
 #ifndef STRCMP
-# define STRCMP strcmp
+# define STRCMP strcmp_ssse3
 #endif
 
 	.section .text.ssse3,"ax",@progbits
diff --git a/libc/arch-x86/atom/string/ssse3-strcpy-atom.S b/libc/arch-x86/atom/string/ssse3-strcpy-atom.S
index 3690b0d..45b0c02 100644
--- a/libc/arch-x86/atom/string/ssse3-strcpy-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-strcpy-atom.S
@@ -81,7 +81,7 @@
 # define POP(REG)	popl REG; CFI_POP (REG)
 
 # ifndef STRCPY
-#  define STRCPY  strcpy
+#  define STRCPY  strcpy_atom
 # endif
 
 # ifdef USE_AS_STRNCPY
diff --git a/libc/arch-x86/atom/string/ssse3-strlcat-atom.S b/libc/arch-x86/atom/string/ssse3-strlcat-atom.S
index daaf254..055b489 100644
--- a/libc/arch-x86/atom/string/ssse3-strlcat-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-strlcat-atom.S
@@ -82,7 +82,7 @@
 #define LEN	SRC+4
 
 	.text
-ENTRY (strlcat)
+ENTRY (strlcat_ssse3)
 	mov	DST(%esp), %edx
 	PUSH	(%ebx)
 	mov	LEN(%esp), %ebx
diff --git a/libc/arch-x86/atom/string/ssse3-strlcpy-atom.S b/libc/arch-x86/atom/string/ssse3-strlcpy-atom.S
index cdb17cc..1671da6 100644
--- a/libc/arch-x86/atom/string/ssse3-strlcpy-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-strlcpy-atom.S
@@ -29,8 +29,8 @@
 */
 
 #define USE_AS_STRNCPY
-#define STRCPY strlcpy
-#define STRLEN strlcpy
+#define STRCPY strlcpy_ssse3
+#define STRLEN strlcpy_ssse3
 #define USE_AS_STRLCPY
 #include "ssse3-strcpy-atom.S"
 
diff --git a/libc/arch-x86/atom/string/ssse3-strncat-atom.S b/libc/arch-x86/atom/string/ssse3-strncat-atom.S
index 5618771..ccb08a7 100644
--- a/libc/arch-x86/atom/string/ssse3-strncat-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-strncat-atom.S
@@ -28,7 +28,7 @@
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#define STRCAT  strncat
+#define STRCAT  strncat_ssse3
 #define USE_AS_STRNCAT
 
 #include "ssse3-strcat-atom.S"
diff --git a/libc/arch-x86/atom/string/ssse3-strncmp-atom.S b/libc/arch-x86/atom/string/ssse3-strncmp-atom.S
index 4762d7e..2bf5002 100644
--- a/libc/arch-x86/atom/string/ssse3-strncmp-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-strncmp-atom.S
@@ -30,6 +30,6 @@
 
 
 #define USE_AS_STRNCMP
-#define STRCMP  strncmp
+#define STRCMP  strncmp_ssse3
 #include "ssse3-strcmp-atom.S"
 
diff --git a/libc/arch-x86/atom/string/ssse3-strncpy-atom.S b/libc/arch-x86/atom/string/ssse3-strncpy-atom.S
index 0948b6d..0c27ffe 100644
--- a/libc/arch-x86/atom/string/ssse3-strncpy-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-strncpy-atom.S
@@ -29,5 +29,5 @@
 */
 
 #define USE_AS_STRNCPY
-#define STRCPY strncpy
+#define STRCPY strncpy_atom
 #include "ssse3-strcpy-atom.S"
diff --git a/libc/arch-x86/atom/string/ssse3-wcscat-atom.S b/libc/arch-x86/atom/string/ssse3-wcscat-atom.S
index 8a389a3..a307983 100644
--- a/libc/arch-x86/atom/string/ssse3-wcscat-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-wcscat-atom.S
@@ -85,7 +85,7 @@
 #define USE_AS_WCSCAT
 
 .text
-ENTRY (wcscat)
+ENTRY (wcscat_ssse3)
 	PUSH    (%edi)
 	mov	STR1(%esp), %edi
 	mov	%edi, %edx
@@ -111,4 +111,4 @@
 #define RETURN  POP(%edi);	ret;	CFI_PUSH(%edi)
 #include "ssse3-wcscpy-atom.S"
 
-END (wcscat)
+END (wcscat_ssse3)
diff --git a/libc/arch-x86/atom/string/ssse3-wcscpy-atom.S b/libc/arch-x86/atom/string/ssse3-wcscpy-atom.S
index 27cb61e..80aa15f 100644
--- a/libc/arch-x86/atom/string/ssse3-wcscpy-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-wcscpy-atom.S
@@ -88,7 +88,7 @@
 # define LEN	STR2+4
 
 .text
-ENTRY (wcscpy)
+ENTRY (wcscpy_ssse3)
 	mov	STR1(%esp), %edx
 	mov	STR2(%esp), %ecx
 
@@ -648,5 +648,5 @@
 	ret
 
 #ifndef USE_AS_WCSCAT
-END (wcscpy)
+END (wcscpy_ssse3)
 #endif
diff --git a/libc/arch-x86/atom/string/ssse3-wmemcmp-atom.S b/libc/arch-x86/atom/string/ssse3-wmemcmp-atom.S
index 2c3fa02..a81b78b 100644
--- a/libc/arch-x86/atom/string/ssse3-wmemcmp-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-wmemcmp-atom.S
@@ -28,7 +28,7 @@
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#define MEMCMP  wmemcmp
+#define MEMCMP  wmemcmp_atom
 
 #define USE_WCHAR
 #define USE_AS_WMEMCMP 1
diff --git a/libc/arch-x86/dynamic_function_dispatch.cpp b/libc/arch-x86/dynamic_function_dispatch.cpp
new file mode 100644
index 0000000..6624385
--- /dev/null
+++ b/libc/arch-x86/dynamic_function_dispatch.cpp
@@ -0,0 +1,193 @@
+/*
+ * 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 <stddef.h>
+
+extern "C" {
+
+struct __processor_model {
+    unsigned int __cpu_vendor;
+    unsigned int __cpu_type;
+    unsigned int __cpu_subtype;
+    unsigned int __cpu_features[1];
+};
+
+__attribute__((visibility("hidden")))
+extern struct __processor_model __cpu_model;
+
+// These definitions have to match the values in
+// llvm/include/llvm/Support/X86TargetParser.def
+static constexpr int SSSE3  = 6;
+static constexpr int SSE4_1 = 7;
+static constexpr int ATOM   = 1;
+
+// __builtin_cpu_supports and __builtin_cpu_is can not be used here. They
+// don't access __cpu_model directly but use GOT.
+// See https://reviews.llvm.org/D53850
+static bool cpu_supports(unsigned int feature) {
+    return (__cpu_model.__cpu_features[0] & (1U << feature)) != 0;
+}
+
+static bool cpu_is(unsigned int type) {
+    return (__cpu_model.__cpu_type == type);
+}
+
+#define DEFINE_IFUNC_FOR(name) \
+    name##_func name __attribute__((ifunc(#name "_resolver"))); \
+    __attribute__((visibility("hidden"))) \
+    name##_func* name##_resolver()
+
+#define DECLARE_FUNC(type, name) \
+    __attribute__((visibility("hidden"))) \
+    type name
+
+#define RETURN_FUNC(type, name) { \
+        DECLARE_FUNC(type, name); \
+        return name; \
+    }
+
+typedef int memcmp_func(const void* __lhs, const void* __rhs, size_t __n);
+DEFINE_IFUNC_FOR(memcmp) {
+    __builtin_cpu_init();
+    if (cpu_is(ATOM)) RETURN_FUNC(memcmp_func, memcmp_atom);
+    if (cpu_supports(SSE4_1)) RETURN_FUNC(memcmp_func, memcmp_sse4);
+    RETURN_FUNC(memcmp_func, memcmp_generic);
+}
+
+typedef void* memset_func(void* __dst, int __ch, size_t __n);
+DEFINE_IFUNC_FOR(memset) {
+    __builtin_cpu_init();
+    if (cpu_is(ATOM)) RETURN_FUNC(memset_func, memset_atom);
+    RETURN_FUNC(memset_func, memset_generic);
+}
+
+typedef void* __memset_chk_func(void *s, int c, size_t n, size_t n2);
+DEFINE_IFUNC_FOR(__memset_chk) {
+    __builtin_cpu_init();
+    if (cpu_is(ATOM)) RETURN_FUNC(__memset_chk_func, __memset_chk_atom);
+    RETURN_FUNC(__memset_chk_func, __memset_chk_generic);
+}
+
+typedef void* memmove_func(void* __dst, const void* __src, size_t __n);
+DEFINE_IFUNC_FOR(memmove) {
+    __builtin_cpu_init();
+    if (cpu_is(ATOM)) RETURN_FUNC(memmove_func, memmove_atom);
+    RETURN_FUNC(memmove_func, memmove_generic);
+}
+
+typedef void* memcpy_func(void*, const void*, size_t);
+DEFINE_IFUNC_FOR(memcpy) {
+    return memmove_resolver();
+}
+
+typedef char* strcpy_func(char* __dst, const char* __src);
+DEFINE_IFUNC_FOR(strcpy) {
+    __builtin_cpu_init();
+    if (cpu_is(ATOM)) RETURN_FUNC(strcpy_func, strcpy_atom);
+    RETURN_FUNC(strcpy_func, strcpy_generic);
+}
+
+typedef char* strncpy_func(char* __dst, const char* __src, size_t __n);
+DEFINE_IFUNC_FOR(strncpy) {
+    __builtin_cpu_init();
+    if (cpu_is(ATOM)) RETURN_FUNC(strncpy_func, strncpy_atom);
+    RETURN_FUNC(strncpy_func, strncpy_generic);
+}
+
+typedef size_t strlen_func(const char* __s);
+DEFINE_IFUNC_FOR(strlen) {
+    __builtin_cpu_init();
+    if (cpu_is(ATOM)) RETURN_FUNC(strlen_func, strlen_atom);
+    RETURN_FUNC(strlen_func, strlen_generic);
+}
+
+typedef int wmemcmp_func(const wchar_t* __lhs, const wchar_t* __rhs, size_t __n);
+DEFINE_IFUNC_FOR(wmemcmp) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSE4_1)) RETURN_FUNC(wmemcmp_func, wmemcmp_sse4);
+    if (cpu_is(ATOM)) RETURN_FUNC(wmemcmp_func, wmemcmp_atom);
+    RETURN_FUNC(wmemcmp_func, wmemcmp_freebsd);
+}
+
+typedef int strcmp_func(const char* __lhs, const char* __rhs);
+DEFINE_IFUNC_FOR(strcmp) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSSE3)) RETURN_FUNC(strcmp_func, strcmp_ssse3);
+    RETURN_FUNC(strcmp_func, strcmp_generic);
+}
+
+typedef int strncmp_func(const char* __lhs, const char* __rhs, size_t __n);
+DEFINE_IFUNC_FOR(strncmp) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSSE3)) RETURN_FUNC(strncmp_func, strncmp_ssse3);
+    RETURN_FUNC(strncmp_func, strncmp_generic);
+}
+
+typedef char* strcat_func(char* __dst, const char* __src);
+DEFINE_IFUNC_FOR(strcat) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSSE3)) RETURN_FUNC(strcat_func, strcat_ssse3);
+    RETURN_FUNC(strcat_func, strcat_generic);
+}
+
+typedef char* strncat_func(char* __dst, const char* __src, size_t __n);
+DEFINE_IFUNC_FOR(strncat) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSSE3)) RETURN_FUNC(strncat_func, strncat_ssse3);
+    RETURN_FUNC(strncat_func, strncat_openbsd);
+}
+
+typedef size_t strlcat_func(char *dst, const char *src, size_t dsize);
+DEFINE_IFUNC_FOR(strlcat) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSSE3)) RETURN_FUNC(strlcat_func, strlcat_ssse3);
+    RETURN_FUNC(strlcat_func, strlcat_openbsd);
+}
+
+typedef size_t strlcpy_func(char *dst, const char *src, size_t dsize);
+DEFINE_IFUNC_FOR(strlcpy) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSSE3)) RETURN_FUNC(strlcpy_func, strlcpy_ssse3);
+    RETURN_FUNC(strlcpy_func, strlcpy_openbsd);
+}
+
+typedef wchar_t* wcscat_func(wchar_t *s1, const wchar_t *s2);
+DEFINE_IFUNC_FOR(wcscat) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSSE3)) RETURN_FUNC(wcscat_func, wcscat_ssse3);
+    RETURN_FUNC(wcscat_func, wcscat_freebsd);
+}
+
+typedef wchar_t* wcscpy_func(wchar_t *s1, const wchar_t *s2);
+DEFINE_IFUNC_FOR(wcscpy) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSSE3)) RETURN_FUNC(wcscpy_func, wcscpy_ssse3);
+    RETURN_FUNC(wcscpy_func, wcscpy_freebsd);
+}
+
+}  // extern "C"
diff --git a/libc/arch-x86/generic/string/memcmp.S b/libc/arch-x86/generic/string/memcmp.S
index ef36b4f..1d327c7 100644
--- a/libc/arch-x86/generic/string/memcmp.S
+++ b/libc/arch-x86/generic/string/memcmp.S
@@ -6,7 +6,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(memcmp)
+ENTRY(memcmp_generic)
 	pushl	%edi
 	pushl	%esi
 	movl	12(%esp),%edi
@@ -41,4 +41,4 @@
 	popl	%esi
 	popl	%edi
 	ret
-END(memcmp)
+END(memcmp_generic)
diff --git a/libc/arch-x86/generic/string/strcat.S b/libc/arch-x86/generic/string/strcat.S
index 49e8eee..e2e9623 100644
--- a/libc/arch-x86/generic/string/strcat.S
+++ b/libc/arch-x86/generic/string/strcat.S
@@ -19,7 +19,7 @@
  * cache.
  */
 
-ENTRY(strcat)
+ENTRY(strcat_generic)
 	pushl	%edi			/* save edi */
 	movl	8(%esp),%edi		/* dst address */
 	movl	12(%esp),%edx		/* src address */
@@ -71,4 +71,4 @@
 L2:	popl	%eax			/* pop destination address */
 	popl	%edi			/* restore edi */
 	ret
-END(strcat)
+END(strcat_generic)
diff --git a/libc/arch-x86/generic/string/strcmp.S b/libc/arch-x86/generic/string/strcmp.S
index 580f4d5..7b003e8 100644
--- a/libc/arch-x86/generic/string/strcmp.S
+++ b/libc/arch-x86/generic/string/strcmp.S
@@ -12,7 +12,7 @@
  * cache.
  */
 
-ENTRY(strcmp)
+ENTRY(strcmp_generic)
 	movl	0x04(%esp),%eax
 	movl	0x08(%esp),%edx
 	jmp	L2			/* Jump into the loop! */
@@ -79,4 +79,4 @@
 	movzbl	(%edx),%edx
 	subl	%edx,%eax
 	ret
-END(strcmp)
+END(strcmp_generic)
diff --git a/libc/include/android/legacy_get_device_api_level_inlines.h b/libc/arch-x86/generic/string/strlcat.c
similarity index 86%
copy from libc/include/android/legacy_get_device_api_level_inlines.h
copy to libc/arch-x86/generic/string/strlcat.c
index b60123c..95c34a3 100644
--- a/libc/include/android/legacy_get_device_api_level_inlines.h
+++ b/libc/arch-x86/generic/string/strlcat.c
@@ -26,13 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#include <upstream-openbsd/android/include/openbsd-compat.h>
 
-#include <sys/cdefs.h>
-
-#if __ANDROID_API__ < __ANDROID_API_Q__
-
-#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
-#include <bits/get_device_api_level_inlines.h>
-
-#endif
+#define strlcat strlcat_openbsd
+#include <upstream-openbsd/lib/libc/string/strlcat.c>
diff --git a/libc/include/android/legacy_get_device_api_level_inlines.h b/libc/arch-x86/generic/string/strlcpy.c
similarity index 86%
copy from libc/include/android/legacy_get_device_api_level_inlines.h
copy to libc/arch-x86/generic/string/strlcpy.c
index b60123c..8d4047c 100644
--- a/libc/include/android/legacy_get_device_api_level_inlines.h
+++ b/libc/arch-x86/generic/string/strlcpy.c
@@ -26,13 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#include <upstream-openbsd/android/include/openbsd-compat.h>
 
-#include <sys/cdefs.h>
-
-#if __ANDROID_API__ < __ANDROID_API_Q__
-
-#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
-#include <bits/get_device_api_level_inlines.h>
-
-#endif
+#define strlcpy strlcpy_openbsd
+#include <upstream-openbsd/lib/libc/string/strlcpy.c>
diff --git a/libc/include/android/legacy_get_device_api_level_inlines.h b/libc/arch-x86/generic/string/strncat.c
similarity index 86%
copy from libc/include/android/legacy_get_device_api_level_inlines.h
copy to libc/arch-x86/generic/string/strncat.c
index b60123c..687e560 100644
--- a/libc/include/android/legacy_get_device_api_level_inlines.h
+++ b/libc/arch-x86/generic/string/strncat.c
@@ -26,13 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#include <upstream-openbsd/android/include/openbsd-compat.h>
 
-#include <sys/cdefs.h>
-
-#if __ANDROID_API__ < __ANDROID_API_Q__
-
-#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
-#include <bits/get_device_api_level_inlines.h>
-
-#endif
+#define strncat strncat_openbsd
+#include <upstream-openbsd/lib/libc/string/strncat.c>
diff --git a/libc/arch-x86/generic/string/strncmp.S b/libc/arch-x86/generic/string/strncmp.S
index 9ba83a1..6d9f23c 100644
--- a/libc/arch-x86/generic/string/strncmp.S
+++ b/libc/arch-x86/generic/string/strncmp.S
@@ -12,7 +12,7 @@
  * cache.
  */
 
-ENTRY(strncmp)
+ENTRY(strncmp_generic)
 	pushl	%ebx
 	movl	8(%esp),%eax
 	movl	12(%esp),%ecx
@@ -111,4 +111,4 @@
 L4:	xorl	%eax,%eax
 	popl	%ebx
 	ret
-END(strncmp)
+END(strncmp_generic)
diff --git a/libc/include/android/legacy_get_device_api_level_inlines.h b/libc/arch-x86/generic/string/wcscat.c
similarity index 86%
copy from libc/include/android/legacy_get_device_api_level_inlines.h
copy to libc/arch-x86/generic/string/wcscat.c
index b60123c..a102551 100644
--- a/libc/include/android/legacy_get_device_api_level_inlines.h
+++ b/libc/arch-x86/generic/string/wcscat.c
@@ -26,13 +26,5 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
-
-#include <sys/cdefs.h>
-
-#if __ANDROID_API__ < __ANDROID_API_Q__
-
-#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
-#include <bits/get_device_api_level_inlines.h>
-
-#endif
+#define wcscat wcscat_freebsd
+#include <upstream-freebsd/lib/libc/string/wcscat.c>
diff --git a/libc/include/android/legacy_get_device_api_level_inlines.h b/libc/arch-x86/generic/string/wcscpy.c
similarity index 86%
copy from libc/include/android/legacy_get_device_api_level_inlines.h
copy to libc/arch-x86/generic/string/wcscpy.c
index b60123c..10fb66d 100644
--- a/libc/include/android/legacy_get_device_api_level_inlines.h
+++ b/libc/arch-x86/generic/string/wcscpy.c
@@ -26,13 +26,5 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
-
-#include <sys/cdefs.h>
-
-#if __ANDROID_API__ < __ANDROID_API_Q__
-
-#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
-#include <bits/get_device_api_level_inlines.h>
-
-#endif
+#define wcscpy wcscpy_freebsd
+#include <upstream-freebsd/lib/libc/string/wcscpy.c>
diff --git a/libc/include/android/legacy_get_device_api_level_inlines.h b/libc/arch-x86/generic/string/wmemcmp.c
similarity index 86%
rename from libc/include/android/legacy_get_device_api_level_inlines.h
rename to libc/arch-x86/generic/string/wmemcmp.c
index b60123c..9d5e929 100644
--- a/libc/include/android/legacy_get_device_api_level_inlines.h
+++ b/libc/arch-x86/generic/string/wmemcmp.c
@@ -26,13 +26,5 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
-
-#include <sys/cdefs.h>
-
-#if __ANDROID_API__ < __ANDROID_API_Q__
-
-#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
-#include <bits/get_device_api_level_inlines.h>
-
-#endif
+#define wmemcmp wmemcmp_freebsd
+#include <upstream-freebsd/lib/libc/string/wmemcmp.c>
diff --git a/libc/arch-x86/silvermont/string/sse2-memmove-slm.S b/libc/arch-x86/silvermont/string/sse2-memmove-slm.S
index ceada1b..da6456c 100644
--- a/libc/arch-x86/silvermont/string/sse2-memmove-slm.S
+++ b/libc/arch-x86/silvermont/string/sse2-memmove-slm.S
@@ -31,7 +31,7 @@
 #include "cache.h"
 
 #ifndef MEMMOVE
-# define MEMMOVE	memmove
+# define MEMMOVE	memmove_generic
 #endif
 
 #ifndef L
@@ -67,12 +67,6 @@
 	cfi_startproc
 #endif
 
-#ifndef ALIAS_SYMBOL
-# define ALIAS_SYMBOL(alias, original) \
-	.globl alias; \
-	.equ alias, original
-#endif
-
 #ifndef END
 # define END(name)		\
 	cfi_endproc;		\
@@ -543,5 +537,3 @@
 	jmp	L(mm_recalc_len)
 
 END (MEMMOVE)
-
-ALIAS_SYMBOL(memcpy, MEMMOVE)
diff --git a/libc/arch-x86/silvermont/string/sse2-memset-slm.S b/libc/arch-x86/silvermont/string/sse2-memset-slm.S
index 03a552d..adaccae 100644
--- a/libc/arch-x86/silvermont/string/sse2-memset-slm.S
+++ b/libc/arch-x86/silvermont/string/sse2-memset-slm.S
@@ -86,7 +86,7 @@
 	movl	(%esp), %ebx
 	ret
 
-ENTRY(__memset_chk)
+ENTRY(__memset_chk_generic)
   ENTRANCE
 
   movl LEN(%esp), %ecx
@@ -95,11 +95,11 @@
 
   POP(%ebx) // Undo ENTRANCE without returning.
   jmp __memset_chk_fail
-END(__memset_chk)
+END(__memset_chk_generic)
 
 	.section .text.sse2,"ax",@progbits
 	ALIGN(4)
-ENTRY(memset)
+ENTRY(memset_generic)
 	ENTRANCE
 
 	movl	LEN(%esp), %ecx
@@ -758,4 +758,4 @@
 	SETRTNVAL
 	RETURN_END
 
-END(memset)
+END(memset_generic)
diff --git a/libc/arch-x86/silvermont/string/sse2-strcpy-slm.S b/libc/arch-x86/silvermont/string/sse2-strcpy-slm.S
index b5d84b5..22ceeab 100755
--- a/libc/arch-x86/silvermont/string/sse2-strcpy-slm.S
+++ b/libc/arch-x86/silvermont/string/sse2-strcpy-slm.S
@@ -79,7 +79,7 @@
 #define POP(REG) popl REG; CFI_POP (REG)
 
 #ifndef STRCPY
-# define STRCPY  strcpy
+# define STRCPY  strcpy_generic
 #endif
 
 #ifdef USE_AS_STPNCPY
diff --git a/libc/arch-x86/silvermont/string/sse2-strlen-slm.S b/libc/arch-x86/silvermont/string/sse2-strlen-slm.S
index 27cc025..b805ad6 100755
--- a/libc/arch-x86/silvermont/string/sse2-strlen-slm.S
+++ b/libc/arch-x86/silvermont/string/sse2-strlen-slm.S
@@ -29,7 +29,7 @@
 */
 
 #ifndef STRLEN
-# define STRLEN strlen
+# define STRLEN strlen_generic
 #endif
 
 #ifndef L
diff --git a/libc/arch-x86/silvermont/string/sse2-strncpy-slm.S b/libc/arch-x86/silvermont/string/sse2-strncpy-slm.S
index 591419f..aff7fb9 100755
--- a/libc/arch-x86/silvermont/string/sse2-strncpy-slm.S
+++ b/libc/arch-x86/silvermont/string/sse2-strncpy-slm.S
@@ -29,5 +29,5 @@
 */

 

 #define USE_AS_STRNCPY

-#define STRCPY strncpy

+#define STRCPY strncpy_generic

 #include "sse2-strcpy-slm.S"

diff --git a/libc/arch-x86/silvermont/string/sse4-memcmp-slm.S b/libc/arch-x86/silvermont/string/sse4-memcmp-slm.S
index e5028ff..f151168 100755
--- a/libc/arch-x86/silvermont/string/sse4-memcmp-slm.S
+++ b/libc/arch-x86/silvermont/string/sse4-memcmp-slm.S
@@ -76,7 +76,7 @@
 #endif
 
 #ifndef MEMCMP
-# define MEMCMP	memcmp
+# define MEMCMP	memcmp_sse4
 #endif
 
 #define CFI_PUSH(REG)	\
diff --git a/libc/arch-x86/silvermont/string/sse4-wmemcmp-slm.S b/libc/arch-x86/silvermont/string/sse4-wmemcmp-slm.S
index 2c350bb..2bf92f5 100755
--- a/libc/arch-x86/silvermont/string/sse4-wmemcmp-slm.S
+++ b/libc/arch-x86/silvermont/string/sse4-wmemcmp-slm.S
@@ -29,5 +29,5 @@
 */
 
 #define USE_AS_WMEMCMP
-#define MEMCMP wmemcmp
+#define MEMCMP wmemcmp_sse4
 #include "sse4-memcmp-slm.S"
diff --git a/libc/include/android/get_device_api_level.h b/libc/arch-x86/static_function_dispatch.S
similarity index 61%
rename from libc/include/android/get_device_api_level.h
rename to libc/arch-x86/static_function_dispatch.S
index 39609da..7e8e63d 100644
--- a/libc/include/android/get_device_api_level.h
+++ b/libc/arch-x86/static_function_dispatch.S
@@ -26,29 +26,27 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#include <private/bionic_asm.h>
 
-/**
- * @file android/get_device_api_level.h
- * @brief Check the API level of the device we're actually running on.
- */
+#define FUNCTION_DELEGATE(name, impl) \
+ENTRY(name); \
+    jmp impl; \
+END(name)
 
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-
-#if __ANDROID_API__ >= __ANDROID_API_Q__
-// This file is implemented as static inlines before API level 29.
-
-/**
- * Returns the API level of the device we're actually running on, or -1 on failure.
- * The returned values correspond to the named constants in <android/api-level.h>,
- * and is equivalent to the Java `Build.VERSION.SDK_INT` API.
- */
-int android_get_device_api_level() __INTRODUCED_IN(29);
-
-#endif
-
-__END_DECLS
-
-#include <android/legacy_get_device_api_level_inlines.h>
+FUNCTION_DELEGATE(memcmp, memcmp_generic)
+FUNCTION_DELEGATE(memset, memset_generic)
+FUNCTION_DELEGATE(__memset_chk, __memset_chk_generic)
+FUNCTION_DELEGATE(memcpy, memmove_generic)
+FUNCTION_DELEGATE(memmove, memmove_generic)
+FUNCTION_DELEGATE(strcpy, strcpy_generic)
+FUNCTION_DELEGATE(strncpy, strncpy_generic)
+FUNCTION_DELEGATE(strlen, strlen_generic)
+FUNCTION_DELEGATE(strcmp, strcmp_generic)
+FUNCTION_DELEGATE(strncmp, strncmp_generic)
+FUNCTION_DELEGATE(strcat, strcat_generic)
+FUNCTION_DELEGATE(wmemcmp, wmemcmp_freebsd)
+FUNCTION_DELEGATE(wcscat, wcscat_freebsd)
+FUNCTION_DELEGATE(strncat, strncat_openbsd)
+FUNCTION_DELEGATE(strlcat, strlcat_openbsd)
+FUNCTION_DELEGATE(strlcpy, strlcpy_openbsd)
+FUNCTION_DELEGATE(wcscpy, wcscpy_freebsd)
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
index 758b295..be9d32e 100644
--- a/libc/bionic/__libc_init_main_thread.cpp
+++ b/libc/bionic/__libc_init_main_thread.cpp
@@ -101,5 +101,5 @@
 
   __init_thread(&main_thread);
 
-  __init_alternate_signal_stack(&main_thread);
+  __init_additional_stacks(&main_thread);
 }
diff --git a/libc/bionic/grp_pwd_file.h b/libc/bionic/grp_pwd_file.h
index 29d75f4..9004c4e 100644
--- a/libc/bionic/grp_pwd_file.h
+++ b/libc/bionic/grp_pwd_file.h
@@ -45,7 +45,7 @@
   bool FindByName(const char* name, Line* line);
   void Unmap();
 
-  DISALLOW_COPY_AND_ASSIGN(MmapFile);
+  BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(MmapFile);
 
  private:
   enum class FileStatus {
@@ -78,7 +78,7 @@
     mmap_file_.Unmap();
   }
 
-  DISALLOW_COPY_AND_ASSIGN(PasswdFile);
+  BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(PasswdFile);
 
  private:
   MmapFile mmap_file_;
@@ -94,7 +94,7 @@
     mmap_file_.Unmap();
   }
 
-  DISALLOW_COPY_AND_ASSIGN(GroupFile);
+  BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(GroupFile);
 
  private:
   MmapFile mmap_file_;
diff --git a/libc/bionic/jemalloc_wrapper.cpp b/libc/bionic/jemalloc_wrapper.cpp
index 40f2a66..ef0d384 100644
--- a/libc/bionic/jemalloc_wrapper.cpp
+++ b/libc/bionic/jemalloc_wrapper.cpp
@@ -52,11 +52,11 @@
   // The only parameter we currently understand is M_DECAY_TIME.
   if (param == M_DECAY_TIME) {
     // Only support setting the value to 1 or 0.
-    ssize_t decay_time;
+    ssize_t decay_time_ms;
     if (value) {
-      decay_time = 1;
+      decay_time_ms = 1000;
     } else {
-      decay_time = 0;
+      decay_time_ms = 0;
     }
     // First get the total number of arenas.
     unsigned narenas;
@@ -66,15 +66,22 @@
     }
 
     // Set the decay time for any arenas that will be created in the future.
-    if (je_mallctl("arenas.decay_time", nullptr, nullptr, &decay_time, sizeof(decay_time)) != 0) {
+    if (je_mallctl("arenas.dirty_decay_ms", nullptr, nullptr, &decay_time_ms, sizeof(decay_time_ms)) != 0) {
+      return 0;
+    }
+    if (je_mallctl("arenas.muzzy_decay_ms", nullptr, nullptr, &decay_time_ms, sizeof(decay_time_ms)) != 0) {
       return 0;
     }
 
     // Change the decay on the already existing arenas.
     char buffer[100];
     for (unsigned i = 0; i < narenas; i++) {
-      snprintf(buffer, sizeof(buffer), "arena.%d.decay_time", i);
-      if (je_mallctl(buffer, nullptr, nullptr, &decay_time, sizeof(decay_time)) != 0) {
+      snprintf(buffer, sizeof(buffer), "arena.%d.dirty_decay_ms", i);
+      if (je_mallctl(buffer, nullptr, nullptr, &decay_time_ms, sizeof(decay_time_ms)) != 0) {
+        break;
+      }
+      snprintf(buffer, sizeof(buffer), "arena.%d.muzzy_decay_ms", i);
+      if (je_mallctl(buffer, nullptr, nullptr, &decay_time_ms, sizeof(decay_time_ms)) != 0) {
         break;
       }
     }
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index f943402..a860b98 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -62,13 +62,9 @@
 const char* __progname;
 
 void __libc_init_globals(KernelArgumentBlock& args) {
-#if defined(__i386__)
-  __libc_init_sysinfo(args);
-#endif
   // Initialize libc globals that are needed in both the linker and in libc.
   // In dynamic binaries, this is run at least twice for different copies of the
   // globals, once for the linker's copy and once for the one in libc.so.
-  __libc_auxv = args.auxv;
   __libc_globals.initialize();
   __libc_globals.mutate([&args](libc_globals* globals) {
     __libc_init_vdso(globals, args);
@@ -275,7 +271,6 @@
 }
 
 static void __sanitize_environment_variables(char** env) {
-  bool is_AT_SECURE = getauxval(AT_SECURE);
   char** src = env;
   char** dst = env;
   for (; src[0] != nullptr; ++src) {
@@ -283,7 +278,7 @@
       continue;
     }
     // Remove various unsafe environment variables if we're loading a setuid program.
-    if (is_AT_SECURE && __is_unsafe_environment_variable(src[0])) {
+    if (__is_unsafe_environment_variable(src[0])) {
       continue;
     }
     dst[0] = src[0];
@@ -306,20 +301,14 @@
 }
 
 void __libc_init_AT_SECURE(KernelArgumentBlock& args) {
-  __libc_auxv = args.auxv;
   __abort_message_ptr = args.abort_message_ptr;
 
   // Check that the kernel provided a value for AT_SECURE.
-  bool found_AT_SECURE = false;
-  for (ElfW(auxv_t)* v = __libc_auxv; v->a_type != AT_NULL; ++v) {
-    if (v->a_type == AT_SECURE) {
-      found_AT_SECURE = true;
-      break;
-    }
-  }
-  if (!found_AT_SECURE) __early_abort(__LINE__);
+  errno = 0;
+  unsigned long is_AT_SECURE = getauxval(AT_SECURE);
+  if (errno != 0) __early_abort(__LINE__);
 
-  if (getauxval(AT_SECURE)) {
+  if (is_AT_SECURE) {
     // If this is a setuid/setgid program, close the security hole described in
     // https://www.freebsd.org/security/advisories/FreeBSD-SA-02:23.stdio.asc
     __nullify_closed_stdio();
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 5f76354..08d3df4 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -51,6 +51,7 @@
 #include <elf.h>
 #include "libc_init_common.h"
 
+#include "private/bionic_auxv.h"
 #include "private/bionic_globals.h"
 #include "private/bionic_macros.h"
 #include "private/bionic_ssp.h"
@@ -78,8 +79,12 @@
 // protector.
 __attribute__((noinline))
 static void __libc_preinit_impl(KernelArgumentBlock& args) {
-  __libc_shared_globals = args.shared_globals;
+  __libc_auxv = args.auxv;
+#if defined(__i386__)
+  __libc_init_sysinfo(args);
+#endif
 
+  __libc_shared_globals = args.shared_globals;
   __libc_init_globals(args);
   __libc_init_common(args);
 
@@ -137,9 +142,3 @@
                  args.argv + __libc_shared_globals->initial_linker_arg_count,
                  args.envp));
 }
-
-extern "C" uint32_t android_get_application_target_sdk_version();
-
-uint32_t bionic_get_application_target_sdk_version() {
-  return android_get_application_target_sdk_version();
-}
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index 38a04f8..ef1c393 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -146,16 +146,12 @@
   __real_libc_init(raw_args, onexit, slingshot, structors);
 }
 
-static uint32_t g_target_sdk_version{__ANDROID_API__};
+static int g_target_sdk_version{__ANDROID_API__};
 
-extern "C" uint32_t android_get_application_target_sdk_version() {
+extern "C" int android_get_application_target_sdk_version() {
   return g_target_sdk_version;
 }
 
-uint32_t bionic_get_application_target_sdk_version() {
-  return android_get_application_target_sdk_version();
-}
-
-extern "C" void android_set_application_target_sdk_version(uint32_t target) {
+extern "C" void android_set_application_target_sdk_version(int target) {
   g_target_sdk_version = target;
 }
diff --git a/libc/bionic/locale.cpp b/libc/bionic/locale.cpp
index 2a5bcab..8358fb0 100644
--- a/libc/bionic/locale.cpp
+++ b/libc/bionic/locale.cpp
@@ -66,7 +66,7 @@
     }
   }
 
-  DISALLOW_COPY_AND_ASSIGN(__locale_t);
+  BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(__locale_t);
 };
 
 size_t __ctype_get_mb_cur_max() {
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 61b3f33..9a80767 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -271,6 +271,7 @@
 
 static const char* HEAPPROFD_SHARED_LIB = "heapprofd_client.so";
 static const char* HEAPPROFD_PREFIX = "heapprofd";
+static const char* HEAPPROFD_PROPERTY_ENABLE = "heapprofd.enable";
 static const int HEAPPROFD_SIGNAL = __SIGRTMIN + 4;
 
 enum FunctionEnum : uint8_t {
@@ -365,12 +366,6 @@
 }
 
 static bool InitMallocFunctions(void* impl_handler, MallocDispatch* table, const char* prefix) {
-  // We initialize free first to prevent the following situation:
-  // Heapprofd's MallocMalloc is installed, and an allocation is observed
-  // and logged to the heap dump. The corresponding free happens before
-  // heapprofd's MallocFree is installed, and is not logged in the heap
-  // dump. This leads to the allocation wrongly being active in the heap
-  // dump indefinitely.
   if (!InitMallocFunction<MallocFree>(impl_handler, &table->free, prefix, "free")) {
     return false;
   }
@@ -469,6 +464,39 @@
   return true;
 }
 
+static bool CheckLoadHeapprofd() {
+  // First check for heapprofd.enable. If it is set to "all", enable
+  // heapprofd for all processes. Otherwise, check heapprofd.enable.${prog},
+  // if it is set and not 0, enable heap profiling for this process.
+  char property_value[PROP_VALUE_MAX];
+  if (__system_property_get(HEAPPROFD_PROPERTY_ENABLE, property_value) == 0) {
+    return false;
+  }
+  if (strcmp(property_value, "all") == 0) {
+    return true;
+  }
+
+  char program_property[128];
+  int ret = snprintf(program_property, sizeof(program_property), "%s.%s",
+                     HEAPPROFD_PROPERTY_ENABLE, getprogname());
+
+  if (ret < 0 || static_cast<size_t>(ret) >= sizeof(program_property)) {
+    if (ret < 0) {
+      error_log("Failed to concatenate heapprofd property %s.%s: %s",
+                HEAPPROFD_PROPERTY_ENABLE, getprogname(), strerror(errno));
+    } else {
+      error_log("Overflow in concatenating heapprofd property");
+    }
+    return false;
+  }
+
+  if (__system_property_get(program_property, property_value) == 0) {
+    return false;
+  }
+
+  return program_property[0] != '\0';
+}
+
 static void ClearGlobalFunctions() {
   for (size_t i = 0; i < FUNC_LAST; i++) {
     g_functions[i] = nullptr;
@@ -511,21 +539,43 @@
   return impl_handle;
 }
 
+// A function pointer to heapprofds init function. Used to re-initialize
+// heapprofd. This will start a new profiling session and tear down the old
+// one in case it is still active.
+static _Atomic init_func_t g_heapprofd_init_func = nullptr;
+
 static void install_hooks(libc_globals* globals, const char* options,
                           const char* prefix, const char* shared_lib) {
+  init_func_t init_func = atomic_load(&g_heapprofd_init_func);
+  if (init_func != nullptr) {
+    init_func(&__libc_malloc_default_dispatch, &gMallocLeakZygoteChild, options);
+    info_log("%s: malloc %s re-enabled", getprogname(), prefix);
+    return;
+  }
+
   MallocDispatch dispatch_table;
   void* impl_handle = LoadSharedLibrary(shared_lib, prefix, &dispatch_table);
   if (impl_handle == nullptr) {
     return;
   }
-
-  init_func_t init_func = reinterpret_cast<init_func_t>(g_functions[FUNC_INITIALIZE]);
+  init_func = reinterpret_cast<init_func_t>(g_functions[FUNC_INITIALIZE]);
   if (!init_func(&__libc_malloc_default_dispatch, &gMallocLeakZygoteChild, options)) {
     dlclose(impl_handle);
     ClearGlobalFunctions();
     return;
   }
 
+  atomic_store(&g_heapprofd_init_func, init_func);
+  // We assign free  first explicitly to prevent the case where we observe a
+  // alloc, but miss the corresponding free because of initialization order.
+  //
+  // This is safer than relying on the declaration order inside
+  // MallocDispatch at the cost of an extra atomic pointer write on
+  // initialization.
+  atomic_store(&globals->malloc_dispatch.free, dispatch_table.free);
+  // The struct gets assigned elementwise and each of the elements is an
+  // _Atomic. Assigning to an _Atomic is an atomic_store operation.
+  // The assignment is done in declaration order.
   globals->malloc_dispatch = dispatch_table;
 
   info_log("%s: malloc %s enabled", getprogname(), prefix);
@@ -560,6 +610,9 @@
   } else if (CheckLoadMallocHooks(&options)) {
     prefix = "hooks";
     shared_lib = HOOKS_SHARED_LIB;
+  } else if (CheckLoadHeapprofd()) {
+    prefix = "heapprofd";
+    shared_lib = HEAPPROFD_SHARED_LIB;
   } else {
     return;
   }
@@ -574,13 +627,22 @@
 
 // The logic for triggering heapprofd below is as following.
 // 1. HEAPPROFD_SIGNAL is received by the process.
-// 2a. If the signal is currently being handled (g_heapprofd_init_in_progress
+// 2. If neither InitHeapprofd nor InitHeapprofdHook are currently installed
+//    (g_heapprofd_init_hook_installed is false), InitHeapprofdHook is
+//    installed and g_heapprofd_init_in_progress is set to true.
+//
+// On the next subsequent malloc, InitHeapprofdHook is called and
+// 3a. If the signal is currently being handled (g_heapprofd_init_in_progress
 //     is true), no action is taken.
-// 2b. Otherwise, The signal handler (InstallInitHeapprofdHook) installs a
+// 3b. Otherwise, The signal handler (InstallInitHeapprofdHook) installs a
 //     temporary malloc hook (InitHeapprofdHook).
-// 3. When this hook gets run the first time, it uninstalls itself and spawns
+// 4. When this hook gets run the first time, it uninstalls itself and spawns
 //    a thread running InitHeapprofd that loads heapprofd.so and installs the
 //    hooks within.
+// 5. g_heapprofd_init_in_progress and g_heapprofd_init_hook_installed are
+//    reset to false so heapprofd can be reinitialized. Reinitialization
+//    means that a new profiling session is started and any still active is
+//    torn down.
 //
 // This roundabout way is needed because we are running non AS-safe code, so
 // we cannot run it directly in the signal handler. The other approach of
@@ -588,18 +650,21 @@
 // significantly increase the number of active threads in the system.
 
 static _Atomic bool g_heapprofd_init_in_progress = false;
-static _Atomic bool g_init_heapprofd_ran = false;
+static _Atomic bool g_heapprofd_init_hook_installed = false;
 
 static void* InitHeapprofd(void*) {
   __libc_globals.mutate([](libc_globals* globals) {
     install_hooks(globals, nullptr, HEAPPROFD_PREFIX, HEAPPROFD_SHARED_LIB);
   });
   atomic_store(&g_heapprofd_init_in_progress, false);
+  // Allow to install hook again to re-initialize heap profiling after the
+  // current session finished.
+  atomic_store(&g_heapprofd_init_hook_installed, false);
   return nullptr;
 }
 
 static void* InitHeapprofdHook(size_t bytes) {
-  if (!atomic_exchange(&g_init_heapprofd_ran, true)) {
+  if (!atomic_exchange(&g_heapprofd_init_hook_installed, true)) {
     __libc_globals.mutate([](libc_globals* globals) {
       atomic_store(&globals->malloc_dispatch.malloc, nullptr);
     });
@@ -618,7 +683,7 @@
 extern "C" void InstallInitHeapprofdHook(int) {
   if (!atomic_exchange(&g_heapprofd_init_in_progress, true)) {
     __libc_globals.mutate([](libc_globals* globals) {
-      globals->malloc_dispatch.malloc = InitHeapprofdHook;
+      atomic_store(&globals->malloc_dispatch.malloc, InitHeapprofdHook);
     });
   }
 }
diff --git a/libc/bionic/malloc_info.cpp b/libc/bionic/malloc_info.cpp
index 99caedb..9c8a4bf 100644
--- a/libc/bionic/malloc_info.cpp
+++ b/libc/bionic/malloc_info.cpp
@@ -53,7 +53,7 @@
   FILE* fp;
   const char* name;
 
-  DISALLOW_COPY_AND_ASSIGN(Elem);
+  BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(Elem);
 };
 
 int malloc_info(int options, FILE* fp) {
diff --git a/libc/bionic/pthread_atfork.cpp b/libc/bionic/pthread_atfork.cpp
index 84e511c..fb12a3b 100644
--- a/libc/bionic/pthread_atfork.cpp
+++ b/libc/bionic/pthread_atfork.cpp
@@ -107,7 +107,7 @@
   atfork_t* first_;
   atfork_t* last_;
 
-  DISALLOW_COPY_AND_ASSIGN(atfork_list_t);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(atfork_list_t);
 };
 
 static pthread_mutex_t g_atfork_list_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
@@ -180,4 +180,3 @@
   });
   pthread_mutex_unlock(&g_atfork_list_mutex);
 }
-
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 543fdc5..6f632e8 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -32,12 +32,14 @@
 #include <string.h>
 #include <sys/mman.h>
 #include <sys/prctl.h>
+#include <sys/random.h>
 #include <unistd.h>
 
 #include "pthread_internal.h"
 
 #include <async_safe/log.h>
 
+#include "private/bionic_constants.h"
 #include "private/bionic_defs.h"
 #include "private/bionic_macros.h"
 #include "private/bionic_ssp.h"
@@ -86,7 +88,7 @@
   thread->tls[TLS_SLOT_STACK_GUARD] = reinterpret_cast<void*>(__stack_chk_guard);
 }
 
-void __init_alternate_signal_stack(pthread_internal_t* thread) {
+static void __init_alternate_signal_stack(pthread_internal_t* thread) {
   // Create and set an alternate signal stack.
   void* stack_base = mmap(nullptr, SIGNAL_STACK_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
   if (stack_base != MAP_FAILED) {
@@ -109,6 +111,30 @@
   }
 }
 
+static void __init_shadow_call_stack(pthread_internal_t* thread __unused) {
+#ifdef __aarch64__
+  // Allocate the stack and store its address in register x18. The address is aligned to SCS_SIZE so
+  // that we only need to store the lower log2(SCS_SIZE) bits in jmp_buf.
+  // TODO(pcc): We ought to allocate a larger guard region here and then allocate the SCS at a
+  // random location within it. This will provide greater security since it would mean that an
+  // attacker who can read the pthread_internal_t won't be able to discover the address of the SCS.
+  // However, doing so is blocked on a solution to b/118642754.
+  char* scs_guard_region = reinterpret_cast<char*>(
+      mmap(nullptr, SCS_GUARD_REGION_SIZE, 0, MAP_PRIVATE | MAP_ANON, -1, 0));
+  thread->shadow_call_stack_guard_region = scs_guard_region;
+
+  char* scs =
+      reinterpret_cast<char*>(align_up(reinterpret_cast<uintptr_t>(scs_guard_region), SCS_SIZE));
+  mprotect(scs, SCS_SIZE, PROT_READ | PROT_WRITE);
+  __asm__ __volatile__("mov x18, %0" ::"r"(scs));
+#endif
+}
+
+void __init_additional_stacks(pthread_internal_t* thread) {
+  __init_alternate_signal_stack(thread);
+  __init_shadow_call_stack(thread);
+}
+
 int __init_thread(pthread_internal_t* thread) {
   thread->cleanup_stack = nullptr;
 
@@ -252,7 +278,7 @@
   // accesses previously made by the creating thread are visible to us.
   thread->startup_handshake_lock.lock();
 
-  __init_alternate_signal_stack(thread);
+  __init_additional_stacks(thread);
 
   void* result = thread->start_routine(thread->start_routine_arg);
   pthread_exit(result);
diff --git a/libc/bionic/pthread_exit.cpp b/libc/bionic/pthread_exit.cpp
index 220f7a0..2d4d6cf 100644
--- a/libc/bionic/pthread_exit.cpp
+++ b/libc/bionic/pthread_exit.cpp
@@ -33,6 +33,7 @@
 #include <string.h>
 #include <sys/mman.h>
 
+#include "private/bionic_constants.h"
 #include "private/bionic_defs.h"
 #include "private/ScopedSignalBlocker.h"
 #include "pthread_internal.h"
@@ -103,6 +104,11 @@
     thread->alternate_signal_stack = nullptr;
   }
 
+#ifdef __aarch64__
+  // Free the shadow call stack and guard pages.
+  munmap(thread->shadow_call_stack_guard_region, SCS_GUARD_REGION_SIZE);
+#endif
+
   ThreadJoinState old_state = THREAD_NOT_JOINED;
   while (old_state == THREAD_NOT_JOINED &&
          !atomic_compare_exchange_weak(&thread->join_state, &old_state, THREAD_EXITED_NOT_JOINED)) {
diff --git a/libc/bionic/pthread_internal.cpp b/libc/bionic/pthread_internal.cpp
index 829194c..2b7a99a 100644
--- a/libc/bionic/pthread_internal.cpp
+++ b/libc/bionic/pthread_internal.cpp
@@ -36,7 +36,6 @@
 #include <async_safe/log.h>
 
 #include "private/bionic_futex.h"
-#include "private/bionic_sdk_version.h"
 #include "private/bionic_tls.h"
 
 static pthread_internal_t* g_thread_list = nullptr;
@@ -54,7 +53,7 @@
 
  private:
   pthread_rwlock_t* rwlock_;
-  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedRWLock);
+  BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedRWLock);
 };
 
 typedef ScopedRWLock<true> ScopedWriteLock;
@@ -114,7 +113,7 @@
   }
 
   // Historically we'd return null, but
-  if (bionic_get_application_target_sdk_version() >= __ANDROID_API_O__) {
+  if (android_get_application_target_sdk_version() >= __ANDROID_API_O__) {
     if (thread == nullptr) {
       // This seems to be a common mistake, and it's relatively harmless because
       // there will never be a valid thread at address 0, whereas other invalid
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index 65ec5ff..81b885a 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -106,16 +106,35 @@
 
   void* alternate_signal_stack;
 
+  // The start address of the shadow call stack's guard region (arm64 only).
+  // This address is only used to deallocate the shadow call stack on thread
+  // exit; the address of the stack itself is stored only in the x18 register.
+  // Because the protection offered by SCS relies on the secrecy of the stack
+  // address, storing the address here weakens the protection, but only
+  // slightly, because it is relatively easy for an attacker to discover the
+  // address of the guard region anyway (e.g. it can be discovered by reference
+  // to other allocations), but not the stack itself, which is <0.1% of the size
+  // of the guard region.
+  //
+  // There are at least two other options for discovering the start address of
+  // the guard region on thread exit, but they are not as simple as storing in
+  // TLS.
+  // 1) Derive it from the value of the x18 register. This is only possible in
+  //    processes that do not contain legacy code that might clobber x18,
+  //    therefore each process must declare early during process startup whether
+  //    it might load legacy code.
+  // 2) Mark the guard region as such using prctl(PR_SET_VMA_ANON_NAME) and
+  //    discover its address by reading /proc/self/maps. One issue with this is
+  //    that reading /proc/self/maps can race with allocations, so we may need
+  //    code to handle retries.
+  void* shadow_call_stack_guard_region;
+
   Lock startup_handshake_lock;
 
   size_t mmap_size;
 
   thread_local_dtor* thread_local_dtors;
 
-  void* tls[BIONIC_TLS_SLOTS];
-
-  pthread_key_data_t key_data[BIONIC_PTHREAD_KEY_COUNT];
-
   /*
    * The dynamic linker implements dlerror(3), which makes it hard for us to implement this
    * per-thread buffer by simply using malloc(3) and free(3).
@@ -124,12 +143,19 @@
   char dlerror_buffer[__BIONIC_DLERROR_BUFFER_SIZE];
 
   bionic_tls* bionic_tls;
+
+  // The thread pointer (__get_tls()) points at this field. This field must come last so that
+  // an executable's TLS segment can be allocated at a fixed offset after the thread pointer.
+  void* tls[BIONIC_TLS_SLOTS];
+
+  // The golang runtime currently expects this field to come after the slots.
+  pthread_key_data_t key_data[BIONIC_PTHREAD_KEY_COUNT];
 };
 
 __LIBC_HIDDEN__ int __init_thread(pthread_internal_t* thread);
 __LIBC_HIDDEN__ bool __init_tls(pthread_internal_t* thread);
 __LIBC_HIDDEN__ void __init_thread_stack_guard(pthread_internal_t* thread);
-__LIBC_HIDDEN__ void __init_alternate_signal_stack(pthread_internal_t*);
+__LIBC_HIDDEN__ void __init_additional_stacks(pthread_internal_t*);
 
 __LIBC_HIDDEN__ pthread_t           __pthread_internal_add(pthread_internal_t* thread);
 __LIBC_HIDDEN__ pthread_internal_t* __pthread_internal_find(pthread_t pthread_id);
@@ -164,9 +190,14 @@
 
 // SIGSTKSZ (8KiB) is not big enough.
 // An snprintf to a stack buffer of size PATH_MAX consumes ~7KiB of stack.
-// Also, on 64-bit, logging uses more than 8KiB by itself:
-// https://code.google.com/p/android/issues/detail?id=187064
+// On 64-bit, logging uses more than 8KiB by itself, ucontext is comically
+// large on aarch64, and we have effectively infinite address space, so double
+// the signal stack size.
+#if defined(__LP64__)
+#define SIGNAL_STACK_SIZE_WITHOUT_GUARD (32 * 1024)
+#else
 #define SIGNAL_STACK_SIZE_WITHOUT_GUARD (16 * 1024)
+#endif
 
 // Traditionally we gave threads a 1MiB stack. When we started
 // allocating per-thread alternate signal stacks to ease debugging of
diff --git a/libc/bionic/pthread_mutex.cpp b/libc/bionic/pthread_mutex.cpp
index fda0b93..d9ddf10 100644
--- a/libc/bionic/pthread_mutex.cpp
+++ b/libc/bionic/pthread_mutex.cpp
@@ -42,7 +42,6 @@
 #include "private/bionic_constants.h"
 #include "private/bionic_fortify.h"
 #include "private/bionic_futex.h"
-#include "private/bionic_sdk_version.h"
 #include "private/bionic_systrace.h"
 #include "private/bionic_time_conversions.h"
 #include "private/bionic_tls.h"
@@ -789,7 +788,7 @@
 // ARM64. So make it noinline.
 static int __attribute__((noinline)) HandleUsingDestroyedMutex(pthread_mutex_t* mutex,
                                                                const char* function_name) {
-    if (bionic_get_application_target_sdk_version() >= __ANDROID_API_P__) {
+    if (android_get_application_target_sdk_version() >= __ANDROID_API_P__) {
         __fortify_fatal("%s called on a destroyed mutex (%p)", function_name, mutex);
     }
     return EBUSY;
diff --git a/libc/bionic/scandir.cpp b/libc/bionic/scandir.cpp
index e55be42..0b39049 100644
--- a/libc/bionic/scandir.cpp
+++ b/libc/bionic/scandir.cpp
@@ -90,7 +90,7 @@
     return copy;
   }
 
-  DISALLOW_COPY_AND_ASSIGN(ScandirResult);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(ScandirResult);
 };
 
 int scandirat(int parent_fd, const char* dir_name, dirent*** name_list,
diff --git a/libc/bionic/semaphore.cpp b/libc/bionic/semaphore.cpp
index d401b66..e0486b4 100644
--- a/libc/bionic/semaphore.cpp
+++ b/libc/bionic/semaphore.cpp
@@ -41,7 +41,6 @@
 
 #include "private/bionic_constants.h"
 #include "private/bionic_futex.h"
-#include "private/bionic_sdk_version.h"
 #include "private/bionic_time_conversions.h"
 
 // In this implementation, a semaphore contains a
@@ -222,7 +221,7 @@
     }
 
     int result = __futex_wait_ex(sem_count_ptr, shared, shared | SEMCOUNT_MINUS_ONE, false, nullptr);
-    if (bionic_get_application_target_sdk_version() >= __ANDROID_API_N__) {
+    if (android_get_application_target_sdk_version() >= __ANDROID_API_N__) {
       if (result ==-EINTR) {
         errno = EINTR;
         return -1;
diff --git a/libc/bionic/system_property_set.cpp b/libc/bionic/system_property_set.cpp
index a70a376..bc3ba76 100644
--- a/libc/bionic/system_property_set.cpp
+++ b/libc/bionic/system_property_set.cpp
@@ -170,7 +170,7 @@
   uint32_t uint_buf_[kUintBufSize];
   size_t uint_buf_index_;
 
-  DISALLOW_IMPLICIT_CONSTRUCTORS(SocketWriter);
+  BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(SocketWriter);
 };
 
 struct prop_msg {
diff --git a/libc/dns/net/getnameinfo.c b/libc/dns/net/getnameinfo.c
index 5fa4e37..31d07c5 100644
--- a/libc/dns/net/getnameinfo.c
+++ b/libc/dns/net/getnameinfo.c
@@ -68,6 +68,13 @@
 #include <stddef.h>
 #include <string.h>
 
+/* This macro is modelled after the ones in <netinet/in6.h>. */
+/* RFC 6052, section 2.1 */
+#define IN6_IS_ADDR_WKP(a) \
+  ((((a)->s6_addr32[0]) == ntohl(0x0064ff9b)) && \
+   (((a)->s6_addr32[1]) == 0) && \
+   (((a)->s6_addr32[2]) == 0))
+
 static const struct afd {
 	int		a_af;
 	socklen_t	a_addrlen;
@@ -248,6 +255,8 @@
 				;
 			else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
 				;
+			else if (IN6_IS_ADDR_WKP(&sin6->sin6_addr))
+				;
 			else
 				flags |= NI_NUMERICHOST;
 			break;
diff --git a/libc/dns/resolv/res_cache.c b/libc/dns/resolv/res_cache.c
index d0673ef..f4c590f 100644
--- a/libc/dns/resolv/res_cache.c
+++ b/libc/dns/resolv/res_cache.c
@@ -2068,14 +2068,19 @@
             // max_samples actually change, in practice the overhead of checking is higher than the
             // cost, and overflows are unlikely
             ++cache_info->revision_id;
-        } else if (cache_info->params.max_samples != old_max_samples) {
-            // If the maximum number of samples changes, the overhead of keeping the most recent
-            // samples around is not considered worth the effort, so they are cleared instead. All
-            // other parameters do not affect shared state: Changing these parameters does not
-            // invalidate the samples, as they only affect aggregation and the conditions under
-            // which servers are considered usable.
-            _res_cache_clear_stats_locked(cache_info);
-            ++cache_info->revision_id;
+        } else {
+            if (cache_info->params.max_samples != old_max_samples) {
+                // If the maximum number of samples changes, the overhead of keeping the most recent
+                // samples around is not considered worth the effort, so they are cleared instead.
+                // All other parameters do not affect shared state: Changing these parameters does
+                // not invalidate the samples, as they only affect aggregation and the conditions
+                // under which servers are considered usable.
+                _res_cache_clear_stats_locked(cache_info);
+                ++cache_info->revision_id;
+            }
+            for (unsigned j = 0; j < numservers; j++) {
+                freeaddrinfo(nsaddrinfo[j]);
+            }
         }
 
         // Always update the search paths, since determining whether they actually changed is
diff --git a/libc/include/android/api-level.h b/libc/include/android/api-level.h
index 3a8f926..a175857 100644
--- a/libc/include/android/api-level.h
+++ b/libc/include/android/api-level.h
@@ -35,6 +35,8 @@
 
 #include <sys/cdefs.h>
 
+__BEGIN_DECLS
+
 #ifndef __ANDROID_API_FUTURE__
 /**
  * Magic version number for an Android OS build which has
@@ -97,3 +99,39 @@
 
 /** Names the "Q" API level (29), for comparisons against __ANDROID_API__. */
 #define __ANDROID_API_Q__ 29
+
+/**
+ * Returns the `targetSdkVersion` of the caller, or `__ANDROID_API_FUTURE__`
+ * if there is no known target SDK version (for code not running in the
+ * context of an app).
+ *
+ * The returned values correspond to the named constants in `<android/api-level.h>`,
+ * and is equivalent to the AndroidManifest.xml `targetSdkVersion`.
+ *
+ * See also android_get_device_api_level().
+ *
+ * Available since API level 24.
+ */
+int android_get_application_target_sdk_version() __INTRODUCED_IN(24);
+
+#if __ANDROID_API__ < __ANDROID_API_Q__
+
+// android_get_device_api_level is a static inline before API level 29.
+#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
+#include <bits/get_device_api_level_inlines.h>
+#undef __BIONIC_GET_DEVICE_API_LEVEL_INLINE
+
+#else
+
+/**
+ * Returns the API level of the device we're actually running on, or -1 on failure.
+ * The returned values correspond to the named constants in `<android/api-level.h>`,
+ * and is equivalent to the Java `Build.VERSION.SDK_INT` API.
+ *
+ * See also android_get_application_target_sdk_version().
+ */
+int android_get_device_api_level() __INTRODUCED_IN(29);
+
+#endif
+
+__END_DECLS
diff --git a/libc/include/android/dlext.h b/libc/include/android/dlext.h
index 431e5ce..e78be39 100644
--- a/libc/include/android/dlext.h
+++ b/libc/include/android/dlext.h
@@ -100,34 +100,11 @@
    */
   ANDROID_DLEXT_FORCE_LOAD = 0x40,
 
-  /**
-   * When set, if the minimum `p_vaddr` of the ELF file's `PT_LOAD` segments is non-zero,
-   * the dynamic linker will load it at that address.
-   *
-   * This flag is for ART internal use only.
-   */
-  ANDROID_DLEXT_FORCE_FIXED_VADDR = 0x80,
-
-  /**
-   * Instructs dlopen to load the library at the address specified by reserved_addr.
-   *
-   * The difference between `ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS` and
-   * `ANDROID_DLEXT_RESERVED_ADDRESS` is that for `ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS` the linker
-   * reserves memory at `reserved_addr` whereas for `ANDROID_DLEXT_RESERVED_ADDRESS` the linker
-   * relies on the caller to reserve the memory.
-   *
-   * This flag can be used with `ANDROID_DLEXT_FORCE_FIXED_VADDR`. When
-   * `ANDROID_DLEXT_FORCE_FIXED_VADDR` is set and `load_bias` is not 0 (`load_bias` is the
-   * minimum `p_vaddr` of all `PT_LOAD` segments) this flag is ignored because the linker has to
-   * pick one address over the other and this way is more convenient for ART.
-   * Note that `ANDROID_DLEXT_FORCE_FIXED_VADDR` does not generate an error when the minimum
-   * `p_vaddr` is 0.
-   *
-   * Cannot be used with `ANDROID_DLEXT_RESERVED_ADDRESS` or `ANDROID_DLEXT_RESERVED_ADDRESS_HINT`.
-   *
-   * This flag is for ART internal use only.
-   */
-  ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS = 0x100,
+  // Historically we had two other options for ART.
+  // They were last available in Android P.
+  // Reuse these bits last!
+  // ANDROID_DLEXT_FORCE_FIXED_VADDR = 0x80
+  // ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS = 0x100
 
   /**
    * This flag used to load library in a different namespace. The namespace is
@@ -145,8 +122,6 @@
                                         ANDROID_DLEXT_USE_LIBRARY_FD |
                                         ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET |
                                         ANDROID_DLEXT_FORCE_LOAD |
-                                        ANDROID_DLEXT_FORCE_FIXED_VADDR |
-                                        ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS |
                                         ANDROID_DLEXT_USE_NAMESPACE,
 };
 
diff --git a/libc/include/android/versioning.h b/libc/include/android/versioning.h
index cab1156..01fa348 100644
--- a/libc/include/android/versioning.h
+++ b/libc/include/android/versioning.h
@@ -14,19 +14,16 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_VERSIONING_H
-#define ANDROID_VERSIONING_H
+#pragma once
 
-#define __INTRODUCED_IN(api_level) __attribute__((annotate("introduced_in=" __STRING(api_level))))
+#define __INTRODUCED_IN(api_level) __attribute__((annotate("introduced_in=" #api_level)))
 #define __INTRODUCED_IN_FUTURE __attribute__((annotate("introduced_in_future")))
-#define __DEPRECATED_IN(api_level) __attribute__((annotate("deprecated_in=" __STRING(api_level))))
-#define __REMOVED_IN(api_level) __attribute__((annotate("obsoleted_in=" __STRING(api_level))))
-#define __INTRODUCED_IN_32(api_level) __attribute__((annotate("introduced_in_32=" __STRING(api_level))))
-#define __INTRODUCED_IN_64(api_level) __attribute__((annotate("introduced_in_64=" __STRING(api_level))))
-#define __INTRODUCED_IN_ARM(api_level) __attribute__((annotate("introduced_in_arm=" __STRING(api_level))))
-#define __INTRODUCED_IN_X86(api_level) __attribute__((annotate("introduced_in_x86=" __STRING(api_level))))
-#define __INTRODUCED_IN_MIPS(api_level) __attribute__((annotate("introduced_in_mips=" __STRING(api_level))))
+#define __DEPRECATED_IN(api_level) __attribute__((annotate("deprecated_in=" #api_level)))
+#define __REMOVED_IN(api_level) __attribute__((annotate("obsoleted_in=" #api_level)))
+#define __INTRODUCED_IN_32(api_level) __attribute__((annotate("introduced_in_32=" #api_level)))
+#define __INTRODUCED_IN_64(api_level) __attribute__((annotate("introduced_in_64=" #api_level)))
+#define __INTRODUCED_IN_ARM(api_level) __attribute__((annotate("introduced_in_arm=" #api_level)))
+#define __INTRODUCED_IN_X86(api_level) __attribute__((annotate("introduced_in_x86=" #api_level)))
+#define __INTRODUCED_IN_MIPS(api_level) __attribute__((annotate("introduced_in_mips=" #api_level)))
 
 #define __VERSIONER_NO_GUARD __attribute__((annotate("versioner_no_guard")))
-
-#endif /* ANDROID_VERSIONING_H */
diff --git a/libc/include/bits/get_device_api_level_inlines.h b/libc/include/bits/get_device_api_level_inlines.h
index 8e17814..9c6e243 100644
--- a/libc/include/bits/get_device_api_level_inlines.h
+++ b/libc/include/bits/get_device_api_level_inlines.h
@@ -28,18 +28,20 @@
 
 #pragma once
 
-#include <stdlib.h>
 #include <sys/cdefs.h>
-#include <sys/system_properties.h>
 
 #if !defined(__BIONIC_GET_DEVICE_API_LEVEL_INLINE)
-#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static __inline
+#define __BIONIC_GET_DEVICE_API_LEVEL_INLINE static inline /* for versioner */
 #endif
 
 __BEGIN_DECLS
 
+// Avoid circular dependencies since this is exposed from <sys/cdefs.h>.
+int __system_property_get(const char* __name, char* __value);
+int atoi(const char* __s) __attribute_pure__;
+
 __BIONIC_GET_DEVICE_API_LEVEL_INLINE int android_get_device_api_level() {
-  char value[PROP_VALUE_MAX] = { 0 };
+  char value[92] = { 0 };
   if (__system_property_get("ro.build.version.sdk", value) < 1) return -1;
   int api_level = atoi(value);
   return (api_level > 0) ? api_level : -1;
diff --git a/libc/include/bits/glibc-syscalls.h b/libc/include/bits/glibc-syscalls.h
index ffd92cc..52eff56 100644
--- a/libc/include/bits/glibc-syscalls.h
+++ b/libc/include/bits/glibc-syscalls.h
@@ -418,6 +418,9 @@
 #if defined(__NR_io_getevents)
   #define SYS_io_getevents __NR_io_getevents
 #endif
+#if defined(__NR_io_pgetevents)
+  #define SYS_io_pgetevents __NR_io_pgetevents
+#endif
 #if defined(__NR_io_setup)
   #define SYS_io_setup __NR_io_setup
 #endif
@@ -799,6 +802,9 @@
 #if defined(__NR_rmdir)
   #define SYS_rmdir __NR_rmdir
 #endif
+#if defined(__NR_rseq)
+  #define SYS_rseq __NR_rseq
+#endif
 #if defined(__NR_rt_sigaction)
   #define SYS_rt_sigaction __NR_rt_sigaction
 #endif
diff --git a/libc/include/bits/ioctl.h b/libc/include/bits/ioctl.h
index 9ed1292..fd31a58 100644
--- a/libc/include/bits/ioctl.h
+++ b/libc/include/bits/ioctl.h
@@ -54,11 +54,8 @@
  *   type of the ioctl you prefer, ...), or
  * - defining BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD, which will make the
  *   overloading go away.
- *
- * FIXME: __has_extension is more or less a clang version check. Remove it when
- * we don't need to support old clang code.
  */
-#if __has_extension(overloadable_unmarked) && !defined(BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD)
+#if !defined(BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD)
 /* enable_if(1) just exists to break overloading ties. */
 int ioctl(int __fd, unsigned __request, ...) __overloadable __enable_if(1, "") __RENAME(ioctl);
 #endif
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index 42237d0..eba18a8 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -31,12 +31,7 @@
 
 __BEGIN_DECLS
 
-// Remove this workaround once b/37423073 is fixed.
-#if !__has_attribute(alloc_size)
-#define __BIONIC_ALLOC_SIZE(...)
-#else
 #define __BIONIC_ALLOC_SIZE(...) __attribute__((__alloc_size__(__VA_ARGS__)))
-#endif
 
 /**
  * [malloc(3)](http://man7.org/linux/man-pages/man3/malloc.3.html) allocates
diff --git a/libc/include/signal.h b/libc/include/signal.h
index 9d1030a..c788ca6 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -114,7 +114,7 @@
 
 int pthread_kill(pthread_t __pthread, int __signal);
 #if defined(__USE_GNU)
-int pthread_sigqueue(pthread_t __pthread, int __signal, const union sigval __value) __INTRODUCED_IN(__ANDROID_API_Q__);
+int pthread_sigqueue(pthread_t __pthread, int __signal, const union sigval __value) __INTRODUCED_IN(29);
 #endif
 
 int pthread_sigmask(int __how, const sigset_t* __new_set, sigset_t* __old_set);
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 26a05c8..e9d0e4b 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -34,36 +34,10 @@
  *	@(#)cdefs.h	8.8 (Berkeley) 1/9/95
  */
 
-#ifndef	_SYS_CDEFS_H_
-#define	_SYS_CDEFS_H_
-
-#include <android/api-level.h>
+#pragma once
 
 #define __BIONIC__ 1
 
-/*
- * Testing against Clang-specific extensions.
- */
-#ifndef __has_extension
-#define __has_extension         __has_feature
-#endif
-#ifndef __has_feature
-#define __has_feature(x)        0
-#endif
-#ifndef __has_include
-#define __has_include(x)        0
-#endif
-#ifndef __has_builtin
-#define __has_builtin(x)        0
-#endif
-#ifndef __has_attribute
-#define __has_attribute(x)      0
-#endif
-
-#define __strong_alias(alias, sym) \
-    __asm__(".global " #alias "\n" \
-            #alias " = " #sym);
-
 #if defined(__cplusplus)
 #define __BEGIN_DECLS extern "C" {
 #define __END_DECLS }
@@ -72,6 +46,10 @@
 #define __END_DECLS
 #endif
 
+#define __strong_alias(alias, sym) \
+    __asm__(".global " #alias "\n" \
+            #alias " = " #sym);
+
 #if defined(__cplusplus)
 #define __BIONIC_CAST(_k,_t,_v) (_k<_t>(_v))
 #else
@@ -88,22 +66,19 @@
  * strings produced by the __STRING macro, but this only works with ANSI C.
  */
 
-#define	___STRING(x)	__STRING(x)
-#define	___CONCAT(x,y)	__CONCAT(x,y)
-
 #define	__P(protos)	protos		/* full-blown ANSI C */
+
 #define	__CONCAT1(x,y)	x ## y
 #define	__CONCAT(x,y)	__CONCAT1(x,y)
+#define	___CONCAT(x,y)	__CONCAT(x,y)
+
 #define	__STRING(x)	#x
+#define	___STRING(x)	__STRING(x)
 
 #if defined(__cplusplus)
 #define	__inline	inline		/* convert to C++ keyword */
 #endif /* !__cplusplus */
 
-#include <android/versioning.h>
-
-#include <android/versioning.h>
-
 #define __always_inline __attribute__((__always_inline__))
 #define __attribute_const__ __attribute__((__const__))
 #define __attribute_pure__ __attribute__((__pure__))
@@ -359,4 +334,5 @@
  */
 #define __unsafe_check_mul_overflow(x, y) ((__SIZE_TYPE__)-1 / (x) < (y))
 
-#endif /* !_SYS_CDEFS_H_ */
+#include <android/versioning.h>
+#include <android/api-level.h>
diff --git a/libc/include/sys/select.h b/libc/include/sys/select.h
index e58df21..9be444c 100644
--- a/libc/include/sys/select.h
+++ b/libc/include/sys/select.h
@@ -80,7 +80,7 @@
 
 int select(int __fd_count, fd_set* __read_fds, fd_set* __write_fds, fd_set* __exception_fds, struct timeval* __timeout);
 int pselect(int __fd_count, fd_set* __read_fds, fd_set* __write_fds, fd_set* __exception_fds, const struct timespec* __timeout, const sigset_t* __mask);
-int pselect64(int __fd_count, fd_set* __read_fds, fd_set* __write_fds, fd_set* __exception_fds, const struct timespec* __timeout, const sigset64_t* __mask);
+int pselect64(int __fd_count, fd_set* __read_fds, fd_set* __write_fds, fd_set* __exception_fds, const struct timespec* __timeout, const sigset64_t* __mask) __INTRODUCED_IN(28);
 
 __END_DECLS
 
diff --git a/libc/kernel/tools/cpp.py b/libc/kernel/tools/cpp.py
old mode 100644
new mode 100755
index 2400f5d..336a9c8
--- a/libc/kernel/tools/cpp.py
+++ b/libc/kernel/tools/cpp.py
@@ -6,6 +6,7 @@
 import os
 import re
 import site
+import unittest
 import utils
 
 top = os.getenv('ANDROID_BUILD_TOP')
@@ -309,75 +310,50 @@
 
 # Unit testing
 #
-class CppTokenizerTester(object):
-    """A class used to test CppTokenizer classes."""
+class CppTokenizerTests(unittest.TestCase):
+    """CppTokenizer tests."""
 
-    def __init__(self, tokenizer=None):
-        self._tokenizer = tokenizer
-        self._token = None
+    def get_tokens(self, token_string, line_col=False):
+        tokens = CppStringTokenizer(token_string)
+        token_list = []
+        while True:
+            token = tokens.nextToken()
+            if not token:
+                break
+            if line_col:
+                token_list.append((token.id, token.location.line,
+                                   token.location.column))
+            else:
+                token_list.append(token.id)
+        return token_list
 
-    def setTokenizer(self, tokenizer):
-        self._tokenizer = tokenizer
+    def test_hash(self):
+        self.assertEqual(self.get_tokens("#an/example  && (01923_xy)"),
+                         ["#", "an", "/", "example", tokLOGICAND, tokLPAREN,
+                          "01923_xy", tokRPAREN])
 
-    def expect(self, id):
-        self._token = self._tokenizer.nextToken()
-        if self._token is None:
-            tokid = ''
-        else:
-            tokid = self._token.id
-        if tokid == id:
-            return
-        raise BadExpectedToken("###  BAD TOKEN: '%s' expecting '%s'" % (
-            tokid, id))
+    def test_parens(self):
+        self.assertEqual(self.get_tokens("FOO(BAR) && defined(BAZ)"),
+                         ["FOO", tokLPAREN, "BAR", tokRPAREN, tokLOGICAND,
+                          "defined", tokLPAREN, "BAZ", tokRPAREN])
 
-    def expectToken(self, id, line, col):
-        self.expect(id)
-        if self._token.location.line != line:
-            raise BadExpectedToken(
-                "###  BAD LINENO: token '%s' got '%d' expecting '%d'" % (
-                    id, self._token.lineno, line))
-        if self._token.location.column != col:
-            raise BadExpectedToken("###  BAD COLNO: '%d' expecting '%d'" % (
-                self._token.colno, col))
+    def test_comment(self):
+        self.assertEqual(self.get_tokens("/*\n#\n*/"), [])
 
-    def expectTokens(self, tokens):
-        for id, line, col in tokens:
-            self.expectToken(id, line, col)
+    def test_line_cross(self):
+        self.assertEqual(self.get_tokens("first\nsecond"), ["first", "second"])
 
-    def expectList(self, list_):
-        for item in list_:
-            self.expect(item)
+    def test_line_cross_line_col(self):
+        self.assertEqual(self.get_tokens("first second\n  third", True),
+                         [("first", 1, 1), ("second", 1, 7), ("third", 2, 3)])
 
+    def test_comment_line_col(self):
+        self.assertEqual(self.get_tokens("boo /* what the\nhell */", True),
+                         [("boo", 1, 1)])
 
-def test_CppTokenizer():
-    tester = CppTokenizerTester()
-
-    tester.setTokenizer(CppStringTokenizer("#an/example  && (01923_xy)"))
-    tester.expectList(["#", "an", "/", "example", tokLOGICAND, tokLPAREN,
-                       "01923_xy", tokRPAREN])
-
-    tester.setTokenizer(CppStringTokenizer("FOO(BAR) && defined(BAZ)"))
-    tester.expectList(["FOO", tokLPAREN, "BAR", tokRPAREN, tokLOGICAND,
-                       "defined", tokLPAREN, "BAZ", tokRPAREN])
-
-    tester.setTokenizer(CppStringTokenizer("/*\n#\n*/"))
-    tester.expectList([])
-
-    tester.setTokenizer(CppStringTokenizer("first\nsecond"))
-    tester.expectList(["first", "second"])
-
-    tester.setTokenizer(CppStringTokenizer("first second\n  third"))
-    tester.expectTokens([("first", 1, 1),
-                         ("second", 1, 7),
-                         ("third", 2, 3)])
-
-    tester.setTokenizer(CppStringTokenizer("boo /* what the\nhell */"))
-    tester.expectTokens([("boo", 1, 1)])
-
-    tester.setTokenizer(CppStringTokenizer("an \\\n example"))
-    tester.expectTokens([("an", 1, 1),
-                         ("example", 2, 2)])
-    return True
+    def test_escapes(self):
+        self.assertEqual(self.get_tokens("an \\\n example", True),
+                         [("an", 1, 1), ("example", 2, 2)])
 
 
 ################################################################################
@@ -829,134 +805,137 @@
             macros = {}
         self.expr = self.optimize_node(self.expr, macros)
 
+class CppExprTest(unittest.TestCase):
+    """CppExpr unit tests."""
 
-def test_cpp_expr(expr, expected):
-    e = CppExpr(CppStringTokenizer(expr).tokens)
-    s1 = repr(e)
-    if s1 != expected:
-        print ("[FAIL]: expression '%s' generates '%s', should be "
-               "'%s'" % (expr, s1, expected))
-        global failure_count
-        failure_count += 1
+    def get_expr(self, expr):
+        return repr(CppExpr(CppStringTokenizer(expr).tokens))
 
+    def test_cpp_expr(self):
+        self.assertEqual(self.get_expr("0"), "(int 0)")
+        self.assertEqual(self.get_expr("1"), "(int 1)")
+        self.assertEqual(self.get_expr("-5"), "(int -5)")
+        self.assertEqual(self.get_expr("+1"), "(int 1)")
+        self.assertEqual(self.get_expr("0U"), "(int 0)")
+        self.assertEqual(self.get_expr("015"), "(oct 015)")
+        self.assertEqual(self.get_expr("015l"), "(oct 015)")
+        self.assertEqual(self.get_expr("0x3e"), "(hex 0x3e)")
+        self.assertEqual(self.get_expr("(0)"), "(int 0)")
+        self.assertEqual(self.get_expr("1 && 1"), "(&& (int 1) (int 1))")
+        self.assertEqual(self.get_expr("1 && 0"), "(&& (int 1) (int 0))")
+        self.assertEqual(self.get_expr("EXAMPLE"), "(ident EXAMPLE)")
+        self.assertEqual(self.get_expr("EXAMPLE - 3"),
+                         "(- (ident EXAMPLE) (int 3))")
+        self.assertEqual(self.get_expr("defined(EXAMPLE)"),
+                         "(defined EXAMPLE)")
+        self.assertEqual(self.get_expr("defined ( EXAMPLE ) "),
+                         "(defined EXAMPLE)")
+        self.assertEqual(self.get_expr("!defined(EXAMPLE)"),
+                         "(! (defined EXAMPLE))")
+        self.assertEqual(self.get_expr("defined(ABC) || defined(BINGO)"),
+                         "(|| (defined ABC) (defined BINGO))")
+        self.assertEqual(self.get_expr("FOO(BAR,5)"), "(call FOO [BAR,5])")
+        self.assertEqual(self.get_expr("A == 1 || defined(B)"),
+                         "(|| (== (ident A) (int 1)) (defined B))")
 
-def test_cpp_expr_optim(expr, expected, macros=None):
-    if macros is None:
-        macros = {}
-    e = CppExpr(CppStringTokenizer(expr).tokens)
-    e.optimize(macros)
-    s1 = repr(e)
-    if s1 != expected:
-        print ("[FAIL]: optimized expression '%s' generates '%s' with "
-               "macros %s, should be '%s'" % (expr, s1, macros, expected))
-        global failure_count
-        failure_count += 1
+    def get_expr_optimize(self, expr, macros=None):
+        if macros is None:
+            macros = {}
+        e = CppExpr(CppStringTokenizer(expr).tokens)
+        e.optimize(macros)
+        return repr(e)
 
-
-def test_cpp_expr_source(expr, expected):
-    e = CppExpr(CppStringTokenizer(expr).tokens)
-    s1 = str(e)
-    if s1 != expected:
-        print ("[FAIL]: source expression '%s' generates '%s', should "
-               "be '%s'" % (expr, s1, expected))
-        global failure_count
-        failure_count += 1
-
-
-def test_CppExpr():
-    test_cpp_expr("0", "(int 0)")
-    test_cpp_expr("1", "(int 1)")
-    test_cpp_expr("-5", "(int -5)")
-    test_cpp_expr("+1", "(int 1)")
-    test_cpp_expr("0U", "(int 0)")
-    test_cpp_expr("015", "(oct 015)")
-    test_cpp_expr("015l", "(oct 015)")
-    test_cpp_expr("0x3e", "(hex 0x3e)")
-    test_cpp_expr("(0)", "(int 0)")
-    test_cpp_expr("1 && 1", "(&& (int 1) (int 1))")
-    test_cpp_expr("1 && 0", "(&& (int 1) (int 0))")
-    test_cpp_expr("EXAMPLE", "(ident EXAMPLE)")
-    test_cpp_expr("EXAMPLE - 3", "(- (ident EXAMPLE) (int 3))")
-    test_cpp_expr("defined(EXAMPLE)", "(defined EXAMPLE)")
-    test_cpp_expr("defined ( EXAMPLE ) ", "(defined EXAMPLE)")
-    test_cpp_expr("!defined(EXAMPLE)", "(! (defined EXAMPLE))")
-    test_cpp_expr("defined(ABC) || defined(BINGO)",
-                  "(|| (defined ABC) (defined BINGO))")
-    test_cpp_expr("FOO(BAR,5)", "(call FOO [BAR,5])")
-    test_cpp_expr("A == 1 || defined(B)",
-                  "(|| (== (ident A) (int 1)) (defined B))")
-
-    test_cpp_expr_optim("0", "(int 0)")
-    test_cpp_expr_optim("1", "(int 1)")
-    test_cpp_expr_optim("1 && 1", "(int 1)")
-    test_cpp_expr_optim("1 && +1", "(int 1)")
-    test_cpp_expr_optim("0x1 && 01", "(oct 01)")
-    test_cpp_expr_optim("1 && 0", "(int 0)")
-    test_cpp_expr_optim("0 && 1", "(int 0)")
-    test_cpp_expr_optim("0 && 0", "(int 0)")
-    test_cpp_expr_optim("1 || 1", "(int 1)")
-    test_cpp_expr_optim("1 || 0", "(int 1)")
-    test_cpp_expr_optim("0 || 1", "(int 1)")
-    test_cpp_expr_optim("0 || 0", "(int 0)")
-    test_cpp_expr_optim("A", "(ident A)")
-    test_cpp_expr_optim("A", "(int 1)", {"A": 1})
-    test_cpp_expr_optim("A || B", "(int 1)", {"A": 1})
-    test_cpp_expr_optim("A || B", "(int 1)", {"B": 1})
-    test_cpp_expr_optim("A && B", "(ident B)", {"A": 1})
-    test_cpp_expr_optim("A && B", "(ident A)", {"B": 1})
-    test_cpp_expr_optim("A && B", "(&& (ident A) (ident B))")
-    test_cpp_expr_optim("EXAMPLE", "(ident EXAMPLE)")
-    test_cpp_expr_optim("EXAMPLE - 3", "(- (ident EXAMPLE) (int 3))")
-    test_cpp_expr_optim("defined(EXAMPLE)", "(defined EXAMPLE)")
-    test_cpp_expr_optim("defined(EXAMPLE)", "(defined XOWOE)",
-                        {"EXAMPLE": "XOWOE"})
-    test_cpp_expr_optim("defined(EXAMPLE)", "(int 0)",
-                        {"EXAMPLE": kCppUndefinedMacro})
-    test_cpp_expr_optim("!defined(EXAMPLE)", "(! (defined EXAMPLE))")
-    test_cpp_expr_optim("!defined(EXAMPLE)", "(! (defined XOWOE))",
-                        {"EXAMPLE": "XOWOE"})
-    test_cpp_expr_optim("!defined(EXAMPLE)", "(int 1)",
-                        {"EXAMPLE": kCppUndefinedMacro})
-    test_cpp_expr_optim("defined(A) || defined(B)",
+    def test_cpp_expr_optimize(self):
+        self.assertEqual(self.get_expr_optimize("0"), "(int 0)")
+        self.assertEqual(self.get_expr_optimize("1"), "(int 1)")
+        self.assertEqual(self.get_expr_optimize("1 && 1"), "(int 1)")
+        self.assertEqual(self.get_expr_optimize("1 && +1"), "(int 1)")
+        self.assertEqual(self.get_expr_optimize("0x1 && 01"), "(oct 01)")
+        self.assertEqual(self.get_expr_optimize("1 && 0"), "(int 0)")
+        self.assertEqual(self.get_expr_optimize("0 && 1"), "(int 0)")
+        self.assertEqual(self.get_expr_optimize("0 && 0"), "(int 0)")
+        self.assertEqual(self.get_expr_optimize("1 || 1"), "(int 1)")
+        self.assertEqual(self.get_expr_optimize("1 || 0"), "(int 1)")
+        self.assertEqual(self.get_expr_optimize("0 || 1"), "(int 1)")
+        self.assertEqual(self.get_expr_optimize("0 || 0"), "(int 0)")
+        self.assertEqual(self.get_expr_optimize("A"), "(ident A)")
+        self.assertEqual(self.get_expr_optimize("A", {"A": 1}), "(int 1)")
+        self.assertEqual(self.get_expr_optimize("A || B", {"A": 1}), "(int 1)")
+        self.assertEqual(self.get_expr_optimize("A || B", {"B": 1}), "(int 1)")
+        self.assertEqual(self.get_expr_optimize("A && B", {"A": 1}), "(ident B)")
+        self.assertEqual(self.get_expr_optimize("A && B", {"B": 1}), "(ident A)")
+        self.assertEqual(self.get_expr_optimize("A && B"), "(&& (ident A) (ident B))")
+        self.assertEqual(self.get_expr_optimize("EXAMPLE"), "(ident EXAMPLE)")
+        self.assertEqual(self.get_expr_optimize("EXAMPLE - 3"), "(- (ident EXAMPLE) (int 3))")
+        self.assertEqual(self.get_expr_optimize("defined(EXAMPLE)"), "(defined EXAMPLE)")
+        self.assertEqual(self.get_expr_optimize("defined(EXAMPLE)",
+                                                {"EXAMPLE": "XOWOE"}),
+                         "(defined XOWOE)")
+        self.assertEqual(self.get_expr_optimize("defined(EXAMPLE)",
+                                                {"EXAMPLE": kCppUndefinedMacro}),
+                         "(int 0)")
+        self.assertEqual(self.get_expr_optimize("!defined(EXAMPLE)"), "(! (defined EXAMPLE))")
+        self.assertEqual(self.get_expr_optimize("!defined(EXAMPLE)",
+                                                {"EXAMPLE": "XOWOE"}),
+                         "(! (defined XOWOE))")
+        self.assertEqual(self.get_expr_optimize("!defined(EXAMPLE)",
+                                                {"EXAMPLE": kCppUndefinedMacro}),
+                         "(int 1)")
+        self.assertEqual(self.get_expr_optimize("defined(A) || defined(B)"),
                         "(|| (defined A) (defined B))")
-    test_cpp_expr_optim("defined(A) || defined(B)", "(int 1)", {"A": "1"})
-    test_cpp_expr_optim("defined(A) || defined(B)", "(int 1)", {"B": "1"})
-    test_cpp_expr_optim("defined(A) || defined(B)", "(defined A)",
-                        {"B": kCppUndefinedMacro})
-    test_cpp_expr_optim("defined(A) || defined(B)", "(int 0)",
-                        {"A": kCppUndefinedMacro, "B": kCppUndefinedMacro})
-    test_cpp_expr_optim("defined(A) && defined(B)",
-                        "(&& (defined A) (defined B))")
-    test_cpp_expr_optim("defined(A) && defined(B)",
-                        "(defined B)", {"A": "1"})
-    test_cpp_expr_optim("defined(A) && defined(B)",
-                        "(defined A)", {"B": "1"})
-    test_cpp_expr_optim("defined(A) && defined(B)", "(int 0)",
-                        {"B": kCppUndefinedMacro})
-    test_cpp_expr_optim("defined(A) && defined(B)",
-                        "(int 0)", {"A": kCppUndefinedMacro})
-    test_cpp_expr_optim("A == 1 || defined(B)",
-                        "(|| (== (ident A) (int 1)) (defined B))")
-    test_cpp_expr_optim(
-        "defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)",
-        "(|| (! (defined __GLIBC__)) (< (ident __GLIBC__) (int 2)))",
-        {"__KERNEL__": kCppUndefinedMacro})
+        self.assertEqual(self.get_expr_optimize("defined(A) || defined(B)",
+                                                {"A": "1"}),
+                         "(int 1)")
+        self.assertEqual(self.get_expr_optimize("defined(A) || defined(B)",
+                                                {"B": "1"}),
+                         "(int 1)")
+        self.assertEqual(self.get_expr_optimize("defined(A) || defined(B)",
+                                                {"B": kCppUndefinedMacro}),
+                         "(defined A)")
+        self.assertEqual(self.get_expr_optimize("defined(A) || defined(B)",
+                                                {"A": kCppUndefinedMacro,
+                                                 "B": kCppUndefinedMacro}),
+                         "(int 0)")
+        self.assertEqual(self.get_expr_optimize("defined(A) && defined(B)"),
+                         "(&& (defined A) (defined B))")
+        self.assertEqual(self.get_expr_optimize("defined(A) && defined(B)",
+                                                {"A": "1"}),
+                         "(defined B)")
+        self.assertEqual(self.get_expr_optimize("defined(A) && defined(B)",
+                                                {"B": "1"}),
+                         "(defined A)")
+        self.assertEqual(self.get_expr_optimize("defined(A) && defined(B)",
+                                                {"B": kCppUndefinedMacro}),
+                        "(int 0)")
+        self.assertEqual(self.get_expr_optimize("defined(A) && defined(B)",
+                                                {"A": kCppUndefinedMacro}),
+                        "(int 0)")
+        self.assertEqual(self.get_expr_optimize("A == 1 || defined(B)"),
+                         "(|| (== (ident A) (int 1)) (defined B))")
+        self.assertEqual(self.get_expr_optimize(
+              "defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)",
+              {"__KERNEL__": kCppUndefinedMacro}),
+              "(|| (! (defined __GLIBC__)) (< (ident __GLIBC__) (int 2)))")
 
-    test_cpp_expr_source("0", "0")
-    test_cpp_expr_source("1", "1")
-    test_cpp_expr_source("1 && 1", "1 && 1")
-    test_cpp_expr_source("1 && 0", "1 && 0")
-    test_cpp_expr_source("0 && 1", "0 && 1")
-    test_cpp_expr_source("0 && 0", "0 && 0")
-    test_cpp_expr_source("1 || 1", "1 || 1")
-    test_cpp_expr_source("1 || 0", "1 || 0")
-    test_cpp_expr_source("0 || 1", "0 || 1")
-    test_cpp_expr_source("0 || 0", "0 || 0")
-    test_cpp_expr_source("EXAMPLE", "EXAMPLE")
-    test_cpp_expr_source("EXAMPLE - 3", "EXAMPLE - 3")
-    test_cpp_expr_source("defined(EXAMPLE)", "defined(EXAMPLE)")
-    test_cpp_expr_source("defined EXAMPLE", "defined(EXAMPLE)")
-    test_cpp_expr_source("A == 1 || defined(B)", "A == 1 || defined(B)")
+    def get_expr_string(self, expr):
+        return str(CppExpr(CppStringTokenizer(expr).tokens))
+
+    def test_cpp_expr_string(self):
+        self.assertEqual(self.get_expr_string("0"), "0")
+        self.assertEqual(self.get_expr_string("1"), "1")
+        self.assertEqual(self.get_expr_string("1 && 1"), "1 && 1")
+        self.assertEqual(self.get_expr_string("1 && 0"), "1 && 0")
+        self.assertEqual(self.get_expr_string("0 && 1"), "0 && 1")
+        self.assertEqual(self.get_expr_string("0 && 0"), "0 && 0")
+        self.assertEqual(self.get_expr_string("1 || 1"), "1 || 1")
+        self.assertEqual(self.get_expr_string("1 || 0"), "1 || 0")
+        self.assertEqual(self.get_expr_string("0 || 1"), "0 || 1")
+        self.assertEqual(self.get_expr_string("0 || 0"), "0 || 0")
+        self.assertEqual(self.get_expr_string("EXAMPLE"), "EXAMPLE")
+        self.assertEqual(self.get_expr_string("EXAMPLE - 3"), "EXAMPLE - 3")
+        self.assertEqual(self.get_expr_string("defined(EXAMPLE)"), "defined(EXAMPLE)")
+        self.assertEqual(self.get_expr_string("defined EXAMPLE"), "defined(EXAMPLE)")
+        self.assertEqual(self.get_expr_string("A == 1 || defined(B)"), "A == 1 || defined(B)")
 
 
 ################################################################################
@@ -1605,31 +1584,30 @@
         return self.getBlocks(CppFileTokenizer(path))
 
 
-def test_block_parsing(lines, expected):
-    """Helper method to test the correctness of BlockParser.parse."""
-    blocks = BlockParser().parse(CppStringTokenizer('\n'.join(lines)))
-    if len(blocks) != len(expected):
-        raise BadExpectedToken("BlockParser.parse() returned '%s' expecting "
-                               "'%s'" % (str(blocks), repr(expected)))
-    for n in range(len(blocks)):
-        if str(blocks[n]) != expected[n]:
-            raise BadExpectedToken("BlockParser.parse()[%d] is '%s', "
-                                   "expecting '%s'" % (n, str(blocks[n]),
-                                                       expected[n]))
+class BlockParserTests(unittest.TestCase):
+    """BlockParser unit tests."""
 
+    def get_blocks(self, lines):
+        blocks = BlockParser().parse(CppStringTokenizer('\n'.join(lines)))
+        return map(lambda a: str(a), blocks)
 
-def test_BlockParser():
-    test_block_parsing(["#error hello"], ["#error hello"])
-    test_block_parsing(["foo", "", "bar"], ["foo bar"])
+    def test_hash(self):
+        self.assertEqual(self.get_blocks(["#error hello"]), ["#error hello"])
 
-    # We currently cannot handle the following case with libclang properly.
-    # Fortunately it doesn't appear in current headers.
-    # test_block_parsing(["foo", "  #  ", "bar"], ["foo", "bar"])
+    def test_empty_line(self):
+        self.assertEqual(self.get_blocks(["foo", "", "bar"]), ["foo bar"])
 
-    test_block_parsing(["foo",
-                        "  #  /* ahah */ if defined(__KERNEL__) /* more */",
-                        "bar", "#endif"],
-                       ["foo", "#ifdef __KERNEL__", "bar", "#endif"])
+    def test_hash_with_space(self):
+        # We currently cannot handle the following case with libclang properly.
+        # Fortunately it doesn't appear in current headers.
+        #self.assertEqual(self.get_blocks(["foo", "  #  ", "bar"]), ["foo", "bar"])
+        pass
+
+    def test_with_comment(self):
+        self.assertEqual(self.get_blocks(["foo",
+                                          "  #  /* ahah */ if defined(__KERNEL__) /* more */",
+                                          "bar", "#endif"]),
+                         ["foo", "#ifdef __KERNEL__", "bar", "#endif"])
 
 
 ################################################################################
@@ -1684,6 +1662,7 @@
 
         if r == 0:
             # if 0 => skip everything until the corresponding #endif
+            start_dir = blocks[j].directive
             j = find_matching_endif(blocks, j + 1)
             if j >= n:
                 # unterminated #if 0, finish here
@@ -1692,18 +1671,27 @@
             if dir_ == "endif":
                 logging.debug("remove 'if 0' .. 'endif' (lines %d to %d)",
                               blocks[i].lineno, blocks[j].lineno)
+                if start_dir == "elif":
+                    # Put an endif since we started with an elif.
+                    result += blocks[j:j+1]
                 i = j + 1
             elif dir_ == "else":
                 # convert 'else' into 'if 1'
                 logging.debug("convert 'if 0' .. 'else' into 'if 1' (lines %d "
                               "to %d)", blocks[i].lineno, blocks[j-1].lineno)
-                blocks[j].directive = "if"
+                if start_dir == "elif":
+                    blocks[j].directive = "elif"
+                else:
+                    blocks[j].directive = "if"
                 blocks[j].expr = CppExpr(CppStringTokenizer("1").tokens)
                 i = j
             elif dir_ == "elif":
                 # convert 'elif' into 'if'
                 logging.debug("convert 'if 0' .. 'elif' into 'if'")
-                blocks[j].directive = "if"
+                if start_dir == "elif":
+                    blocks[j].directive = "elif"
+                else:
+                    blocks[j].directive = "if"
                 i = j
             continue
 
@@ -1715,18 +1703,33 @@
             result += blocks[j+1:k]
             break
 
+        start_dir = blocks[j].directive
         dir_ = blocks[k].directive
         if dir_ == "endif":
             logging.debug("convert 'if 1' .. 'endif' (lines %d to %d)",
                           blocks[j].lineno, blocks[k].lineno)
+            if start_dir == "elif":
+                # Add the elif in to the results and convert it to an elif 1.
+                blocks[j].tokens = CppStringTokenizer("1").tokens
+                result += blocks[j:j+1]
             result += optimize_if01(blocks[j+1:k])
+            if start_dir == "elif":
+                # Add the endif in to the results.
+                result += blocks[k:k+1]
             i = k + 1
         elif dir_ == "else":
             # convert 'else' into 'if 0'
             logging.debug("convert 'if 1' .. 'else' (lines %d to %d)",
                           blocks[j].lineno, blocks[k].lineno)
+            if start_dir == "elif":
+                # Add the elif in to the results and convert it to an elif 1.
+                blocks[j].tokens = CppStringTokenizer("1").tokens
+                result += blocks[j:j+1]
             result += optimize_if01(blocks[j+1:k])
-            blocks[k].directive = "if"
+            if start_dir == "elif":
+                blocks[k].directive = "elif"
+            else:
+                blocks[k].directive = "if"
             blocks[k].expr = CppExpr(CppStringTokenizer("0").tokens)
             i = k
         elif dir_ == "elif":
@@ -1738,85 +1741,203 @@
             i = k
     return result
 
+class OptimizerTests(unittest.TestCase):
+    def parse(self, text, macros=None):
+        out = utils.StringOutput()
+        blocks = BlockParser().parse(CppStringTokenizer(text))
+        blocks.replaceTokens(kernel_token_replacements)
+        blocks.optimizeAll(macros)
+        blocks.write(out)
+        return out.get()
 
-def test_optimizeAll():
-    text = """\
+    def test_if1(self):
+        text = """\
 #if 1
-#define  GOOD_1
+#define  GOOD
 #endif
-#if 0
-#define  BAD_2
-#define  BAD_3
-#endif
+"""
+        expected = """\
+#define GOOD
+"""
+        self.assertEqual(self.parse(text), expected)
 
+    def test_if0(self):
+        text = """\
+#if 0
+#define  SHOULD_SKIP1
+#define  SHOULD_SKIP2
+#endif
+"""
+        expected = ""
+        self.assertEqual(self.parse(text), expected)
+
+    def test_if1_else(self):
+        text = """\
 #if 1
-#define  GOOD_2
+#define  GOOD
 #else
-#define  BAD_4
+#define  BAD
 #endif
+"""
+        expected = """\
+#define GOOD
+"""
+        self.assertEqual(self.parse(text), expected)
 
+    def test_if0_else(self):
+        text = """\
 #if 0
-#define  BAD_5
+#define  BAD
 #else
-#define  GOOD_3
+#define  GOOD
 #endif
+"""
+        expected = """\
+#define GOOD
+"""
+        self.assertEqual(self.parse(text), expected)
 
+    def test_if_elif1(self):
+        text = """\
+#if defined(something)
+#define EXISTS
+#elif 1
+#define GOOD
+#endif
+"""
+        expected = """\
+#ifdef something
+#define EXISTS
+#elif 1
+#define GOOD
+#endif
+"""
+        self.assertEqual(self.parse(text), expected)
+
+    def test_if_elif1_macro(self):
+        text = """\
+#if defined(something)
+#define EXISTS
+#elif defined(WILL_BE_ONE)
+#define GOOD
+#endif
+"""
+        expected = """\
+#ifdef something
+#define EXISTS
+#elif 1
+#define GOOD
+#endif
+"""
+        self.assertEqual(self.parse(text, {"WILL_BE_ONE": "1"}), expected)
+
+
+    def test_if_elif1_else(self):
+        text = """\
+#if defined(something)
+#define EXISTS
+#elif 1
+#define GOOD
+#else
+#define BAD
+#endif
+"""
+        expected = """\
+#ifdef something
+#define EXISTS
+#elif 1
+#define GOOD
+#endif
+"""
+        self.assertEqual(self.parse(text), expected)
+
+    def test_if_elif1_else_macro(self):
+        text = """\
+#if defined(something)
+#define EXISTS
+#elif defined(WILL_BE_ONE)
+#define GOOD
+#else
+#define BAD
+#endif
+"""
+        expected = """\
+#ifdef something
+#define EXISTS
+#elif 1
+#define GOOD
+#endif
+"""
+        self.assertEqual(self.parse(text, {"WILL_BE_ONE": "1"}), expected)
+
+
+    def test_if_elif1_else_macro(self):
+        text = """\
+#if defined(something)
+#define EXISTS
+#elif defined(WILL_BE_ONE)
+#define GOOD
+#else
+#define BAD
+#endif
+"""
+        expected = """\
+#ifdef something
+#define EXISTS
+#elif 1
+#define GOOD
+#endif
+"""
+        self.assertEqual(self.parse(text, {"WILL_BE_ONE": "1"}), expected)
+
+    def test_macro_set_to_undefined_single(self):
+        text = """\
 #if defined(__KERNEL__)
 #define BAD_KERNEL
 #endif
+"""
+        expected = ""
+        macros = {"__KERNEL__": kCppUndefinedMacro}
+        self.assertEqual(self.parse(text, macros), expected)
 
+    def test_macro_set_to_undefined_if(self):
+        text = """\
 #if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
-#define X
+#define CHECK
 #endif
+"""
+        expected = """\
+#if !defined(__GLIBC__) || __GLIBC__ < 2
+#define CHECK
+#endif
+"""
+        macros = {"__KERNEL__": kCppUndefinedMacro}
+        self.assertEqual(self.parse(text, macros), expected)
 
+    def test_endif_comment_removed(self):
+        text = """\
 #ifndef SIGRTMAX
 #define SIGRTMAX 123
 #endif /* SIGRTMAX */
-
-#if 0
-#if 1
-#define  BAD_6
-#endif
-#endif\
 """
-
-    expected = """\
-#define GOOD_1
-#define GOOD_2
-#define GOOD_3
-#if !defined(__GLIBC__) || __GLIBC__ < 2
-#define X
-#endif
+        expected = """\
 #ifndef __SIGRTMAX
 #define __SIGRTMAX 123
 #endif
 """
+        self.assertEqual(self.parse(text), expected)
 
-    out = utils.StringOutput()
-    blocks = BlockParser().parse(CppStringTokenizer(text))
-    blocks.replaceTokens(kernel_token_replacements)
-    blocks.optimizeAll({"__KERNEL__": kCppUndefinedMacro})
-    blocks.write(out)
-    if out.get() != expected:
-        print "[FAIL]: macro optimization failed\n"
-        print "<<<< expecting '",
-        print expected,
-        print "'\n>>>> result '",
-        print out.get(),
-        print "'\n----"
-        global failure_count
-        failure_count += 1
+    def test_multilevel_if0(self):
+        text = """\
+#if 0
+#if 1
+#define  BAD_6
+#endif
+#endif
+"""
+        expected = ""
+        self.assertEqual(self.parse(text), expected)
 
 
-def runUnitTests():
-    """Always run all unit tests for this program."""
-    test_CppTokenizer()
-    test_CppExpr()
-    test_optimizeAll()
-    test_BlockParser()
-
-
-failure_count = 0
-runUnitTests()
-if failure_count != 0:
-    utils.panic("Unit tests failed in cpp.py.\n")
+if __name__ == '__main__':
+    unittest.main()
diff --git a/libc/kernel/uapi/asm-arm/asm/kvm.h b/libc/kernel/uapi/asm-arm/asm/kvm.h
index 6cbc533..95f0c4d 100644
--- a/libc/kernel/uapi/asm-arm/asm/kvm.h
+++ b/libc/kernel/uapi/asm-arm/asm/kvm.h
@@ -24,6 +24,7 @@
 #define __KVM_HAVE_GUEST_DEBUG
 #define __KVM_HAVE_IRQ_LINE
 #define __KVM_HAVE_READONLY_MEM
+#define __KVM_HAVE_VCPU_EVENTS
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 #define KVM_REG_SIZE(id) (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
 #define KVM_ARM_SVC_sp svc_regs[0]
@@ -69,6 +70,7 @@
 #define KVM_VGIC_V3_ADDR_TYPE_DIST 2
 #define KVM_VGIC_V3_ADDR_TYPE_REDIST 3
 #define KVM_VGIC_ITS_ADDR_TYPE 4
+#define KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION 5
 #define KVM_VGIC_V3_DIST_SIZE SZ_64K
 #define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K)
 #define KVM_VGIC_V3_ITS_SIZE (2 * SZ_64K)
@@ -91,6 +93,15 @@
 };
 struct kvm_arch_memory_slot {
 };
+struct kvm_vcpu_events {
+  struct {
+    __u8 serror_pending;
+    __u8 serror_has_esr;
+    __u8 pad[6];
+    __u64 serror_esr;
+  } exception;
+  __u32 reserved[12];
+};
 #define KVM_REG_ARM_COPROC_MASK 0x000000000FFF0000
 #define KVM_REG_ARM_COPROC_SHIFT 16
 #define KVM_REG_ARM_32_OPC2_MASK 0x0000000000000007
diff --git a/libc/kernel/uapi/asm-arm/asm/unistd-common.h b/libc/kernel/uapi/asm-arm/asm/unistd-common.h
index c9ee555..824a7d3 100644
--- a/libc/kernel/uapi/asm-arm/asm/unistd-common.h
+++ b/libc/kernel/uapi/asm-arm/asm/unistd-common.h
@@ -371,4 +371,6 @@
 #define __NR_pkey_alloc (__NR_SYSCALL_BASE + 395)
 #define __NR_pkey_free (__NR_SYSCALL_BASE + 396)
 #define __NR_statx (__NR_SYSCALL_BASE + 397)
+#define __NR_rseq (__NR_SYSCALL_BASE + 398)
+#define __NR_io_pgetevents (__NR_SYSCALL_BASE + 399)
 #endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/auxvec.h b/libc/kernel/uapi/asm-arm64/asm/auxvec.h
index 74fca55..4735fd5 100644
--- a/libc/kernel/uapi/asm-arm64/asm/auxvec.h
+++ b/libc/kernel/uapi/asm-arm64/asm/auxvec.h
@@ -19,5 +19,6 @@
 #ifndef __ASM_AUXVEC_H
 #define __ASM_AUXVEC_H
 #define AT_SYSINFO_EHDR 33
-#define AT_VECTOR_SIZE_ARCH 1
+#define AT_MINSIGSTKSZ 51
+#define AT_VECTOR_SIZE_ARCH 2
 #endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/kvm.h b/libc/kernel/uapi/asm-arm64/asm/kvm.h
index 167d811..e79562c 100644
--- a/libc/kernel/uapi/asm-arm64/asm/kvm.h
+++ b/libc/kernel/uapi/asm-arm64/asm/kvm.h
@@ -32,6 +32,7 @@
 #define __KVM_HAVE_GUEST_DEBUG
 #define __KVM_HAVE_IRQ_LINE
 #define __KVM_HAVE_READONLY_MEM
+#define __KVM_HAVE_VCPU_EVENTS
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 #define KVM_REG_SIZE(id) (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
 struct kvm_regs {
@@ -60,6 +61,7 @@
 #define KVM_VGIC_V3_ADDR_TYPE_DIST 2
 #define KVM_VGIC_V3_ADDR_TYPE_REDIST 3
 #define KVM_VGIC_ITS_ADDR_TYPE 4
+#define KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION 5
 #define KVM_VGIC_V3_DIST_SIZE SZ_64K
 #define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K)
 #define KVM_VGIC_V3_ITS_SIZE (2 * SZ_64K)
@@ -93,6 +95,15 @@
 };
 struct kvm_arch_memory_slot {
 };
+struct kvm_vcpu_events {
+  struct {
+    __u8 serror_pending;
+    __u8 serror_has_esr;
+    __u8 pad[6];
+    __u64 serror_esr;
+  } exception;
+  __u32 reserved[12];
+};
 #define KVM_REG_ARM_COPROC_MASK 0x000000000FFF0000
 #define KVM_REG_ARM_COPROC_SHIFT 16
 #define KVM_REG_ARM_CORE (0x0010 << KVM_REG_ARM_COPROC_SHIFT)
diff --git a/libc/kernel/uapi/asm-generic/hugetlb_encode.h b/libc/kernel/uapi/asm-generic/hugetlb_encode.h
index 68849b3..01a10ce 100644
--- a/libc/kernel/uapi/asm-generic/hugetlb_encode.h
+++ b/libc/kernel/uapi/asm-generic/hugetlb_encode.h
@@ -26,7 +26,9 @@
 #define HUGETLB_FLAG_ENCODE_2MB (21 << HUGETLB_FLAG_ENCODE_SHIFT)
 #define HUGETLB_FLAG_ENCODE_8MB (23 << HUGETLB_FLAG_ENCODE_SHIFT)
 #define HUGETLB_FLAG_ENCODE_16MB (24 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_32MB (25 << HUGETLB_FLAG_ENCODE_SHIFT)
 #define HUGETLB_FLAG_ENCODE_256MB (28 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_512MB (29 << HUGETLB_FLAG_ENCODE_SHIFT)
 #define HUGETLB_FLAG_ENCODE_1GB (30 << HUGETLB_FLAG_ENCODE_SHIFT)
 #define HUGETLB_FLAG_ENCODE_2GB (31 << HUGETLB_FLAG_ENCODE_SHIFT)
 #define HUGETLB_FLAG_ENCODE_16GB (34 << HUGETLB_FLAG_ENCODE_SHIFT)
diff --git a/libc/kernel/uapi/asm-generic/msgbuf.h b/libc/kernel/uapi/asm-generic/msgbuf.h
index 86a80a4..a8af16e 100644
--- a/libc/kernel/uapi/asm-generic/msgbuf.h
+++ b/libc/kernel/uapi/asm-generic/msgbuf.h
@@ -21,24 +21,24 @@
 #include <asm/bitsperlong.h>
 struct msqid64_ds {
   struct ipc64_perm msg_perm;
+#if __BITS_PER_LONG == 64
   __kernel_time_t msg_stime;
-#if __BITS_PER_LONG != 64
-  unsigned long __unused1;
-#endif
   __kernel_time_t msg_rtime;
-#if __BITS_PER_LONG != 64
-  unsigned long __unused2;
-#endif
   __kernel_time_t msg_ctime;
-#if __BITS_PER_LONG != 64
-  unsigned long __unused3;
+#else
+  unsigned long msg_stime;
+  unsigned long msg_stime_high;
+  unsigned long msg_rtime;
+  unsigned long msg_rtime_high;
+  unsigned long msg_ctime;
+  unsigned long msg_ctime_high;
 #endif
-  __kernel_ulong_t msg_cbytes;
-  __kernel_ulong_t msg_qnum;
-  __kernel_ulong_t msg_qbytes;
+  unsigned long msg_cbytes;
+  unsigned long msg_qnum;
+  unsigned long msg_qbytes;
   __kernel_pid_t msg_lspid;
   __kernel_pid_t msg_lrpid;
-  __kernel_ulong_t __unused4;
-  __kernel_ulong_t __unused5;
+  unsigned long __unused4;
+  unsigned long __unused5;
 };
 #endif
diff --git a/libc/kernel/uapi/asm-generic/posix_types.h b/libc/kernel/uapi/asm-generic/posix_types.h
index 1bafe1b..5aaa56d 100644
--- a/libc/kernel/uapi/asm-generic/posix_types.h
+++ b/libc/kernel/uapi/asm-generic/posix_types.h
@@ -75,6 +75,7 @@
 typedef __kernel_long_t __kernel_off_t;
 typedef long long __kernel_loff_t;
 typedef __kernel_long_t __kernel_time_t;
+typedef long long __kernel_time64_t;
 typedef __kernel_long_t __kernel_clock_t;
 typedef int __kernel_timer_t;
 typedef int __kernel_clockid_t;
diff --git a/libc/kernel/uapi/asm-generic/sembuf.h b/libc/kernel/uapi/asm-generic/sembuf.h
index 1a94bff..c8c1d29 100644
--- a/libc/kernel/uapi/asm-generic/sembuf.h
+++ b/libc/kernel/uapi/asm-generic/sembuf.h
@@ -21,13 +21,14 @@
 #include <asm/bitsperlong.h>
 struct semid64_ds {
   struct ipc64_perm sem_perm;
+#if __BITS_PER_LONG == 64
   __kernel_time_t sem_otime;
-#if __BITS_PER_LONG != 64
-  unsigned long __unused1;
-#endif
   __kernel_time_t sem_ctime;
-#if __BITS_PER_LONG != 64
-  unsigned long __unused2;
+#else
+  unsigned long sem_otime;
+  unsigned long sem_otime_high;
+  unsigned long sem_ctime;
+  unsigned long sem_ctime_high;
 #endif
   unsigned long sem_nsems;
   unsigned long __unused3;
diff --git a/libc/kernel/uapi/asm-generic/shmbuf.h b/libc/kernel/uapi/asm-generic/shmbuf.h
index 6d4d867..1d003ba 100644
--- a/libc/kernel/uapi/asm-generic/shmbuf.h
+++ b/libc/kernel/uapi/asm-generic/shmbuf.h
@@ -22,33 +22,33 @@
 struct shmid64_ds {
   struct ipc64_perm shm_perm;
   size_t shm_segsz;
+#if __BITS_PER_LONG == 64
   __kernel_time_t shm_atime;
-#if __BITS_PER_LONG != 64
-  unsigned long __unused1;
-#endif
   __kernel_time_t shm_dtime;
-#if __BITS_PER_LONG != 64
-  unsigned long __unused2;
-#endif
   __kernel_time_t shm_ctime;
-#if __BITS_PER_LONG != 64
-  unsigned long __unused3;
+#else
+  unsigned long shm_atime;
+  unsigned long shm_atime_high;
+  unsigned long shm_dtime;
+  unsigned long shm_dtime_high;
+  unsigned long shm_ctime;
+  unsigned long shm_ctime_high;
 #endif
   __kernel_pid_t shm_cpid;
   __kernel_pid_t shm_lpid;
-  __kernel_ulong_t shm_nattch;
-  __kernel_ulong_t __unused4;
-  __kernel_ulong_t __unused5;
+  unsigned long shm_nattch;
+  unsigned long __unused4;
+  unsigned long __unused5;
 };
 struct shminfo64 {
-  __kernel_ulong_t shmmax;
-  __kernel_ulong_t shmmin;
-  __kernel_ulong_t shmmni;
-  __kernel_ulong_t shmseg;
-  __kernel_ulong_t shmall;
-  __kernel_ulong_t __unused1;
-  __kernel_ulong_t __unused2;
-  __kernel_ulong_t __unused3;
-  __kernel_ulong_t __unused4;
+  unsigned long shmmax;
+  unsigned long shmmin;
+  unsigned long shmmni;
+  unsigned long shmseg;
+  unsigned long shmall;
+  unsigned long __unused1;
+  unsigned long __unused2;
+  unsigned long __unused3;
+  unsigned long __unused4;
 };
 #endif
diff --git a/libc/kernel/uapi/asm-generic/siginfo.h b/libc/kernel/uapi/asm-generic/siginfo.h
index af3d98e..166193b 100644
--- a/libc/kernel/uapi/asm-generic/siginfo.h
+++ b/libc/kernel/uapi/asm-generic/siginfo.h
@@ -194,7 +194,8 @@
 #define TRAP_TRACE 2
 #define TRAP_BRANCH 3
 #define TRAP_HWBKPT 4
-#define NSIGTRAP 4
+#define TRAP_UNK 5
+#define NSIGTRAP 5
 #define CLD_EXITED 1
 #define CLD_KILLED 2
 #define CLD_DUMPED 3
diff --git a/libc/kernel/uapi/asm-generic/socket.h b/libc/kernel/uapi/asm-generic/socket.h
index b821554..7c52ccc 100644
--- a/libc/kernel/uapi/asm-generic/socket.h
+++ b/libc/kernel/uapi/asm-generic/socket.h
@@ -88,4 +88,6 @@
 #define SCM_TIMESTAMPING_PKTINFO 58
 #define SO_PEERGROUPS 59
 #define SO_ZEROCOPY 60
+#define SO_TXTIME 61
+#define SCM_TXTIME SO_TXTIME
 #endif
diff --git a/libc/kernel/uapi/asm-generic/unistd.h b/libc/kernel/uapi/asm-generic/unistd.h
index 39b7c1a..52f0b57 100644
--- a/libc/kernel/uapi/asm-generic/unistd.h
+++ b/libc/kernel/uapi/asm-generic/unistd.h
@@ -317,8 +317,10 @@
 #define __NR_pkey_alloc 289
 #define __NR_pkey_free 290
 #define __NR_statx 291
+#define __NR_io_pgetevents 292
+#define __NR_rseq 293
 #undef __NR_syscalls
-#define __NR_syscalls 292
+#define __NR_syscalls 294
 #if __BITS_PER_LONG == 64 && !defined(__SYSCALL_COMPAT)
 #define __NR_fcntl __NR3264_fcntl
 #define __NR_statfs __NR3264_statfs
diff --git a/libc/kernel/uapi/asm-mips/asm/msgbuf.h b/libc/kernel/uapi/asm-mips/asm/msgbuf.h
index e64d9a9..e41761a 100644
--- a/libc/kernel/uapi/asm-mips/asm/msgbuf.h
+++ b/libc/kernel/uapi/asm-mips/asm/msgbuf.h
@@ -18,20 +18,12 @@
  ****************************************************************************/
 #ifndef _ASM_MSGBUF_H
 #define _ASM_MSGBUF_H
+#ifdef __mips64
 struct msqid64_ds {
   struct ipc64_perm msg_perm;
   __kernel_time_t msg_stime;
-#ifndef __mips64
-  unsigned long __unused1;
-#endif
   __kernel_time_t msg_rtime;
-#ifndef __mips64
-  unsigned long __unused2;
-#endif
   __kernel_time_t msg_ctime;
-#ifndef __mips64
-  unsigned long __unused3;
-#endif
   unsigned long msg_cbytes;
   unsigned long msg_qnum;
   unsigned long msg_qbytes;
@@ -40,4 +32,22 @@
   unsigned long __unused4;
   unsigned long __unused5;
 };
+#elif 1
+struct msqid64_ds {
+  struct ipc64_perm msg_perm;
+  unsigned long msg_stime;
+  unsigned long msg_stime_high;
+  unsigned long msg_rtime;
+  unsigned long msg_rtime_high;
+  unsigned long msg_ctime;
+  unsigned long msg_ctime_high;
+  unsigned long msg_cbytes;
+  unsigned long msg_qnum;
+  unsigned long msg_qbytes;
+  __kernel_pid_t msg_lspid;
+  __kernel_pid_t msg_lrpid;
+  unsigned long __unused4;
+  unsigned long __unused5;
+};
+#endif
 #endif
diff --git a/libc/kernel/uapi/asm-mips/asm/sembuf.h b/libc/kernel/uapi/asm-mips/asm/sembuf.h
index 25979ac..a46f326 100644
--- a/libc/kernel/uapi/asm-mips/asm/sembuf.h
+++ b/libc/kernel/uapi/asm-mips/asm/sembuf.h
@@ -18,6 +18,7 @@
  ****************************************************************************/
 #ifndef _ASM_SEMBUF_H
 #define _ASM_SEMBUF_H
+#ifdef __mips64
 struct semid64_ds {
   struct ipc64_perm sem_perm;
   __kernel_time_t sem_otime;
@@ -26,4 +27,14 @@
   unsigned long __unused1;
   unsigned long __unused2;
 };
+#else
+struct semid64_ds {
+  struct ipc64_perm sem_perm;
+  unsigned long sem_otime;
+  unsigned long sem_ctime;
+  unsigned long sem_nsems;
+  unsigned long sem_otime_high;
+  unsigned long sem_ctime_high;
+};
+#endif
 #endif
diff --git a/libc/kernel/uapi/asm-mips/asm/shmbuf.h b/libc/kernel/uapi/asm-mips/asm/shmbuf.h
index 0d1e8a1..9c42cee 100644
--- a/libc/kernel/uapi/asm-mips/asm/shmbuf.h
+++ b/libc/kernel/uapi/asm-mips/asm/shmbuf.h
@@ -18,6 +18,7 @@
  ****************************************************************************/
 #ifndef _ASM_SHMBUF_H
 #define _ASM_SHMBUF_H
+#ifdef __mips64
 struct shmid64_ds {
   struct ipc64_perm shm_perm;
   size_t shm_segsz;
@@ -30,6 +31,22 @@
   unsigned long __unused1;
   unsigned long __unused2;
 };
+#else
+struct shmid64_ds {
+  struct ipc64_perm shm_perm;
+  size_t shm_segsz;
+  unsigned long shm_atime;
+  unsigned long shm_dtime;
+  unsigned long shm_ctime;
+  __kernel_pid_t shm_cpid;
+  __kernel_pid_t shm_lpid;
+  unsigned long shm_nattch;
+  unsigned short shm_atime_high;
+  unsigned short shm_dtime_high;
+  unsigned short shm_ctime_high;
+  unsigned short __unused1;
+};
+#endif
 struct shminfo64 {
   unsigned long shmmax;
   unsigned long shmmin;
diff --git a/libc/kernel/uapi/asm-mips/asm/socket.h b/libc/kernel/uapi/asm-mips/asm/socket.h
index b8de15c..960b141 100644
--- a/libc/kernel/uapi/asm-mips/asm/socket.h
+++ b/libc/kernel/uapi/asm-mips/asm/socket.h
@@ -87,4 +87,6 @@
 #define SCM_TIMESTAMPING_PKTINFO 58
 #define SO_PEERGROUPS 59
 #define SO_ZEROCOPY 60
+#define SO_TXTIME 61
+#define SCM_TXTIME SO_TXTIME
 #endif
diff --git a/libc/kernel/uapi/asm-mips/asm/unistd.h b/libc/kernel/uapi/asm-mips/asm/unistd.h
index 76d7b81..e4dee2b 100644
--- a/libc/kernel/uapi/asm-mips/asm/unistd.h
+++ b/libc/kernel/uapi/asm-mips/asm/unistd.h
@@ -387,10 +387,12 @@
 #define __NR_pkey_alloc (__NR_Linux + 364)
 #define __NR_pkey_free (__NR_Linux + 365)
 #define __NR_statx (__NR_Linux + 366)
-#define __NR_Linux_syscalls 366
+#define __NR_rseq (__NR_Linux + 367)
+#define __NR_io_pgetevents (__NR_Linux + 368)
+#define __NR_Linux_syscalls 368
 #endif
 #define __NR_O32_Linux 4000
-#define __NR_O32_Linux_syscalls 366
+#define __NR_O32_Linux_syscalls 368
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 #define __NR_Linux 5000
 #define __NR_read (__NR_Linux + 0)
@@ -719,10 +721,12 @@
 #define __NR_pkey_alloc (__NR_Linux + 324)
 #define __NR_pkey_free (__NR_Linux + 325)
 #define __NR_statx (__NR_Linux + 326)
-#define __NR_Linux_syscalls 326
+#define __NR_rseq (__NR_Linux + 327)
+#define __NR_io_pgetevents (__NR_Linux + 328)
+#define __NR_Linux_syscalls 328
 #endif
 #define __NR_64_Linux 5000
-#define __NR_64_Linux_syscalls 326
+#define __NR_64_Linux_syscalls 328
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 #define __NR_Linux 6000
 #define __NR_read (__NR_Linux + 0)
@@ -1055,8 +1059,10 @@
 #define __NR_pkey_alloc (__NR_Linux + 328)
 #define __NR_pkey_free (__NR_Linux + 329)
 #define __NR_statx (__NR_Linux + 330)
-#define __NR_Linux_syscalls 330
+#define __NR_rseq (__NR_Linux + 331)
+#define __NR_io_pgetevents (__NR_Linux + 332)
+#define __NR_Linux_syscalls 332
 #endif
 #define __NR_N32_Linux 6000
-#define __NR_N32_Linux_syscalls 330
+#define __NR_N32_Linux_syscalls 332
 #endif
diff --git a/libc/kernel/uapi/asm-x86/asm/kvm.h b/libc/kernel/uapi/asm-x86/asm/kvm.h
index df1b396..1d7f767 100644
--- a/libc/kernel/uapi/asm-x86/asm/kvm.h
+++ b/libc/kernel/uapi/asm-x86/asm/kvm.h
@@ -313,4 +313,26 @@
 };
 #define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0)
 #define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1)
+#define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2)
+#define KVM_STATE_NESTED_GUEST_MODE 0x00000001
+#define KVM_STATE_NESTED_RUN_PENDING 0x00000002
+#define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001
+#define KVM_STATE_NESTED_SMM_VMXON 0x00000002
+struct kvm_vmx_nested_state {
+  __u64 vmxon_pa;
+  __u64 vmcs_pa;
+  struct {
+    __u16 flags;
+  } smm;
+};
+struct kvm_nested_state {
+  __u16 flags;
+  __u16 format;
+  __u32 size;
+  union {
+    struct kvm_vmx_nested_state vmx;
+    __u8 pad[120];
+  };
+  __u8 data[0];
+};
 #endif
diff --git a/libc/kernel/uapi/asm-x86/asm/kvm_para.h b/libc/kernel/uapi/asm-x86/asm/kvm_para.h
index 0e4f2e0..47ecca9 100644
--- a/libc/kernel/uapi/asm-x86/asm/kvm_para.h
+++ b/libc/kernel/uapi/asm-x86/asm/kvm_para.h
@@ -31,6 +31,7 @@
 #define KVM_FEATURE_PV_UNHALT 7
 #define KVM_FEATURE_PV_TLB_FLUSH 9
 #define KVM_FEATURE_ASYNC_PF_VMEXIT 10
+#define KVM_FEATURE_PV_SEND_IPI 11
 #define KVM_HINTS_REALTIME 0
 #define KVM_FEATURE_CLOCKSOURCE_STABLE_BIT 24
 #define MSR_KVM_WALL_CLOCK 0x11
diff --git a/libc/kernel/uapi/asm-x86/asm/sembuf.h b/libc/kernel/uapi/asm-x86/asm/sembuf.h
index 9b7e109..9b96722 100644
--- a/libc/kernel/uapi/asm-x86/asm/sembuf.h
+++ b/libc/kernel/uapi/asm-x86/asm/sembuf.h
@@ -20,10 +20,17 @@
 #define _ASM_X86_SEMBUF_H
 struct semid64_ds {
   struct ipc64_perm sem_perm;
+#ifdef __i386__
+  unsigned long sem_otime;
+  unsigned long sem_otime_high;
+  unsigned long sem_ctime;
+  unsigned long sem_ctime_high;
+#else
   __kernel_time_t sem_otime;
   __kernel_ulong_t __unused1;
   __kernel_time_t sem_ctime;
   __kernel_ulong_t __unused2;
+#endif
   __kernel_ulong_t sem_nsems;
   __kernel_ulong_t __unused3;
   __kernel_ulong_t __unused4;
diff --git a/libc/kernel/uapi/asm-x86/asm/unistd_32.h b/libc/kernel/uapi/asm-x86/asm/unistd_32.h
index 0038efb..4afa676 100644
--- a/libc/kernel/uapi/asm-x86/asm/unistd_32.h
+++ b/libc/kernel/uapi/asm-x86/asm/unistd_32.h
@@ -399,4 +399,6 @@
 #define __NR_pkey_free 382
 #define __NR_statx 383
 #define __NR_arch_prctl 384
+#define __NR_io_pgetevents 385
+#define __NR_rseq 386
 #endif
diff --git a/libc/kernel/uapi/asm-x86/asm/unistd_64.h b/libc/kernel/uapi/asm-x86/asm/unistd_64.h
index 3cde166..a118200 100644
--- a/libc/kernel/uapi/asm-x86/asm/unistd_64.h
+++ b/libc/kernel/uapi/asm-x86/asm/unistd_64.h
@@ -351,4 +351,6 @@
 #define __NR_pkey_alloc 330
 #define __NR_pkey_free 331
 #define __NR_statx 332
+#define __NR_io_pgetevents 333
+#define __NR_rseq 334
 #endif
diff --git a/libc/kernel/uapi/asm-x86/asm/unistd_x32.h b/libc/kernel/uapi/asm-x86/asm/unistd_x32.h
index e10cc6b..b5f3fb1 100644
--- a/libc/kernel/uapi/asm-x86/asm/unistd_x32.h
+++ b/libc/kernel/uapi/asm-x86/asm/unistd_x32.h
@@ -304,6 +304,8 @@
 #define __NR_pkey_alloc (__X32_SYSCALL_BIT + 330)
 #define __NR_pkey_free (__X32_SYSCALL_BIT + 331)
 #define __NR_statx (__X32_SYSCALL_BIT + 332)
+#define __NR_io_pgetevents (__X32_SYSCALL_BIT + 333)
+#define __NR_rseq (__X32_SYSCALL_BIT + 334)
 #define __NR_rt_sigaction (__X32_SYSCALL_BIT + 512)
 #define __NR_rt_sigreturn (__X32_SYSCALL_BIT + 513)
 #define __NR_ioctl (__X32_SYSCALL_BIT + 514)
diff --git a/libc/kernel/uapi/drm/amdgpu_drm.h b/libc/kernel/uapi/drm/amdgpu_drm.h
index 59f5260..bdf59d6 100644
--- a/libc/kernel/uapi/drm/amdgpu_drm.h
+++ b/libc/kernel/uapi/drm/amdgpu_drm.h
@@ -59,6 +59,7 @@
 #define AMDGPU_GEM_DOMAIN_GDS 0x8
 #define AMDGPU_GEM_DOMAIN_GWS 0x10
 #define AMDGPU_GEM_DOMAIN_OA 0x20
+#define AMDGPU_GEM_DOMAIN_MASK (AMDGPU_GEM_DOMAIN_CPU | AMDGPU_GEM_DOMAIN_GTT | AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GDS | AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA)
 #define AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED (1 << 0)
 #define AMDGPU_GEM_CREATE_NO_CPU_ACCESS (1 << 1)
 #define AMDGPU_GEM_CREATE_CPU_GTT_USWC (1 << 2)
@@ -67,6 +68,7 @@
 #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)
+#define AMDGPU_GEM_CREATE_MQD_GFX9 (1 << 8)
 struct drm_amdgpu_gem_create_in {
   __u64 bo_size;
   __u64 alignment;
@@ -305,13 +307,15 @@
 #define AMDGPU_HW_IP_UVD_ENC 5
 #define AMDGPU_HW_IP_VCN_DEC 6
 #define AMDGPU_HW_IP_VCN_ENC 7
-#define AMDGPU_HW_IP_NUM 8
+#define AMDGPU_HW_IP_VCN_JPEG 8
+#define AMDGPU_HW_IP_NUM 9
 #define AMDGPU_HW_IP_INSTANCE_MAX_COUNT 1
 #define AMDGPU_CHUNK_ID_IB 0x01
 #define AMDGPU_CHUNK_ID_FENCE 0x02
 #define AMDGPU_CHUNK_ID_DEPENDENCIES 0x03
 #define AMDGPU_CHUNK_ID_SYNCOBJ_IN 0x04
 #define AMDGPU_CHUNK_ID_SYNCOBJ_OUT 0x05
+#define AMDGPU_CHUNK_ID_BO_HANDLES 0x06
 struct drm_amdgpu_cs_chunk {
   __u32 chunk_id;
   __u32 length_dw;
@@ -334,6 +338,7 @@
 #define AMDGPU_IB_FLAG_CE (1 << 0)
 #define AMDGPU_IB_FLAG_PREAMBLE (1 << 1)
 #define AMDGPU_IB_FLAG_PREEMPT (1 << 2)
+#define AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE (1 << 3)
 struct drm_amdgpu_cs_chunk_ib {
   __u32 _pad;
   __u32 flags;
@@ -397,6 +402,9 @@
 #define AMDGPU_INFO_FW_SOS 0x0c
 #define AMDGPU_INFO_FW_ASD 0x0d
 #define AMDGPU_INFO_FW_VCN 0x0e
+#define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_CNTL 0x0f
+#define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_GPM_MEM 0x10
+#define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_SRM_MEM 0x11
 #define AMDGPU_INFO_NUM_BYTES_MOVED 0x0f
 #define AMDGPU_INFO_VRAM_USAGE 0x10
 #define AMDGPU_INFO_GTT_USAGE 0x11
diff --git a/libc/kernel/uapi/drm/drm.h b/libc/kernel/uapi/drm/drm.h
index ec0c1fa..21f23f4 100644
--- a/libc/kernel/uapi/drm/drm.h
+++ b/libc/kernel/uapi/drm/drm.h
@@ -369,6 +369,8 @@
 #define DRM_CLIENT_CAP_STEREO_3D 1
 #define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2
 #define DRM_CLIENT_CAP_ATOMIC 3
+#define DRM_CLIENT_CAP_ASPECT_RATIO 4
+#define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 5
 struct drm_set_client_cap {
   __u64 capability;
   __u64 value;
diff --git a/libc/kernel/uapi/drm/drm_fourcc.h b/libc/kernel/uapi/drm/drm_fourcc.h
index d5fb055..9634e99 100644
--- a/libc/kernel/uapi/drm/drm_fourcc.h
+++ b/libc/kernel/uapi/drm/drm_fourcc.h
@@ -106,6 +106,7 @@
 #define DRM_FORMAT_MOD_VENDOR_QCOM 0x05
 #define DRM_FORMAT_MOD_VENDOR_VIVANTE 0x06
 #define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07
+#define DRM_FORMAT_MOD_VENDOR_ARM 0x08
 #define DRM_FORMAT_RESERVED ((1ULL << 56) - 1)
 #define fourcc_mod_code(vendor,val) ((((__u64) DRM_FORMAT_MOD_VENDOR_ ##vendor) << 56) | ((val) & 0x00ffffffffffffffULL))
 #define DRM_FORMAT_MOD_INVALID fourcc_mod_code(NONE, DRM_FORMAT_RESERVED)
@@ -116,6 +117,7 @@
 #define I915_FORMAT_MOD_Y_TILED_CCS fourcc_mod_code(INTEL, 4)
 #define I915_FORMAT_MOD_Yf_TILED_CCS fourcc_mod_code(INTEL, 5)
 #define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1)
+#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1)
 #define DRM_FORMAT_MOD_VIVANTE_TILED fourcc_mod_code(VIVANTE, 1)
 #define DRM_FORMAT_MOD_VIVANTE_SUPER_TILED fourcc_mod_code(VIVANTE, 2)
 #define DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED fourcc_mod_code(VIVANTE, 3)
@@ -128,7 +130,31 @@
 #define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB fourcc_mod_code(NVIDIA, 0x13)
 #define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB fourcc_mod_code(NVIDIA, 0x14)
 #define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB fourcc_mod_code(NVIDIA, 0x15)
+#define __fourcc_mod_broadcom_param_shift 8
+#define __fourcc_mod_broadcom_param_bits 48
+#define fourcc_mod_broadcom_code(val,params) fourcc_mod_code(BROADCOM, ((((__u64) params) << __fourcc_mod_broadcom_param_shift) | val))
+#define fourcc_mod_broadcom_param(m) ((int) (((m) >> __fourcc_mod_broadcom_param_shift) & ((1ULL << __fourcc_mod_broadcom_param_bits) - 1)))
+#define fourcc_mod_broadcom_mod(m) ((m) & ~(((1ULL << __fourcc_mod_broadcom_param_bits) - 1) << __fourcc_mod_broadcom_param_shift))
 #define DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED fourcc_mod_code(BROADCOM, 1)
+#define DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(v) fourcc_mod_broadcom_code(2, v)
+#define DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(v) fourcc_mod_broadcom_code(3, v)
+#define DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(v) fourcc_mod_broadcom_code(4, v)
+#define DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(v) fourcc_mod_broadcom_code(5, v)
+#define DRM_FORMAT_MOD_BROADCOM_SAND32 DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(0)
+#define DRM_FORMAT_MOD_BROADCOM_SAND64 DRM_FORMAT_MOD_BROADCOM_SAND64_COL_HEIGHT(0)
+#define DRM_FORMAT_MOD_BROADCOM_SAND128 DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT(0)
+#define DRM_FORMAT_MOD_BROADCOM_SAND256 DRM_FORMAT_MOD_BROADCOM_SAND256_COL_HEIGHT(0)
+#define DRM_FORMAT_MOD_BROADCOM_UIF fourcc_mod_code(BROADCOM, 6)
+#define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) fourcc_mod_code(ARM, __afbc_mode)
+#define AFBC_FORMAT_MOD_BLOCK_SIZE_MASK 0xf
+#define AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 (1ULL)
+#define AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 (2ULL)
+#define AFBC_FORMAT_MOD_YTR (1ULL << 4)
+#define AFBC_FORMAT_MOD_SPLIT (1ULL << 5)
+#define AFBC_FORMAT_MOD_SPARSE (1ULL << 6)
+#define AFBC_FORMAT_MOD_CBR (1ULL << 7)
+#define AFBC_FORMAT_MOD_TILED (1ULL << 8)
+#define AFBC_FORMAT_MOD_SC (1ULL << 9)
 #ifdef __cplusplus
 #endif
 #endif
diff --git a/libc/kernel/uapi/drm/drm_mode.h b/libc/kernel/uapi/drm/drm_mode.h
index b91f161..06c26e4 100644
--- a/libc/kernel/uapi/drm/drm_mode.h
+++ b/libc/kernel/uapi/drm/drm_mode.h
@@ -60,10 +60,19 @@
 #define DRM_MODE_PICTURE_ASPECT_NONE 0
 #define DRM_MODE_PICTURE_ASPECT_4_3 1
 #define DRM_MODE_PICTURE_ASPECT_16_9 2
+#define DRM_MODE_PICTURE_ASPECT_64_27 3
+#define DRM_MODE_PICTURE_ASPECT_256_135 4
+#define DRM_MODE_CONTENT_TYPE_NO_DATA 0
+#define DRM_MODE_CONTENT_TYPE_GRAPHICS 1
+#define DRM_MODE_CONTENT_TYPE_PHOTO 2
+#define DRM_MODE_CONTENT_TYPE_CINEMA 3
+#define DRM_MODE_CONTENT_TYPE_GAME 4
 #define DRM_MODE_FLAG_PIC_AR_MASK (0x0F << 19)
 #define DRM_MODE_FLAG_PIC_AR_NONE (DRM_MODE_PICTURE_ASPECT_NONE << 19)
 #define DRM_MODE_FLAG_PIC_AR_4_3 (DRM_MODE_PICTURE_ASPECT_4_3 << 19)
 #define DRM_MODE_FLAG_PIC_AR_16_9 (DRM_MODE_PICTURE_ASPECT_16_9 << 19)
+#define DRM_MODE_FLAG_PIC_AR_64_27 (DRM_MODE_PICTURE_ASPECT_64_27 << 19)
+#define DRM_MODE_FLAG_PIC_AR_256_135 (DRM_MODE_PICTURE_ASPECT_256_135 << 19)
 #define DRM_MODE_FLAG_ALL (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_CSYNC | DRM_MODE_FLAG_PCSYNC | DRM_MODE_FLAG_NCSYNC | DRM_MODE_FLAG_HSKEW | DRM_MODE_FLAG_DBLCLK | DRM_MODE_FLAG_CLKDIV2 | DRM_MODE_FLAG_3D_MASK)
 #define DRM_MODE_DPMS_ON 0
 #define DRM_MODE_DPMS_STANDBY 1
@@ -207,6 +216,7 @@
 #define DRM_MODE_CONNECTOR_VIRTUAL 15
 #define DRM_MODE_CONNECTOR_DSI 16
 #define DRM_MODE_CONNECTOR_DPI 17
+#define DRM_MODE_CONNECTOR_WRITEBACK 18
 struct drm_mode_get_connector {
   __u64 encoders_ptr;
   __u64 modes_ptr;
diff --git a/libc/kernel/uapi/drm/exynos_drm.h b/libc/kernel/uapi/drm/exynos_drm.h
index ed9022b..8b27cbb 100644
--- a/libc/kernel/uapi/drm/exynos_drm.h
+++ b/libc/kernel/uapi/drm/exynos_drm.h
@@ -80,6 +80,109 @@
 struct drm_exynos_g2d_exec {
   __u64 async;
 };
+struct drm_exynos_ioctl_ipp_get_res {
+  __u32 count_ipps;
+  __u32 reserved;
+  __u64 ipp_id_ptr;
+};
+enum drm_exynos_ipp_format_type {
+  DRM_EXYNOS_IPP_FORMAT_SOURCE = 0x01,
+  DRM_EXYNOS_IPP_FORMAT_DESTINATION = 0x02,
+};
+struct drm_exynos_ipp_format {
+  __u32 fourcc;
+  __u32 type;
+  __u64 modifier;
+};
+enum drm_exynos_ipp_capability {
+  DRM_EXYNOS_IPP_CAP_CROP = 0x01,
+  DRM_EXYNOS_IPP_CAP_ROTATE = 0x02,
+  DRM_EXYNOS_IPP_CAP_SCALE = 0x04,
+  DRM_EXYNOS_IPP_CAP_CONVERT = 0x08,
+};
+struct drm_exynos_ioctl_ipp_get_caps {
+  __u32 ipp_id;
+  __u32 capabilities;
+  __u32 reserved;
+  __u32 formats_count;
+  __u64 formats_ptr;
+};
+enum drm_exynos_ipp_limit_type {
+  DRM_EXYNOS_IPP_LIMIT_TYPE_SIZE = 0x0001,
+  DRM_EXYNOS_IPP_LIMIT_TYPE_SCALE = 0x0002,
+  DRM_EXYNOS_IPP_LIMIT_SIZE_BUFFER = 0x0001 << 16,
+  DRM_EXYNOS_IPP_LIMIT_SIZE_AREA = 0x0002 << 16,
+  DRM_EXYNOS_IPP_LIMIT_SIZE_ROTATED = 0x0003 << 16,
+  DRM_EXYNOS_IPP_LIMIT_TYPE_MASK = 0x000f,
+  DRM_EXYNOS_IPP_LIMIT_SIZE_MASK = 0x000f << 16,
+};
+struct drm_exynos_ipp_limit_val {
+  __u32 min;
+  __u32 max;
+  __u32 align;
+  __u32 reserved;
+};
+struct drm_exynos_ipp_limit {
+  __u32 type;
+  __u32 reserved;
+  struct drm_exynos_ipp_limit_val h;
+  struct drm_exynos_ipp_limit_val v;
+};
+struct drm_exynos_ioctl_ipp_get_limits {
+  __u32 ipp_id;
+  __u32 fourcc;
+  __u64 modifier;
+  __u32 type;
+  __u32 limits_count;
+  __u64 limits_ptr;
+};
+enum drm_exynos_ipp_task_id {
+  DRM_EXYNOS_IPP_TASK_BUFFER = 0x0001,
+  DRM_EXYNOS_IPP_TASK_RECTANGLE = 0x0002,
+  DRM_EXYNOS_IPP_TASK_TRANSFORM = 0x0003,
+  DRM_EXYNOS_IPP_TASK_ALPHA = 0x0004,
+  DRM_EXYNOS_IPP_TASK_TYPE_SOURCE = 0x0001 << 16,
+  DRM_EXYNOS_IPP_TASK_TYPE_DESTINATION = 0x0002 << 16,
+};
+struct drm_exynos_ipp_task_buffer {
+  __u32 id;
+  __u32 fourcc;
+  __u32 width, height;
+  __u32 gem_id[4];
+  __u32 offset[4];
+  __u32 pitch[4];
+  __u64 modifier;
+};
+struct drm_exynos_ipp_task_rect {
+  __u32 id;
+  __u32 reserved;
+  __u32 x;
+  __u32 y;
+  __u32 w;
+  __u32 h;
+};
+struct drm_exynos_ipp_task_transform {
+  __u32 id;
+  __u32 rotation;
+};
+struct drm_exynos_ipp_task_alpha {
+  __u32 id;
+  __u32 value;
+};
+enum drm_exynos_ipp_flag {
+  DRM_EXYNOS_IPP_FLAG_EVENT = 0x01,
+  DRM_EXYNOS_IPP_FLAG_TEST_ONLY = 0x02,
+  DRM_EXYNOS_IPP_FLAG_NONBLOCK = 0x04,
+};
+#define DRM_EXYNOS_IPP_FLAGS (DRM_EXYNOS_IPP_FLAG_EVENT | DRM_EXYNOS_IPP_FLAG_TEST_ONLY | DRM_EXYNOS_IPP_FLAG_NONBLOCK)
+struct drm_exynos_ioctl_ipp_commit {
+  __u32 ipp_id;
+  __u32 flags;
+  __u32 reserved;
+  __u32 params_size;
+  __u64 params_ptr;
+  __u64 user_data;
+};
 #define DRM_EXYNOS_GEM_CREATE 0x00
 #define DRM_EXYNOS_GEM_MAP 0x01
 #define DRM_EXYNOS_GEM_GET 0x04
@@ -87,6 +190,10 @@
 #define DRM_EXYNOS_G2D_GET_VER 0x20
 #define DRM_EXYNOS_G2D_SET_CMDLIST 0x21
 #define DRM_EXYNOS_G2D_EXEC 0x22
+#define DRM_EXYNOS_IPP_GET_RESOURCES 0x40
+#define DRM_EXYNOS_IPP_GET_CAPS 0x41
+#define DRM_EXYNOS_IPP_GET_LIMITS 0x42
+#define DRM_EXYNOS_IPP_COMMIT 0x43
 #define DRM_IOCTL_EXYNOS_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_EXYNOS_GEM_CREATE, struct drm_exynos_gem_create)
 #define DRM_IOCTL_EXYNOS_GEM_MAP DRM_IOWR(DRM_COMMAND_BASE + DRM_EXYNOS_GEM_MAP, struct drm_exynos_gem_map)
 #define DRM_IOCTL_EXYNOS_GEM_GET DRM_IOWR(DRM_COMMAND_BASE + DRM_EXYNOS_GEM_GET, struct drm_exynos_gem_info)
@@ -94,7 +201,12 @@
 #define DRM_IOCTL_EXYNOS_G2D_GET_VER DRM_IOWR(DRM_COMMAND_BASE + DRM_EXYNOS_G2D_GET_VER, struct drm_exynos_g2d_get_ver)
 #define DRM_IOCTL_EXYNOS_G2D_SET_CMDLIST DRM_IOWR(DRM_COMMAND_BASE + DRM_EXYNOS_G2D_SET_CMDLIST, struct drm_exynos_g2d_set_cmdlist)
 #define DRM_IOCTL_EXYNOS_G2D_EXEC DRM_IOWR(DRM_COMMAND_BASE + DRM_EXYNOS_G2D_EXEC, struct drm_exynos_g2d_exec)
+#define DRM_IOCTL_EXYNOS_IPP_GET_RESOURCES DRM_IOWR(DRM_COMMAND_BASE + DRM_EXYNOS_IPP_GET_RESOURCES, struct drm_exynos_ioctl_ipp_get_res)
+#define DRM_IOCTL_EXYNOS_IPP_GET_CAPS DRM_IOWR(DRM_COMMAND_BASE + DRM_EXYNOS_IPP_GET_CAPS, struct drm_exynos_ioctl_ipp_get_caps)
+#define DRM_IOCTL_EXYNOS_IPP_GET_LIMITS DRM_IOWR(DRM_COMMAND_BASE + DRM_EXYNOS_IPP_GET_LIMITS, struct drm_exynos_ioctl_ipp_get_limits)
+#define DRM_IOCTL_EXYNOS_IPP_COMMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_EXYNOS_IPP_COMMIT, struct drm_exynos_ioctl_ipp_commit)
 #define DRM_EXYNOS_G2D_EVENT 0x80000000
+#define DRM_EXYNOS_IPP_EVENT 0x80000002
 struct drm_exynos_g2d_event {
   struct drm_event base;
   __u64 user_data;
@@ -103,6 +215,15 @@
   __u32 cmdlist_no;
   __u32 reserved;
 };
+struct drm_exynos_ipp_event {
+  struct drm_event base;
+  __u64 user_data;
+  __u32 tv_sec;
+  __u32 tv_usec;
+  __u32 ipp_id;
+  __u32 sequence;
+  __u64 reserved;
+};
 #ifdef __cplusplus
 #endif
 #endif
diff --git a/libc/kernel/uapi/drm/tegra_drm.h b/libc/kernel/uapi/drm/tegra_drm.h
index e0bcf95..ee111dc 100644
--- a/libc/kernel/uapi/drm/tegra_drm.h
+++ b/libc/kernel/uapi/drm/tegra_drm.h
@@ -154,7 +154,7 @@
 #define DRM_IOCTL_TEGRA_SYNCPT_INCR DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_INCR, struct drm_tegra_syncpt_incr)
 #define DRM_IOCTL_TEGRA_SYNCPT_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_WAIT, struct drm_tegra_syncpt_wait)
 #define DRM_IOCTL_TEGRA_OPEN_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_OPEN_CHANNEL, struct drm_tegra_open_channel)
-#define DRM_IOCTL_TEGRA_CLOSE_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_CLOSE_CHANNEL, struct drm_tegra_open_channel)
+#define DRM_IOCTL_TEGRA_CLOSE_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_CLOSE_CHANNEL, struct drm_tegra_close_channel)
 #define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt)
 #define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit)
 #define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base)
diff --git a/libc/kernel/uapi/drm/v3d_drm.h b/libc/kernel/uapi/drm/v3d_drm.h
new file mode 100644
index 0000000..c3e58cb
--- /dev/null
+++ b/libc/kernel/uapi/drm/v3d_drm.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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 _V3D_DRM_H_
+#define _V3D_DRM_H_
+#include "drm.h"
+#ifdef __cplusplus
+#endif
+#define DRM_V3D_SUBMIT_CL 0x00
+#define DRM_V3D_WAIT_BO 0x01
+#define DRM_V3D_CREATE_BO 0x02
+#define DRM_V3D_MMAP_BO 0x03
+#define DRM_V3D_GET_PARAM 0x04
+#define DRM_V3D_GET_BO_OFFSET 0x05
+#define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
+#define DRM_IOCTL_V3D_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
+#define DRM_IOCTL_V3D_CREATE_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_CREATE_BO, struct drm_v3d_create_bo)
+#define DRM_IOCTL_V3D_MMAP_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_MMAP_BO, struct drm_v3d_mmap_bo)
+#define DRM_IOCTL_V3D_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_PARAM, struct drm_v3d_get_param)
+#define DRM_IOCTL_V3D_GET_BO_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_BO_OFFSET, struct drm_v3d_get_bo_offset)
+struct drm_v3d_submit_cl {
+  __u32 bcl_start;
+  __u32 bcl_end;
+  __u32 rcl_start;
+  __u32 rcl_end;
+  __u32 in_sync_bcl;
+  __u32 in_sync_rcl;
+  __u32 out_sync;
+  __u32 qma;
+  __u32 qms;
+  __u32 qts;
+  __u64 bo_handles;
+  __u32 bo_handle_count;
+  __u32 pad;
+};
+struct drm_v3d_wait_bo {
+  __u32 handle;
+  __u32 pad;
+  __u64 timeout_ns;
+};
+struct drm_v3d_create_bo {
+  __u32 size;
+  __u32 flags;
+  __u32 handle;
+  __u32 offset;
+};
+struct drm_v3d_mmap_bo {
+  __u32 handle;
+  __u32 flags;
+  __u64 offset;
+};
+enum drm_v3d_param {
+  DRM_V3D_PARAM_V3D_UIFCFG,
+  DRM_V3D_PARAM_V3D_HUB_IDENT1,
+  DRM_V3D_PARAM_V3D_HUB_IDENT2,
+  DRM_V3D_PARAM_V3D_HUB_IDENT3,
+  DRM_V3D_PARAM_V3D_CORE0_IDENT0,
+  DRM_V3D_PARAM_V3D_CORE0_IDENT1,
+  DRM_V3D_PARAM_V3D_CORE0_IDENT2,
+};
+struct drm_v3d_get_param {
+  __u32 param;
+  __u32 pad;
+  __u64 value;
+};
+struct drm_v3d_get_bo_offset {
+  __u32 handle;
+  __u32 offset;
+};
+#ifdef __cplusplus
+#endif
+#endif
diff --git a/libc/kernel/uapi/drm/vc4_drm.h b/libc/kernel/uapi/drm/vc4_drm.h
index 05ed172..29eb872 100644
--- a/libc/kernel/uapi/drm/vc4_drm.h
+++ b/libc/kernel/uapi/drm/vc4_drm.h
@@ -91,6 +91,8 @@
   __u32 flags;
   __u64 seqno;
   __u32 perfmonid;
+  __u32 in_sync;
+  __u32 out_sync;
   __u32 pad2;
 };
 struct drm_vc4_wait_seqno {
diff --git a/libc/kernel/uapi/drm/vmwgfx_drm.h b/libc/kernel/uapi/drm/vmwgfx_drm.h
index f6a7b14..7df722a 100644
--- a/libc/kernel/uapi/drm/vmwgfx_drm.h
+++ b/libc/kernel/uapi/drm/vmwgfx_drm.h
@@ -25,6 +25,7 @@
 #define DRM_VMW_MAX_MIP_LEVELS 24
 #define DRM_VMW_GET_PARAM 0
 #define DRM_VMW_ALLOC_DMABUF 1
+#define DRM_VMW_ALLOC_BO 1
 #define DRM_VMW_UNREF_DMABUF 2
 #define DRM_VMW_HANDLE_CLOSE 2
 #define DRM_VMW_CURSOR_BYPASS 3
@@ -51,6 +52,8 @@
 #define DRM_VMW_GB_SURFACE_REF 24
 #define DRM_VMW_SYNCCPU 25
 #define DRM_VMW_CREATE_EXTENDED_CONTEXT 26
+#define DRM_VMW_GB_SURFACE_CREATE_EXT 27
+#define DRM_VMW_GB_SURFACE_REF_EXT 28
 #define DRM_VMW_PARAM_NUM_STREAMS 0
 #define DRM_VMW_PARAM_NUM_FREE_STREAMS 1
 #define DRM_VMW_PARAM_3D 2
@@ -64,6 +67,8 @@
 #define DRM_VMW_PARAM_MAX_MOB_SIZE 10
 #define DRM_VMW_PARAM_SCREEN_TARGET 11
 #define DRM_VMW_PARAM_DX 12
+#define DRM_VMW_PARAM_HW_CAPS2 13
+#define DRM_VMW_PARAM_SM4_1 14
 enum drm_vmw_handle_type {
   DRM_VMW_HANDLE_LEGACY = 0,
   DRM_VMW_HANDLE_PRIME = 1
@@ -124,25 +129,24 @@
   __s32 fd;
   __s32 error;
 };
-struct drm_vmw_alloc_dmabuf_req {
+struct drm_vmw_alloc_bo_req {
   __u32 size;
   __u32 pad64;
 };
-struct drm_vmw_dmabuf_rep {
+#define drm_vmw_alloc_dmabuf_req drm_vmw_alloc_bo_req
+struct drm_vmw_bo_rep {
   __u64 map_handle;
   __u32 handle;
   __u32 cur_gmr_id;
   __u32 cur_gmr_offset;
   __u32 pad64;
 };
-union drm_vmw_alloc_dmabuf_arg {
-  struct drm_vmw_alloc_dmabuf_req req;
-  struct drm_vmw_dmabuf_rep rep;
+#define drm_vmw_dmabuf_rep drm_vmw_bo_rep
+union drm_vmw_alloc_bo_arg {
+  struct drm_vmw_alloc_bo_req req;
+  struct drm_vmw_bo_rep rep;
 };
-struct drm_vmw_unref_dmabuf_arg {
-  __u32 handle;
-  __u32 pad64;
-};
+#define drm_vmw_alloc_dmabuf_arg drm_vmw_alloc_bo_arg
 struct drm_vmw_rect {
   __s32 x;
   __s32 y;
@@ -321,6 +325,30 @@
   __u32 handle;
   __u32 pad64;
 };
+#define drm_vmw_unref_dmabuf_arg drm_vmw_handle_close_arg
+enum drm_vmw_surface_version {
+  drm_vmw_gb_surface_v1
+};
+struct drm_vmw_gb_surface_create_ext_req {
+  struct drm_vmw_gb_surface_create_req base;
+  enum drm_vmw_surface_version version;
+  uint32_t svga3d_flags_upper_32_bits;
+  SVGA3dMSPattern multisample_pattern;
+  SVGA3dMSQualityLevel quality_level;
+  uint64_t must_be_zero;
+};
+union drm_vmw_gb_surface_create_ext_arg {
+  struct drm_vmw_gb_surface_create_rep rep;
+  struct drm_vmw_gb_surface_create_ext_req req;
+};
+struct drm_vmw_gb_surface_ref_ext_rep {
+  struct drm_vmw_gb_surface_create_ext_req creq;
+  struct drm_vmw_gb_surface_create_rep crep;
+};
+union drm_vmw_gb_surface_reference_ext_arg {
+  struct drm_vmw_gb_surface_ref_ext_rep rep;
+  struct drm_vmw_surface_arg req;
+};
 #ifdef __cplusplus
 #endif
 #endif
diff --git a/libc/kernel/uapi/linux/aio_abi.h b/libc/kernel/uapi/linux/aio_abi.h
index e71936d..17ca2f9 100644
--- a/libc/kernel/uapi/linux/aio_abi.h
+++ b/libc/kernel/uapi/linux/aio_abi.h
@@ -27,11 +27,13 @@
   IOCB_CMD_PWRITE = 1,
   IOCB_CMD_FSYNC = 2,
   IOCB_CMD_FDSYNC = 3,
+  IOCB_CMD_POLL = 5,
   IOCB_CMD_NOOP = 6,
   IOCB_CMD_PREADV = 7,
   IOCB_CMD_PWRITEV = 8,
 };
 #define IOCB_FLAG_RESFD (1 << 0)
+#define IOCB_FLAG_IOPRIO (1 << 1)
 struct io_event {
   __u64 data;
   __u64 obj;
diff --git a/libc/kernel/uapi/linux/audit.h b/libc/kernel/uapi/linux/audit.h
index be48b44..235a0e7 100644
--- a/libc/kernel/uapi/linux/audit.h
+++ b/libc/kernel/uapi/linux/audit.h
@@ -110,13 +110,16 @@
 #define AUDIT_INTEGRITY_HASH 1803
 #define AUDIT_INTEGRITY_PCR 1804
 #define AUDIT_INTEGRITY_RULE 1805
+#define AUDIT_INTEGRITY_EVM_XATTR 1806
+#define AUDIT_INTEGRITY_POLICY_RULE 1807
 #define AUDIT_KERNEL 2000
 #define AUDIT_FILTER_USER 0x00
 #define AUDIT_FILTER_TASK 0x01
 #define AUDIT_FILTER_ENTRY 0x02
 #define AUDIT_FILTER_WATCH 0x03
 #define AUDIT_FILTER_EXIT 0x04
-#define AUDIT_FILTER_TYPE 0x05
+#define AUDIT_FILTER_EXCLUDE 0x05
+#define AUDIT_FILTER_TYPE AUDIT_FILTER_EXCLUDE
 #define AUDIT_FILTER_FS 0x06
 #define AUDIT_NR_FILTERS 7
 #define AUDIT_FILTER_PREPEND 0x10
@@ -335,6 +338,7 @@
   __u32 log_passwd;
 };
 #define AUDIT_UID_UNSET (unsigned int) - 1
+#define AUDIT_SID_UNSET ((unsigned int) - 1)
 struct audit_rule_data {
   __u32 flags;
   __u32 action;
diff --git a/libc/kernel/uapi/linux/auto_fs.h b/libc/kernel/uapi/linux/auto_fs.h
index 93a3724..0264b86 100644
--- a/libc/kernel/uapi/linux/auto_fs.h
+++ b/libc/kernel/uapi/linux/auto_fs.h
@@ -21,9 +21,10 @@
 #include <linux/types.h>
 #include <linux/limits.h>
 #include <sys/ioctl.h>
-#define AUTOFS_PROTO_VERSION 3
-#define AUTOFS_MAX_PROTO_VERSION AUTOFS_PROTO_VERSION
-#define AUTOFS_MIN_PROTO_VERSION AUTOFS_PROTO_VERSION
+#define AUTOFS_PROTO_VERSION 5
+#define AUTOFS_MIN_PROTO_VERSION 3
+#define AUTOFS_MAX_PROTO_VERSION 5
+#define AUTOFS_PROTO_SUBVERSION 3
 #if defined(__ia64__) || defined(__alpha__)
 typedef unsigned long autofs_wqt_t;
 #else
@@ -62,4 +63,66 @@
 #define AUTOFS_IOC_SETTIMEOUT32 _IOWR(AUTOFS_IOCTL, AUTOFS_IOC_SETTIMEOUT_CMD, compat_ulong_t)
 #define AUTOFS_IOC_SETTIMEOUT _IOWR(AUTOFS_IOCTL, AUTOFS_IOC_SETTIMEOUT_CMD, unsigned long)
 #define AUTOFS_IOC_EXPIRE _IOR(AUTOFS_IOCTL, AUTOFS_IOC_EXPIRE_CMD, struct autofs_packet_expire)
+#define AUTOFS_EXP_NORMAL 0x00
+#define AUTOFS_EXP_IMMEDIATE 0x01
+#define AUTOFS_EXP_LEAVES 0x02
+#define AUTOFS_EXP_FORCED 0x04
+#define AUTOFS_TYPE_ANY 0U
+#define AUTOFS_TYPE_INDIRECT 1U
+#define AUTOFS_TYPE_DIRECT 2U
+#define AUTOFS_TYPE_OFFSET 4U
+enum autofs_notify {
+  NFY_NONE,
+  NFY_MOUNT,
+  NFY_EXPIRE
+};
+#define autofs_ptype_expire_multi 2
+#define autofs_ptype_missing_indirect 3
+#define autofs_ptype_expire_indirect 4
+#define autofs_ptype_missing_direct 5
+#define autofs_ptype_expire_direct 6
+struct autofs_packet_expire_multi {
+  struct autofs_packet_hdr hdr;
+  autofs_wqt_t wait_queue_token;
+  int len;
+  char name[NAME_MAX + 1];
+};
+union autofs_packet_union {
+  struct autofs_packet_hdr hdr;
+  struct autofs_packet_missing missing;
+  struct autofs_packet_expire expire;
+  struct autofs_packet_expire_multi expire_multi;
+};
+struct autofs_v5_packet {
+  struct autofs_packet_hdr hdr;
+  autofs_wqt_t wait_queue_token;
+  __u32 dev;
+  __u64 ino;
+  __u32 uid;
+  __u32 gid;
+  __u32 pid;
+  __u32 tgid;
+  __u32 len;
+  char name[NAME_MAX + 1];
+};
+typedef struct autofs_v5_packet autofs_packet_missing_indirect_t;
+typedef struct autofs_v5_packet autofs_packet_expire_indirect_t;
+typedef struct autofs_v5_packet autofs_packet_missing_direct_t;
+typedef struct autofs_v5_packet autofs_packet_expire_direct_t;
+union autofs_v5_packet_union {
+  struct autofs_packet_hdr hdr;
+  struct autofs_v5_packet v5_packet;
+  autofs_packet_missing_indirect_t missing_indirect;
+  autofs_packet_expire_indirect_t expire_indirect;
+  autofs_packet_missing_direct_t missing_direct;
+  autofs_packet_expire_direct_t expire_direct;
+};
+enum {
+  AUTOFS_IOC_EXPIRE_MULTI_CMD = 0x66,
+  AUTOFS_IOC_PROTOSUBVER_CMD,
+  AUTOFS_IOC_ASKUMOUNT_CMD = 0x70,
+};
+#define AUTOFS_IOC_EXPIRE_MULTI _IOW(AUTOFS_IOCTL, AUTOFS_IOC_EXPIRE_MULTI_CMD, int)
+#define AUTOFS_IOC_PROTOSUBVER _IOR(AUTOFS_IOCTL, AUTOFS_IOC_PROTOSUBVER_CMD, int)
+#define AUTOFS_IOC_ASKUMOUNT _IOR(AUTOFS_IOCTL, AUTOFS_IOC_ASKUMOUNT_CMD, int)
 #endif
diff --git a/libc/kernel/uapi/linux/auto_fs4.h b/libc/kernel/uapi/linux/auto_fs4.h
index be6766b..41f3c8c 100644
--- a/libc/kernel/uapi/linux/auto_fs4.h
+++ b/libc/kernel/uapi/linux/auto_fs4.h
@@ -16,75 +16,7 @@
  ***
  ****************************************************************************
  ****************************************************************************/
-#ifndef _LINUX_AUTO_FS4_H
-#define _LINUX_AUTO_FS4_H
-#include <linux/types.h>
+#ifndef _UAPI_LINUX_AUTO_FS4_H
+#define _UAPI_LINUX_AUTO_FS4_H
 #include <linux/auto_fs.h>
-#undef AUTOFS_PROTO_VERSION
-#undef AUTOFS_MIN_PROTO_VERSION
-#undef AUTOFS_MAX_PROTO_VERSION
-#define AUTOFS_PROTO_VERSION 5
-#define AUTOFS_MIN_PROTO_VERSION 3
-#define AUTOFS_MAX_PROTO_VERSION 5
-#define AUTOFS_PROTO_SUBVERSION 2
-#define AUTOFS_EXP_IMMEDIATE 1
-#define AUTOFS_EXP_LEAVES 2
-#define AUTOFS_TYPE_ANY 0U
-#define AUTOFS_TYPE_INDIRECT 1U
-#define AUTOFS_TYPE_DIRECT 2U
-#define AUTOFS_TYPE_OFFSET 4U
-enum autofs_notify {
-  NFY_NONE,
-  NFY_MOUNT,
-  NFY_EXPIRE
-};
-#define autofs_ptype_expire_multi 2
-#define autofs_ptype_missing_indirect 3
-#define autofs_ptype_expire_indirect 4
-#define autofs_ptype_missing_direct 5
-#define autofs_ptype_expire_direct 6
-struct autofs_packet_expire_multi {
-  struct autofs_packet_hdr hdr;
-  autofs_wqt_t wait_queue_token;
-  int len;
-  char name[NAME_MAX + 1];
-};
-union autofs_packet_union {
-  struct autofs_packet_hdr hdr;
-  struct autofs_packet_missing missing;
-  struct autofs_packet_expire expire;
-  struct autofs_packet_expire_multi expire_multi;
-};
-struct autofs_v5_packet {
-  struct autofs_packet_hdr hdr;
-  autofs_wqt_t wait_queue_token;
-  __u32 dev;
-  __u64 ino;
-  __u32 uid;
-  __u32 gid;
-  __u32 pid;
-  __u32 tgid;
-  __u32 len;
-  char name[NAME_MAX + 1];
-};
-typedef struct autofs_v5_packet autofs_packet_missing_indirect_t;
-typedef struct autofs_v5_packet autofs_packet_expire_indirect_t;
-typedef struct autofs_v5_packet autofs_packet_missing_direct_t;
-typedef struct autofs_v5_packet autofs_packet_expire_direct_t;
-union autofs_v5_packet_union {
-  struct autofs_packet_hdr hdr;
-  struct autofs_v5_packet v5_packet;
-  autofs_packet_missing_indirect_t missing_indirect;
-  autofs_packet_expire_indirect_t expire_indirect;
-  autofs_packet_missing_direct_t missing_direct;
-  autofs_packet_expire_direct_t expire_direct;
-};
-enum {
-  AUTOFS_IOC_EXPIRE_MULTI_CMD = 0x66,
-  AUTOFS_IOC_PROTOSUBVER_CMD,
-  AUTOFS_IOC_ASKUMOUNT_CMD = 0x70,
-};
-#define AUTOFS_IOC_EXPIRE_MULTI _IOW(AUTOFS_IOCTL, AUTOFS_IOC_EXPIRE_MULTI_CMD, int)
-#define AUTOFS_IOC_PROTOSUBVER _IOR(AUTOFS_IOCTL, AUTOFS_IOC_PROTOSUBVER_CMD, int)
-#define AUTOFS_IOC_ASKUMOUNT _IOR(AUTOFS_IOCTL, AUTOFS_IOC_ASKUMOUNT_CMD, int)
 #endif
diff --git a/libc/kernel/uapi/linux/bcache.h b/libc/kernel/uapi/linux/bcache.h
index 4c7e32a..1bee0a3 100644
--- a/libc/kernel/uapi/linux/bcache.h
+++ b/libc/kernel/uapi/linux/bcache.h
@@ -29,8 +29,8 @@
   __u64 ptr[];
 };
 #define KEY_FIELD(name,field,offset,size) BITMASK(name, struct bkey, field, offset, size)
-#define PTR_FIELD(name,offset,size) static inline __u64 name(const struct bkey * k, unsigned i) \
-{ return(k->ptr[i] >> offset) & ~(~0ULL << size); } static inline void SET_ ##name(struct bkey * k, unsigned i, __u64 v) \
+#define PTR_FIELD(name,offset,size) static inline __u64 name(const struct bkey * k, unsigned int i) \
+{ return(k->ptr[i] >> offset) & ~(~0ULL << size); } static inline void SET_ ##name(struct bkey * k, unsigned int i, __u64 v) \
 { k->ptr[i] &= ~(~(~0ULL << size) << offset); k->ptr[i] |= (v & ~(~0ULL << size)) << offset; \
 }
 #define KEY_SIZE_BITS 16
diff --git a/libc/kernel/uapi/linux/blkzoned.h b/libc/kernel/uapi/linux/blkzoned.h
index c071c98..eaff1d8 100644
--- a/libc/kernel/uapi/linux/blkzoned.h
+++ b/libc/kernel/uapi/linux/blkzoned.h
@@ -50,7 +50,7 @@
   __u32 nr_zones;
   __u8 reserved[4];
   struct blk_zone zones[0];
-} __packed;
+};
 struct blk_zone_range {
   __u64 sector;
   __u64 nr_sectors;
diff --git a/libc/kernel/uapi/linux/bpf.h b/libc/kernel/uapi/linux/bpf.h
index 0eb0d45..a187913 100644
--- a/libc/kernel/uapi/linux/bpf.h
+++ b/libc/kernel/uapi/linux/bpf.h
@@ -65,6 +65,10 @@
   __u32 prefixlen;
   __u8 data[0];
 };
+struct bpf_cgroup_storage_key {
+  __u64 cgroup_inode_id;
+  __u32 attach_type;
+};
 enum bpf_cmd {
   BPF_MAP_CREATE,
   BPF_MAP_LOOKUP_ELEM,
@@ -84,6 +88,9 @@
   BPF_OBJ_GET_INFO_BY_FD,
   BPF_PROG_QUERY,
   BPF_RAW_TRACEPOINT_OPEN,
+  BPF_BTF_LOAD,
+  BPF_BTF_GET_FD_BY_ID,
+  BPF_TASK_FD_QUERY,
 };
 enum bpf_map_type {
   BPF_MAP_TYPE_UNSPEC,
@@ -103,6 +110,10 @@
   BPF_MAP_TYPE_DEVMAP,
   BPF_MAP_TYPE_SOCKMAP,
   BPF_MAP_TYPE_CPUMAP,
+  BPF_MAP_TYPE_XSKMAP,
+  BPF_MAP_TYPE_SOCKHASH,
+  BPF_MAP_TYPE_CGROUP_STORAGE,
+  BPF_MAP_TYPE_REUSEPORT_SOCKARRAY,
 };
 enum bpf_prog_type {
   BPF_PROG_TYPE_UNSPEC,
@@ -124,6 +135,9 @@
   BPF_PROG_TYPE_SK_MSG,
   BPF_PROG_TYPE_RAW_TRACEPOINT,
   BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
+  BPF_PROG_TYPE_LWT_SEG6LOCAL,
+  BPF_PROG_TYPE_LIRC_MODE2,
+  BPF_PROG_TYPE_SK_REUSEPORT,
 };
 enum bpf_attach_type {
   BPF_CGROUP_INET_INGRESS,
@@ -140,6 +154,9 @@
   BPF_CGROUP_INET6_CONNECT,
   BPF_CGROUP_INET4_POST_BIND,
   BPF_CGROUP_INET6_POST_BIND,
+  BPF_CGROUP_UDP4_SENDMSG,
+  BPF_CGROUP_UDP6_SENDMSG,
+  BPF_LIRC_MODE2,
   __MAX_BPF_ATTACH_TYPE
 };
 #define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
@@ -184,6 +201,9 @@
     __u32 numa_node;
     char map_name[BPF_OBJ_NAME_LEN];
     __u32 map_ifindex;
+    __u32 btf_fd;
+    __u32 btf_key_type_id;
+    __u32 btf_value_type_id;
   };
   struct {
     __u32 map_fd;
@@ -234,6 +254,7 @@
       __u32 start_id;
       __u32 prog_id;
       __u32 map_id;
+      __u32 btf_id;
     };
     __u32 next_id;
     __u32 open_flags;
@@ -255,8 +276,26 @@
     __u64 name;
     __u32 prog_fd;
   } raw_tracepoint;
+  struct {
+    __aligned_u64 btf;
+    __aligned_u64 btf_log_buf;
+    __u32 btf_size;
+    __u32 btf_log_size;
+    __u32 btf_log_level;
+  };
+  struct {
+    __u32 pid;
+    __u32 fd;
+    __u32 flags;
+    __u32 buf_len;
+    __aligned_u64 buf;
+    __u32 prog_id;
+    __u32 fd_type;
+    __u64 probe_offset;
+    __u64 probe_addr;
+  } task_fd_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), FN(xdp_adjust_meta), FN(perf_event_read_value), FN(perf_prog_read_value), FN(getsockopt), FN(override_return), FN(sock_ops_cb_flags_set), FN(msg_redirect_map), FN(msg_apply_bytes), FN(msg_cork_bytes), FN(msg_pull_data), FN(bind),
+#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), FN(override_return), FN(sock_ops_cb_flags_set), FN(msg_redirect_map), FN(msg_apply_bytes), FN(msg_cork_bytes), FN(msg_pull_data), FN(bind), FN(xdp_adjust_tail), FN(skb_get_xfrm_state), FN(get_stack), FN(skb_load_bytes_relative), FN(fib_lookup), FN(sock_hash_update), FN(msg_redirect_hash), FN(sk_redirect_hash), FN(lwt_push_encap), FN(lwt_seg6_store_bytes), FN(lwt_seg6_adjust_srh), FN(lwt_seg6_action), FN(rc_repeat), FN(rc_keydown), FN(skb_cgroup_id), FN(get_current_cgroup_id), FN(get_local_storage), FN(sk_select_reuseport), FN(skb_ancestor_cgroup_id),
 #define __BPF_ENUM_FN(x) BPF_FUNC_ ##x
 enum bpf_func_id {
   __BPF_FUNC_MAPPER(__BPF_ENUM_FN) __BPF_FUNC_MAX_ID,
@@ -274,6 +313,7 @@
 #define BPF_F_USER_STACK (1ULL << 8)
 #define BPF_F_FAST_STACK_CMP (1ULL << 9)
 #define BPF_F_REUSE_STACKID (1ULL << 10)
+#define BPF_F_USER_BUILD_ID (1ULL << 11)
 #define BPF_F_ZERO_CSUM_TX (1ULL << 1)
 #define BPF_F_DONT_FRAGMENT (1ULL << 2)
 #define BPF_F_SEQ_NUMBER (1ULL << 3)
@@ -283,6 +323,14 @@
 enum bpf_adj_room_mode {
   BPF_ADJ_ROOM_NET,
 };
+enum bpf_hdr_start_off {
+  BPF_HDR_START_MAC,
+  BPF_HDR_START_NET,
+};
+enum bpf_lwt_encap_mode {
+  BPF_LWT_ENCAP_SEG6,
+  BPF_LWT_ENCAP_SEG6_INLINE
+};
 struct __sk_buff {
   __u32 len;
   __u32 pkt_type;
@@ -322,6 +370,16 @@
   __u16 tunnel_ext;
   __u32 tunnel_label;
 };
+struct bpf_xfrm_state {
+  __u32 reqid;
+  __u32 spi;
+  __u16 family;
+  __u16 ext;
+  union {
+    __u32 remote_ipv4;
+    __u32 remote_ipv6[4];
+  };
+};
 enum bpf_ret_code {
   BPF_OK = 0,
   BPF_DROP = 2,
@@ -360,6 +418,22 @@
 struct sk_msg_md {
   void * data;
   void * data_end;
+  __u32 family;
+  __u32 remote_ip4;
+  __u32 local_ip4;
+  __u32 remote_ip6[4];
+  __u32 local_ip6[4];
+  __u32 remote_port;
+  __u32 local_port;
+};
+struct sk_reuseport_md {
+  void * data;
+  void * data_end;
+  __u32 len;
+  __u32 eth_protocol;
+  __u32 ip_protocol;
+  __u32 bind_inany;
+  __u32 hash;
 };
 #define BPF_TAG_SIZE 8
 struct bpf_prog_info {
@@ -376,9 +450,13 @@
   __aligned_u64 map_ids;
   char name[BPF_OBJ_NAME_LEN];
   __u32 ifindex;
-  __u32 : 32;
+  __u32 gpl_compatible : 1;
   __u64 netns_dev;
   __u64 netns_ino;
+  __u32 nr_jited_ksyms;
+  __u32 nr_jited_func_lens;
+  __aligned_u64 jited_ksyms;
+  __aligned_u64 jited_func_lens;
 } __attribute__((aligned(8)));
 struct bpf_map_info {
   __u32 type;
@@ -392,6 +470,14 @@
   __u32 : 32;
   __u64 netns_dev;
   __u64 netns_ino;
+  __u32 btf_id;
+  __u32 btf_key_type_id;
+  __u32 btf_value_type_id;
+} __attribute__((aligned(8)));
+struct bpf_btf_info {
+  __aligned_u64 btf;
+  __u32 btf_size;
+  __u32 id;
 } __attribute__((aligned(8)));
 struct bpf_sock_addr {
   __u32 user_family;
@@ -401,6 +487,8 @@
   __u32 family;
   __u32 type;
   __u32 protocol;
+  __u32 msg_src_ip4;
+  __u32 msg_src_ip6[4];
 };
 struct bpf_sock_ops {
   __u32 op;
@@ -459,6 +547,7 @@
   BPF_SOCK_OPS_RTO_CB,
   BPF_SOCK_OPS_RETRANS_CB,
   BPF_SOCK_OPS_STATE_CB,
+  BPF_SOCK_OPS_TCP_LISTEN_CB,
 };
 enum {
   BPF_TCP_ESTABLISHED = 1,
@@ -495,4 +584,50 @@
 struct bpf_raw_tracepoint_args {
   __u64 args[0];
 };
+#define BPF_FIB_LOOKUP_DIRECT BIT(0)
+#define BPF_FIB_LOOKUP_OUTPUT BIT(1)
+enum {
+  BPF_FIB_LKUP_RET_SUCCESS,
+  BPF_FIB_LKUP_RET_BLACKHOLE,
+  BPF_FIB_LKUP_RET_UNREACHABLE,
+  BPF_FIB_LKUP_RET_PROHIBIT,
+  BPF_FIB_LKUP_RET_NOT_FWDED,
+  BPF_FIB_LKUP_RET_FWD_DISABLED,
+  BPF_FIB_LKUP_RET_UNSUPP_LWT,
+  BPF_FIB_LKUP_RET_NO_NEIGH,
+  BPF_FIB_LKUP_RET_FRAG_NEEDED,
+};
+struct bpf_fib_lookup {
+  __u8 family;
+  __u8 l4_protocol;
+  __be16 sport;
+  __be16 dport;
+  __u16 tot_len;
+  __u32 ifindex;
+  union {
+    __u8 tos;
+    __be32 flowinfo;
+    __u32 rt_metric;
+  };
+  union {
+    __be32 ipv4_src;
+    __u32 ipv6_src[4];
+  };
+  union {
+    __be32 ipv4_dst;
+    __u32 ipv6_dst[4];
+  };
+  __be16 h_vlan_proto;
+  __be16 h_vlan_TCI;
+  __u8 smac[6];
+  __u8 dmac[6];
+};
+enum bpf_task_fd_type {
+  BPF_FD_TYPE_RAW_TRACEPOINT,
+  BPF_FD_TYPE_TRACEPOINT,
+  BPF_FD_TYPE_KPROBE,
+  BPF_FD_TYPE_KRETPROBE,
+  BPF_FD_TYPE_UPROBE,
+  BPF_FD_TYPE_URETPROBE,
+};
 #endif
diff --git a/libc/kernel/uapi/linux/ncp_no.h b/libc/kernel/uapi/linux/bpfilter.h
similarity index 63%
copy from libc/kernel/uapi/linux/ncp_no.h
copy to libc/kernel/uapi/linux/bpfilter.h
index fe5caa0..a7d8d66 100644
--- a/libc/kernel/uapi/linux/ncp_no.h
+++ b/libc/kernel/uapi/linux/bpfilter.h
@@ -16,19 +16,19 @@
  ***
  ****************************************************************************
  ****************************************************************************/
-#ifndef _NCP_NO
-#define _NCP_NO
-#define aRONLY (__cpu_to_le32(1))
-#define aHIDDEN (__cpu_to_le32(2))
-#define aSYSTEM (__cpu_to_le32(4))
-#define aEXECUTE (__cpu_to_le32(8))
-#define aDIR (__cpu_to_le32(0x10))
-#define aARCH (__cpu_to_le32(0x20))
-#define aSHARED (__cpu_to_le32(0x80))
-#define aDONTSUBALLOCATE (__cpu_to_le32(1L << 11))
-#define aTRANSACTIONAL (__cpu_to_le32(1L << 12))
-#define aPURGE (__cpu_to_le32(1L << 16))
-#define aRENAMEINHIBIT (__cpu_to_le32(1L << 17))
-#define aDELETEINHIBIT (__cpu_to_le32(1L << 18))
-#define aDONTCOMPRESS (__cpu_to_le32(1L << 27))
+#ifndef _UAPI_LINUX_BPFILTER_H
+#define _UAPI_LINUX_BPFILTER_H
+#include <linux/if.h>
+enum {
+  BPFILTER_IPT_SO_SET_REPLACE = 64,
+  BPFILTER_IPT_SO_SET_ADD_COUNTERS = 65,
+  BPFILTER_IPT_SET_MAX,
+};
+enum {
+  BPFILTER_IPT_SO_GET_INFO = 64,
+  BPFILTER_IPT_SO_GET_ENTRIES = 65,
+  BPFILTER_IPT_SO_GET_REVISION_MATCH = 66,
+  BPFILTER_IPT_SO_GET_REVISION_TARGET = 67,
+  BPFILTER_IPT_GET_MAX,
+};
 #endif
diff --git a/libc/kernel/uapi/linux/btf.h b/libc/kernel/uapi/linux/btf.h
new file mode 100644
index 0000000..33dde5a
--- /dev/null
+++ b/libc/kernel/uapi/linux/btf.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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_BTF_H__
+#define _UAPI__LINUX_BTF_H__
+#include <linux/types.h>
+#define BTF_MAGIC 0xeB9F
+#define BTF_VERSION 1
+struct btf_header {
+  __u16 magic;
+  __u8 version;
+  __u8 flags;
+  __u32 hdr_len;
+  __u32 type_off;
+  __u32 type_len;
+  __u32 str_off;
+  __u32 str_len;
+};
+#define BTF_MAX_TYPE 0x0000ffff
+#define BTF_MAX_NAME_OFFSET 0x0000ffff
+#define BTF_MAX_VLEN 0xffff
+struct btf_type {
+  __u32 name_off;
+  __u32 info;
+  union {
+    __u32 size;
+    __u32 type;
+  };
+};
+#define BTF_INFO_KIND(info) (((info) >> 24) & 0x0f)
+#define BTF_INFO_VLEN(info) ((info) & 0xffff)
+#define BTF_KIND_UNKN 0
+#define BTF_KIND_INT 1
+#define BTF_KIND_PTR 2
+#define BTF_KIND_ARRAY 3
+#define BTF_KIND_STRUCT 4
+#define BTF_KIND_UNION 5
+#define BTF_KIND_ENUM 6
+#define BTF_KIND_FWD 7
+#define BTF_KIND_TYPEDEF 8
+#define BTF_KIND_VOLATILE 9
+#define BTF_KIND_CONST 10
+#define BTF_KIND_RESTRICT 11
+#define BTF_KIND_MAX 11
+#define NR_BTF_KINDS 12
+#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
+#define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16)
+#define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff)
+#define BTF_INT_SIGNED (1 << 0)
+#define BTF_INT_CHAR (1 << 1)
+#define BTF_INT_BOOL (1 << 2)
+struct btf_enum {
+  __u32 name_off;
+  __s32 val;
+};
+struct btf_array {
+  __u32 type;
+  __u32 index_type;
+  __u32 nelems;
+};
+struct btf_member {
+  __u32 name_off;
+  __u32 type;
+  __u32 offset;
+};
+#endif
diff --git a/libc/kernel/uapi/linux/btrfs.h b/libc/kernel/uapi/linux/btrfs.h
index a162bb0..2bb79d8 100644
--- a/libc/kernel/uapi/linux/btrfs.h
+++ b/libc/kernel/uapi/linux/btrfs.h
@@ -248,6 +248,13 @@
   __u64 objectid;
   char name[BTRFS_INO_LOOKUP_PATH_MAX];
 };
+#define BTRFS_INO_LOOKUP_USER_PATH_MAX (4080 - BTRFS_VOL_NAME_MAX - 1)
+struct btrfs_ioctl_ino_lookup_user_args {
+  __u64 dirid;
+  __u64 treeid;
+  char name[BTRFS_VOL_NAME_MAX + 1];
+  char path[BTRFS_INO_LOOKUP_USER_PATH_MAX];
+};
 struct btrfs_ioctl_search_key {
   __u64 tree_id;
   __u64 min_objectid;
@@ -406,6 +413,36 @@
   __u64 flags;
   __u64 reserved[4];
 };
+struct btrfs_ioctl_get_subvol_info_args {
+  __u64 treeid;
+  char name[BTRFS_VOL_NAME_MAX + 1];
+  __u64 parent_id;
+  __u64 dirid;
+  __u64 generation;
+  __u64 flags;
+  __u8 uuid[BTRFS_UUID_SIZE];
+  __u8 parent_uuid[BTRFS_UUID_SIZE];
+  __u8 received_uuid[BTRFS_UUID_SIZE];
+  __u64 ctransid;
+  __u64 otransid;
+  __u64 stransid;
+  __u64 rtransid;
+  struct btrfs_ioctl_timespec ctime;
+  struct btrfs_ioctl_timespec otime;
+  struct btrfs_ioctl_timespec stime;
+  struct btrfs_ioctl_timespec rtime;
+  __u64 reserved[8];
+};
+#define BTRFS_MAX_ROOTREF_BUFFER_NUM 255
+struct btrfs_ioctl_get_subvol_rootref_args {
+  __u64 min_treeid;
+  struct {
+    __u64 treeid;
+    __u64 dirid;
+  } rootref[BTRFS_MAX_ROOTREF_BUFFER_NUM];
+  __u8 num_items;
+  __u8 align[7];
+};
 enum btrfs_err_code {
   BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET = 1,
   BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET,
@@ -472,4 +509,7 @@
 #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)
+#define BTRFS_IOC_GET_SUBVOL_INFO _IOR(BTRFS_IOCTL_MAGIC, 60, struct btrfs_ioctl_get_subvol_info_args)
+#define BTRFS_IOC_GET_SUBVOL_ROOTREF _IOWR(BTRFS_IOCTL_MAGIC, 61, struct btrfs_ioctl_get_subvol_rootref_args)
+#define BTRFS_IOC_INO_LOOKUP_USER _IOWR(BTRFS_IOCTL_MAGIC, 62, struct btrfs_ioctl_ino_lookup_user_args)
 #endif
diff --git a/libc/kernel/uapi/linux/cec.h b/libc/kernel/uapi/linux/cec.h
index 98892f7..fd0f824 100644
--- a/libc/kernel/uapi/linux/cec.h
+++ b/libc/kernel/uapi/linux/cec.h
@@ -132,6 +132,8 @@
 #define CEC_EVENT_PIN_CEC_HIGH 4
 #define CEC_EVENT_PIN_HPD_LOW 5
 #define CEC_EVENT_PIN_HPD_HIGH 6
+#define CEC_EVENT_PIN_5V_LOW 7
+#define CEC_EVENT_PIN_5V_HIGH 8
 #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/cn_proc.h b/libc/kernel/uapi/linux/cn_proc.h
index 8aa48a8..411b725 100644
--- a/libc/kernel/uapi/linux/cn_proc.h
+++ b/libc/kernel/uapi/linux/cn_proc.h
@@ -82,11 +82,15 @@
     struct coredump_proc_event {
       __kernel_pid_t process_pid;
       __kernel_pid_t process_tgid;
+      __kernel_pid_t parent_pid;
+      __kernel_pid_t parent_tgid;
     } coredump;
     struct exit_proc_event {
       __kernel_pid_t process_pid;
       __kernel_pid_t process_tgid;
       __u32 exit_code, exit_signal;
+      __kernel_pid_t parent_pid;
+      __kernel_pid_t parent_tgid;
     } exit;
   } event_data;
 };
diff --git a/libc/kernel/uapi/linux/dcbnl.h b/libc/kernel/uapi/linux/dcbnl.h
index 2fe4cce..d1f2eba 100644
--- a/libc/kernel/uapi/linux/dcbnl.h
+++ b/libc/kernel/uapi/linux/dcbnl.h
@@ -71,6 +71,13 @@
   __u64 requests[IEEE_8021QAZ_MAX_TCS];
   __u64 indications[IEEE_8021QAZ_MAX_TCS];
 };
+#define IEEE_8021Q_MAX_PRIORITIES 8
+#define DCBX_MAX_BUFFERS 8
+struct dcbnl_buffer {
+  __u8 prio2buffer[IEEE_8021Q_MAX_PRIORITIES];
+  __u32 buffer_size[DCBX_MAX_BUFFERS];
+  __u32 total_size;
+};
 #define CEE_DCBX_MAX_PGS 8
 #define CEE_DCBX_MAX_PRIO 8
 struct cee_pg {
@@ -170,6 +177,7 @@
   DCB_ATTR_IEEE_MAXRATE,
   DCB_ATTR_IEEE_QCN,
   DCB_ATTR_IEEE_QCN_STATS,
+  DCB_ATTR_DCB_BUFFER,
   __DCB_ATTR_IEEE_MAX
 };
 #define DCB_ATTR_IEEE_MAX (__DCB_ATTR_IEEE_MAX - 1)
diff --git a/libc/kernel/uapi/linux/devlink.h b/libc/kernel/uapi/linux/devlink.h
index 07c5752..ead40ad 100644
--- a/libc/kernel/uapi/linux/devlink.h
+++ b/libc/kernel/uapi/linux/devlink.h
@@ -62,6 +62,15 @@
   DEVLINK_CMD_RESOURCE_SET,
   DEVLINK_CMD_RESOURCE_DUMP,
   DEVLINK_CMD_RELOAD,
+  DEVLINK_CMD_PARAM_GET,
+  DEVLINK_CMD_PARAM_SET,
+  DEVLINK_CMD_PARAM_NEW,
+  DEVLINK_CMD_PARAM_DEL,
+  DEVLINK_CMD_REGION_GET,
+  DEVLINK_CMD_REGION_SET,
+  DEVLINK_CMD_REGION_NEW,
+  DEVLINK_CMD_REGION_DEL,
+  DEVLINK_CMD_REGION_READ,
   __DEVLINK_CMD_MAX,
   DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1
 };
@@ -94,6 +103,18 @@
   DEVLINK_ESWITCH_ENCAP_MODE_NONE,
   DEVLINK_ESWITCH_ENCAP_MODE_BASIC,
 };
+enum devlink_port_flavour {
+  DEVLINK_PORT_FLAVOUR_PHYSICAL,
+  DEVLINK_PORT_FLAVOUR_CPU,
+  DEVLINK_PORT_FLAVOUR_DSA,
+};
+enum devlink_param_cmode {
+  DEVLINK_PARAM_CMODE_RUNTIME,
+  DEVLINK_PARAM_CMODE_DRIVERINIT,
+  DEVLINK_PARAM_CMODE_PERMANENT,
+  __DEVLINK_PARAM_CMODE_MAX,
+  DEVLINK_PARAM_CMODE_MAX = __DEVLINK_PARAM_CMODE_MAX - 1
+};
 enum devlink_attr {
   DEVLINK_ATTR_UNSPEC,
   DEVLINK_ATTR_BUS_NAME,
@@ -172,6 +193,27 @@
   DEVLINK_ATTR_RESOURCE_OCC,
   DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID,
   DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS,
+  DEVLINK_ATTR_PORT_FLAVOUR,
+  DEVLINK_ATTR_PORT_NUMBER,
+  DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER,
+  DEVLINK_ATTR_PARAM,
+  DEVLINK_ATTR_PARAM_NAME,
+  DEVLINK_ATTR_PARAM_GENERIC,
+  DEVLINK_ATTR_PARAM_TYPE,
+  DEVLINK_ATTR_PARAM_VALUES_LIST,
+  DEVLINK_ATTR_PARAM_VALUE,
+  DEVLINK_ATTR_PARAM_VALUE_DATA,
+  DEVLINK_ATTR_PARAM_VALUE_CMODE,
+  DEVLINK_ATTR_REGION_NAME,
+  DEVLINK_ATTR_REGION_SIZE,
+  DEVLINK_ATTR_REGION_SNAPSHOTS,
+  DEVLINK_ATTR_REGION_SNAPSHOT,
+  DEVLINK_ATTR_REGION_SNAPSHOT_ID,
+  DEVLINK_ATTR_REGION_CHUNKS,
+  DEVLINK_ATTR_REGION_CHUNK,
+  DEVLINK_ATTR_REGION_CHUNK_DATA,
+  DEVLINK_ATTR_REGION_CHUNK_ADDR,
+  DEVLINK_ATTR_REGION_CHUNK_LEN,
   __DEVLINK_ATTR_MAX,
   DEVLINK_ATTR_MAX = __DEVLINK_ATTR_MAX - 1
 };
diff --git a/libc/kernel/uapi/linux/dvb/audio.h b/libc/kernel/uapi/linux/dvb/audio.h
index e606f79..0a527c1 100644
--- a/libc/kernel/uapi/linux/dvb/audio.h
+++ b/libc/kernel/uapi/linux/dvb/audio.h
@@ -48,12 +48,6 @@
   int bypass_mode;
   audio_mixer_t mixer_state;
 } audio_status_t;
-typedef struct audio_karaoke {
-  int vocal1;
-  int vocal2;
-  int melody;
-} audio_karaoke_t;
-typedef __u16 audio_attributes_t;
 #define AUDIO_CAP_DTS 1
 #define AUDIO_CAP_LPCM 2
 #define AUDIO_CAP_MP1 4
@@ -78,9 +72,5 @@
 #define AUDIO_SET_ID _IO('o', 13)
 #define AUDIO_SET_MIXER _IOW('o', 14, audio_mixer_t)
 #define AUDIO_SET_STREAMTYPE _IO('o', 15)
-#define AUDIO_SET_EXT_ID _IO('o', 16)
-#define AUDIO_SET_ATTRIBUTES _IOW('o', 17, audio_attributes_t)
-#define AUDIO_SET_KARAOKE _IOW('o', 18, audio_karaoke_t)
-#define AUDIO_GET_PTS _IOR('o', 19, __u64)
 #define AUDIO_BILINGUAL_CHANNEL_SELECT _IO('o', 20)
 #endif
diff --git a/libc/kernel/uapi/linux/dvb/video.h b/libc/kernel/uapi/linux/dvb/video.h
index 7ada1a0..6577e1f 100644
--- a/libc/kernel/uapi/linux/dvb/video.h
+++ b/libc/kernel/uapi/linux/dvb/video.h
@@ -26,16 +26,6 @@
   VIDEO_FORMAT_221_1
 } video_format_t;
 typedef enum {
-  VIDEO_SYSTEM_PAL,
-  VIDEO_SYSTEM_NTSC,
-  VIDEO_SYSTEM_PALN,
-  VIDEO_SYSTEM_PALNc,
-  VIDEO_SYSTEM_PALM,
-  VIDEO_SYSTEM_NTSC60,
-  VIDEO_SYSTEM_PAL60,
-  VIDEO_SYSTEM_PALM60
-} video_system_t;
-typedef enum {
   VIDEO_PAN_SCAN,
   VIDEO_LETTER_BOX,
   VIDEO_CENTER_CUT_OUT
@@ -107,27 +97,6 @@
   char __user * iFrame;
   __s32 size;
 };
-typedef struct video_highlight {
-  int active;
-  __u8 contrast1;
-  __u8 contrast2;
-  __u8 color1;
-  __u8 color2;
-  __u32 ypos;
-  __u32 xpos;
-} video_highlight_t;
-typedef struct video_spu {
-  int active;
-  int stream_id;
-} video_spu_t;
-typedef struct video_spu_palette {
-  int length;
-  __u8 __user * palette;
-} video_spu_palette_t;
-typedef struct video_navi_pack {
-  int length;
-  __u8 data[1024];
-} video_navi_pack_t;
 typedef __u16 video_attributes_t;
 #define VIDEO_CAP_MPEG1 1
 #define VIDEO_CAP_MPEG2 2
@@ -150,17 +119,9 @@
 #define VIDEO_SLOWMOTION _IO('o', 32)
 #define VIDEO_GET_CAPABILITIES _IOR('o', 33, unsigned int)
 #define VIDEO_CLEAR_BUFFER _IO('o', 34)
-#define VIDEO_SET_ID _IO('o', 35)
 #define VIDEO_SET_STREAMTYPE _IO('o', 36)
 #define VIDEO_SET_FORMAT _IO('o', 37)
-#define VIDEO_SET_SYSTEM _IO('o', 38)
-#define VIDEO_SET_HIGHLIGHT _IOW('o', 39, video_highlight_t)
-#define VIDEO_SET_SPU _IOW('o', 50, video_spu_t)
-#define VIDEO_SET_SPU_PALETTE _IOW('o', 51, video_spu_palette_t)
-#define VIDEO_GET_NAVI _IOR('o', 52, video_navi_pack_t)
-#define VIDEO_SET_ATTRIBUTES _IO('o', 53)
 #define VIDEO_GET_SIZE _IOR('o', 55, video_size_t)
-#define VIDEO_GET_FRAME_RATE _IOR('o', 56, unsigned int)
 #define VIDEO_GET_PTS _IOR('o', 57, __u64)
 #define VIDEO_GET_FRAME_COUNT _IOR('o', 58, __u64)
 #define VIDEO_COMMAND _IOWR('o', 59, struct video_command)
diff --git a/libc/kernel/uapi/linux/elf.h b/libc/kernel/uapi/linux/elf.h
index 195ef09..1f69e1b 100644
--- a/libc/kernel/uapi/linux/elf.h
+++ b/libc/kernel/uapi/linux/elf.h
@@ -356,6 +356,9 @@
 #define NT_ARM_SYSTEM_CALL 0x404
 #define NT_ARM_SVE 0x405
 #define NT_ARC_V2 0x600
+#define NT_VMCOREDD 0x700
+#define NT_MIPS_DSP 0x800
+#define NT_MIPS_FP_MODE 0x801
 typedef struct elf32_note {
   Elf32_Word n_namesz;
   Elf32_Word n_descsz;
diff --git a/libc/kernel/uapi/linux/errqueue.h b/libc/kernel/uapi/linux/errqueue.h
index 196189b..f4a244f 100644
--- a/libc/kernel/uapi/linux/errqueue.h
+++ b/libc/kernel/uapi/linux/errqueue.h
@@ -34,9 +34,12 @@
 #define SO_EE_ORIGIN_ICMP6 3
 #define SO_EE_ORIGIN_TXSTATUS 4
 #define SO_EE_ORIGIN_ZEROCOPY 5
+#define SO_EE_ORIGIN_TXTIME 6
 #define SO_EE_ORIGIN_TIMESTAMPING SO_EE_ORIGIN_TXSTATUS
 #define SO_EE_OFFENDER(ee) ((struct sockaddr *) ((ee) + 1))
 #define SO_EE_CODE_ZEROCOPY_COPIED 1
+#define SO_EE_CODE_TXTIME_INVALID_PARAM 1
+#define SO_EE_CODE_TXTIME_MISSED 2
 struct scm_timestamping {
   struct timespec ts[3];
 };
diff --git a/libc/kernel/uapi/linux/ethtool.h b/libc/kernel/uapi/linux/ethtool.h
index 92607f9..25e1a9e 100644
--- a/libc/kernel/uapi/linux/ethtool.h
+++ b/libc/kernel/uapi/linux/ethtool.h
@@ -320,6 +320,17 @@
 #define ETHTOOL_RX_FLOW_SPEC_RING 0x00000000FFFFFFFFLL
 #define ETHTOOL_RX_FLOW_SPEC_RING_VF 0x000000FF00000000LL
 #define ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF 32
+struct ethtool_rxnfc {
+  __u32 cmd;
+  __u32 flow_type;
+  __u64 data;
+  struct ethtool_rx_flow_spec fs;
+  union {
+    __u32 rule_cnt;
+    __u32 rss_context;
+  };
+  __u32 rule_locs[0];
+};
 struct ethtool_rxfh_indir {
   __u32 cmd;
   __u32 size;
@@ -683,6 +694,7 @@
 #define WAKE_ARP (1 << 4)
 #define WAKE_MAGIC (1 << 5)
 #define WAKE_MAGICSECURE (1 << 6)
+#define WAKE_FILTER (1 << 7)
 #define TCP_V4_FLOW 0x01
 #define UDP_V4_FLOW 0x02
 #define SCTP_V4_FLOW 0x03
@@ -713,6 +725,7 @@
 #define RXH_L4_B_2_3 (1 << 7)
 #define RXH_DISCARD (1 << 31)
 #define RX_CLS_FLOW_DISC 0xffffffffffffffffULL
+#define RX_CLS_FLOW_WAKE 0xfffffffffffffffeULL
 #define RX_CLS_LOC_SPECIAL 0x80000000
 #define RX_CLS_LOC_ANY 0xffffffff
 #define RX_CLS_LOC_FIRST 0xfffffffe
diff --git a/libc/kernel/uapi/linux/eventpoll.h b/libc/kernel/uapi/linux/eventpoll.h
index 2e5ba8e..d2601e5 100644
--- a/libc/kernel/uapi/linux/eventpoll.h
+++ b/libc/kernel/uapi/linux/eventpoll.h
@@ -37,10 +37,10 @@
 #define EPOLLWRBAND (__force __poll_t) 0x00000200
 #define EPOLLMSG (__force __poll_t) 0x00000400
 #define EPOLLRDHUP (__force __poll_t) 0x00002000
-#define EPOLLEXCLUSIVE (__force __poll_t) (1U << 28)
-#define EPOLLWAKEUP (__force __poll_t) (1U << 29)
-#define EPOLLONESHOT (__force __poll_t) (1U << 30)
-#define EPOLLET (__force __poll_t) (1U << 31)
+#define EPOLLEXCLUSIVE ((__force __poll_t) (1U << 28))
+#define EPOLLWAKEUP ((__force __poll_t) (1U << 29))
+#define EPOLLONESHOT ((__force __poll_t) (1U << 30))
+#define EPOLLET ((__force __poll_t) (1U << 31))
 #ifdef __x86_64__
 #define EPOLL_PACKED __attribute__((packed))
 #else
diff --git a/libc/kernel/uapi/linux/fpga-dfl.h b/libc/kernel/uapi/linux/fpga-dfl.h
new file mode 100644
index 0000000..bf9a7c7
--- /dev/null
+++ b/libc/kernel/uapi/linux/fpga-dfl.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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_FPGA_DFL_H
+#define _UAPI_LINUX_FPGA_DFL_H
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#define DFL_FPGA_API_VERSION 0
+#define DFL_FPGA_MAGIC 0xB6
+#define DFL_FPGA_BASE 0
+#define DFL_PORT_BASE 0x40
+#define DFL_FME_BASE 0x80
+#define DFL_FPGA_GET_API_VERSION _IO(DFL_FPGA_MAGIC, DFL_FPGA_BASE + 0)
+#define DFL_FPGA_CHECK_EXTENSION _IO(DFL_FPGA_MAGIC, DFL_FPGA_BASE + 1)
+#define DFL_FPGA_PORT_RESET _IO(DFL_FPGA_MAGIC, DFL_PORT_BASE + 0)
+struct dfl_fpga_port_info {
+  __u32 argsz;
+  __u32 flags;
+  __u32 num_regions;
+  __u32 num_umsgs;
+};
+#define DFL_FPGA_PORT_GET_INFO _IO(DFL_FPGA_MAGIC, DFL_PORT_BASE + 1)
+struct dfl_fpga_port_region_info {
+  __u32 argsz;
+  __u32 flags;
+#define DFL_PORT_REGION_READ (1 << 0)
+#define DFL_PORT_REGION_WRITE (1 << 1)
+#define DFL_PORT_REGION_MMAP (1 << 2)
+  __u32 index;
+#define DFL_PORT_REGION_INDEX_AFU 0
+#define DFL_PORT_REGION_INDEX_STP 1
+  __u32 padding;
+  __u64 size;
+  __u64 offset;
+};
+#define DFL_FPGA_PORT_GET_REGION_INFO _IO(DFL_FPGA_MAGIC, DFL_PORT_BASE + 2)
+struct dfl_fpga_port_dma_map {
+  __u32 argsz;
+  __u32 flags;
+  __u64 user_addr;
+  __u64 length;
+  __u64 iova;
+};
+#define DFL_FPGA_PORT_DMA_MAP _IO(DFL_FPGA_MAGIC, DFL_PORT_BASE + 3)
+struct dfl_fpga_port_dma_unmap {
+  __u32 argsz;
+  __u32 flags;
+  __u64 iova;
+};
+#define DFL_FPGA_PORT_DMA_UNMAP _IO(DFL_FPGA_MAGIC, DFL_PORT_BASE + 4)
+struct dfl_fpga_fme_port_pr {
+  __u32 argsz;
+  __u32 flags;
+  __u32 port_id;
+  __u32 buffer_size;
+  __u64 buffer_address;
+};
+#define DFL_FPGA_FME_PORT_PR _IO(DFL_FPGA_MAGIC, DFL_FME_BASE + 0)
+#endif
diff --git a/libc/kernel/uapi/linux/fs.h b/libc/kernel/uapi/linux/fs.h
index 77c45c8..5c237d8 100644
--- a/libc/kernel/uapi/linux/fs.h
+++ b/libc/kernel/uapi/linux/fs.h
@@ -170,6 +170,7 @@
 #define FICLONE _IOW(0x94, 9, int)
 #define FICLONERANGE _IOW(0x94, 13, struct file_clone_range)
 #define FIDEDUPERANGE _IOWR(0x94, 54, struct file_dedupe_range)
+#define FSLABEL_MAX 256
 #define FS_IOC_GETFLAGS _IOR('f', 1, long)
 #define FS_IOC_SETFLAGS _IOW('f', 2, long)
 #define FS_IOC_GETVERSION _IOR('v', 1, long)
@@ -181,6 +182,8 @@
 #define FS_IOC32_SETVERSION _IOW('v', 2, int)
 #define FS_IOC_FSGETXATTR _IOR('X', 31, struct fsxattr)
 #define FS_IOC_FSSETXATTR _IOW('X', 32, struct fsxattr)
+#define FS_IOC_GETFSLABEL _IOR(0x94, 49, char[FSLABEL_MAX])
+#define FS_IOC_SETFSLABEL _IOW(0x94, 50, char[FSLABEL_MAX])
 #define FS_KEY_DESCRIPTOR_SIZE 8
 #define FS_POLICY_FLAGS_PAD_4 0x00
 #define FS_POLICY_FLAGS_PAD_8 0x01
@@ -195,6 +198,8 @@
 #define FS_ENCRYPTION_MODE_AES_256_CTS 4
 #define FS_ENCRYPTION_MODE_AES_128_CBC 5
 #define FS_ENCRYPTION_MODE_AES_128_CTS 6
+#define FS_ENCRYPTION_MODE_SPECK128_256_XTS 7
+#define FS_ENCRYPTION_MODE_SPECK128_256_CTS 8
 struct fscrypt_policy {
   __u8 version;
   __u8 contents_encryption_mode;
diff --git a/libc/kernel/uapi/linux/fsi.h b/libc/kernel/uapi/linux/fsi.h
new file mode 100644
index 0000000..fc88464
--- /dev/null
+++ b/libc/kernel/uapi/linux/fsi.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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_FSI_H
+#define _UAPI_LINUX_FSI_H
+#include <linux/types.h>
+#include <linux/ioctl.h>
+struct scom_access {
+  __u64 addr;
+  __u64 data;
+  __u64 mask;
+  __u32 intf_errors;
+#define SCOM_INTF_ERR_PARITY 0x00000001
+#define SCOM_INTF_ERR_PROTECTION 0x00000002
+#define SCOM_INTF_ERR_ABORT 0x00000004
+#define SCOM_INTF_ERR_UNKNOWN 0x80000000
+  __u8 pib_status;
+#define SCOM_PIB_SUCCESS 0
+#define SCOM_PIB_BLOCKED 1
+#define SCOM_PIB_OFFLINE 2
+#define SCOM_PIB_PARTIAL 3
+#define SCOM_PIB_BAD_ADDR 4
+#define SCOM_PIB_CLK_ERR 5
+#define SCOM_PIB_PARITY_ERR 6
+#define SCOM_PIB_TIMEOUT 7
+  __u8 pad;
+};
+#define SCOM_CHECK_SUPPORTED 0x00000001
+#define SCOM_CHECK_PROTECTED 0x00000002
+#define SCOM_RESET_INTF 0x00000001
+#define SCOM_RESET_PIB 0x00000002
+#define FSI_SCOM_CHECK _IOR('s', 0x00, __u32)
+#define FSI_SCOM_READ _IOWR('s', 0x01, struct scom_access)
+#define FSI_SCOM_WRITE _IOWR('s', 0x02, struct scom_access)
+#define FSI_SCOM_RESET _IOW('s', 0x03, __u32)
+#endif
diff --git a/libc/kernel/uapi/linux/fuse.h b/libc/kernel/uapi/linux/fuse.h
index 42f9ed6..a727580 100644
--- a/libc/kernel/uapi/linux/fuse.h
+++ b/libc/kernel/uapi/linux/fuse.h
@@ -20,7 +20,7 @@
 #define _LINUX_FUSE_H
 #include <stdint.h>
 #define FUSE_KERNEL_VERSION 7
-#define FUSE_KERNEL_MINOR_VERSION 26
+#define FUSE_KERNEL_MINOR_VERSION 27
 #define FUSE_ROOT_ID 1
 struct fuse_attr {
   uint64_t ino;
@@ -93,6 +93,7 @@
 #define FUSE_PARALLEL_DIROPS (1 << 18)
 #define FUSE_HANDLE_KILLPRIV (1 << 19)
 #define FUSE_POSIX_ACL (1 << 20)
+#define FUSE_ABORT_ERROR (1 << 21)
 #define CUSE_UNRESTRICTED_IOCTL (1 << 0)
 #define FUSE_RELEASE_FLUSH (1 << 0)
 #define FUSE_RELEASE_FLOCK_UNLOCK (1 << 1)
diff --git a/libc/kernel/uapi/linux/if_addr.h b/libc/kernel/uapi/linux/if_addr.h
index cefc11b..0a4b0ae 100644
--- a/libc/kernel/uapi/linux/if_addr.h
+++ b/libc/kernel/uapi/linux/if_addr.h
@@ -37,6 +37,7 @@
   IFA_CACHEINFO,
   IFA_MULTICAST,
   IFA_FLAGS,
+  IFA_RT_PRIORITY,
   __IFA_MAX,
 };
 #define IFA_MAX (__IFA_MAX - 1)
diff --git a/libc/kernel/uapi/linux/if_link.h b/libc/kernel/uapi/linux/if_link.h
index 8a9993b..4bbf21d 100644
--- a/libc/kernel/uapi/linux/if_link.h
+++ b/libc/kernel/uapi/linux/if_link.h
@@ -141,6 +141,8 @@
   IFLA_CARRIER_UP_COUNT,
   IFLA_CARRIER_DOWN_COUNT,
   IFLA_NEW_IFINDEX,
+  IFLA_MIN_MTU,
+  IFLA_MAX_MTU,
   __IFLA_MAX
 };
 #define IFLA_MAX (__IFLA_MAX - 1)
@@ -262,6 +264,8 @@
   IFLA_BRPORT_BCAST_FLOOD,
   IFLA_BRPORT_GROUP_FWD_MASK,
   IFLA_BRPORT_NEIGH_SUPPRESS,
+  IFLA_BRPORT_ISOLATED,
+  IFLA_BRPORT_BACKUP_PORT,
   __IFLA_BRPORT_MAX
 };
 #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
@@ -361,6 +365,13 @@
   __IFLA_MACSEC_MAX,
 };
 #define IFLA_MACSEC_MAX (__IFLA_MACSEC_MAX - 1)
+enum {
+  IFLA_XFRM_UNSPEC,
+  IFLA_XFRM_LINK,
+  IFLA_XFRM_IF_ID,
+  __IFLA_XFRM_MAX
+};
+#define IFLA_XFRM_MAX (__IFLA_XFRM_MAX - 1)
 enum macsec_validation_type {
   MACSEC_VALIDATE_DISABLED = 0,
   MACSEC_VALIDATE_CHECK = 1,
@@ -412,6 +423,7 @@
   IFLA_VXLAN_COLLECT_METADATA,
   IFLA_VXLAN_LABEL,
   IFLA_VXLAN_GPE,
+  IFLA_VXLAN_TTL_INHERIT,
   __IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
@@ -714,6 +726,7 @@
   XDP_ATTACHED_DRV,
   XDP_ATTACHED_SKB,
   XDP_ATTACHED_HW,
+  XDP_ATTACHED_MULTI,
 };
 enum {
   IFLA_XDP_UNSPEC,
@@ -721,6 +734,9 @@
   IFLA_XDP_ATTACHED,
   IFLA_XDP_FLAGS,
   IFLA_XDP_PROG_ID,
+  IFLA_XDP_DRV_PROG_ID,
+  IFLA_XDP_SKB_PROG_ID,
+  IFLA_XDP_HW_PROG_ID,
   __IFLA_XDP_MAX,
 };
 #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
diff --git a/libc/kernel/uapi/linux/if_xdp.h b/libc/kernel/uapi/linux/if_xdp.h
new file mode 100644
index 0000000..a0935bd
--- /dev/null
+++ b/libc/kernel/uapi/linux/if_xdp.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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 _LINUX_IF_XDP_H
+#define _LINUX_IF_XDP_H
+#include <linux/types.h>
+#define XDP_SHARED_UMEM (1 << 0)
+#define XDP_COPY (1 << 1)
+#define XDP_ZEROCOPY (1 << 2)
+struct sockaddr_xdp {
+  __u16 sxdp_family;
+  __u16 sxdp_flags;
+  __u32 sxdp_ifindex;
+  __u32 sxdp_queue_id;
+  __u32 sxdp_shared_umem_fd;
+};
+struct xdp_ring_offset {
+  __u64 producer;
+  __u64 consumer;
+  __u64 desc;
+};
+struct xdp_mmap_offsets {
+  struct xdp_ring_offset rx;
+  struct xdp_ring_offset tx;
+  struct xdp_ring_offset fr;
+  struct xdp_ring_offset cr;
+};
+#define XDP_MMAP_OFFSETS 1
+#define XDP_RX_RING 2
+#define XDP_TX_RING 3
+#define XDP_UMEM_REG 4
+#define XDP_UMEM_FILL_RING 5
+#define XDP_UMEM_COMPLETION_RING 6
+#define XDP_STATISTICS 7
+struct xdp_umem_reg {
+  __u64 addr;
+  __u64 len;
+  __u32 chunk_size;
+  __u32 headroom;
+};
+struct xdp_statistics {
+  __u64 rx_dropped;
+  __u64 rx_invalid_descs;
+  __u64 tx_invalid_descs;
+};
+#define XDP_PGOFF_RX_RING 0
+#define XDP_PGOFF_TX_RING 0x80000000
+#define XDP_UMEM_PGOFF_FILL_RING 0x100000000ULL
+#define XDP_UMEM_PGOFF_COMPLETION_RING 0x180000000ULL
+struct xdp_desc {
+  __u64 addr;
+  __u32 len;
+  __u32 options;
+};
+#endif
diff --git a/libc/kernel/uapi/linux/iio/types.h b/libc/kernel/uapi/linux/iio/types.h
index 3d4769d..834a2eb 100644
--- a/libc/kernel/uapi/linux/iio/types.h
+++ b/libc/kernel/uapi/linux/iio/types.h
@@ -51,6 +51,8 @@
   IIO_COUNT,
   IIO_INDEX,
   IIO_GRAVITY,
+  IIO_POSITIONRELATIVE,
+  IIO_PHASE,
 };
 enum iio_modifier {
   IIO_NO_MOD,
@@ -90,6 +92,7 @@
   IIO_MOD_CO2,
   IIO_MOD_VOC,
   IIO_MOD_LIGHT_UV,
+  IIO_MOD_LIGHT_DUV,
 };
 enum iio_event_type {
   IIO_EV_TYPE_THRESH,
diff --git a/libc/kernel/uapi/linux/ila.h b/libc/kernel/uapi/linux/ila.h
index a5af23a..75de8eb 100644
--- a/libc/kernel/uapi/linux/ila.h
+++ b/libc/kernel/uapi/linux/ila.h
@@ -39,6 +39,7 @@
   ILA_CMD_ADD,
   ILA_CMD_DEL,
   ILA_CMD_GET,
+  ILA_CMD_FLUSH,
   __ILA_CMD_MAX,
 };
 #define ILA_CMD_MAX (__ILA_CMD_MAX - 1)
diff --git a/libc/kernel/uapi/linux/inotify.h b/libc/kernel/uapi/linux/inotify.h
index 653dc07..eb9ac3c 100644
--- a/libc/kernel/uapi/linux/inotify.h
+++ b/libc/kernel/uapi/linux/inotify.h
@@ -47,6 +47,7 @@
 #define IN_ONLYDIR 0x01000000
 #define IN_DONT_FOLLOW 0x02000000
 #define IN_EXCL_UNLINK 0x04000000
+#define IN_MASK_CREATE 0x10000000
 #define IN_MASK_ADD 0x20000000
 #define IN_ISDIR 0x40000000
 #define IN_ONESHOT 0x80000000
diff --git a/libc/kernel/uapi/linux/input.h b/libc/kernel/uapi/linux/input.h
index 298e2a3..0a4b563 100644
--- a/libc/kernel/uapi/linux/input.h
+++ b/libc/kernel/uapi/linux/input.h
@@ -120,10 +120,11 @@
 #define BUS_RMI 0x1D
 #define BUS_CEC 0x1E
 #define BUS_INTEL_ISHTP 0x1F
-#define MT_TOOL_FINGER 0
-#define MT_TOOL_PEN 1
-#define MT_TOOL_PALM 2
-#define MT_TOOL_MAX 2
+#define MT_TOOL_FINGER 0x00
+#define MT_TOOL_PEN 0x01
+#define MT_TOOL_PALM 0x02
+#define MT_TOOL_DIAL 0x0a
+#define MT_TOOL_MAX 0x0f
 #define FF_STATUS_STOPPED 0x00
 #define FF_STATUS_PLAYING 0x01
 #define FF_STATUS_MAX 0x01
diff --git a/libc/kernel/uapi/linux/ip.h b/libc/kernel/uapi/linux/ip.h
index 8632d45..564fd8d 100644
--- a/libc/kernel/uapi/linux/ip.h
+++ b/libc/kernel/uapi/linux/ip.h
@@ -145,6 +145,7 @@
   IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN,
   IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST,
   IPV4_DEVCONF_DROP_GRATUITOUS_ARP,
+  IPV4_DEVCONF_BC_FORWARDING,
   __IPV4_DEVCONF_MAX
 };
 #define IPV4_DEVCONF_MAX (__IPV4_DEVCONF_MAX - 1)
diff --git a/libc/kernel/uapi/linux/kernel-page-flags.h b/libc/kernel/uapi/linux/kernel-page-flags.h
index a1212cc..afa0393 100644
--- a/libc/kernel/uapi/linux/kernel-page-flags.h
+++ b/libc/kernel/uapi/linux/kernel-page-flags.h
@@ -44,4 +44,5 @@
 #define KPF_BALLOON 23
 #define KPF_ZERO_PAGE 24
 #define KPF_IDLE 25
+#define KPF_PGTABLE 26
 #endif
diff --git a/libc/kernel/uapi/linux/keyboard.h b/libc/kernel/uapi/linux/keyboard.h
index 3694fb6..570cca9 100644
--- a/libc/kernel/uapi/linux/keyboard.h
+++ b/libc/kernel/uapi/linux/keyboard.h
@@ -357,7 +357,28 @@
 #define K_DTILDE K(KT_DEAD, 3)
 #define K_DDIERE K(KT_DEAD, 4)
 #define K_DCEDIL K(KT_DEAD, 5)
-#define NR_DEAD 6
+#define K_DMACRON K(KT_DEAD, 6)
+#define K_DBREVE K(KT_DEAD, 7)
+#define K_DABDOT K(KT_DEAD, 8)
+#define K_DABRING K(KT_DEAD, 9)
+#define K_DDBACUTE K(KT_DEAD, 10)
+#define K_DCARON K(KT_DEAD, 11)
+#define K_DOGONEK K(KT_DEAD, 12)
+#define K_DIOTA K(KT_DEAD, 13)
+#define K_DVOICED K(KT_DEAD, 14)
+#define K_DSEMVOICED K(KT_DEAD, 15)
+#define K_DBEDOT K(KT_DEAD, 16)
+#define K_DHOOK K(KT_DEAD, 17)
+#define K_DHORN K(KT_DEAD, 18)
+#define K_DSTROKE K(KT_DEAD, 19)
+#define K_DABCOMMA K(KT_DEAD, 20)
+#define K_DABREVCOMMA K(KT_DEAD, 21)
+#define K_DDBGRAVE K(KT_DEAD, 22)
+#define K_DINVBREVE K(KT_DEAD, 23)
+#define K_DBECOMMA K(KT_DEAD, 24)
+#define K_DCURRENCY K(KT_DEAD, 25)
+#define K_DGREEK K(KT_DEAD, 26)
+#define NR_DEAD 27
 #define K_DOWN K(KT_CUR, 0)
 #define K_LEFT K(KT_CUR, 1)
 #define K_RIGHT K(KT_CUR, 2)
diff --git a/libc/kernel/uapi/linux/kfd_ioctl.h b/libc/kernel/uapi/linux/kfd_ioctl.h
index 05db3fb..55aff04 100644
--- a/libc/kernel/uapi/linux/kfd_ioctl.h
+++ b/libc/kernel/uapi/linux/kfd_ioctl.h
@@ -59,6 +59,11 @@
   __u32 queue_percentage;
   __u32 queue_priority;
 };
+struct kfd_ioctl_set_cu_mask_args {
+  __u32 queue_id;
+  __u32 num_cu_mask;
+  __u64 cu_mask_ptr;
+};
 #define KFD_IOC_CACHE_POLICY_COHERENT 0
 #define KFD_IOC_CACHE_POLICY_NONCOHERENT 1
 struct kfd_ioctl_set_memory_policy_args {
@@ -132,6 +137,10 @@
 #define KFD_IOC_WAIT_RESULT_TIMEOUT 1
 #define KFD_IOC_WAIT_RESULT_FAIL 2
 #define KFD_SIGNAL_EVENT_LIMIT 4096
+#define KFD_HW_EXCEPTION_WHOLE_GPU_RESET 0
+#define KFD_HW_EXCEPTION_PER_ENGINE_RESET 1
+#define KFD_HW_EXCEPTION_GPU_HANG 0
+#define KFD_HW_EXCEPTION_ECC 1
 struct kfd_ioctl_create_event_args {
   __u64 event_page_offset;
   __u32 event_trigger_data;
@@ -157,7 +166,7 @@
   __u32 NotPresent;
   __u32 ReadOnly;
   __u32 NoExecute;
-  __u32 pad;
+  __u32 imprecise;
 };
 struct kfd_hsa_memory_exception_data {
   struct kfd_memory_exception_failure failure;
@@ -165,9 +174,16 @@
   __u32 gpu_id;
   __u32 pad;
 };
+struct kfd_hsa_hw_exception_data {
+  uint32_t reset_type;
+  uint32_t reset_cause;
+  uint32_t memory_lost;
+  uint32_t gpu_id;
+};
 struct kfd_event_data {
   union {
     struct kfd_hsa_memory_exception_data memory_exception_data;
+    struct kfd_hsa_hw_exception_data hw_exception_data;
   };
   __u64 kfd_event_data_ext;
   __u32 event_id;
@@ -268,6 +284,7 @@
 #define AMDKFD_IOC_FREE_MEMORY_OF_GPU AMDKFD_IOW(0x17, struct kfd_ioctl_free_memory_of_gpu_args)
 #define AMDKFD_IOC_MAP_MEMORY_TO_GPU AMDKFD_IOWR(0x18, struct kfd_ioctl_map_memory_to_gpu_args)
 #define AMDKFD_IOC_UNMAP_MEMORY_FROM_GPU AMDKFD_IOWR(0x19, struct kfd_ioctl_unmap_memory_from_gpu_args)
+#define AMDKFD_IOC_SET_CU_MASK AMDKFD_IOW(0x1A, struct kfd_ioctl_set_cu_mask_args)
 #define AMDKFD_COMMAND_START 0x01
-#define AMDKFD_COMMAND_END 0x1A
+#define AMDKFD_COMMAND_END 0x1B
 #endif
diff --git a/libc/kernel/uapi/linux/kvm.h b/libc/kernel/uapi/linux/kvm.h
index 6c8ae61..14e882b 100644
--- a/libc/kernel/uapi/linux/kvm.h
+++ b/libc/kernel/uapi/linux/kvm.h
@@ -739,6 +739,11 @@
 #define KVM_CAP_S390_BPB 152
 #define KVM_CAP_GET_MSR_FEATURES 153
 #define KVM_CAP_HYPERV_EVENTFD 154
+#define KVM_CAP_HYPERV_TLBFLUSH 155
+#define KVM_CAP_S390_HPAGE_1M 156
+#define KVM_CAP_NESTED_STATE 157
+#define KVM_CAP_ARM_INJECT_SERROR_ESR 158
+#define KVM_CAP_MSR_PLATFORM_INFO 159
 #ifdef KVM_CAP_IRQ_ROUTING
 struct kvm_irq_routing_irqchip {
   __u32 irqchip;
@@ -1048,6 +1053,8 @@
 #define KVM_MEMORY_ENCRYPT_REG_REGION _IOR(KVMIO, 0xbb, struct kvm_enc_region)
 #define KVM_MEMORY_ENCRYPT_UNREG_REGION _IOR(KVMIO, 0xbc, struct kvm_enc_region)
 #define KVM_HYPERV_EVENTFD _IOW(KVMIO, 0xbd, struct kvm_hyperv_eventfd)
+#define KVM_GET_NESTED_STATE _IOWR(KVMIO, 0xbe, struct kvm_nested_state)
+#define KVM_SET_NESTED_STATE _IOW(KVMIO, 0xbf, struct kvm_nested_state)
 enum sev_cmd_id {
   KVM_SEV_INIT = 0,
   KVM_SEV_ES_INIT,
diff --git a/libc/kernel/uapi/linux/kvm_para.h b/libc/kernel/uapi/linux/kvm_para.h
index 5035c23..b08a605 100644
--- a/libc/kernel/uapi/linux/kvm_para.h
+++ b/libc/kernel/uapi/linux/kvm_para.h
@@ -20,6 +20,7 @@
 #define _UAPI__LINUX_KVM_PARA_H
 #define KVM_ENOSYS 1000
 #define KVM_EFAULT EFAULT
+#define KVM_EINVAL EINVAL
 #define KVM_E2BIG E2BIG
 #define KVM_EPERM EPERM
 #define KVM_EOPNOTSUPP 95
@@ -32,5 +33,6 @@
 #define KVM_HC_MIPS_EXIT_VM 7
 #define KVM_HC_MIPS_CONSOLE_OUTPUT 8
 #define KVM_HC_CLOCK_PAIRING 9
+#define KVM_HC_SEND_IPI 10
 #include <asm/kvm_para.h>
 #endif
diff --git a/libc/kernel/uapi/linux/lirc.h b/libc/kernel/uapi/linux/lirc.h
index 3dfb6d0..4a8d0ff 100644
--- a/libc/kernel/uapi/linux/lirc.h
+++ b/libc/kernel/uapi/linux/lirc.h
@@ -92,6 +92,7 @@
 #define LIRC_SET_MEASURE_CARRIER_MODE _IOW('i', 0x0000001d, __u32)
 #define LIRC_SET_REC_CARRIER_RANGE _IOW('i', 0x0000001f, __u32)
 #define LIRC_SET_WIDEBAND_RECEIVER _IOW('i', 0x00000023, __u32)
+#define LIRC_GET_REC_TIMEOUT _IOR('i', 0x00000024, __u32)
 struct lirc_scancode {
   __u64 timestamp;
   __u16 flags;
diff --git a/libc/kernel/uapi/linux/media-bus-format.h b/libc/kernel/uapi/linux/media-bus-format.h
index dd7fcc7..7c701b1 100644
--- a/libc/kernel/uapi/linux/media-bus-format.h
+++ b/libc/kernel/uapi/linux/media-bus-format.h
@@ -56,6 +56,7 @@
 #define MEDIA_BUS_FMT_YUYV8_2X8 0x2008
 #define MEDIA_BUS_FMT_YVYU8_2X8 0x2009
 #define MEDIA_BUS_FMT_Y10_1X10 0x200a
+#define MEDIA_BUS_FMT_Y10_2X8_PADHI_LE 0x202c
 #define MEDIA_BUS_FMT_UYVY10_2X10 0x2018
 #define MEDIA_BUS_FMT_VYUY10_2X10 0x2019
 #define MEDIA_BUS_FMT_YUYV10_2X10 0x200b
diff --git a/libc/kernel/uapi/linux/media.h b/libc/kernel/uapi/linux/media.h
index e6236f9..eefc07a 100644
--- a/libc/kernel/uapi/linux/media.h
+++ b/libc/kernel/uapi/linux/media.h
@@ -21,7 +21,6 @@
 #include <stdint.h>
 #include <linux/ioctl.h>
 #include <linux/types.h>
-#include <linux/version.h>
 struct media_device_info {
   char driver[16];
   char model[32];
@@ -48,8 +47,6 @@
 #define MEDIA_ENT_F_CAM_SENSOR (MEDIA_ENT_F_OLD_SUBDEV_BASE + 1)
 #define MEDIA_ENT_F_FLASH (MEDIA_ENT_F_OLD_SUBDEV_BASE + 2)
 #define MEDIA_ENT_F_LENS (MEDIA_ENT_F_OLD_SUBDEV_BASE + 3)
-#define MEDIA_ENT_F_ATV_DECODER (MEDIA_ENT_F_OLD_SUBDEV_BASE + 4)
-#define MEDIA_ENT_F_DTV_DECODER (MEDIA_ENT_F_BASE + 0x6001)
 #define MEDIA_ENT_F_TUNER (MEDIA_ENT_F_OLD_SUBDEV_BASE + 5)
 #define MEDIA_ENT_F_IF_VID_DECODER (MEDIA_ENT_F_BASE + 0x02001)
 #define MEDIA_ENT_F_IF_AUD_DECODER (MEDIA_ENT_F_BASE + 0x02002)
@@ -62,8 +59,13 @@
 #define MEDIA_ENT_F_PROC_VIDEO_LUT (MEDIA_ENT_F_BASE + 0x4004)
 #define MEDIA_ENT_F_PROC_VIDEO_SCALER (MEDIA_ENT_F_BASE + 0x4005)
 #define MEDIA_ENT_F_PROC_VIDEO_STATISTICS (MEDIA_ENT_F_BASE + 0x4006)
+#define MEDIA_ENT_F_PROC_VIDEO_ENCODER (MEDIA_ENT_F_BASE + 0x4007)
+#define MEDIA_ENT_F_PROC_VIDEO_DECODER (MEDIA_ENT_F_BASE + 0x4008)
 #define MEDIA_ENT_F_VID_MUX (MEDIA_ENT_F_BASE + 0x5001)
 #define MEDIA_ENT_F_VID_IF_BRIDGE (MEDIA_ENT_F_BASE + 0x5002)
+#define MEDIA_ENT_F_ATV_DECODER (MEDIA_ENT_F_OLD_SUBDEV_BASE + 4)
+#define MEDIA_ENT_F_DV_DECODER (MEDIA_ENT_F_BASE + 0x6001)
+#define MEDIA_ENT_F_DV_ENCODER (MEDIA_ENT_F_BASE + 0x6002)
 #define MEDIA_ENT_FL_DEFAULT (1 << 0)
 #define MEDIA_ENT_FL_CONNECTOR (1 << 1)
 #define MEDIA_ENT_ID_FLAG_NEXT (1 << 31)
@@ -139,11 +141,13 @@
 #define MEDIA_INTF_T_V4L_SUBDEV (MEDIA_INTF_T_V4L_BASE + 3)
 #define MEDIA_INTF_T_V4L_SWRADIO (MEDIA_INTF_T_V4L_BASE + 4)
 #define MEDIA_INTF_T_V4L_TOUCH (MEDIA_INTF_T_V4L_BASE + 5)
+#define MEDIA_V2_ENTITY_HAS_FLAGS(media_version) ((media_version) >= ((4 << 16) | (19 << 8) | 0))
 struct media_v2_entity {
   __u32 id;
   char name[64];
   __u32 function;
-  __u32 reserved[6];
+  __u32 flags;
+  __u32 reserved[5];
 } __attribute__((packed));
 struct media_v2_intf_devnode {
   __u32 major;
@@ -159,11 +163,13 @@
     __u32 raw[16];
   };
 } __attribute__((packed));
+#define MEDIA_V2_PAD_HAS_INDEX(media_version) ((media_version) >= ((4 << 16) | (19 << 8) | 0))
 struct media_v2_pad {
   __u32 id;
   __u32 entity_id;
   __u32 flags;
-  __u32 reserved[5];
+  __u32 index;
+  __u32 reserved[4];
 } __attribute__((packed));
 struct media_v2_link {
   __u32 id;
@@ -209,6 +215,7 @@
 #define MEDIA_ENT_T_V4L2_SUBDEV_LENS MEDIA_ENT_F_LENS
 #define MEDIA_ENT_T_V4L2_SUBDEV_DECODER MEDIA_ENT_F_ATV_DECODER
 #define MEDIA_ENT_T_V4L2_SUBDEV_TUNER MEDIA_ENT_F_TUNER
+#define MEDIA_ENT_F_DTV_DECODER MEDIA_ENT_F_DV_DECODER
 #define MEDIA_INTF_T_ALSA_BASE 0x00000300
 #define MEDIA_INTF_T_ALSA_PCM_CAPTURE (MEDIA_INTF_T_ALSA_BASE)
 #define MEDIA_INTF_T_ALSA_PCM_PLAYBACK (MEDIA_INTF_T_ALSA_BASE + 1)
@@ -218,5 +225,5 @@
 #define MEDIA_INTF_T_ALSA_HWDEP (MEDIA_INTF_T_ALSA_BASE + 5)
 #define MEDIA_INTF_T_ALSA_SEQUENCER (MEDIA_INTF_T_ALSA_BASE + 6)
 #define MEDIA_INTF_T_ALSA_TIMER (MEDIA_INTF_T_ALSA_BASE + 7)
-#define MEDIA_API_VERSION KERNEL_VERSION(0, 1, 0)
+#define MEDIA_API_VERSION ((0 << 16) | (1 << 8) | 0)
 #endif
diff --git a/libc/kernel/uapi/linux/memfd.h b/libc/kernel/uapi/linux/memfd.h
index e3e5cd5..914c076 100644
--- a/libc/kernel/uapi/linux/memfd.h
+++ b/libc/kernel/uapi/linux/memfd.h
@@ -30,7 +30,9 @@
 #define MFD_HUGE_2MB HUGETLB_FLAG_ENCODE_2MB
 #define MFD_HUGE_8MB HUGETLB_FLAG_ENCODE_8MB
 #define MFD_HUGE_16MB HUGETLB_FLAG_ENCODE_16MB
+#define MFD_HUGE_32MB HUGETLB_FLAG_ENCODE_32MB
 #define MFD_HUGE_256MB HUGETLB_FLAG_ENCODE_256MB
+#define MFD_HUGE_512MB HUGETLB_FLAG_ENCODE_512MB
 #define MFD_HUGE_1GB HUGETLB_FLAG_ENCODE_1GB
 #define MFD_HUGE_2GB HUGETLB_FLAG_ENCODE_2GB
 #define MFD_HUGE_16GB HUGETLB_FLAG_ENCODE_16GB
diff --git a/libc/kernel/uapi/linux/mii.h b/libc/kernel/uapi/linux/mii.h
index aa4824d..5c87990 100644
--- a/libc/kernel/uapi/linux/mii.h
+++ b/libc/kernel/uapi/linux/mii.h
@@ -122,6 +122,7 @@
 #define ADVERTISE_1000HALF 0x0100
 #define CTL1000_AS_MASTER 0x0800
 #define CTL1000_ENABLE_MASTER 0x1000
+#define LPA_1000MSFAIL 0x8000
 #define LPA_1000LOCALRXOK 0x2000
 #define LPA_1000REMRXOK 0x1000
 #define LPA_1000FULL 0x0800
diff --git a/libc/kernel/uapi/linux/mman.h b/libc/kernel/uapi/linux/mman.h
index b0ce77e..0c9c397 100644
--- a/libc/kernel/uapi/linux/mman.h
+++ b/libc/kernel/uapi/linux/mman.h
@@ -33,7 +33,9 @@
 #define MAP_HUGE_2MB HUGETLB_FLAG_ENCODE_2MB
 #define MAP_HUGE_8MB HUGETLB_FLAG_ENCODE_8MB
 #define MAP_HUGE_16MB HUGETLB_FLAG_ENCODE_16MB
+#define MAP_HUGE_32MB HUGETLB_FLAG_ENCODE_32MB
 #define MAP_HUGE_256MB HUGETLB_FLAG_ENCODE_256MB
+#define MAP_HUGE_512MB HUGETLB_FLAG_ENCODE_512MB
 #define MAP_HUGE_1GB HUGETLB_FLAG_ENCODE_1GB
 #define MAP_HUGE_2GB HUGETLB_FLAG_ENCODE_2GB
 #define MAP_HUGE_16GB HUGETLB_FLAG_ENCODE_16GB
diff --git a/libc/kernel/uapi/linux/mroute.h b/libc/kernel/uapi/linux/mroute.h
index d962f8b..f0cb21b 100644
--- a/libc/kernel/uapi/linux/mroute.h
+++ b/libc/kernel/uapi/linux/mroute.h
@@ -103,6 +103,7 @@
   IPMRA_TABLE_MROUTE_DO_ASSERT,
   IPMRA_TABLE_MROUTE_DO_PIM,
   IPMRA_TABLE_VIFS,
+  IPMRA_TABLE_MROUTE_DO_WRVIFWHOLE,
   __IPMRA_TABLE_MAX
 };
 #define IPMRA_TABLE_MAX (__IPMRA_TABLE_MAX - 1)
@@ -141,4 +142,5 @@
 #define IGMPMSG_NOCACHE 1
 #define IGMPMSG_WRONGVIF 2
 #define IGMPMSG_WHOLEPKT 3
+#define IGMPMSG_WRVIFWHOLE 4
 #endif
diff --git a/libc/kernel/uapi/linux/nbd.h b/libc/kernel/uapi/linux/nbd.h
index 749c38a..3b74393 100644
--- a/libc/kernel/uapi/linux/nbd.h
+++ b/libc/kernel/uapi/linux/nbd.h
@@ -45,6 +45,7 @@
 #define NBD_FLAG_CAN_MULTI_CONN (1 << 8)
 #define NBD_CMD_FLAG_FUA (1 << 16)
 #define NBD_CFLAG_DESTROY_ON_DISCONNECT (1 << 0)
+#define NBD_CFLAG_DISCONNECT_ON_CLOSE (1 << 1)
 #define NBD_REQUEST_MAGIC 0x25609513
 #define NBD_REPLY_MAGIC 0x67446698
 struct nbd_request {
diff --git a/libc/kernel/uapi/linux/ncp.h b/libc/kernel/uapi/linux/ncp.h
deleted file mode 100644
index c3f318b..0000000
--- a/libc/kernel/uapi/linux/ncp.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- ***   This header was automatically generated from a Linux kernel header
- ***   of the same name, to make information necessary for userspace to
- ***   call into the kernel available to libc.  It contains only constants,
- ***   structures, and macros generated from the original header, and thus,
- ***   contains no copyrightable information.
- ***
- ***   To edit the content of this header, modify the corresponding
- ***   source file (e.g. under external/kernel-headers/original/) then
- ***   run bionic/libc/kernel/tools/update_all.py
- ***
- ***   Any manual change here will be lost the next time this script will
- ***   be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef _LINUX_NCP_H
-#define _LINUX_NCP_H
-#include <linux/types.h>
-#define NCP_PTYPE (0x11)
-#define NCP_PORT (0x0451)
-#define NCP_ALLOC_SLOT_REQUEST (0x1111)
-#define NCP_REQUEST (0x2222)
-#define NCP_DEALLOC_SLOT_REQUEST (0x5555)
-struct ncp_request_header {
-  __u16 type;
-  __u8 sequence;
-  __u8 conn_low;
-  __u8 task;
-  __u8 conn_high;
-  __u8 function;
-  __u8 data[0];
-} __attribute__((packed));
-#define NCP_REPLY (0x3333)
-#define NCP_WATCHDOG (0x3E3E)
-#define NCP_POSITIVE_ACK (0x9999)
-struct ncp_reply_header {
-  __u16 type;
-  __u8 sequence;
-  __u8 conn_low;
-  __u8 task;
-  __u8 conn_high;
-  __u8 completion_code;
-  __u8 connection_state;
-  __u8 data[0];
-} __attribute__((packed));
-#define NCP_VOLNAME_LEN (16)
-#define NCP_NUMBER_OF_VOLUMES (256)
-struct ncp_volume_info {
-  __u32 total_blocks;
-  __u32 free_blocks;
-  __u32 purgeable_blocks;
-  __u32 not_yet_purgeable_blocks;
-  __u32 total_dir_entries;
-  __u32 available_dir_entries;
-  __u8 sectors_per_block;
-  char volume_name[NCP_VOLNAME_LEN + 1];
-};
-#define AR_READ (cpu_to_le16(1))
-#define AR_WRITE (cpu_to_le16(2))
-#define AR_EXCLUSIVE (cpu_to_le16(0x20))
-#define NCP_FILE_ID_LEN 6
-#define NW_NS_DOS 0
-#define NW_NS_MAC 1
-#define NW_NS_NFS 2
-#define NW_NS_FTAM 3
-#define NW_NS_OS2 4
-#define RIM_NAME (cpu_to_le32(1))
-#define RIM_SPACE_ALLOCATED (cpu_to_le32(2))
-#define RIM_ATTRIBUTES (cpu_to_le32(4))
-#define RIM_DATA_SIZE (cpu_to_le32(8))
-#define RIM_TOTAL_SIZE (cpu_to_le32(0x10))
-#define RIM_EXT_ATTR_INFO (cpu_to_le32(0x20))
-#define RIM_ARCHIVE (cpu_to_le32(0x40))
-#define RIM_MODIFY (cpu_to_le32(0x80))
-#define RIM_CREATION (cpu_to_le32(0x100))
-#define RIM_OWNING_NAMESPACE (cpu_to_le32(0x200))
-#define RIM_DIRECTORY (cpu_to_le32(0x400))
-#define RIM_RIGHTS (cpu_to_le32(0x800))
-#define RIM_ALL (cpu_to_le32(0xFFF))
-#define RIM_COMPRESSED_INFO (cpu_to_le32(0x80000000))
-#define NSIBM_NFS_NAME 0x0001
-#define NSIBM_NFS_MODE 0x0002
-#define NSIBM_NFS_GID 0x0004
-#define NSIBM_NFS_NLINKS 0x0008
-#define NSIBM_NFS_RDEV 0x0010
-#define NSIBM_NFS_LINK 0x0020
-#define NSIBM_NFS_CREATED 0x0040
-#define NSIBM_NFS_UID 0x0080
-#define NSIBM_NFS_ACSFLAG 0x0100
-#define NSIBM_NFS_MYFLAG 0x0200
-#define OC_MODE_OPEN 0x01
-#define OC_MODE_TRUNCATE 0x02
-#define OC_MODE_REPLACE 0x02
-#define OC_MODE_CREATE 0x08
-#define OC_ACTION_NONE 0x00
-#define OC_ACTION_OPEN 0x01
-#define OC_ACTION_CREATE 0x02
-#define OC_ACTION_TRUNCATE 0x04
-#define OC_ACTION_REPLACE 0x04
-#ifndef AR_READ_ONLY
-#define AR_READ_ONLY 0x0001
-#define AR_WRITE_ONLY 0x0002
-#define AR_DENY_READ 0x0004
-#define AR_DENY_WRITE 0x0008
-#define AR_COMPATIBILITY 0x0010
-#define AR_WRITE_THROUGH 0x0040
-#define AR_OPEN_COMPRESSED 0x0100
-#endif
-struct nw_nfs_info {
-  __u32 mode;
-  __u32 rdev;
-};
-struct nw_info_struct {
-  __u32 spaceAlloc;
-  __le32 attributes;
-  __u16 flags;
-  __le32 dataStreamSize;
-  __le32 totalStreamSize;
-  __u16 numberOfStreams;
-  __le16 creationTime;
-  __le16 creationDate;
-  __u32 creatorID;
-  __le16 modifyTime;
-  __le16 modifyDate;
-  __u32 modifierID;
-  __le16 lastAccessDate;
-  __u16 archiveTime;
-  __u16 archiveDate;
-  __u32 archiverID;
-  __u16 inheritedRightsMask;
-  __le32 dirEntNum;
-  __le32 DosDirNum;
-  __u32 volNumber;
-  __u32 EADataSize;
-  __u32 EAKeyCount;
-  __u32 EAKeySize;
-  __u32 NSCreator;
-  __u8 nameLen;
-  __u8 entryName[256];
-} __attribute__((packed));
-#define DM_ATTRIBUTES (cpu_to_le32(0x02))
-#define DM_CREATE_DATE (cpu_to_le32(0x04))
-#define DM_CREATE_TIME (cpu_to_le32(0x08))
-#define DM_CREATOR_ID (cpu_to_le32(0x10))
-#define DM_ARCHIVE_DATE (cpu_to_le32(0x20))
-#define DM_ARCHIVE_TIME (cpu_to_le32(0x40))
-#define DM_ARCHIVER_ID (cpu_to_le32(0x80))
-#define DM_MODIFY_DATE (cpu_to_le32(0x0100))
-#define DM_MODIFY_TIME (cpu_to_le32(0x0200))
-#define DM_MODIFIER_ID (cpu_to_le32(0x0400))
-#define DM_LAST_ACCESS_DATE (cpu_to_le32(0x0800))
-#define DM_INHERITED_RIGHTS_MASK (cpu_to_le32(0x1000))
-#define DM_MAXIMUM_SPACE (cpu_to_le32(0x2000))
-struct nw_modify_dos_info {
-  __le32 attributes;
-  __le16 creationDate;
-  __le16 creationTime;
-  __u32 creatorID;
-  __le16 modifyDate;
-  __le16 modifyTime;
-  __u32 modifierID;
-  __u16 archiveDate;
-  __u16 archiveTime;
-  __u32 archiverID;
-  __le16 lastAccessDate;
-  __u16 inheritanceGrantMask;
-  __u16 inheritanceRevokeMask;
-  __u32 maximumSpace;
-} __attribute__((packed));
-struct nw_search_sequence {
-  __u8 volNumber;
-  __u32 dirBase;
-  __u32 sequence;
-} __attribute__((packed));
-#endif
diff --git a/libc/kernel/uapi/linux/ncp_fs.h b/libc/kernel/uapi/linux/ncp_fs.h
deleted file mode 100644
index ddb9742..0000000
--- a/libc/kernel/uapi/linux/ncp_fs.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- ***   This header was automatically generated from a Linux kernel header
- ***   of the same name, to make information necessary for userspace to
- ***   call into the kernel available to libc.  It contains only constants,
- ***   structures, and macros generated from the original header, and thus,
- ***   contains no copyrightable information.
- ***
- ***   To edit the content of this header, modify the corresponding
- ***   source file (e.g. under external/kernel-headers/original/) then
- ***   run bionic/libc/kernel/tools/update_all.py
- ***
- ***   Any manual change here will be lost the next time this script will
- ***   be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef _LINUX_NCP_FS_H
-#define _LINUX_NCP_FS_H
-#include <linux/fs.h>
-#include <linux/in.h>
-#include <linux/types.h>
-#include <linux/magic.h>
-#include <linux/ipx.h>
-#include <linux/ncp_no.h>
-struct ncp_ioctl_request {
-  unsigned int function;
-  unsigned int size;
-  char __user * data;
-};
-struct ncp_fs_info {
-  int version;
-  struct sockaddr_ipx addr;
-  __kernel_uid_t mounted_uid;
-  int connection;
-  int buffer_size;
-  int volume_number;
-  __le32 directory_id;
-};
-struct ncp_fs_info_v2 {
-  int version;
-  unsigned long mounted_uid;
-  unsigned int connection;
-  unsigned int buffer_size;
-  unsigned int volume_number;
-  __le32 directory_id;
-  __u32 dummy1;
-  __u32 dummy2;
-  __u32 dummy3;
-};
-struct ncp_sign_init {
-  char sign_root[8];
-  char sign_last[16];
-};
-struct ncp_lock_ioctl {
-#define NCP_LOCK_LOG 0
-#define NCP_LOCK_SH 1
-#define NCP_LOCK_EX 2
-#define NCP_LOCK_CLEAR 256
-  int cmd;
-  int origin;
-  unsigned int offset;
-  unsigned int length;
-#define NCP_LOCK_DEFAULT_TIMEOUT 18
-#define NCP_LOCK_MAX_TIMEOUT 180
-  int timeout;
-};
-struct ncp_setroot_ioctl {
-  int volNumber;
-  int namespace;
-  __le32 dirEntNum;
-};
-struct ncp_objectname_ioctl {
-#define NCP_AUTH_NONE 0x00
-#define NCP_AUTH_BIND 0x31
-#define NCP_AUTH_NDS 0x32
-  int auth_type;
-  size_t object_name_len;
-  void __user * object_name;
-};
-struct ncp_privatedata_ioctl {
-  size_t len;
-  void __user * data;
-};
-#define NCP_IOCSNAME_LEN 20
-struct ncp_nls_ioctl {
-  unsigned char codepage[NCP_IOCSNAME_LEN + 1];
-  unsigned char iocharset[NCP_IOCSNAME_LEN + 1];
-};
-#define NCP_IOC_NCPREQUEST _IOR('n', 1, struct ncp_ioctl_request)
-#define NCP_IOC_GETMOUNTUID _IOW('n', 2, __kernel_old_uid_t)
-#define NCP_IOC_GETMOUNTUID2 _IOW('n', 2, unsigned long)
-#define NCP_IOC_CONN_LOGGED_IN _IO('n', 3)
-#define NCP_GET_FS_INFO_VERSION (1)
-#define NCP_IOC_GET_FS_INFO _IOWR('n', 4, struct ncp_fs_info)
-#define NCP_GET_FS_INFO_VERSION_V2 (2)
-#define NCP_IOC_GET_FS_INFO_V2 _IOWR('n', 4, struct ncp_fs_info_v2)
-#define NCP_IOC_SIGN_INIT _IOR('n', 5, struct ncp_sign_init)
-#define NCP_IOC_SIGN_WANTED _IOR('n', 6, int)
-#define NCP_IOC_SET_SIGN_WANTED _IOW('n', 6, int)
-#define NCP_IOC_LOCKUNLOCK _IOR('n', 7, struct ncp_lock_ioctl)
-#define NCP_IOC_GETROOT _IOW('n', 8, struct ncp_setroot_ioctl)
-#define NCP_IOC_SETROOT _IOR('n', 8, struct ncp_setroot_ioctl)
-#define NCP_IOC_GETOBJECTNAME _IOWR('n', 9, struct ncp_objectname_ioctl)
-#define NCP_IOC_SETOBJECTNAME _IOR('n', 9, struct ncp_objectname_ioctl)
-#define NCP_IOC_GETPRIVATEDATA _IOWR('n', 10, struct ncp_privatedata_ioctl)
-#define NCP_IOC_SETPRIVATEDATA _IOR('n', 10, struct ncp_privatedata_ioctl)
-#define NCP_IOC_GETCHARSETS _IOWR('n', 11, struct ncp_nls_ioctl)
-#define NCP_IOC_SETCHARSETS _IOR('n', 11, struct ncp_nls_ioctl)
-#define NCP_IOC_GETDENTRYTTL _IOW('n', 12, __u32)
-#define NCP_IOC_SETDENTRYTTL _IOR('n', 12, __u32)
-#define NCP_PACKET_SIZE 4070
-#define NCP_MAXPATHLEN 255
-#define NCP_MAXNAMELEN 14
-#endif
diff --git a/libc/kernel/uapi/linux/ncp_mount.h b/libc/kernel/uapi/linux/ncp_mount.h
deleted file mode 100644
index e29640d..0000000
--- a/libc/kernel/uapi/linux/ncp_mount.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- ***   This header was automatically generated from a Linux kernel header
- ***   of the same name, to make information necessary for userspace to
- ***   call into the kernel available to libc.  It contains only constants,
- ***   structures, and macros generated from the original header, and thus,
- ***   contains no copyrightable information.
- ***
- ***   To edit the content of this header, modify the corresponding
- ***   source file (e.g. under external/kernel-headers/original/) then
- ***   run bionic/libc/kernel/tools/update_all.py
- ***
- ***   Any manual change here will be lost the next time this script will
- ***   be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef _LINUX_NCP_MOUNT_H
-#define _LINUX_NCP_MOUNT_H
-#include <linux/types.h>
-#include <linux/ncp.h>
-#define NCP_MOUNT_VERSION 3
-#define NCP_MOUNT_SOFT 0x0001
-#define NCP_MOUNT_INTR 0x0002
-#define NCP_MOUNT_STRONG 0x0004
-#define NCP_MOUNT_NO_OS2 0x0008
-#define NCP_MOUNT_NO_NFS 0x0010
-#define NCP_MOUNT_EXTRAS 0x0020
-#define NCP_MOUNT_SYMLINKS 0x0040
-#define NCP_MOUNT_NFS_EXTRAS 0x0080
-struct ncp_mount_data {
-  int version;
-  unsigned int ncp_fd;
-  __kernel_uid_t mounted_uid;
-  __kernel_pid_t wdog_pid;
-  unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
-  unsigned int time_out;
-  unsigned int retry_count;
-  unsigned int flags;
-  __kernel_uid_t uid;
-  __kernel_gid_t gid;
-  __kernel_mode_t file_mode;
-  __kernel_mode_t dir_mode;
-};
-#define NCP_MOUNT_VERSION_V4 (4)
-struct ncp_mount_data_v4 {
-  int version;
-  unsigned long flags;
-  unsigned long mounted_uid;
-  long wdog_pid;
-  unsigned int ncp_fd;
-  unsigned int time_out;
-  unsigned int retry_count;
-  unsigned long uid;
-  unsigned long gid;
-  unsigned long file_mode;
-  unsigned long dir_mode;
-};
-#define NCP_MOUNT_VERSION_V5 (5)
-#endif
diff --git a/libc/kernel/uapi/linux/net_tstamp.h b/libc/kernel/uapi/linux/net_tstamp.h
index 49d4c2c..2f022ea 100644
--- a/libc/kernel/uapi/linux/net_tstamp.h
+++ b/libc/kernel/uapi/linux/net_tstamp.h
@@ -73,4 +73,14 @@
   __u32 pkt_length;
   __u32 reserved[2];
 };
+enum txtime_flags {
+  SOF_TXTIME_DEADLINE_MODE = (1 << 0),
+  SOF_TXTIME_REPORT_ERRORS = (1 << 1),
+  SOF_TXTIME_FLAGS_LAST = SOF_TXTIME_REPORT_ERRORS,
+  SOF_TXTIME_FLAGS_MASK = (SOF_TXTIME_FLAGS_LAST - 1) | SOF_TXTIME_FLAGS_LAST
+};
+struct sock_txtime {
+  clockid_t clockid;
+  __u32 flags;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/netconf.h b/libc/kernel/uapi/linux/netconf.h
index 4f86757..27d3854 100644
--- a/libc/kernel/uapi/linux/netconf.h
+++ b/libc/kernel/uapi/linux/netconf.h
@@ -32,6 +32,7 @@
   NETCONFA_PROXY_NEIGH,
   NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
   NETCONFA_INPUT,
+  NETCONFA_BC_FORWARDING,
   __NETCONFA_MAX
 };
 #define NETCONFA_MAX (__NETCONFA_MAX - 1)
diff --git a/libc/kernel/uapi/linux/netfilter/nf_conntrack_common.h b/libc/kernel/uapi/linux/netfilter/nf_conntrack_common.h
index 2259e09..43d60ca 100644
--- a/libc/kernel/uapi/linux/netfilter/nf_conntrack_common.h
+++ b/libc/kernel/uapi/linux/netfilter/nf_conntrack_common.h
@@ -65,7 +65,7 @@
   IPS_OFFLOAD_BIT = 14,
   IPS_OFFLOAD = (1 << IPS_OFFLOAD_BIT),
   IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK | IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING | IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_OFFLOAD),
-  __IPS_MAX_BIT = 14,
+  __IPS_MAX_BIT = 15,
 };
 enum ip_conntrack_events {
   IPCT_NEW,
diff --git a/libc/kernel/uapi/linux/netfilter/nf_nat.h b/libc/kernel/uapi/linux/netfilter/nf_nat.h
index 80a55e6..f01669b 100644
--- a/libc/kernel/uapi/linux/netfilter/nf_nat.h
+++ b/libc/kernel/uapi/linux/netfilter/nf_nat.h
@@ -25,8 +25,9 @@
 #define NF_NAT_RANGE_PROTO_RANDOM (1 << 2)
 #define NF_NAT_RANGE_PERSISTENT (1 << 3)
 #define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4)
+#define NF_NAT_RANGE_PROTO_OFFSET (1 << 5)
 #define NF_NAT_RANGE_PROTO_RANDOM_ALL (NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY)
-#define NF_NAT_RANGE_MASK (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED | NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PERSISTENT | NF_NAT_RANGE_PROTO_RANDOM_FULLY)
+#define NF_NAT_RANGE_MASK (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED | NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PERSISTENT | NF_NAT_RANGE_PROTO_RANDOM_FULLY | NF_NAT_RANGE_PROTO_OFFSET)
 struct nf_nat_ipv4_range {
   unsigned int flags;
   __be32 min_ip;
@@ -45,4 +46,12 @@
   union nf_conntrack_man_proto min_proto;
   union nf_conntrack_man_proto max_proto;
 };
+struct nf_nat_range2 {
+  unsigned int flags;
+  union nf_inet_addr min_addr;
+  union nf_inet_addr max_addr;
+  union nf_conntrack_man_proto min_proto;
+  union nf_conntrack_man_proto max_proto;
+  union nf_conntrack_man_proto base_proto;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/netfilter/nf_tables.h b/libc/kernel/uapi/linux/netfilter/nf_tables.h
index 610594c..63394e0 100644
--- a/libc/kernel/uapi/linux/netfilter/nf_tables.h
+++ b/libc/kernel/uapi/linux/netfilter/nf_tables.h
@@ -24,6 +24,7 @@
 #define NFT_SET_MAXNAMELEN NFT_NAME_MAXLEN
 #define NFT_OBJ_MAXNAMELEN NFT_NAME_MAXLEN
 #define NFT_USERDATA_MAXLEN 256
+#define NFT_OSF_MAXGENRELEN 16
 enum nft_registers {
   NFT_REG_VERDICT,
   NFT_REG_1,
@@ -418,7 +419,9 @@
   NFT_RT_NEXTHOP4,
   NFT_RT_NEXTHOP6,
   NFT_RT_TCPMSS,
+  __NFT_RT_MAX
 };
+#define NFT_RT_MAX (__NFT_RT_MAX - 1)
 enum nft_hash_types {
   NFT_HASH_JENKINS,
   NFT_HASH_SYM,
@@ -432,6 +435,8 @@
   NFTA_HASH_SEED,
   NFTA_HASH_OFFSET,
   NFTA_HASH_TYPE,
+  NFTA_HASH_SET_NAME,
+  NFTA_HASH_SET_ID,
   __NFTA_HASH_MAX,
 };
 #define NFTA_HASH_MAX (__NFTA_HASH_MAX - 1)
@@ -450,6 +455,19 @@
   __NFTA_RT_MAX
 };
 #define NFTA_RT_MAX (__NFTA_RT_MAX - 1)
+enum nft_socket_attributes {
+  NFTA_SOCKET_UNSPEC,
+  NFTA_SOCKET_KEY,
+  NFTA_SOCKET_DREG,
+  __NFTA_SOCKET_MAX
+};
+#define NFTA_SOCKET_MAX (__NFTA_SOCKET_MAX - 1)
+enum nft_socket_keys {
+  NFT_SOCKET_TRANSPARENT,
+  NFT_SOCKET_MARK,
+  __NFT_SOCKET_MAX
+};
+#define NFT_SOCKET_MAX (__NFT_SOCKET_MAX - 1)
 enum nft_ct_keys {
   NFT_CT_STATE,
   NFT_CT_DIRECTION,
@@ -474,7 +492,10 @@
   NFT_CT_DST_IP,
   NFT_CT_SRC_IP6,
   NFT_CT_DST_IP6,
+  NFT_CT_TIMEOUT,
+  __NFT_CT_MAX
 };
+#define NFT_CT_MAX (__NFT_CT_MAX - 1)
 enum nft_ct_attributes {
   NFTA_CT_UNSPEC,
   NFTA_CT_DREG,
@@ -508,6 +529,16 @@
   __NFTA_LIMIT_MAX
 };
 #define NFTA_LIMIT_MAX (__NFTA_LIMIT_MAX - 1)
+enum nft_connlimit_flags {
+  NFT_CONNLIMIT_F_INV = (1 << 0),
+};
+enum nft_connlimit_attributes {
+  NFTA_CONNLIMIT_UNSPEC,
+  NFTA_CONNLIMIT_COUNT,
+  NFTA_CONNLIMIT_FLAGS,
+  __NFTA_CONNLIMIT_MAX
+};
+#define NFTA_CONNLIMIT_MAX (__NFTA_CONNLIMIT_MAX - 1)
 enum nft_counter_attributes {
   NFTA_COUNTER_UNSPEC,
   NFTA_COUNTER_BYTES,
@@ -527,6 +558,19 @@
   __NFTA_LOG_MAX
 };
 #define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1)
+enum nft_log_level {
+  NFT_LOGLEVEL_EMERG,
+  NFT_LOGLEVEL_ALERT,
+  NFT_LOGLEVEL_CRIT,
+  NFT_LOGLEVEL_ERR,
+  NFT_LOGLEVEL_WARNING,
+  NFT_LOGLEVEL_NOTICE,
+  NFT_LOGLEVEL_INFO,
+  NFT_LOGLEVEL_DEBUG,
+  NFT_LOGLEVEL_AUDIT,
+  __NFT_LOGLEVEL_MAX
+};
+#define NFT_LOGLEVEL_MAX (__NFT_LOGLEVEL_MAX + 1)
 enum nft_queue_attributes {
   NFTA_QUEUE_UNSPEC,
   NFTA_QUEUE_NUM,
@@ -588,6 +632,14 @@
   __NFTA_NAT_MAX
 };
 #define NFTA_NAT_MAX (__NFTA_NAT_MAX - 1)
+enum nft_tproxy_attributes {
+  NFTA_TPROXY_UNSPEC,
+  NFTA_TPROXY_FAMILY,
+  NFTA_TPROXY_REG_ADDR,
+  NFTA_TPROXY_REG_PORT,
+  __NFTA_TPROXY_MAX
+};
+#define NFTA_TPROXY_MAX (__NFTA_TPROXY_MAX - 1)
 enum nft_masq_attributes {
   NFTA_MASQ_UNSPEC,
   NFTA_MASQ_FLAGS,
@@ -614,6 +666,8 @@
 enum nft_fwd_attributes {
   NFTA_FWD_UNSPEC,
   NFTA_FWD_SREG_DEV,
+  NFTA_FWD_SREG_ADDR,
+  NFTA_FWD_NFPROTO,
   __NFTA_FWD_MAX
 };
 #define NFTA_FWD_MAX (__NFTA_FWD_MAX - 1)
@@ -667,12 +721,23 @@
   __NFTA_CT_HELPER_MAX,
 };
 #define NFTA_CT_HELPER_MAX (__NFTA_CT_HELPER_MAX - 1)
+enum nft_ct_timeout_timeout_attributes {
+  NFTA_CT_TIMEOUT_UNSPEC,
+  NFTA_CT_TIMEOUT_L3PROTO,
+  NFTA_CT_TIMEOUT_L4PROTO,
+  NFTA_CT_TIMEOUT_DATA,
+  __NFTA_CT_TIMEOUT_MAX,
+};
+#define NFTA_CT_TIMEOUT_MAX (__NFTA_CT_TIMEOUT_MAX - 1)
 #define NFT_OBJECT_UNSPEC 0
 #define NFT_OBJECT_COUNTER 1
 #define NFT_OBJECT_QUOTA 2
 #define NFT_OBJECT_CT_HELPER 3
 #define NFT_OBJECT_LIMIT 4
-#define __NFT_OBJECT_MAX 5
+#define NFT_OBJECT_CONNLIMIT 5
+#define NFT_OBJECT_TUNNEL 6
+#define NFT_OBJECT_CT_TIMEOUT 7
+#define __NFT_OBJECT_MAX 8
 #define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1)
 enum nft_object_attributes {
   NFTA_OBJ_UNSPEC,
@@ -705,6 +770,12 @@
   __NFTA_FLOWTABLE_HOOK_MAX
 };
 #define NFTA_FLOWTABLE_HOOK_MAX (__NFTA_FLOWTABLE_HOOK_MAX - 1)
+enum nft_osf_attributes {
+  NFTA_OSF_UNSPEC,
+  NFTA_OSF_DREG,
+  __NFTA_OSF_MAX,
+};
+#define NFTA_OSF_MAX (__NFTA_OSF_MAX - 1)
 enum nft_devices_attributes {
   NFTA_DEVICE_UNSPEC,
   NFTA_DEVICE_NAME,
@@ -747,6 +818,8 @@
   NFTA_NG_MODULUS,
   NFTA_NG_TYPE,
   NFTA_NG_OFFSET,
+  NFTA_NG_SET_NAME,
+  NFTA_NG_SET_ID,
   __NFTA_NG_MAX
 };
 #define NFTA_NG_MAX (__NFTA_NG_MAX - 1)
@@ -756,4 +829,74 @@
   __NFT_NG_MAX
 };
 #define NFT_NG_MAX (__NFT_NG_MAX - 1)
+enum nft_tunnel_key_ip_attributes {
+  NFTA_TUNNEL_KEY_IP_UNSPEC,
+  NFTA_TUNNEL_KEY_IP_SRC,
+  NFTA_TUNNEL_KEY_IP_DST,
+  __NFTA_TUNNEL_KEY_IP_MAX
+};
+#define NFTA_TUNNEL_KEY_IP_MAX (__NFTA_TUNNEL_KEY_IP_MAX - 1)
+enum nft_tunnel_ip6_attributes {
+  NFTA_TUNNEL_KEY_IP6_UNSPEC,
+  NFTA_TUNNEL_KEY_IP6_SRC,
+  NFTA_TUNNEL_KEY_IP6_DST,
+  NFTA_TUNNEL_KEY_IP6_FLOWLABEL,
+  __NFTA_TUNNEL_KEY_IP6_MAX
+};
+#define NFTA_TUNNEL_KEY_IP6_MAX (__NFTA_TUNNEL_KEY_IP6_MAX - 1)
+enum nft_tunnel_opts_attributes {
+  NFTA_TUNNEL_KEY_OPTS_UNSPEC,
+  NFTA_TUNNEL_KEY_OPTS_VXLAN,
+  NFTA_TUNNEL_KEY_OPTS_ERSPAN,
+  __NFTA_TUNNEL_KEY_OPTS_MAX
+};
+#define NFTA_TUNNEL_KEY_OPTS_MAX (__NFTA_TUNNEL_KEY_OPTS_MAX - 1)
+enum nft_tunnel_opts_vxlan_attributes {
+  NFTA_TUNNEL_KEY_VXLAN_UNSPEC,
+  NFTA_TUNNEL_KEY_VXLAN_GBP,
+  __NFTA_TUNNEL_KEY_VXLAN_MAX
+};
+#define NFTA_TUNNEL_KEY_VXLAN_MAX (__NFTA_TUNNEL_KEY_VXLAN_MAX - 1)
+enum nft_tunnel_opts_erspan_attributes {
+  NFTA_TUNNEL_KEY_ERSPAN_UNSPEC,
+  NFTA_TUNNEL_KEY_ERSPAN_VERSION,
+  NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX,
+  NFTA_TUNNEL_KEY_ERSPAN_V2_HWID,
+  NFTA_TUNNEL_KEY_ERSPAN_V2_DIR,
+  __NFTA_TUNNEL_KEY_ERSPAN_MAX
+};
+#define NFTA_TUNNEL_KEY_ERSPAN_MAX (__NFTA_TUNNEL_KEY_ERSPAN_MAX - 1)
+enum nft_tunnel_flags {
+  NFT_TUNNEL_F_ZERO_CSUM_TX = (1 << 0),
+  NFT_TUNNEL_F_DONT_FRAGMENT = (1 << 1),
+  NFT_TUNNEL_F_SEQ_NUMBER = (1 << 2),
+};
+#define NFT_TUNNEL_F_MASK (NFT_TUNNEL_F_ZERO_CSUM_TX | NFT_TUNNEL_F_DONT_FRAGMENT | NFT_TUNNEL_F_SEQ_NUMBER)
+enum nft_tunnel_key_attributes {
+  NFTA_TUNNEL_KEY_UNSPEC,
+  NFTA_TUNNEL_KEY_ID,
+  NFTA_TUNNEL_KEY_IP,
+  NFTA_TUNNEL_KEY_IP6,
+  NFTA_TUNNEL_KEY_FLAGS,
+  NFTA_TUNNEL_KEY_TOS,
+  NFTA_TUNNEL_KEY_TTL,
+  NFTA_TUNNEL_KEY_SPORT,
+  NFTA_TUNNEL_KEY_DPORT,
+  NFTA_TUNNEL_KEY_OPTS,
+  __NFTA_TUNNEL_KEY_MAX
+};
+#define NFTA_TUNNEL_KEY_MAX (__NFTA_TUNNEL_KEY_MAX - 1)
+enum nft_tunnel_keys {
+  NFT_TUNNEL_PATH,
+  NFT_TUNNEL_ID,
+  __NFT_TUNNEL_MAX
+};
+#define NFT_TUNNEL_MAX (__NFT_TUNNEL_MAX - 1)
+enum nft_tunnel_attributes {
+  NFTA_TUNNEL_UNSPEC,
+  NFTA_TUNNEL_KEY,
+  NFTA_TUNNEL_DREG,
+  __NFTA_TUNNEL_MAX
+};
+#define NFTA_TUNNEL_MAX (__NFTA_TUNNEL_MAX - 1)
 #endif
diff --git a/libc/kernel/uapi/linux/netfilter/nfnetlink_conntrack.h b/libc/kernel/uapi/linux/netfilter/nfnetlink_conntrack.h
index 1347820..4981fc1 100644
--- a/libc/kernel/uapi/linux/netfilter/nfnetlink_conntrack.h
+++ b/libc/kernel/uapi/linux/netfilter/nfnetlink_conntrack.h
@@ -253,6 +253,7 @@
 enum ctattr_stats_global {
   CTA_STATS_GLOBAL_UNSPEC,
   CTA_STATS_GLOBAL_ENTRIES,
+  CTA_STATS_GLOBAL_MAX_ENTRIES,
   __CTA_STATS_GLOBAL_MAX,
 };
 #define CTA_STATS_GLOBAL_MAX (__CTA_STATS_GLOBAL_MAX - 1)
diff --git a/libc/kernel/uapi/linux/netfilter/nfnetlink_osf.h b/libc/kernel/uapi/linux/netfilter/nfnetlink_osf.h
new file mode 100644
index 0000000..3f930da
--- /dev/null
+++ b/libc/kernel/uapi/linux/netfilter/nfnetlink_osf.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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 _NF_OSF_H
+#define _NF_OSF_H
+#include <linux/types.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#define MAXGENRELEN 32
+#define NF_OSF_GENRE (1 << 0)
+#define NF_OSF_TTL (1 << 1)
+#define NF_OSF_LOG (1 << 2)
+#define NF_OSF_INVERT (1 << 3)
+#define NF_OSF_LOGLEVEL_ALL 0
+#define NF_OSF_LOGLEVEL_FIRST 1
+#define NF_OSF_LOGLEVEL_ALL_KNOWN 2
+#define NF_OSF_TTL_TRUE 0
+#define NF_OSF_TTL_LESS 1
+#define NF_OSF_TTL_NOCHECK 2
+#define NF_OSF_FLAGMASK (NF_OSF_GENRE | NF_OSF_TTL | NF_OSF_LOG | NF_OSF_INVERT)
+struct nf_osf_wc {
+  __u32 wc;
+  __u32 val;
+};
+struct nf_osf_opt {
+  __u16 kind, length;
+  struct nf_osf_wc wc;
+};
+struct nf_osf_info {
+  char genre[MAXGENRELEN];
+  __u32 len;
+  __u32 flags;
+  __u32 loglevel;
+  __u32 ttl;
+};
+struct nf_osf_user_finger {
+  struct nf_osf_wc wss;
+  __u8 ttl, df;
+  __u16 ss, mss;
+  __u16 opt_num;
+  char genre[MAXGENRELEN];
+  char version[MAXGENRELEN];
+  char subtype[MAXGENRELEN];
+  struct nf_osf_opt opt[MAX_IPOPTLEN];
+};
+struct nf_osf_nlmsg {
+  struct nf_osf_user_finger f;
+  struct iphdr ip;
+  struct tcphdr tcp;
+};
+enum iana_options {
+  OSFOPT_EOL = 0,
+  OSFOPT_NOP,
+  OSFOPT_MSS,
+  OSFOPT_WSO,
+  OSFOPT_SACKP,
+  OSFOPT_SACK,
+  OSFOPT_ECHO,
+  OSFOPT_ECHOREPLY,
+  OSFOPT_TS,
+  OSFOPT_POCP,
+  OSFOPT_POSP,
+  OSFOPT_EMPTY = 255,
+};
+enum nf_osf_window_size_options {
+  OSF_WSS_PLAIN = 0,
+  OSF_WSS_MSS,
+  OSF_WSS_MTU,
+  OSF_WSS_MODULO,
+  OSF_WSS_MAX,
+};
+enum nf_osf_attr_type {
+  OSF_ATTR_UNSPEC,
+  OSF_ATTR_FINGER,
+  OSF_ATTR_MAX,
+};
+enum nf_osf_msg_types {
+  OSF_MSG_ADD,
+  OSF_MSG_REMOVE,
+  OSF_MSG_MAX,
+};
+#endif
diff --git a/libc/kernel/uapi/linux/netfilter/xt_osf.h b/libc/kernel/uapi/linux/netfilter/xt_osf.h
index 50156ef..892ad40 100644
--- a/libc/kernel/uapi/linux/netfilter/xt_osf.h
+++ b/libc/kernel/uapi/linux/netfilter/xt_osf.h
@@ -19,78 +19,24 @@
 #ifndef _XT_OSF_H
 #define _XT_OSF_H
 #include <linux/types.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#define MAXGENRELEN 32
-#define XT_OSF_GENRE (1 << 0)
-#define XT_OSF_TTL (1 << 1)
-#define XT_OSF_LOG (1 << 2)
-#define XT_OSF_INVERT (1 << 3)
-#define XT_OSF_LOGLEVEL_ALL 0
-#define XT_OSF_LOGLEVEL_FIRST 1
-#define XT_OSF_LOGLEVEL_ALL_KNOWN 2
-#define XT_OSF_TTL_TRUE 0
-#define XT_OSF_TTL_LESS 1
-#define XT_OSF_TTL_NOCHECK 2
-struct xt_osf_info {
-  char genre[MAXGENRELEN];
-  __u32 len;
-  __u32 flags;
-  __u32 loglevel;
-  __u32 ttl;
-};
-struct xt_osf_wc {
-  __u32 wc;
-  __u32 val;
-};
-struct xt_osf_opt {
-  __u16 kind, length;
-  struct xt_osf_wc wc;
-};
-struct xt_osf_user_finger {
-  struct xt_osf_wc wss;
-  __u8 ttl, df;
-  __u16 ss, mss;
-  __u16 opt_num;
-  char genre[MAXGENRELEN];
-  char version[MAXGENRELEN];
-  char subtype[MAXGENRELEN];
-  struct xt_osf_opt opt[MAX_IPOPTLEN];
-};
-struct xt_osf_nlmsg {
-  struct xt_osf_user_finger f;
-  struct iphdr ip;
-  struct tcphdr tcp;
-};
-enum iana_options {
-  OSFOPT_EOL = 0,
-  OSFOPT_NOP,
-  OSFOPT_MSS,
-  OSFOPT_WSO,
-  OSFOPT_SACKP,
-  OSFOPT_SACK,
-  OSFOPT_ECHO,
-  OSFOPT_ECHOREPLY,
-  OSFOPT_TS,
-  OSFOPT_POCP,
-  OSFOPT_POSP,
-  OSFOPT_EMPTY = 255,
-};
-enum xt_osf_window_size_options {
-  OSF_WSS_PLAIN = 0,
-  OSF_WSS_MSS,
-  OSF_WSS_MTU,
-  OSF_WSS_MODULO,
-  OSF_WSS_MAX,
-};
-enum xt_osf_msg_types {
-  OSF_MSG_ADD,
-  OSF_MSG_REMOVE,
-  OSF_MSG_MAX,
-};
-enum xt_osf_attr_type {
-  OSF_ATTR_UNSPEC,
-  OSF_ATTR_FINGER,
-  OSF_ATTR_MAX,
-};
+#include <linux/netfilter/nfnetlink_osf.h>
+#define XT_OSF_GENRE NF_OSF_GENRE
+#define XT_OSF_INVERT NF_OSF_INVERT
+#define XT_OSF_TTL NF_OSF_TTL
+#define XT_OSF_LOG NF_OSF_LOG
+#define XT_OSF_LOGLEVEL_ALL NF_OSF_LOGLEVEL_ALL
+#define XT_OSF_LOGLEVEL_FIRST NF_OSF_LOGLEVEL_FIRST
+#define XT_OSF_LOGLEVEL_ALL_KNOWN NF_OSF_LOGLEVEL_ALL_KNOWN
+#define XT_OSF_TTL_TRUE NF_OSF_TTL_TRUE
+#define XT_OSF_TTL_NOCHECK NF_OSF_TTL_NOCHECK
+#define XT_OSF_TTL_LESS NF_OSF_TTL_LESS
+#define xt_osf_wc nf_osf_wc
+#define xt_osf_opt nf_osf_opt
+#define xt_osf_info nf_osf_info
+#define xt_osf_user_finger nf_osf_user_finger
+#define xt_osf_finger nf_osf_finger
+#define xt_osf_nlmsg nf_osf_nlmsg
+#define xt_osf_window_size_options nf_osf_window_size_options
+#define xt_osf_attr_type nf_osf_attr_type
+#define xt_osf_msg_types nf_osf_msg_types
 #endif
diff --git a/libc/kernel/uapi/linux/netfilter_bridge.h b/libc/kernel/uapi/linux/netfilter_bridge.h
index 57de0e9..6da98f5 100644
--- a/libc/kernel/uapi/linux/netfilter_bridge.h
+++ b/libc/kernel/uapi/linux/netfilter_bridge.h
@@ -30,4 +30,14 @@
 #define NF_BR_POST_ROUTING 4
 #define NF_BR_BROUTING 5
 #define NF_BR_NUMHOOKS 6
+enum nf_br_hook_priorities {
+  NF_BR_PRI_FIRST = INT_MIN,
+  NF_BR_PRI_NAT_DST_BRIDGED = - 300,
+  NF_BR_PRI_FILTER_BRIDGED = - 200,
+  NF_BR_PRI_BRNF = 0,
+  NF_BR_PRI_NAT_DST_OTHER = 100,
+  NF_BR_PRI_FILTER_OTHER = 200,
+  NF_BR_PRI_NAT_SRC = 300,
+  NF_BR_PRI_LAST = INT_MAX,
+};
 #endif
diff --git a/libc/kernel/uapi/linux/netfilter_ipv6/ip6t_srh.h b/libc/kernel/uapi/linux/netfilter_ipv6/ip6t_srh.h
index 70fd3e4..a9474e7 100644
--- a/libc/kernel/uapi/linux/netfilter_ipv6/ip6t_srh.h
+++ b/libc/kernel/uapi/linux/netfilter_ipv6/ip6t_srh.h
@@ -31,7 +31,10 @@
 #define IP6T_SRH_LAST_GT 0x0100
 #define IP6T_SRH_LAST_LT 0x0200
 #define IP6T_SRH_TAG 0x0400
-#define IP6T_SRH_MASK 0x07FF
+#define IP6T_SRH_PSID 0x0800
+#define IP6T_SRH_NSID 0x1000
+#define IP6T_SRH_LSID 0x2000
+#define IP6T_SRH_MASK 0x3FFF
 #define IP6T_SRH_INV_NEXTHDR 0x0001
 #define IP6T_SRH_INV_LEN_EQ 0x0002
 #define IP6T_SRH_INV_LEN_GT 0x0004
@@ -43,7 +46,10 @@
 #define IP6T_SRH_INV_LAST_GT 0x0100
 #define IP6T_SRH_INV_LAST_LT 0x0200
 #define IP6T_SRH_INV_TAG 0x0400
-#define IP6T_SRH_INV_MASK 0x07FF
+#define IP6T_SRH_INV_PSID 0x0800
+#define IP6T_SRH_INV_NSID 0x1000
+#define IP6T_SRH_INV_LSID 0x2000
+#define IP6T_SRH_INV_MASK 0x3FFF
 struct ip6t_srh {
   __u8 next_hdr;
   __u8 hdr_len;
@@ -53,4 +59,19 @@
   __u16 mt_flags;
   __u16 mt_invflags;
 };
+struct ip6t_srh1 {
+  __u8 next_hdr;
+  __u8 hdr_len;
+  __u8 segs_left;
+  __u8 last_entry;
+  __u16 tag;
+  struct in6_addr psid_addr;
+  struct in6_addr nsid_addr;
+  struct in6_addr lsid_addr;
+  struct in6_addr psid_msk;
+  struct in6_addr nsid_msk;
+  struct in6_addr lsid_msk;
+  __u16 mt_flags;
+  __u16 mt_invflags;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/nl80211.h b/libc/kernel/uapi/linux/nl80211.h
index 349b471..1f2f77d 100644
--- a/libc/kernel/uapi/linux/nl80211.h
+++ b/libc/kernel/uapi/linux/nl80211.h
@@ -444,6 +444,11 @@
   NL80211_ATTR_NSS,
   NL80211_ATTR_ACK_SIGNAL,
   NL80211_ATTR_CONTROL_PORT_OVER_NL80211,
+  NL80211_ATTR_TXQ_STATS,
+  NL80211_ATTR_TXQ_LIMIT,
+  NL80211_ATTR_TXQ_MEMORY_LIMIT,
+  NL80211_ATTR_TXQ_QUANTUM,
+  NL80211_ATTR_HE_CAPABILITY,
   __NL80211_ATTR_AFTER_LAST,
   NUM_NL80211_ATTR = __NL80211_ATTR_AFTER_LAST,
   NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
@@ -482,6 +487,8 @@
 #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24
 #define NL80211_HT_CAPABILITY_LEN 26
 #define NL80211_VHT_CAPABILITY_LEN 12
+#define NL80211_HE_MIN_CAPABILITY_LEN 16
+#define NL80211_HE_MAX_CAPABILITY_LEN 51
 #define NL80211_MAX_NR_CIPHER_SUITES 5
 #define NL80211_MAX_NR_AKM_SUITES 2
 #define NL80211_MIN_REMAIN_ON_CHANNEL_TIME 10
@@ -526,6 +533,20 @@
   __u32 mask;
   __u32 set;
 } __attribute__((packed));
+enum nl80211_he_gi {
+  NL80211_RATE_INFO_HE_GI_0_8,
+  NL80211_RATE_INFO_HE_GI_1_6,
+  NL80211_RATE_INFO_HE_GI_3_2,
+};
+enum nl80211_he_ru_alloc {
+  NL80211_RATE_INFO_HE_RU_ALLOC_26,
+  NL80211_RATE_INFO_HE_RU_ALLOC_52,
+  NL80211_RATE_INFO_HE_RU_ALLOC_106,
+  NL80211_RATE_INFO_HE_RU_ALLOC_242,
+  NL80211_RATE_INFO_HE_RU_ALLOC_484,
+  NL80211_RATE_INFO_HE_RU_ALLOC_996,
+  NL80211_RATE_INFO_HE_RU_ALLOC_2x996,
+};
 enum nl80211_rate_info {
   __NL80211_RATE_INFO_INVALID,
   NL80211_RATE_INFO_BITRATE,
@@ -540,6 +561,11 @@
   NL80211_RATE_INFO_160_MHZ_WIDTH,
   NL80211_RATE_INFO_10_MHZ_WIDTH,
   NL80211_RATE_INFO_5_MHZ_WIDTH,
+  NL80211_RATE_INFO_HE_MCS,
+  NL80211_RATE_INFO_HE_NSS,
+  NL80211_RATE_INFO_HE_GI,
+  NL80211_RATE_INFO_HE_DCM,
+  NL80211_RATE_INFO_HE_RU_ALLOC,
   __NL80211_RATE_INFO_AFTER_LAST,
   NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
 };
@@ -589,6 +615,7 @@
   NL80211_STA_INFO_RX_DURATION,
   NL80211_STA_INFO_PAD,
   NL80211_STA_INFO_ACK_SIGNAL,
+  NL80211_STA_INFO_DATA_ACK_SIGNAL_AVG,
   __NL80211_STA_INFO_AFTER_LAST,
   NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1
 };
@@ -599,9 +626,26 @@
   NL80211_TID_STATS_TX_MSDU_RETRIES,
   NL80211_TID_STATS_TX_MSDU_FAILED,
   NL80211_TID_STATS_PAD,
+  NL80211_TID_STATS_TXQ_STATS,
   NUM_NL80211_TID_STATS,
   NL80211_TID_STATS_MAX = NUM_NL80211_TID_STATS - 1
 };
+enum nl80211_txq_stats {
+  __NL80211_TXQ_STATS_INVALID,
+  NL80211_TXQ_STATS_BACKLOG_BYTES,
+  NL80211_TXQ_STATS_BACKLOG_PACKETS,
+  NL80211_TXQ_STATS_FLOWS,
+  NL80211_TXQ_STATS_DROPS,
+  NL80211_TXQ_STATS_ECN_MARKS,
+  NL80211_TXQ_STATS_OVERLIMIT,
+  NL80211_TXQ_STATS_OVERMEMORY,
+  NL80211_TXQ_STATS_COLLISIONS,
+  NL80211_TXQ_STATS_TX_BYTES,
+  NL80211_TXQ_STATS_TX_PACKETS,
+  NL80211_TXQ_STATS_MAX_FLOWS,
+  NUM_NL80211_TXQ_STATS,
+  NL80211_TXQ_STATS_MAX = NUM_NL80211_TXQ_STATS - 1
+};
 enum nl80211_mpath_flags {
   NL80211_MPATH_FLAG_ACTIVE = 1 << 0,
   NL80211_MPATH_FLAG_RESOLVING = 1 << 1,
@@ -621,6 +665,16 @@
   __NL80211_MPATH_INFO_AFTER_LAST,
   NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1
 };
+enum nl80211_band_iftype_attr {
+  __NL80211_BAND_IFTYPE_ATTR_INVALID,
+  NL80211_BAND_IFTYPE_ATTR_IFTYPES,
+  NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC,
+  NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY,
+  NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET,
+  NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE,
+  __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST,
+  NL80211_BAND_IFTYPE_ATTR_MAX = __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST - 1
+};
 enum nl80211_band_attr {
   __NL80211_BAND_ATTR_INVALID,
   NL80211_BAND_ATTR_FREQS,
@@ -631,10 +685,20 @@
   NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
   NL80211_BAND_ATTR_VHT_MCS_SET,
   NL80211_BAND_ATTR_VHT_CAPA,
+  NL80211_BAND_ATTR_IFTYPE_DATA,
   __NL80211_BAND_ATTR_AFTER_LAST,
   NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1
 };
 #define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA
+enum nl80211_wmm_rule {
+  __NL80211_WMMR_INVALID,
+  NL80211_WMMR_CW_MIN,
+  NL80211_WMMR_CW_MAX,
+  NL80211_WMMR_AIFSN,
+  NL80211_WMMR_TXOP,
+  __NL80211_WMMR_LAST,
+  NL80211_WMMR_MAX = __NL80211_WMMR_LAST - 1
+};
 enum nl80211_frequency_attr {
   __NL80211_FREQUENCY_ATTR_INVALID,
   NL80211_FREQUENCY_ATTR_FREQ,
@@ -654,6 +718,7 @@
   NL80211_FREQUENCY_ATTR_IR_CONCURRENT,
   NL80211_FREQUENCY_ATTR_NO_20MHZ,
   NL80211_FREQUENCY_ATTR_NO_10MHZ,
+  NL80211_FREQUENCY_ATTR_WMM,
   __NL80211_FREQUENCY_ATTR_AFTER_LAST,
   NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1
 };
@@ -1218,6 +1283,10 @@
   NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN,
   NL80211_EXT_FEATURE_DFS_OFFLOAD,
   NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211,
+  NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT,
+  NL80211_EXT_FEATURE_TXQS,
+  NL80211_EXT_FEATURE_SCAN_RANDOM_SN,
+  NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT,
   NUM_NL80211_EXT_FEATURES,
   MAX_NL80211_EXT_FEATURES = NUM_NL80211_EXT_FEATURES - 1
 };
@@ -1249,6 +1318,8 @@
   NL80211_SCAN_FLAG_LOW_SPAN = 1 << 8,
   NL80211_SCAN_FLAG_LOW_POWER = 1 << 9,
   NL80211_SCAN_FLAG_HIGH_ACCURACY = 1 << 10,
+  NL80211_SCAN_FLAG_RANDOM_SN = 1 << 11,
+  NL80211_SCAN_FLAG_MIN_PREQ_CONTENT = 1 << 12,
 };
 enum nl80211_acl_policy {
   NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED,
diff --git a/libc/kernel/uapi/linux/omap3isp.h b/libc/kernel/uapi/linux/omap3isp.h
index 66942e7..d2eceb7 100644
--- a/libc/kernel/uapi/linux/omap3isp.h
+++ b/libc/kernel/uapi/linux/omap3isp.h
@@ -26,6 +26,7 @@
 #define VIDIOC_OMAP3ISP_HIST_CFG _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct omap3isp_hist_config)
 #define VIDIOC_OMAP3ISP_AF_CFG _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct omap3isp_h3a_af_config)
 #define VIDIOC_OMAP3ISP_STAT_REQ _IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct omap3isp_stat_data)
+#define VIDIOC_OMAP3ISP_STAT_REQ_TIME32 _IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct omap3isp_stat_data_time32)
 #define VIDIOC_OMAP3ISP_STAT_EN _IOWR('V', BASE_VIDIOC_PRIVATE + 7, unsigned long)
 #define V4L2_EVENT_OMAP3ISP_CLASS (V4L2_EVENT_PRIVATE_START | 0x100)
 #define V4L2_EVENT_OMAP3ISP_AEWB (V4L2_EVENT_OMAP3ISP_CLASS | 0x1)
diff --git a/libc/kernel/uapi/linux/openvswitch.h b/libc/kernel/uapi/linux/openvswitch.h
index 1dba16e..7e75ac6 100644
--- a/libc/kernel/uapi/linux/openvswitch.h
+++ b/libc/kernel/uapi/linux/openvswitch.h
@@ -425,6 +425,7 @@
   OVS_ACTION_ATTR_PUSH_NSH,
   OVS_ACTION_ATTR_POP_NSH,
   OVS_ACTION_ATTR_METER,
+  OVS_ACTION_ATTR_CLONE,
   __OVS_ACTION_ATTR_MAX,
 };
 #define OVS_ACTION_ATTR_MAX (__OVS_ACTION_ATTR_MAX - 1)
@@ -467,4 +468,25 @@
   __OVS_METER_BAND_TYPE_MAX
 };
 #define OVS_METER_BAND_TYPE_MAX (__OVS_METER_BAND_TYPE_MAX - 1)
+#define OVS_CT_LIMIT_FAMILY "ovs_ct_limit"
+#define OVS_CT_LIMIT_MCGROUP "ovs_ct_limit"
+#define OVS_CT_LIMIT_VERSION 0x1
+enum ovs_ct_limit_cmd {
+  OVS_CT_LIMIT_CMD_UNSPEC,
+  OVS_CT_LIMIT_CMD_SET,
+  OVS_CT_LIMIT_CMD_DEL,
+  OVS_CT_LIMIT_CMD_GET
+};
+enum ovs_ct_limit_attr {
+  OVS_CT_LIMIT_ATTR_UNSPEC,
+  OVS_CT_LIMIT_ATTR_ZONE_LIMIT,
+  __OVS_CT_LIMIT_ATTR_MAX
+};
+#define OVS_CT_LIMIT_ATTR_MAX (__OVS_CT_LIMIT_ATTR_MAX - 1)
+#define OVS_ZONE_LIMIT_DEFAULT_ZONE - 1
+struct ovs_zone_limit {
+  int zone_id;
+  __u32 limit;
+  __u32 count;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/pci_regs.h b/libc/kernel/uapi/linux/pci_regs.h
index 4ef3837..7b234f5 100644
--- a/libc/kernel/uapi/linux/pci_regs.h
+++ b/libc/kernel/uapi/linux/pci_regs.h
@@ -416,6 +416,8 @@
 #define PCI_EXP_DEVCTL_READRQ_256B 0x1000
 #define PCI_EXP_DEVCTL_READRQ_512B 0x2000
 #define PCI_EXP_DEVCTL_READRQ_1024B 0x3000
+#define PCI_EXP_DEVCTL_READRQ_2048B 0x4000
+#define PCI_EXP_DEVCTL_READRQ_4096B 0x5000
 #define PCI_EXP_DEVCTL_BCR_FLR 0x8000
 #define PCI_EXP_DEVSTA 10
 #define PCI_EXP_DEVSTA_CED 0x0001
@@ -536,6 +538,7 @@
 #define PCI_EXP_DEVCAP2_OBFF_MASK 0x000c0000
 #define PCI_EXP_DEVCAP2_OBFF_MSG 0x00040000
 #define PCI_EXP_DEVCAP2_OBFF_WAKE 0x00080000
+#define PCI_EXP_DEVCAP2_EE_PREFIX 0x00200000
 #define PCI_EXP_DEVCTL2 40
 #define PCI_EXP_DEVCTL2_COMP_TIMEOUT 0x000f
 #define PCI_EXP_DEVCTL2_COMP_TMOUT_DIS 0x0010
@@ -557,6 +560,11 @@
 #define PCI_EXP_LNKCAP2_SLS_16_0GB 0x00000010
 #define PCI_EXP_LNKCAP2_CROSSLINK 0x00000100
 #define PCI_EXP_LNKCTL2 48
+#define PCI_EXP_LNKCTL2_TLS 0x000f
+#define PCI_EXP_LNKCTL2_TLS_2_5GT 0x0001
+#define PCI_EXP_LNKCTL2_TLS_5_0GT 0x0002
+#define PCI_EXP_LNKCTL2_TLS_8_0GT 0x0003
+#define PCI_EXP_LNKCTL2_TLS_16_0GT 0x0004
 #define PCI_EXP_LNKSTA2 50
 #define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 52
 #define PCI_EXP_SLTCAP2 52
@@ -814,6 +822,7 @@
 #define PCI_REBAR_CTRL_NBAR_MASK 0x000000E0
 #define PCI_REBAR_CTRL_NBAR_SHIFT 5
 #define PCI_REBAR_CTRL_BAR_SIZE 0x00001F00
+#define PCI_REBAR_CTRL_BAR_SHIFT 8
 #define PCI_DPA_CAP 4
 #define PCI_DPA_CAP_SUBSTATE_MASK 0x1F
 #define PCI_DPA_BASE_SIZEOF 16
@@ -833,6 +842,7 @@
 #define PCI_EXP_DPC_RP_PIO_LOG_SIZE 0x0F00
 #define PCI_EXP_DPC_CAP_DL_ACTIVE 0x1000
 #define PCI_EXP_DPC_CTL 6
+#define PCI_EXP_DPC_CTL_EN_FATAL 0x0001
 #define PCI_EXP_DPC_CTL_EN_NONFATAL 0x0002
 #define PCI_EXP_DPC_CTL_INT_EN 0x0008
 #define PCI_EXP_DPC_STATUS 8
diff --git a/libc/kernel/uapi/linux/pcitest.h b/libc/kernel/uapi/linux/pcitest.h
index e6c0264..c6112d0 100644
--- a/libc/kernel/uapi/linux/pcitest.h
+++ b/libc/kernel/uapi/linux/pcitest.h
@@ -24,4 +24,7 @@
 #define PCITEST_WRITE _IOW('P', 0x4, unsigned long)
 #define PCITEST_READ _IOW('P', 0x5, unsigned long)
 #define PCITEST_COPY _IOW('P', 0x6, unsigned long)
+#define PCITEST_MSIX _IOW('P', 0x7, int)
+#define PCITEST_SET_IRQTYPE _IOW('P', 0x8, int)
+#define PCITEST_GET_IRQTYPE _IO('P', 0x9)
 #endif
diff --git a/libc/kernel/uapi/linux/perf_event.h b/libc/kernel/uapi/linux/perf_event.h
index dc1e32c..c106b5b 100644
--- a/libc/kernel/uapi/linux/perf_event.h
+++ b/libc/kernel/uapi/linux/perf_event.h
@@ -100,6 +100,7 @@
   PERF_SAMPLE_REGS_INTR = 1U << 18,
   PERF_SAMPLE_PHYS_ADDR = 1U << 19,
   PERF_SAMPLE_MAX = 1U << 20,
+  __PERF_SAMPLE_CALLCHAIN_EARLY = 1ULL << 63,
 };
 enum perf_branch_sample_type_shift {
   PERF_SAMPLE_BRANCH_USER_SHIFT = 0,
diff --git a/libc/kernel/uapi/linux/pkt_cls.h b/libc/kernel/uapi/linux/pkt_cls.h
index 113469c..1ede892 100644
--- a/libc/kernel/uapi/linux/pkt_cls.h
+++ b/libc/kernel/uapi/linux/pkt_cls.h
@@ -50,12 +50,15 @@
 #define TC_ACT_REPEAT 6
 #define TC_ACT_REDIRECT 7
 #define TC_ACT_TRAP 8
+#define TC_ACT_VALUE_MAX TC_ACT_TRAP
 #define __TC_ACT_EXT_SHIFT 28
 #define __TC_ACT_EXT(local) ((local) << __TC_ACT_EXT_SHIFT)
 #define TC_ACT_EXT_VAL_MASK ((1 << __TC_ACT_EXT_SHIFT) - 1)
-#define TC_ACT_EXT_CMP(combined,opcode) (((combined) & (~TC_ACT_EXT_VAL_MASK)) == opcode)
+#define TC_ACT_EXT_OPCODE(combined) ((combined) & (~TC_ACT_EXT_VAL_MASK))
+#define TC_ACT_EXT_CMP(combined,opcode) (TC_ACT_EXT_OPCODE(combined) == opcode)
 #define TC_ACT_JUMP __TC_ACT_EXT(1)
 #define TC_ACT_GOTO_CHAIN __TC_ACT_EXT(2)
+#define TC_ACT_EXT_OPCODE_MAX TC_ACT_GOTO_CHAIN
 enum {
   TCA_ID_UNSPEC = 0,
   TCA_ID_POLICE = 1,
@@ -107,6 +110,7 @@
 #define TCA_CLS_FLAGS_SKIP_SW (1 << 1)
 #define TCA_CLS_FLAGS_IN_HW (1 << 2)
 #define TCA_CLS_FLAGS_NOT_IN_HW (1 << 3)
+#define TCA_CLS_FLAGS_VERBOSE (1 << 4)
 #define TC_U32_HTID(h) ((h) & 0xFFF00000)
 #define TC_U32_USERHTID(h) (TC_U32_HTID(h) >> 20)
 #define TC_U32_HASH(h) (((h) >> 12) & 0xFF)
@@ -375,10 +379,33 @@
   TCA_FLOWER_KEY_IP_TOS_MASK,
   TCA_FLOWER_KEY_IP_TTL,
   TCA_FLOWER_KEY_IP_TTL_MASK,
+  TCA_FLOWER_KEY_CVLAN_ID,
+  TCA_FLOWER_KEY_CVLAN_PRIO,
+  TCA_FLOWER_KEY_CVLAN_ETH_TYPE,
+  TCA_FLOWER_KEY_ENC_IP_TOS,
+  TCA_FLOWER_KEY_ENC_IP_TOS_MASK,
+  TCA_FLOWER_KEY_ENC_IP_TTL,
+  TCA_FLOWER_KEY_ENC_IP_TTL_MASK,
+  TCA_FLOWER_KEY_ENC_OPTS,
+  TCA_FLOWER_KEY_ENC_OPTS_MASK,
   __TCA_FLOWER_MAX,
 };
 #define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
 enum {
+  TCA_FLOWER_KEY_ENC_OPTS_UNSPEC,
+  TCA_FLOWER_KEY_ENC_OPTS_GENEVE,
+  __TCA_FLOWER_KEY_ENC_OPTS_MAX,
+};
+#define TCA_FLOWER_KEY_ENC_OPTS_MAX (__TCA_FLOWER_KEY_ENC_OPTS_MAX - 1)
+enum {
+  TCA_FLOWER_KEY_ENC_OPT_GENEVE_UNSPEC,
+  TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS,
+  TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE,
+  TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA,
+  __TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX,
+};
+#define TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX (__TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX - 1)
+enum {
   TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0),
   TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1),
 };
diff --git a/libc/kernel/uapi/linux/pkt_sched.h b/libc/kernel/uapi/linux/pkt_sched.h
index a3f2adf..4efbc1c 100644
--- a/libc/kernel/uapi/linux/pkt_sched.h
+++ b/libc/kernel/uapi/linux/pkt_sched.h
@@ -87,6 +87,10 @@
 struct tc_fifo_qopt {
   __u32 limit;
 };
+#define SKBPRIO_MAX_PRIORITY 64
+struct tc_skbprio_qopt {
+  __u32 limit;
+};
 #define TCQ_PRIO_BANDS 16
 #define TCQ_MIN_PRIO_BANDS 2
 struct tc_prio_qopt {
@@ -407,6 +411,7 @@
   TCA_NETEM_LATENCY64,
   TCA_NETEM_JITTER64,
   TCA_NETEM_SLOT,
+  TCA_NETEM_SLOT_DIST,
   __TCA_NETEM_MAX,
 };
 #define TCA_NETEM_MAX (__TCA_NETEM_MAX - 1)
@@ -442,6 +447,8 @@
   __s64 max_delay;
   __s32 max_packets;
   __s32 max_bytes;
+  __s64 dist_delay;
+  __s64 dist_jitter;
 };
 enum {
   NETEM_LOSS_UNSPEC,
@@ -703,4 +710,122 @@
   __TCA_CBS_MAX,
 };
 #define TCA_CBS_MAX (__TCA_CBS_MAX - 1)
+struct tc_etf_qopt {
+  __s32 delta;
+  __s32 clockid;
+  __u32 flags;
+#define TC_ETF_DEADLINE_MODE_ON BIT(0)
+#define TC_ETF_OFFLOAD_ON BIT(1)
+};
+enum {
+  TCA_ETF_UNSPEC,
+  TCA_ETF_PARMS,
+  __TCA_ETF_MAX,
+};
+#define TCA_ETF_MAX (__TCA_ETF_MAX - 1)
+enum {
+  TCA_CAKE_UNSPEC,
+  TCA_CAKE_PAD,
+  TCA_CAKE_BASE_RATE64,
+  TCA_CAKE_DIFFSERV_MODE,
+  TCA_CAKE_ATM,
+  TCA_CAKE_FLOW_MODE,
+  TCA_CAKE_OVERHEAD,
+  TCA_CAKE_RTT,
+  TCA_CAKE_TARGET,
+  TCA_CAKE_AUTORATE,
+  TCA_CAKE_MEMORY,
+  TCA_CAKE_NAT,
+  TCA_CAKE_RAW,
+  TCA_CAKE_WASH,
+  TCA_CAKE_MPU,
+  TCA_CAKE_INGRESS,
+  TCA_CAKE_ACK_FILTER,
+  TCA_CAKE_SPLIT_GSO,
+  __TCA_CAKE_MAX
+};
+#define TCA_CAKE_MAX (__TCA_CAKE_MAX - 1)
+enum {
+  __TCA_CAKE_STATS_INVALID,
+  TCA_CAKE_STATS_PAD,
+  TCA_CAKE_STATS_CAPACITY_ESTIMATE64,
+  TCA_CAKE_STATS_MEMORY_LIMIT,
+  TCA_CAKE_STATS_MEMORY_USED,
+  TCA_CAKE_STATS_AVG_NETOFF,
+  TCA_CAKE_STATS_MIN_NETLEN,
+  TCA_CAKE_STATS_MAX_NETLEN,
+  TCA_CAKE_STATS_MIN_ADJLEN,
+  TCA_CAKE_STATS_MAX_ADJLEN,
+  TCA_CAKE_STATS_TIN_STATS,
+  TCA_CAKE_STATS_DEFICIT,
+  TCA_CAKE_STATS_COBALT_COUNT,
+  TCA_CAKE_STATS_DROPPING,
+  TCA_CAKE_STATS_DROP_NEXT_US,
+  TCA_CAKE_STATS_P_DROP,
+  TCA_CAKE_STATS_BLUE_TIMER_US,
+  __TCA_CAKE_STATS_MAX
+};
+#define TCA_CAKE_STATS_MAX (__TCA_CAKE_STATS_MAX - 1)
+enum {
+  __TCA_CAKE_TIN_STATS_INVALID,
+  TCA_CAKE_TIN_STATS_PAD,
+  TCA_CAKE_TIN_STATS_SENT_PACKETS,
+  TCA_CAKE_TIN_STATS_SENT_BYTES64,
+  TCA_CAKE_TIN_STATS_DROPPED_PACKETS,
+  TCA_CAKE_TIN_STATS_DROPPED_BYTES64,
+  TCA_CAKE_TIN_STATS_ACKS_DROPPED_PACKETS,
+  TCA_CAKE_TIN_STATS_ACKS_DROPPED_BYTES64,
+  TCA_CAKE_TIN_STATS_ECN_MARKED_PACKETS,
+  TCA_CAKE_TIN_STATS_ECN_MARKED_BYTES64,
+  TCA_CAKE_TIN_STATS_BACKLOG_PACKETS,
+  TCA_CAKE_TIN_STATS_BACKLOG_BYTES,
+  TCA_CAKE_TIN_STATS_THRESHOLD_RATE64,
+  TCA_CAKE_TIN_STATS_TARGET_US,
+  TCA_CAKE_TIN_STATS_INTERVAL_US,
+  TCA_CAKE_TIN_STATS_WAY_INDIRECT_HITS,
+  TCA_CAKE_TIN_STATS_WAY_MISSES,
+  TCA_CAKE_TIN_STATS_WAY_COLLISIONS,
+  TCA_CAKE_TIN_STATS_PEAK_DELAY_US,
+  TCA_CAKE_TIN_STATS_AVG_DELAY_US,
+  TCA_CAKE_TIN_STATS_BASE_DELAY_US,
+  TCA_CAKE_TIN_STATS_SPARSE_FLOWS,
+  TCA_CAKE_TIN_STATS_BULK_FLOWS,
+  TCA_CAKE_TIN_STATS_UNRESPONSIVE_FLOWS,
+  TCA_CAKE_TIN_STATS_MAX_SKBLEN,
+  TCA_CAKE_TIN_STATS_FLOW_QUANTUM,
+  __TCA_CAKE_TIN_STATS_MAX
+};
+#define TCA_CAKE_TIN_STATS_MAX (__TCA_CAKE_TIN_STATS_MAX - 1)
+#define TC_CAKE_MAX_TINS (8)
+enum {
+  CAKE_FLOW_NONE = 0,
+  CAKE_FLOW_SRC_IP,
+  CAKE_FLOW_DST_IP,
+  CAKE_FLOW_HOSTS,
+  CAKE_FLOW_FLOWS,
+  CAKE_FLOW_DUAL_SRC,
+  CAKE_FLOW_DUAL_DST,
+  CAKE_FLOW_TRIPLE,
+  CAKE_FLOW_MAX,
+};
+enum {
+  CAKE_DIFFSERV_DIFFSERV3 = 0,
+  CAKE_DIFFSERV_DIFFSERV4,
+  CAKE_DIFFSERV_DIFFSERV8,
+  CAKE_DIFFSERV_BESTEFFORT,
+  CAKE_DIFFSERV_PRECEDENCE,
+  CAKE_DIFFSERV_MAX
+};
+enum {
+  CAKE_ACK_NONE = 0,
+  CAKE_ACK_FILTER,
+  CAKE_ACK_AGGRESSIVE,
+  CAKE_ACK_MAX
+};
+enum {
+  CAKE_ATM_NONE = 0,
+  CAKE_ATM_ATM,
+  CAKE_ATM_PTM,
+  CAKE_ATM_MAX
+};
 #endif
diff --git a/libc/kernel/uapi/linux/psp-sev.h b/libc/kernel/uapi/linux/psp-sev.h
index 5f59330..10582d4 100644
--- a/libc/kernel/uapi/linux/psp-sev.h
+++ b/libc/kernel/uapi/linux/psp-sev.h
@@ -27,6 +27,7 @@
   SEV_PDH_GEN,
   SEV_PDH_CERT_EXPORT,
   SEV_PEK_CERT_IMPORT,
+  SEV_GET_ID,
   SEV_MAX,
 };
 typedef enum {
@@ -78,6 +79,10 @@
   __u64 cert_chain_address;
   __u32 cert_chain_len;
 } __packed;
+struct sev_user_data_get_id {
+  __u8 socket1[64];
+  __u8 socket2[64];
+} __packed;
 struct sev_issue_cmd {
   __u32 cmd;
   __u64 data;
diff --git a/libc/kernel/uapi/linux/rds.h b/libc/kernel/uapi/linux/rds.h
index c726f54..05da0cd 100644
--- a/libc/kernel/uapi/linux/rds.h
+++ b/libc/kernel/uapi/linux/rds.h
@@ -20,6 +20,7 @@
 #define _LINUX_RDS_H
 #include <linux/types.h>
 #include <linux/socket.h>
+#include <linux/in6.h>
 #define RDS_IB_ABI_VERSION 0x301
 #define SOL_RDS 276
 #define RDS_CANCEL_SENT_TO 1
@@ -58,7 +59,14 @@
 #define RDS_INFO_IB_CONNECTIONS 10008
 #define RDS_INFO_CONNECTION_STATS 10009
 #define RDS_INFO_IWARP_CONNECTIONS 10010
-#define RDS_INFO_LAST 10010
+#define RDS6_INFO_CONNECTIONS 10011
+#define RDS6_INFO_SEND_MESSAGES 10012
+#define RDS6_INFO_RETRANS_MESSAGES 10013
+#define RDS6_INFO_RECV_MESSAGES 10014
+#define RDS6_INFO_SOCKETS 10015
+#define RDS6_INFO_TCP_SOCKETS 10016
+#define RDS6_INFO_IB_CONNECTIONS 10017
+#define RDS_INFO_LAST 10017
 struct rds_info_counter {
   __u8 name[32];
   __u64 value;
@@ -75,6 +83,14 @@
   __u8 transport[TRANSNAMSIZ];
   __u8 flags;
 } __attribute__((packed));
+struct rds6_info_connection {
+  __u64 next_tx_seq;
+  __u64 next_rx_seq;
+  struct in6_addr laddr;
+  struct in6_addr faddr;
+  __u8 transport[TRANSNAMSIZ];
+  __u8 flags;
+} __attribute__((packed));
 #define RDS_INFO_MESSAGE_FLAG_ACK 0x01
 #define RDS_INFO_MESSAGE_FLAG_FAST_ACK 0x02
 struct rds_info_message {
@@ -86,6 +102,16 @@
   __be16 fport;
   __u8 flags;
 } __attribute__((packed));
+struct rds6_info_message {
+  __u64 seq;
+  __u32 len;
+  struct in6_addr laddr;
+  struct in6_addr faddr;
+  __be16 lport;
+  __be16 fport;
+  __u8 flags;
+  __u8 tos;
+} __attribute__((packed));
 struct rds_info_socket {
   __u32 sndbuf;
   __be32 bound_addr;
@@ -95,6 +121,15 @@
   __u32 rcvbuf;
   __u64 inum;
 } __attribute__((packed));
+struct rds6_info_socket {
+  __u32 sndbuf;
+  struct in6_addr bound_addr;
+  struct in6_addr connected_addr;
+  __be16 bound_port;
+  __be16 connected_port;
+  __u32 rcvbuf;
+  __u64 inum;
+} __attribute__((packed));
 struct rds_info_tcp_socket {
   __be32 local_addr;
   __be16 local_port;
@@ -106,6 +141,17 @@
   __u32 last_expected_una;
   __u32 last_seen_una;
 } __attribute__((packed));
+struct rds6_info_tcp_socket {
+  struct in6_addr local_addr;
+  __be16 local_port;
+  struct in6_addr peer_addr;
+  __be16 peer_port;
+  __u64 hdr_rem;
+  __u64 data_rem;
+  __u32 last_sent_nxt;
+  __u32 last_expected_una;
+  __u32 last_seen_una;
+} __attribute__((packed));
 #define RDS_IB_GID_LEN 16
 struct rds_info_rdma_connection {
   __be32 src_addr;
@@ -118,6 +164,17 @@
   __u32 rdma_mr_max;
   __u32 rdma_mr_size;
 };
+struct rds6_info_rdma_connection {
+  struct in6_addr src_addr;
+  struct in6_addr dst_addr;
+  __u8 src_gid[RDS_IB_GID_LEN];
+  __u8 dst_gid[RDS_IB_GID_LEN];
+  __u32 max_send_wr;
+  __u32 max_recv_wr;
+  __u32 max_send_sge;
+  __u32 rdma_mr_max;
+  __u32 rdma_mr_size;
+};
 enum rds_message_rxpath_latency {
   RDS_MSG_RX_HDR_TO_DGRAM_START = 0,
   RDS_MSG_RX_DGRAM_REASSEMBLE,
diff --git a/libc/kernel/uapi/linux/rseq.h b/libc/kernel/uapi/linux/rseq.h
new file mode 100644
index 0000000..ba0ceb1
--- /dev/null
+++ b/libc/kernel/uapi/linux/rseq.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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_RSEQ_H
+#define _UAPI_LINUX_RSEQ_H
+#include <linux/types.h>
+#include <asm/byteorder.h>
+enum rseq_cpu_id_state {
+  RSEQ_CPU_ID_UNINITIALIZED = - 1,
+  RSEQ_CPU_ID_REGISTRATION_FAILED = - 2,
+};
+enum rseq_flags {
+  RSEQ_FLAG_UNREGISTER = (1 << 0),
+};
+enum rseq_cs_flags_bit {
+  RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT = 0,
+  RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT = 1,
+  RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT = 2,
+};
+enum rseq_cs_flags {
+  RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT = (1U << RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT),
+  RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL = (1U << RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT),
+  RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE = (1U << RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT),
+};
+struct rseq_cs {
+  __u32 version;
+  __u32 flags;
+  __u64 start_ip;
+  __u64 post_commit_offset;
+  __u64 abort_ip;
+} __attribute__((aligned(4 * sizeof(__u64))));
+struct rseq {
+  __u32 cpu_id_start;
+  __u32 cpu_id;
+  union {
+    __u64 ptr64;
+#ifdef __LP64__
+    __u64 ptr;
+#else
+    struct {
+#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || defined(__BIG_ENDIAN)
+      __u32 padding;
+      __u32 ptr32;
+#else
+      __u32 ptr32;
+      __u32 padding;
+#endif
+    } ptr;
+#endif
+  } rseq_cs;
+  __u32 flags;
+} __attribute__((aligned(4 * sizeof(__u64))));
+#endif
diff --git a/libc/kernel/uapi/linux/rtnetlink.h b/libc/kernel/uapi/linux/rtnetlink.h
index 6fffcd3..33af1b3 100644
--- a/libc/kernel/uapi/linux/rtnetlink.h
+++ b/libc/kernel/uapi/linux/rtnetlink.h
@@ -133,6 +133,12 @@
 #define RTM_GETSTATS RTM_GETSTATS
   RTM_NEWCACHEREPORT = 96,
 #define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT
+  RTM_NEWCHAIN = 100,
+#define RTM_NEWCHAIN RTM_NEWCHAIN
+  RTM_DELCHAIN,
+#define RTM_DELCHAIN RTM_DELCHAIN
+  RTM_GETCHAIN,
+#define RTM_GETCHAIN RTM_GETCHAIN
   __RTM_MAX,
 #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
 };
@@ -194,6 +200,11 @@
 #define RTPROT_DHCP 16
 #define RTPROT_MROUTED 17
 #define RTPROT_BABEL 42
+#define RTPROT_BGP 186
+#define RTPROT_ISIS 187
+#define RTPROT_OSPF 188
+#define RTPROT_RIP 189
+#define RTPROT_EIGRP 192
 enum rt_scope_t {
   RT_SCOPE_UNIVERSE = 0,
   RT_SCOPE_SITE = 200,
@@ -243,6 +254,9 @@
   RTA_PAD,
   RTA_UID,
   RTA_TTL_PROPAGATE,
+  RTA_IP_PROTO,
+  RTA_SPORT,
+  RTA_DPORT,
   __RTA_MAX
 };
 #define RTA_MAX (__RTA_MAX - 1)
diff --git a/libc/kernel/uapi/linux/sctp.h b/libc/kernel/uapi/linux/sctp.h
index 1f7fed1..6ba738e 100644
--- a/libc/kernel/uapi/linux/sctp.h
+++ b/libc/kernel/uapi/linux/sctp.h
@@ -59,6 +59,7 @@
 #define SCTP_RECVNXTINFO 33
 #define SCTP_DEFAULT_SNDINFO 34
 #define SCTP_AUTH_DEACTIVATE_KEY 35
+#define SCTP_REUSE_PORT 36
 #define SCTP_SOCKOPT_BINDX_ADD 100
 #define SCTP_SOCKOPT_BINDX_REM 101
 #define SCTP_SOCKOPT_PEELOFF 102
@@ -159,6 +160,7 @@
   SCTP_ABORT = (1 << 2),
   SCTP_SACK_IMMEDIATELY = (1 << 3),
   SCTP_SENDALL = (1 << 6),
+  SCTP_PR_SCTP_ALL = (1 << 7),
   SCTP_NOTIFICATION = MSG_NOTIFICATION,
   SCTP_EOF = MSG_FIN,
 };
@@ -428,6 +430,8 @@
   SPP_SACKDELAY_DISABLE = 1 << 6,
   SPP_SACKDELAY = SPP_SACKDELAY_ENABLE | SPP_SACKDELAY_DISABLE,
   SPP_HB_TIME_IS_ZERO = 1 << 7,
+  SPP_IPV6_FLOWLABEL = 1 << 8,
+  SPP_DSCP = 1 << 9,
 };
 struct sctp_paddrparams {
   sctp_assoc_t spp_assoc_id;
@@ -437,6 +441,8 @@
   __u32 spp_pathmtu;
   __u32 spp_sackdelay;
   __u32 spp_flags;
+  __u32 spp_ipv6_flowlabel;
+  __u8 spp_dscp;
 } __attribute__((packed, aligned(4)));
 struct sctp_authchunk {
   __u8 sauth_chunk;
diff --git a/libc/kernel/uapi/linux/seg6_local.h b/libc/kernel/uapi/linux/seg6_local.h
index 7a10701..73873a8 100644
--- a/libc/kernel/uapi/linux/seg6_local.h
+++ b/libc/kernel/uapi/linux/seg6_local.h
@@ -28,6 +28,7 @@
   SEG6_LOCAL_NH6,
   SEG6_LOCAL_IIF,
   SEG6_LOCAL_OIF,
+  SEG6_LOCAL_BPF,
   __SEG6_LOCAL_MAX,
 };
 #define SEG6_LOCAL_MAX (__SEG6_LOCAL_MAX - 1)
@@ -47,7 +48,15 @@
   SEG6_LOCAL_ACTION_END_S = 12,
   SEG6_LOCAL_ACTION_END_AS = 13,
   SEG6_LOCAL_ACTION_END_AM = 14,
+  SEG6_LOCAL_ACTION_END_BPF = 15,
   __SEG6_LOCAL_ACTION_MAX,
 };
 #define SEG6_LOCAL_ACTION_MAX (__SEG6_LOCAL_ACTION_MAX - 1)
+enum {
+  SEG6_LOCAL_BPF_PROG_UNSPEC,
+  SEG6_LOCAL_BPF_PROG,
+  SEG6_LOCAL_BPF_PROG_NAME,
+  __SEG6_LOCAL_BPF_PROG_MAX,
+};
+#define SEG6_LOCAL_BPF_PROG_MAX (__SEG6_LOCAL_BPF_PROG_MAX - 1)
 #endif
diff --git a/libc/kernel/uapi/linux/shm.h b/libc/kernel/uapi/linux/shm.h
index a30a089..57394cb 100644
--- a/libc/kernel/uapi/linux/shm.h
+++ b/libc/kernel/uapi/linux/shm.h
@@ -53,7 +53,9 @@
 #define SHM_HUGE_2MB HUGETLB_FLAG_ENCODE_2MB
 #define SHM_HUGE_8MB HUGETLB_FLAG_ENCODE_8MB
 #define SHM_HUGE_16MB HUGETLB_FLAG_ENCODE_16MB
+#define SHM_HUGE_32MB HUGETLB_FLAG_ENCODE_32MB
 #define SHM_HUGE_256MB HUGETLB_FLAG_ENCODE_256MB
+#define SHM_HUGE_512MB HUGETLB_FLAG_ENCODE_512MB
 #define SHM_HUGE_1GB HUGETLB_FLAG_ENCODE_1GB
 #define SHM_HUGE_2GB HUGETLB_FLAG_ENCODE_2GB
 #define SHM_HUGE_16GB HUGETLB_FLAG_ENCODE_16GB
diff --git a/libc/kernel/uapi/linux/signalfd.h b/libc/kernel/uapi/linux/signalfd.h
index a1fe2de..5108ef0 100644
--- a/libc/kernel/uapi/linux/signalfd.h
+++ b/libc/kernel/uapi/linux/signalfd.h
@@ -40,6 +40,10 @@
   __u64 ssi_stime;
   __u64 ssi_addr;
   __u16 ssi_addr_lsb;
-  __u8 __pad[46];
+  __u16 __pad2;
+  __s32 ssi_syscall;
+  __u64 ssi_call_addr;
+  __u32 ssi_arch;
+  __u8 __pad[28];
 };
 #endif
diff --git a/libc/kernel/uapi/linux/smc_diag.h b/libc/kernel/uapi/linux/smc_diag.h
index 66f93f0..30e0fa2 100644
--- a/libc/kernel/uapi/linux/smc_diag.h
+++ b/libc/kernel/uapi/linux/smc_diag.h
@@ -30,17 +30,27 @@
 struct smc_diag_msg {
   __u8 diag_family;
   __u8 diag_state;
-  __u8 diag_fallback;
+  union {
+    __u8 diag_mode;
+    __u8 diag_fallback;
+  };
   __u8 diag_shutdown;
   struct inet_diag_sockid id;
   __u32 diag_uid;
-  __u64 diag_inode;
+  __aligned_u64 diag_inode;
+};
+enum {
+  SMC_DIAG_MODE_SMCR,
+  SMC_DIAG_MODE_FALLBACK_TCP,
+  SMC_DIAG_MODE_SMCD,
 };
 enum {
   SMC_DIAG_NONE,
   SMC_DIAG_CONNINFO,
   SMC_DIAG_LGRINFO,
   SMC_DIAG_SHUTDOWN,
+  SMC_DIAG_DMBINFO,
+  SMC_DIAG_FALLBACK,
   __SMC_DIAG_MAX,
 };
 #define SMC_DIAG_MAX (__SMC_DIAG_MAX - 1)
@@ -77,4 +87,15 @@
   struct smc_diag_linkinfo lnk[1];
   __u8 role;
 };
+struct smc_diag_fallback {
+  __u32 reason;
+  __u32 peer_diagnosis;
+};
+struct smcd_diag_dmbinfo {
+  __u32 linkid;
+  __aligned_u64 peer_gid;
+  __aligned_u64 my_gid;
+  __aligned_u64 token;
+  __aligned_u64 peer_token;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/snmp.h b/libc/kernel/uapi/linux/snmp.h
index b9f0c3e..ae24f0f 100644
--- a/libc/kernel/uapi/linux/snmp.h
+++ b/libc/kernel/uapi/linux/snmp.h
@@ -55,6 +55,7 @@
   IPSTATS_MIB_ECT1PKTS,
   IPSTATS_MIB_ECT0PKTS,
   IPSTATS_MIB_CEPKTS,
+  IPSTATS_MIB_REASM_OVERLAPS,
   __IPSTATS_MIB_MAX
 };
 enum {
@@ -243,6 +244,11 @@
   LINUX_MIB_TCPKEEPALIVE,
   LINUX_MIB_TCPMTUPFAIL,
   LINUX_MIB_TCPMTUPSUCCESS,
+  LINUX_MIB_TCPDELIVERED,
+  LINUX_MIB_TCPDELIVEREDCE,
+  LINUX_MIB_TCPACKCOMPRESSED,
+  LINUX_MIB_TCPZEROWINDOWDROP,
+  LINUX_MIB_TCPRCVQDROP,
   __LINUX_MIB_MAX
 };
 enum {
diff --git a/libc/kernel/uapi/linux/sysctl.h b/libc/kernel/uapi/linux/sysctl.h
index eb6e61f..24d8362 100644
--- a/libc/kernel/uapi/linux/sysctl.h
+++ b/libc/kernel/uapi/linux/sysctl.h
@@ -491,7 +491,8 @@
   __NET_IPV6_MAX
 };
 enum {
-  NET_IPV6_ICMP_RATELIMIT = 1
+  NET_IPV6_ICMP_RATELIMIT = 1,
+  NET_IPV6_ICMP_ECHO_IGNORE_ALL = 2
 };
 enum {
   NET_NEIGH_MCAST_SOLICIT = 1,
diff --git a/libc/kernel/uapi/linux/target_core_user.h b/libc/kernel/uapi/linux/target_core_user.h
index 264b46f..7c997d1 100644
--- a/libc/kernel/uapi/linux/target_core_user.h
+++ b/libc/kernel/uapi/linux/target_core_user.h
@@ -24,6 +24,7 @@
 #define TCMU_MAILBOX_VERSION 2
 #define ALIGN_SIZE 64
 #define TCMU_MAILBOX_FLAG_CAP_OOOC (1 << 0)
+#define TCMU_MAILBOX_FLAG_CAP_READ_LEN (1 << 1)
 struct tcmu_mailbox {
   __u16 version;
   __u16 flags;
@@ -41,6 +42,7 @@
   __u16 cmd_id;
   __u8 kflags;
 #define TCMU_UFLAG_UNKNOWN_OP 0x1
+#define TCMU_UFLAG_READ_LEN 0x2
   __u8 uflags;
 } __packed;
 #define TCMU_OP_MASK 0x7
@@ -61,7 +63,7 @@
       __u8 scsi_status;
       __u8 __pad1;
       __u16 __pad2;
-      __u32 __pad3;
+      __u32 read_len;
       char sense_buffer[TCMU_SENSE_BUFFERSIZE];
     } rsp;
   };
diff --git a/libc/kernel/uapi/linux/tc_act/tc_skbedit.h b/libc/kernel/uapi/linux/tc_act/tc_skbedit.h
index cb5c2e1..30d529a 100644
--- a/libc/kernel/uapi/linux/tc_act/tc_skbedit.h
+++ b/libc/kernel/uapi/linux/tc_act/tc_skbedit.h
@@ -25,6 +25,7 @@
 #define SKBEDIT_F_MARK 0x4
 #define SKBEDIT_F_PTYPE 0x8
 #define SKBEDIT_F_MASK 0x10
+#define SKBEDIT_F_INHERITDSFIELD 0x20
 struct tc_skbedit {
   tc_gen;
 };
@@ -38,6 +39,7 @@
   TCA_SKBEDIT_PAD,
   TCA_SKBEDIT_PTYPE,
   TCA_SKBEDIT_MASK,
+  TCA_SKBEDIT_FLAGS,
   __TCA_SKBEDIT_MAX
 };
 #define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1)
diff --git a/libc/kernel/uapi/linux/tc_act/tc_tunnel_key.h b/libc/kernel/uapi/linux/tc_act/tc_tunnel_key.h
index 24e7403..bd5fb24 100644
--- a/libc/kernel/uapi/linux/tc_act/tc_tunnel_key.h
+++ b/libc/kernel/uapi/linux/tc_act/tc_tunnel_key.h
@@ -38,7 +38,24 @@
   TCA_TUNNEL_KEY_PAD,
   TCA_TUNNEL_KEY_ENC_DST_PORT,
   TCA_TUNNEL_KEY_NO_CSUM,
+  TCA_TUNNEL_KEY_ENC_OPTS,
+  TCA_TUNNEL_KEY_ENC_TOS,
+  TCA_TUNNEL_KEY_ENC_TTL,
   __TCA_TUNNEL_KEY_MAX,
 };
 #define TCA_TUNNEL_KEY_MAX (__TCA_TUNNEL_KEY_MAX - 1)
+enum {
+  TCA_TUNNEL_KEY_ENC_OPTS_UNSPEC,
+  TCA_TUNNEL_KEY_ENC_OPTS_GENEVE,
+  __TCA_TUNNEL_KEY_ENC_OPTS_MAX,
+};
+#define TCA_TUNNEL_KEY_ENC_OPTS_MAX (__TCA_TUNNEL_KEY_ENC_OPTS_MAX - 1)
+enum {
+  TCA_TUNNEL_KEY_ENC_OPT_GENEVE_UNSPEC,
+  TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS,
+  TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE,
+  TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA,
+  __TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX,
+};
+#define TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX (__TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX - 1)
 #endif
diff --git a/libc/kernel/uapi/linux/tcp.h b/libc/kernel/uapi/linux/tcp.h
index 8b73119..d940f0f 100644
--- a/libc/kernel/uapi/linux/tcp.h
+++ b/libc/kernel/uapi/linux/tcp.h
@@ -89,6 +89,12 @@
 #define TCP_MD5SIG_EXT 32
 #define TCP_FASTOPEN_KEY 33
 #define TCP_FASTOPEN_NO_COOKIE 34
+#define TCP_ZEROCOPY_RECEIVE 35
+#define TCP_INQ 36
+#define TCP_CM_INQ TCP_INQ
+#define TCP_REPAIR_ON 1
+#define TCP_REPAIR_OFF 0
+#define TCP_REPAIR_OFF_NO_WP - 1
 struct tcp_repair_opt {
   __u32 opt_code;
   __u32 opt_val;
@@ -171,6 +177,12 @@
   __u64 tcpi_busy_time;
   __u64 tcpi_rwnd_limited;
   __u64 tcpi_sndbuf_limited;
+  __u32 tcpi_delivered;
+  __u32 tcpi_delivered_ce;
+  __u64 tcpi_bytes_sent;
+  __u64 tcpi_bytes_retrans;
+  __u32 tcpi_dsack_dups;
+  __u32 tcpi_reord_seen;
 };
 enum {
   TCP_NLA_PAD,
@@ -189,6 +201,12 @@
   TCP_NLA_SNDQ_SIZE,
   TCP_NLA_CA_STATE,
   TCP_NLA_SND_SSTHRESH,
+  TCP_NLA_DELIVERED,
+  TCP_NLA_DELIVERED_CE,
+  TCP_NLA_BYTES_SENT,
+  TCP_NLA_BYTES_RETRANS,
+  TCP_NLA_DSACK_DUPS,
+  TCP_NLA_REORD_SEEN,
 };
 #define TCP_MD5SIG_MAXKEYLEN 80
 #define TCP_MD5SIG_FLAG_PREFIX 1
@@ -207,4 +225,9 @@
   __be32 tcpm_addr[4];
   __u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN];
 };
+struct tcp_zerocopy_receive {
+  __u64 address;
+  __u32 length;
+  __u32 recv_skip_hint;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/time.h b/libc/kernel/uapi/linux/time.h
index b75d2dc..96a7042 100644
--- a/libc/kernel/uapi/linux/time.h
+++ b/libc/kernel/uapi/linux/time.h
@@ -45,6 +45,18 @@
   struct timeval it_interval;
   struct timeval it_value;
 };
+#ifndef __kernel_timespec
+struct __kernel_timespec {
+  __kernel_time64_t tv_sec;
+  long long tv_nsec;
+};
+#endif
+#ifndef __kernel_itimerspec
+struct __kernel_itimerspec {
+  struct __kernel_timespec it_interval;
+  struct __kernel_timespec it_value;
+};
+#endif
 struct __kernel_old_timeval {
   __kernel_long_t tv_sec;
   __kernel_long_t tv_usec;
diff --git a/libc/kernel/uapi/linux/tipc.h b/libc/kernel/uapi/linux/tipc.h
index 603c58f..72bcad9 100644
--- a/libc/kernel/uapi/linux/tipc.h
+++ b/libc/kernel/uapi/linux/tipc.h
@@ -119,16 +119,22 @@
   __u32 scope;
   __u32 flags;
 };
+#define TIPC_NODEID_LEN 16
 #define TIPC_MAX_MEDIA_NAME 16
 #define TIPC_MAX_IF_NAME 16
 #define TIPC_MAX_BEARER_NAME 32
 #define TIPC_MAX_LINK_NAME 68
 #define SIOCGETLINKNAME SIOCPROTOPRIVATE
+#define SIOCGETNODEID (SIOCPROTOPRIVATE + 1)
 struct tipc_sioc_ln_req {
   __u32 peer;
   __u32 bearer_id;
   char linkname[TIPC_MAX_LINK_NAME];
 };
+struct tipc_sioc_nodeid_req {
+  __u32 peer;
+  char node_id[TIPC_NODEID_LEN];
+};
 #define TIPC_CFG_SRV 0
 #define TIPC_ZONE_SCOPE 1
 #define TIPC_ADDR_NAMESEQ 1
diff --git a/libc/kernel/uapi/linux/tipc_config.h b/libc/kernel/uapi/linux/tipc_config.h
index c52f5ff..a371e37 100644
--- a/libc/kernel/uapi/linux/tipc_config.h
+++ b/libc/kernel/uapi/linux/tipc_config.h
@@ -90,6 +90,7 @@
 #define TIPC_MIN_LINK_WIN 16
 #define TIPC_DEF_LINK_WIN 50
 #define TIPC_MAX_LINK_WIN 8191
+#define TIPC_DEF_LINK_UDP_MTU 14000
 struct tipc_node_info {
   __be32 addr;
   __be32 up;
diff --git a/libc/kernel/uapi/linux/tipc_netlink.h b/libc/kernel/uapi/linux/tipc_netlink.h
index ce77441..911bbde 100644
--- a/libc/kernel/uapi/linux/tipc_netlink.h
+++ b/libc/kernel/uapi/linux/tipc_netlink.h
@@ -92,6 +92,7 @@
   TIPC_NLA_SOCK_TIPC_STATE,
   TIPC_NLA_SOCK_COOKIE,
   TIPC_NLA_SOCK_PAD,
+  TIPC_NLA_SOCK_GROUP,
   __TIPC_NLA_SOCK_MAX,
   TIPC_NLA_SOCK_MAX = __TIPC_NLA_SOCK_MAX - 1
 };
@@ -177,6 +178,16 @@
   TIPC_NLA_MON_PEER_MAX = __TIPC_NLA_MON_PEER_MAX - 1
 };
 enum {
+  TIPC_NLA_SOCK_GROUP_ID,
+  TIPC_NLA_SOCK_GROUP_OPEN,
+  TIPC_NLA_SOCK_GROUP_NODE_SCOPE,
+  TIPC_NLA_SOCK_GROUP_CLUSTER_SCOPE,
+  TIPC_NLA_SOCK_GROUP_INSTANCE,
+  TIPC_NLA_SOCK_GROUP_BC_SEND_NEXT,
+  __TIPC_NLA_SOCK_GROUP_MAX,
+  TIPC_NLA_SOCK_GROUP_MAX = __TIPC_NLA_SOCK_GROUP_MAX - 1
+};
+enum {
   TIPC_NLA_CON_UNSPEC,
   TIPC_NLA_CON_FLAG,
   TIPC_NLA_CON_NODE,
@@ -200,6 +211,7 @@
   TIPC_NLA_PROP_PRIO,
   TIPC_NLA_PROP_TOL,
   TIPC_NLA_PROP_WIN,
+  TIPC_NLA_PROP_MTU,
   __TIPC_NLA_PROP_MAX,
   TIPC_NLA_PROP_MAX = __TIPC_NLA_PROP_MAX - 1
 };
diff --git a/libc/kernel/uapi/linux/types.h b/libc/kernel/uapi/linux/types.h
index e111573..9145e66 100644
--- a/libc/kernel/uapi/linux/types.h
+++ b/libc/kernel/uapi/linux/types.h
@@ -34,10 +34,6 @@
 #define __aligned_u64 __u64 __attribute__((aligned(8)))
 #define __aligned_be64 __be64 __attribute__((aligned(8)))
 #define __aligned_le64 __le64 __attribute__((aligned(8)))
-#ifdef __CHECK_POLL
 typedef unsigned __bitwise __poll_t;
-#else
-typedef unsigned __poll_t;
-#endif
 #endif
 #endif
diff --git a/libc/kernel/uapi/linux/udp.h b/libc/kernel/uapi/linux/udp.h
index 02e1373..3cd286b 100644
--- a/libc/kernel/uapi/linux/udp.h
+++ b/libc/kernel/uapi/linux/udp.h
@@ -29,9 +29,11 @@
 #define UDP_ENCAP 100
 #define UDP_NO_CHECK6_TX 101
 #define UDP_NO_CHECK6_RX 102
+#define UDP_SEGMENT 103
 #define UDP_ENCAP_ESPINUDP_NON_IKE 1
 #define UDP_ENCAP_ESPINUDP 2
 #define UDP_ENCAP_L2TPINUDP 3
 #define UDP_ENCAP_GTP0 4
 #define UDP_ENCAP_GTP1U 5
+#define UDP_ENCAP_RXRPC 6
 #endif
diff --git a/libc/kernel/uapi/linux/usb/audio.h b/libc/kernel/uapi/linux/usb/audio.h
index 87b8bd5..7d36157 100644
--- a/libc/kernel/uapi/linux/usb/audio.h
+++ b/libc/kernel/uapi/linux/usb/audio.h
@@ -154,6 +154,12 @@
 #define UAC_OUTPUT_TERMINAL_ROOM_SPEAKER 0x305
 #define UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER 0x306
 #define UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER 0x307
+#define UAC_BIDIR_TERMINAL_UNDEFINED 0x400
+#define UAC_BIDIR_TERMINAL_HANDSET 0x401
+#define UAC_BIDIR_TERMINAL_HEADSET 0x402
+#define UAC_BIDIR_TERMINAL_SPEAKER_PHONE 0x403
+#define UAC_BIDIR_TERMINAL_ECHO_SUPPRESSING 0x404
+#define UAC_BIDIR_TERMINAL_ECHO_CANCELING 0x405
 #define UAC_DT_FEATURE_UNIT_SIZE(ch) (7 + ((ch) + 1) * 2)
 #define DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(ch) struct uac_feature_unit_descriptor_ ##ch { __u8 bLength; __u8 bDescriptorType; __u8 bDescriptorSubtype; __u8 bUnitID; __u8 bSourceID; __u8 bControlSize; __le16 bmaControls[ch + 1]; __u8 iFeature; \
 } __attribute__((packed))
diff --git a/libc/kernel/uapi/linux/usb/ch11.h b/libc/kernel/uapi/linux/usb/ch11.h
index e31c37b..55387fe 100644
--- a/libc/kernel/uapi/linux/usb/ch11.h
+++ b/libc/kernel/uapi/linux/usb/ch11.h
@@ -109,6 +109,8 @@
 #define USB_EXT_PORT_STAT_TX_SPEED_ID 0x000000f0
 #define USB_EXT_PORT_STAT_RX_LANES 0x00000f00
 #define USB_EXT_PORT_STAT_TX_LANES 0x0000f000
+#define USB_EXT_PORT_RX_LANES(p) (((p) & USB_EXT_PORT_STAT_RX_LANES) >> 8)
+#define USB_EXT_PORT_TX_LANES(p) (((p) & USB_EXT_PORT_STAT_TX_LANES) >> 12)
 #define HUB_CHAR_LPSM 0x0003
 #define HUB_CHAR_COMMON_LPSM 0x0000
 #define HUB_CHAR_INDV_PORT_LPSM 0x0001
diff --git a/libc/kernel/uapi/linux/usb/g_uvc.h b/libc/kernel/uapi/linux/usb/g_uvc.h
new file mode 100644
index 0000000..0aeba3d
--- /dev/null
+++ b/libc/kernel/uapi/linux/usb/g_uvc.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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 __LINUX_USB_G_UVC_H
+#define __LINUX_USB_G_UVC_H
+#include <linux/ioctl.h>
+#include <linux/types.h>
+#include <linux/usb/ch9.h>
+#define UVC_EVENT_FIRST (V4L2_EVENT_PRIVATE_START + 0)
+#define UVC_EVENT_CONNECT (V4L2_EVENT_PRIVATE_START + 0)
+#define UVC_EVENT_DISCONNECT (V4L2_EVENT_PRIVATE_START + 1)
+#define UVC_EVENT_STREAMON (V4L2_EVENT_PRIVATE_START + 2)
+#define UVC_EVENT_STREAMOFF (V4L2_EVENT_PRIVATE_START + 3)
+#define UVC_EVENT_SETUP (V4L2_EVENT_PRIVATE_START + 4)
+#define UVC_EVENT_DATA (V4L2_EVENT_PRIVATE_START + 5)
+#define UVC_EVENT_LAST (V4L2_EVENT_PRIVATE_START + 5)
+struct uvc_request_data {
+  __s32 length;
+  __u8 data[60];
+};
+struct uvc_event {
+  union {
+    enum usb_device_speed speed;
+    struct usb_ctrlrequest req;
+    struct uvc_request_data data;
+  };
+};
+#define UVCIOC_SEND_RESPONSE _IOW('U', 1, struct uvc_request_data)
+#endif
diff --git a/libc/kernel/uapi/linux/usb/tmc.h b/libc/kernel/uapi/linux/usb/tmc.h
index c93096e..6e276de 100644
--- a/libc/kernel/uapi/linux/usb/tmc.h
+++ b/libc/kernel/uapi/linux/usb/tmc.h
@@ -18,6 +18,7 @@
  ****************************************************************************/
 #ifndef __LINUX_USB_TMC_H
 #define __LINUX_USB_TMC_H
+#include <linux/types.h>
 #define USBTMC_STATUS_SUCCESS 0x01
 #define USBTMC_STATUS_PENDING 0x02
 #define USBTMC_STATUS_FAILED 0x80
@@ -36,6 +37,10 @@
 #define USBTMC488_REQUEST_REN_CONTROL 160
 #define USBTMC488_REQUEST_GOTO_LOCAL 161
 #define USBTMC488_REQUEST_LOCAL_LOCKOUT 162
+struct usbtmc_termchar {
+  __u8 term_char;
+  __u8 term_char_enabled;
+} __attribute__((packed));
 #define USBTMC_IOC_NR 91
 #define USBTMC_IOCTL_INDICATOR_PULSE _IO(USBTMC_IOC_NR, 1)
 #define USBTMC_IOCTL_CLEAR _IO(USBTMC_IOC_NR, 2)
@@ -43,11 +48,16 @@
 #define USBTMC_IOCTL_ABORT_BULK_IN _IO(USBTMC_IOC_NR, 4)
 #define USBTMC_IOCTL_CLEAR_OUT_HALT _IO(USBTMC_IOC_NR, 6)
 #define USBTMC_IOCTL_CLEAR_IN_HALT _IO(USBTMC_IOC_NR, 7)
+#define USBTMC_IOCTL_GET_TIMEOUT _IOR(USBTMC_IOC_NR, 9, __u32)
+#define USBTMC_IOCTL_SET_TIMEOUT _IOW(USBTMC_IOC_NR, 10, __u32)
+#define USBTMC_IOCTL_EOM_ENABLE _IOW(USBTMC_IOC_NR, 11, __u8)
+#define USBTMC_IOCTL_CONFIG_TERMCHAR _IOW(USBTMC_IOC_NR, 12, struct usbtmc_termchar)
 #define USBTMC488_IOCTL_GET_CAPS _IOR(USBTMC_IOC_NR, 17, unsigned char)
 #define USBTMC488_IOCTL_READ_STB _IOR(USBTMC_IOC_NR, 18, unsigned char)
 #define USBTMC488_IOCTL_REN_CONTROL _IOW(USBTMC_IOC_NR, 19, unsigned char)
 #define USBTMC488_IOCTL_GOTO_LOCAL _IO(USBTMC_IOC_NR, 20)
 #define USBTMC488_IOCTL_LOCAL_LOCKOUT _IO(USBTMC_IOC_NR, 21)
+#define USBTMC488_IOCTL_TRIGGER _IO(USBTMC_IOC_NR, 22)
 #define USBTMC488_CAPABILITY_TRIGGER 1
 #define USBTMC488_CAPABILITY_SIMPLE 2
 #define USBTMC488_CAPABILITY_REN_CONTROL 2
diff --git a/libc/kernel/uapi/linux/uvcvideo.h b/libc/kernel/uapi/linux/uvcvideo.h
index 7ae7aad..719147a 100644
--- a/libc/kernel/uapi/linux/uvcvideo.h
+++ b/libc/kernel/uapi/linux/uvcvideo.h
@@ -34,6 +34,7 @@
 #define UVC_CTRL_FLAG_GET_DEF (1 << 5)
 #define UVC_CTRL_FLAG_RESTORE (1 << 6)
 #define UVC_CTRL_FLAG_AUTO_UPDATE (1 << 7)
+#define UVC_CTRL_FLAG_ASYNCHRONOUS (1 << 8)
 #define UVC_CTRL_FLAG_GET_RANGE (UVC_CTRL_FLAG_GET_CUR | UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES | UVC_CTRL_FLAG_GET_DEF)
 struct uvc_menu_info {
   __u32 value;
diff --git a/libc/kernel/uapi/linux/v4l2-controls.h b/libc/kernel/uapi/linux/v4l2-controls.h
index 37e447e..45590a2 100644
--- a/libc/kernel/uapi/linux/v4l2-controls.h
+++ b/libc/kernel/uapi/linux/v4l2-controls.h
@@ -108,7 +108,7 @@
 #define V4L2_CID_USER_ADV7180_BASE (V4L2_CID_USER_BASE + 0x1070)
 #define V4L2_CID_USER_TC358743_BASE (V4L2_CID_USER_BASE + 0x1080)
 #define V4L2_CID_USER_MAX217X_BASE (V4L2_CID_USER_BASE + 0x1090)
-#define V4L2_CID_USER_IMX_BASE (V4L2_CID_USER_BASE + 0x1090)
+#define V4L2_CID_USER_IMX_BASE (V4L2_CID_USER_BASE + 0x10b0)
 #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900)
 #define V4L2_CID_MPEG_CLASS (V4L2_CTRL_CLASS_MPEG | 1)
 #define V4L2_CID_MPEG_STREAM_TYPE (V4L2_CID_MPEG_BASE + 0)
@@ -489,7 +489,21 @@
 #define V4L2_CID_MPEG_VIDEO_VPX_MAX_QP (V4L2_CID_MPEG_BASE + 508)
 #define V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP (V4L2_CID_MPEG_BASE + 509)
 #define V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP (V4L2_CID_MPEG_BASE + 510)
-#define V4L2_CID_MPEG_VIDEO_VPX_PROFILE (V4L2_CID_MPEG_BASE + 511)
+#define V4L2_CID_MPEG_VIDEO_VP8_PROFILE (V4L2_CID_MPEG_BASE + 511)
+enum v4l2_mpeg_video_vp8_profile {
+  V4L2_MPEG_VIDEO_VP8_PROFILE_0 = 0,
+  V4L2_MPEG_VIDEO_VP8_PROFILE_1 = 1,
+  V4L2_MPEG_VIDEO_VP8_PROFILE_2 = 2,
+  V4L2_MPEG_VIDEO_VP8_PROFILE_3 = 3,
+};
+#define V4L2_CID_MPEG_VIDEO_VPX_PROFILE V4L2_CID_MPEG_VIDEO_VP8_PROFILE
+#define V4L2_CID_MPEG_VIDEO_VP9_PROFILE (V4L2_CID_MPEG_BASE + 512)
+enum v4l2_mpeg_video_vp9_profile {
+  V4L2_MPEG_VIDEO_VP9_PROFILE_0 = 0,
+  V4L2_MPEG_VIDEO_VP9_PROFILE_1 = 1,
+  V4L2_MPEG_VIDEO_VP9_PROFILE_2 = 2,
+  V4L2_MPEG_VIDEO_VP9_PROFILE_3 = 3,
+};
 #define V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP (V4L2_CID_MPEG_BASE + 600)
 #define V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP (V4L2_CID_MPEG_BASE + 601)
 #define V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP (V4L2_CID_MPEG_BASE + 602)
diff --git a/libc/kernel/uapi/linux/v4l2-subdev.h b/libc/kernel/uapi/linux/v4l2-subdev.h
index fd1764b..303d167 100644
--- a/libc/kernel/uapi/linux/v4l2-subdev.h
+++ b/libc/kernel/uapi/linux/v4l2-subdev.h
@@ -91,8 +91,12 @@
 #define VIDIOC_SUBDEV_S_CROP _IOWR('V', 60, struct v4l2_subdev_crop)
 #define VIDIOC_SUBDEV_G_SELECTION _IOWR('V', 61, struct v4l2_subdev_selection)
 #define VIDIOC_SUBDEV_S_SELECTION _IOWR('V', 62, struct v4l2_subdev_selection)
+#define VIDIOC_SUBDEV_G_STD _IOR('V', 23, v4l2_std_id)
+#define VIDIOC_SUBDEV_S_STD _IOW('V', 24, v4l2_std_id)
+#define VIDIOC_SUBDEV_ENUMSTD _IOWR('V', 25, struct v4l2_standard)
 #define VIDIOC_SUBDEV_G_EDID _IOWR('V', 40, struct v4l2_edid)
 #define VIDIOC_SUBDEV_S_EDID _IOWR('V', 41, struct v4l2_edid)
+#define VIDIOC_SUBDEV_QUERYSTD _IOR('V', 63, v4l2_std_id)
 #define VIDIOC_SUBDEV_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings)
 #define VIDIOC_SUBDEV_G_DV_TIMINGS _IOWR('V', 88, struct v4l2_dv_timings)
 #define VIDIOC_SUBDEV_ENUM_DV_TIMINGS _IOWR('V', 98, struct v4l2_enum_dv_timings)
diff --git a/libc/kernel/uapi/linux/version.h b/libc/kernel/uapi/linux/version.h
index 61f0c3d..a234744 100644
--- a/libc/kernel/uapi/linux/version.h
+++ b/libc/kernel/uapi/linux/version.h
@@ -16,5 +16,5 @@
  ***
  ****************************************************************************
  ****************************************************************************/
-#define LINUX_VERSION_CODE 266499
+#define LINUX_VERSION_CODE 267008
 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
diff --git a/libc/kernel/uapi/linux/vhost.h b/libc/kernel/uapi/linux/vhost.h
index b6c1f9d..e802e02 100644
--- a/libc/kernel/uapi/linux/vhost.h
+++ b/libc/kernel/uapi/linux/vhost.h
@@ -55,6 +55,7 @@
   __u8 type;
 };
 #define VHOST_IOTLB_MSG 0x1
+#define VHOST_IOTLB_MSG_V2 0x2
 struct vhost_msg {
   int type;
   union {
@@ -62,6 +63,14 @@
     __u8 padding[64];
   };
 };
+struct vhost_msg_v2 {
+  __u32 type;
+  __u32 reserved;
+  union {
+    struct vhost_iotlb_msg iotlb;
+    __u8 padding[64];
+  };
+};
 struct vhost_memory_region {
   __u64 guest_phys_addr;
   __u64 memory_size;
@@ -95,6 +104,9 @@
 #define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
 #define VHOST_SET_VRING_BUSYLOOP_TIMEOUT _IOW(VHOST_VIRTIO, 0x23, struct vhost_vring_state)
 #define VHOST_GET_VRING_BUSYLOOP_TIMEOUT _IOW(VHOST_VIRTIO, 0x24, struct vhost_vring_state)
+#define VHOST_BACKEND_F_IOTLB_MSG_V2 0x1
+#define VHOST_SET_BACKEND_FEATURES _IOW(VHOST_VIRTIO, 0x25, __u64)
+#define VHOST_GET_BACKEND_FEATURES _IOR(VHOST_VIRTIO, 0x26, __u64)
 #define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
 #define VHOST_F_LOG_ALL 26
 #define VHOST_NET_F_VIRTIO_NET_HDR 27
diff --git a/libc/kernel/uapi/linux/videodev2.h b/libc/kernel/uapi/linux/videodev2.h
index 0569ba7..51faa1e 100644
--- a/libc/kernel/uapi/linux/videodev2.h
+++ b/libc/kernel/uapi/linux/videodev2.h
@@ -225,6 +225,7 @@
 #define V4L2_PIX_FMT_Y16 v4l2_fourcc('Y', '1', '6', ' ')
 #define V4L2_PIX_FMT_Y16_BE v4l2_fourcc_be('Y', '1', '6', ' ')
 #define V4L2_PIX_FMT_Y10BPACK v4l2_fourcc('Y', '1', '0', 'B')
+#define V4L2_PIX_FMT_Y10P v4l2_fourcc('Y', '1', '0', 'P')
 #define V4L2_PIX_FMT_PAL8 v4l2_fourcc('P', 'A', 'L', '8')
 #define V4L2_PIX_FMT_UV8 v4l2_fourcc('U', 'V', '8', ' ')
 #define V4L2_PIX_FMT_YUYV v4l2_fourcc('Y', 'U', 'Y', 'V')
@@ -292,6 +293,10 @@
 #define V4L2_PIX_FMT_SGBRG12P v4l2_fourcc('p', 'G', 'C', 'C')
 #define V4L2_PIX_FMT_SGRBG12P v4l2_fourcc('p', 'g', 'C', 'C')
 #define V4L2_PIX_FMT_SRGGB12P v4l2_fourcc('p', 'R', 'C', 'C')
+#define V4L2_PIX_FMT_SBGGR14P v4l2_fourcc('p', 'B', 'E', 'E')
+#define V4L2_PIX_FMT_SGBRG14P v4l2_fourcc('p', 'G', 'E', 'E')
+#define V4L2_PIX_FMT_SGRBG14P v4l2_fourcc('p', 'g', 'E', 'E')
+#define V4L2_PIX_FMT_SRGGB14P v4l2_fourcc('p', 'R', 'E', 'E')
 #define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B', 'Y', 'R', '2')
 #define V4L2_PIX_FMT_SGBRG16 v4l2_fourcc('G', 'B', '1', '6')
 #define V4L2_PIX_FMT_SGRBG16 v4l2_fourcc('G', 'R', '1', '6')
@@ -315,6 +320,7 @@
 #define V4L2_PIX_FMT_VP8 v4l2_fourcc('V', 'P', '8', '0')
 #define V4L2_PIX_FMT_VP9 v4l2_fourcc('V', 'P', '9', '0')
 #define V4L2_PIX_FMT_HEVC v4l2_fourcc('H', 'E', 'V', 'C')
+#define V4L2_PIX_FMT_FWHT v4l2_fourcc('F', 'W', 'H', 'T')
 #define V4L2_PIX_FMT_CPIA1 v4l2_fourcc('C', 'P', 'I', 'A')
 #define V4L2_PIX_FMT_WNVA v4l2_fourcc('W', 'N', 'V', 'A')
 #define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S', '9', '1', '0')
@@ -1271,7 +1277,6 @@
   __u32 reserved[8];
 };
 #define VIDIOC_QUERYCAP _IOR('V', 0, struct v4l2_capability)
-#define VIDIOC_RESERVED _IO('V', 1)
 #define VIDIOC_ENUM_FMT _IOWR('V', 2, struct v4l2_fmtdesc)
 #define VIDIOC_G_FMT _IOWR('V', 4, struct v4l2_format)
 #define VIDIOC_S_FMT _IOWR('V', 5, struct v4l2_format)
diff --git a/libc/kernel/uapi/linux/virtio_config.h b/libc/kernel/uapi/linux/virtio_config.h
index 80a0b1b..ddf5e4e 100644
--- a/libc/kernel/uapi/linux/virtio_config.h
+++ b/libc/kernel/uapi/linux/virtio_config.h
@@ -26,11 +26,12 @@
 #define VIRTIO_CONFIG_S_NEEDS_RESET 0x40
 #define VIRTIO_CONFIG_S_FAILED 0x80
 #define VIRTIO_TRANSPORT_F_START 28
-#define VIRTIO_TRANSPORT_F_END 34
+#define VIRTIO_TRANSPORT_F_END 38
 #ifndef VIRTIO_CONFIG_NO_LEGACY
 #define VIRTIO_F_NOTIFY_ON_EMPTY 24
 #define VIRTIO_F_ANY_LAYOUT 27
 #endif
 #define VIRTIO_F_VERSION_1 32
 #define VIRTIO_F_IOMMU_PLATFORM 33
+#define VIRTIO_F_SR_IOV 37
 #endif
diff --git a/libc/kernel/uapi/linux/virtio_gpu.h b/libc/kernel/uapi/linux/virtio_gpu.h
index b43671f..60dbf71 100644
--- a/libc/kernel/uapi/linux/virtio_gpu.h
+++ b/libc/kernel/uapi/linux/virtio_gpu.h
@@ -185,6 +185,7 @@
   __le32 padding;
 };
 #define VIRTIO_GPU_CAPSET_VIRGL 1
+#define VIRTIO_GPU_CAPSET_VIRGL2 2
 struct virtio_gpu_get_capset_info {
   struct virtio_gpu_ctrl_hdr hdr;
   __le32 capset_index;
diff --git a/libc/kernel/uapi/linux/virtio_net.h b/libc/kernel/uapi/linux/virtio_net.h
index 329d736..07afd06 100644
--- a/libc/kernel/uapi/linux/virtio_net.h
+++ b/libc/kernel/uapi/linux/virtio_net.h
@@ -45,6 +45,7 @@
 #define VIRTIO_NET_F_GUEST_ANNOUNCE 21
 #define VIRTIO_NET_F_MQ 22
 #define VIRTIO_NET_F_CTRL_MAC_ADDR 23
+#define VIRTIO_NET_F_STANDBY 62
 #define VIRTIO_NET_F_SPEED_DUPLEX 63
 #ifndef VIRTIO_NET_NO_LEGACY
 #define VIRTIO_NET_F_GSO 6
diff --git a/libc/kernel/uapi/linux/ncp_no.h b/libc/kernel/uapi/linux/vmcore.h
similarity index 63%
rename from libc/kernel/uapi/linux/ncp_no.h
rename to libc/kernel/uapi/linux/vmcore.h
index fe5caa0..3fa7fee 100644
--- a/libc/kernel/uapi/linux/ncp_no.h
+++ b/libc/kernel/uapi/linux/vmcore.h
@@ -16,19 +16,16 @@
  ***
  ****************************************************************************
  ****************************************************************************/
-#ifndef _NCP_NO
-#define _NCP_NO
-#define aRONLY (__cpu_to_le32(1))
-#define aHIDDEN (__cpu_to_le32(2))
-#define aSYSTEM (__cpu_to_le32(4))
-#define aEXECUTE (__cpu_to_le32(8))
-#define aDIR (__cpu_to_le32(0x10))
-#define aARCH (__cpu_to_le32(0x20))
-#define aSHARED (__cpu_to_le32(0x80))
-#define aDONTSUBALLOCATE (__cpu_to_le32(1L << 11))
-#define aTRANSACTIONAL (__cpu_to_le32(1L << 12))
-#define aPURGE (__cpu_to_le32(1L << 16))
-#define aRENAMEINHIBIT (__cpu_to_le32(1L << 17))
-#define aDELETEINHIBIT (__cpu_to_le32(1L << 18))
-#define aDONTCOMPRESS (__cpu_to_le32(1L << 27))
+#ifndef _UAPI_VMCORE_H
+#define _UAPI_VMCORE_H
+#include <linux/types.h>
+#define VMCOREDD_NOTE_NAME "LINUX"
+#define VMCOREDD_MAX_NAME_BYTES 44
+struct vmcoredd_header {
+  __u32 n_namesz;
+  __u32 n_descsz;
+  __u32 n_type;
+  __u8 name[8];
+  __u8 dump_name[VMCOREDD_MAX_NAME_BYTES];
+};
 #endif
diff --git a/libc/kernel/uapi/linux/vsoc_shm.h b/libc/kernel/uapi/linux/vsoc_shm.h
new file mode 100644
index 0000000..467b89b
--- /dev/null
+++ b/libc/kernel/uapi/linux/vsoc_shm.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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_VSOC_SHM_H
+#define _UAPI_LINUX_VSOC_SHM_H
+#include <linux/types.h>
+struct fd_scoped_permission {
+  __u32 begin_offset;
+  __u32 end_offset;
+  __u32 owner_offset;
+  __u32 owned_value;
+};
+#define VSOC_REGION_FREE ((__u32) 0)
+struct fd_scoped_permission_arg {
+  struct fd_scoped_permission perm;
+  __s32 managed_region_fd;
+};
+#define VSOC_NODE_FREE ((__u32) 0)
+struct vsoc_signal_table_layout {
+  __u32 num_nodes_lg2;
+  __u32 futex_uaddr_table_offset;
+  __u32 interrupt_signalled_offset;
+};
+#define VSOC_REGION_WHOLE ((__s32) 0)
+#define VSOC_DEVICE_NAME_SZ 16
+struct vsoc_device_region {
+  __u16 current_version;
+  __u16 min_compatible_version;
+  __u32 region_begin_offset;
+  __u32 region_end_offset;
+  __u32 offset_of_region_data;
+  struct vsoc_signal_table_layout guest_to_host_signal_table;
+  struct vsoc_signal_table_layout host_to_guest_signal_table;
+  char device_name[VSOC_DEVICE_NAME_SZ];
+  __u32 managed_by;
+};
+struct vsoc_shm_layout_descriptor {
+  __u16 major_version;
+  __u16 minor_version;
+  __u32 size;
+  __u32 region_count;
+  __u32 vsoc_region_desc_offset;
+};
+#define CURRENT_VSOC_LAYOUT_MAJOR_VERSION 2
+#define CURRENT_VSOC_LAYOUT_MINOR_VERSION 0
+#define VSOC_CREATE_FD_SCOPED_PERMISSION _IOW(0xF5, 0, struct fd_scoped_permission)
+#define VSOC_GET_FD_SCOPED_PERMISSION _IOR(0xF5, 1, struct fd_scoped_permission)
+#define VSOC_MAYBE_SEND_INTERRUPT_TO_HOST _IO(0xF5, 2)
+#define VSOC_WAIT_FOR_INCOMING_INTERRUPT _IO(0xF5, 3)
+#define VSOC_DESCRIBE_REGION _IOR(0xF5, 4, struct vsoc_device_region)
+#define VSOC_SELF_INTERRUPT _IO(0xF5, 5)
+#define VSOC_SEND_INTERRUPT_TO_HOST _IO(0xF5, 6)
+enum wait_types {
+  VSOC_WAIT_UNDEFINED = 0,
+  VSOC_WAIT_IF_EQUAL = 1,
+  VSOC_WAIT_IF_EQUAL_TIMEOUT = 2
+};
+struct vsoc_cond_wait {
+  __u32 offset;
+  __u32 value;
+  __u64 wake_time_sec;
+  __u32 wake_time_nsec;
+  __u32 wait_type;
+  __u32 wakes;
+  __u32 reserved_1;
+};
+#define VSOC_COND_WAIT _IOWR(0xF5, 7, struct vsoc_cond_wait)
+#define VSOC_COND_WAKE _IO(0xF5, 8)
+#endif
diff --git a/libc/kernel/uapi/linux/xfrm.h b/libc/kernel/uapi/linux/xfrm.h
index 5ec7193..ea0ef5e 100644
--- a/libc/kernel/uapi/linux/xfrm.h
+++ b/libc/kernel/uapi/linux/xfrm.h
@@ -258,8 +258,11 @@
   XFRMA_ADDRESS_FILTER,
   XFRMA_PAD,
   XFRMA_OFFLOAD_DEV,
-  XFRMA_OUTPUT_MARK,
+  XFRMA_SET_MARK,
+  XFRMA_SET_MARK_MASK,
+  XFRMA_IF_ID,
   __XFRMA_MAX
+#define XFRMA_OUTPUT_MARK XFRMA_SET_MARK
 #define XFRMA_MAX (__XFRMA_MAX - 1)
 };
 struct xfrm_mark {
diff --git a/libc/kernel/uapi/misc/ocxl.h b/libc/kernel/uapi/misc/ocxl.h
index 98d3eac..676aaf8 100644
--- a/libc/kernel/uapi/misc/ocxl.h
+++ b/libc/kernel/uapi/misc/ocxl.h
@@ -50,6 +50,16 @@
   __u64 global_mmio_size;
   __u64 reserved[13];
 };
+struct ocxl_ioctl_p9_wait {
+  __u16 thread_id;
+  __u16 reserved1;
+  __u32 reserved2;
+  __u64 reserved3[3];
+};
+#define OCXL_IOCTL_FEATURES_FLAGS0_P9_WAIT 0x01
+struct ocxl_ioctl_features {
+  __u64 flags[4];
+};
 struct ocxl_ioctl_irq_fd {
   __u64 irq_offset;
   __s32 eventfd;
@@ -61,4 +71,6 @@
 #define OCXL_IOCTL_IRQ_FREE _IOW(OCXL_MAGIC, 0x12, __u64)
 #define OCXL_IOCTL_IRQ_SET_FD _IOW(OCXL_MAGIC, 0x13, struct ocxl_ioctl_irq_fd)
 #define OCXL_IOCTL_GET_METADATA _IOR(OCXL_MAGIC, 0x14, struct ocxl_ioctl_metadata)
+#define OCXL_IOCTL_ENABLE_P9_WAIT _IOR(OCXL_MAGIC, 0x15, struct ocxl_ioctl_p9_wait)
+#define OCXL_IOCTL_GET_FEATURES _IOR(OCXL_MAGIC, 0x16, struct ocxl_ioctl_features)
 #endif
diff --git a/libc/kernel/uapi/mtd/ubi-user.h b/libc/kernel/uapi/mtd/ubi-user.h
index 8f888fe..8405536 100644
--- a/libc/kernel/uapi/mtd/ubi-user.h
+++ b/libc/kernel/uapi/mtd/ubi-user.h
@@ -56,12 +56,16 @@
   __s16 max_beb_per1024;
   __s8 padding[10];
 };
+enum {
+  UBI_VOL_SKIP_CRC_CHECK_FLG = 0x1,
+};
+#define UBI_VOL_VALID_FLGS (UBI_VOL_SKIP_CRC_CHECK_FLG)
 struct ubi_mkvol_req {
   __s32 vol_id;
   __s32 alignment;
   __s64 bytes;
   __s8 vol_type;
-  __s8 padding1;
+  __u8 flags;
   __s16 name_len;
   __s8 padding2[4];
   char name[UBI_MAX_VOLUME_NAME + 1];
diff --git a/libc/kernel/uapi/rdma/cxgb4-abi.h b/libc/kernel/uapi/rdma/cxgb4-abi.h
index 188d901..5433ce6 100644
--- a/libc/kernel/uapi/rdma/cxgb4-abi.h
+++ b/libc/kernel/uapi/rdma/cxgb4-abi.h
@@ -20,6 +20,13 @@
 #define CXGB4_ABI_USER_H
 #include <linux/types.h>
 #define C4IW_UVERBS_ABI_VERSION 3
+enum {
+  C4IW_64B_CQE = (1 << 0)
+};
+struct c4iw_create_cq {
+  __u32 flags;
+  __u32 reserved;
+};
 struct c4iw_create_cq_resp {
   __aligned_u64 key;
   __aligned_u64 gts_key;
@@ -27,10 +34,11 @@
   __u32 cqid;
   __u32 size;
   __u32 qid_mask;
-  __u32 reserved;
+  __u32 flags;
 };
 enum {
-  C4IW_QPF_ONCHIP = (1 << 0)
+  C4IW_QPF_ONCHIP = (1 << 0),
+  C4IW_QPF_WRITE_W_IMM = (1 << 1)
 };
 struct c4iw_create_qp_resp {
   __aligned_u64 ma_sync_key;
@@ -47,6 +55,20 @@
   __u32 qid_mask;
   __u32 flags;
 };
+struct c4iw_create_srq_resp {
+  __aligned_u64 srq_key;
+  __aligned_u64 srq_db_gts_key;
+  __aligned_u64 srq_memsize;
+  __u32 srqid;
+  __u32 srq_size;
+  __u32 rqt_abs_idx;
+  __u32 qid_mask;
+  __u32 flags;
+  __u32 reserved;
+};
+enum {
+  T4_SRQ_LIMIT_SUPPORT = 1 << 0,
+};
 struct c4iw_alloc_ucontext_resp {
   __aligned_u64 status_page_key;
   __u32 status_page_size;
diff --git a/libc/kernel/uapi/rdma/hns-abi.h b/libc/kernel/uapi/rdma/hns-abi.h
index 8c66f27..23bedf9 100644
--- a/libc/kernel/uapi/rdma/hns-abi.h
+++ b/libc/kernel/uapi/rdma/hns-abi.h
@@ -34,6 +34,7 @@
   __u8 log_sq_stride;
   __u8 sq_no_prefetch;
   __u8 reserved[5];
+  __aligned_u64 sdb_addr;
 };
 struct hns_roce_ib_create_qp_resp {
   __aligned_u64 cap_flags;
diff --git a/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h b/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h
index 4bc9786..69ded8e 100644
--- a/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h
+++ b/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h
@@ -38,6 +38,7 @@
   UVERBS_OBJECT_WQ,
   UVERBS_OBJECT_FLOW_ACTION,
   UVERBS_OBJECT_DM,
+  UVERBS_OBJECT_COUNTERS,
 };
 enum {
   UVERBS_ATTR_UHW_IN = UVERBS_UDATA_DRIVER_DATA_FLAG,
@@ -57,13 +58,16 @@
   UVERBS_ATTR_DESTROY_CQ_RESP,
 };
 enum uverbs_attrs_create_flow_action_esp {
-  UVERBS_ATTR_FLOW_ACTION_ESP_HANDLE,
+  UVERBS_ATTR_CREATE_FLOW_ACTION_ESP_HANDLE,
   UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS,
   UVERBS_ATTR_FLOW_ACTION_ESP_ESN,
   UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT,
   UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY,
   UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP,
 };
+enum uverbs_attrs_modify_flow_action_esp {
+  UVERBS_ATTR_MODIFY_FLOW_ACTION_ESP_HANDLE = UVERBS_ATTR_CREATE_FLOW_ACTION_ESP_HANDLE,
+};
 enum uverbs_attrs_destroy_flow_action_esp {
   UVERBS_ATTR_DESTROY_FLOW_ACTION_HANDLE,
 };
@@ -101,4 +105,20 @@
 enum uverbs_methods_mr {
   UVERBS_METHOD_DM_MR_REG,
 };
+enum uverbs_attrs_create_counters_cmd_attr_ids {
+  UVERBS_ATTR_CREATE_COUNTERS_HANDLE,
+};
+enum uverbs_attrs_destroy_counters_cmd_attr_ids {
+  UVERBS_ATTR_DESTROY_COUNTERS_HANDLE,
+};
+enum uverbs_attrs_read_counters_cmd_attr_ids {
+  UVERBS_ATTR_READ_COUNTERS_HANDLE,
+  UVERBS_ATTR_READ_COUNTERS_BUFF,
+  UVERBS_ATTR_READ_COUNTERS_FLAGS,
+};
+enum uverbs_methods_actions_counters_ops {
+  UVERBS_METHOD_COUNTERS_CREATE,
+  UVERBS_METHOD_COUNTERS_DESTROY,
+  UVERBS_METHOD_COUNTERS_READ,
+};
 #endif
diff --git a/libc/kernel/uapi/rdma/ib_user_ioctl_verbs.h b/libc/kernel/uapi/rdma/ib_user_ioctl_verbs.h
index 261734e..8bea1cb 100644
--- a/libc/kernel/uapi/rdma/ib_user_ioctl_verbs.h
+++ b/libc/kernel/uapi/rdma/ib_user_ioctl_verbs.h
@@ -22,6 +22,50 @@
 #ifndef RDMA_UAPI_PTR
 #define RDMA_UAPI_PTR(_type,_name) __aligned_u64 _name
 #endif
+enum ib_uverbs_access_flags {
+  IB_UVERBS_ACCESS_LOCAL_WRITE = 1 << 0,
+  IB_UVERBS_ACCESS_REMOTE_WRITE = 1 << 1,
+  IB_UVERBS_ACCESS_REMOTE_READ = 1 << 2,
+  IB_UVERBS_ACCESS_REMOTE_ATOMIC = 1 << 3,
+  IB_UVERBS_ACCESS_MW_BIND = 1 << 4,
+  IB_UVERBS_ACCESS_ZERO_BASED = 1 << 5,
+  IB_UVERBS_ACCESS_ON_DEMAND = 1 << 6,
+  IB_UVERBS_ACCESS_HUGETLB = 1 << 7,
+};
+enum ib_uverbs_query_port_cap_flags {
+  IB_UVERBS_PCF_SM = 1 << 1,
+  IB_UVERBS_PCF_NOTICE_SUP = 1 << 2,
+  IB_UVERBS_PCF_TRAP_SUP = 1 << 3,
+  IB_UVERBS_PCF_OPT_IPD_SUP = 1 << 4,
+  IB_UVERBS_PCF_AUTO_MIGR_SUP = 1 << 5,
+  IB_UVERBS_PCF_SL_MAP_SUP = 1 << 6,
+  IB_UVERBS_PCF_MKEY_NVRAM = 1 << 7,
+  IB_UVERBS_PCF_PKEY_NVRAM = 1 << 8,
+  IB_UVERBS_PCF_LED_INFO_SUP = 1 << 9,
+  IB_UVERBS_PCF_SM_DISABLED = 1 << 10,
+  IB_UVERBS_PCF_SYS_IMAGE_GUID_SUP = 1 << 11,
+  IB_UVERBS_PCF_PKEY_SW_EXT_PORT_TRAP_SUP = 1 << 12,
+  IB_UVERBS_PCF_EXTENDED_SPEEDS_SUP = 1 << 14,
+  IB_UVERBS_PCF_CM_SUP = 1 << 16,
+  IB_UVERBS_PCF_SNMP_TUNNEL_SUP = 1 << 17,
+  IB_UVERBS_PCF_REINIT_SUP = 1 << 18,
+  IB_UVERBS_PCF_DEVICE_MGMT_SUP = 1 << 19,
+  IB_UVERBS_PCF_VENDOR_CLASS_SUP = 1 << 20,
+  IB_UVERBS_PCF_DR_NOTICE_SUP = 1 << 21,
+  IB_UVERBS_PCF_CAP_MASK_NOTICE_SUP = 1 << 22,
+  IB_UVERBS_PCF_BOOT_MGMT_SUP = 1 << 23,
+  IB_UVERBS_PCF_LINK_LATENCY_SUP = 1 << 24,
+  IB_UVERBS_PCF_CLIENT_REG_SUP = 1 << 25,
+  IB_UVERBS_PCF_LINK_SPEED_WIDTH_TABLE_SUP = 1 << 27,
+  IB_UVERBS_PCF_VENDOR_SPECIFIC_MADS_TABLE_SUP = 1 << 28,
+  IB_UVERBS_PCF_MCAST_PKEY_TRAP_SUPPRESSION_SUP = 1 << 29,
+  IB_UVERBS_PCF_MCAST_FDB_TOP_SUP = 1 << 30,
+  IB_UVERBS_PCF_HIERARCHY_INFO_SUP = 1ULL << 31,
+  IB_UVERBS_PCF_IP_BASED_GIDS = 1 << 26,
+};
+enum ib_uverbs_query_port_flags {
+  IB_UVERBS_QPF_GRH_REQUIRED = 1 << 0,
+};
 enum ib_uverbs_flow_action_esp_keymat {
   IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM,
 };
@@ -65,4 +109,7 @@
   __u32 flags;
   __aligned_u64 hard_limit_pkts;
 };
+enum ib_uverbs_read_counters_flags {
+  IB_UVERBS_READ_COUNTERS_PREFER_CACHED = 1 << 0,
+};
 #endif
diff --git a/libc/kernel/uapi/rdma/ib_user_verbs.h b/libc/kernel/uapi/rdma/ib_user_verbs.h
index 53e4725..3baf4ed 100644
--- a/libc/kernel/uapi/rdma/ib_user_verbs.h
+++ b/libc/kernel/uapi/rdma/ib_user_verbs.h
@@ -228,7 +228,8 @@
   __u8 active_speed;
   __u8 phys_state;
   __u8 link_layer;
-  __u8 reserved[2];
+  __u8 flags;
+  __u8 reserved;
 };
 struct ib_uverbs_alloc_pd {
   __aligned_u64 response;
@@ -828,6 +829,18 @@
   __u32 handle;
   __u32 reserved1;
 };
+struct ib_uverbs_flow_spec_action_count {
+  union {
+    struct ib_uverbs_flow_spec_hdr hdr;
+    struct {
+      __u32 type;
+      __u16 size;
+      __u16 reserved;
+    };
+  };
+  __u32 handle;
+  __u32 reserved1;
+};
 struct ib_uverbs_flow_tunnel_filter {
   __be32 tunnel_id;
 };
@@ -859,6 +872,38 @@
   struct ib_uverbs_flow_spec_esp_filter val;
   struct ib_uverbs_flow_spec_esp_filter mask;
 };
+struct ib_uverbs_flow_gre_filter {
+  __be16 c_ks_res0_ver;
+  __be16 protocol;
+  __be32 key;
+};
+struct ib_uverbs_flow_spec_gre {
+  union {
+    struct ib_uverbs_flow_spec_hdr hdr;
+    struct {
+      __u32 type;
+      __u16 size;
+      __u16 reserved;
+    };
+  };
+  struct ib_uverbs_flow_gre_filter val;
+  struct ib_uverbs_flow_gre_filter mask;
+};
+struct ib_uverbs_flow_mpls_filter {
+  __be32 label;
+};
+struct ib_uverbs_flow_spec_mpls {
+  union {
+    struct ib_uverbs_flow_spec_hdr hdr;
+    struct {
+      __u32 type;
+      __u16 size;
+      __u16 reserved;
+    };
+  };
+  struct ib_uverbs_flow_mpls_filter val;
+  struct ib_uverbs_flow_mpls_filter mask;
+};
 struct ib_uverbs_flow_attr {
   __u32 type;
   __u16 size;
diff --git a/libc/kernel/uapi/rdma/mlx5-abi.h b/libc/kernel/uapi/rdma/mlx5-abi.h
index 170c0a6..50ecd2f 100644
--- a/libc/kernel/uapi/rdma/mlx5-abi.h
+++ b/libc/kernel/uapi/rdma/mlx5-abi.h
@@ -20,6 +20,7 @@
 #define MLX5_ABI_USER_H
 #include <linux/types.h>
 #include <linux/if_ether.h>
+#include <rdma/ib_user_ioctl_verbs.h>
 enum {
   MLX5_QP_FLAG_SIGNATURE = 1 << 0,
   MLX5_QP_FLAG_SCATTER_CQE = 1 << 1,
@@ -42,6 +43,9 @@
 enum mlx5_lib_caps {
   MLX5_LIB_CAP_4K_UAR = (__u64) 1 << 0,
 };
+enum mlx5_ib_alloc_uctx_v2_flags {
+  MLX5_IB_ALLOC_UCTX_DEVX = 1 << 0,
+};
 struct mlx5_ib_alloc_ucontext_req_v2 {
   __u32 total_num_bfregs;
   __u32 num_low_latency_bfregs;
@@ -55,6 +59,7 @@
 };
 enum mlx5_ib_alloc_ucontext_resp_mask {
   MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_CORE_CLOCK_OFFSET = 1UL << 0,
+  MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_DUMP_FILL_MKEY = 1UL << 1,
 };
 enum mlx5_user_cmds_supp_uhw {
   MLX5_USER_CMDS_SUPP_UHW_QUERY_DEVICE = 1 << 0,
@@ -96,7 +101,7 @@
   __u32 log_uar_size;
   __u32 num_uars_per_page;
   __u32 num_dyn_bfregs;
-  __u32 reserved3;
+  __u32 dump_fill_mkey;
 };
 struct mlx5_ib_alloc_pd_resp {
   __u32 pdn;
@@ -113,7 +118,7 @@
 enum mlx5_ib_cqe_comp_res_format {
   MLX5_IB_CQE_RES_FORMAT_HASH = 1 << 0,
   MLX5_IB_CQE_RES_FORMAT_CSUM = 1 << 1,
-  MLX5_IB_CQE_RES_RESERVED = 1 << 2,
+  MLX5_IB_CQE_RES_FORMAT_CSUM_STRIDX = 1 << 2,
 };
 struct mlx5_ib_cqe_comp_caps {
   __u32 max_num;
@@ -158,7 +163,9 @@
 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
+  MLX5_IB_TUNNELED_OFFLOADS_GENEVE = 1 << 2,
+  MLX5_IB_TUNNELED_OFFLOADS_MPLS_GRE = 1 << 3,
+  MLX5_IB_TUNNELED_OFFLOADS_MPLS_UDP = 1 << 4,
 };
 struct mlx5_ib_query_device_resp {
   __u32 comp_mask;
@@ -328,4 +335,18 @@
 enum {
   MLX5_IB_CLOCK_INFO_V1 = 0,
 };
+struct mlx5_ib_flow_counters_desc {
+  __u32 description;
+  __u32 index;
+};
+struct mlx5_ib_flow_counters_data {
+  RDMA_UAPI_PTR(struct mlx5_ib_flow_counters_desc *, counters_data);
+  __u32 ncounters;
+  __u32 reserved;
+};
+struct mlx5_ib_create_flow {
+  __u32 ncounters_data;
+  __u32 reserved;
+  struct mlx5_ib_flow_counters_data data[];
+};
 #endif
diff --git a/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h b/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h
index 37aebaf..11ff576 100644
--- a/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h
+++ b/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h
@@ -18,6 +18,7 @@
  ****************************************************************************/
 #ifndef MLX5_USER_IOCTL_CMDS_H
 #define MLX5_USER_IOCTL_CMDS_H
+#include <linux/types.h>
 #include <rdma/ib_user_ioctl_cmds.h>
 enum mlx5_ib_create_flow_action_attrs {
   MLX5_IB_ATTR_CREATE_FLOW_ACTION_FLAGS = (1U << UVERBS_ID_NS_SHIFT),
@@ -26,4 +27,102 @@
   MLX5_IB_ATTR_ALLOC_DM_RESP_START_OFFSET = (1U << UVERBS_ID_NS_SHIFT),
   MLX5_IB_ATTR_ALLOC_DM_RESP_PAGE_INDEX,
 };
+enum mlx5_ib_devx_methods {
+  MLX5_IB_METHOD_DEVX_OTHER = (1U << UVERBS_ID_NS_SHIFT),
+  MLX5_IB_METHOD_DEVX_QUERY_UAR,
+  MLX5_IB_METHOD_DEVX_QUERY_EQN,
+};
+enum mlx5_ib_devx_other_attrs {
+  MLX5_IB_ATTR_DEVX_OTHER_CMD_IN = (1U << UVERBS_ID_NS_SHIFT),
+  MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT,
+};
+enum mlx5_ib_devx_obj_create_attrs {
+  MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+  MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN,
+  MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT,
+};
+enum mlx5_ib_devx_query_uar_attrs {
+  MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX = (1U << UVERBS_ID_NS_SHIFT),
+  MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX,
+};
+enum mlx5_ib_devx_obj_destroy_attrs {
+  MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+};
+enum mlx5_ib_devx_obj_modify_attrs {
+  MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+  MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN,
+  MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
+};
+enum mlx5_ib_devx_obj_query_attrs {
+  MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+  MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN,
+  MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
+};
+enum mlx5_ib_devx_query_eqn_attrs {
+  MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC = (1U << UVERBS_ID_NS_SHIFT),
+  MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN,
+};
+enum mlx5_ib_devx_obj_methods {
+  MLX5_IB_METHOD_DEVX_OBJ_CREATE = (1U << UVERBS_ID_NS_SHIFT),
+  MLX5_IB_METHOD_DEVX_OBJ_DESTROY,
+  MLX5_IB_METHOD_DEVX_OBJ_MODIFY,
+  MLX5_IB_METHOD_DEVX_OBJ_QUERY,
+};
+enum mlx5_ib_devx_umem_reg_attrs {
+  MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+  MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR,
+  MLX5_IB_ATTR_DEVX_UMEM_REG_LEN,
+  MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
+  MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID,
+};
+enum mlx5_ib_devx_umem_dereg_attrs {
+  MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+};
+enum mlx5_ib_devx_umem_methods {
+  MLX5_IB_METHOD_DEVX_UMEM_REG = (1U << UVERBS_ID_NS_SHIFT),
+  MLX5_IB_METHOD_DEVX_UMEM_DEREG,
+};
+enum mlx5_ib_objects {
+  MLX5_IB_OBJECT_DEVX = (1U << UVERBS_ID_NS_SHIFT),
+  MLX5_IB_OBJECT_DEVX_OBJ,
+  MLX5_IB_OBJECT_DEVX_UMEM,
+  MLX5_IB_OBJECT_FLOW_MATCHER,
+};
+enum mlx5_ib_flow_matcher_create_attrs {
+  MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+  MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK,
+  MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE,
+  MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA,
+};
+enum mlx5_ib_flow_matcher_destroy_attrs {
+  MLX5_IB_ATTR_FLOW_MATCHER_DESTROY_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+};
+enum mlx5_ib_flow_matcher_methods {
+  MLX5_IB_METHOD_FLOW_MATCHER_CREATE = (1U << UVERBS_ID_NS_SHIFT),
+  MLX5_IB_METHOD_FLOW_MATCHER_DESTROY,
+};
+#define MLX5_IB_DW_MATCH_PARAM 0x80
+struct mlx5_ib_match_params {
+  __u32 match_params[MLX5_IB_DW_MATCH_PARAM];
+};
+enum mlx5_ib_flow_type {
+  MLX5_IB_FLOW_TYPE_NORMAL,
+  MLX5_IB_FLOW_TYPE_SNIFFER,
+  MLX5_IB_FLOW_TYPE_ALL_DEFAULT,
+  MLX5_IB_FLOW_TYPE_MC_DEFAULT,
+};
+enum mlx5_ib_create_flow_attrs {
+  MLX5_IB_ATTR_CREATE_FLOW_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+  MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE,
+  MLX5_IB_ATTR_CREATE_FLOW_DEST_QP,
+  MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX,
+  MLX5_IB_ATTR_CREATE_FLOW_MATCHER,
+};
+enum mlx5_ib_destoy_flow_attrs {
+  MLX5_IB_ATTR_DESTROY_FLOW_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+};
+enum mlx5_ib_flow_methods {
+  MLX5_IB_METHOD_CREATE_FLOW = (1U << UVERBS_ID_NS_SHIFT),
+  MLX5_IB_METHOD_DESTROY_FLOW,
+};
 #endif
diff --git a/libc/kernel/uapi/rdma/qedr-abi.h b/libc/kernel/uapi/rdma/qedr-abi.h
index 8626f8c..57ad827 100644
--- a/libc/kernel/uapi/rdma/qedr-abi.h
+++ b/libc/kernel/uapi/rdma/qedr-abi.h
@@ -69,4 +69,14 @@
   __u32 rq_db2_offset;
   __u32 reserved;
 };
+struct qedr_create_srq_ureq {
+  __aligned_u64 prod_pair_addr;
+  __aligned_u64 srq_addr;
+  __aligned_u64 srq_len;
+};
+struct qedr_create_srq_uresp {
+  __u16 srq_id;
+  __u16 reserved0;
+  __u32 reserved1;
+};
 #endif
diff --git a/libc/kernel/uapi/rdma/rdma_netlink.h b/libc/kernel/uapi/rdma/rdma_netlink.h
index 36c8911..48cbc3d 100644
--- a/libc/kernel/uapi/rdma/rdma_netlink.h
+++ b/libc/kernel/uapi/rdma/rdma_netlink.h
@@ -182,8 +182,16 @@
   RDMA_NLDEV_CMD_RES_PD_GET,
   RDMA_NLDEV_NUM_OPS
 };
+enum {
+  RDMA_NLDEV_ATTR_ENTRY_STRLEN = 16,
+};
+enum rdma_nldev_print_type {
+  RDMA_NLDEV_PRINT_TYPE_UNSPEC,
+  RDMA_NLDEV_PRINT_TYPE_HEX,
+};
 enum rdma_nldev_attr {
   RDMA_NLDEV_ATTR_UNSPEC,
+  RDMA_NLDEV_ATTR_PAD = RDMA_NLDEV_ATTR_UNSPEC,
   RDMA_NLDEV_ATTR_DEV_INDEX,
   RDMA_NLDEV_ATTR_DEV_NAME,
   RDMA_NLDEV_ATTR_PORT_INDEX,
@@ -235,6 +243,14 @@
   RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY,
   RDMA_NLDEV_ATTR_NDEV_INDEX,
   RDMA_NLDEV_ATTR_NDEV_NAME,
+  RDMA_NLDEV_ATTR_DRIVER,
+  RDMA_NLDEV_ATTR_DRIVER_ENTRY,
+  RDMA_NLDEV_ATTR_DRIVER_STRING,
+  RDMA_NLDEV_ATTR_DRIVER_PRINT_TYPE,
+  RDMA_NLDEV_ATTR_DRIVER_S32,
+  RDMA_NLDEV_ATTR_DRIVER_U32,
+  RDMA_NLDEV_ATTR_DRIVER_S64,
+  RDMA_NLDEV_ATTR_DRIVER_U64,
   RDMA_NLDEV_ATTR_MAX
 };
 #endif
diff --git a/libc/kernel/uapi/rdma/rdma_user_ioctl_cmds.h b/libc/kernel/uapi/rdma/rdma_user_ioctl_cmds.h
index 5da7917..7cd6cd0 100644
--- a/libc/kernel/uapi/rdma/rdma_user_ioctl_cmds.h
+++ b/libc/kernel/uapi/rdma/rdma_user_ioctl_cmds.h
@@ -37,7 +37,10 @@
     } enum_data;
     __u16 reserved;
   } attr_data;
-  __aligned_u64 data;
+  union {
+    __aligned_u64 data;
+    __s64 data_s64;
+  };
 };
 struct ib_uverbs_ioctl_hdr {
   __u16 length;
diff --git a/libc/kernel/uapi/sound/asoc.h b/libc/kernel/uapi/sound/asoc.h
index d0bab8b..e46c4b5 100644
--- a/libc/kernel/uapi/sound/asoc.h
+++ b/libc/kernel/uapi/sound/asoc.h
@@ -95,6 +95,11 @@
 #define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES (1 << 0)
 #define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS (1 << 1)
 #define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2)
+#define SND_SOC_TPLG_DAI_CLK_GATE_UNDEFINED 0
+#define SND_SOC_TPLG_DAI_CLK_GATE_GATED 1
+#define SND_SOC_TPLG_DAI_CLK_GATE_CONT 2
+#define SND_SOC_TPLG_MCLK_CO 0
+#define SND_SOC_TPLG_MCLK_CI 1
 #define SND_SOC_DAI_FORMAT_I2S 1
 #define SND_SOC_DAI_FORMAT_RIGHT_J 2
 #define SND_SOC_DAI_FORMAT_LEFT_J 3
@@ -108,6 +113,10 @@
 #define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS (1 << 1)
 #define SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2)
 #define SND_SOC_TPLG_LNK_FLGBIT_VOICE_WAKEUP (1 << 3)
+#define SND_SOC_TPLG_BCLK_CM 0
+#define SND_SOC_TPLG_BCLK_CS 1
+#define SND_SOC_TPLG_FSYNC_CM 0
+#define SND_SOC_TPLG_FSYNC_CS 1
 struct snd_soc_tplg_hdr {
   __le32 magic;
   __le32 abi;
@@ -335,4 +344,48 @@
   __le32 flags;
   struct snd_soc_tplg_private priv;
 } __attribute__((packed));
+struct snd_soc_tplg_manifest_v4 {
+  __le32 size;
+  __le32 control_elems;
+  __le32 widget_elems;
+  __le32 graph_elems;
+  __le32 pcm_elems;
+  __le32 dai_link_elems;
+  struct snd_soc_tplg_private priv;
+} __packed;
+struct snd_soc_tplg_stream_caps_v4 {
+  __le32 size;
+  char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+  __le64 formats;
+  __le32 rates;
+  __le32 rate_min;
+  __le32 rate_max;
+  __le32 channels_min;
+  __le32 channels_max;
+  __le32 periods_min;
+  __le32 periods_max;
+  __le32 period_size_min;
+  __le32 period_size_max;
+  __le32 buffer_size_min;
+  __le32 buffer_size_max;
+} __packed;
+struct snd_soc_tplg_pcm_v4 {
+  __le32 size;
+  char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+  char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+  __le32 pcm_id;
+  __le32 dai_id;
+  __le32 playback;
+  __le32 capture;
+  __le32 compress;
+  struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX];
+  __le32 num_streams;
+  struct snd_soc_tplg_stream_caps_v4 caps[2];
+} __packed;
+struct snd_soc_tplg_link_config_v4 {
+  __le32 size;
+  __le32 id;
+  struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX];
+  __le32 num_streams;
+} __packed;
 #endif
diff --git a/libc/kernel/uapi/sound/skl-tplg-interface.h b/libc/kernel/uapi/sound/skl-tplg-interface.h
new file mode 100644
index 0000000..58e0afa
--- /dev/null
+++ b/libc/kernel/uapi/sound/skl-tplg-interface.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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 __HDA_TPLG_INTERFACE_H__
+#define __HDA_TPLG_INTERFACE_H__
+#include <linux/types.h>
+#define SKL_CONTROL_TYPE_BYTE_TLV 0x100
+#define SKL_CONTROL_TYPE_MIC_SELECT 0x102
+#define HDA_SST_CFG_MAX 900
+#define MAX_IN_QUEUE 8
+#define MAX_OUT_QUEUE 8
+#define SKL_UUID_STR_SZ 40
+enum skl_event_types {
+  SKL_EVENT_NONE = 0,
+  SKL_MIXER_EVENT,
+  SKL_MUX_EVENT,
+  SKL_VMIXER_EVENT,
+  SKL_PGA_EVENT
+};
+enum skl_ch_cfg {
+  SKL_CH_CFG_MONO = 0,
+  SKL_CH_CFG_STEREO = 1,
+  SKL_CH_CFG_2_1 = 2,
+  SKL_CH_CFG_3_0 = 3,
+  SKL_CH_CFG_3_1 = 4,
+  SKL_CH_CFG_QUATRO = 5,
+  SKL_CH_CFG_4_0 = 6,
+  SKL_CH_CFG_5_0 = 7,
+  SKL_CH_CFG_5_1 = 8,
+  SKL_CH_CFG_DUAL_MONO = 9,
+  SKL_CH_CFG_I2S_DUAL_STEREO_0 = 10,
+  SKL_CH_CFG_I2S_DUAL_STEREO_1 = 11,
+  SKL_CH_CFG_4_CHANNEL = 12,
+  SKL_CH_CFG_INVALID
+};
+enum skl_module_type {
+  SKL_MODULE_TYPE_MIXER = 0,
+  SKL_MODULE_TYPE_COPIER,
+  SKL_MODULE_TYPE_UPDWMIX,
+  SKL_MODULE_TYPE_SRCINT,
+  SKL_MODULE_TYPE_ALGO,
+  SKL_MODULE_TYPE_BASE_OUTFMT,
+  SKL_MODULE_TYPE_KPB,
+  SKL_MODULE_TYPE_MIC_SELECT,
+};
+enum skl_core_affinity {
+  SKL_AFFINITY_CORE_0 = 0,
+  SKL_AFFINITY_CORE_1,
+  SKL_AFFINITY_CORE_MAX
+};
+enum skl_pipe_conn_type {
+  SKL_PIPE_CONN_TYPE_NONE = 0,
+  SKL_PIPE_CONN_TYPE_FE,
+  SKL_PIPE_CONN_TYPE_BE
+};
+enum skl_hw_conn_type {
+  SKL_CONN_NONE = 0,
+  SKL_CONN_SOURCE = 1,
+  SKL_CONN_SINK = 2
+};
+enum skl_dev_type {
+  SKL_DEVICE_BT = 0x0,
+  SKL_DEVICE_DMIC = 0x1,
+  SKL_DEVICE_I2S = 0x2,
+  SKL_DEVICE_SLIMBUS = 0x3,
+  SKL_DEVICE_HDALINK = 0x4,
+  SKL_DEVICE_HDAHOST = 0x5,
+  SKL_DEVICE_NONE
+};
+enum skl_interleaving {
+  SKL_INTERLEAVING_PER_CHANNEL = 0,
+  SKL_INTERLEAVING_PER_SAMPLE = 1,
+};
+enum skl_sample_type {
+  SKL_SAMPLE_TYPE_INT_MSB = 0,
+  SKL_SAMPLE_TYPE_INT_LSB = 1,
+  SKL_SAMPLE_TYPE_INT_SIGNED = 2,
+  SKL_SAMPLE_TYPE_INT_UNSIGNED = 3,
+  SKL_SAMPLE_TYPE_FLOAT = 4
+};
+enum module_pin_type {
+  SKL_PIN_TYPE_HOMOGENEOUS,
+  SKL_PIN_TYPE_HETEROGENEOUS,
+};
+enum skl_module_param_type {
+  SKL_PARAM_DEFAULT = 0,
+  SKL_PARAM_INIT,
+  SKL_PARAM_SET,
+  SKL_PARAM_BIND
+};
+struct skl_dfw_algo_data {
+  __u32 set_params : 2;
+  __u32 rsvd : 30;
+  __u32 param_id;
+  __u32 max;
+  char params[0];
+} __packed;
+enum skl_tkn_dir {
+  SKL_DIR_IN,
+  SKL_DIR_OUT
+};
+enum skl_tuple_type {
+  SKL_TYPE_TUPLE,
+  SKL_TYPE_DATA
+};
+struct skl_dfw_v4_module_pin {
+  __u16 module_id;
+  __u16 instance_id;
+} __packed;
+struct skl_dfw_v4_module_fmt {
+  __u32 channels;
+  __u32 freq;
+  __u32 bit_depth;
+  __u32 valid_bit_depth;
+  __u32 ch_cfg;
+  __u32 interleaving_style;
+  __u32 sample_type;
+  __u32 ch_map;
+} __packed;
+struct skl_dfw_v4_module_caps {
+  __u32 set_params : 2;
+  __u32 rsvd : 30;
+  __u32 param_id;
+  __u32 caps_size;
+  __u32 caps[HDA_SST_CFG_MAX];
+} __packed;
+struct skl_dfw_v4_pipe {
+  __u8 pipe_id;
+  __u8 pipe_priority;
+  __u16 conn_type : 4;
+  __u16 rsvd : 4;
+  __u16 memory_pages : 8;
+} __packed;
+struct skl_dfw_v4_module {
+  char uuid[SKL_UUID_STR_SZ];
+  __u16 module_id;
+  __u16 instance_id;
+  __u32 max_mcps;
+  __u32 mem_pages;
+  __u32 obs;
+  __u32 ibs;
+  __u32 vbus_id;
+  __u32 max_in_queue : 8;
+  __u32 max_out_queue : 8;
+  __u32 time_slot : 8;
+  __u32 core_id : 4;
+  __u32 rsvd1 : 4;
+  __u32 module_type : 8;
+  __u32 conn_type : 4;
+  __u32 dev_type : 4;
+  __u32 hw_conn_type : 4;
+  __u32 rsvd2 : 12;
+  __u32 params_fixup : 8;
+  __u32 converter : 8;
+  __u32 input_pin_type : 1;
+  __u32 output_pin_type : 1;
+  __u32 is_dynamic_in_pin : 1;
+  __u32 is_dynamic_out_pin : 1;
+  __u32 is_loadable : 1;
+  __u32 rsvd3 : 11;
+  struct skl_dfw_v4_pipe pipe;
+  struct skl_dfw_v4_module_fmt in_fmt[MAX_IN_QUEUE];
+  struct skl_dfw_v4_module_fmt out_fmt[MAX_OUT_QUEUE];
+  struct skl_dfw_v4_module_pin in_pin[MAX_IN_QUEUE];
+  struct skl_dfw_v4_module_pin out_pin[MAX_OUT_QUEUE];
+  struct skl_dfw_v4_module_caps caps;
+} __packed;
+#endif
diff --git a/libc/kernel/uapi/sound/tlv.h b/libc/kernel/uapi/sound/tlv.h
index 9a5c521..0822429 100644
--- a/libc/kernel/uapi/sound/tlv.h
+++ b/libc/kernel/uapi/sound/tlv.h
@@ -29,18 +29,26 @@
 #define SNDRV_CTL_TLVT_CHMAP_PAIRED 0x103
 #define SNDRV_CTL_TLVD_ITEM(type,...) (type), SNDRV_CTL_TLVD_LENGTH(__VA_ARGS__), __VA_ARGS__
 #define SNDRV_CTL_TLVD_LENGTH(...) ((unsigned int) sizeof((const unsigned int[]) { __VA_ARGS__ }))
+#define SNDRV_CTL_TLVO_TYPE 0
+#define SNDRV_CTL_TLVO_LEN 1
 #define SNDRV_CTL_TLVD_CONTAINER_ITEM(...) SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_CONTAINER, __VA_ARGS__)
 #define SNDRV_CTL_TLVD_DECLARE_CONTAINER(name,...) unsigned int name[] = { SNDRV_CTL_TLVD_CONTAINER_ITEM(__VA_ARGS__) }
 #define SNDRV_CTL_TLVD_DB_SCALE_MASK 0xffff
 #define SNDRV_CTL_TLVD_DB_SCALE_MUTE 0x10000
 #define SNDRV_CTL_TLVD_DB_SCALE_ITEM(min,step,mute) SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_SCALE, (min), ((step) & SNDRV_CTL_TLVD_DB_SCALE_MASK) | ((mute) ? SNDRV_CTL_TLVD_DB_SCALE_MUTE : 0))
 #define SNDRV_CTL_TLVD_DECLARE_DB_SCALE(name,min,step,mute) unsigned int name[] = { SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) }
+#define SNDRV_CTL_TLVO_DB_SCALE_MIN 2
+#define SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP 3
 #define SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB,max_dB) SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX, (min_dB), (max_dB))
 #define SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB,max_dB) SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX_MUTE, (min_dB), (max_dB))
 #define SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(name,min_dB,max_dB) unsigned int name[] = { SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) }
 #define SNDRV_CTL_TLVD_DECLARE_DB_MINMAX_MUTE(name,min_dB,max_dB) unsigned int name[] = { SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) }
+#define SNDRV_CTL_TLVO_DB_MINMAX_MIN 2
+#define SNDRV_CTL_TLVO_DB_MINMAX_MAX 3
 #define SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB,max_dB) SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_LINEAR, (min_dB), (max_dB))
 #define SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(name,min_dB,max_dB) unsigned int name[] = { SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) }
+#define SNDRV_CTL_TLVO_DB_LINEAR_MIN 2
+#define SNDRV_CTL_TLVO_DB_LINEAR_MAX 3
 #define SNDRV_CTL_TLVD_DB_RANGE_ITEM(...) SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_RANGE, __VA_ARGS__)
 #define SNDRV_CTL_TLVD_DECLARE_DB_RANGE(name,...) unsigned int name[] = { SNDRV_CTL_TLVD_DB_RANGE_ITEM(__VA_ARGS__) }
 #define SNDRV_CTL_TLVD_DB_GAIN_MUTE - 9999999
diff --git a/libc/kernel/uapi/xen/gntdev.h b/libc/kernel/uapi/xen/gntdev.h
index 44b5e8c..1e78ac3 100644
--- a/libc/kernel/uapi/xen/gntdev.h
+++ b/libc/kernel/uapi/xen/gntdev.h
@@ -73,4 +73,32 @@
 };
 #define UNMAP_NOTIFY_CLEAR_BYTE 0x1
 #define UNMAP_NOTIFY_SEND_EVENT 0x2
+#define GNTDEV_DMA_FLAG_WC (1 << 0)
+#define GNTDEV_DMA_FLAG_COHERENT (1 << 1)
+#define IOCTL_GNTDEV_DMABUF_EXP_FROM_REFS _IOC(_IOC_NONE, 'G', 9, sizeof(struct ioctl_gntdev_dmabuf_exp_from_refs))
+struct ioctl_gntdev_dmabuf_exp_from_refs {
+  __u32 flags;
+  __u32 count;
+  __u32 fd;
+  __u32 domid;
+  __u32 refs[1];
+};
+#define IOCTL_GNTDEV_DMABUF_EXP_WAIT_RELEASED _IOC(_IOC_NONE, 'G', 10, sizeof(struct ioctl_gntdev_dmabuf_exp_wait_released))
+struct ioctl_gntdev_dmabuf_exp_wait_released {
+  __u32 fd;
+  __u32 wait_to_ms;
+};
+#define IOCTL_GNTDEV_DMABUF_IMP_TO_REFS _IOC(_IOC_NONE, 'G', 11, sizeof(struct ioctl_gntdev_dmabuf_imp_to_refs))
+struct ioctl_gntdev_dmabuf_imp_to_refs {
+  __u32 fd;
+  __u32 count;
+  __u32 domid;
+  __u32 reserved;
+  __u32 refs[1];
+};
+#define IOCTL_GNTDEV_DMABUF_IMP_RELEASE _IOC(_IOC_NONE, 'G', 12, sizeof(struct ioctl_gntdev_dmabuf_imp_release))
+struct ioctl_gntdev_dmabuf_imp_release {
+  __u32 fd;
+  __u32 reserved;
+};
 #endif
diff --git a/libc/kernel/uapi/xen/privcmd.h b/libc/kernel/uapi/xen/privcmd.h
index 210a75e..145446b 100644
--- a/libc/kernel/uapi/xen/privcmd.h
+++ b/libc/kernel/uapi/xen/privcmd.h
@@ -59,10 +59,19 @@
   __u16 num;
   const struct privcmd_dm_op_buf __user * ubufs;
 };
+struct privcmd_mmap_resource {
+  domid_t dom;
+  __u32 type;
+  __u32 id;
+  __u32 idx;
+  __u64 num;
+  __u64 addr;
+};
 #define IOCTL_PRIVCMD_HYPERCALL _IOC(_IOC_NONE, 'P', 0, sizeof(struct privcmd_hypercall))
 #define IOCTL_PRIVCMD_MMAP _IOC(_IOC_NONE, 'P', 2, sizeof(struct privcmd_mmap))
 #define IOCTL_PRIVCMD_MMAPBATCH _IOC(_IOC_NONE, 'P', 3, sizeof(struct privcmd_mmapbatch))
 #define IOCTL_PRIVCMD_MMAPBATCH_V2 _IOC(_IOC_NONE, 'P', 4, sizeof(struct privcmd_mmapbatch_v2))
 #define IOCTL_PRIVCMD_DM_OP _IOC(_IOC_NONE, 'P', 5, sizeof(struct privcmd_dm_op))
 #define IOCTL_PRIVCMD_RESTRICT _IOC(_IOC_NONE, 'P', 6, sizeof(domid_t))
+#define IOCTL_PRIVCMD_MMAP_RESOURCE _IOC(_IOC_NONE, 'P', 7, sizeof(struct privcmd_mmap_resource))
 #endif
diff --git a/libc/malloc_debug/Android.bp b/libc/malloc_debug/Android.bp
index 01f42b7..0961a94 100644
--- a/libc/malloc_debug/Android.bp
+++ b/libc/malloc_debug/Android.bp
@@ -63,11 +63,6 @@
         },
     },
 
-    // Clang lld link flags do not work with special link rules
-    // for libunwind_llvm yet. Linked aosp_arm-eng image failed to
-    // boot up in the emulator. http://b/78118944.
-    use_clang_lld: false,
-
     static_libs: [
         "libasync_safe",
         "libbase",
diff --git a/libc/malloc_debug/DebugData.h b/libc/malloc_debug/DebugData.h
index f7cf8ab..3a36299 100644
--- a/libc/malloc_debug/DebugData.h
+++ b/libc/malloc_debug/DebugData.h
@@ -94,7 +94,7 @@
 
   Config config_;
 
-  DISALLOW_COPY_AND_ASSIGN(DebugData);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(DebugData);
 };
 
 extern DebugData* g_debug;
diff --git a/libc/malloc_debug/GuardData.h b/libc/malloc_debug/GuardData.h
index 7b21671..b6ec889 100644
--- a/libc/malloc_debug/GuardData.h
+++ b/libc/malloc_debug/GuardData.h
@@ -56,7 +56,7 @@
 
   virtual const char* GetTypeName() = 0;
 
-  DISALLOW_COPY_AND_ASSIGN(GuardData);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(GuardData);
 };
 
 class FrontGuardData : public GuardData {
@@ -75,7 +75,7 @@
 
   size_t offset_ = 0;
 
-  DISALLOW_COPY_AND_ASSIGN(FrontGuardData);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(FrontGuardData);
 };
 
 class RearGuardData : public GuardData {
@@ -90,5 +90,5 @@
  private:
   const char* GetTypeName() override { return "REAR"; }
 
-  DISALLOW_COPY_AND_ASSIGN(RearGuardData);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(RearGuardData);
 };
diff --git a/libc/malloc_debug/MapData.h b/libc/malloc_debug/MapData.h
index d8398bd..b9b697c 100644
--- a/libc/malloc_debug/MapData.h
+++ b/libc/malloc_debug/MapData.h
@@ -68,5 +68,5 @@
   std::mutex m_;
   std::set<MapEntry*, compare_entries> entries_;
 
-  DISALLOW_COPY_AND_ASSIGN(MapData);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(MapData);
 };
diff --git a/libc/malloc_debug/OptionData.h b/libc/malloc_debug/OptionData.h
index 3fa8e14..8fb13a4 100644
--- a/libc/malloc_debug/OptionData.h
+++ b/libc/malloc_debug/OptionData.h
@@ -39,5 +39,5 @@
  protected:
   DebugData* debug_;
 
-  DISALLOW_COPY_AND_ASSIGN(OptionData);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(OptionData);
 };
diff --git a/libc/malloc_debug/PointerData.h b/libc/malloc_debug/PointerData.h
index 62d4186..b05a763 100644
--- a/libc/malloc_debug/PointerData.h
+++ b/libc/malloc_debug/PointerData.h
@@ -184,5 +184,5 @@
   static std::mutex free_pointer_mutex_;
   static std::deque<FreePointerInfoType> free_pointers_;
 
-  DISALLOW_COPY_AND_ASSIGN(PointerData);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(PointerData);
 };
diff --git a/libc/malloc_debug/RecordData.h b/libc/malloc_debug/RecordData.h
index 3e5ca02..a015882 100644
--- a/libc/malloc_debug/RecordData.h
+++ b/libc/malloc_debug/RecordData.h
@@ -49,7 +49,7 @@
   pid_t tid_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(RecordEntry);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(RecordEntry);
 };
 
 class ThreadCompleteEntry : public RecordEntry {
@@ -60,7 +60,7 @@
   std::string GetString() const override;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ThreadCompleteEntry);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(ThreadCompleteEntry);
 };
 
 class AllocEntry : public RecordEntry {
@@ -72,7 +72,7 @@
   void* pointer_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(AllocEntry);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(AllocEntry);
 };
 
 class MallocEntry : public AllocEntry {
@@ -86,7 +86,7 @@
   size_t size_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(MallocEntry);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(MallocEntry);
 };
 
 class FreeEntry : public AllocEntry {
@@ -97,7 +97,7 @@
   std::string GetString() const override;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(FreeEntry);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(FreeEntry);
 };
 
 class CallocEntry : public MallocEntry {
@@ -111,7 +111,7 @@
   size_t nmemb_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(CallocEntry);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(CallocEntry);
 };
 
 class ReallocEntry : public MallocEntry {
@@ -125,7 +125,7 @@
   void* old_pointer_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ReallocEntry);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(ReallocEntry);
 };
 
 // aligned_alloc, posix_memalign, memalign, pvalloc, valloc all recorded with this class.
@@ -140,7 +140,7 @@
   size_t alignment_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(MemalignEntry);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(MemalignEntry);
 };
 
 class Config;
@@ -170,5 +170,5 @@
   std::atomic_bool dump_;
   std::string dump_file_;
 
-  DISALLOW_COPY_AND_ASSIGN(RecordData);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(RecordData);
 };
diff --git a/libc/malloc_debug/debug_disable.h b/libc/malloc_debug/debug_disable.h
index 0049595..f9c3149 100644
--- a/libc/malloc_debug/debug_disable.h
+++ b/libc/malloc_debug/debug_disable.h
@@ -57,5 +57,5 @@
  private:
   bool disabled_;
 
-  DISALLOW_COPY_AND_ASSIGN(ScopedDisableDebugCalls);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(ScopedDisableDebugCalls);
 };
diff --git a/libc/private/ErrnoRestorer.h b/libc/private/ErrnoRestorer.h
index f467393..52e115a 100644
--- a/libc/private/ErrnoRestorer.h
+++ b/libc/private/ErrnoRestorer.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ERRNO_RESTORER_H
-#define ERRNO_RESTORER_H
+#pragma once
 
 #include <errno.h>
 
@@ -37,7 +36,5 @@
  private:
   int saved_errno_;
 
-  DISALLOW_COPY_AND_ASSIGN(ErrnoRestorer);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(ErrnoRestorer);
 };
-
-#endif // ERRNO_RESTORER_H
diff --git a/libc/private/KernelArgumentBlock.h b/libc/private/KernelArgumentBlock.h
index e05ceb9..886dd32 100644
--- a/libc/private/KernelArgumentBlock.h
+++ b/libc/private/KernelArgumentBlock.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef KERNEL_ARGUMENT_BLOCK_H
-#define KERNEL_ARGUMENT_BLOCK_H
+#pragma once
 
 #include <elf.h>
 #include <link.h>
@@ -71,7 +70,5 @@
   libc_shared_globals* shared_globals;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(KernelArgumentBlock);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(KernelArgumentBlock);
 };
-
-#endif // KERNEL_ARGUMENT_BLOCK_H
diff --git a/libc/private/ScopedPthreadMutexLocker.h b/libc/private/ScopedPthreadMutexLocker.h
index 58462e3..1c1e4a7 100644
--- a/libc/private/ScopedPthreadMutexLocker.h
+++ b/libc/private/ScopedPthreadMutexLocker.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef SCOPED_PTHREAD_MUTEX_LOCKER_H
-#define SCOPED_PTHREAD_MUTEX_LOCKER_H
+#pragma once
 
 #include <pthread.h>
 
@@ -34,7 +33,5 @@
  private:
   pthread_mutex_t* mu_;
 
-  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedPthreadMutexLocker);
+  BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedPthreadMutexLocker);
 };
-
-#endif // SCOPED_PTHREAD_MUTEX_LOCKER_H
diff --git a/libc/private/ScopedReaddir.h b/libc/private/ScopedReaddir.h
index 1a59e1a..dc22309 100644
--- a/libc/private/ScopedReaddir.h
+++ b/libc/private/ScopedReaddir.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef SCOPED_READDIR_H
-#define SCOPED_READDIR_H
+#pragma once
 
 #include <dirent.h>
 
@@ -47,7 +46,5 @@
  private:
   DIR* dir_;
 
-  DISALLOW_COPY_AND_ASSIGN(ScopedReaddir);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(ScopedReaddir);
 };
-
-#endif // SCOPED_READDIR_H
diff --git a/libc/private/ScopedSignalBlocker.h b/libc/private/ScopedSignalBlocker.h
index d1cf629..10aacb3 100644
--- a/libc/private/ScopedSignalBlocker.h
+++ b/libc/private/ScopedSignalBlocker.h
@@ -46,5 +46,5 @@
 
   sigset64_t old_set_;
 
-  DISALLOW_COPY_AND_ASSIGN(ScopedSignalBlocker);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(ScopedSignalBlocker);
 };
diff --git a/libc/private/WriteProtected.h b/libc/private/WriteProtected.h
index 7a6b098..69a6822 100644
--- a/libc/private/WriteProtected.h
+++ b/libc/private/WriteProtected.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef _PRIVATE_WRITEPROTECTED_H
-#define _PRIVATE_WRITEPROTECTED_H
+#pragma once
 
 #include <errno.h>
 #include <string.h>
@@ -33,7 +32,7 @@
   char padding[PAGE_SIZE];
 
   WriteProtectedContents() = default;
-  DISALLOW_COPY_AND_ASSIGN(WriteProtectedContents);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(WriteProtectedContents);
 } __attribute__((aligned(PAGE_SIZE)));
 
 // Write protected wrapper class that aligns its contents to a page boundary,
@@ -49,7 +48,7 @@
 
  public:
   WriteProtected() = default;
-  DISALLOW_COPY_AND_ASSIGN(WriteProtected);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(WriteProtected);
 
   void initialize() {
     // Not strictly necessary, but this will hopefully segfault if we initialize
@@ -82,5 +81,3 @@
     }
   }
 };
-
-#endif
diff --git a/libc/private/bionic_constants.h b/libc/private/bionic_constants.h
index 9ae1c8d..e64c826 100644
--- a/libc/private/bionic_constants.h
+++ b/libc/private/bionic_constants.h
@@ -19,4 +19,14 @@
 
 #define NS_PER_S 1000000000
 
+// Size of the shadow call stack. This must be a power of 2.
+#define SCS_SIZE (8 * 1024)
+
+// The shadow call stack is allocated at an aligned address within a guard region of this size. The
+// guard region must be large enough that we can allocate an SCS_SIZE-aligned SCS while ensuring
+// that there is at least one guard page after the SCS so that a stack overflow results in a SIGSEGV
+// instead of corrupting the allocation that comes after it.
+// TODO(b/118642754): Use a larger guard region.
+#define SCS_GUARD_REGION_SIZE (SCS_SIZE * 2)
+
 #endif // _BIONIC_CONSTANTS_H_
diff --git a/libc/private/bionic_lock.h b/libc/private/bionic_lock.h
index 54168d3..eebfeff 100644
--- a/libc/private/bionic_lock.h
+++ b/libc/private/bionic_lock.h
@@ -25,8 +25,8 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#ifndef _BIONIC_LOCK_H
-#define _BIONIC_LOCK_H
+
+#pragma once
 
 #include <stdatomic.h>
 #include "private/bionic_futex.h"
@@ -85,10 +85,8 @@
     lock_.unlock();
   }
 
-  DISALLOW_COPY_AND_ASSIGN(LockGuard);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(LockGuard);
 
  private:
   Lock& lock_;
 };
-
-#endif  // _BIONIC_LOCK_H
diff --git a/libc/private/bionic_macros.h b/libc/private/bionic_macros.h
index 0a36cdb..4800e3a 100644
--- a/libc/private/bionic_macros.h
+++ b/libc/private/bionic_macros.h
@@ -14,31 +14,17 @@
  * limitations under the License.
  */
 
-#ifndef _BIONIC_MACROS_H_
-#define _BIONIC_MACROS_H_
+#pragma once
 
 #include <stdint.h>
 
-// Frameworks OpenGL code currently leaks this header and allows
-// collisions with other declarations, e.g., from libnativehelper.
-// TODO: Remove once cleaned up. b/18334516
-#if !defined(DISALLOW_COPY_AND_ASSIGN)
-// DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions.
-// It goes in the private: declarations in a class.
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
-  TypeName(const TypeName&) = delete;      \
+#define BIONIC_DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&) = delete;             \
   void operator=(const TypeName&) = delete
-#endif  // !defined(DISALLOW_COPY_AND_ASSIGN)
 
-// A macro to disallow all the implicit constructors, namely the
-// default constructor, copy constructor and operator= functions.
-//
-// This should be used in the private: declarations for a class
-// that wants to prevent anyone from instantiating it. This is
-// especially useful for classes containing only static methods.
-#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
-  TypeName() = delete;                           \
-  DISALLOW_COPY_AND_ASSIGN(TypeName)
+#define BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+  TypeName() = delete;                                  \
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(TypeName)
 
 #define BIONIC_ROUND_UP_POWER_OF_2(value) \
   ((sizeof(value) == 8) \
@@ -101,5 +87,3 @@
 #else
 #define __BIONIC_FALLTHROUGH
 #endif
-
-#endif // _BIONIC_MACROS_H_
diff --git a/libc/private/bionic_sdk_version.h b/libc/private/bionic_sdk_version.h
deleted file mode 100644
index 871d25c..0000000
--- a/libc/private/bionic_sdk_version.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2016 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_SDK_VERSION_H_
-#define _BIONIC_SDK_VERSION_H_
-
-#include <stdint.h>
-
-uint32_t bionic_get_application_target_sdk_version();
-
-#endif  // _BIONIC_SDK_VERSION_H_
diff --git a/libc/private/bionic_systrace.h b/libc/private/bionic_systrace.h
index 304fb80..86d2a08 100644
--- a/libc/private/bionic_systrace.h
+++ b/libc/private/bionic_systrace.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef BIONIC_SYSTRACE_H
-#define BIONIC_SYSTRACE_H
+#pragma once
 
 #include "bionic_macros.h"
 
@@ -31,10 +30,8 @@
   void End();
  private:
   bool called_end_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedTrace);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(ScopedTrace);
 };
 
 void bionic_trace_begin(const char* message);
 void bionic_trace_end();
-
-#endif
diff --git a/libc/system_properties/include/system_properties/context_node.h b/libc/system_properties/include/system_properties/context_node.h
index 35d0e92..20f4013 100644
--- a/libc/system_properties/include/system_properties/context_node.h
+++ b/libc/system_properties/include/system_properties/context_node.h
@@ -42,7 +42,7 @@
     Unmap();
   }
 
-  DISALLOW_COPY_AND_ASSIGN(ContextNode);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(ContextNode);
 
   bool Open(bool access_rw, bool* fsetxattr_failed);
   bool CheckAccessAndOpen();
diff --git a/libc/system_properties/include/system_properties/prop_area.h b/libc/system_properties/include/system_properties/prop_area.h
index 2c25337..a69f90e 100644
--- a/libc/system_properties/include/system_properties/prop_area.h
+++ b/libc/system_properties/include/system_properties/prop_area.h
@@ -86,7 +86,7 @@
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(prop_bt);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(prop_bt);
 };
 
 class prop_area {
@@ -158,5 +158,5 @@
   uint32_t reserved_[28];
   char data_[0];
 
-  DISALLOW_COPY_AND_ASSIGN(prop_area);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(prop_area);
 };
diff --git a/libc/system_properties/include/system_properties/prop_info.h b/libc/system_properties/include/system_properties/prop_info.h
index a127550..27b29c8 100644
--- a/libc/system_properties/include/system_properties/prop_info.h
+++ b/libc/system_properties/include/system_properties/prop_info.h
@@ -83,7 +83,7 @@
   prop_info(const char* name, uint32_t namelen, uint32_t long_offset);
 
  private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(prop_info);
+  BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(prop_info);
 };
 
 static_assert(sizeof(prop_info) == 96, "sizeof struct prop_info must be 96 bytes");
diff --git a/libc/system_properties/include/system_properties/system_properties.h b/libc/system_properties/include/system_properties/system_properties.h
index 52ffcaf..cad29cc 100644
--- a/libc/system_properties/include/system_properties/system_properties.h
+++ b/libc/system_properties/include/system_properties/system_properties.h
@@ -52,7 +52,7 @@
   explicit SystemProperties(bool initialized) : initialized_(initialized) {
   }
 
-  DISALLOW_COPY_AND_ASSIGN(SystemProperties);
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(SystemProperties);
 
   bool Init(const char* filename);
   bool AreaInit(const char* filename, bool* fsetxattr_failed);
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index 01c580f..d78a5e7 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -489,6 +489,14 @@
         if arch_list == "all":
             for arch in all_arches:
                 t[arch] = True
+        elif arch_list == "lp32":
+            for arch in all_arches:
+                if "64" not in arch:
+                    t[arch] = True
+        elif arch_list == "lp64":
+            for arch in all_arches:
+                if "64" in arch:
+                    t[arch] = True
         else:
             for arch in string.split(arch_list, ','):
                 if arch in all_arches:
diff --git a/libc/tzcode/bionic.cpp b/libc/tzcode/bionic.cpp
index 9b59183..51fd39a 100644
--- a/libc/tzcode/bionic.cpp
+++ b/libc/tzcode/bionic.cpp
@@ -200,11 +200,15 @@
   int fd;
 
 #if defined(__ANDROID__)
-  // On Android, try the two hard-coded locations.
+  // On Android, try the three hard-coded locations.
   fd = __bionic_open_tzdata_path("/data/misc/zoneinfo/current/tzdata",
                                  olson_id, entry_length);
   if (fd >= 0) return fd;
 
+  fd = __bionic_open_tzdata_path("/apex/com.android.tzdata/etc/tzdata",
+                                 olson_id, entry_length);
+  if (fd >= 0) return fd;
+
   fd = __bionic_open_tzdata_path("/system/usr/share/zoneinfo/tzdata",
                                  olson_id, entry_length);
   if (fd >= 0) return fd;
diff --git a/libdl/libdl.arm.map b/libdl/libdl.arm.map
index 1fcfc58..28f0601 100644
--- a/libdl/libdl.arm.map
+++ b/libdl/libdl.arm.map
@@ -31,6 +31,7 @@
 
 LIBC_N {
   global:
+    android_get_application_target_sdk_version; # introduced=24 versioned=29
     dlvsym; # introduced=24
 } LIBC;
 
@@ -45,7 +46,6 @@
   global:
     __cfi_init;
     android_dlwarning;
-    android_get_application_target_sdk_version;
     android_set_application_target_sdk_version;
     android_get_LD_LIBRARY_PATH;
     android_update_LD_LIBRARY_PATH;
diff --git a/libdl/libdl.arm64.map b/libdl/libdl.arm64.map
index 8d4019c..a03e9e1 100644
--- a/libdl/libdl.arm64.map
+++ b/libdl/libdl.arm64.map
@@ -30,6 +30,7 @@
 
 LIBC_N {
   global:
+    android_get_application_target_sdk_version; # introduced=24 versioned=29
     dlvsym; # introduced=24
 } LIBC;
 
@@ -44,7 +45,6 @@
   global:
     __cfi_init;
     android_dlwarning;
-    android_get_application_target_sdk_version;
     android_set_application_target_sdk_version;
     android_get_LD_LIBRARY_PATH;
     android_update_LD_LIBRARY_PATH;
diff --git a/libdl/libdl.cpp b/libdl/libdl.cpp
index 402804e..a468f81 100644
--- a/libdl/libdl.cpp
+++ b/libdl/libdl.cpp
@@ -67,10 +67,10 @@
                                   const void* caller_addr);
 
 __attribute__((__weak__, visibility("default")))
-void __loader_android_set_application_target_sdk_version(uint32_t target);
+void __loader_android_set_application_target_sdk_version(int target);
 
 __attribute__((__weak__, visibility("default")))
-uint32_t __loader_android_get_application_target_sdk_version();
+int __loader_android_get_application_target_sdk_version();
 
 __attribute__((__weak__, visibility("default")))
 bool __loader_android_init_anonymous_namespace(const char* shared_libs_sonames,
@@ -165,12 +165,12 @@
 }
 
 __attribute__((__weak__))
-void android_set_application_target_sdk_version(uint32_t target) {
+void android_set_application_target_sdk_version(int target) {
   __loader_android_set_application_target_sdk_version(target);
 }
 
 __attribute__((__weak__))
-uint32_t android_get_application_target_sdk_version() {
+int android_get_application_target_sdk_version() {
   return __loader_android_get_application_target_sdk_version();
 }
 
diff --git a/libdl/libdl.map.txt b/libdl/libdl.map.txt
index 002e9f8..c5d1be4 100644
--- a/libdl/libdl.map.txt
+++ b/libdl/libdl.map.txt
@@ -30,6 +30,7 @@
 
 LIBC_N {
   global:
+    android_get_application_target_sdk_version; # introduced=24 versioned=29
     dlvsym; # introduced=24
 } LIBC;
 
@@ -44,7 +45,6 @@
   global:
     __cfi_init;
     android_dlwarning;
-    android_get_application_target_sdk_version;
     android_set_application_target_sdk_version;
     android_get_LD_LIBRARY_PATH;
     android_update_LD_LIBRARY_PATH;
diff --git a/libdl/libdl.mips.map b/libdl/libdl.mips.map
index 8d4019c..a03e9e1 100644
--- a/libdl/libdl.mips.map
+++ b/libdl/libdl.mips.map
@@ -30,6 +30,7 @@
 
 LIBC_N {
   global:
+    android_get_application_target_sdk_version; # introduced=24 versioned=29
     dlvsym; # introduced=24
 } LIBC;
 
@@ -44,7 +45,6 @@
   global:
     __cfi_init;
     android_dlwarning;
-    android_get_application_target_sdk_version;
     android_set_application_target_sdk_version;
     android_get_LD_LIBRARY_PATH;
     android_update_LD_LIBRARY_PATH;
diff --git a/libdl/libdl.mips64.map b/libdl/libdl.mips64.map
index 8d4019c..a03e9e1 100644
--- a/libdl/libdl.mips64.map
+++ b/libdl/libdl.mips64.map
@@ -30,6 +30,7 @@
 
 LIBC_N {
   global:
+    android_get_application_target_sdk_version; # introduced=24 versioned=29
     dlvsym; # introduced=24
 } LIBC;
 
@@ -44,7 +45,6 @@
   global:
     __cfi_init;
     android_dlwarning;
-    android_get_application_target_sdk_version;
     android_set_application_target_sdk_version;
     android_get_LD_LIBRARY_PATH;
     android_update_LD_LIBRARY_PATH;
diff --git a/libdl/libdl.x86.map b/libdl/libdl.x86.map
index 8d4019c..a03e9e1 100644
--- a/libdl/libdl.x86.map
+++ b/libdl/libdl.x86.map
@@ -30,6 +30,7 @@
 
 LIBC_N {
   global:
+    android_get_application_target_sdk_version; # introduced=24 versioned=29
     dlvsym; # introduced=24
 } LIBC;
 
@@ -44,7 +45,6 @@
   global:
     __cfi_init;
     android_dlwarning;
-    android_get_application_target_sdk_version;
     android_set_application_target_sdk_version;
     android_get_LD_LIBRARY_PATH;
     android_update_LD_LIBRARY_PATH;
diff --git a/libdl/libdl.x86_64.map b/libdl/libdl.x86_64.map
index 8d4019c..a03e9e1 100644
--- a/libdl/libdl.x86_64.map
+++ b/libdl/libdl.x86_64.map
@@ -30,6 +30,7 @@
 
 LIBC_N {
   global:
+    android_get_application_target_sdk_version; # introduced=24 versioned=29
     dlvsym; # introduced=24
 } LIBC;
 
@@ -44,7 +45,6 @@
   global:
     __cfi_init;
     android_dlwarning;
-    android_get_application_target_sdk_version;
     android_set_application_target_sdk_version;
     android_get_LD_LIBRARY_PATH;
     android_update_LD_LIBRARY_PATH;
diff --git a/libm/Android.bp b/libm/Android.bp
index 6d55967..e4ba20d 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -514,6 +514,9 @@
         integer_overflow: false,
     },
     stl: "none",
+
+    // TODO(ivanlozano): Remove after b/118321713
+    xom: false,
 }
 
 ndk_library {
diff --git a/linker/Android.bp b/linker/Android.bp
index 697c260..a9907ca 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -15,7 +15,7 @@
     // We need to access Bionic private headers in the linker.
     include_dirs: ["bionic/libc"],
 
-    static_libs: ["libasync_safe"],
+    static_libs: ["libasync_safe", "libbase"],
 }
 
 // This is used for bionic on (host) Linux to bootstrap our linker embedded into
@@ -167,10 +167,6 @@
         "-Wl,-soname,ld-android.so",
     ],
 
-    // lld bug: https://bugs.llvm.org/show_bug.cgi?id=36295
-    // error: symbol __aeabi_*@@LIBC_N has undefined version LIBC_N
-    use_clang_lld: false,
-
     cflags: [
         "-fno-stack-protector",
         "-Wstrict-overflow=5",
@@ -293,6 +289,7 @@
         },
     },
     compile_multilib: "both",
+    xom: false,
 }
 
 cc_library {
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index dfe8e8c..45ae6ed 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -57,7 +57,7 @@
                            const android_dlextinfo* extinfo,
                            const void* caller_addr) __LINKER_PUBLIC__;
 void __loader_android_dlwarning(void* obj, void (*f)(void*, const char*)) __LINKER_PUBLIC__;
-uint32_t __loader_android_get_application_target_sdk_version() __LINKER_PUBLIC__;
+int __loader_android_get_application_target_sdk_version() __LINKER_PUBLIC__;
 void __loader_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) __LINKER_PUBLIC__;
 android_namespace_t* __loader_android_get_exported_namespace(const char* name) __LINKER_PUBLIC__;
 bool __loader_android_init_anonymous_namespace(const char* shared_libs_sonames,
@@ -67,7 +67,7 @@
                                       const char* shared_libs_sonames) __LINKER_PUBLIC__;
 bool __loader_android_link_namespaces_all_libs(android_namespace_t* namespace_from,
                                                android_namespace_t* namespace_to) __LINKER_PUBLIC__;
-void __loader_android_set_application_target_sdk_version(uint32_t target) __LINKER_PUBLIC__;
+void __loader_android_set_application_target_sdk_version(int target) __LINKER_PUBLIC__;
 void __loader_android_update_LD_LIBRARY_PATH(const char* ld_library_path) __LINKER_PUBLIC__;
 void __loader_cfi_fail(uint64_t CallSiteTypeId,
                        void* Ptr,
@@ -204,13 +204,13 @@
 }
 #endif
 
-void __loader_android_set_application_target_sdk_version(uint32_t target) {
+void __loader_android_set_application_target_sdk_version(int target) {
   // lock to avoid modification in the middle of dlopen.
   ScopedPthreadMutexLocker locker(&g_dl_mutex);
   set_application_target_sdk_version(target);
 }
 
-uint32_t __loader_android_get_application_target_sdk_version() {
+int __loader_android_get_application_target_sdk_version() {
   return get_application_target_sdk_version();
 }
 
diff --git a/linker/linked_list.h b/linker/linked_list.h
index 7f70a2c..5473ca0 100644
--- a/linker/linked_list.h
+++ b/linker/linked_list.h
@@ -28,7 +28,7 @@
 
 #pragma once
 
-#include "private/bionic_macros.h"
+#include <android-base/macros.h>
 
 template<typename T>
 struct LinkedListEntry {
diff --git a/linker/linker.cpp b/linker/linker.cpp
index f085863..7993681 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1086,6 +1086,7 @@
     fd = open_library_on_paths(zip_archive_cache, name, file_offset, needed_by->get_dt_runpath(), realpath);
     // Check if the library is accessible
     if (fd != -1 && !ns->is_accessible(*realpath)) {
+      close(fd);
       fd = -1;
     }
   }
@@ -2073,13 +2074,6 @@
       return nullptr;
     }
 
-    if ((extinfo->flags & ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS) != 0 &&
-        (extinfo->flags & (ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_HINT)) != 0) {
-      DL_ERR("invalid extended flag combination: ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS is not "
-             "compatible with ANDROID_DLEXT_RESERVED_ADDRESS/ANDROID_DLEXT_RESERVED_ADDRESS_HINT");
-      return nullptr;
-    }
-
     if ((extinfo->flags & ANDROID_DLEXT_USE_NAMESPACE) != 0) {
       if (extinfo->library_namespace == nullptr) {
         DL_ERR("ANDROID_DLEXT_USE_NAMESPACE is set but extinfo->library_namespace is null");
@@ -3711,6 +3705,15 @@
   return namespaces;
 }
 
+// return /apex/<name>/etc/ld.config.txt from /apex/<name>/bin/<exec>
+static std::string get_ld_config_file_apex_path(const char* executable_path) {
+  std::vector<std::string> paths = android::base::Split(executable_path, "/");
+  if (paths.size() == 5 && paths[1] == "apex" && paths[3] == "bin") {
+    return std::string("/apex/") + paths[2] + "/etc/ld.config.txt";
+  }
+  return "";
+}
+
 static std::string get_ld_config_file_vndk_path() {
   if (android::base::GetBoolProperty("ro.vndk.lite", false)) {
     return kLdConfigVndkLiteFilePath;
@@ -3725,7 +3728,7 @@
   return ld_config_file_vndk;
 }
 
-static std::string get_ld_config_file_path() {
+static std::string get_ld_config_file_path(const char* executable_path) {
 #ifdef USE_LD_CONFIG_FILE
   // This is a debugging/testing only feature. Must not be available on
   // production builds.
@@ -3735,13 +3738,23 @@
   }
 #endif
 
-  if (file_exists(kLdConfigArchFilePath)) {
-    return kLdConfigArchFilePath;
+  std::string path = get_ld_config_file_apex_path(executable_path);
+  if (!path.empty()) {
+    if (file_exists(path.c_str())) {
+      return path;
+    }
+    DL_WARN("Warning: couldn't read config file \"%s\" for \"%s\"",
+            path.c_str(), executable_path);
   }
 
-  std::string ld_config_file_vndk = get_ld_config_file_vndk_path();
-  if (file_exists(ld_config_file_vndk.c_str())) {
-    return ld_config_file_vndk;
+  path = kLdConfigArchFilePath;
+  if (file_exists(path.c_str())) {
+    return path;
+  }
+
+  path = get_ld_config_file_vndk_path();
+  if (file_exists(path.c_str())) {
+    return path;
   }
 
   return kLdConfigFilePath;
@@ -3764,7 +3777,7 @@
 
   std::string error_msg;
 
-  std::string ld_config_file_path = get_ld_config_file_path();
+  std::string ld_config_file_path = get_ld_config_file_path(executable_path);
 
   if (!Config::read_binary_config(ld_config_file_path.c_str(),
                                   executable_path,
diff --git a/linker/linker.h b/linker/linker.h
index dd45f67..91d3ddf 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -131,8 +131,8 @@
 // void ___cfi_slowpath_diag(uint64_t CallSiteTypeId, void *Ptr, void *DiagData, void *Ret);
 void ___cfi_fail(uint64_t CallSiteTypeId, void* Ptr, void *DiagData, void *Ret);
 
-void set_application_target_sdk_version(uint32_t target);
-uint32_t get_application_target_sdk_version();
+void set_application_target_sdk_version(int target);
+int get_application_target_sdk_version();
 
 enum {
   /* A regular namespace is the namespace with a custom search path that does
diff --git a/linker/linker_block_allocator.h b/linker/linker_block_allocator.h
index b501659..bd44fc8 100644
--- a/linker/linker_block_allocator.h
+++ b/linker/linker_block_allocator.h
@@ -30,7 +30,8 @@
 
 #include <stdlib.h>
 #include <limits.h>
-#include "private/bionic_macros.h"
+
+#include <android-base/macros.h>
 
 struct LinkerBlockAllocatorPage;
 
diff --git a/linker/linker_common_types.h b/linker/linker_common_types.h
index ffa4066..ae78aa9 100644
--- a/linker/linker_common_types.h
+++ b/linker/linker_common_types.h
@@ -31,6 +31,8 @@
 #include <android/dlext.h>
 #include "linked_list.h"
 
+#include <android-base/macros.h>
+
 // TODO(dimitry): move this to linker_defines.h? Unless it is removed by
 // consequent refactoring steps.
 
diff --git a/linker/linker_config.h b/linker/linker_config.h
index e117aea..49739ee 100644
--- a/linker/linker_config.h
+++ b/linker/linker_config.h
@@ -32,13 +32,14 @@
 
 #include <stdlib.h>
 #include <limits.h>
-#include "private/bionic_macros.h"
 
 #include <memory>
 #include <string>
 #include <vector>
 #include <unordered_map>
 
+#include <android-base/macros.h>
+
 class NamespaceLinkConfig {
  public:
   NamespaceLinkConfig() = default;
@@ -139,7 +140,7 @@
     return it == namespace_configs_map_.end() ? nullptr : it->second;
   }
 
-  uint32_t target_sdk_version() const {
+  int target_sdk_version() const {
     return target_sdk_version_;
   }
 
@@ -158,7 +159,7 @@
  private:
   void clear();
 
-  void set_target_sdk_version(uint32_t target_sdk_version) {
+  void set_target_sdk_version(int target_sdk_version) {
     target_sdk_version_ = target_sdk_version;
   }
 
@@ -166,7 +167,7 @@
 
   std::vector<std::unique_ptr<NamespaceConfig>> namespace_configs_;
   std::unordered_map<std::string, NamespaceConfig*> namespace_configs_map_;
-  uint32_t target_sdk_version_;
+  int target_sdk_version_;
 
   DISALLOW_COPY_AND_ASSIGN(Config);
 };
diff --git a/linker/linker_logger.h b/linker/linker_logger.h
index 9ce438e..1828799 100644
--- a/linker/linker_logger.h
+++ b/linker/linker_logger.h
@@ -30,9 +30,11 @@
 
 #include <stdlib.h>
 #include <limits.h>
-#include "private/bionic_macros.h"
+
 #include "private/bionic_systrace.h"
 
+#include <android-base/macros.h>
+
 #define LD_LOG(type, x...) \
   { \
     g_linker_logger.Log(type, x); \
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index f7c496a..66766fe 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -28,6 +28,9 @@
 
 #include "linker_main.h"
 
+#include <link.h>
+#include <sys/auxv.h>
+
 #include "linker_debug.h"
 #include "linker_cfi.h"
 #include "linker_gdb_support.h"
@@ -35,7 +38,6 @@
 #include "linker_phdr.h"
 #include "linker_utils.h"
 
-#include "private/bionic_auxv.h"
 #include "private/bionic_globals.h"
 #include "private/bionic_tls.h"
 #include "private/KernelArgumentBlock.h"
@@ -48,12 +50,10 @@
 #endif
 
 #include <async_safe/log.h>
+#include <bionic/libc_init_common.h>
 
 #include <vector>
 
-extern void __libc_init_globals(KernelArgumentBlock&);
-extern void __libc_init_AT_SECURE(KernelArgumentBlock&);
-
 __LIBC_HIDDEN__ extern "C" void _start();
 
 static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf);
diff --git a/linker/linker_mapped_file_fragment.h b/linker/linker_mapped_file_fragment.h
index f7872bd..91e094f 100644
--- a/linker/linker_mapped_file_fragment.h
+++ b/linker/linker_mapped_file_fragment.h
@@ -30,7 +30,7 @@
 
 #include <unistd.h>
 
-#include "private/bionic_macros.h"
+#include <android-base/macros.h>
 
 class MappedFileFragment {
  public:
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 8bf4c94..0123d3c 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -525,14 +525,10 @@
 
 // Reserve a virtual address range such that if it's limits were extended to the next 2**align
 // boundary, it would not overlap with any existing mappings.
-static void* ReserveAligned(void* hint, size_t size, size_t align) {
+static void* ReserveAligned(size_t size, size_t align) {
   int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
-  // Address hint is only used in Art for the image mapping, and it is pretty important. Don't mess
-  // with it.
-  // FIXME: try an aligned allocation and fall back to plain mmap() if the former does not provide a
-  // mapping at the requested address?
-  if (align == PAGE_SIZE || hint != nullptr) {
-    void* mmap_ptr = mmap(hint, size, PROT_NONE, mmap_flags, -1, 0);
+  if (align == PAGE_SIZE) {
+    void* mmap_ptr = mmap(nullptr, size, PROT_NONE, mmap_flags, -1, 0);
     if (mmap_ptr == MAP_FAILED) {
       return nullptr;
     }
@@ -575,9 +571,6 @@
   void* start;
   size_t reserved_size = 0;
   bool reserved_hint = true;
-  bool strict_hint = false;
-  // Assume position independent executable by default.
-  void* mmap_hint = nullptr;
 
   if (extinfo != nullptr) {
     if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS) {
@@ -586,13 +579,6 @@
     } else if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_HINT) {
       reserved_size = extinfo->reserved_size;
     }
-
-    if (addr != nullptr && (extinfo->flags & ANDROID_DLEXT_FORCE_FIXED_VADDR) != 0) {
-      mmap_hint = addr;
-    } else if ((extinfo->flags & ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS) != 0) {
-      mmap_hint = extinfo->reserved_addr;
-      strict_hint = true;
-    }
   }
 
   if (load_size_ > reserved_size) {
@@ -601,17 +587,11 @@
              reserved_size - load_size_, load_size_, name_.c_str());
       return false;
     }
-    start = ReserveAligned(mmap_hint, load_size_, kLibraryAlignment);
+    start = ReserveAligned(load_size_, kLibraryAlignment);
     if (start == nullptr) {
       DL_ERR("couldn't reserve %zd bytes of address space for \"%s\"", load_size_, name_.c_str());
       return false;
     }
-    if (strict_hint && (start != mmap_hint)) {
-      munmap(start, load_size_);
-      DL_ERR("couldn't reserve %zd bytes of address space at %p for \"%s\"",
-             load_size_, mmap_hint, name_.c_str());
-      return false;
-    }
   } else {
     start = extinfo->reserved_addr;
     mapped_by_caller_ = true;
diff --git a/linker/linker_sdk_versions.cpp b/linker/linker_sdk_versions.cpp
index 7bfa26c..b06f3e6 100644
--- a/linker/linker_sdk_versions.cpp
+++ b/linker/linker_sdk_versions.cpp
@@ -30,9 +30,9 @@
 #include <android/api-level.h>
 #include <atomic>
 
-static std::atomic<uint32_t> g_target_sdk_version(__ANDROID_API__);
+static std::atomic<int> g_target_sdk_version(__ANDROID_API__);
 
-void set_application_target_sdk_version(uint32_t target) {
+void set_application_target_sdk_version(int target) {
   // translate current sdk_version to platform sdk_version
   if (target == 0) {
     target = __ANDROID_API__;
@@ -40,7 +40,7 @@
   g_target_sdk_version = target;
 }
 
-uint32_t get_application_target_sdk_version() {
+int get_application_target_sdk_version() {
   return g_target_sdk_version;
 }
 
diff --git a/linker/linker_soinfo.cpp b/linker/linker_soinfo.cpp
index 795b01d..71e8a4d 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -44,7 +44,7 @@
 // TODO(dimitry): These functions are currently located in linker.cpp - find a better place for it
 bool find_verdef_version_index(const soinfo* si, const version_info* vi, ElfW(Versym)* versym);
 ElfW(Addr) call_ifunc_resolver(ElfW(Addr) resolver_addr);
-uint32_t get_application_target_sdk_version();
+int get_application_target_sdk_version();
 
 soinfo::soinfo(android_namespace_t* ns, const char* realpath,
                const struct stat* file_stat, off64_t file_offset,
@@ -719,7 +719,7 @@
 // This function returns api-level at the time of
 // dlopen/load. Note that libraries opened by system
 // will always have 'current' api level.
-uint32_t soinfo::get_target_sdk_version() const {
+int soinfo::get_target_sdk_version() const {
   if (!has_min_version(2)) {
     return __ANDROID_API__;
   }
diff --git a/linker/linker_soinfo.h b/linker/linker_soinfo.h
index 7331b2f..44bff28 100644
--- a/linker/linker_soinfo.h
+++ b/linker/linker_soinfo.h
@@ -276,7 +276,7 @@
   ElfW(Addr) get_verdef_ptr() const;
   size_t get_verdef_cnt() const;
 
-  uint32_t get_target_sdk_version() const;
+  int get_target_sdk_version() const;
 
   void set_dt_runpath(const char *);
   const std::vector<std::string>& get_dt_runpath() const;
@@ -353,7 +353,7 @@
   ElfW(Addr) verneed_ptr_;
   size_t verneed_cnt_;
 
-  uint32_t target_sdk_version_;
+  int target_sdk_version_;
 
   // version >= 3
   std::vector<std::string> dt_runpath_;
diff --git a/linker/linker_utils.cpp b/linker/linker_utils.cpp
index 6b9aec9..d08b161 100644
--- a/linker/linker_utils.cpp
+++ b/linker/linker_utils.cpp
@@ -235,6 +235,13 @@
         }
 
         resolved_paths->push_back(std::string(resolved_path) + kZipFileSeparator + entry_path);
+      } else {
+        struct stat s;
+        if (stat(normalized_path.c_str(), &s) == 0 && S_ISDIR(s.st_mode)) {
+          // Path is not a zip path, but an existing directory. Then add it
+          // although we failed to resolve it. b/119656753
+          resolved_paths->push_back(normalized_path);
+        }
       }
     }
   }
diff --git a/linker/tests/Android.mk b/linker/tests/Android.mk
index 8284bea..9268e31 100644
--- a/linker/tests/Android.mk
+++ b/linker/tests/Android.mk
@@ -51,6 +51,6 @@
   ../linker_config.cpp \
   ../linker_utils.cpp \
 
-LOCAL_STATIC_LIBRARIES += libasync_safe libbase
+LOCAL_STATIC_LIBRARIES += libasync_safe libbase liblog
 
 include $(BUILD_NATIVE_TEST)
diff --git a/linker/tests/linker_config_test.cpp b/linker/tests/linker_config_test.cpp
index 9208d9d..14fd132 100644
--- a/linker/tests/linker_config_test.cpp
+++ b/linker/tests/linker_config_test.cpp
@@ -37,10 +37,9 @@
 
 #include <unistd.h>
 
+#include <android-base/file.h>
 #include <android-base/scopeguard.h>
 #include <android-base/stringprintf.h>
-#include <android-base/file.h>
-#include <android-base/test_utils.h>
 
 #if defined(__LP64__)
 #define ARCH_SUFFIX "64"
@@ -144,7 +143,7 @@
   ASSERT_TRUE(config != nullptr);
   ASSERT_TRUE(error_msg.empty());
 
-  ASSERT_EQ(113U, config->target_sdk_version());
+  ASSERT_EQ(113, config->target_sdk_version());
 
   const NamespaceConfig* default_ns_config = config->default_namespace_config();
   ASSERT_TRUE(default_ns_config != nullptr);
diff --git a/tests/Android.bp b/tests/Android.bp
index 4ad51da..899fc66 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -102,6 +102,7 @@
         "limits_test.cpp",
         "linux_swab_test.cpp",
         "locale_test.cpp",
+        "malloc_iterate_test.cpp",
         "malloc_test.cpp",
         "math_test.cpp",
         "math_force_long_double_test.cpp",
@@ -120,6 +121,7 @@
         "regex_test.cpp",
         "resolv_test.cpp",
         "sched_test.cpp",
+        "scs_test.cpp",
         "scsi_sg_test.cpp",
         "search_test.cpp",
         "semaphore_test.cpp",
@@ -196,6 +198,7 @@
         bionic: {
             whole_static_libs: [
                 "libasync_safe",
+                "libprocinfo",
                 "libsystemproperties",
             ],
         },
@@ -628,6 +631,10 @@
 
     static_executable: true,
     stl: "libc++_static",
+
+    // libclang_rt.builtins does not work with libm
+    // http://b/117167374
+    no_libcrt: true,
 }
 
 // -----------------------------------------------------------------------------
diff --git a/tests/TemporaryFile.h b/tests/TemporaryFile.h
deleted file mode 100644
index 8af92d4..0000000
--- a/tests/TemporaryFile.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "private/bionic_macros.h"
-
-template <typename T = int (*)(char*)>
-class GenericTemporaryFile {
- public:
-  explicit GenericTemporaryFile(T mk_fn = mkstemp) : mk_fn(mk_fn) {
-    // Since we might be running on the host or the target, and if we're
-    // running on the host we might be running under bionic or glibc,
-    // let's just try both possible temporary directories and take the
-    // first one that works.
-    init("/data/local/tmp");
-    if (fd == -1) {
-      init("/tmp");
-    }
-  }
-
-  explicit GenericTemporaryFile(const char* dirpath, T mk_fn = mkstemp) : mk_fn(mk_fn) {
-    init(dirpath);
-  }
-
-  ~GenericTemporaryFile() {
-    close(fd);
-    unlink(filename);
-  }
-
-  void reopen() {
-    close(fd);
-    fd = open(filename, O_RDWR);
-  }
-
-  int fd;
-  char filename[1024];
-
- private:
-  T mk_fn;
-
-  void init(const char* tmp_dir) {
-    snprintf(filename, sizeof(filename), "%s/TemporaryFile-XXXXXX", tmp_dir);
-    fd = mk_fn(filename);
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(GenericTemporaryFile);
-};
-
-typedef GenericTemporaryFile<> TemporaryFile;
-
-class TemporaryDir {
- public:
-  TemporaryDir() {
-    if (!init("/data/local/tmp")) {
-      init("/tmp");
-    }
-  }
-
-  ~TemporaryDir() {
-    rmdir(dirname);
-  }
-
-  char dirname[1024];
-
- private:
-  bool init(const char* tmp_dir) {
-    snprintf(dirname, sizeof(dirname), "%s/TemporaryDir-XXXXXX", tmp_dir);
-    return (mkdtemp(dirname) != nullptr);
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(TemporaryDir);
-};
diff --git a/tests/android_get_device_api_level.cpp b/tests/android_get_device_api_level.cpp
index 5272a48..0662404 100644
--- a/tests/android_get_device_api_level.cpp
+++ b/tests/android_get_device_api_level.cpp
@@ -29,7 +29,7 @@
 #include <gtest/gtest.h>
 
 #if __BIONIC__
-#include <android/get_device_api_level.h>
+#include <android/api-level.h>
 #endif
 
 TEST(android_get_device_api_level, smoke) {
diff --git a/tests/buffer_tests.cpp b/tests/buffer_tests.cpp
index a5a0c2a..7563448 100644
--- a/tests/buffer_tests.cpp
+++ b/tests/buffer_tests.cpp
@@ -227,6 +227,18 @@
   }
 }
 
+// Malloc can return a tagged pointer, which is not accepted in mm system calls like mprotect.
+// Clear top 8 bits of the address on 64-bit platforms.
+static int MprotectHeap(void* addr, size_t len, int prot) {
+#if defined(__LP64__)
+  constexpr uintptr_t mask = (static_cast<uintptr_t>(1) << 56) - 1;
+  void* untagged_addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(addr) & mask);
+#else
+  void* untagged_addr = addr;
+#endif
+  return mprotect(untagged_addr, len, prot);
+}
+
 void RunSingleBufferAlignTest(
     size_t max_test_size, void (*test_func)(uint8_t*, size_t),
     size_t (*set_incr)(size_t)) {
@@ -358,14 +370,14 @@
   memset(memory, 0x23, 2*pagesize);
 
   // Make the second page unreadable and unwritable.
-  ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_NONE) == 0);
+  ASSERT_TRUE(MprotectHeap(&memory[pagesize], pagesize, PROT_NONE) == 0);
 
   for (size_t i = 0; i < pagesize; i++) {
     uint8_t* buf = &memory[pagesize-i];
 
     test_func(buf, i);
   }
-  ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
+  ASSERT_TRUE(MprotectHeap(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
   free(memory);
 }
 
@@ -379,7 +391,7 @@
   memset(memory, 0x23, 2*pagesize);
 
   // Make the second page unreadable and unwritable.
-  ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_NONE) == 0);
+  ASSERT_TRUE(MprotectHeap(&memory[pagesize], pagesize, PROT_NONE) == 0);
 
   uint8_t* dst_buffer = new uint8_t[2*pagesize];
   // Change the dst alignment as we change the source.
@@ -391,7 +403,7 @@
       test_func(src, dst, j);
     }
   }
-  ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
+  ASSERT_TRUE(MprotectHeap(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
   free(memory);
   delete[] dst_buffer;
 }
@@ -409,7 +421,7 @@
   memset(memory1, 0x23, 2*pagesize);
 
   // Make the second page unreadable and unwritable.
-  ASSERT_TRUE(mprotect(&memory1[pagesize], pagesize, PROT_NONE) == 0);
+  ASSERT_TRUE(MprotectHeap(&memory1[pagesize], pagesize, PROT_NONE) == 0);
 
   uint8_t* memory2;
   ASSERT_TRUE(posix_memalign(reinterpret_cast<void**>(&memory2), pagesize,
@@ -417,7 +429,7 @@
   memset(memory2, 0x23, 2*pagesize);
 
   // Make the second page unreadable and unwritable.
-  ASSERT_TRUE(mprotect(&memory2[pagesize], pagesize, PROT_NONE) == 0);
+  ASSERT_TRUE(MprotectHeap(&memory2[pagesize], pagesize, PROT_NONE) == 0);
 
   for (size_t i = 0; i < pagesize; i++) {
     uint8_t* buf1 = &memory1[pagesize-i];
@@ -445,8 +457,8 @@
     }
   }
 
-  ASSERT_TRUE(mprotect(&memory1[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
-  ASSERT_TRUE(mprotect(&memory2[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
+  ASSERT_TRUE(MprotectHeap(&memory1[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
+  ASSERT_TRUE(MprotectHeap(&memory2[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
   free(memory1);
   free(memory2);
 }
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index cb98cae..18ba011 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -31,7 +31,7 @@
 #include <fstream>
 
 #include "gtest_globals.h"
-#include "TemporaryFile.h"
+#include <android-base/file.h>
 #include "utils.h"
 
 extern "C" int main_global_default_serial() {
@@ -136,6 +136,7 @@
 
 TEST(dl, preinit_system_calls) {
 #if defined(__BIONIC__)
+  SKIP_WITH_HWASAN; // hwasan not initialized in preinit_array
   std::string helper = GetTestlibRoot() +
       "/preinit_syscall_test_helper/preinit_syscall_test_helper";
   chmod(helper.c_str(), 0755); // TODO: "x" lost in CTS, b/34945607
@@ -153,6 +154,9 @@
   ExecTestHelper eth;
   eth.SetArgs({ helper.c_str(), nullptr });
   eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, nullptr);
+#else
+  // Force a failure when not compiled for bionic so the test is considered a pass.
+  ASSERT_TRUE(false);
 #endif
 }
 
@@ -235,6 +239,7 @@
 // whose search paths include the 'ns2/' subdir.
 TEST(dl, exec_with_ld_config_file) {
 #if defined(__BIONIC__)
+  SKIP_WITH_HWASAN; // libclang_rt.hwasan is not found with custom ld config
   if (!is_debuggable_build()) {
     // LD_CONFIG_FILE is not supported on user build
     return;
@@ -242,8 +247,8 @@
   std::string helper = GetTestlibRoot() +
       "/ld_config_test_helper/ld_config_test_helper";
   TemporaryFile config_file;
-  create_ld_config_file(config_file.filename);
-  std::string env = std::string("LD_CONFIG_FILE=") + config_file.filename;
+  create_ld_config_file(config_file.path);
+  std::string env = std::string("LD_CONFIG_FILE=") + config_file.path;
   chmod(helper.c_str(), 0755);
   ExecTestHelper eth;
   eth.SetArgs({ helper.c_str(), nullptr });
@@ -257,6 +262,7 @@
 // additional namespaces other than the default namespace.
 TEST(dl, exec_with_ld_config_file_with_ld_preload) {
 #if defined(__BIONIC__)
+  SKIP_WITH_HWASAN; // libclang_rt.hwasan is not found with custom ld config
   if (!is_debuggable_build()) {
     // LD_CONFIG_FILE is not supported on user build
     return;
@@ -264,8 +270,8 @@
   std::string helper = GetTestlibRoot() +
       "/ld_config_test_helper/ld_config_test_helper";
   TemporaryFile config_file;
-  create_ld_config_file(config_file.filename);
-  std::string env = std::string("LD_CONFIG_FILE=") + config_file.filename;
+  create_ld_config_file(config_file.path);
+  std::string env = std::string("LD_CONFIG_FILE=") + config_file.path;
   std::string env2 = std::string("LD_PRELOAD=") + GetTestlibRoot() + "/ld_config_test_helper_lib3.so";
   chmod(helper.c_str(), 0755);
   ExecTestHelper eth;
@@ -294,8 +300,8 @@
   std::string helper = GetTestlibRoot() +
       "/ld_config_test_helper/ld_config_test_helper";
   TemporaryFile config_file;
-  create_ld_config_file(config_file.filename);
-  std::string env = std::string("LD_CONFIG_FILE=") + config_file.filename;
+  create_ld_config_file(config_file.path);
+  std::string env = std::string("LD_CONFIG_FILE=") + config_file.path;
   chmod(helper.c_str(), 0755);
   ExecTestHelper eth;
   eth.SetArgs({ helper.c_str(), nullptr });
diff --git a/tests/dlext_private.h b/tests/dlext_private.h
index 2621a68..b338ae0 100644
--- a/tests/dlext_private.h
+++ b/tests/dlext_private.h
@@ -98,7 +98,7 @@
 extern bool android_link_namespaces_all_libs(android_namespace_t* from,
                                              android_namespace_t* to);
 
-extern void android_set_application_target_sdk_version(uint32_t target);
+extern void android_set_application_target_sdk_version(int target);
 
 __END_DECLS
 
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index b33cf68..34013a7 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -40,7 +40,6 @@
 #include <ziparchive/zip_archive.h>
 
 #include "gtest_globals.h"
-#include "TemporaryFile.h"
 #include "utils.h"
 #include "dlext_private.h"
 #include "dlfcn_symlink_support.h"
@@ -367,48 +366,6 @@
   EXPECT_EQ(4, f());
 }
 
-TEST_F(DlExtTest, LoadAtFixedAddress) {
-  void* start = mmap(nullptr, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-  ASSERT_TRUE(start != MAP_FAILED);
-  munmap(start, kLibSize);
-
-  android_dlextinfo extinfo;
-  extinfo.flags = ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS;
-  extinfo.reserved_addr = start;
-
-  handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
-  ASSERT_DL_NOTNULL(handle_);
-  fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
-  ASSERT_DL_NOTNULL(f);
-  EXPECT_GE(reinterpret_cast<void*>(f), start);
-  EXPECT_LT(reinterpret_cast<void*>(f), reinterpret_cast<char*>(start) + kLibSize);
-
-  EXPECT_EQ(4, f());
-  dlclose(handle_);
-  handle_ = nullptr;
-
-  // Check that dlclose unmapped the file
-  void* addr = mmap(start, kLibSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-  ASSERT_EQ(start, addr) << "dlclose did not unmap the memory";
-}
-
-TEST_F(DlExtTest, LoadAtFixedAddressTooSmall) {
-  void* start = mmap(nullptr, kLibSize + PAGE_SIZE, PROT_NONE,
-                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-  ASSERT_TRUE(start != MAP_FAILED);
-  munmap(start, kLibSize + PAGE_SIZE);
-  void* new_addr = mmap(reinterpret_cast<uint8_t*>(start) + PAGE_SIZE, kLibSize, PROT_NONE,
-                        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-  ASSERT_TRUE(new_addr != MAP_FAILED);
-
-  android_dlextinfo extinfo;
-  extinfo.flags = ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS;
-  extinfo.reserved_addr = start;
-
-  handle_ = android_dlopen_ext(kLibName, RTLD_NOW, &extinfo);
-  ASSERT_TRUE(handle_ == nullptr);
-}
-
 class DlExtRelroSharingTest : public DlExtTest {
 protected:
   virtual void SetUp() {
@@ -477,7 +434,7 @@
   TemporaryFile tf; // Use tf to get an unique filename.
   ASSERT_NOERROR(close(tf.fd));
 
-  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.filename));
+  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path));
   ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName));
 
   // Use destructor of tf to close and unlink the file.
@@ -488,7 +445,7 @@
   TemporaryFile tf; // // Use tf to get an unique filename.
   ASSERT_NOERROR(close(tf.fd));
 
-  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameNoRelro, tf.filename));
+  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameNoRelro, tf.path));
   ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameNoRelro));
 
   // Use destructor of tf to close and unlink the file.
@@ -508,14 +465,14 @@
   TemporaryFile tf; // Use tf to get an unique filename.
   ASSERT_NOERROR(close(tf.fd));
 
-  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.filename));
+  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path));
 
   int pipefd[2];
   ASSERT_NOERROR(pipe(pipefd));
 
   size_t without_sharing, with_sharing;
-  ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.filename, false, &without_sharing));
-  ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.filename, true, &with_sharing));
+  ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.path, false, &without_sharing));
+  ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.path, true, &with_sharing));
   ASSERT_LT(with_sharing, without_sharing);
 
   // We expect the sharing to save at least 50% of the library's total PSS.
diff --git a/tests/fcntl_test.cpp b/tests/fcntl_test.cpp
index da44fee..d7dce31 100644
--- a/tests/fcntl_test.cpp
+++ b/tests/fcntl_test.cpp
@@ -22,8 +22,7 @@
 #include <sys/utsname.h>
 #include <sys/vfs.h>
 
-#include "TemporaryFile.h"
-
+#include <android-base/file.h>
 #include <android-base/stringprintf.h>
 
 // Glibc v2.19 doesn't include these in fcntl.h so host builds will fail without.
@@ -307,7 +306,7 @@
   // Without O_EXCL, we're allowed to give this a name later.
   // (This is unrelated to the O_CREAT interaction with O_EXCL.)
   const mode_t perms = S_IRUSR | S_IWUSR;
-  int fd = open(dir.dirname, O_TMPFILE | O_RDWR, perms);
+  int fd = open(dir.path, O_TMPFILE | O_RDWR, perms);
 
   // Ignore kernels without O_TMPFILE support (< 3.11).
   if (fd == -1 && (errno == EISDIR || errno == EINVAL || errno == EOPNOTSUPP)) return;
@@ -322,7 +321,7 @@
   // On Android if we're not root, we won't be able to create links anyway...
   if (getuid() != 0) return;
 
-  std::string final_path = android::base::StringPrintf("%s/named_now", dir.dirname);
+  std::string final_path = android::base::StringPrintf("%s/named_now", dir.path);
   ASSERT_EQ(0, linkat(AT_FDCWD, android::base::StringPrintf("/proc/self/fd/%d", fd).c_str(),
                       AT_FDCWD, final_path.c_str(),
                       AT_SYMLINK_FOLLOW));
@@ -333,11 +332,11 @@
   ASSERT_EQ(perms, (sb.st_mode & ~S_IFMT));
 
   // With O_EXCL, you're not allowed to add a name later.
-  fd = open(dir.dirname, O_TMPFILE | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
+  fd = open(dir.path, O_TMPFILE | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
   ASSERT_TRUE(fd != -1) << strerror(errno);
   errno = 0;
   ASSERT_EQ(-1, linkat(AT_FDCWD, android::base::StringPrintf("/proc/self/fd/%d", fd).c_str(),
-                       AT_FDCWD, android::base::StringPrintf("%s/no_chance", dir.dirname).c_str(),
+                       AT_FDCWD, android::base::StringPrintf("%s/no_chance", dir.path).c_str(),
                        AT_SYMLINK_FOLLOW));
   ASSERT_EQ(ENOENT, errno);
   ASSERT_EQ(0, close(fd));
diff --git a/tests/ftw_test.cpp b/tests/ftw_test.cpp
index 22ab399..dfc4d72 100644
--- a/tests/ftw_test.cpp
+++ b/tests/ftw_test.cpp
@@ -16,6 +16,7 @@
 
 #include <ftw.h>
 
+#include <fcntl.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -23,8 +24,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "TemporaryFile.h"
-
+#include <android-base/file.h>
 #include <android-base/stringprintf.h>
 #include <gtest/gtest.h>
 
@@ -102,26 +102,26 @@
 
 TEST(ftw, ftw) {
   TemporaryDir root;
-  MakeTree(root.dirname);
-  ASSERT_EQ(0, ftw(root.dirname, check_ftw, 128));
+  MakeTree(root.path);
+  ASSERT_EQ(0, ftw(root.path, check_ftw, 128));
 }
 
 TEST(ftw, ftw64) {
   TemporaryDir root;
-  MakeTree(root.dirname);
-  ASSERT_EQ(0, ftw64(root.dirname, check_ftw64, 128));
+  MakeTree(root.path);
+  ASSERT_EQ(0, ftw64(root.path, check_ftw64, 128));
 }
 
 TEST(ftw, nftw) {
   TemporaryDir root;
-  MakeTree(root.dirname);
-  ASSERT_EQ(0, nftw(root.dirname, check_nftw, 128, 0));
+  MakeTree(root.path);
+  ASSERT_EQ(0, nftw(root.path, check_nftw, 128, 0));
 }
 
 TEST(ftw, nftw64) {
   TemporaryDir root;
-  MakeTree(root.dirname);
-  ASSERT_EQ(0, nftw64(root.dirname, check_nftw64, 128, 0));
+  MakeTree(root.path);
+  ASSERT_EQ(0, nftw64(root.path, check_nftw64, 128, 0));
 }
 
 template <typename StatT>
@@ -145,13 +145,13 @@
 
   TemporaryDir root;
 
-  std::string path = android::base::StringPrintf("%s/unreadable-directory", root.dirname);
+  std::string path = android::base::StringPrintf("%s/unreadable-directory", root.path);
   ASSERT_EQ(0, mkdir(path.c_str(), 0000)) << path;
 
-  ASSERT_EQ(0, ftw(root.dirname, bug_28197840_ftw<struct stat>, 128));
-  ASSERT_EQ(0, ftw64(root.dirname, bug_28197840_ftw<struct stat64>, 128));
-  ASSERT_EQ(0, nftw(root.dirname, bug_28197840_nftw<struct stat>, 128, FTW_PHYS));
-  ASSERT_EQ(0, nftw64(root.dirname, bug_28197840_nftw<struct stat64>, 128, FTW_PHYS));
+  ASSERT_EQ(0, ftw(root.path, bug_28197840_ftw<struct stat>, 128));
+  ASSERT_EQ(0, ftw64(root.path, bug_28197840_ftw<struct stat64>, 128));
+  ASSERT_EQ(0, nftw(root.path, bug_28197840_nftw<struct stat>, 128, FTW_PHYS));
+  ASSERT_EQ(0, nftw64(root.path, bug_28197840_nftw<struct stat64>, 128, FTW_PHYS));
 }
 
 template <typename StatT>
diff --git a/tests/getcwd_test.cpp b/tests/getcwd_test.cpp
index f8f205e..791ffae 100644
--- a/tests/getcwd_test.cpp
+++ b/tests/getcwd_test.cpp
@@ -20,6 +20,8 @@
 #include <limits.h>
 #include <unistd.h>
 
+#include "utils.h"
+
 TEST(getcwd, auto_full) {
   // If we let the library do all the work, everything's fine.
   errno = 0;
@@ -49,6 +51,7 @@
 }
 
 TEST(getcwd, auto_too_large) {
+  SKIP_WITH_HWASAN; // allocation size too large
   // If we ask the library to allocate an unreasonably large buffer, ERANGE.
   errno = 0;
   char* cwd = getcwd(nullptr, static_cast<size_t>(-1));
diff --git a/tests/glob_test.cpp b/tests/glob_test.cpp
index 623a2a3..b48f2af 100644
--- a/tests/glob_test.cpp
+++ b/tests/glob_test.cpp
@@ -22,7 +22,7 @@
 #include <string>
 #include <vector>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
 
 #if defined(__BIONIC__)
 #define ASSERT_MATCH_COUNT(n_,g_) ASSERT_EQ(n_, g_.gl_matchc)
@@ -140,22 +140,22 @@
 TEST(glob, glob_GLOB_MARK) {
   TemporaryDir td;
   // The pattern we're about to pass doesn't have a trailing '/'...
-  ASSERT_NE('/', std::string(td.dirname).back());
+  ASSERT_NE('/', std::string(td.path).back());
 
   glob_t g = {};
   // Using GLOB_MARK gets you a trailing '/' on a directory...
-  ASSERT_EQ(0, glob(td.dirname, GLOB_MARK, nullptr, &g));
+  ASSERT_EQ(0, glob(td.path, GLOB_MARK, nullptr, &g));
   ASSERT_EQ(1U, g.gl_pathc);
   ASSERT_MATCH_COUNT(1U, g);
-  ASSERT_EQ(std::string(td.dirname) + "/", g.gl_pathv[0]);
+  ASSERT_EQ(std::string(td.path) + "/", g.gl_pathv[0]);
   ASSERT_EQ(nullptr, g.gl_pathv[1]);
 
   TemporaryFile tf;
   // But not on a file...
-  ASSERT_EQ(0, glob(tf.filename, GLOB_MARK, nullptr, &g));
+  ASSERT_EQ(0, glob(tf.path, GLOB_MARK, nullptr, &g));
   ASSERT_EQ(1U, g.gl_pathc);
   ASSERT_MATCH_COUNT(1U, g);
-  ASSERT_STREQ(tf.filename, g.gl_pathv[0]);
+  ASSERT_STREQ(tf.path, g.gl_pathv[0]);
   ASSERT_EQ(nullptr, g.gl_pathv[1]);
 
   globfree(&g);
diff --git a/tests/grp_pwd_file_test.cpp b/tests/grp_pwd_file_test.cpp
index 8721805..2cbad62 100644
--- a/tests/grp_pwd_file_test.cpp
+++ b/tests/grp_pwd_file_test.cpp
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
 
 #if defined(__BIONIC__)
 #include "../libc/bionic/grp_pwd_file.cpp"
@@ -94,7 +94,7 @@
   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, nullptr);
+  PasswdFile passwd_file(file.path, nullptr);
   FileUnmapper unmapper(passwd_file);
 
   FindAndCheckPasswdEntry(&passwd_file, "name", 1, 2, "dir", "shell");
@@ -114,7 +114,7 @@
   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, nullptr);
+  GroupFile group_file(file.path, nullptr);
   FileUnmapper unmapper(group_file);
 
   FindAndCheckGroupEntry(&group_file, "name", 1);
@@ -150,7 +150,7 @@
 
   write(file.fd, test_string, sizeof(test_string) - 1);
 
-  PasswdFile passwd_file(file.filename, nullptr);
+  PasswdFile passwd_file(file.path, nullptr);
   FileUnmapper unmapper(passwd_file);
 
   FindAndCheckPasswdEntry(&passwd_file, "first", 1, 2, "dir", "shell");
@@ -186,7 +186,7 @@
 
   write(file.fd, test_string, sizeof(test_string) - 1);
 
-  GroupFile group_file(file.filename, nullptr);
+  GroupFile group_file(file.path, nullptr);
   FileUnmapper unmapper(group_file);
 
   FindAndCheckGroupEntry(&group_file, "first", 1);
@@ -210,7 +210,7 @@
       "vendor_name:password:3:4:user_info:dir:shell\n";
   write(file.fd, test_string, sizeof(test_string) - 1);
 
-  PasswdFile passwd_file(file.filename, "vendor_");
+  PasswdFile passwd_file(file.path, "vendor_");
   FileUnmapper unmapper(passwd_file);
 
   EXPECT_FALSE(passwd_file.FindByName("name", nullptr));
@@ -232,7 +232,7 @@
       "vendor_name:password:2:one,two,three\n";
   write(file.fd, test_string, sizeof(test_string) - 1);
 
-  GroupFile group_file(file.filename, "vendor_");
+  GroupFile group_file(file.path, "vendor_");
   FileUnmapper unmapper(group_file);
 
   EXPECT_FALSE(group_file.FindByName("name", nullptr));
diff --git a/tests/headers/posix/sys_msg_h.c b/tests/headers/posix/sys_msg_h.c
index b908188..b02cd47 100644
--- a/tests/headers/posix/sys_msg_h.c
+++ b/tests/headers/posix/sys_msg_h.c
@@ -26,6 +26,8 @@
  * SUCH DAMAGE.
  */
 
+#if defined(__BIONIC__)
+
 #include <sys/msg.h>
 
 #include "header_checks.h"
@@ -42,9 +44,16 @@
   STRUCT_MEMBER(struct msqid_ds, msglen_t, msg_qbytes);
   STRUCT_MEMBER(struct msqid_ds, pid_t, msg_lspid);
   STRUCT_MEMBER(struct msqid_ds, pid_t, msg_lrpid);
+#if defined(__LP64__)
   STRUCT_MEMBER(struct msqid_ds, time_t, msg_stime);
   STRUCT_MEMBER(struct msqid_ds, time_t, msg_rtime);
   STRUCT_MEMBER(struct msqid_ds, time_t, msg_ctime);
+#else
+  // Starting at kernel v4.19, 32 bit changed these to unsigned values.
+  STRUCT_MEMBER(struct msqid_ds, unsigned long, msg_stime);
+  STRUCT_MEMBER(struct msqid_ds, unsigned long, msg_rtime);
+  STRUCT_MEMBER(struct msqid_ds, unsigned long, msg_ctime);
+#endif
 
   TYPE(pid_t);
   TYPE(size_t);
@@ -56,3 +65,4 @@
   FUNCTION(msgrcv, ssize_t (*f)(int, void*, size_t, long, int));
   FUNCTION(msgsnd, int (*f)(int, const void*, size_t, int));
 }
+#endif
diff --git a/tests/headers/posix/sys_sem_h.c b/tests/headers/posix/sys_sem_h.c
index 1b1b16d..49b236f 100644
--- a/tests/headers/posix/sys_sem_h.c
+++ b/tests/headers/posix/sys_sem_h.c
@@ -26,6 +26,8 @@
  * SUCH DAMAGE.
  */
 
+#if defined(__BIONIC__)
+
 #include <sys/sem.h>
 
 #include "header_checks.h"
@@ -48,8 +50,14 @@
 #else
   STRUCT_MEMBER(struct semid_ds, unsigned short, sem_nsems);
 #endif
+#if defined(__LP64__)
   STRUCT_MEMBER(struct semid_ds, time_t, sem_otime);
   STRUCT_MEMBER(struct semid_ds, time_t, sem_ctime);
+#else
+  // Starting at kernel v4.19, 32 bit changed these to unsigned values.
+  STRUCT_MEMBER(struct semid_ds, unsigned long, sem_otime);
+  STRUCT_MEMBER(struct semid_ds, unsigned long, sem_ctime);
+#endif
 
   TYPE(pid_t);
   TYPE(size_t);
@@ -64,3 +72,5 @@
   FUNCTION(semget, int (*f)(key_t, int, int));
   FUNCTION(semop, int (*f)(int, struct sembuf*, size_t));
 }
+
+#endif
diff --git a/tests/headers/posix/sys_shm_h.c b/tests/headers/posix/sys_shm_h.c
index 4ecd6d3..03d6815 100644
--- a/tests/headers/posix/sys_shm_h.c
+++ b/tests/headers/posix/sys_shm_h.c
@@ -26,6 +26,8 @@
  * SUCH DAMAGE.
  */
 
+#if defined(__BIONIC__)
+
 #include <sys/shm.h>
 
 #include "header_checks.h"
@@ -43,9 +45,16 @@
   STRUCT_MEMBER(struct shmid_ds, pid_t, shm_lpid);
   STRUCT_MEMBER(struct shmid_ds, pid_t, shm_cpid);
   STRUCT_MEMBER(struct shmid_ds, shmatt_t, shm_nattch);
+#if defined(__LP64__)
   STRUCT_MEMBER(struct shmid_ds, time_t, shm_atime);
   STRUCT_MEMBER(struct shmid_ds, time_t, shm_dtime);
   STRUCT_MEMBER(struct shmid_ds, time_t, shm_ctime);
+#else
+  // Starting at kernel v4.19, 32 bit changed these to unsigned values.
+  STRUCT_MEMBER(struct shmid_ds, unsigned long, shm_atime);
+  STRUCT_MEMBER(struct shmid_ds, unsigned long, shm_dtime);
+  STRUCT_MEMBER(struct shmid_ds, unsigned long, shm_ctime);
+#endif
 
   TYPE(pid_t);
   TYPE(size_t);
@@ -56,3 +65,4 @@
   FUNCTION(shmdt, int (*f)(const void*));
   FUNCTION(shmget, int (*f)(key_t, size_t, int));
 }
+#endif
diff --git a/tests/libdl_test.cpp b/tests/libdl_test.cpp
index b162edc..6774f1d 100644
--- a/tests/libdl_test.cpp
+++ b/tests/libdl_test.cpp
@@ -18,17 +18,16 @@
 
 #include <android/api-level.h>
 
-extern "C" uint32_t android_get_application_target_sdk_version();
-extern "C" void android_set_application_target_sdk_version(uint32_t target);
+extern "C" void android_set_application_target_sdk_version(int target);
 
 TEST(libdl, application_sdk_versions_smoke) {
   // Check initial values
-  ASSERT_EQ(static_cast<uint32_t>(__ANDROID_API__), android_get_application_target_sdk_version());
+  ASSERT_EQ(__ANDROID_API__, android_get_application_target_sdk_version());
 
-  android_set_application_target_sdk_version(20U);
-  ASSERT_EQ(20U, android_get_application_target_sdk_version());
+  android_set_application_target_sdk_version(20);
+  ASSERT_EQ(20, android_get_application_target_sdk_version());
 
-  android_set_application_target_sdk_version(22U);
-  ASSERT_EQ(22U, android_get_application_target_sdk_version());
+  android_set_application_target_sdk_version(22);
+  ASSERT_EQ(22, android_get_application_target_sdk_version());
 }
 
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 5c4eb42..79c9a06 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -531,8 +531,6 @@
     defaults: ["bionic_testlib_defaults"],
     srcs: ["dl_df_1_global.cpp"],
     ldflags: ["-Wl,-z,global"],
-    // b/80109858, clang lld ignores -z,global
-    use_clang_lld: false,
 
     target: {
         host: {
@@ -561,8 +559,6 @@
     defaults: ["bionic_testlib_defaults"],
     srcs: ["dl_df_1_global_dummy.cpp"],
     ldflags: ["-Wl,-z,global"],
-    // b/80109858, clang lld ignores -z,global
-    use_clang_lld: false,
 
     target: {
         host: {
diff --git a/tests/libs/cfi_test_helper.cpp b/tests/libs/cfi_test_helper.cpp
index ff313a2..c1a7b6d 100644
--- a/tests/libs/cfi_test_helper.cpp
+++ b/tests/libs/cfi_test_helper.cpp
@@ -27,11 +27,13 @@
 static int g_count;
 
 // Mock a CFI-enabled library without relying on the compiler.
-extern "C" __attribute__((aligned(4096))) void __cfi_check(uint64_t /*CallSiteTypeId*/,
-                                                           void* /*TargetAddr*/, void* /*Diag*/) {
+extern "C" __attribute__((no_sanitize("hwaddress")))  __attribute__((aligned(4096)))
+void __cfi_check(uint64_t /*CallSiteTypeId*/, void* /*TargetAddr*/, void* /*Diag*/) {
   ++g_count;
 }
 
+// This code runs before hwasan is initialized.
+__attribute__((no_sanitize("hwaddress")))
 void preinit_ctor() {
   CHECK(g_count == 0);
   __cfi_slowpath(42, reinterpret_cast<void*>(&preinit_ctor));
diff --git a/tests/malloc_iterate_test.cpp b/tests/malloc_iterate_test.cpp
new file mode 100644
index 0000000..5e60a6d
--- /dev/null
+++ b/tests/malloc_iterate_test.cpp
@@ -0,0 +1,225 @@
+/*
+ * 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 <stdint.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <gtest/gtest.h>
+
+#if defined(__BIONIC__)
+
+#include <vector>
+
+#include <procinfo/process_map.h>
+
+#include "utils.h"
+
+extern "C" void malloc_disable();
+extern "C" void malloc_enable();
+extern "C" int malloc_iterate(uintptr_t base, size_t size, void (*callback)(uintptr_t base,
+                              size_t size, void* arg), void* arg);
+
+struct AllocDataType {
+  void* ptr;
+  size_t size;
+  size_t size_reported;
+  size_t count;
+};
+
+struct TestDataType {
+  size_t total_allocated_bytes;
+  std::vector<AllocDataType> allocs;
+};
+
+static void AllocPtr(TestDataType* test_data, size_t size) {
+  test_data->allocs.resize(test_data->allocs.size() + 1);
+  AllocDataType* alloc = &test_data->allocs.back();
+  void* ptr = malloc(size);
+  ASSERT_TRUE(ptr != nullptr);
+  alloc->ptr = ptr;
+  alloc->size = malloc_usable_size(ptr);
+  alloc->size_reported = 0;
+  alloc->count = 0;
+}
+
+static void FreePtrs(TestDataType* test_data) {
+  for (size_t i = 0; i < test_data->allocs.size(); i++) {
+    free(test_data->allocs[i].ptr);
+  }
+}
+
+static void SavePointers(uintptr_t base, size_t size, void* data) {
+  TestDataType* test_data = reinterpret_cast<TestDataType*>(data);
+
+  test_data->total_allocated_bytes += size;
+
+  uintptr_t end;
+  if (__builtin_add_overflow(base, size, &end)) {
+    // Skip this entry.
+    return;
+  }
+
+  for (size_t i = 0; i < test_data->allocs.size(); i++) {
+    uintptr_t ptr = reinterpret_cast<uintptr_t>(test_data->allocs[i].ptr);
+    if (ptr >= base && ptr < end) {
+      test_data->allocs[i].count++;
+
+      uintptr_t max_size = end - ptr;
+      if (max_size > test_data->allocs[i].size) {
+        test_data->allocs[i].size_reported = test_data->allocs[i].size;
+      } else {
+        test_data->allocs[i].size_reported = max_size;
+      }
+    }
+  }
+}
+
+static void VerifyPtrs(TestDataType* test_data) {
+  test_data->total_allocated_bytes = 0;
+
+  // Find all of the maps that are [anon:libc_malloc].
+  ASSERT_TRUE(android::procinfo::ReadMapFile("/proc/self/maps",
+    [&](uint64_t start, uint64_t end, uint16_t, uint64_t, const char* name) {
+    if (std::string(name) == "[anon:libc_malloc]") {
+      malloc_disable();
+      malloc_iterate(start, end - start, SavePointers, test_data);
+      malloc_enable();
+    }
+  }));
+
+  for (size_t i = 0; i < test_data->allocs.size(); i++) {
+    EXPECT_EQ(1UL, test_data->allocs[i].count) << "Failed on size " << test_data->allocs[i].size;
+    if (test_data->allocs[i].count == 1) {
+      EXPECT_EQ(test_data->allocs[i].size, test_data->allocs[i].size_reported);
+    }
+  }
+}
+
+static void AllocateSizes(TestDataType* test_data, const std::vector<size_t>& sizes) {
+  static constexpr size_t kInitialAllocations = 40;
+  static constexpr size_t kNumAllocs = 50;
+  for (size_t size : sizes) {
+    // Verify that if the tcache is enabled, that tcache pointers
+    // are found by allocating and freeing 20 pointers (should be larger
+    // than the total number of cache entries).
+    for (size_t i = 0; i < kInitialAllocations; i++) {
+      void* ptr = malloc(size);
+      ASSERT_TRUE(ptr != nullptr);
+      memset(ptr, 0, size);
+      free(ptr);
+    }
+    for (size_t i = 0; i < kNumAllocs; i++) {
+      AllocPtr(test_data, size);
+    }
+  }
+}
+#endif
+
+// Verify that small allocs can be found properly.
+TEST(malloc_iterate, small_allocs) {
+#if defined(__BIONIC__)
+  SKIP_WITH_HWASAN;
+  TestDataType test_data;
+
+  // Try to cycle through all of the different small bins.
+  // This is specific to the implementation of jemalloc and should be
+  // adjusted if a different native memory allocator is used.
+  std::vector<size_t> sizes{8,    16,   32,   48,    64,    80,    96,    112,   128,  160,
+                            192,  224,  256,  320,   384,   448,   512,   640,   768,  896,
+                            1024, 1280, 1536, 1792,  2048,  2560,  3072,  3584,  4096, 5120,
+                            6144, 7168, 8192, 10240, 12288, 14336, 16384, 32768, 65536};
+  AllocateSizes(&test_data, sizes);
+
+  SCOPED_TRACE("");
+  VerifyPtrs(&test_data);
+
+  FreePtrs(&test_data);
+#else
+  GTEST_LOG_(INFO) << "Skipping, this is a bionic only test.";
+#endif
+}
+
+// Verify that large allocs can be found properly.
+TEST(malloc_iterate, large_allocs) {
+#if defined(__BIONIC__)
+  SKIP_WITH_HWASAN;
+  TestDataType test_data;
+
+  // Try some larger sizes.
+  std::vector<size_t> sizes{131072, 262144, 524288, 1048576, 2097152};
+  AllocateSizes(&test_data, sizes);
+
+  SCOPED_TRACE("");
+  VerifyPtrs(&test_data);
+
+  FreePtrs(&test_data);
+#else
+  GTEST_LOG_(INFO) << "Skipping, this is a bionic only test.";
+#endif
+}
+
+// Verify that there are no crashes attempting to get pointers from
+// non-allocated pointers.
+TEST(malloc_iterate, invalid_pointers) {
+#if defined(__BIONIC__)
+  SKIP_WITH_HWASAN;
+  TestDataType test_data = {};
+
+  // Find all of the maps that are not [anon:libc_malloc].
+  ASSERT_TRUE(android::procinfo::ReadMapFile("/proc/self/maps",
+    [&](uint64_t start, uint64_t end, uint16_t, uint64_t, const char* name) {
+    if (std::string(name) != "[anon:libc_malloc]") {
+      malloc_disable();
+      malloc_iterate(start, end - start, SavePointers, &test_data);
+      malloc_enable();
+    }
+  }));
+
+  ASSERT_EQ(0UL, test_data.total_allocated_bytes);
+#else
+  GTEST_LOG_(INFO) << "Skipping, this is a bionic only test.";
+#endif
+}
+
+TEST(malloc_iterate, malloc_disable_prevents_allocs) {
+#if defined(__BIONIC__)
+  SKIP_WITH_HWASAN;
+  pid_t pid;
+  if ((pid = fork()) == 0) {
+    malloc_disable();
+    void* ptr = malloc(1024);
+    if (ptr == nullptr) {
+      exit(1);
+    }
+    memset(ptr, 0, 1024);
+    exit(0);
+  }
+  ASSERT_NE(-1, pid);
+
+  // Expect that the malloc will hang forever, and that if the process
+  // does not return for two seconds, it is hung.
+  sleep(2);
+  pid_t wait_pid = TEMP_FAILURE_RETRY(waitpid(pid, nullptr, WNOHANG));
+  if (wait_pid <= 0) {
+    kill(pid, SIGKILL);
+  }
+  ASSERT_NE(-1, wait_pid) << "Unknown failure in waitpid.";
+  ASSERT_EQ(0, wait_pid) << "malloc_disable did not prevent allocation calls.";
+#else
+  GTEST_LOG_(INFO) << "Skipping, this is a bionic only test.";
+#endif
+}
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index c4f13f6..4a01278 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -25,6 +25,7 @@
 #include <tinyxml2.h>
 
 #include "private/bionic_config.h"
+#include "utils.h"
 
 #if defined(__BIONIC__)
 #define HAVE_REALLOCARRAY 1
@@ -41,6 +42,7 @@
 }
 
 TEST(malloc, malloc_overflow) {
+  SKIP_WITH_HWASAN;
   errno = 0;
   ASSERT_EQ(nullptr, malloc(SIZE_MAX));
   ASSERT_EQ(ENOMEM, errno);
@@ -59,12 +61,14 @@
 }
 
 TEST(malloc, calloc_illegal) {
+  SKIP_WITH_HWASAN;
   errno = 0;
   ASSERT_EQ(nullptr, calloc(-1, 100));
   ASSERT_EQ(ENOMEM, errno);
 }
 
 TEST(malloc, calloc_overflow) {
+  SKIP_WITH_HWASAN;
   errno = 0;
   ASSERT_EQ(nullptr, calloc(1, SIZE_MAX));
   ASSERT_EQ(ENOMEM, errno);
@@ -80,6 +84,7 @@
 }
 
 TEST(malloc, memalign_multiple) {
+  SKIP_WITH_HWASAN; // hwasan requires power of 2 alignment.
   // Memalign test where the alignment is any value.
   for (size_t i = 0; i <= 12; i++) {
     for (size_t alignment = 1 << i; alignment < (1U << (i+1)); alignment++) {
@@ -94,10 +99,12 @@
 }
 
 TEST(malloc, memalign_overflow) {
+  SKIP_WITH_HWASAN;
   ASSERT_EQ(nullptr, memalign(4096, SIZE_MAX));
 }
 
 TEST(malloc, memalign_non_power2) {
+  SKIP_WITH_HWASAN;
   void* ptr;
   for (size_t align = 0; align <= 256; align++) {
     ptr = memalign(align, 1024);
@@ -280,6 +287,7 @@
 }
 
 TEST(malloc, realloc_overflow) {
+  SKIP_WITH_HWASAN;
   errno = 0;
   ASSERT_EQ(nullptr, realloc(nullptr, SIZE_MAX));
   ASSERT_EQ(ENOMEM, errno);
@@ -504,6 +512,27 @@
   ASSERT_EQ(0, errno);
 }
 
+TEST(malloc, mallopt_decay) {
+#if defined(__BIONIC__)
+  errno = 0;
+  ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
+  ASSERT_EQ(1, mallopt(M_DECAY_TIME, 0));
+  ASSERT_EQ(1, mallopt(M_DECAY_TIME, 1));
+  ASSERT_EQ(1, mallopt(M_DECAY_TIME, 0));
+#else
+  GTEST_LOG_(INFO) << "This tests a bionic implementation detail.\n";
+#endif
+}
+
+TEST(malloc, mallopt_purge) {
+#if defined(__BIONIC__)
+  errno = 0;
+  ASSERT_EQ(1, mallopt(M_PURGE, 0));
+#else
+  GTEST_LOG_(INFO) << "This tests a bionic implementation detail.\n";
+#endif
+}
+
 TEST(malloc, reallocarray_overflow) {
 #if HAVE_REALLOCARRAY
   // Values that cause overflow to a result small enough (8 on LP64) that malloc would "succeed".
@@ -531,3 +560,44 @@
   GTEST_LOG_(INFO) << "This test requires a C library with reallocarray.\n";
 #endif
 }
+
+TEST(malloc, mallinfo) {
+#if defined(__BIONIC__)
+  static size_t sizes[] = {
+    8, 32, 128, 4096, 32768, 131072, 1024000, 10240000, 20480000, 300000000
+  };
+
+  constexpr static size_t kMaxAllocs = 50;
+
+  for (size_t size : sizes) {
+    // If some of these allocations are stuck in a thread cache, then keep
+    // looping until we make an allocation that changes the total size of the
+    // memory allocated.
+    // jemalloc implementations counts the thread cache allocations against
+    // total memory allocated.
+    void* ptrs[kMaxAllocs] = {};
+    bool pass = false;
+    for (size_t i = 0; i < kMaxAllocs; i++) {
+      size_t allocated = mallinfo().uordblks;
+      ptrs[i] = malloc(size);
+      ASSERT_TRUE(ptrs[i] != nullptr);
+      size_t new_allocated = mallinfo().uordblks;
+      if (allocated != new_allocated) {
+        size_t usable_size = malloc_usable_size(ptrs[i]);
+        ASSERT_GE(new_allocated, allocated + usable_size)
+            << "Failed at size " << size << " usable size " << usable_size;
+        pass = true;
+        break;
+      }
+    }
+    for (void* ptr : ptrs) {
+      free(ptr);
+    }
+    ASSERT_TRUE(pass)
+        << "For size " << size << " allocated bytes did not increase after "
+        << kMaxAllocs << " allocations.";
+  }
+#else
+  GTEST_LOG_(INFO) << "Host glibc does not pass this test, skipping.\n";
+#endif
+}
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index e68f1ff..84ce531 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -34,12 +34,12 @@
 #include <future>
 #include <vector>
 
+#include <android-base/macros.h>
 #include <android-base/parseint.h>
 #include <android-base/scopeguard.h>
 #include <android-base/strings.h>
 
 #include "private/bionic_constants.h"
-#include "private/bionic_macros.h"
 #include "BionicDeathTest.h"
 #include "SignalUtils.h"
 #include "utils.h"
diff --git a/tests/scs_test.cpp b/tests/scs_test.cpp
new file mode 100644
index 0000000..24cb347
--- /dev/null
+++ b/tests/scs_test.cpp
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+#if __has_feature(shadow_call_stack)
+
+#include <gtest/gtest.h>
+
+#include "private/bionic_constants.h"
+
+int recurse2(int count);
+
+__attribute__((weak, noinline)) int recurse1(int count) {
+  if (count != 0) return recurse2(count - 1) + 1;
+  return 0;
+}
+
+__attribute__((weak, noinline)) int recurse2(int count) {
+  if (count != 0) return recurse1(count - 1) + 1;
+  return 0;
+}
+
+TEST(scs_test, stack_overflow) {
+  ASSERT_EXIT(recurse1(SCS_SIZE), testing::KilledBySignal(SIGSEGV), "");
+}
+
+#endif
diff --git a/tests/semaphore_test.cpp b/tests/semaphore_test.cpp
index 10d99ea..690e886 100644
--- a/tests/semaphore_test.cpp
+++ b/tests/semaphore_test.cpp
@@ -174,7 +174,7 @@
   ASSERT_EQ(1, i);
 }
 
-extern "C" void android_set_application_target_sdk_version(uint32_t target);
+extern "C" void android_set_application_target_sdk_version(int target);
 
 static void sem_wait_test_signal_handler(int) {
 }
diff --git a/tests/setjmp_test.cpp b/tests/setjmp_test.cpp
index dde0be1..44d8af1 100644
--- a/tests/setjmp_test.cpp
+++ b/tests/setjmp_test.cpp
@@ -264,3 +264,14 @@
     fprintf(stderr, "setjmp_cookie_checksum: longjmp succeeded?");
   }
 }
+
+__attribute__((noinline)) void call_longjmp(jmp_buf buf) {
+  longjmp(buf, 123);
+}
+
+TEST(setjmp, setjmp_stack) {
+  jmp_buf buf;
+  int value = setjmp(buf);
+  if (value == 0) call_longjmp(buf);
+  EXPECT_EQ(123, value);
+}
diff --git a/tests/stdio_ext_test.cpp b/tests/stdio_ext_test.cpp
index d4616ef..d84fda0 100644
--- a/tests/stdio_ext_test.cpp
+++ b/tests/stdio_ext_test.cpp
@@ -29,7 +29,8 @@
 #include <wchar.h>
 #include <locale.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
+
 #include "utils.h"
 
 TEST(stdio_ext, __fbufsize) {
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 54b913a..e9ec499 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -31,8 +31,9 @@
 #include <string>
 #include <vector>
 
+#include <android-base/file.h>
+
 #include "BionicDeathTest.h"
-#include "TemporaryFile.h"
 #include "utils.h"
 
 #if defined(NOFORTIFY)
@@ -1412,7 +1413,7 @@
   fflush(fp);
   fclose(fp);
 
-  fp = fopen(tf.filename, "r");
+  fp = fopen(tf.path, "r");
   ASSERT_TRUE(fp != nullptr);
 
   // Store a valid position.
@@ -2041,7 +2042,7 @@
 TEST(STDIO_TEST, fread_after_fseek) {
   TemporaryFile tf;
 
-  FILE* fp = fopen(tf.filename, "w+");
+  FILE* fp = fopen(tf.path, "w+");
   ASSERT_TRUE(fp != nullptr);
 
   char file_data[12288];
@@ -2051,7 +2052,7 @@
   ASSERT_EQ(12288U, fwrite(file_data, 1, 12288, fp));
   fclose(fp);
 
-  fp = fopen(tf.filename, "r");
+  fp = fopen(tf.path, "r");
   ASSERT_TRUE(fp != nullptr);
 
   char buffer[8192];
@@ -2080,10 +2081,10 @@
   TemporaryFile tf;
   char buf[6] = {0};
 
-  FILE* fw = fopen(tf.filename, "w");
+  FILE* fw = fopen(tf.path, "w");
   ASSERT_TRUE(fw != nullptr);
 
-  FILE* fr = fopen(tf.filename, "r");
+  FILE* fr = fopen(tf.path, "r");
   ASSERT_TRUE(fr != nullptr);
 
   fwrite("a", 1, 1, fw);
@@ -2197,7 +2198,7 @@
   for (size_t i = 0; i < 256; ++i) {
     TemporaryFile* tf = new TemporaryFile;
     tfs.push_back(tf);
-    FILE* fp = fopen(tf->filename, "w+");
+    FILE* fp = fopen(tf->path, "w+");
     fps.push_back(fp);
     fprintf(fp, "hello %zu!\n", i);
     fflush(fp);
@@ -2313,21 +2314,21 @@
   struct stat sb;
 
   TemporaryFile tf;
-  ASSERT_EQ(0, remove(tf.filename));
-  ASSERT_EQ(-1, lstat(tf.filename, &sb));
+  ASSERT_EQ(0, remove(tf.path));
+  ASSERT_EQ(-1, lstat(tf.path, &sb));
   ASSERT_EQ(ENOENT, errno);
 
   TemporaryDir td;
-  ASSERT_EQ(0, remove(td.dirname));
-  ASSERT_EQ(-1, lstat(td.dirname, &sb));
+  ASSERT_EQ(0, remove(td.path));
+  ASSERT_EQ(-1, lstat(td.path, &sb));
   ASSERT_EQ(ENOENT, errno);
 
   errno = 0;
-  ASSERT_EQ(-1, remove(tf.filename));
+  ASSERT_EQ(-1, remove(tf.path));
   ASSERT_EQ(ENOENT, errno);
 
   errno = 0;
-  ASSERT_EQ(-1, remove(td.dirname));
+  ASSERT_EQ(-1, remove(td.path));
   ASSERT_EQ(ENOENT, errno);
 }
 
@@ -2404,8 +2405,8 @@
 
 TEST(STDIO_TEST, fopen_append_mode_and_ftell) {
   TemporaryFile tf;
-  SetFileTo(tf.filename, "0123456789");
-  FILE* fp = fopen(tf.filename, "a");
+  SetFileTo(tf.path, "0123456789");
+  FILE* fp = fopen(tf.path, "a");
   EXPECT_EQ(10, ftell(fp));
   ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
   EXPECT_EQ(2, ftell(fp));
@@ -2415,13 +2416,13 @@
   ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
   EXPECT_EQ(13, ftell(fp));
   ASSERT_EQ(0, fclose(fp));
-  AssertFileIs(tf.filename, "0123456789xxx");
+  AssertFileIs(tf.path, "0123456789xxx");
 }
 
 TEST(STDIO_TEST, fdopen_append_mode_and_ftell) {
   TemporaryFile tf;
-  SetFileTo(tf.filename, "0123456789");
-  int fd = open(tf.filename, O_RDWR);
+  SetFileTo(tf.path, "0123456789");
+  int fd = open(tf.path, O_RDWR);
   ASSERT_NE(-1, fd);
   // POSIX: "The file position indicator associated with the new stream is set to the position
   // indicated by the file offset associated with the file descriptor."
@@ -2436,14 +2437,14 @@
   ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
   EXPECT_EQ(13, ftell(fp));
   ASSERT_EQ(0, fclose(fp));
-  AssertFileIs(tf.filename, "0123456789xxx");
+  AssertFileIs(tf.path, "0123456789xxx");
 }
 
 TEST(STDIO_TEST, freopen_append_mode_and_ftell) {
   TemporaryFile tf;
-  SetFileTo(tf.filename, "0123456789");
+  SetFileTo(tf.path, "0123456789");
   FILE* other_fp = fopen("/proc/version", "r");
-  FILE* fp = freopen(tf.filename, "a", other_fp);
+  FILE* fp = freopen(tf.path, "a", other_fp);
   EXPECT_EQ(10, ftell(fp));
   ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
   EXPECT_EQ(2, ftell(fp));
@@ -2453,7 +2454,7 @@
   ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
   EXPECT_EQ(13, ftell(fp));
   ASSERT_EQ(0, fclose(fp));
-  AssertFileIs(tf.filename, "0123456789xxx");
+  AssertFileIs(tf.path, "0123456789xxx");
 }
 
 TEST(STDIO_TEST, constants) {
@@ -2476,7 +2477,7 @@
 TEST(STDIO_TEST, unlocked) {
   TemporaryFile tf;
 
-  FILE* fp = fopen(tf.filename, "w+");
+  FILE* fp = fopen(tf.path, "w+");
   ASSERT_TRUE(fp != nullptr);
 
   clearerr_unlocked(fp);
@@ -2521,7 +2522,7 @@
 
 TEST(STDIO_TEST, fseek_64bit) {
   TemporaryFile tf;
-  FILE* fp = fopen64(tf.filename, "w+");
+  FILE* fp = fopen64(tf.path, "w+");
   ASSERT_TRUE(fp != nullptr);
   ASSERT_EQ(0, fseeko64(fp, 0x2'0000'0000, SEEK_SET));
   ASSERT_EQ(0x2'0000'0000, ftello64(fp));
@@ -2534,7 +2535,7 @@
 // isn't representable in long/off_t.
 TEST(STDIO_TEST, fseek_overflow_32bit) {
   TemporaryFile tf;
-  FILE* fp = fopen64(tf.filename, "w+");
+  FILE* fp = fopen64(tf.path, "w+");
   ASSERT_EQ(0, ftruncate64(fileno(fp), 0x2'0000'0000));
 
   // Bionic implements overflow checking for SEEK_CUR, but glibc doesn't.
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 1c3e1d1..00850f6 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -14,13 +14,6 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-
-#include "BionicDeathTest.h"
-#include "math_data_test.h"
-#include "TemporaryFile.h"
-#include "utils.h"
-
 #include <errno.h>
 #include <fcntl.h>
 #include <libgen.h>
@@ -31,10 +24,18 @@
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <unistd.h>
 
 #include <limits>
 #include <string>
 
+#include <android-base/macros.h>
+#include <gtest/gtest.h>
+
+#include "BionicDeathTest.h"
+#include "math_data_test.h"
+#include "utils.h"
+
 #if defined(__BIONIC__)
   #define ALIGNED_ALLOC_AVAILABLE 1
 #elif defined(__GLIBC_PREREQ)
@@ -43,6 +44,41 @@
   #endif
 #endif
 
+template <typename T = int (*)(char*)>
+class GenericTemporaryFile {
+ public:
+  explicit GenericTemporaryFile(T mk_fn = mkstemp) : mk_fn_(mk_fn) {
+    // Since we might be running on the host or the target, and if we're
+    // running on the host we might be running under bionic or glibc,
+    // let's just try both possible temporary directories and take the
+    // first one that works.
+    init("/data/local/tmp");
+    if (fd == -1) {
+      init("/tmp");
+    }
+  }
+
+  ~GenericTemporaryFile() {
+    close(fd);
+    unlink(path);
+  }
+
+  int fd;
+  char path[1024];
+
+ private:
+  T mk_fn_;
+
+  void init(const char* tmp_dir) {
+    snprintf(path, sizeof(path), "%s/TemporaryFile-XXXXXX", tmp_dir);
+    fd = mk_fn_(path);
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(GenericTemporaryFile);
+};
+
+typedef GenericTemporaryFile<> MyTemporaryFile;
+
 // 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.
@@ -191,6 +227,7 @@
 }
 
 TEST(stdlib, posix_memalign_sweep) {
+  SKIP_WITH_HWASAN;
   void* ptr;
 
   // These should all fail.
@@ -230,11 +267,13 @@
 }
 
 TEST(stdlib, posix_memalign_overflow) {
+  SKIP_WITH_HWASAN;
   void* ptr;
   ASSERT_NE(0, posix_memalign(&ptr, 16, SIZE_MAX));
 }
 
 TEST(stdlib, aligned_alloc_sweep) {
+  SKIP_WITH_HWASAN;
 #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.
@@ -259,6 +298,7 @@
 }
 
 TEST(stdlib, aligned_alloc_overflow) {
+  SKIP_WITH_HWASAN;
 #if defined(ALIGNED_ALLOC_AVAILABLE)
   ASSERT_TRUE(aligned_alloc(16, SIZE_MAX) == nullptr);
 #else
@@ -267,6 +307,7 @@
 }
 
 TEST(stdlib, aligned_alloc_size_not_multiple_of_alignment) {
+  SKIP_WITH_HWASAN;
 #if defined(ALIGNED_ALLOC_AVAILABLE)
   for (size_t size = 1; size <= 2048; size++) {
     void* ptr = aligned_alloc(2048, size);
@@ -379,24 +420,24 @@
 }
 
 TEST(stdlib, mkostemp64) {
-  TemporaryFile tf([](char* path) { return mkostemp64(path, O_CLOEXEC); });
+  MyTemporaryFile tf([](char* path) { return mkostemp64(path, O_CLOEXEC); });
   AssertCloseOnExec(tf.fd, true);
 }
 
 TEST(stdlib, mkostemp) {
-  TemporaryFile tf([](char* path) { return mkostemp(path, O_CLOEXEC); });
+  MyTemporaryFile tf([](char* path) { return mkostemp(path, O_CLOEXEC); });
   AssertCloseOnExec(tf.fd, true);
 }
 
 TEST(stdlib, mkstemp64) {
-  TemporaryFile tf(mkstemp64);
+  MyTemporaryFile tf(mkstemp64);
   struct stat64 sb;
   ASSERT_EQ(0, fstat64(tf.fd, &sb));
   ASSERT_EQ(O_LARGEFILE, fcntl(tf.fd, F_GETFL) & O_LARGEFILE);
 }
 
 TEST(stdlib, mkstemp) {
-  TemporaryFile tf;
+  MyTemporaryFile tf(mkstemp);
   struct stat sb;
   ASSERT_EQ(0, fstat(tf.fd, &sb));
 }
diff --git a/tests/sys_mman_test.cpp b/tests/sys_mman_test.cpp
index 22dc383..0b98198 100644
--- a/tests/sys_mman_test.cpp
+++ b/tests/sys_mman_test.cpp
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-
+#include <fcntl.h>
 #include <sys/mman.h>
 #include <sys/user.h>
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
+#include <gtest/gtest.h>
 
 TEST(sys_mman, mmap_std) {
   void* map = mmap(nullptr, 4096, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
@@ -82,7 +82,7 @@
 
   ASSERT_EQ(0, munmap(map, sizeof(STRING_MSG)));
 
-  tf.reopen();
+  tf.fd = open(tf.path, O_RDWR);
   char buf[sizeof(STRING_MSG)];
   memset(buf, 0, sizeof(STRING_MSG));
   ASSERT_EQ(STR_SSIZE(STRING_MSG), read(tf.fd, buf, sizeof(STRING_MSG)));
@@ -153,7 +153,7 @@
   memcpy(map, NEWPAGE1_MSG, sizeof(NEWPAGE1_MSG));
   ASSERT_EQ(0, munmap(map, pagesize));
 
-  tf.reopen();
+  tf.fd = open(tf.path, O_RDWR);
   map = mmap(nullptr, pagesize, PROT_WRITE, MAP_SHARED, tf.fd, 2 * pagesize);
   ASSERT_NE(MAP_FAILED, map);
   close(tf.fd);
@@ -161,7 +161,7 @@
   memcpy(map, NEWPAGE2_MSG, sizeof(NEWPAGE2_MSG));
   ASSERT_EQ(0, munmap(map, pagesize));
 
-  tf.reopen();
+  tf.fd = open(tf.path, O_RDWR);
   char buf[pagesize];
   ASSERT_EQ(static_cast<ssize_t>(pagesize), read(tf.fd, buf, pagesize));
   ASSERT_STREQ(PAGE0_MSG, buf);
diff --git a/tests/sys_msg_test.cpp b/tests/sys_msg_test.cpp
index 4eb5a14..8b3623e 100644
--- a/tests/sys_msg_test.cpp
+++ b/tests/sys_msg_test.cpp
@@ -31,7 +31,7 @@
 #include <errno.h>
 #include <sys/msg.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
 
 TEST(sys_msg, smoke) {
   if (msgctl(-1, IPC_STAT, nullptr) == -1 && errno == ENOSYS) {
@@ -41,7 +41,7 @@
 
   // Create a queue.
   TemporaryDir dir;
-  key_t key = ftok(dir.dirname, 1);
+  key_t key = ftok(dir.path, 1);
   int id = msgget(key, IPC_CREAT|0666);
   ASSERT_NE(id, -1);
 
diff --git a/tests/sys_sem_test.cpp b/tests/sys_sem_test.cpp
index eaf2b8f..dff34c8 100644
--- a/tests/sys_sem_test.cpp
+++ b/tests/sys_sem_test.cpp
@@ -31,7 +31,7 @@
 #include <errno.h>
 #include <sys/sem.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
 
 TEST(sys_sem, smoke) {
   if (semctl(-1, 0, IPC_RMID) == -1 && errno == ENOSYS) {
@@ -41,7 +41,7 @@
 
   // Create a semaphore.
   TemporaryDir dir;
-  key_t key = ftok(dir.dirname, 1);
+  key_t key = ftok(dir.path, 1);
   int id = semget(key, 1, IPC_CREAT|0666);
   ASSERT_NE(id, -1);
 
diff --git a/tests/sys_sendfile_test.cpp b/tests/sys_sendfile_test.cpp
index 3d6b5cc..4cddd0d 100644
--- a/tests/sys_sendfile_test.cpp
+++ b/tests/sys_sendfile_test.cpp
@@ -14,14 +14,15 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-#include "TemporaryFile.h"
 
-#include <sys/sendfile.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
 #include <errno.h>
+#include <fcntl.h>
+#include <sys/sendfile.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <android-base/file.h>
+#include <gtest/gtest.h>
 
 TEST(sys_sendfile, sendfile) {
   TemporaryFile src_file;
diff --git a/tests/sys_shm_test.cpp b/tests/sys_shm_test.cpp
index ca2d01a..15abe05 100644
--- a/tests/sys_shm_test.cpp
+++ b/tests/sys_shm_test.cpp
@@ -26,12 +26,11 @@
  * SUCH DAMAGE.
  */
 
-#include <gtest/gtest.h>
-
 #include <errno.h>
 #include <sys/shm.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
+#include <gtest/gtest.h>
 
 TEST(sys_shm, smoke) {
   if (shmctl(-1, IPC_STAT, nullptr) == -1 && errno == ENOSYS) {
@@ -41,7 +40,7 @@
 
   // Create a segment.
   TemporaryDir dir;
-  key_t key = ftok(dir.dirname, 1);
+  key_t key = ftok(dir.path, 1);
   int id = shmget(key, 1234, IPC_CREAT|0666);
   ASSERT_NE(id, -1);
 
diff --git a/tests/sys_stat_test.cpp b/tests/sys_stat_test.cpp
index c0a576d..70ad451 100644
--- a/tests/sys_stat_test.cpp
+++ b/tests/sys_stat_test.cpp
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-
 #include <errno.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
+#include <gtest/gtest.h>
 
 TEST(sys_stat, futimens) {
   FILE* fp = tmpfile();
@@ -73,7 +72,7 @@
     std::string path;
     {
       TemporaryFile tf;
-      path = tf.filename;
+      path = tf.path;
     }
 
     ASSERT_EQ(0, mkfifo(path.c_str(), 0666));
@@ -148,19 +147,19 @@
 TEST(sys_stat, fchmodat_file) {
   TemporaryFile tf;
 
-  ASSERT_EQ(0, fchmodat(AT_FDCWD, tf.filename, 0751, 0));
-  AssertFileModeEquals(0751, tf.filename);
+  ASSERT_EQ(0, fchmodat(AT_FDCWD, tf.path, 0751, 0));
+  AssertFileModeEquals(0751, tf.path);
 }
 
 TEST(sys_stat, fchmodat_AT_SYMLINK_NOFOLLOW_file) {
   TemporaryFile tf;
   errno = 0;
-  int result = fchmodat(AT_FDCWD, tf.filename, 0751, AT_SYMLINK_NOFOLLOW);
+  int result = fchmodat(AT_FDCWD, tf.path, 0751, AT_SYMLINK_NOFOLLOW);
 
 #if defined(__BIONIC__)
   ASSERT_EQ(0, result);
   ASSERT_EQ(0, errno);
-  AssertFileModeEquals(0751, tf.filename);
+  AssertFileModeEquals(0751, tf.path);
 #else
   // glibc 2.19 does not implement AT_SYMLINK_NOFOLLOW and always
   // returns ENOTSUP
@@ -173,11 +172,11 @@
   TemporaryFile tf;
   char linkname[255];
 
-  snprintf(linkname, sizeof(linkname), "%s.link", tf.filename);
+  snprintf(linkname, sizeof(linkname), "%s.link", tf.path);
 
-  ASSERT_EQ(0, symlink(tf.filename, linkname));
+  ASSERT_EQ(0, symlink(tf.path, linkname));
   ASSERT_EQ(0, fchmodat(AT_FDCWD, linkname, 0751, 0));
-  AssertFileModeEquals(0751, tf.filename);
+  AssertFileModeEquals(0751, tf.path);
   unlink(linkname);
 }
 
@@ -186,8 +185,8 @@
   char linkname[255];
   char target[255];
 
-  snprintf(linkname, sizeof(linkname), "%s.link", tf.filename);
-  snprintf(target, sizeof(target), "%s.doesnotexist", tf.filename);
+  snprintf(linkname, sizeof(linkname), "%s.link", tf.path);
+  snprintf(target, sizeof(target), "%s.doesnotexist", tf.path);
 
   ASSERT_EQ(0, symlink(target, linkname));
   ASSERT_EQ(-1, fchmodat(AT_FDCWD, linkname, 0751, 0));
@@ -205,12 +204,12 @@
 TEST(sys_stat, fchmodat_AT_SYMLINK_NOFOLLOW_with_symlink) {
   TemporaryFile tf;
   struct stat tf_sb;
-  ASSERT_EQ(0, stat(tf.filename, &tf_sb));
+  ASSERT_EQ(0, stat(tf.path, &tf_sb));
 
   char linkname[255];
-  snprintf(linkname, sizeof(linkname), "%s.link", tf.filename);
+  snprintf(linkname, sizeof(linkname), "%s.link", tf.path);
 
-  ASSERT_EQ(0, symlink(tf.filename, linkname));
+  ASSERT_EQ(0, symlink(tf.path, linkname));
   int result = fchmodat(AT_FDCWD, linkname, 0751, AT_SYMLINK_NOFOLLOW);
   // It depends on the kernel whether chmod operation on symlink is allowed.
   if (result == 0) {
@@ -221,7 +220,7 @@
   }
 
   // Target file mode shouldn't be modified.
-  AssertFileModeEquals(tf_sb.st_mode, tf.filename);
+  AssertFileModeEquals(tf_sb.st_mode, tf.path);
   unlink(linkname);
 }
 
@@ -230,8 +229,8 @@
 
   char linkname[255];
   char target[255];
-  snprintf(linkname, sizeof(linkname), "%s.link", tf.filename);
-  snprintf(target, sizeof(target), "%s.doesnotexist", tf.filename);
+  snprintf(linkname, sizeof(linkname), "%s.link", tf.path);
+  snprintf(target, sizeof(target), "%s.doesnotexist", tf.path);
 
   ASSERT_EQ(0, symlink(target, linkname));
   int result = fchmodat(AT_FDCWD, linkname, 0751, AT_SYMLINK_NOFOLLOW);
diff --git a/tests/sys_time_test.cpp b/tests/sys_time_test.cpp
index b3ec161..16187eb 100644
--- a/tests/sys_time_test.cpp
+++ b/tests/sys_time_test.cpp
@@ -17,15 +17,16 @@
 #include <gtest/gtest.h>
 
 #include <errno.h>
+#include <fcntl.h>
 #include <sys/syscall.h>
 #include <sys/time.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
 
 // http://b/11383777
 TEST(sys_time, utimes_nullptr) {
   TemporaryFile tf;
-  ASSERT_EQ(0, utimes(tf.filename, nullptr));
+  ASSERT_EQ(0, utimes(tf.path, nullptr));
 }
 
 TEST(sys_time, utimes_EINVAL) {
@@ -34,19 +35,19 @@
   timeval tv[2] = {};
 
   tv[0].tv_usec = -123;
-  ASSERT_EQ(-1, utimes(tf.filename, tv));
+  ASSERT_EQ(-1, utimes(tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
   tv[0].tv_usec = 1234567;
-  ASSERT_EQ(-1, utimes(tf.filename, tv));
+  ASSERT_EQ(-1, utimes(tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
 
   tv[0].tv_usec = 0;
 
   tv[1].tv_usec = -123;
-  ASSERT_EQ(-1, utimes(tf.filename, tv));
+  ASSERT_EQ(-1, utimes(tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
   tv[1].tv_usec = 1234567;
-  ASSERT_EQ(-1, utimes(tf.filename, tv));
+  ASSERT_EQ(-1, utimes(tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
 }
 
@@ -79,7 +80,7 @@
 
 TEST(sys_time, futimesat_nullptr) {
   TemporaryFile tf;
-  ASSERT_EQ(0, futimesat(AT_FDCWD, tf.filename, nullptr));
+  ASSERT_EQ(0, futimesat(AT_FDCWD, tf.path, nullptr));
 }
 
 TEST(sys_time, futimesat_EINVAL) {
@@ -88,25 +89,25 @@
   timeval tv[2] = {};
 
   tv[0].tv_usec = -123;
-  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.filename, tv));
+  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
   tv[0].tv_usec = 1234567;
-  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.filename, tv));
+  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
 
   tv[0].tv_usec = 0;
 
   tv[1].tv_usec = -123;
-  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.filename, tv));
+  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
   tv[1].tv_usec = 1234567;
-  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.filename, tv));
+  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
 }
 
 TEST(sys_time, lutimes_nullptr) {
   TemporaryFile tf;
-  ASSERT_EQ(0, lutimes(tf.filename, nullptr));
+  ASSERT_EQ(0, lutimes(tf.path, nullptr));
 }
 
 TEST(sys_time, lutimes_EINVAL) {
@@ -115,19 +116,19 @@
   timeval tv[2] = {};
 
   tv[0].tv_usec = -123;
-  ASSERT_EQ(-1, lutimes(tf.filename, tv));
+  ASSERT_EQ(-1, lutimes(tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
   tv[0].tv_usec = 1234567;
-  ASSERT_EQ(-1, lutimes(tf.filename, tv));
+  ASSERT_EQ(-1, lutimes(tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
 
   tv[0].tv_usec = 0;
 
   tv[1].tv_usec = -123;
-  ASSERT_EQ(-1, lutimes(tf.filename, tv));
+  ASSERT_EQ(-1, lutimes(tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
   tv[1].tv_usec = 1234567;
-  ASSERT_EQ(-1, lutimes(tf.filename, tv));
+  ASSERT_EQ(-1, lutimes(tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
 }
 
diff --git a/tests/sys_uio_test.cpp b/tests/sys_uio_test.cpp
index 60bd224..8460041 100644
--- a/tests/sys_uio_test.cpp
+++ b/tests/sys_uio_test.cpp
@@ -18,7 +18,7 @@
 
 #include <sys/uio.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
 
 TEST(sys_uio, readv_writev) {
   TemporaryFile tf;
diff --git a/tests/sys_xattr_test.cpp b/tests/sys_xattr_test.cpp
index 006e840..8f4a336 100644
--- a/tests/sys_xattr_test.cpp
+++ b/tests/sys_xattr_test.cpp
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-
+#include <fcntl.h>
 #include <sys/types.h>
 #include <sys/xattr.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
+#include <gtest/gtest.h>
 
 TEST(sys_xattr, setxattr) {
   TemporaryFile tf;
   char buf[10];
-  ASSERT_EQ(0, setxattr(tf.filename, "user.foo", "bar", 4, 0));
-  ASSERT_EQ(4, getxattr(tf.filename, "user.foo", buf, sizeof(buf)));
+  ASSERT_EQ(0, setxattr(tf.path, "user.foo", "bar", 4, 0));
+  ASSERT_EQ(4, getxattr(tf.path, "user.foo", buf, sizeof(buf)));
   ASSERT_STREQ("bar", buf);
   buf[0] = '\0';
-  ASSERT_EQ(4, lgetxattr(tf.filename, "user.foo", buf, sizeof(buf)));
+  ASSERT_EQ(4, lgetxattr(tf.path, "user.foo", buf, sizeof(buf)));
   ASSERT_STREQ("bar", buf);
 }
 
@@ -67,7 +67,7 @@
 
 TEST(sys_xattr, fsetxattr_with_opath) {
   TemporaryFile tf;
-  int fd = open(tf.filename, O_PATH);
+  int fd = open(tf.path, O_PATH);
   ASSERT_NE(-1, fd);
 
   int res = fsetxattr(fd, "user.foo", "bar", 4, 0);
@@ -85,7 +85,7 @@
 
 TEST(sys_xattr, fsetxattr_with_opath_toosmall) {
   TemporaryFile tf;
-  int fd = open(tf.filename, O_PATH);
+  int fd = open(tf.path, O_PATH);
   ASSERT_NE(-1, fd);
 
   int res = fsetxattr(fd, "user.foo", "01234567890123456789", 21, 0);
@@ -114,7 +114,7 @@
   TemporaryFile tf;
   char buf[65536];  // 64kB is max possible xattr list size. See "man 7 xattr".
   ASSERT_EQ(0, fsetxattr(tf.fd, "user.foo", "bar", 4, 0));
-  int fd = open(tf.filename, O_PATH);
+  int fd = open(tf.path, O_PATH);
   ASSERT_NE(-1, fd);
   ssize_t res = flistxattr(fd, buf, sizeof(buf));
 #if defined(__BIONIC__)
diff --git a/tests/system_properties_test.cpp b/tests/system_properties_test.cpp
index 949019f..3b50896 100644
--- a/tests/system_properties_test.cpp
+++ b/tests/system_properties_test.cpp
@@ -24,7 +24,7 @@
 #include <string>
 #include <thread>
 
-#include <android-base/test_utils.h>
+#include <android-base/file.h>
 
 using namespace std::literals;
 
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index e82f15d..4ec5976 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -488,23 +488,6 @@
   ASSERT_EQ(EINVAL, errno);
 }
 
-TEST(time, timer_delete_multiple) {
-  timer_t timer_id;
-  ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, nullptr, &timer_id));
-  ASSERT_EQ(0, timer_delete(timer_id));
-  ASSERT_EQ(-1, timer_delete(timer_id));
-  ASSERT_EQ(EINVAL, errno);
-
-  sigevent_t se;
-  memset(&se, 0, sizeof(se));
-  se.sigev_notify = SIGEV_THREAD;
-  se.sigev_notify_function = NoOpNotifyFunction;
-  ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
-  ASSERT_EQ(0, timer_delete(timer_id));
-  ASSERT_EQ(-1, timer_delete(timer_id));
-  ASSERT_EQ(EINVAL, errno);
-}
-
 TEST(time, timer_create_multiple) {
   Counter counter1(Counter::CountNotifyFunction);
   Counter counter2(Counter::CountNotifyFunction);
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index da083de..f4a7f1f 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -18,7 +18,6 @@
 
 #include "BionicDeathTest.h"
 #include "SignalUtils.h"
-#include "TemporaryFile.h"
 #include "utils.h"
 
 #include <errno.h>
@@ -166,20 +165,20 @@
 TEST(UNISTD_TEST, truncate) {
   TemporaryFile tf;
   ASSERT_EQ(0, close(tf.fd));
-  ASSERT_EQ(0, truncate(tf.filename, 123));
+  ASSERT_EQ(0, truncate(tf.path, 123));
 
   struct stat sb;
-  ASSERT_EQ(0, stat(tf.filename, &sb));
+  ASSERT_EQ(0, stat(tf.path, &sb));
   ASSERT_EQ(123, sb.st_size);
 }
 
 TEST(UNISTD_TEST, truncate64) {
   TemporaryFile tf;
   ASSERT_EQ(0, close(tf.fd));
-  ASSERT_EQ(0, truncate64(tf.filename, 123));
+  ASSERT_EQ(0, truncate64(tf.path, 123));
 
   struct stat sb;
-  ASSERT_EQ(0, stat(tf.filename, &sb));
+  ASSERT_EQ(0, stat(tf.path, &sb));
   ASSERT_EQ(123, sb.st_size);
 }
 
@@ -189,7 +188,7 @@
   ASSERT_EQ(0, close(tf.fd));
 
   struct stat sb;
-  ASSERT_EQ(0, stat(tf.filename, &sb));
+  ASSERT_EQ(0, stat(tf.path, &sb));
   ASSERT_EQ(123, sb.st_size);
 }
 
@@ -199,7 +198,7 @@
   ASSERT_EQ(0, close(tf.fd));
 
   struct stat sb;
-  ASSERT_EQ(0, stat(tf.filename, &sb));
+  ASSERT_EQ(0, stat(tf.path, &sb));
   ASSERT_EQ(123, sb.st_size);
 }
 
@@ -389,11 +388,11 @@
 
   EXPECT_EQ(0, fn(tf.fd));
 
-  ASSERT_NE(-1, fd = open(tf.filename, O_RDONLY));
+  ASSERT_NE(-1, fd = open(tf.path, O_RDONLY));
   EXPECT_EQ(0, fn(fd));
   close(fd);
 
-  ASSERT_NE(-1, fd = open(tf.filename, O_RDWR));
+  ASSERT_NE(-1, fd = open(tf.path, O_RDWR));
   EXPECT_EQ(0, fn(fd));
   close(fd);
 
@@ -671,11 +670,11 @@
   long rc = 0L;
   // As a file system's block size is always power of 2, the configure values
   // for ALLOC and XFER should be power of 2 as well.
-  rc = pathconf(tf.filename, _PC_ALLOC_SIZE_MIN);
+  rc = pathconf(tf.path, _PC_ALLOC_SIZE_MIN);
   ASSERT_TRUE(rc > 0 && powerof2(rc));
-  rc = pathconf(tf.filename, _PC_REC_MIN_XFER_SIZE);
+  rc = pathconf(tf.path, _PC_REC_MIN_XFER_SIZE);
   ASSERT_TRUE(rc > 0 && powerof2(rc));
-  rc = pathconf(tf.filename, _PC_REC_XFER_ALIGN);
+  rc = pathconf(tf.path, _PC_REC_XFER_ALIGN);
   ASSERT_TRUE(rc > 0 && powerof2(rc));
 
   rc = fpathconf(tf.fd, _PC_ALLOC_SIZE_MIN);
@@ -1343,38 +1342,38 @@
 TEST(UNISTD_TEST, execvpe_ENOEXEC) {
   // Create a shell script with #!.
   TemporaryFile tf;
-  ASSERT_TRUE(android::base::WriteStringToFile("#!" BIN_DIR "sh\necho script\n", tf.filename));
+  ASSERT_TRUE(android::base::WriteStringToFile("#!" BIN_DIR "sh\necho script\n", tf.path));
 
   // Set $PATH so we can find it.
-  setenv("PATH", dirname(tf.filename), 1);
+  setenv("PATH", dirname(tf.path), 1);
 
   ExecTestHelper eth;
-  eth.SetArgs({basename(tf.filename), nullptr});
+  eth.SetArgs({basename(tf.path), nullptr});
 
   // It's not inherently executable.
   errno = 0;
-  ASSERT_EQ(-1, execvpe(basename(tf.filename), eth.GetArgs(), eth.GetEnv()));
+  ASSERT_EQ(-1, execvpe(basename(tf.path), eth.GetArgs(), eth.GetEnv()));
   ASSERT_EQ(EACCES, errno);
 
   // Make it executable (and keep it writable because we're going to rewrite it below).
-  ASSERT_EQ(0, chmod(tf.filename, 0777));
+  ASSERT_EQ(0, chmod(tf.path, 0777));
 
   // TemporaryFile will have a writable fd, so we can test ETXTBSY while we're here...
   errno = 0;
-  ASSERT_EQ(-1, execvpe(basename(tf.filename), eth.GetArgs(), eth.GetEnv()));
+  ASSERT_EQ(-1, execvpe(basename(tf.path), eth.GetArgs(), eth.GetEnv()));
   ASSERT_EQ(ETXTBSY, errno);
 
   // 1. The simplest test: the kernel should handle this.
   ASSERT_EQ(0, close(tf.fd));
-  eth.Run([&]() { execvpe(basename(tf.filename), eth.GetArgs(), eth.GetEnv()); }, 0, "script\n");
+  eth.Run([&]() { execvpe(basename(tf.path), eth.GetArgs(), eth.GetEnv()); }, 0, "script\n");
 
   // 2. Try again without a #!. We should have to handle this ourselves.
-  ASSERT_TRUE(android::base::WriteStringToFile("echo script\n", tf.filename));
-  eth.Run([&]() { execvpe(basename(tf.filename), eth.GetArgs(), eth.GetEnv()); }, 0, "script\n");
+  ASSERT_TRUE(android::base::WriteStringToFile("echo script\n", tf.path));
+  eth.Run([&]() { execvpe(basename(tf.path), eth.GetArgs(), eth.GetEnv()); }, 0, "script\n");
 
   // 3. Again without a #!, but also with a leading '/', since that's a special case in the
   // implementation.
-  eth.Run([&]() { execvpe(tf.filename, eth.GetArgs(), eth.GetEnv()); }, 0, "script\n");
+  eth.Run([&]() { execvpe(tf.path, eth.GetArgs(), eth.GetEnv()); }, 0, "script\n");
 }
 
 TEST(UNISTD_TEST, execvp_libcore_test_55017) {
diff --git a/tests/utils.h b/tests/utils.h
index c8656dc..5fc1d93 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -58,6 +58,14 @@
   return (dlopen("libc.so", 0) != nullptr);
 }
 
+extern "C" void __hwasan_init() __attribute__((weak));
+
+static inline bool running_with_hwasan() {
+  return &__hwasan_init != 0;
+}
+
+#define SKIP_WITH_HWASAN if (running_with_hwasan()) { return; }
+
 #if defined(__linux__)
 
 #include <sys/sysmacros.h>
diff --git a/tools/versioner/README.md b/tools/versioner/README.md
index 39b5128..edb32be 100644
--- a/tools/versioner/README.md
+++ b/tools/versioner/README.md
@@ -2,7 +2,7 @@
 Use clang to verify the correctness of bionic's availability attributes against the NDK platform definitions.
 
 #### Build
-Build with `FORCE_BUILD_LLVM_COMPONENTS=true mma -j48`
+Build with `LLVM_BUILD_HOST_TOOLS=true mma -j48`
 
 #### Use
 `versioner -p platforms current dependencies`
diff --git a/tools/versioner/platforms/crtbegin.map.txt b/tools/versioner/platforms/crtbegin.map.txt
new file mode 100644
index 0000000..2c08da6
--- /dev/null
+++ b/tools/versioner/platforms/crtbegin.map.txt
@@ -0,0 +1,7 @@
+# This file lists the libc functions are included in `crtbegin.o` and not
+# exported by `libc.so`.
+
+CRTBEGIN {
+  global:
+    atexit;  # arm64 x86 x86_64 mips mips64
+};
diff --git a/tools/versioner/platforms/libc.map.txt b/tools/versioner/platforms/libc.map.txt
new file mode 120000
index 0000000..8527b2e
--- /dev/null
+++ b/tools/versioner/platforms/libc.map.txt
@@ -0,0 +1 @@
+../../../libc/libc.map.txt
\ No newline at end of file
diff --git a/tools/versioner/src/Android.bp b/tools/versioner/src/Android.bp
index f138cc3..59e1b92 100644
--- a/tools/versioner/src/Android.bp
+++ b/tools/versioner/src/Android.bp
@@ -1,6 +1,8 @@
 cc_binary_host {
     name: "versioner",
 
+    defaults: ["llvm-build-host-tools-defaults"],
+
     cpp_std: "gnu++17",
 
     // b/117120485 bugprone-exception-escape hangs with DeclarationDatabase.cpp
@@ -14,21 +16,17 @@
         "Driver.cpp",
         "Preprocessor.cpp",
         "SymbolDatabase.cpp",
+        "SymbolFileParser.cpp",
         "Utils.cpp",
         "VFS.cpp",
     ],
 
     shared_libs: [
-        "libclang_android",
-        "libLLVM_android",
+        "libclang_cxx_host",
+        "libLLVM_host",
         "libbase",
     ],
 
-    header_libs: [
-        "llvm-headers",
-        "clang-headers",
-    ],
-
     cflags: [
         "-Wall",
         "-Wextra",
diff --git a/tools/versioner/src/Arch.cpp b/tools/versioner/src/Arch.cpp
index 8d1d41e..4cd9e07 100644
--- a/tools/versioner/src/Arch.cpp
+++ b/tools/versioner/src/Arch.cpp
@@ -44,20 +44,19 @@
   errx(1, "unknown arch '%zu'", size_t(arch));
 }
 
-Arch arch_from_string(const std::string& name) {
-  if (name == "arm") {
-    return Arch::arm;
-  } else if (name == "arm64") {
-    return Arch::arm64;
-  } else if (name == "mips") {
-    return Arch::mips;
-  } else if (name == "mips64") {
-    return Arch::mips64;
-  } else if (name == "x86") {
-    return Arch::x86;
-  } else if (name == "x86_64") {
-    return Arch::x86_64;
-  }
+static const std::unordered_map<std::string, Arch> arch_name_map{
+  {"arm", Arch::arm},
+  {"arm64", Arch::arm64},
+  {"mips", Arch::mips},
+  {"mips64", Arch::mips64},
+  {"x86", Arch::x86},
+  {"x86_64", Arch::x86_64},
+};
 
-  errx(1, "unknown architecture '%s'", name.c_str());
+std::optional<Arch> arch_from_string(const std::string& name) {
+  auto it = arch_name_map.find(name);
+  if (it == arch_name_map.end()) {
+    return std::nullopt;
+  }
+  return std::make_optional(it->second);
 }
diff --git a/tools/versioner/src/Arch.h b/tools/versioner/src/Arch.h
index ab05d5c..bac9ec4 100644
--- a/tools/versioner/src/Arch.h
+++ b/tools/versioner/src/Arch.h
@@ -20,8 +20,10 @@
 
 #include <array>
 #include <initializer_list>
+#include <optional>
 #include <set>
 #include <string>
+#include <unordered_map>
 
 enum class Arch : size_t {
   arm = 0,
@@ -33,7 +35,7 @@
 };
 
 std::string to_string(const Arch& arch);
-Arch arch_from_string(const std::string& name);
+std::optional<Arch> arch_from_string(const std::string& name);
 
 template <typename T>
 class ArchMapIterator;
@@ -136,7 +138,7 @@
   { Arch::x86_64, "x86_64-linux-android" },
 };
 
-static const std::set<int> default_levels = { 14, 15, 16, 17, 18, 19, 21, 23, 24, 25, 26, 27 };
+static const std::set<int> default_levels = { 14, 15, 16, 17, 18, 19, 21, 23, 24, 25, 26, 27, 28 };
 
 static const ArchMap<int> arch_min_api = {
   { Arch::arm, 9 },
@@ -146,3 +148,23 @@
   { Arch::x86, 9 },
   { Arch::x86_64, 21 },
 };
+
+static constexpr int future_api = 10000;
+
+static const std::unordered_map<std::string, int> api_codename_map{
+  {"G", 9},
+  {"I", 14},
+  {"J", 16},
+  {"J-MR1", 17},
+  {"J-MR2", 18},
+  {"K", 19},
+  {"L", 21},
+  {"L-MR1", 22},
+  {"M", 23},
+  {"N", 24},
+  {"N-MR1", 25},
+  {"O", 26},
+  {"O-MR1", 27},
+  {"P", 28},
+  {"Q", 9001},
+};
diff --git a/tools/versioner/src/Driver.cpp b/tools/versioner/src/Driver.cpp
index 8911190..8ba3d42 100644
--- a/tools/versioner/src/Driver.cpp
+++ b/tools/versioner/src/Driver.cpp
@@ -29,7 +29,6 @@
 #include <clang/AST/ASTConsumer.h>
 #include <clang/Basic/Diagnostic.h>
 #include <clang/Basic/TargetInfo.h>
-#include <clang/Basic/VirtualFileSystem.h>
 #include <clang/Driver/Compilation.h>
 #include <clang/Driver/Driver.h>
 #include <clang/Frontend/CompilerInstance.h>
@@ -42,7 +41,7 @@
 #include <llvm/ADT/IntrusiveRefCntPtr.h>
 #include <llvm/ADT/SmallVector.h>
 #include <llvm/ADT/StringRef.h>
-#include <llvm/Config/config.h>
+#include <llvm/Support/VirtualFileSystem.h>
 
 #include "Arch.h"
 #include "DeclarationDatabase.h"
@@ -94,7 +93,7 @@
 // Run it once to generate flags for each target, and memoize the results.
 static std::unordered_map<CompilationType, std::vector<std::string>> cc1_flags;
 static const char* filename_placeholder = "__VERSIONER_PLACEHOLDER__";
-static void generateTargetCC1Flags(llvm::IntrusiveRefCntPtr<clang::vfs::FileSystem> vfs,
+static void generateTargetCC1Flags(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
                                    CompilationType type,
                                    const std::vector<std::string>& include_dirs) {
   std::vector<std::string> cmd = { "versioner" };
@@ -208,7 +207,7 @@
   return result;
 }
 
-void initializeTargetCC1FlagCache(llvm::IntrusiveRefCntPtr<clang::vfs::FileSystem> vfs,
+void initializeTargetCC1FlagCache(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
                                   const std::set<CompilationType>& types,
                                   const std::unordered_map<Arch, CompilationRequirements>& reqs) {
   if (!cc1_flags.empty()) {
@@ -243,7 +242,7 @@
   }
 }
 
-void compileHeader(llvm::IntrusiveRefCntPtr<clang::vfs::FileSystem> vfs,
+void compileHeader(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
                    HeaderDatabase* header_database, CompilationType type,
                    const std::string& filename) {
   auto diags = constructDiags();
@@ -256,13 +255,7 @@
 
   clang::CompilerInstance Compiler;
 
-// Remove the workaround once b/35936936 is fixed.
-#if LLVM_VERSION_MAJOR >= 5
   Compiler.setInvocation(std::move(invocation));
-#else
-  Compiler.setInvocation(invocation.release());
-#endif
-
   Compiler.setDiagnostics(diags.get());
   Compiler.setVirtualFileSystem(vfs);
 
diff --git a/tools/versioner/src/Driver.h b/tools/versioner/src/Driver.h
index 48683e4..99e57ae 100644
--- a/tools/versioner/src/Driver.h
+++ b/tools/versioner/src/Driver.h
@@ -31,10 +31,10 @@
   std::vector<std::string> dependencies;
 };
 
-void initializeTargetCC1FlagCache(llvm::IntrusiveRefCntPtr<clang::vfs::FileSystem> vfs,
+void initializeTargetCC1FlagCache(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
                                   const std::set<CompilationType>& types,
                                   const std::unordered_map<Arch, CompilationRequirements>& reqs);
 
-void compileHeader(llvm::IntrusiveRefCntPtr<clang::vfs::FileSystem> vfs,
+void compileHeader(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
                    HeaderDatabase* header_database, CompilationType type,
                    const std::string& filename);
diff --git a/tools/versioner/src/SymbolDatabase.cpp b/tools/versioner/src/SymbolDatabase.cpp
index 5b8ed5a..c483c0f 100644
--- a/tools/versioner/src/SymbolDatabase.cpp
+++ b/tools/versioner/src/SymbolDatabase.cpp
@@ -16,6 +16,8 @@
 
 #include "SymbolDatabase.h"
 
+#include "SymbolFileParser.h"
+
 #include <err.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -61,3 +63,53 @@
 
   return result;
 }
+
+static std::map<std::string, NdkSymbolType> parsePlatform(const CompilationType& type,
+                                                          const std::string& platform_dir) {
+  static const std::pair<const char*, bool> wanted_files[] = {
+    {"crtbegin.map.txt", false},
+    {"libc.map.txt", true},
+  };
+
+  std::map<std::string, NdkSymbolType> result;
+
+  for (auto&& [filename, required] : wanted_files) {
+    std::string path = platform_dir + "/" + filename;
+
+    std::optional<SymbolMap> symbols = parseSymbolFile(path, type);
+    if (!symbols) {
+      if (required) {
+        errx(1, "error: failed to load: %s", path.c_str());
+      }
+      continue;
+    }
+
+    for (auto&& [symbol_name, symbol_type] : *symbols) {
+      if (symbol_name.empty()) {
+        continue;
+      }
+
+      if (result.count(symbol_name) != 0) {
+        if (strict) {
+          printf("duplicated symbol '%s' in '%s'\n", symbol_name.c_str(), path.c_str());
+        }
+      }
+
+      result[symbol_name] = symbol_type;
+    }
+  }
+
+  return result;
+}
+
+std::optional<NdkSymbolDatabase> parsePlatforms(const std::set<CompilationType>& types,
+                                                const std::string& platform_dir) {
+  NdkSymbolDatabase result;
+  for (const CompilationType& type : types) {
+    std::map<std::string, NdkSymbolType> symbols = parsePlatform(type, platform_dir);
+    for (const auto& it : symbols) {
+      result[it.first][type] = it.second;
+    }
+  }
+  return std::make_optional(std::move(result));
+}
diff --git a/tools/versioner/src/SymbolDatabase.h b/tools/versioner/src/SymbolDatabase.h
index c5b89d7..dbbba4f 100644
--- a/tools/versioner/src/SymbolDatabase.h
+++ b/tools/versioner/src/SymbolDatabase.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <map>
+#include <optional>
 #include <set>
 #include <string>
 #include <unordered_set>
@@ -32,3 +33,5 @@
 };
 
 using NdkSymbolDatabase = std::map<std::string, std::map<CompilationType, NdkSymbolType>>;
+std::optional<NdkSymbolDatabase> parsePlatforms(const std::set<CompilationType>& types,
+                                                const std::string& platform_dir);
diff --git a/tools/versioner/src/SymbolFileParser.cpp b/tools/versioner/src/SymbolFileParser.cpp
new file mode 100644
index 0000000..33308d9
--- /dev/null
+++ b/tools/versioner/src/SymbolFileParser.cpp
@@ -0,0 +1,308 @@
+/*
+ * 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 "SymbolFileParser.h"
+
+#include "Arch.h"
+#include "CompilationType.h"
+
+#include <android-base/strings.h>
+
+#include <fstream>
+#include <ios>
+#include <optional>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <err.h>
+
+namespace {
+
+using TagList = std::vector<std::string>;
+
+struct SymbolEnt {
+  std::string name;
+  TagList tags;
+};
+
+using SymbolList = std::vector<SymbolEnt>;
+
+struct Version {
+  std::string name;
+  std::string base;
+  SymbolList symbols;
+  TagList tags;
+};
+
+class SymbolFileParser {
+ public:
+  SymbolFileParser(const std::string& path, const CompilationType& type)
+    : file_path(path),
+      compilation_type(type),
+      api_level_arch_prefix("api-level-" + to_string(type.arch) + "="),
+      intro_arch_perfix("introduced-" + to_string(type.arch) + "="),
+      file(path, std::ios_base::in),
+      curr_line_num(0) {
+  }
+
+  // Parse the version script and build a symbol map.
+  std::optional<SymbolMap> parse() {
+    if (!file) {
+      return std::nullopt;
+    }
+
+    SymbolMap symbol_map;
+    while (hasNextLine()) {
+      auto&& version = parseVersion();
+      if (!version) {
+        return std::nullopt;
+      }
+
+      if (isInArch(version->tags) && isInApi(version->tags)) {
+        for (auto&& [name, tags] : version->symbols) {
+          if (isInArch(tags) && isInApi(tags)) {
+            symbol_map[name] = getSymbolType(tags);
+          }
+        }
+      }
+    }
+    return std::make_optional(std::move(symbol_map));
+  }
+
+ private:
+  // Read a non-empty line from the input and split at the first '#' character.
+  bool hasNextLine() {
+    std::string line;
+    while (std::getline(file, line)) {
+      ++curr_line_num;
+
+      size_t hash_pos = line.find('#');
+      curr_line = android::base::Trim(line.substr(0, hash_pos));
+      if (!curr_line.empty()) {
+        if (hash_pos != std::string::npos) {
+          curr_tags = parseTags(line.substr(hash_pos + 1));
+        } else {
+          curr_tags.clear();
+        }
+        return true;
+      }
+    }
+    return false;
+  }
+
+  // Tokenize the tags after the '#' character.
+  static std::vector<std::string> parseTags(const std::string& tags_line) {
+    std::vector<std::string> tags = android::base::Split(tags_line, " \t");
+    tags.erase(std::remove(tags.begin(), tags.end(), ""), tags.end());
+    return tags;
+  }
+
+  // Parse a version scope.
+  std::optional<Version> parseVersion() {
+    size_t start_line_num = curr_line_num;
+
+    std::string::size_type lparen_pos = curr_line.find('{');
+    if (lparen_pos == std::string::npos) {
+      errx(1, "%s:%zu: error: expected '{' cannot be found in this line",
+           file_path.c_str(), curr_line_num);
+    }
+
+    // Record the version name and version tags (before hasNextLine()).
+    std::string name = android::base::Trim(curr_line.substr(0, lparen_pos));
+    TagList tags = std::move(curr_tags);
+
+    // Read symbol lines.
+    SymbolList symbols;
+    bool global_scope = true;
+    bool cpp_scope = false;
+    while (hasNextLine()) {
+      size_t rparen_pos = curr_line.find('}');
+      if (rparen_pos != std::string::npos) {
+        size_t semicolon_pos = curr_line.find(';', rparen_pos + 1);
+        if (semicolon_pos == std::string::npos) {
+          errx(1, "%s:%zu: error: the line that ends a scope must end with ';'",
+               file_path.c_str(), curr_line_num);
+        }
+
+        if (cpp_scope) {
+          cpp_scope = false;
+          continue;
+        }
+
+        std::string base = android::base::Trim(
+          curr_line.substr(rparen_pos + 1, semicolon_pos - 1));
+
+        return std::make_optional(Version{std::move(name), std::move(base),
+                                          std::move(symbols), std::move(tags)});
+      }
+
+      if (android::base::StartsWith(curr_line, R"(extern "C++" {)")) {
+        cpp_scope = true;
+        continue;
+      }
+
+      if (cpp_scope) {
+        continue;
+      }
+
+      size_t colon_pos = curr_line.find(':');
+      if (colon_pos != std::string::npos) {
+        std::string visibility =
+          android::base::Trim(curr_line.substr(0, colon_pos));
+
+        if (visibility == "global") {
+          global_scope = true;
+        } else if (visibility == "local") {
+          global_scope = false;
+        } else {
+          errx(1, "%s:%zu: error: unknown version visibility: %s",
+               file_path.c_str(), curr_line_num, visibility.c_str());
+        }
+        continue;
+      }
+
+      if (global_scope) {
+        size_t semicolon_pos = curr_line.find(';');
+        if (semicolon_pos == std::string::npos) {
+          errx(1, "%s:%zu: error: symbol name line must end with ';'",
+               file_path.c_str(), curr_line_num);
+        }
+
+        std::string symbol_name =
+          android::base::Trim(curr_line.substr(0, semicolon_pos));
+
+        size_t asterisk_pos = symbol_name.find('*');
+        if (asterisk_pos != std::string::npos) {
+          errx(1, "%s:%zu: error: global symbol name must not have wildcards",
+               file_path.c_str(), curr_line_num);
+        }
+
+        symbols.push_back(SymbolEnt{std::move(symbol_name),
+                                    std::move(curr_tags)});
+      }
+    }
+
+    errx(1, "%s:%zu: error: scope started from %zu must be closed before EOF",
+         file_path.c_str(), curr_line_num, start_line_num);
+  }
+
+  static NdkSymbolType getSymbolType(const TagList& tags) {
+    for (auto&& tag : tags) {
+      if (tag == "var") {
+        return NdkSymbolType::variable;
+      }
+    }
+    return NdkSymbolType::function;
+  }
+
+  // isInArch() returns true if there is a matching arch-specific tag or there
+  // are no arch-specific tags.
+  bool isInArch(const TagList& tags) const {
+    bool has_arch_tags = false;
+    for (auto&& tag : tags) {
+      std::optional<Arch> arch = arch_from_string(tag);
+      if (!arch) {
+        continue;
+      }
+      if (*arch == compilation_type.arch) {
+        return true;
+      }
+      has_arch_tags = true;
+    }
+    return !has_arch_tags;
+  }
+
+  // isInApi() returns true if the specified API level is equal to the
+  // api-level tag, or the specified API level is greater than or equal to the
+  // introduced tag, or there are no api-level or introduced tags.
+  bool isInApi(const TagList& tags) const {
+    bool api_level_arch = false;
+    bool intro_arch = false;
+    std::string api_level;
+    std::string intro;
+
+    for (const std::string& tag : tags) {
+      // Check api-level tags.
+      if (android::base::StartsWith(tag, "api-level=") && !api_level_arch) {
+        api_level = tag;
+        continue;
+      }
+      if (android::base::StartsWith(tag, api_level_arch_prefix)) {
+        api_level = tag;
+        api_level_arch = true;
+        continue;
+      }
+
+      // Check introduced tags.
+      if (android::base::StartsWith(tag, "introduced=") && !intro_arch) {
+        intro = tag;
+        continue;
+      }
+      if (android::base::StartsWith(tag, intro_arch_perfix)) {
+        intro = tag;
+        intro_arch = true;
+        continue;
+      }
+
+      if (tag == "future") {
+        return compilation_type.api_level == future_api;
+      }
+    }
+
+    if (intro.empty() && api_level.empty()) {
+      return true;
+    }
+
+    if (!api_level.empty()) {
+      // If an api-level tag is specified, it must be an exact match (mainly
+      // for versioner unit tests).
+      return compilation_type.api_level == decodeApiLevelValue(api_level);
+    }
+
+    return compilation_type.api_level >= decodeApiLevelValue(intro);
+  }
+
+  // Extract and decode the integer API level from api-level or introduced tags.
+  static int decodeApiLevelValue(const std::string& tag) {
+    std::string api_level = tag.substr(tag.find('=') + 1);
+    auto it = api_codename_map.find(api_level);
+    if (it != api_codename_map.end()) {
+      return it->second;
+    }
+    return std::stoi(api_level);
+  }
+
+ private:
+  const std::string& file_path;
+  const CompilationType& compilation_type;
+  const std::string api_level_arch_prefix;
+  const std::string intro_arch_perfix;
+
+  std::ifstream file;
+  std::string curr_line;
+  std::vector<std::string> curr_tags;
+  size_t curr_line_num;
+};
+
+}  // anonymous namespace
+
+
+std::optional<SymbolMap> parseSymbolFile(const std::string& file_path,
+                                         const CompilationType& type) {
+  SymbolFileParser parser(file_path, type);
+  return parser.parse();
+}
diff --git a/tools/versioner/src/SymbolFileParser.h b/tools/versioner/src/SymbolFileParser.h
new file mode 100644
index 0000000..5cdbf2f
--- /dev/null
+++ b/tools/versioner/src/SymbolFileParser.h
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <map>
+#include <string>
+#include <optional>
+
+#include "DeclarationDatabase.h"
+#include "SymbolDatabase.h"
+
+using SymbolMap = std::map<std::string, NdkSymbolType>;
+
+std::optional<SymbolMap> parseSymbolFile(const std::string &file,
+                                         const CompilationType& type);
diff --git a/tools/versioner/src/VFS.cpp b/tools/versioner/src/VFS.cpp
index 8f9de88..d797f82 100644
--- a/tools/versioner/src/VFS.cpp
+++ b/tools/versioner/src/VFS.cpp
@@ -25,14 +25,14 @@
 #include <string>
 
 #include <android-base/unique_fd.h>
-#include <clang/Basic/VirtualFileSystem.h>
 #include <llvm/ADT/IntrusiveRefCntPtr.h>
 #include <llvm/Support/MemoryBuffer.h>
+#include <llvm/Support/VirtualFileSystem.h>
 
 #include "Utils.h"
 
 using android::base::unique_fd;
-using namespace clang::vfs;
+using namespace llvm::vfs;
 
 static void addDirectoryToVFS(InMemoryFileSystem* vfs, const std::string& path) {
   char* paths[] = { const_cast<char*>(path.c_str()), nullptr };
diff --git a/tools/versioner/src/VFS.h b/tools/versioner/src/VFS.h
index e2ab002..e4aac75 100644
--- a/tools/versioner/src/VFS.h
+++ b/tools/versioner/src/VFS.h
@@ -20,8 +20,8 @@
 #include <string>
 
 #include <llvm/ADT/IntrusiveRefCntPtr.h>
-#include <clang/Basic/VirtualFileSystem.h>
+#include <llvm/Support/VirtualFileSystem.h>
 
-llvm::IntrusiveRefCntPtr<clang::vfs::FileSystem> createCommonVFS(const std::string& header_dir,
-                                                                 const std::string& dependency_dir,
-                                                                 bool add_versioning_header);
+llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> createCommonVFS(const std::string& header_dir,
+                                                                const std::string& dependency_dir,
+                                                                bool add_versioning_header);
diff --git a/tools/versioner/src/versioner.cpp b/tools/versioner/src/versioner.cpp
index af0c067..73eff0e 100644
--- a/tools/versioner/src/versioner.cpp
+++ b/tools/versioner/src/versioner.cpp
@@ -33,7 +33,6 @@
 #include <iostream>
 #include <map>
 #include <memory>
-#include <optional>
 #include <set>
 #include <sstream>
 #include <string>
@@ -519,8 +518,11 @@
       }
 
       case 'r': {
-        Arch arch = arch_from_string(optarg);
-        selected_architectures.insert(arch);
+        std::optional<Arch> arch = arch_from_string(optarg);
+        if (!arch) {
+          errx(1, "unknown architecture '%s'", optarg);
+        }
+        selected_architectures.insert(*arch);
         break;
       }
 
@@ -613,6 +615,9 @@
     std::string versioner_dir = to_string(top) + "/bionic/tools/versioner";
     location.header_path = versioner_dir + "/current";
     location.dependency_dir = versioner_dir + "/dependencies";
+    if (platform_dir.empty()) {
+      platform_dir = versioner_dir + "/platforms";
+    }
   } else {
     if (!android::base::Realpath(argv[optind], &location.header_path)) {
       err(1, "failed to get realpath for path '%s'", argv[optind]);
@@ -653,6 +658,12 @@
 
   compilation_types = generateCompilationTypes(selected_architectures, selected_levels);
 
+  // Do this before compiling so that we can early exit if the platforms don't match what we
+  // expect.
+  if (!platform_dir.empty()) {
+    symbol_database = parsePlatforms(compilation_types, platform_dir);
+  }
+
   auto start = std::chrono::high_resolution_clock::now();
   std::unique_ptr<HeaderDatabase> declaration_database =
       compileHeaders(compilation_types, location);
diff --git a/tools/versioner/tests/arch_specific/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/arch_specific/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/arch_specific/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/arch_specific/platforms/android-9/arch-x86/symbols/libc.so.functions.txt b/tools/versioner/tests/arch_specific/platforms/android-9/arch-x86/symbols/libc.so.functions.txt
deleted file mode 100644
index 3bd1f0e..0000000
--- a/tools/versioner/tests/arch_specific/platforms/android-9/arch-x86/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-foo
-bar
diff --git a/tools/versioner/tests/arch_specific/platforms/libc.map.txt b/tools/versioner/tests/arch_specific/platforms/libc.map.txt
new file mode 100644
index 0000000..5aa11ed
--- /dev/null
+++ b/tools/versioner/tests/arch_specific/platforms/libc.map.txt
@@ -0,0 +1,5 @@
+LIBC {
+  global:
+    foo;  # arm x86
+    bar;  # x86
+};
diff --git a/tools/versioner/tests/compilation_error/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/compilation_error/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/compilation_error/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/compilation_error/platforms/libc.map.txt b/tools/versioner/tests/compilation_error/platforms/libc.map.txt
new file mode 100644
index 0000000..6cc4a2e
--- /dev/null
+++ b/tools/versioner/tests/compilation_error/platforms/libc.map.txt
@@ -0,0 +1,4 @@
+LIBC {
+  global:
+    foo;
+};
diff --git a/tools/versioner/tests/dependencies/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/dependencies/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/dependencies/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/dependencies/platforms/android-9/arch-x86/symbols/libc.so.functions.txt b/tools/versioner/tests/dependencies/platforms/android-9/arch-x86/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/dependencies/platforms/android-9/arch-x86/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/dependencies/platforms/libc.map.txt b/tools/versioner/tests/dependencies/platforms/libc.map.txt
new file mode 100644
index 0000000..6cc4a2e
--- /dev/null
+++ b/tools/versioner/tests/dependencies/platforms/libc.map.txt
@@ -0,0 +1,4 @@
+LIBC {
+  global:
+    foo;
+};
diff --git a/tools/versioner/tests/extern_cpp/platforms/android-21/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/extern_cpp/platforms/android-21/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 8b13789..0000000
--- a/tools/versioner/tests/extern_cpp/platforms/android-21/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/tools/versioner/tests/extern_cpp/platforms/android-23/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/extern_cpp/platforms/android-23/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 36fe04f..0000000
--- a/tools/versioner/tests/extern_cpp/platforms/android-23/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-__gnu_basename
diff --git a/tools/versioner/tests/extern_cpp/platforms/libc.map.txt b/tools/versioner/tests/extern_cpp/platforms/libc.map.txt
new file mode 100644
index 0000000..297d1fb
--- /dev/null
+++ b/tools/versioner/tests/extern_cpp/platforms/libc.map.txt
@@ -0,0 +1,4 @@
+LIBC {
+  global:
+    __gnu_basename;  # introduced=23
+};
diff --git a/tools/versioner/tests/extern_cpp_mismatch/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/extern_cpp_mismatch/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/extern_cpp_mismatch/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/extern_cpp_mismatch/platforms/libc.map.txt b/tools/versioner/tests/extern_cpp_mismatch/platforms/libc.map.txt
new file mode 100644
index 0000000..6cc4a2e
--- /dev/null
+++ b/tools/versioner/tests/extern_cpp_mismatch/platforms/libc.map.txt
@@ -0,0 +1,4 @@
+LIBC {
+  global:
+    foo;
+};
diff --git a/tools/versioner/tests/future/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/future/platforms/libc.map.txt
similarity index 100%
rename from tools/versioner/tests/future/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
rename to tools/versioner/tests/future/platforms/libc.map.txt
diff --git a/tools/versioner/tests/future_arch/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/future_arch/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/future_arch/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/future_arch/platforms/android-9/arch-x86/symbols/libc.so.functions.txt b/tools/versioner/tests/future_arch/platforms/android-9/arch-x86/symbols/libc.so.functions.txt
deleted file mode 100644
index e69de29..0000000
--- a/tools/versioner/tests/future_arch/platforms/android-9/arch-x86/symbols/libc.so.functions.txt
+++ /dev/null
diff --git a/tools/versioner/tests/future_arch/platforms/libc.map.txt b/tools/versioner/tests/future_arch/platforms/libc.map.txt
new file mode 100644
index 0000000..f56190e
--- /dev/null
+++ b/tools/versioner/tests/future_arch/platforms/libc.map.txt
@@ -0,0 +1,4 @@
+LIBC {
+  global:
+    foo;  # arm
+};
diff --git a/tools/versioner/tests/inline/platforms/android-12/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/inline/platforms/android-12/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/inline/platforms/android-12/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/inline/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/inline/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index e69de29..0000000
--- a/tools/versioner/tests/inline/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
diff --git a/tools/versioner/tests/inline/platforms/libc.map.txt b/tools/versioner/tests/inline/platforms/libc.map.txt
new file mode 100644
index 0000000..4dced92
--- /dev/null
+++ b/tools/versioner/tests/inline/platforms/libc.map.txt
@@ -0,0 +1,4 @@
+LIBC {
+  global:
+    foo;  # introduced=12
+};
diff --git a/tools/versioner/tests/missing_api/platforms/android-12/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/missing_api/platforms/android-12/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index e69de29..0000000
--- a/tools/versioner/tests/missing_api/platforms/android-12/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
diff --git a/tools/versioner/tests/missing_api/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/missing_api/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/missing_api/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/missing_api/platforms/libc.map.txt b/tools/versioner/tests/missing_api/platforms/libc.map.txt
new file mode 100644
index 0000000..3701a9d
--- /dev/null
+++ b/tools/versioner/tests/missing_api/platforms/libc.map.txt
@@ -0,0 +1,4 @@
+LIBC {
+  global:
+    foo;  # api-level=9
+};
diff --git a/tools/versioner/tests/missing_arch/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/missing_arch/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/missing_arch/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/missing_arch/platforms/android-9/arch-x86/symbols/libc.so.functions.txt b/tools/versioner/tests/missing_arch/platforms/android-9/arch-x86/symbols/libc.so.functions.txt
deleted file mode 100644
index e69de29..0000000
--- a/tools/versioner/tests/missing_arch/platforms/android-9/arch-x86/symbols/libc.so.functions.txt
+++ /dev/null
diff --git a/tools/versioner/tests/missing_arch/platforms/libc.map.txt b/tools/versioner/tests/missing_arch/platforms/libc.map.txt
new file mode 100644
index 0000000..f56190e
--- /dev/null
+++ b/tools/versioner/tests/missing_arch/platforms/libc.map.txt
@@ -0,0 +1,4 @@
+LIBC {
+  global:
+    foo;  # arm
+};
diff --git a/tools/versioner/tests/multiple_decl/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/multiple_decl/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/multiple_decl/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/multiple_decl/platforms/libc.map.txt b/tools/versioner/tests/multiple_decl/platforms/libc.map.txt
new file mode 100644
index 0000000..6cc4a2e
--- /dev/null
+++ b/tools/versioner/tests/multiple_decl/platforms/libc.map.txt
@@ -0,0 +1,4 @@
+LIBC {
+  global:
+    foo;
+};
diff --git a/tools/versioner/tests/multiple_decl_mismatch/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/multiple_decl_mismatch/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/multiple_decl_mismatch/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/multiple_decl_mismatch/platforms/libc.map.txt b/tools/versioner/tests/multiple_decl_mismatch/platforms/libc.map.txt
new file mode 100644
index 0000000..6cc4a2e
--- /dev/null
+++ b/tools/versioner/tests/multiple_decl_mismatch/platforms/libc.map.txt
@@ -0,0 +1,4 @@
+LIBC {
+  global:
+    foo;
+};
diff --git a/tools/versioner/tests/multiple_definition/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/multiple_definition/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/multiple_definition/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/multiple_definition/platforms/libc.map.txt b/tools/versioner/tests/multiple_definition/platforms/libc.map.txt
new file mode 100644
index 0000000..6cc4a2e
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition/platforms/libc.map.txt
@@ -0,0 +1,4 @@
+LIBC {
+  global:
+    foo;
+};
diff --git a/tools/versioner/tests/multiple_definition_ok/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/multiple_definition_ok/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/multiple_definition_ok/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/multiple_definition_ok/platforms/libc.map.txt b/tools/versioner/tests/multiple_definition_ok/platforms/libc.map.txt
new file mode 100644
index 0000000..6cc4a2e
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition_ok/platforms/libc.map.txt
@@ -0,0 +1,4 @@
+LIBC {
+  global:
+    foo;
+};
diff --git a/tools/versioner/tests/obsoleted/platforms/android-12/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/obsoleted/platforms/android-12/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index e69de29..0000000
--- a/tools/versioner/tests/obsoleted/platforms/android-12/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
diff --git a/tools/versioner/tests/obsoleted/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/obsoleted/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/obsoleted/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/obsoleted/platforms/libc.map.txt b/tools/versioner/tests/obsoleted/platforms/libc.map.txt
new file mode 100644
index 0000000..3701a9d
--- /dev/null
+++ b/tools/versioner/tests/obsoleted/platforms/libc.map.txt
@@ -0,0 +1,4 @@
+LIBC {
+  global:
+    foo;  # api-level=9
+};
diff --git a/tools/versioner/tests/preprocessor/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/preprocessor/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/preprocessor/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/preprocessor_extern_cpp/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/preprocessor_extern_cpp/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/preprocessor_extern_cpp/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/preprocessor_merging/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/preprocessor_merging/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/preprocessor_merging/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/smoke/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/smoke/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/smoke/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/smoke/platforms/libc.map.txt b/tools/versioner/tests/smoke/platforms/libc.map.txt
new file mode 100644
index 0000000..6cc4a2e
--- /dev/null
+++ b/tools/versioner/tests/smoke/platforms/libc.map.txt
@@ -0,0 +1,4 @@
+LIBC {
+  global:
+    foo;
+};
diff --git a/tools/versioner/tests/unnamed_bitfield/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/unnamed_bitfield/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/unnamed_bitfield/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/unnamed_bitfield/platforms/libc.map.txt b/tools/versioner/tests/unnamed_bitfield/platforms/libc.map.txt
new file mode 100644
index 0000000..6cc4a2e
--- /dev/null
+++ b/tools/versioner/tests/unnamed_bitfield/platforms/libc.map.txt
@@ -0,0 +1,4 @@
+LIBC {
+  global:
+    foo;
+};
diff --git a/tools/versioner/tests/version_mismatch/platforms/android-12/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/version_mismatch/platforms/android-12/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/version_mismatch/platforms/android-12/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/version_mismatch/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/version_mismatch/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
deleted file mode 100644
index 257cc56..0000000
--- a/tools/versioner/tests/version_mismatch/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
+++ /dev/null
@@ -1 +0,0 @@
-foo
diff --git a/tools/versioner/tests/version_mismatch/platforms/libc.map.txt b/tools/versioner/tests/version_mismatch/platforms/libc.map.txt
new file mode 100644
index 0000000..6cc4a2e
--- /dev/null
+++ b/tools/versioner/tests/version_mismatch/platforms/libc.map.txt
@@ -0,0 +1,4 @@
+LIBC {
+  global:
+    foo;
+};