Merge "Revert "async-safe logging: __ANDROID_API_LEVEL__ isn't a thing."" into main
diff --git a/OWNERS b/OWNERS
index 3818b1d..1859b9e 100644
--- a/OWNERS
+++ b/OWNERS
@@ -5,3 +5,5 @@
 danalbert@google.com
 rprichard@google.com
 yabinc@google.com
+
+per-file docs/mte.md=eugenis@google.com,fmayer@google.com,pcc@google.com
diff --git a/README.md b/README.md
index 0f2c30f..953e983 100644
--- a/README.md
+++ b/README.md
@@ -177,7 +177,7 @@
 library that would make more sense as the place to add the wrapper.
 
 In all other cases, you should use
-[syscall(3)](http://man7.org/linux/man-pages/man2/syscall.2.html) instead.
+[syscall(3)](https://man7.org/linux/man-pages/man2/syscall.2.html) instead.
 
 Adding a system call usually involves:
 
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 60a4f61..e98c2ff 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -88,6 +88,12 @@
     },
     {
       "name": "toybox-tests"
+    },
+    {
+      "name": "hwasan_test"
+    },
+    {
+      "name": "hwasan_test_static"
     }
   ],
   "kernel-presubmit": [
diff --git a/benchmarks/property_benchmark.cpp b/benchmarks/property_benchmark.cpp
index 1b4ba23..b356ab7 100644
--- a/benchmarks/property_benchmark.cpp
+++ b/benchmarks/property_benchmark.cpp
@@ -28,8 +28,7 @@
 
 #if defined(__BIONIC__)
 
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
+#include <sys/system_properties.h>
 
 #include <benchmark/benchmark.h>
 #include <system_properties/system_properties.h>
diff --git a/cpu_target_features/Android.bp b/cpu_target_features/Android.bp
new file mode 100644
index 0000000..25f37d1
--- /dev/null
+++ b/cpu_target_features/Android.bp
@@ -0,0 +1,18 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_binary {
+    name: "cpu-target-features",
+    srcs: [
+        "main.cpp",
+    ],
+    generated_headers: ["print_target_features.inc"],
+}
+
+genrule {
+    name: "print_target_features.inc",
+    out: ["print_target_features.inc"],
+    tool_files: ["generate_printer.py"],
+    cmd: "$(location generate_printer.py) $(out)",
+}
diff --git a/cpu_target_features/generate_printer.py b/cpu_target_features/generate_printer.py
new file mode 100755
index 0000000..dc56eb5
--- /dev/null
+++ b/cpu_target_features/generate_printer.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python3
+
+"""Generate the compilation target feature printing source code.
+
+The source code for detecting target features is heavily redundant and
+copy-pasted, and is easier to maintain using a generative script.
+
+This script creates the source and the include files in its current
+directory.
+"""
+
+import argparse
+from pathlib import Path
+from typing import Dict, List, Iterable
+
+_CPP_BOILERPLATE: str = """\
+#include <stdio.h>
+
+#define TO_STRING_EXP(DEF) #DEF
+#define TO_STRING(DEF) TO_STRING_EXP(DEF)
+"""
+
+_FEATURES = {
+    "Aarch64": [
+        "__ARM_FEATURE_AES",
+        "__ARM_FEATURE_BTI",
+        "__ARM_FEATURE_CRC32",
+        "__ARM_FEATURE_CRYPTO",
+        "__ARM_FEATURE_PAC_DEFAULT",
+        "__ARM_FEATURE_SHA2",
+        "__ARM_FEATURE_SHA3",
+        "__ARM_FEATURE_SHA512",
+    ],
+    "Arm32": [
+        "__ARM_ARCH_ISA_THUMB",
+        "__ARM_FEATURE_AES",
+        "__ARM_FEATURE_BTI",
+        "__ARM_FEATURE_CRC32",
+        "__ARM_FEATURE_CRYPTO",
+        "__ARM_FEATURE_PAC_DEFAULT",
+        "__ARM_FEATURE_SHA2",
+    ],
+    "X86": [
+        "__AES__",
+        "__AVX__",
+        "__CRC32__",
+        "__POPCNT__",
+        "__SHA512__",
+        "__SHA__",
+    ],
+    "Riscv": [
+        "__riscv_vector",
+    ],
+}
+
+
+def _make_function_sig(name: str) -> str:
+    return f"void print{name}TargetFeatures()"
+
+
+def check_template(define: str) -> List[str]:
+    return [
+        f"#if defined({define})",
+        f'  printf("%s=%s\\n", TO_STRING_EXP({define}), TO_STRING({define}));',
+        "#else",
+        f'  printf("%s not defined\\n", TO_STRING_EXP({define}));',
+        "#endif",
+    ]
+
+
+def generate_cpp_file(define_mapping: Dict[str, List[str]]) -> List[str]:
+    out: List[str] = _CPP_BOILERPLATE.split("\n")
+    for target, defines in define_mapping.items():
+        out.append("")
+        out.extend(generate_print_function(target, defines))
+    return out
+
+
+def generate_print_function(name: str, defines: List[str]) -> List[str]:
+    """Generate a print<DEFINE>TargetFeatures function."""
+    function_body = [_make_function_sig(name) + " {"]
+    for d in defines:
+        function_body.extend(check_template(d))
+    function_body.append("}")
+    return function_body
+
+
+def parse_args() -> argparse.Namespace:
+    parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument(
+        "cpp_in",
+        type=Path,
+        help="Output path to generate the cpp file.",
+    )
+    return parser.parse_args()
+
+
+def main() -> None:
+    args = parse_args()
+    printer_cpp_filepath = args.cpp_in
+    printer_cpp_filepath.write_text(
+        "\n".join(generate_cpp_file(_FEATURES)), encoding="utf-8"
+    )
+
+
+if __name__ == "__main__":
+    main()
diff --git a/cpu_target_features/main.cpp b/cpu_target_features/main.cpp
new file mode 100644
index 0000000..61f3d25
--- /dev/null
+++ b/cpu_target_features/main.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 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 <stdio.h>
+
+#include "print_target_features.inc"
+
+int main() {
+#if defined(__aarch64__)
+  printAarch64TargetFeatures();
+  return 0;
+#elif defined(__arm__)
+  printArm32TargetFeatures();
+  return 0;
+#elif defined(__x86_64__) || defined(__i386__)
+  printX86TargetFeatures();
+  return 0;
+#elif defined(__riscv)
+  printRiscvTargetFeatures();
+  return 0;
+#else
+#error Unsupported arch. This binary only supports aarch64, arm, x86, x86-64, and risc-v
+#endif
+}
diff --git a/docs/clang_fortify_anatomy.md b/docs/clang_fortify_anatomy.md
index 4b95fdc..46d3a71 100644
--- a/docs/clang_fortify_anatomy.md
+++ b/docs/clang_fortify_anatomy.md
@@ -147,8 +147,7 @@
 void* mempcpy(void* __dst, const void* __src, size_t __n) __INTRODUCED_IN(23);
 ```
 
-Which is annotated with nothing special, except for Bionic's versioner, which
-is Android-specific (and orthogonal to FORTIFY anyway), so it will be ignored.
+Which is annotated with nothing special, so it will be ignored.
 
 The [source for `mempcpy`] in Bionic's headers for is:
 ```c
diff --git a/docs/fdtrack.md b/docs/fdtrack.md
index 07c69b3..8928a5c 100644
--- a/docs/fdtrack.md
+++ b/docs/fdtrack.md
@@ -4,9 +4,11 @@
 
 fdtrack is a file descriptor leak checker added to Android in API level 30.
 
-fdtrack consists of two parts: a set of hooks in bionic to register a callback
-that's invoked on file descriptor operations, and a library that implements a
-hook to perform and store backtraces for file descriptor creation.
+fdtrack consists of several parts: a set of hooks in bionic to register a
+callback that's invoked on file descriptor operations, a library that implements
+a hook to perform and store backtraces for file descriptor creation, and
+code in frameworks to automatically enable it (and deliberately crash a process
+that's leaking).
 
 ### bionic hooks
 bionic provides a header in the `bionic_libc_platform_headers` header_lib at <[bionic/fdtrack.h](https://android.googlesource.com/platform/bionic/+/refs/heads/main/libc/platform/bionic/fdtrack.h)>.
@@ -21,6 +23,28 @@
 [libfdtrack](https://android.googlesource.com/platform/bionic/+/refs/heads/main/libfdtrack)
 implements a library that uses libunwindstack to unwind and store fd creation backtraces.
 
+### frameworks
+As the name implies, `spawnFdLeakCheckThread` in SystemServer spawns a thread
+to monitor the number of open file descriptors every so often.
+If that passes a certain threshold, fdtrack is enabled.
+If it passes another threshold, the process is aborted.
+These thresholds are configurable via system properties:
+```
+    // Number of open file descriptors before fdtrack starts; default 1600.
+    private static final String SYSPROP_FDTRACK_ENABLE_THRESHOLD =
+            "persist.sys.debug.fdtrack_enable_threshold";
+
+    // Number of open file descriptors before aborting; default 3000.
+    private static final String SYSPROP_FDTRACK_ABORT_THRESHOLD =
+            "persist.sys.debug.fdtrack_abort_threshold";
+
+    // Number of seconds between open fd count checks; default 120s.
+    private static final String SYSPROP_FDTRACK_INTERVAL =
+            "persist.sys.debug.fdtrack_interval";
+```
+Note that it's also possible to monitor the number of open file descriptors for
+a given process from the shell. `adb shell watch ls -l /proc/<pid>/fd` will show
+them (and you can choose your own update rate as an argument to `watch`).
 
 #### Using libfdtrack
 libfdtrack registers its hook upon being loaded, so to start capturing
diff --git a/docs/mte.md b/docs/mte.md
new file mode 100644
index 0000000..3034cc7
--- /dev/null
+++ b/docs/mte.md
@@ -0,0 +1,244 @@
+# Arm Memory Tagging Extension (MTE) implementation
+
+AOSP supports Arm MTE to detect invalid memory accesses. The implementation is
+spread across multiple components, both within and out of the AOSP tree. This
+document gives an overview and pointers about how the various MTE features are
+implemented.
+
+For documentation of the behavior rather than the implementation, see the
+[SAC page on MTE] instead. For MTE for apps, see the [NDK page on MTE].
+
+The relevant components are:
+
+* [LLVM Project] (out of AOSP tree)
+    * Stack tagging instrumentation pass
+    * Scudo memory allocator
+* bionic
+    * libc
+    * dynamic loader
+* Zygote
+* debuggerd
+* [NDK]
+
+## MTE enablement
+
+The way MTE is requested and enabled differs between native binaries and Java
+apps. This is necessarily so, because Java apps get forked from the Zygote,
+while native executables get inintialized by the linker.
+
+### Native binaries
+
+Both AOSP and the NDK allow you to compile C/C++ code that use MTE to detect
+memory safety issues. The [NDK legacy cmake toolchain] and the
+[NDK new cmake toolchain] both support "memtag" as an argument for
+`ANDROID_SANITIZE`. NDK make has no specific support for MTE, but the
+relevant flags can be passed directly as `CFLAGS` and `LDFLAGS`.
+
+For the OS itself, [Soong] supports "memtag_[heap|stack|globals]" as
+`SANITIZE_TARGET  and as `sanitize:` attribute in Android.bp files;
+[Android make] supports the same environment variables as Soong. This passes
+the appropriate flags to the clang driver for both compile and link steps.
+
+#### Linker
+
+* For **dynamic executables** LLD has support to
+  [add appropriate dynamic sections] as defined in the [ELF standard]
+* For **static executables** and as a fallback for older devices, LLD
+  also supports [adding the Android-specific ELF note]
+
+Both of the above are controlled by the linker flag `--android-memtag-mode`
+which is [passed in by the clang driver] if
+`-fsanitize=memtag-[stack|heap|globals]` is [passed in].
+`-fsanitize=memtag` [enables all three] (even for API levels that don't
+implement the runtime for globals, which means builds from old versions
+of clang may no work with newer platform versions that support globals).
+`-fsanitize-memtag-mode` allows to choose between ASYNC and SYNC.
+
+This information can be queried using `llvm-readelf --memtag`.
+
+This information is [picked up by libc init] to decide whether to enable MTE.
+`-fsanitize-heap` controls both whether scudo tags allocations, and whether
+tag checking is enabled.
+
+#### Runtime environment (dynamic loader, libc)
+
+There are two different initialization sequences for libc, both of which end up
+calling `__libc_init_mte`.
+
+N.B. the linker has its own copy of libc, which is used when executing these
+functions. That is why we have to use `__libc_shared_globals` to communicate
+with the libc of the process we are starting.
+
+* **static executables** `__libc_init` is called from `crtbegin.c`, which calls
+                         `__libc_init_mte`
+* **dynamic executables** the linker calls `__libc_init_mte`
+
+`__libc_init_mte` figures out the appropriate MTE level that is requested by
+the process, calls `prctl` to request this from the kernel, and stores data in
+`__libc_shared_globals` which gets picked up later to enable MTE in scudo.
+
+It also does work related to stack tagging and permissive mode, which will be
+detailed later.
+
+### Apps
+
+Apps can request MTE be enabled for their process via the manifest attribute
+`android:memtagMode`. This gets interpreted by Zygote, which always runs with
+`ASYNC` MTE enabled, because MTE for a process can only be disabled after
+it has been initialized (see [Native binaries](#native-binaries)), not enabled.
+
+[decideTaggingLevel] in the Zygote figures out whether to enable MTE for
+an app, and stores it in the `runtimeFlags`, which get picked up by
+[SpecializeCommon] after forking from the Zygote.
+
+## MTE implementation
+
+### Heap Tagging
+
+Heap tagging is implemented in the scudo allocator. On `malloc` and `free`,
+scudo will update the memory's tags to prevent use-after-free and buffer
+overflows.
+
+[scudo's memtag.h] contains helper functions to deal with MTE tag management,
+which are used in [combined.h] and [secondary.h].
+
+
+### Stack Tagging
+
+Stack tagging requires instrumenting function bodies. It is implemented as
+an instrumentation pass in LLVM called [AArch64StackTagging], which sets
+the tags according to the lifetime of stack objects.
+
+The instrumentation pass also supports recording stack history, consisting of:
+
+* PC
+* Frame pointer
+* Base tag
+
+This can be used to reconstruct which stack object was referred to in an
+invalid access. The logic to reconstruct this can be found in the
+[stack script].
+
+
+Stack tagging is enabled in one of two circumstances:
+* at process startup, if the main binary or any of its dependencies are
+  compiled with `memtag-stack`
+* library compiled with `memtag-stack` is `dlopen`ed later, either directly or
+  as a dependency of a `dlopen`ed library. In this case, the
+  [__pthread_internal_remap_stack_with_mte] function is used (called from
+  `memtag_stack_dlopen_callback`). Because `dlopen`
+  is handled by the linker, we have to [store a function pointer] to the
+  process's version of the function in `__libc_shared_globals`.
+
+Enabling stack MTE consists of two operations:
+* Remapping the stacks as `PROT_MTE`
+* Allocating a stack history buffer.
+
+The first operation is only necessary when the process is running with MTE
+enabled. The second operation is also necessary when the process is not running
+with MTE enabled, because the writes to the stack history buffer are
+unconditional.
+
+libc keeps track of this through two globals:
+
+* `__libc_memtag_stack`:  whether stack MTE is enabled on the process, i.e.
+  whether the stack pages are mapped with PROT\_MTE. This is always false if
+  MTE is disabled for the process (i.e. `libc_globals.memtag` is false).
+* `__libc_memtag_stack_abi`: whether the process contains any code that was
+  compiled with memtag-stack. This is true even if the process does not have
+  MTE enabled.
+
+### Globals Tagging
+
+TODO(fmayer): write once submitted
+
+### Crash reporting
+
+For MTE crashes, debuggerd serializes special information into the Tombstone
+proto:
+
+* Tags around fault address
+* Scudo allocation history
+
+This is done in [tombstone\_proto.cpp]. The information is converted to a text
+proto in [tombstone\_proto\_to\_text.cpp].
+
+## Bootloader control
+
+The bootloader API allows userspace to enable MTE on devices that do not ship
+with MTE enabled by default.
+
+See [SAC MTE bootloader support] for the API definition. In AOSP, this API is
+implemented in [system/extras/mtectrl]. mtectrl.rc handles the property
+changes and invokes mtectrl to update the misc partition to communicate
+with the bootloader.
+
+There is also an [API in Device Policy Manager] that allows the device admin
+to enable or disable MTE under certain circumstances.
+
+The device can opt in or out of these APIs by a set of system properties:
+
+* `ro.arm64.memtag.bootctl_supported`: the system property API is supported,
+  and an option is displayed in Developer Options.
+* `ro.arm64.memtag.bootctl_settings_toggle`: an option is displayed in the
+  normal settings. This requires `ro.arm64.memtag.bootctl_supported` to be
+  true. This implies `ro.arm64.memtag.bootctl_device_policy_manager`, if it
+  is not explicitely set.
+* `ro.arm64.memtag.bootctl_device_policy_manager`: the Device Policy Manager
+  API is supported.
+
+## Permissive MTE
+
+Permissive MTE refers to a mode which, instead of crashing the process on an
+MTE fault, records a tombstone but then continues execution of the process.
+An important caveat is that system calls with invalid pointers (where the
+pointer tag does not match the memory tag) still return an error code.
+
+This mode is only available for system services, not apps. It is implemented
+in the [debugger\_signal\_handler] by disabling MTE for the faulting thread.
+Optionally, the user can ask for MTE to be re-enabled after some time.
+This is achieved by arming a timer that calls [enable_mte_signal_handler]
+upon expiry.
+
+## MTE Mode Upgrade
+
+When a system service [crashes in ASYNC mode], we set an impossible signal
+as an exit code (because that signal is always gracefully handled by libc),
+and [in init] we set `BIONIC_MEMTAG_UPGRADE_SECS`, which gets handled by
+[libc startup].
+
+[SpecializeCommon]: https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/jni/com_android_internal_os_Zygote.cpp?q=f:frameworks%2Fbase%2Fcore%2Fjni%2Fcom_android_internal_os_Zygote.cpp%20%22%20mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL,%22&ss=android%2Fplatform%2Fsuperproject%2Fmain
+[LLVM Project]: https://github.com/llvm/llvm-project/
+[NDK]: https://android.googlesource.com/platform/ndk/
+[NDK legacy cmake toolchain]: https://android.googlesource.com/platform/ndk/+/refs/heads/main/build/cmake/android-legacy.toolchain.cmake#490
+[NDK new cmake toolchain]: https://android.googlesource.com/platform/ndk/+/refs/heads/main/build/cmake/flags.cmake#56
+[Soong]: https://cs.android.com/android/platform/superproject/main/+/main:build/soong/cc/sanitize.go?q=sanitize.go&ss=android%2Fplatform%2Fsuperproject%2Fmain
+[decideTaggingLevel]: https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/java/com/android/internal/os/Zygote.java?q=symbol:decideTaggingLevel
+[picked up by libc init]: https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/bionic/libc_init_mte.cpp?q=symbol:__get_tagging_level%20f:bionic
+[enables all three]: https://github.com/llvm/llvm-project/blob/e732d1ce86783b1d7fe30645fcb30434109505b9/clang/include/clang/Basic/Sanitizers.def#L62
+[passed in]: https://github.com/llvm/llvm-project/blob/ff2e619dfcd77328812a42d2ba2b11c3ff96f410/clang/lib/Driver/SanitizerArgs.cpp#L719
+[passed in by the clang driver]: https://github.com/llvm/llvm-project/blob/ff2e619dfcd77328812a42d2ba2b11c3ff96f410/clang/lib/Driver/ToolChains/CommonArgs.cpp#L1595
+[adding the Android-specific ELF note]: https://github.com/llvm/llvm-project/blob/435cb0dc5eca08cdd8d9ed0d887fa1693cc2bf33/lld/ELF/Driver.cpp#L1258
+[ELF standard]: https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#6dynamic-section
+[add appropriate dynamic sections]: https://github.com/llvm/llvm-project/blob/7022498ac2f236e411e8a0f9a48669e754000a4b/lld/ELF/SyntheticSections.cpp#L1473
+[storeTags]: https://cs.android.com/android/platform/superproject/main/+/main:external/scudo/standalone/memtag.h?q=f:scudo%20f:memtag.h%20function:storeTags
+[SAC page on MTE]: https://source.android.com/docs/security/test/memory-safety/arm-mte
+[NDK page on MTE]: https://developer.android.com/ndk/guides/arm-mte
+[AArch64StackTagging]: https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/AArch64/AArch64StackTagging.cpp
+[scudo's memtag.h]: https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/scudo/standalone/memtag.h
+[combined.h]: https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/scudo/standalone/combined.h
+[secondary.h]: https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/scudo/standalone/secondary.h
+[__pthread_internal_remap_stack_with_mte]: https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/bionic/pthread_internal.cpp?q=__pthread_internal_remap_stack_with_mte
+[stack script]: https://cs.android.com/android/platform/superproject/main/+/main:development/scripts/stack?q=stack
+[Android make]: https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/config_sanitizers.mk
+[store a function pointer]: https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/bionic/libc_init_dynamic.cpp;l=168?q=memtag_stack_dlopen_callback
+[tombstone\_proto.cpp]: https://cs.android.com/android/platform/superproject/main/+/main:system/core/debuggerd/libdebuggerd/tombstone_proto.cpp?q=tombstone_proto.cpp
+[tombstone\_proto\_to\_text.cpp]: https://cs.android.com/android/platform/superproject/main/+/main:system/core/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
+[SAC MTE bootloader support]: https://source.android.com/docs/security/test/memory-safety/bootloader-support
+[system/extras/mtectrl]: https://cs.android.com/android/platform/superproject/main/+/main:system/extras/mtectrl/
+[API in Device Policy Manager]: https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/java/android/app/admin/DevicePolicyManager.java?q=symbol:setMtePolicy%20f:DevicePolicyManager.java
+[debuggerd\_signal_handler]: https://cs.android.com/android/platform/superproject/main/+/main:system/core/debuggerd/handler/debuggerd_handler.cpp?q=f:debuggerd_handler.cpp%20symbol:debuggerd_signal_handler
+[enable_mte_signal_handler]: https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/bionic/libc_init_mte.cpp?q=symbol:__enable_mte_signal_handler
+[in init]: https://cs.android.com/android/platform/superproject/main/+/main:system/core/init/service.cpp?q=f:system%2Fcore%2Finit%2Fservice.cpp%20should_upgrade_mte
+[crashes in ASYNC mode]: https://cs.android.com/android/platform/superproject/main/+/main:system/core/debuggerd/handler/debuggerd_handler.cpp;l=799?q=BIONIC_SIGNAL_ART_PROFILER
+[libc startup]: https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/bionic/libc_init_mte.cpp?q=BIONIC_MEMTAG_UPGRADE_SECS
diff --git a/docs/status.md b/docs/status.md
index 7ebd195..e7111d9 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -32,10 +32,14 @@
   * `ualarm`
 
 Missing functionality:
-  * `<aio.h>`
+  * `<aio.h>`. No particular reason not to have this other than that no-one's
+    needed it yet, and it's relatively complex. If/when llvm-libc adds this,
+    maybe we'll just reuse that.
   * `<monetary.h>`. See
     [discussion](https://github.com/android/ndk/issues/1182).
-  * `<wordexp.h>`
+  * `<wordexp.h>`. Unsafe because it passes user input to the shell (!),
+    and often should just be a call to glob() anyway. See also
+    [OpenBSD's discussion about adding wordexp()](https://www.mail-archive.com/tech@openbsd.org/msg02325.html).
   * Locales. Although bionic contains the various `_l()` functions, the only
     locale supported is a UTF-8 C/POSIX locale. Most of the POSIX APIs are
     insufficient to support the wide range of languages used by Android users,
@@ -55,6 +59,12 @@
 
 Current libc symbols: https://android.googlesource.com/platform/bionic/+/main/libc/libc.map.txt
 
+New libc functions in API level 36:
+  * `qsort_r`, `sig2str`/`str2sig` (POSIX Issue 8 additions).
+  * GNU/BSD extension `lchmod`.
+  * GNU extensions `pthread_getaffinity_np`/`pthread_setaffinity_np`.
+  * New system call wrapper: `mseal` (`<sys/mman.h>`).
+
 New libc functions in V (API level 35):
   * New `android_crash_detail_register`, `android_crash_detail_unregister`,
     `android_crash_detail_replace_name`, and `android_crash_detail_replace_data`
diff --git a/libc/Android.bp b/libc/Android.bp
index 79b85c5..3c5c9f1 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -264,6 +264,7 @@
     name: "libc_init_static",
     defaults: ["libc_defaults"],
     srcs: [
+        "bionic/libc_init_mte.cpp",
         "bionic/libc_init_static.cpp",
         ":elf_note_sources",
     ],
@@ -353,7 +354,6 @@
         "-Wno-unused-parameter",
         "-include netbsd-compat.h",
         "-Wframe-larger-than=66000",
-        "-include private/bsd_sys_param.h",
     ],
 
     local_include_dirs: [
@@ -389,6 +389,7 @@
         "upstream-freebsd/lib/libc/stdlib/hdestroy_r.c",
         "upstream-freebsd/lib/libc/stdlib/hsearch_r.c",
         "upstream-freebsd/lib/libc/stdlib/qsort.c",
+        "upstream-freebsd/lib/libc/stdlib/qsort_r.c",
         "upstream-freebsd/lib/libc/stdlib/quick_exit.c",
         "upstream-freebsd/lib/libc/string/wcpcpy.c",
         "upstream-freebsd/lib/libc/string/wcpncpy.c",
@@ -417,20 +418,6 @@
         "upstream-freebsd/lib/libc/string/wmemmove.c",
         "upstream-freebsd/lib/libc/string/wmemset.c",
     ],
-    arch: {
-        x86: {
-            exclude_srcs: [
-                "upstream-freebsd/lib/libc/string/wcschr.c",
-                "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",
-            ],
-        },
-    },
 
     cflags: [
         "-Wno-sign-compare",
@@ -484,7 +471,6 @@
         "upstream-netbsd/lib/libc/regex/regerror.c",
         "upstream-netbsd/lib/libc/regex/regexec.c",
         "upstream-netbsd/lib/libc/regex/regfree.c",
-        "upstream-netbsd/lib/libc/stdlib/bsearch.c",
         "upstream-netbsd/lib/libc/stdlib/drand48.c",
         "upstream-netbsd/lib/libc/stdlib/erand48.c",
         "upstream-netbsd/lib/libc/stdlib/jrand48.c",
@@ -570,7 +556,6 @@
         "upstream-openbsd/lib/libc/stdio/fgetwc.c",
         "upstream-openbsd/lib/libc/stdio/fgetws.c",
         "upstream-openbsd/lib/libc/stdio/flags.c",
-        "upstream-openbsd/lib/libc/stdio/fpurge.c",
         "upstream-openbsd/lib/libc/stdio/fputwc.c",
         "upstream-openbsd/lib/libc/stdio/fputws.c",
         "upstream-openbsd/lib/libc/stdio/fvwrite.c",
@@ -624,10 +609,12 @@
         "upstream-openbsd/lib/libc/string/wcslcpy.c",
         "upstream-openbsd/lib/libc/string/wcswidth.c",
 
-        // This file is originally from OpenBSD, and benefits from
-        // being compiled with openbsd-compat.h.
-        // TODO: clean this up instead.
+        // These files are originally from OpenBSD,
+        // and benefit from being compiled with openbsd-compat.h.
+        // TODO: clean them up instead.
         "bionic/fts.c",
+        "stdio/vfprintf.cpp",
+        "stdio/vfwprintf.cpp",
     ],
 
     // Each architecture has optimized versions of some routines,
@@ -636,10 +623,7 @@
         arm: {
             srcs: [
                 "upstream-openbsd/lib/libc/string/memchr.c",
-                "upstream-openbsd/lib/libc/string/memrchr.c",
                 "upstream-openbsd/lib/libc/string/stpncpy.c",
-                "upstream-openbsd/lib/libc/string/strlcat.c",
-                "upstream-openbsd/lib/libc/string/strlcpy.c",
                 "upstream-openbsd/lib/libc/string/strncat.c",
                 "upstream-openbsd/lib/libc/string/strncmp.c",
                 "upstream-openbsd/lib/libc/string/strncpy.c",
@@ -649,18 +633,13 @@
             srcs: [
                 "upstream-openbsd/lib/libc/string/strcat.c",
                 "upstream-openbsd/lib/libc/string/stpncpy.c",
-                "upstream-openbsd/lib/libc/string/strlcat.c",
-                "upstream-openbsd/lib/libc/string/strlcpy.c",
                 "upstream-openbsd/lib/libc/string/strncat.c",
                 "upstream-openbsd/lib/libc/string/strncpy.c",
             ],
         },
         riscv64: {
             srcs: [
-                "upstream-openbsd/lib/libc/string/memrchr.c",
                 "upstream-openbsd/lib/libc/string/stpncpy.c",
-                "upstream-openbsd/lib/libc/string/strlcat.c",
-                "upstream-openbsd/lib/libc/string/strlcpy.c",
             ],
         },
         x86: {
@@ -670,10 +649,7 @@
         },
         x86_64: {
             srcs: [
-                "upstream-openbsd/lib/libc/string/memchr.c",
-                "upstream-openbsd/lib/libc/string/memrchr.c",
-                "upstream-openbsd/lib/libc/string/strlcat.c",
-                "upstream-openbsd/lib/libc/string/strlcpy.c",
+                // x86_64 has custom/llvm-libc implementations of all of these.
             ],
         },
     },
@@ -686,9 +662,11 @@
 
     local_include_dirs: [
         "private",
-        "upstream-openbsd/android/include",
         "stdio",
-        "upstream-openbsd/lib/libc/include",
+        "upstream-openbsd/android/include/",
+        "upstream-openbsd/lib/libc/gdtoa/",
+        "upstream-openbsd/lib/libc/include/",
+        "upstream-openbsd/lib/libc/stdio/",
     ],
 
     name: "libc_openbsd",
@@ -698,8 +676,6 @@
     name: "libc_openbsd_large_stack",
     defaults: ["libc_defaults"],
     srcs: [
-        "stdio/vfprintf.cpp",
-        "stdio/vfwprintf.cpp",
         "upstream-openbsd/lib/libc/string/memmem.c",
         "upstream-openbsd/lib/libc/string/strstr.c",
     ],
@@ -710,11 +686,7 @@
     ],
 
     local_include_dirs: [
-        "private",
         "upstream-openbsd/android/include/",
-        "upstream-openbsd/lib/libc/gdtoa/",
-        "upstream-openbsd/lib/libc/include/",
-        "upstream-openbsd/lib/libc/stdio/",
     ],
 }
 
@@ -915,6 +887,7 @@
         "bionic/isatty.cpp",
         "bionic/killpg.cpp",
         "bionic/langinfo.cpp",
+        "bionic/lchmod.cpp",
         "bionic/lchown.cpp",
         "bionic/lfs64_support.cpp",
         "bionic/libc_init_common.cpp",
@@ -956,6 +929,7 @@
         "bionic/pthread_detach.cpp",
         "bionic/pthread_equal.cpp",
         "bionic/pthread_exit.cpp",
+        "bionic/pthread_getaffinity.cpp",
         "bionic/pthread_getcpuclockid.cpp",
         "bionic/pthread_getschedparam.cpp",
         "bionic/pthread_gettid_np.cpp",
@@ -969,6 +943,7 @@
         "bionic/pthread_sigqueue.cpp",
         "bionic/pthread_self.cpp",
         "bionic/pthread_setname_np.cpp",
+        "bionic/pthread_setaffinity.cpp",
         "bionic/pthread_setschedparam.cpp",
         "bionic/pthread_spinlock.cpp",
         "bionic/ptrace.cpp",
@@ -1031,7 +1006,6 @@
         "bionic/thread_private.cpp",
         "bionic/threads.cpp",
         "bionic/time.cpp",
-        "bionic/time_l.cpp",
         "bionic/tmpfile.cpp",
         "bionic/umount.cpp",
         "bionic/unlink.cpp",
@@ -1183,22 +1157,8 @@
                 "arch-x86/bionic/vfork.S",
                 "arch-x86/bionic/__x86.get_pc_thunk.S",
 
-                "arch-x86/generic/string/memcmp.S",
-                "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/string/sse2-memchr-atom.S",
                 "arch-x86/string/sse2-memmove-slm.S",
-                "arch-x86/string/sse2-memrchr-atom.S",
-                "arch-x86/string/sse2-memset-atom.S",
                 "arch-x86/string/sse2-memset-slm.S",
                 "arch-x86/string/sse2-stpcpy-slm.S",
                 "arch-x86/string/sse2-stpncpy-slm.S",
@@ -1208,28 +1168,14 @@
                 "arch-x86/string/sse2-strncpy-slm.S",
                 "arch-x86/string/sse2-strnlen-atom.S",
                 "arch-x86/string/sse2-strrchr-atom.S",
-                "arch-x86/string/sse2-wcschr-atom.S",
-                "arch-x86/string/sse2-wcsrchr-atom.S",
-                "arch-x86/string/sse2-wcslen-atom.S",
-                "arch-x86/string/sse2-wcscmp-atom.S",
-                "arch-x86/string/sse2-strlen-atom.S",
 
                 "arch-x86/string/ssse3-memcmp-atom.S",
-                "arch-x86/string/ssse3-memmove-atom.S",
                 "arch-x86/string/ssse3-strcat-atom.S",
                 "arch-x86/string/ssse3-strcmp-atom.S",
-                "arch-x86/string/ssse3-strcpy-atom.S",
-                "arch-x86/string/ssse3-strlcat-atom.S",
-                "arch-x86/string/ssse3-strlcpy-atom.S",
                 "arch-x86/string/ssse3-strncat-atom.S",
                 "arch-x86/string/ssse3-strncmp-atom.S",
-                "arch-x86/string/ssse3-strncpy-atom.S",
-                "arch-x86/string/ssse3-wcscat-atom.S",
-                "arch-x86/string/ssse3-wcscpy-atom.S",
-                "arch-x86/string/ssse3-wmemcmp-atom.S",
 
                 "arch-x86/string/sse4-memcmp-slm.S",
-                "arch-x86/string/sse4-wmemcmp-slm.S",
 
                 "bionic/strchrnul.cpp",
             ],
@@ -1256,11 +1202,6 @@
                 "arch-x86_64/string/sse4-memcmp-slm.S",
                 "arch-x86_64/string/ssse3-strcmp-slm.S",
                 "arch-x86_64/string/ssse3-strncmp-slm.S",
-
-                "bionic/strchr.cpp",
-                "bionic/strchrnul.cpp",
-                "bionic/strnlen.cpp",
-                "bionic/strrchr.cpp",
             ],
         },
     },
@@ -1279,6 +1220,7 @@
     generated_headers: ["generated_android_ids"],
 
     whole_static_libs: [
+        "//external/llvm-libc:llvmlibc",
         "libsystemproperties",
     ],
 
@@ -1415,43 +1357,13 @@
 }
 
 // ========================================================
-// libc_static_dispatch.a --- libc.a ifuncs
+// libc_static_dispatch.a/libc_dynamic_dispatch.a --- string/memory "ifuncs"
+// (Actually ifuncs for libc.so, but a home-grown alternative for libc.a.)
 // ========================================================
-cc_library_static {
+
+cc_defaults {
+    name: "libc_dispatch_defaults",
     defaults: ["libc_defaults"],
-    name: "libc_static_dispatch",
-
-    arch: {
-        x86_64: {
-            srcs: ["arch-x86_64/static_function_dispatch.S"],
-        },
-        x86: {
-            srcs: ["arch-x86/static_function_dispatch.S"],
-        },
-        arm: {
-            srcs: ["arch-arm/static_function_dispatch.S"],
-        },
-        arm64: {
-            srcs: ["arch-arm64/static_function_dispatch.S"],
-        },
-        riscv64: {
-            srcs: ["arch-riscv64/static_function_dispatch.S"],
-        },
-    },
-}
-
-// ========================================================
-// libc_dynamic_dispatch.a --- libc.so ifuncs
-// ========================================================
-cc_library_static {
-    defaults: ["libc_defaults"],
-    name: "libc_dynamic_dispatch",
-
-    cflags: [
-        "-ffreestanding",
-        "-fno-stack-protector",
-        "-fno-jump-tables",
-    ],
     arch: {
         x86_64: {
             srcs: ["arch-x86_64/dynamic_function_dispatch.cpp"],
@@ -1469,6 +1381,30 @@
             srcs: ["arch-riscv64/dynamic_function_dispatch.cpp"],
         },
     },
+    // Prevent the compiler from inserting calls to libc/taking the address of
+    // a jump table from within an ifunc (or, in the static case, code that
+    // can be executed arbitrarily early).
+    cflags: [
+        "-ffreestanding",
+        "-fno-stack-protector",
+        "-fno-jump-tables",
+    ],
+}
+
+cc_library_static {
+    name: "libc_static_dispatch",
+    defaults: ["libc_dispatch_defaults"],
+    cflags: [
+        "-DBIONIC_STATIC_DISPATCH",
+    ],
+}
+
+cc_library_static {
+    name: "libc_dynamic_dispatch",
+    defaults: ["libc_dispatch_defaults"],
+    cflags: [
+        "-DBIONIC_DYNAMIC_DISPATCH",
+    ],
 }
 
 // ========================================================
@@ -1537,6 +1473,7 @@
     srcs: [
         "arch-common/bionic/crtbegin_so.c",
         "arch-common/bionic/crtbrand.S",
+        "bionic/android_mallopt.cpp",
         "bionic/gwp_asan_wrappers.cpp",
         "bionic/heap_tagging.cpp",
         "bionic/icu.cpp",
@@ -1555,6 +1492,7 @@
 filegroup {
     name: "libc_sources_static",
     srcs: [
+        "bionic/android_mallopt.cpp",
         "bionic/gwp_asan_wrappers.cpp",
         "bionic/heap_tagging.cpp",
         "bionic/icu_static.cpp",
@@ -1665,7 +1603,6 @@
     },
 
     apex_available: [
-        "//apex_available:platform",
         "com.android.runtime",
     ],
 
@@ -1695,8 +1632,7 @@
     llndk: {
         symbol_file: "libc.map.txt",
         export_headers_as_system: true,
-        export_preprocessed_headers: ["include"],
-        export_llndk_headers: ["libc_llndk_headers"],
+        export_llndk_headers: ["libc_headers"],
     },
 }
 
@@ -1807,9 +1743,10 @@
 }
 
 cc_library_headers {
-    name: "libc_llndk_headers",
+    name: "libc_uapi_headers",
     visibility: [
         "//external/musl",
+        "//external/rust/crates/v4l2r/android",
     ],
     llndk: {
         llndk_headers: true,
@@ -1902,13 +1839,13 @@
     target: {
         android: {
             export_system_include_dirs: ["include"],
-            header_libs: ["libc_llndk_headers"],
-            export_header_lib_headers: ["libc_llndk_headers"],
+            header_libs: ["libc_uapi_headers"],
+            export_header_lib_headers: ["libc_uapi_headers"],
         },
         linux_bionic: {
             export_system_include_dirs: ["include"],
-            header_libs: ["libc_llndk_headers"],
-            export_header_lib_headers: ["libc_llndk_headers"],
+            header_libs: ["libc_uapi_headers"],
+            export_header_lib_headers: ["libc_uapi_headers"],
         },
     },
 }
@@ -2045,15 +1982,6 @@
 cc_defaults {
     name: "crt_so_defaults",
     defaults: ["crt_defaults"],
-
-    arch: {
-        x86: {
-            cflags: ["-fPIC"],
-        },
-        x86_64: {
-            cflags: ["-fPIC"],
-        },
-    },
     stl: "none",
 }
 
@@ -2193,6 +2121,7 @@
 //     async_safe_fatal_va_list
 cc_library_static {
     name: "librust_baremetal",
+    defaults: ["cc_baremetal_defaults"],
     header_libs: ["libc_headers"],
     include_dirs: [
         "bionic/libc/async_safe/include",
@@ -2219,6 +2148,7 @@
         },
     },
     whole_static_libs: [
+        "//external/llvm-libc:llvmlibc",
         "libarm-optimized-routines-mem",
         "libc_netbsd",
     ],
@@ -2228,17 +2158,29 @@
     visibility: [
         "//packages/modules/Virtualization/libs/libvmbase",
     ],
+
+    // b/358211032: This library gets linked into a rust rlib.  Disable LTO
+    // until cross-language lto is supported.
+    lto: {
+        never: true,
+    },
 }
 
 // ========================================================
 // NDK headers.
 // ========================================================
 
-versioned_ndk_headers {
+ndk_headers {
     name: "common_libc",
     from: "include",
     to: "",
+    srcs: ["include/**/*.h"],
     license: "NOTICE",
+    // These don't pass the bad verification we do because many of them are
+    // arch-specific, and they aren't necessarily independently includable.
+    // That's not much of a problem though, since C-incompaitibilities in the
+    // UAPI headers should run into problems long before they reach us.
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2258,6 +2200,7 @@
         "kernel/uapi/xen/**/*.h",
     ],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2274,6 +2217,7 @@
     to: "scsi",
     srcs: ["kernel/android/scsi/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2282,6 +2226,7 @@
     to: "arm-linux-androideabi",
     srcs: ["kernel/uapi/asm-arm/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2290,6 +2235,7 @@
     to: "aarch64-linux-android",
     srcs: ["kernel/uapi/asm-arm64/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2298,6 +2244,7 @@
     to: "riscv64-linux-android",
     srcs: ["kernel/uapi/asm-riscv/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2306,6 +2253,7 @@
     to: "i686-linux-android",
     srcs: ["kernel/uapi/asm-x86/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2314,23 +2262,13 @@
     to: "x86_64-linux-android",
     srcs: ["kernel/uapi/asm-x86/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_library {
     name: "libc",
     symbol_file: "libc.map.txt",
     first_version: "9",
-    export_header_libs: [
-        "common_libc",
-        "libc_uapi",
-        "libc_kernel_android_uapi_linux",
-        "libc_kernel_android_scsi",
-        "libc_asm_arm",
-        "libc_asm_arm64",
-        "libc_asm_riscv64",
-        "libc_asm_x86",
-        "libc_asm_x86_64",
-    ],
 }
 
 ndk_library {
@@ -2980,13 +2918,6 @@
     },
 }
 
-// headers that will be placed on the include path when running versioner in bazel
-// this module should be a no-op in soong
-filegroup {
-    name: "versioner-dependencies",
-    srcs: ["versioner-dependencies/**/*"],
-}
-
 filegroup {
     name: "linux_capability_header",
     srcs: ["kernel/uapi/linux/capability.h"],
diff --git a/libc/NOTICE b/libc/NOTICE
index 1a84d3c..bca4891 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -3585,22 +3585,6 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 2007 Todd C. Miller <millert@openbsd.org>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
 Copyright (c) 2007-2008  Michael G Schwern
 
 This software originally derived from Paul Sheer's pivotal_gmtime_r.c.
@@ -3862,36 +3846,6 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 2011 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.
-
--------------------------------------------------------------------
-
 Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
 
 Permission to use, copy, modify, and distribute this software for any
@@ -3937,36 +3891,6 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 2011, 2012, 2013 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.
-
--------------------------------------------------------------------
-
 Copyright (c) 2011, Intel Corporation
 All rights reserved.
 
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 182de17..8c5572e 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -88,7 +88,6 @@
 int     setregid:setregid(gid_t, gid_t)    lp64
 int     chroot(const char*)  all
 int     prctl(int, unsigned long, unsigned long, unsigned long, unsigned long) all
-long    __arch_prctl:arch_prctl(int, unsigned long) x86_64
 int     capget(cap_user_header_t header, cap_user_data_t data) all
 int     capset(cap_user_header_t header, const cap_user_data_t data) all
 int     sigaltstack(const stack_t*, stack_t*) all
@@ -126,6 +125,7 @@
 int mlock2(const void* addr, size_t len, int flags)    all
 int         munlock(const void* addr, size_t len)   all
 int         mlockall(int flags)   all
+int mseal(void*, size_t, unsigned long) lp64
 int         munlockall()   all
 int         mincore(void*  start, size_t  length, unsigned char*  vec)   all
 int         __ioctl:ioctl(int, int, void*)  all
@@ -350,7 +350,7 @@
 int setdomainname(const char*, size_t)  all
 int sethostname(const char*, size_t)  all
 
-int __sync_file_range:sync_file_range(int, off64_t, off64_t, unsigned int) x86,lp64
+int sync_file_range(int, off64_t, off64_t, unsigned int) x86,lp64
 int __sync_file_range2:sync_file_range2(int, unsigned int, off64_t, off64_t) arm
 
 pid_t wait4(pid_t, int*, int, struct rusage*)  all
@@ -365,6 +365,7 @@
 
 # x86-specific
 int     __set_thread_area:set_thread_area(void*) x86
+long arch_prctl(int, unsigned long) x86_64
 
 # vdso stuff.
 int __clock_getres:clock_getres(clockid_t, struct timespec*) all
diff --git a/libc/arch-arm/dynamic_function_dispatch.cpp b/libc/arch-arm/dynamic_function_dispatch.cpp
index 1d2f38f..f984421 100644
--- a/libc/arch-arm/dynamic_function_dispatch.cpp
+++ b/libc/arch-arm/dynamic_function_dispatch.cpp
@@ -27,27 +27,26 @@
  */
 
 #include <fcntl.h>
-#include <sys/syscall.h>
-
 #include <private/bionic_ifuncs.h>
+#include <sys/syscall.h>
 
 extern "C" {
 
 enum CpuVariant {
-    kUnknown = 0,
-    kGeneric,
-    kCortexA7,
-    kCortexA9,
-    kCortexA53,
-    kCortexA55,
-    kKrait,
-    kKryo,
+  kUnknown = 0,
+  kGeneric,
+  kCortexA7,
+  kCortexA9,
+  kCortexA53,
+  kCortexA55,
+  kKrait,
+  kKryo,
 };
 
 static constexpr int MAX_CPU_NAME_LEN = 12;
 struct CpuVariantNames {
-    alignas(alignof(int)) char name[MAX_CPU_NAME_LEN];
-    CpuVariant variant;
+  alignas(alignof(int)) char name[MAX_CPU_NAME_LEN];
+  CpuVariant variant;
 };
 
 static constexpr CpuVariantNames cpu_variant_names[] = {
@@ -66,227 +65,237 @@
 };
 
 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;
+  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;
+  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;
+  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;
 }
 
 static bool is_same_name(const char* a, const char* b) {
-    static_assert(MAX_CPU_NAME_LEN % sizeof(int) == 0, "");
-    const int* ia = reinterpret_cast<const int*>(a);
-    const int* ib = reinterpret_cast<const int*>(b);
-    for (size_t i = 0; i < MAX_CPU_NAME_LEN / sizeof(int); ++i) {
-        if (ia[i] != ib[i]) {
-            return false;
-        }
+  static_assert(MAX_CPU_NAME_LEN % sizeof(int) == 0, "");
+  const int* ia = reinterpret_cast<const int*>(a);
+  const int* ib = reinterpret_cast<const int*>(b);
+  for (size_t i = 0; i < MAX_CPU_NAME_LEN / sizeof(int); ++i) {
+    if (ia[i] != ib[i]) {
+      return false;
     }
-    return true;
+  }
+  return true;
 }
 
 static CpuVariant init_cpu_variant() {
-    int fd = ifunc_open("/dev/cpu_variant:arm");
-    if (fd < 0) return kGeneric;
+  int fd = ifunc_open("/dev/cpu_variant:arm");
+  if (fd < 0) return kGeneric;
 
-    alignas(alignof(int)) char name[MAX_CPU_NAME_LEN] = {};
+  alignas(alignof(int)) 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);
+  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;
-
-    const CpuVariantNames* cpu_variant = cpu_variant_names;
-    while (cpu_variant->variant != kUnknown) {
-        if (is_same_name(cpu_variant->name, name)) {
-            return cpu_variant->variant;
-        }
-        cpu_variant++;
-    }
+  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;
+
+  const CpuVariantNames* cpu_variant = cpu_variant_names;
+  while (cpu_variant->variant != kUnknown) {
+    if (is_same_name(cpu_variant->name, name)) {
+      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;
+  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_FOR(memmove) {
-    RETURN_FUNC(memmove_func, memmove_a15);
+  RETURN_FUNC(memmove_func_t, memmove_a15);
 }
+MEMMOVE_SHIM()
 
-typedef void* memcpy_func(void*, const void*, size_t);
 DEFINE_IFUNC_FOR(memcpy) {
-    return memmove_resolver(hwcap);
+  return memmove_resolver(hwcap);
 }
+MEMCPY_SHIM()
 
-typedef void* __memcpy_func(void*, const void*, size_t);
+// On arm32, __memcpy() is not publicly exposed, but gets called by memmove()
+// in cases where the copy is known to be overlap-safe.
+typedef void* __memcpy_func_t(void*, const void*, size_t);
 DEFINE_IFUNC_FOR(__memcpy) {
-    switch(get_cpu_variant()) {
-        case kCortexA7:
-            RETURN_FUNC(__memcpy_func, __memcpy_a7);
-        case kCortexA9:
-            RETURN_FUNC(__memcpy_func, __memcpy_a9);
-        case kKrait:
-            RETURN_FUNC(__memcpy_func, __memcpy_krait);
-        case kCortexA53:
-            RETURN_FUNC(__memcpy_func, __memcpy_a53);
-        case kCortexA55:
-            RETURN_FUNC(__memcpy_func, __memcpy_a55);
-        case kKryo:
-            RETURN_FUNC(__memcpy_func, __memcpy_kryo);
-        default:
-            RETURN_FUNC(__memcpy_func, __memcpy_a15);
-    }
+  switch (get_cpu_variant()) {
+    case kCortexA7:
+      RETURN_FUNC(__memcpy_func_t, __memcpy_a7);
+    case kCortexA9:
+      RETURN_FUNC(__memcpy_func_t, __memcpy_a9);
+    case kKrait:
+      RETURN_FUNC(__memcpy_func_t, __memcpy_krait);
+    case kCortexA53:
+      RETURN_FUNC(__memcpy_func_t, __memcpy_a53);
+    case kCortexA55:
+      RETURN_FUNC(__memcpy_func_t, __memcpy_a55);
+    case kKryo:
+      RETURN_FUNC(__memcpy_func_t, __memcpy_kryo);
+    default:
+      RETURN_FUNC(__memcpy_func_t, __memcpy_a15);
+  }
 }
+DEFINE_STATIC_SHIM(void* __memcpy(void* dst, const void* src, size_t n) {
+  FORWARD(__memcpy)(dst, src, n);
+})
 
-typedef void* __memset_chk_func(void* s, int c, size_t n, size_t n2);
 DEFINE_IFUNC_FOR(__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);
-        default:
-            RETURN_FUNC(__memset_chk_func, __memset_chk_a15);
-    }
+  switch (get_cpu_variant()) {
+    case kCortexA7:
+    case kCortexA53:
+    case kCortexA55:
+    case kKryo:
+      RETURN_FUNC(__memset_chk_func_t, __memset_chk_a7);
+    case kCortexA9:
+      RETURN_FUNC(__memset_chk_func_t, __memset_chk_a9);
+    case kKrait:
+      RETURN_FUNC(__memset_chk_func_t, __memset_chk_krait);
+    default:
+      RETURN_FUNC(__memset_chk_func_t, __memset_chk_a15);
+  }
 }
+__MEMSET_CHK_SHIM()
 
-typedef void* memset_func(void* __dst, int __ch, size_t __n);
 DEFINE_IFUNC_FOR(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);
-        default:
-             RETURN_FUNC(memset_func, memset_a15);
-    }
+  switch (get_cpu_variant()) {
+    case kCortexA7:
+    case kCortexA53:
+    case kCortexA55:
+    case kKryo:
+      RETURN_FUNC(memset_func_t, memset_a7);
+    case kCortexA9:
+      RETURN_FUNC(memset_func_t, memset_a9);
+    case kKrait:
+      RETURN_FUNC(memset_func_t, memset_krait);
+    default:
+      RETURN_FUNC(memset_func_t, memset_a15);
+  }
 }
+MEMSET_SHIM()
 
-typedef char* strcpy_func(char* __dst, const char* __src);
 DEFINE_IFUNC_FOR(strcpy) {
-    switch(get_cpu_variant()) {
-        case kCortexA9:
-            RETURN_FUNC(strcpy_func, strcpy_a9);
-        default:
-            RETURN_FUNC(strcpy_func, strcpy_a15);
-    }
+  switch (get_cpu_variant()) {
+    case kCortexA9:
+      RETURN_FUNC(strcpy_func_t, strcpy_a9);
+    default:
+      RETURN_FUNC(strcpy_func_t, strcpy_a15);
+  }
 }
+STRCPY_SHIM()
 
-typedef char* __strcpy_chk_func(char* dst, const char* src, size_t dst_len);
 DEFINE_IFUNC_FOR(__strcpy_chk) {
-    switch(get_cpu_variant()) {
-        case kCortexA7:
-            RETURN_FUNC(__strcpy_chk_func, __strcpy_chk_a7);
-        case kCortexA9:
-            RETURN_FUNC(__strcpy_chk_func, __strcpy_chk_a9);
-        case kKrait:
-        case kKryo:
-            RETURN_FUNC(__strcpy_chk_func, __strcpy_chk_krait);
-        case kCortexA53:
-            RETURN_FUNC(__strcpy_chk_func, __strcpy_chk_a53);
-        case kCortexA55:
-            RETURN_FUNC(__strcpy_chk_func, __strcpy_chk_a55);
-        default:
-            RETURN_FUNC(__strcpy_chk_func, __strcpy_chk_a15);
-    }
+  switch (get_cpu_variant()) {
+    case kCortexA7:
+      RETURN_FUNC(__strcpy_chk_func_t, __strcpy_chk_a7);
+    case kCortexA9:
+      RETURN_FUNC(__strcpy_chk_func_t, __strcpy_chk_a9);
+    case kKrait:
+    case kKryo:
+      RETURN_FUNC(__strcpy_chk_func_t, __strcpy_chk_krait);
+    case kCortexA53:
+      RETURN_FUNC(__strcpy_chk_func_t, __strcpy_chk_a53);
+    case kCortexA55:
+      RETURN_FUNC(__strcpy_chk_func_t, __strcpy_chk_a55);
+    default:
+      RETURN_FUNC(__strcpy_chk_func_t, __strcpy_chk_a15);
+  }
 }
+__STRCPY_CHK_SHIM()
 
-typedef char* stpcpy_func(char* __dst, const char* __src);
 DEFINE_IFUNC_FOR(stpcpy) {
-    switch(get_cpu_variant()) {
-        case kCortexA9:
-            RETURN_FUNC(stpcpy_func, stpcpy_a9);
-        default:
-            RETURN_FUNC(stpcpy_func, stpcpy_a15);
-    }
+  switch (get_cpu_variant()) {
+    case kCortexA9:
+      RETURN_FUNC(stpcpy_func_t, stpcpy_a9);
+    default:
+      RETURN_FUNC(stpcpy_func_t, stpcpy_a15);
+  }
 }
+STPCPY_SHIM()
 
-typedef char* strcat_func(char* __dst, const char* __src);
 DEFINE_IFUNC_FOR(strcat) {
-    switch(get_cpu_variant()) {
-        case kCortexA9:
-            RETURN_FUNC(strcat_func, strcat_a9);
-        default:
-            RETURN_FUNC(strcat_func, strcat_a15);
-    }
+  switch (get_cpu_variant()) {
+    case kCortexA9:
+      RETURN_FUNC(strcat_func_t, strcat_a9);
+    default:
+      RETURN_FUNC(strcat_func_t, strcat_a15);
+  }
 }
+STRCAT_SHIM()
 
-typedef char* __strcat_chk_func(char* dst, const char* src, size_t dst_buf_size);
 DEFINE_IFUNC_FOR(__strcat_chk) {
-    switch(get_cpu_variant()) {
-        case kCortexA7:
-            RETURN_FUNC(__strcat_chk_func, __strcat_chk_a7);
-        case kCortexA9:
-            RETURN_FUNC(__strcat_chk_func, __strcat_chk_a9);
-        case kKrait:
-        case kKryo:
-            RETURN_FUNC(__strcat_chk_func, __strcat_chk_krait);
-        case kCortexA53:
-            RETURN_FUNC(__strcat_chk_func, __strcat_chk_a53);
-        case kCortexA55:
-            RETURN_FUNC(__strcat_chk_func, __strcat_chk_a55);
-        default:
-            RETURN_FUNC(__strcat_chk_func, __strcat_chk_a15);
-    }
+  switch (get_cpu_variant()) {
+    case kCortexA7:
+      RETURN_FUNC(__strcat_chk_func_t, __strcat_chk_a7);
+    case kCortexA9:
+      RETURN_FUNC(__strcat_chk_func_t, __strcat_chk_a9);
+    case kKrait:
+    case kKryo:
+      RETURN_FUNC(__strcat_chk_func_t, __strcat_chk_krait);
+    case kCortexA53:
+      RETURN_FUNC(__strcat_chk_func_t, __strcat_chk_a53);
+    case kCortexA55:
+      RETURN_FUNC(__strcat_chk_func_t, __strcat_chk_a55);
+    default:
+      RETURN_FUNC(__strcat_chk_func_t, __strcat_chk_a15);
+  }
 }
+__STRCAT_CHK_SHIM()
 
-typedef int strcmp_func(const char* __lhs, const char* __rhs);
 DEFINE_IFUNC_FOR(strcmp) {
-    RETURN_FUNC(strcmp_func, strcmp_a15);
+  RETURN_FUNC(strcmp_func_t, strcmp_a15);
 }
+STRCMP_SHIM()
 
-typedef size_t strlen_func(const char* __s);
 DEFINE_IFUNC_FOR(strlen) {
-    switch(get_cpu_variant()) {
-        case kCortexA9:
-            RETURN_FUNC(strlen_func, strlen_a9);
-        default:
-            RETURN_FUNC(strlen_func, strlen_a15);
-    }
+  switch (get_cpu_variant()) {
+    case kCortexA9:
+      RETURN_FUNC(strlen_func_t, strlen_a9);
+    default:
+      RETURN_FUNC(strlen_func_t, strlen_a15);
+  }
 }
+STRLEN_SHIM()
 
 }  // extern "C"
diff --git a/libc/arch-arm64/dynamic_function_dispatch.cpp b/libc/arch-arm64/dynamic_function_dispatch.cpp
index f9e4263..29e47b3 100644
--- a/libc/arch-arm64/dynamic_function_dispatch.cpp
+++ b/libc/arch-arm64/dynamic_function_dispatch.cpp
@@ -28,148 +28,147 @@
 
 #include <private/bionic_ifuncs.h>
 #include <stddef.h>
-#include <sys/auxv.h>
 
 static inline bool __bionic_is_oryon(unsigned long hwcap) {
-    if (!(hwcap & HWCAP_CPUID)) return false;
+  if (!(hwcap & HWCAP_CPUID)) return false;
 
-    // Extract the implementor and variant bits from MIDR_EL1.
-    // https://www.kernel.org/doc/html/latest/arch/arm64/cpu-feature-registers.html#list-of-registers-with-visible-features
-    unsigned long midr;
-    __asm__ __volatile__("mrs %0, MIDR_EL1" : "=r"(midr));
-    uint16_t cpu = (midr >> 20) & 0xfff;
+  // Extract the implementor and variant bits from MIDR_EL1.
+  // https://www.kernel.org/doc/html/latest/arch/arm64/cpu-feature-registers.html#list-of-registers-with-visible-features
+  unsigned long midr;
+  __asm__ __volatile__("mrs %0, MIDR_EL1" : "=r"(midr));
+  uint16_t cpu = (midr >> 20) & 0xfff;
 
-    auto make_cpu = [](unsigned implementor, unsigned variant) {
-        return (implementor << 4) | variant;
-    };
+  auto make_cpu = [](unsigned implementor, unsigned variant) {
+    return (implementor << 4) | variant;
+  };
 
-    // Check for implementor Qualcomm's variants 0x1..0x5 (Oryon).
-    return cpu >= make_cpu('Q', 0x1) && cpu <= make_cpu('Q', 0x5);
+  // Check for implementor Qualcomm's variants 0x1..0x5 (Oryon).
+  return cpu >= make_cpu('Q', 0x1) && cpu <= make_cpu('Q', 0x5);
 }
 
 extern "C" {
 
-typedef void* memchr_func(const void*, int, size_t);
 DEFINE_IFUNC_FOR(memchr) {
-    if (arg->_hwcap2 & HWCAP2_MTE) {
-        RETURN_FUNC(memchr_func, __memchr_aarch64_mte);
-    } else {
-        RETURN_FUNC(memchr_func, __memchr_aarch64);
-    }
-}
-
-typedef int memcmp_func(const void*, const void*, size_t);
-DEFINE_IFUNC_FOR(memcmp) {
-    // TODO: enable the SVE version.
-    RETURN_FUNC(memcmp_func, __memcmp_aarch64);
-}
-
-typedef void* memcpy_func(void*, const void*, size_t);
-DEFINE_IFUNC_FOR(memcpy) {
-    if (arg->_hwcap2 & HWCAP2_MOPS) {
-        RETURN_FUNC(memcpy_func, __memmove_aarch64_mops);
-    } else if (__bionic_is_oryon(arg->_hwcap)) {
-        RETURN_FUNC(memcpy_func, __memcpy_aarch64_nt);
-    } else if (arg->_hwcap & HWCAP_ASIMD) {
-        RETURN_FUNC(memcpy_func, __memcpy_aarch64_simd);
-    } else {
-        RETURN_FUNC(memcpy_func, __memcpy_aarch64);
-    }
-}
-
-typedef void* memmove_func(void*, const void*, size_t);
-DEFINE_IFUNC_FOR(memmove) {
-  if (arg->_hwcap2 & HWCAP2_MOPS) {
-    RETURN_FUNC(memmove_func, __memmove_aarch64_mops);
-  } else if (__bionic_is_oryon(arg->_hwcap)) {
-    RETURN_FUNC(memcpy_func, __memmove_aarch64_nt);
-  } else if (arg->_hwcap & HWCAP_ASIMD) {
-    RETURN_FUNC(memmove_func, __memmove_aarch64_simd);
+  if (arg->_hwcap2 & HWCAP2_MTE) {
+    RETURN_FUNC(memchr_func_t, __memchr_aarch64_mte);
   } else {
-    RETURN_FUNC(memmove_func, __memmove_aarch64);
+    RETURN_FUNC(memchr_func_t, __memchr_aarch64);
   }
 }
+MEMCHR_SHIM()
 
-typedef int memrchr_func(const void*, int, size_t);
+DEFINE_IFUNC_FOR(memcmp) {
+  // TODO: enable the SVE version.
+  RETURN_FUNC(memcmp_func_t, __memcmp_aarch64);
+}
+MEMCMP_SHIM()
+
+DEFINE_IFUNC_FOR(memcpy) {
+  if (arg->_hwcap2 & HWCAP2_MOPS) {
+    RETURN_FUNC(memcpy_func_t, __memmove_aarch64_mops);
+  } else if (__bionic_is_oryon(arg->_hwcap)) {
+    RETURN_FUNC(memcpy_func_t, __memcpy_aarch64_nt);
+  } else if (arg->_hwcap & HWCAP_ASIMD) {
+    RETURN_FUNC(memcpy_func_t, __memcpy_aarch64_simd);
+  } else {
+    RETURN_FUNC(memcpy_func_t, __memcpy_aarch64);
+  }
+}
+MEMCPY_SHIM()
+
+DEFINE_IFUNC_FOR(memmove) {
+  if (arg->_hwcap2 & HWCAP2_MOPS) {
+    RETURN_FUNC(memmove_func_t, __memmove_aarch64_mops);
+  } else if (__bionic_is_oryon(arg->_hwcap)) {
+    RETURN_FUNC(memmove_func_t, __memmove_aarch64_nt);
+  } else if (arg->_hwcap & HWCAP_ASIMD) {
+    RETURN_FUNC(memmove_func_t, __memmove_aarch64_simd);
+  } else {
+    RETURN_FUNC(memmove_func_t, __memmove_aarch64);
+  }
+}
+MEMMOVE_SHIM()
+
 DEFINE_IFUNC_FOR(memrchr) {
-    RETURN_FUNC(memrchr_func, __memrchr_aarch64);
+  RETURN_FUNC(memrchr_func_t, __memrchr_aarch64);
 }
+MEMRCHR_SHIM()
 
-typedef int memset_func(void*, int, size_t);
 DEFINE_IFUNC_FOR(memset) {
-    if (arg->_hwcap2 & HWCAP2_MOPS) {
-        RETURN_FUNC(memset_func, __memset_aarch64_mops);
-    } else if (__bionic_is_oryon(arg->_hwcap)) {
-        RETURN_FUNC(memset_func, __memset_aarch64_nt);
-    } else {
-        RETURN_FUNC(memset_func, __memset_aarch64);
-    }
+  if (arg->_hwcap2 & HWCAP2_MOPS) {
+    RETURN_FUNC(memset_func_t, __memset_aarch64_mops);
+  } else if (__bionic_is_oryon(arg->_hwcap)) {
+    RETURN_FUNC(memset_func_t, __memset_aarch64_nt);
+  } else {
+    RETURN_FUNC(memset_func_t, __memset_aarch64);
+  }
 }
+MEMSET_SHIM()
 
-typedef char* stpcpy_func(char*, const char*, size_t);
 DEFINE_IFUNC_FOR(stpcpy) {
-    // TODO: enable the SVE version.
-    RETURN_FUNC(stpcpy_func, __stpcpy_aarch64);
+  // TODO: enable the SVE version.
+  RETURN_FUNC(stpcpy_func_t, __stpcpy_aarch64);
 }
+STPCPY_SHIM()
 
-typedef char* strchr_func(const char*, int);
 DEFINE_IFUNC_FOR(strchr) {
-    if (arg->_hwcap2 & HWCAP2_MTE) {
-        RETURN_FUNC(strchr_func, __strchr_aarch64_mte);
-    } else {
-        RETURN_FUNC(strchr_func, __strchr_aarch64);
-    }
+  if (arg->_hwcap2 & HWCAP2_MTE) {
+    RETURN_FUNC(strchr_func_t, __strchr_aarch64_mte);
+  } else {
+    RETURN_FUNC(strchr_func_t, __strchr_aarch64);
+  }
 }
+STRCHR_SHIM()
 
-typedef char* strchrnul_func(const char*, int);
 DEFINE_IFUNC_FOR(strchrnul) {
-    if (arg->_hwcap2 & HWCAP2_MTE) {
-        RETURN_FUNC(strchrnul_func, __strchrnul_aarch64_mte);
-    } else {
-        RETURN_FUNC(strchrnul_func, __strchrnul_aarch64);
-    }
+  if (arg->_hwcap2 & HWCAP2_MTE) {
+    RETURN_FUNC(strchrnul_func_t, __strchrnul_aarch64_mte);
+  } else {
+    RETURN_FUNC(strchrnul_func_t, __strchrnul_aarch64);
+  }
 }
+STRCHRNUL_SHIM()
 
-typedef int strcmp_func(const char*, const char*);
 DEFINE_IFUNC_FOR(strcmp) {
-    // TODO: enable the SVE version.
-    RETURN_FUNC(strcmp_func, __strcmp_aarch64);
+  // TODO: enable the SVE version.
+  RETURN_FUNC(strcmp_func_t, __strcmp_aarch64);
 }
+STRCMP_SHIM()
 
-typedef char* strcpy_func(char*, const char*);
 DEFINE_IFUNC_FOR(strcpy) {
-    // TODO: enable the SVE version.
-    RETURN_FUNC(strcpy_func, __strcpy_aarch64);
+  // TODO: enable the SVE version.
+  RETURN_FUNC(strcpy_func_t, __strcpy_aarch64);
 }
+STRCPY_SHIM()
 
-typedef size_t strlen_func(const char*);
 DEFINE_IFUNC_FOR(strlen) {
-    if (arg->_hwcap2 & HWCAP2_MTE) {
-        RETURN_FUNC(strlen_func, __strlen_aarch64_mte);
-    } else {
-        RETURN_FUNC(strlen_func, __strlen_aarch64);
-    }
+  if (arg->_hwcap2 & HWCAP2_MTE) {
+    RETURN_FUNC(strlen_func_t, __strlen_aarch64_mte);
+  } else {
+    RETURN_FUNC(strlen_func_t, __strlen_aarch64);
+  }
 }
+STRLEN_SHIM()
 
-typedef int strncmp_func(const char*, const char*, size_t);
 DEFINE_IFUNC_FOR(strncmp) {
-    // TODO: enable the SVE version.
-    RETURN_FUNC(strncmp_func, __strncmp_aarch64);
+  // TODO: enable the SVE version.
+  RETURN_FUNC(strncmp_func_t, __strncmp_aarch64);
 }
+STRNCMP_SHIM()
 
-typedef size_t strnlen_func(const char*, size_t);
 DEFINE_IFUNC_FOR(strnlen) {
-    // TODO: enable the SVE version.
-    RETURN_FUNC(strnlen_func, __strnlen_aarch64);
+  // TODO: enable the SVE version.
+  RETURN_FUNC(strnlen_func_t, __strnlen_aarch64);
 }
+STRNLEN_SHIM()
 
-typedef char* strrchr_func(const char*, int);
 DEFINE_IFUNC_FOR(strrchr) {
-    if (arg->_hwcap2 & HWCAP2_MTE) {
-        RETURN_FUNC(strrchr_func, __strrchr_aarch64_mte);
-    } else {
-        RETURN_FUNC(strrchr_func, __strrchr_aarch64);
-    }
+  if (arg->_hwcap2 & HWCAP2_MTE) {
+    RETURN_FUNC(strrchr_func_t, __strrchr_aarch64_mte);
+  } else {
+    RETURN_FUNC(strrchr_func_t, __strrchr_aarch64);
+  }
 }
+STRRCHR_SHIM()
 
 }  // extern "C"
diff --git a/libc/arch-arm64/static_function_dispatch.S b/libc/arch-arm64/static_function_dispatch.S
deleted file mode 100644
index 18c3783..0000000
--- a/libc/arch-arm64/static_function_dispatch.S
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2019 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 <private/bionic_asm.h>
-
-#define FUNCTION_DELEGATE(name, impl) \
-ENTRY(name); \
-    b impl; \
-END(name)
-
-FUNCTION_DELEGATE(memchr, __memchr_aarch64_mte)
-FUNCTION_DELEGATE(memcmp, __memcmp_aarch64)
-FUNCTION_DELEGATE(memcpy, __memcpy_aarch64)
-FUNCTION_DELEGATE(memmove, __memmove_aarch64)
-FUNCTION_DELEGATE(memrchr, __memrchr_aarch64)
-FUNCTION_DELEGATE(memset, __memset_aarch64)
-FUNCTION_DELEGATE(stpcpy, __stpcpy_aarch64)
-FUNCTION_DELEGATE(strchr, __strchr_aarch64_mte)
-FUNCTION_DELEGATE(strchrnul, __strchrnul_aarch64_mte)
-FUNCTION_DELEGATE(strcmp, __strcmp_aarch64)
-FUNCTION_DELEGATE(strcpy, __strcpy_aarch64)
-FUNCTION_DELEGATE(strlen, __strlen_aarch64_mte)
-FUNCTION_DELEGATE(strrchr, __strrchr_aarch64_mte)
-FUNCTION_DELEGATE(strncmp, __strncmp_aarch64)
-FUNCTION_DELEGATE(strnlen, __strnlen_aarch64)
-
-NOTE_GNU_PROPERTY()
diff --git a/libc/arch-common/bionic/crt_pad_segment.S b/libc/arch-common/bionic/crt_pad_segment.S
index 86c730d..2fbe0b9 100644
--- a/libc/arch-common/bionic/crt_pad_segment.S
+++ b/libc/arch-common/bionic/crt_pad_segment.S
@@ -26,6 +26,12 @@
  * SUCH DAMAGE.
  */
 
+#if defined(__aarch64__)
+#include <private/bionic_asm_arm64.h>
+
+__bionic_asm_custom_note_gnu_section()
+#endif
+
 #include <private/bionic_asm_note.h>
 
   .section ".note.android.pad_segment", "a", %note
diff --git a/libc/arch-riscv64/dynamic_function_dispatch.cpp b/libc/arch-riscv64/dynamic_function_dispatch.cpp
index bb2ba51..ce6c028 100644
--- a/libc/arch-riscv64/dynamic_function_dispatch.cpp
+++ b/libc/arch-riscv64/dynamic_function_dispatch.cpp
@@ -27,12 +27,11 @@
  */
 
 #include <fcntl.h>
+#include <private/bionic_ifuncs.h>
 #include <stddef.h>
 #include <sys/syscall.h>
 #include <unistd.h>
 
-#include <private/bionic_ifuncs.h>
-
 extern "C" {
 
 static inline __always_inline int ifunc_faccessat(int dir_fd, const char* path, int mode) {
@@ -53,94 +52,94 @@
   return result;
 }
 
-typedef void* memchr_func(const void*, int, size_t);
 DEFINE_IFUNC_FOR(memchr) {
-  if (have_fast_v()) RETURN_FUNC(memchr_func, memchr_v);
-  RETURN_FUNC(memchr_func, memchr_gc);
+  if (have_fast_v()) RETURN_FUNC(memchr_func_t, memchr_v);
+  RETURN_FUNC(memchr_func_t, memchr_gc);
 }
+MEMCHR_SHIM()
 
-typedef int memcmp_func(const void*, const void*, size_t);
 DEFINE_IFUNC_FOR(memcmp) {
-  if (have_fast_v()) RETURN_FUNC(memcmp_func, memcmp_v);
-  RETURN_FUNC(memcmp_func, memcmp_gc);
+  if (have_fast_v()) RETURN_FUNC(memcmp_func_t, memcmp_v);
+  RETURN_FUNC(memcmp_func_t, memcmp_gc);
 }
+MEMCMP_SHIM()
 
-typedef void* memcpy_func(void*, const void*, size_t);
 DEFINE_IFUNC_FOR(memcpy) {
-  if (have_fast_v()) RETURN_FUNC(memcpy_func, memcpy_v);
-  RETURN_FUNC(memcpy_func, memcpy_gc);
+  if (have_fast_v()) RETURN_FUNC(memcpy_func_t, memcpy_v);
+  RETURN_FUNC(memcpy_func_t, memcpy_gc);
 }
+MEMCPY_SHIM()
 
-typedef void* memmove_func(void*, const void*, size_t);
 DEFINE_IFUNC_FOR(memmove) {
-  if (have_fast_v()) RETURN_FUNC(memmove_func, memmove_v);
-  RETURN_FUNC(memmove_func, memmove_gc);
+  if (have_fast_v()) RETURN_FUNC(memmove_func_t, memmove_v);
+  RETURN_FUNC(memmove_func_t, memmove_gc);
 }
+MEMMOVE_SHIM()
 
-typedef void* memset_func(void*, int, size_t);
 DEFINE_IFUNC_FOR(memset) {
-  if (have_fast_v()) RETURN_FUNC(memset_func, memset_v);
-  RETURN_FUNC(memset_func, memset_gc);
+  if (have_fast_v()) RETURN_FUNC(memset_func_t, memset_v);
+  RETURN_FUNC(memset_func_t, memset_gc);
 }
+MEMSET_SHIM()
 
-typedef char* stpcpy_func(char*, const char*);
 DEFINE_IFUNC_FOR(stpcpy) {
-  if (have_fast_v()) RETURN_FUNC(stpcpy_func, stpcpy_v);
-  RETURN_FUNC(stpcpy_func, stpcpy_gc);
+  if (have_fast_v()) RETURN_FUNC(stpcpy_func_t, stpcpy_v);
+  RETURN_FUNC(stpcpy_func_t, stpcpy_gc);
 }
+STPCPY_SHIM()
 
-typedef char* strcat_func(char*, const char*);
 DEFINE_IFUNC_FOR(strcat) {
-  if (have_fast_v()) RETURN_FUNC(strcat_func, strcat_v);
-  RETURN_FUNC(strcat_func, strcat_gc);
+  if (have_fast_v()) RETURN_FUNC(strcat_func_t, strcat_v);
+  RETURN_FUNC(strcat_func_t, strcat_gc);
 }
+STRCAT_SHIM()
 
-typedef char* strchr_func(const char*, int);
 DEFINE_IFUNC_FOR(strchr) {
-  if (have_fast_v()) RETURN_FUNC(strchr_func, strchr_v);
-  RETURN_FUNC(strchr_func, strchr_gc);
+  if (have_fast_v()) RETURN_FUNC(strchr_func_t, strchr_v);
+  RETURN_FUNC(strchr_func_t, strchr_gc);
 }
+STRCHR_SHIM()
 
-typedef int strcmp_func(const char*, const char*);
 DEFINE_IFUNC_FOR(strcmp) {
-  if (have_fast_v()) RETURN_FUNC(strcmp_func, strcmp_v);
-  RETURN_FUNC(strcmp_func, strcmp_gc);
+  if (have_fast_v()) RETURN_FUNC(strcmp_func_t, strcmp_v);
+  RETURN_FUNC(strcmp_func_t, strcmp_gc);
 }
+STRCMP_SHIM()
 
-typedef char* strcpy_func(char*, const char*);
 DEFINE_IFUNC_FOR(strcpy) {
-  if (have_fast_v()) RETURN_FUNC(strcpy_func, strcpy_v);
-  RETURN_FUNC(strcpy_func, strcpy_gc);
+  if (have_fast_v()) RETURN_FUNC(strcpy_func_t, strcpy_v);
+  RETURN_FUNC(strcpy_func_t, strcpy_gc);
 }
+STRCPY_SHIM()
 
-typedef size_t strlen_func(const char*);
 DEFINE_IFUNC_FOR(strlen) {
-  if (have_fast_v()) RETURN_FUNC(strlen_func, strlen_v);
-  RETURN_FUNC(strlen_func, strlen_gc);
+  if (have_fast_v()) RETURN_FUNC(strlen_func_t, strlen_v);
+  RETURN_FUNC(strlen_func_t, strlen_gc);
 }
+STRLEN_SHIM()
 
-typedef char* strncat_func(char*, const char*, size_t);
 DEFINE_IFUNC_FOR(strncat) {
-  if (have_fast_v()) RETURN_FUNC(strncat_func, strncat_v);
-  RETURN_FUNC(strncat_func, strncat_gc);
+  if (have_fast_v()) RETURN_FUNC(strncat_func_t, strncat_v);
+  RETURN_FUNC(strncat_func_t, strncat_gc);
 }
+STRNCAT_SHIM()
 
-typedef int strncmp_func(const char*, const char*, size_t);
 DEFINE_IFUNC_FOR(strncmp) {
-  if (have_fast_v()) RETURN_FUNC(strncmp_func, strncmp_v);
-  RETURN_FUNC(strncmp_func, strncmp_gc);
+  if (have_fast_v()) RETURN_FUNC(strncmp_func_t, strncmp_v);
+  RETURN_FUNC(strncmp_func_t, strncmp_gc);
 }
+STRNCMP_SHIM()
 
-typedef char* strncpy_func(char*, const char*, size_t);
 DEFINE_IFUNC_FOR(strncpy) {
-  if (have_fast_v()) RETURN_FUNC(strncpy_func, strncpy_v);
-  RETURN_FUNC(strncpy_func, strncpy_gc);
+  if (have_fast_v()) RETURN_FUNC(strncpy_func_t, strncpy_v);
+  RETURN_FUNC(strncpy_func_t, strncpy_gc);
 }
+STRNCPY_SHIM()
 
-typedef size_t strnlen_func(const char*, size_t);
 DEFINE_IFUNC_FOR(strnlen) {
-  if (have_fast_v()) RETURN_FUNC(strnlen_func, strnlen_v);
-  RETURN_FUNC(strnlen_func, strnlen_gc);
+  if (have_fast_v()) RETURN_FUNC(strnlen_func_t, strnlen_v);
+  RETURN_FUNC(strnlen_func_t, strnlen_gc);
 }
+STRNLEN_SHIM()
 
 }  // extern "C"
diff --git a/libc/arch-riscv64/static_function_dispatch.S b/libc/arch-riscv64/static_function_dispatch.S
deleted file mode 100644
index accfec8..0000000
--- a/libc/arch-riscv64/static_function_dispatch.S
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2023 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 <private/bionic_asm.h>
-
-#define FUNCTION_DELEGATE(name, impl) \
-ENTRY(name); \
-    j impl; \
-END(name)
-
-// TODO: switch to the V variants when qemu is fixed.
-FUNCTION_DELEGATE(memchr, memchr_gc)
-FUNCTION_DELEGATE(memcmp, memcmp_gc)
-FUNCTION_DELEGATE(memcpy, memcpy_gc)
-FUNCTION_DELEGATE(memmove, memmove_gc)
-FUNCTION_DELEGATE(memset, memset_gc)
-FUNCTION_DELEGATE(stpcpy, stpcpy_gc)
-FUNCTION_DELEGATE(strcat, strcat_gc)
-FUNCTION_DELEGATE(strchr, strchr_gc)
-FUNCTION_DELEGATE(strcmp, strcmp_gc)
-FUNCTION_DELEGATE(strcpy, strcpy_gc)
-FUNCTION_DELEGATE(strlen, strlen_gc)
-FUNCTION_DELEGATE(strncat, strncat_gc)
-FUNCTION_DELEGATE(strncmp, strncmp_gc)
-FUNCTION_DELEGATE(strncpy, strncpy_gc)
-FUNCTION_DELEGATE(strnlen, strnlen_gc)
diff --git a/libc/arch-x86/dynamic_function_dispatch.cpp b/libc/arch-x86/dynamic_function_dispatch.cpp
index 38d8a0a..240fcdf 100644
--- a/libc/arch-x86/dynamic_function_dispatch.cpp
+++ b/libc/arch-x86/dynamic_function_dispatch.cpp
@@ -26,129 +26,16 @@
  * SUCH DAMAGE.
  */
 
-#include <stddef.h>
-
 #include <private/bionic_ifuncs.h>
+#include <stddef.h>
 
 extern "C" {
 
-typedef int memcmp_func(const void* __lhs, const void* __rhs, size_t __n);
 DEFINE_IFUNC_FOR(memcmp) {
-    __builtin_cpu_init();
-    if (__builtin_cpu_is("atom")) RETURN_FUNC(memcmp_func, memcmp_atom);
-    if (__builtin_cpu_supports("sse4.1")) RETURN_FUNC(memcmp_func, memcmp_sse4);
-    RETURN_FUNC(memcmp_func, memcmp_generic);
+  __builtin_cpu_init();
+  if (__builtin_cpu_supports("sse4.1")) RETURN_FUNC(memcmp_func_t, memcmp_sse4);
+  RETURN_FUNC(memcmp_func_t, memcmp_atom);
 }
-
-typedef void* memset_func(void* __dst, int __ch, size_t __n);
-DEFINE_IFUNC_FOR(memset) {
-    __builtin_cpu_init();
-    if (__builtin_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 (__builtin_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 (__builtin_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 (__builtin_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 (__builtin_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 (__builtin_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 (__builtin_cpu_supports("sse4.1")) RETURN_FUNC(wmemcmp_func, wmemcmp_sse4);
-    if (__builtin_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 (__builtin_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 (__builtin_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 (__builtin_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 (__builtin_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 (__builtin_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 (__builtin_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 (__builtin_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 (__builtin_cpu_supports("ssse3")) RETURN_FUNC(wcscpy_func, wcscpy_ssse3);
-    RETURN_FUNC(wcscpy_func, wcscpy_freebsd);
-}
+MEMCMP_SHIM()
 
 }  // extern "C"
diff --git a/libc/arch-x86/generic/string/memcmp.S b/libc/arch-x86/generic/string/memcmp.S
deleted file mode 100644
index 1d327c7..0000000
--- a/libc/arch-x86/generic/string/memcmp.S
+++ /dev/null
@@ -1,44 +0,0 @@
-/*	$OpenBSD: memcmp.S,v 1.4 2005/08/07 11:30:38 espie Exp $ */
-/*
- * Written by J.T. Conklin <jtc@netbsd.org>.
- * Public domain.
- */
-
-#include <private/bionic_asm.h>
-
-ENTRY(memcmp_generic)
-	pushl	%edi
-	pushl	%esi
-	movl	12(%esp),%edi
-	movl	16(%esp),%esi
-	cld				/* set compare direction forward */
-
-	movl	20(%esp),%ecx		/* compare by words */
-	shrl	$2,%ecx
-	repe
-	cmpsl
-	jne	L5			/* do we match so far? */
-
-	movl	20(%esp),%ecx		/* compare remainder by bytes */
-	andl	$3,%ecx
-	repe
-	cmpsb
-	jne	L6			/* do we match? */
-
-	xorl	%eax,%eax		/* we match, return zero	*/
-	popl	%esi
-	popl	%edi
-	ret
-
-L5:	movl	$4,%ecx			/* We know that one of the next	*/
-	subl	%ecx,%edi		/* four pairs of bytes do not	*/
-	subl	%ecx,%esi		/* match.			*/
-	repe
-	cmpsb
-L6:	movzbl  -1(%edi),%eax		/* Perform unsigned comparison	*/
-	movzbl	-1(%esi),%edx
-	subl	%edx,%eax
-	popl	%esi
-	popl	%edi
-	ret
-END(memcmp_generic)
diff --git a/libc/arch-x86/generic/string/strcat.S b/libc/arch-x86/generic/string/strcat.S
deleted file mode 100644
index e2e9623..0000000
--- a/libc/arch-x86/generic/string/strcat.S
+++ /dev/null
@@ -1,74 +0,0 @@
-/*	$OpenBSD: strcat.S,v 1.8 2005/08/07 11:30:38 espie Exp $ */
-/*
- * Written by J.T. Conklin <jtc@netbsd.org>.
- * Public domain.
- */
-
-#include <private/bionic_asm.h>
-
-#if defined(APIWARN)
-#APP
-	.section .gnu.warning.strcat
-	.ascii "warning: strcat() is almost always misused, please use strlcat()"
-#NO_APP
-#endif
-
-/*
- * NOTE: I've unrolled the loop eight times: large enough to make a
- * significant difference, and small enough not to totally trash the
- * cache.
- */
-
-ENTRY(strcat_generic)
-	pushl	%edi			/* save edi */
-	movl	8(%esp),%edi		/* dst address */
-	movl	12(%esp),%edx		/* src address */
-	pushl	%edi			/* push destination address */
-
-	cld				/* set search forward */
-	xorl	%eax,%eax		/* set search for null terminator */
-	movl	$-1,%ecx		/* set search for lots of characters */
-	repne				/* search! */
-	scasb
-
-	leal	-1(%edi),%ecx		/* correct dst address */
-
-	.align 2,0x90
-L1:	movb	(%edx),%al		/* unroll loop, but not too much */
-	movb	%al,(%ecx)
-	testb	%al,%al
-	jz	L2
-	movb	1(%edx),%al
-	movb	%al,1(%ecx)
-	testb	%al,%al
-	jz	L2
-	movb	2(%edx),%al
-	movb	%al,2(%ecx)
-	testb	%al,%al
-	jz	L2
-	movb	3(%edx),%al
-	movb	%al,3(%ecx)
-	testb	%al,%al
-	jz	L2
-	movb	4(%edx),%al
-	movb	%al,4(%ecx)
-	testb	%al,%al
-	jz	L2
-	movb	5(%edx),%al
-	movb	%al,5(%ecx)
-	testb	%al,%al
-	jz	L2
-	movb	6(%edx),%al
-	movb	%al,6(%ecx)
-	testb	%al,%al
-	jz	L2
-	movb	7(%edx),%al
-	movb	%al,7(%ecx)
-	addl	$8,%edx
-	addl	$8,%ecx
-	testb	%al,%al
-	jnz	L1
-L2:	popl	%eax			/* pop destination address */
-	popl	%edi			/* restore edi */
-	ret
-END(strcat_generic)
diff --git a/libc/arch-x86/generic/string/strcmp.S b/libc/arch-x86/generic/string/strcmp.S
deleted file mode 100644
index 7b003e8..0000000
--- a/libc/arch-x86/generic/string/strcmp.S
+++ /dev/null
@@ -1,82 +0,0 @@
-/*	$OpenBSD: strcmp.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
-/*
- * Written by J.T. Conklin <jtc@netbsd.org>.
- * Public domain.
- */
-
-#include <private/bionic_asm.h>
-
-/*
- * NOTE: I've unrolled the loop eight times: large enough to make a
- * significant difference, and small enough not to totally trash the
- * cache.
- */
-
-ENTRY(strcmp_generic)
-	movl	0x04(%esp),%eax
-	movl	0x08(%esp),%edx
-	jmp	L2			/* Jump into the loop! */
-
-	.align	2,0x90
-L1:	incl	%eax
-	incl	%edx
-L2:	movb	(%eax),%cl
-	testb	%cl,%cl			/* null terminator??? */
-	jz	L3
-	cmpb	%cl,(%edx)		/* chars match??? */
-	jne	L3
-	incl	%eax
-	incl	%edx
-	movb	(%eax),%cl
-	testb	%cl,%cl
-	jz	L3
-	cmpb	%cl,(%edx)
-	jne	L3
-	incl	%eax
-	incl	%edx
-	movb	(%eax),%cl
-	testb	%cl,%cl
-	jz	L3
-	cmpb	%cl,(%edx)
-	jne	L3
-	incl	%eax
-	incl	%edx
-	movb	(%eax),%cl
-	testb	%cl,%cl
-	jz	L3
-	cmpb	%cl,(%edx)
-	jne	L3
-	incl	%eax
-	incl	%edx
-	movb	(%eax),%cl
-	testb	%cl,%cl
-	jz	L3
-	cmpb	%cl,(%edx)
-	jne	L3
-	incl	%eax
-	incl	%edx
-	movb	(%eax),%cl
-	testb	%cl,%cl
-	jz	L3
-	cmpb	%cl,(%edx)
-	jne	L3
-	incl	%eax
-	incl	%edx
-	movb	(%eax),%cl
-	testb	%cl,%cl
-	jz	L3
-	cmpb	%cl,(%edx)
-	jne	L3
-	incl	%eax
-	incl	%edx
-	movb	(%eax),%cl
-	testb	%cl,%cl
-	jz	L3
-	cmpb	%cl,(%edx)
-	je	L1
-	.align 2, 0x90
-L3:	movzbl	(%eax),%eax		/* unsigned comparison */
-	movzbl	(%edx),%edx
-	subl	%edx,%eax
-	ret
-END(strcmp_generic)
diff --git a/libc/arch-x86/generic/string/strlcat.c b/libc/arch-x86/generic/string/strlcat.c
deleted file mode 100644
index 95c34a3..0000000
--- a/libc/arch-x86/generic/string/strlcat.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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 <upstream-openbsd/android/include/openbsd-compat.h>
-
-#define strlcat strlcat_openbsd
-#include <upstream-openbsd/lib/libc/string/strlcat.c>
diff --git a/libc/arch-x86/generic/string/strlcpy.c b/libc/arch-x86/generic/string/strlcpy.c
deleted file mode 100644
index 8d4047c..0000000
--- a/libc/arch-x86/generic/string/strlcpy.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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 <upstream-openbsd/android/include/openbsd-compat.h>
-
-#define strlcpy strlcpy_openbsd
-#include <upstream-openbsd/lib/libc/string/strlcpy.c>
diff --git a/libc/arch-x86/generic/string/strncat.c b/libc/arch-x86/generic/string/strncat.c
deleted file mode 100644
index 687e560..0000000
--- a/libc/arch-x86/generic/string/strncat.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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 <upstream-openbsd/android/include/openbsd-compat.h>
-
-#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
deleted file mode 100644
index 6d9f23c..0000000
--- a/libc/arch-x86/generic/string/strncmp.S
+++ /dev/null
@@ -1,114 +0,0 @@
-/*	$OpenBSD: strncmp.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
-/*
- * Written by J.T. Conklin <jtc@netbsd.org>.
- * Public domain.
- */
-
-#include <private/bionic_asm.h>
-
-/*
- * NOTE: I've unrolled the loop eight times: large enough to make a
- * significant difference, and small enough not to totally trash the
- * cache.
- */
-
-ENTRY(strncmp_generic)
-	pushl	%ebx
-	movl	8(%esp),%eax
-	movl	12(%esp),%ecx
-	movl	16(%esp),%edx
-	testl	%edx,%edx
-	jmp	L2			/* Jump into the loop! */
-
-	.align 2,0x90
-L1:	incl	%eax
-	incl	%ecx
-	decl	%edx
-L2:	jz	L4			/* strings are equal */
-	movb	(%eax),%bl
-	testb	%bl,%bl
-	jz	L3
-	cmpb	%bl,(%ecx)
-	jne	L3
-
-	incl	%eax
-	incl	%ecx
-	decl	%edx
-	jz	L4
-	movb	(%eax),%bl
-	testb	%bl,%bl
-	jz	L3
-	cmpb	%bl,(%ecx)
-	jne	L3
-
-	incl	%eax
-	incl	%ecx
-	decl	%edx
-	jz	L4
-	movb	(%eax),%bl
-	testb	%bl,%bl
-	jz	L3
-	cmpb	%bl,(%ecx)
-	jne	L3
-
-	incl	%eax
-	incl	%ecx
-	decl	%edx
-	jz	L4
-	movb	(%eax),%bl
-	testb	%bl,%bl
-	jz	L3
-	cmpb	%bl,(%ecx)
-	jne	L3
-
-	incl	%eax
-	incl	%ecx
-	decl	%edx
-	jz	L4
-	movb	(%eax),%bl
-	testb	%bl,%bl
-	jz	L3
-	cmpb	%bl,(%ecx)
-	jne	L3
-
-	incl	%eax
-	incl	%ecx
-	decl	%edx
-	jz	L4
-	movb	(%eax),%bl
-	testb	%bl,%bl
-	jz	L3
-	cmpb	%bl,(%ecx)
-	jne	L3
-
-	incl	%eax
-	incl	%ecx
-	decl	%edx
-	jz	L4
-	movb	(%eax),%bl
-	testb	%bl,%bl
-	jz	L3
-	cmpb	%bl,(%ecx)
-	jne	L3
-
-	incl	%eax
-	incl	%ecx
-	decl	%edx
-	jz	L4
-	movb	(%eax),%bl
-	testb	%bl,%bl
-	jz	L3
-	cmpb	%bl,(%ecx)
-	je	L1
-
-	.align 2,0x90
-L3:	movzbl	(%eax),%eax		/* unsigned comparision */
-	movzbl	(%ecx),%ecx
-	subl	%ecx,%eax
-	popl	%ebx
-	ret
-	.align 2,0x90
-L4:	xorl	%eax,%eax
-	popl	%ebx
-	ret
-END(strncmp_generic)
diff --git a/libc/arch-x86/generic/string/wcscpy.c b/libc/arch-x86/generic/string/wcscpy.c
deleted file mode 100644
index 10fb66d..0000000
--- a/libc/arch-x86/generic/string/wcscpy.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.
- */
-
-#define wcscpy wcscpy_freebsd
-#include <upstream-freebsd/lib/libc/string/wcscpy.c>
diff --git a/libc/arch-x86/generic/string/wmemcmp.c b/libc/arch-x86/generic/string/wmemcmp.c
deleted file mode 100644
index 9d5e929..0000000
--- a/libc/arch-x86/generic/string/wmemcmp.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.
- */
-
-#define wmemcmp wmemcmp_freebsd
-#include <upstream-freebsd/lib/libc/string/wmemcmp.c>
diff --git a/libc/arch-x86/static_function_dispatch.S b/libc/arch-x86/static_function_dispatch.S
deleted file mode 100644
index 7e8e63d..0000000
--- a/libc/arch-x86/static_function_dispatch.S
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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 <private/bionic_asm.h>
-
-#define FUNCTION_DELEGATE(name, impl) \
-ENTRY(name); \
-    jmp impl; \
-END(name)
-
-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/arch-x86/string/sse2-memmove-slm.S b/libc/arch-x86/string/sse2-memmove-slm.S
index 7f42374..2ed4e7b 100644
--- a/libc/arch-x86/string/sse2-memmove-slm.S
+++ b/libc/arch-x86/string/sse2-memmove-slm.S
@@ -31,7 +31,7 @@
 #define FOR_SILVERMONT
 
 #ifndef MEMMOVE
-# define MEMMOVE	memmove_generic
+# define MEMMOVE	memmove
 #endif
 
 #ifndef L
@@ -551,3 +551,9 @@
 	jmp	L(mm_recalc_len)
 
 END (MEMMOVE)
+
+// N.B., `private/bionic_asm.h` provides ALIAS_SYMBOL, but that file provides
+// conflicting definitions for some macros in this file. Since ALIAS_SYMBOL is
+// small, inline it here.
+.globl memcpy;
+.equ memcpy, MEMMOVE
diff --git a/libc/arch-x86/string/sse2-memrchr-atom.S b/libc/arch-x86/string/sse2-memrchr-atom.S
deleted file mode 100644
index 1aa1a1a..0000000
--- a/libc/arch-x86/string/sse2-memrchr-atom.S
+++ /dev/null
@@ -1,778 +0,0 @@
-/*
-Copyright (c) 2011, 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.
-*/
-
-#ifndef L
-# define L(label)	.L##label
-#endif
-
-#ifndef cfi_startproc
-# define cfi_startproc	.cfi_startproc
-#endif
-
-#ifndef cfi_endproc
-# define cfi_endproc	.cfi_endproc
-#endif
-
-#ifndef cfi_rel_offset
-# define cfi_rel_offset(reg, off)	.cfi_rel_offset reg, off
-#endif
-
-#ifndef cfi_restore
-# define cfi_restore(reg)	.cfi_restore reg
-#endif
-
-#ifndef cfi_adjust_cfa_offset
-# define cfi_adjust_cfa_offset(off)	.cfi_adjust_cfa_offset off
-#endif
-
-#ifndef ENTRY
-# define ENTRY(name)	\
-	.type name,  @function;	\
-	.globl name;	\
-	.p2align 4;	\
-name:	\
-	cfi_startproc
-#endif
-
-#ifndef END
-# define END(name)	\
-	cfi_endproc;	\
-	.size name,	.-name
-#endif
-
-#define CFI_PUSH(REG)	\
-	cfi_adjust_cfa_offset (4);	\
-	cfi_rel_offset (REG, 0)
-
-#define CFI_POP(REG)	\
-	cfi_adjust_cfa_offset (-4);	\
-	cfi_restore (REG)
-
-#define PUSH(REG) pushl REG; CFI_PUSH (REG)
-#define POP(REG) popl REG; CFI_POP (REG)
-
-#define PARMS  4
-#define STR1  PARMS
-#define STR2  STR1+4
-#define LEN   STR2+4
-
-	.text
-ENTRY (memrchr)
-	mov	STR1(%esp), %ecx
-	movd	STR2(%esp), %xmm1
-	mov	LEN(%esp), %edx
-
-	test	%edx, %edx
-	jz	L(return_null)
-	sub	$16, %edx
-	jbe	L(length_less16)
-
-	punpcklbw %xmm1, %xmm1
-	add	%edx, %ecx
-	punpcklbw %xmm1, %xmm1
-
-	movdqu	(%ecx), %xmm0
-	pshufd	$0, %xmm1, %xmm1
-	pcmpeqb	%xmm1, %xmm0
-
-	pmovmskb %xmm0, %eax
-	test	%eax, %eax
-	jnz	L(exit_dispatch)
-
-	sub	$64, %ecx
-	mov	%ecx, %eax
-	and	$15, %eax
-	jz	L(loop_prolog)
-
-	add	$16, %ecx
-	add	$16, %edx
-	and	$-16, %ecx
-	sub	%eax, %edx
-
-	.p2align 4
-/* Loop start on aligned string.  */
-L(loop_prolog):
-	sub	$64, %edx
-	jbe	L(exit_loop)
-
-	movdqa	48(%ecx), %xmm0
-	pcmpeqb	%xmm1, %xmm0
-	pmovmskb %xmm0, %eax
-	test	%eax, %eax
-	jnz	L(matches48)
-
-	movdqa	32(%ecx), %xmm2
-	pcmpeqb	%xmm1, %xmm2
-	pmovmskb %xmm2, %eax
-	test	%eax, %eax
-	jnz	L(matches32)
-
-	movdqa	16(%ecx), %xmm3
-	pcmpeqb	%xmm1, %xmm3
-	pmovmskb %xmm3, %eax
-	test	%eax, %eax
-	jnz	L(matches16)
-
-	movdqa	(%ecx), %xmm4
-	pcmpeqb	%xmm1, %xmm4
-	pmovmskb %xmm4, %eax
-	test	%eax, %eax
-	jnz	L(exit_dispatch)
-
-	sub	$64, %ecx
-	sub	$64, %edx
-	jbe	L(exit_loop)
-
-	movdqa	48(%ecx), %xmm0
-	pcmpeqb	%xmm1, %xmm0
-	pmovmskb %xmm0, %eax
-	test	%eax, %eax
-	jnz	L(matches48)
-
-	movdqa	32(%ecx), %xmm2
-	pcmpeqb	%xmm1, %xmm2
-	pmovmskb %xmm2, %eax
-	test	%eax, %eax
-	jnz	L(matches32)
-
-	movdqa	16(%ecx), %xmm3
-	pcmpeqb	%xmm1, %xmm3
-	pmovmskb %xmm3, %eax
-	test	%eax, %eax
-	jnz	L(matches16)
-
-	movdqa	(%ecx), %xmm3
-	pcmpeqb	%xmm1, %xmm3
-	pmovmskb %xmm3, %eax
-	test	%eax, %eax
-	jnz	L(exit_dispatch)
-
-	mov	%ecx, %eax
-	and	$63, %eax
-	test	%eax, %eax
-	jz	L(align64_loop)
-
-	add	$64, %ecx
-	add	$64, %edx
-	and	$-64, %ecx
-	sub	%eax, %edx
-
-	.p2align 4
-L(align64_loop):
-	sub	$64, %ecx
-	sub	$64, %edx
-	jbe	L(exit_loop)
-
-	movdqa	(%ecx), %xmm0
-	movdqa	16(%ecx), %xmm2
-	movdqa	32(%ecx), %xmm3
-	movdqa	48(%ecx), %xmm4
-
-	pcmpeqb	%xmm1, %xmm0
-	pcmpeqb	%xmm1, %xmm2
-	pcmpeqb	%xmm1, %xmm3
-	pcmpeqb	%xmm1, %xmm4
-
-	pmaxub	%xmm3, %xmm0
-	pmaxub	%xmm4, %xmm2
-	pmaxub	%xmm0, %xmm2
-	pmovmskb %xmm2, %eax
-
-	test	%eax, %eax
-	jz	L(align64_loop)
-
-	pmovmskb %xmm4, %eax
-	test	%eax, %eax
-	jnz	L(matches48)
-
-	pmovmskb %xmm3, %eax
-	test	%eax, %eax
-	jnz	L(matches32)
-
-	movdqa	16(%ecx), %xmm2
-
-	pcmpeqb	%xmm1, %xmm2
-	pcmpeqb	(%ecx), %xmm1
-
-	pmovmskb %xmm2, %eax
-	test	%eax, %eax
-	jnz	L(matches16)
-
-	pmovmskb %xmm1, %eax
-	test	%ah, %ah
-	jnz	L(exit_dispatch_high)
-	mov	%al, %dl
-	and	$15 << 4, %dl
-	jnz	L(exit_dispatch_8)
-	test	$0x08, %al
-	jnz	L(exit_4)
-	test	$0x04, %al
-	jnz	L(exit_3)
-	test	$0x02, %al
-	jnz	L(exit_2)
-	mov	%ecx, %eax
-	ret
-
-	.p2align 4
-L(exit_loop):
-	add	$64, %edx
-	cmp	$32, %edx
-	jbe	L(exit_loop_32)
-
-	movdqa	48(%ecx), %xmm0
-	pcmpeqb	%xmm1, %xmm0
-	pmovmskb %xmm0, %eax
-	test	%eax, %eax
-	jnz	L(matches48)
-
-	movdqa	32(%ecx), %xmm2
-	pcmpeqb	%xmm1, %xmm2
-	pmovmskb %xmm2, %eax
-	test	%eax, %eax
-	jnz	L(matches32)
-
-	movdqa	16(%ecx), %xmm3
-	pcmpeqb	%xmm1, %xmm3
-	pmovmskb %xmm3, %eax
-	test	%eax, %eax
-	jnz	L(matches16_1)
-	cmp	$48, %edx
-	jbe	L(return_null)
-
-	pcmpeqb	(%ecx), %xmm1
-	pmovmskb %xmm1, %eax
-	test	%eax, %eax
-	jnz	L(matches0_1)
-	xor	%eax, %eax
-	ret
-
-	.p2align 4
-L(exit_loop_32):
-	movdqa	48(%ecx), %xmm0
-	pcmpeqb	%xmm1, %xmm0
-	pmovmskb %xmm0, %eax
-	test	%eax, %eax
-	jnz	L(matches48_1)
-	cmp	$16, %edx
-	jbe	L(return_null)
-
-	pcmpeqb	32(%ecx), %xmm1
-	pmovmskb %xmm1, %eax
-	test	%eax, %eax
-	jnz	L(matches32_1)
-	xor	%eax, %eax
-	ret
-
-	.p2align 4
-L(matches16):
-	lea	16(%ecx), %ecx
-	test	%ah, %ah
-	jnz	L(exit_dispatch_high)
-	mov	%al, %dl
-	and	$15 << 4, %dl
-	jnz	L(exit_dispatch_8)
-	test	$0x08, %al
-	jnz	L(exit_4)
-	test	$0x04, %al
-	jnz	L(exit_3)
-	test	$0x02, %al
-	jnz	L(exit_2)
-	mov	%ecx, %eax
-	ret
-
-	.p2align 4
-L(matches32):
-	lea	32(%ecx), %ecx
-	test	%ah, %ah
-	jnz	L(exit_dispatch_high)
-	mov	%al, %dl
-	and	$15 << 4, %dl
-	jnz	L(exit_dispatch_8)
-	test	$0x08, %al
-	jnz	L(exit_4)
-	test	$0x04, %al
-	jnz	L(exit_3)
-	test	$0x02, %al
-	jnz	L(exit_2)
-	mov	%ecx, %eax
-	ret
-
-	.p2align 4
-L(matches48):
-	lea	48(%ecx), %ecx
-
-	.p2align 4
-L(exit_dispatch):
-	test	%ah, %ah
-	jnz	L(exit_dispatch_high)
-	mov	%al, %dl
-	and	$15 << 4, %dl
-	jnz	L(exit_dispatch_8)
-	test	$0x08, %al
-	jnz	L(exit_4)
-	test	$0x04, %al
-	jnz	L(exit_3)
-	test	$0x02, %al
-	jnz	L(exit_2)
-	mov	%ecx, %eax
-	ret
-
-	.p2align 4
-L(exit_dispatch_8):
-	test	$0x80, %al
-	jnz	L(exit_8)
-	test	$0x40, %al
-	jnz	L(exit_7)
-	test	$0x20, %al
-	jnz	L(exit_6)
-	lea	4(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_dispatch_high):
-	mov	%ah, %dh
-	and	$15 << 4, %dh
-	jnz	L(exit_dispatch_high_8)
-	test	$0x08, %ah
-	jnz	L(exit_12)
-	test	$0x04, %ah
-	jnz	L(exit_11)
-	test	$0x02, %ah
-	jnz	L(exit_10)
-	lea	8(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_dispatch_high_8):
-	test	$0x80, %ah
-	jnz	L(exit_16)
-	test	$0x40, %ah
-	jnz	L(exit_15)
-	test	$0x20, %ah
-	jnz	L(exit_14)
-	lea	12(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_2):
-	lea	1(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_3):
-	lea	2(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_4):
-	lea	3(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_6):
-	lea	5(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_7):
-	lea	6(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_8):
-	lea	7(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_10):
-	lea	9(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_11):
-	lea	10(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_12):
-	lea	11(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_14):
-	lea	13(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_15):
-	lea	14(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_16):
-	lea	15(%ecx), %eax
-	ret
-
-	.p2align 4
-L(matches0_1):
-	lea	-64(%edx), %edx
-
-	test	%ah, %ah
-	jnz	L(exit_dispatch_1_high)
-	mov	%al, %ah
-	and	$15 << 4, %ah
-	jnz	L(exit_dispatch_1_8)
-	test	$0x08, %al
-	jnz	L(exit_1_4)
-	test	$0x04, %al
-	jnz	L(exit_1_3)
-	test	$0x02, %al
-	jnz	L(exit_1_2)
-
-	add	$0, %edx
-	jl	L(return_null)
-	mov	%ecx, %eax
-	ret
-
-	.p2align 4
-L(matches16_1):
-	lea	-48(%edx), %edx
-	lea	16(%ecx), %ecx
-
-	test	%ah, %ah
-	jnz	L(exit_dispatch_1_high)
-	mov	%al, %ah
-	and	$15 << 4, %ah
-	jnz	L(exit_dispatch_1_8)
-	test	$0x08, %al
-	jnz	L(exit_1_4)
-	test	$0x04, %al
-	jnz	L(exit_1_3)
-	test	$0x02, %al
-	jnz	L(exit_1_2)
-
-	add	$0, %edx
-	jl	L(return_null)
-	mov	%ecx, %eax
-	ret
-
-	.p2align 4
-L(matches32_1):
-	lea	-32(%edx), %edx
-	lea	32(%ecx), %ecx
-
-	test	%ah, %ah
-	jnz	L(exit_dispatch_1_high)
-	mov	%al, %ah
-	and	$15 << 4, %ah
-	jnz	L(exit_dispatch_1_8)
-	test	$0x08, %al
-	jnz	L(exit_1_4)
-	test	$0x04, %al
-	jnz	L(exit_1_3)
-	test	$0x02, %al
-	jnz	L(exit_1_2)
-
-	add	$0, %edx
-	jl	L(return_null)
-	mov	%ecx, %eax
-	ret
-
-	.p2align 4
-L(matches48_1):
-	lea	-16(%edx), %edx
-	lea	48(%ecx), %ecx
-
-	.p2align 4
-L(exit_dispatch_1):
-	test	%ah, %ah
-	jnz	L(exit_dispatch_1_high)
-	mov	%al, %ah
-	and	$15 << 4, %ah
-	jnz	L(exit_dispatch_1_8)
-	test	$0x08, %al
-	jnz	L(exit_1_4)
-	test	$0x04, %al
-	jnz	L(exit_1_3)
-	test	$0x02, %al
-	jnz	L(exit_1_2)
-
-	add	$0, %edx
-	jl	L(return_null)
-	mov	%ecx, %eax
-	ret
-
-	.p2align 4
-L(exit_dispatch_1_8):
-	test	$0x80, %al
-	jnz	L(exit_1_8)
-	test	$0x40, %al
-	jnz	L(exit_1_7)
-	test	$0x20, %al
-	jnz	L(exit_1_6)
-
-	add	$4, %edx
-	jl	L(return_null)
-	lea	4(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_dispatch_1_high):
-	mov	%ah, %al
-	and	$15 << 4, %al
-	jnz	L(exit_dispatch_1_high_8)
-	test	$0x08, %ah
-	jnz	L(exit_1_12)
-	test	$0x04, %ah
-	jnz	L(exit_1_11)
-	test	$0x02, %ah
-	jnz	L(exit_1_10)
-
-	add	$8, %edx
-	jl	L(return_null)
-	lea	8(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_dispatch_1_high_8):
-	test	$0x80, %ah
-	jnz	L(exit_1_16)
-	test	$0x40, %ah
-	jnz	L(exit_1_15)
-	test	$0x20, %ah
-	jnz	L(exit_1_14)
-
-	add	$12, %edx
-	jl	L(return_null)
-	lea	12(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_1_2):
-	add	$1, %edx
-	jl	L(return_null)
-	lea	1(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_1_3):
-	add	$2, %edx
-	jl	L(return_null)
-	lea	2(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_1_4):
-	add	$3, %edx
-	jl	L(return_null)
-	lea	3(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_1_6):
-	add	$5, %edx
-	jl	L(return_null)
-	lea	5(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_1_7):
-	add	$6, %edx
-	jl	L(return_null)
-	lea	6(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_1_8):
-	add	$7, %edx
-	jl	L(return_null)
-	lea	7(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_1_10):
-	add	$9, %edx
-	jl	L(return_null)
-	lea	9(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_1_11):
-	add	$10, %edx
-	jl	L(return_null)
-	lea	10(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_1_12):
-	add	$11, %edx
-	jl	L(return_null)
-	lea	11(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_1_14):
-	add	$13, %edx
-	jl	L(return_null)
-	lea	13(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_1_15):
-	add	$14, %edx
-	jl	L(return_null)
-	lea	14(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit_1_16):
-	add	$15, %edx
-	jl	L(return_null)
-	lea	15(%ecx), %eax
-	ret
-
-	.p2align 4
-L(return_null):
-	xor	%eax, %eax
-	ret
-
-	.p2align 4
-L(length_less16_offset0):
-	mov	%dl, %cl
-	pcmpeqb	(%eax), %xmm1
-
-	mov	$1, %edx
-	sal	%cl, %edx
-	sub	$1, %edx
-
-	mov	%eax, %ecx
-	pmovmskb %xmm1, %eax
-
-	and	%edx, %eax
-	test	%eax, %eax
-	jnz	L(exit_dispatch)
-
-	xor	%eax, %eax
-	ret
-
-	.p2align 4
-L(length_less16):
-	punpcklbw %xmm1, %xmm1
-	add	$16, %edx
-	punpcklbw %xmm1, %xmm1
-
-	mov	%ecx, %eax
-	pshufd	$0, %xmm1, %xmm1
-
-	and	$15, %ecx
-	jz	L(length_less16_offset0)
-
-	PUSH	(%edi)
-
-	mov	%cl, %dh
-	add	%dl, %dh
-	and	$-16, %eax
-
-	sub	$16, %dh
-	ja	L(length_less16_part2)
-
-	pcmpeqb	(%eax), %xmm1
-	pmovmskb %xmm1, %edi
-
-	sar	%cl, %edi
-	add	%ecx, %eax
-	mov	%dl, %cl
-
-	mov	$1, %edx
-	sal	%cl, %edx
-	sub	$1, %edx
-
-	and	%edx, %edi
-	test	%edi, %edi
-	jz	L(ret_null)
-
-	bsr	%edi, %edi
-	add	%edi, %eax
-	POP	(%edi)
-	ret
-
-	CFI_PUSH     (%edi)
-
-	.p2align 4
-L(length_less16_part2):
-	movdqa	16(%eax), %xmm2
-	pcmpeqb	%xmm1, %xmm2
-	pmovmskb %xmm2, %edi
-
-	mov	%cl, %ch
-
-	mov	%dh, %cl
-	mov	$1, %edx
-	sal	%cl, %edx
-	sub	$1, %edx
-
-	and	%edx, %edi
-
-	test	%edi, %edi
-	jnz	L(length_less16_part2_return)
-
-	pcmpeqb	(%eax), %xmm1
-	pmovmskb %xmm1, %edi
-
-	mov	%ch, %cl
-	sar	%cl, %edi
-	test	%edi, %edi
-	jz	L(ret_null)
-
-	bsr	%edi, %edi
-	add	%edi, %eax
-	xor	%ch, %ch
-	add	%ecx, %eax
-	POP	(%edi)
-	ret
-
-	CFI_PUSH     (%edi)
-
-	.p2align 4
-L(length_less16_part2_return):
-	bsr	%edi, %edi
-	lea	16(%eax, %edi), %eax
-	POP	(%edi)
-	ret
-
-	CFI_PUSH     (%edi)
-
-	.p2align 4
-L(ret_null):
-	xor	%eax, %eax
-	POP	(%edi)
-	ret
-
-END (memrchr)
diff --git a/libc/arch-x86/string/sse2-memset-atom.S b/libc/arch-x86/string/sse2-memset-atom.S
deleted file mode 100644
index e43ead0..0000000
--- a/libc/arch-x86/string/sse2-memset-atom.S
+++ /dev/null
@@ -1,841 +0,0 @@
-/*
-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.
-*/
-
-#include <private/bionic_asm.h>
-
-#define FOR_ATOM
-
-#ifndef L
-# define L(label)	.L##label
-#endif
-
-#ifndef ALIGN
-# define ALIGN(n)	.p2align n
-#endif
-
-#define CFI_PUSH(REG)						\
-  .cfi_adjust_cfa_offset 4;					\
-  .cfi_rel_offset REG, 0
-
-#define CFI_POP(REG)						\
-  .cfi_adjust_cfa_offset -4;					\
-  .cfi_restore REG
-
-#define PUSH(REG)	pushl REG; CFI_PUSH(REG)
-#define POP(REG)	popl REG; CFI_POP(REG)
-
-#define PARMS 8  /* Preserve EBX. */
-#define DST PARMS
-#define CHR (DST+4)
-#define LEN (CHR+4)
-#define CHK_DST_LEN (LEN+4)
-#define SETRTNVAL	movl DST(%esp), %eax
-
-#define ENTRANCE	PUSH(%ebx);
-#define RETURN_END	POP(%ebx); ret
-#define RETURN		RETURN_END; CFI_PUSH(%ebx)
-#define JMPTBL(I, B)	I - B
-
-#define SETUP_PIC_REG(x)	call	__x86.get_pc_thunk.x
-
-/* Load an entry in a jump table into EBX and branch to it.  TABLE is a
-   jump table with relative offsets.   */
-# define BRANCH_TO_JMPTBL_ENTRY(TABLE)				\
-    /* We first load PC into EBX.  */				\
-    call	__x86.get_pc_thunk.bx;				\
-    /* Get the address of the jump table.  */			\
-    add		$(TABLE - .), %ebx;				\
-    /* Get the entry and convert the relative offset to the	\
-       absolute address.  */					\
-    add		(%ebx,%ecx,4), %ebx;				\
-    add		%ecx, %edx;					\
-    /* We loaded the jump table and adjusted EDX. Go.  */	\
-    jmp		*%ebx
-
-ENTRY(__memset_chk_atom)
-  ENTRANCE
-
-  movl LEN(%esp), %ecx
-  cmpl CHK_DST_LEN(%esp), %ecx
-  jna L(memset_length_loaded)
-
-  POP(%ebx) // Undo ENTRANCE without returning.
-  jmp __memset_chk_fail
-END(__memset_chk_atom)
-
-	.section .text.sse2,"ax",@progbits
-	ALIGN(4)
-ENTRY(memset_atom)
-	ENTRANCE
-
-	movl	LEN(%esp), %ecx
-L(memset_length_loaded):
-	movzbl	CHR(%esp), %eax
-	movb	%al, %ah
-	/* Fill the whole EAX with pattern.  */
-	movl	%eax, %edx
-	shl	$16, %eax
-	or	%edx, %eax
-	movl	DST(%esp), %edx
-	cmp	$32, %ecx
-	jae	L(32bytesormore)
-
-L(write_less32bytes):
-	BRANCH_TO_JMPTBL_ENTRY(L(table_less_32bytes))
-
-
-	.pushsection .rodata.sse2,"a",@progbits
-	ALIGN(2)
-L(table_less_32bytes):
-	.int	JMPTBL(L(write_0bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_1bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_2bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_3bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_4bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_5bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_6bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_7bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_8bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_9bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_10bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_11bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_12bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_13bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_14bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_15bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_16bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_17bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_18bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_19bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_20bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_21bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_22bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_23bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_24bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_25bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_26bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_27bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_28bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_29bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_30bytes), L(table_less_32bytes))
-	.int	JMPTBL(L(write_31bytes), L(table_less_32bytes))
-	.popsection
-
-	ALIGN(4)
-L(write_28bytes):
-	movl	%eax, -28(%edx)
-L(write_24bytes):
-	movl	%eax, -24(%edx)
-L(write_20bytes):
-	movl	%eax, -20(%edx)
-L(write_16bytes):
-	movl	%eax, -16(%edx)
-L(write_12bytes):
-	movl	%eax, -12(%edx)
-L(write_8bytes):
-	movl	%eax, -8(%edx)
-L(write_4bytes):
-	movl	%eax, -4(%edx)
-L(write_0bytes):
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(write_29bytes):
-	movl	%eax, -29(%edx)
-L(write_25bytes):
-	movl	%eax, -25(%edx)
-L(write_21bytes):
-	movl	%eax, -21(%edx)
-L(write_17bytes):
-	movl	%eax, -17(%edx)
-L(write_13bytes):
-	movl	%eax, -13(%edx)
-L(write_9bytes):
-	movl	%eax, -9(%edx)
-L(write_5bytes):
-	movl	%eax, -5(%edx)
-L(write_1bytes):
-	movb	%al, -1(%edx)
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(write_30bytes):
-	movl	%eax, -30(%edx)
-L(write_26bytes):
-	movl	%eax, -26(%edx)
-L(write_22bytes):
-	movl	%eax, -22(%edx)
-L(write_18bytes):
-	movl	%eax, -18(%edx)
-L(write_14bytes):
-	movl	%eax, -14(%edx)
-L(write_10bytes):
-	movl	%eax, -10(%edx)
-L(write_6bytes):
-	movl	%eax, -6(%edx)
-L(write_2bytes):
-	movw	%ax, -2(%edx)
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(write_31bytes):
-	movl	%eax, -31(%edx)
-L(write_27bytes):
-	movl	%eax, -27(%edx)
-L(write_23bytes):
-	movl	%eax, -23(%edx)
-L(write_19bytes):
-	movl	%eax, -19(%edx)
-L(write_15bytes):
-	movl	%eax, -15(%edx)
-L(write_11bytes):
-	movl	%eax, -11(%edx)
-L(write_7bytes):
-	movl	%eax, -7(%edx)
-L(write_3bytes):
-	movw	%ax, -3(%edx)
-	movb	%al, -1(%edx)
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-/* ECX > 32 and EDX is 4 byte aligned.  */
-L(32bytesormore):
-	/* Fill xmm0 with the pattern.  */
-	movd	%eax, %xmm0
-	pshufd	$0, %xmm0, %xmm0
-	testl	$0xf, %edx
-	jz	L(aligned_16)
-/* ECX > 32 and EDX is not 16 byte aligned.  */
-L(not_aligned_16):
-	movdqu	%xmm0, (%edx)
-	movl	%edx, %eax
-	and	$-16, %edx
-	add	$16, %edx
-	sub	%edx, %eax
-	add	%eax, %ecx
-	movd	%xmm0, %eax
-
-	ALIGN(4)
-L(aligned_16):
-	cmp	$128, %ecx
-	jae	L(128bytesormore)
-
-L(aligned_16_less128bytes):
-	BRANCH_TO_JMPTBL_ENTRY(L(table_16_128bytes))
-
-	ALIGN(4)
-L(128bytesormore):
-	PUSH(%ebx)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	mov	__x86_shared_cache_size@GOTOFF(%ebx), %ebx
-	cmp	%ebx, %ecx
-	jae	L(128bytesormore_nt_start)
-
-
-	POP(%ebx)
-# define RESTORE_EBX_STATE CFI_PUSH(%ebx)
-	PUSH(%ebx)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_data_cache_size@GOTOFF(%ebx), %ecx
-	POP(%ebx)
-
-	jae	L(128bytes_L2_normal)
-	subl	$128, %ecx
-L(128bytesormore_normal):
-	sub	$128, %ecx
-	movdqa	%xmm0, (%edx)
-	movdqa	%xmm0, 0x10(%edx)
-	movdqa	%xmm0, 0x20(%edx)
-	movdqa	%xmm0, 0x30(%edx)
-	movdqa	%xmm0, 0x40(%edx)
-	movdqa	%xmm0, 0x50(%edx)
-	movdqa	%xmm0, 0x60(%edx)
-	movdqa	%xmm0, 0x70(%edx)
-	lea	128(%edx), %edx
-	jb	L(128bytesless_normal)
-
-
-	sub	$128, %ecx
-	movdqa	%xmm0, (%edx)
-	movdqa	%xmm0, 0x10(%edx)
-	movdqa	%xmm0, 0x20(%edx)
-	movdqa	%xmm0, 0x30(%edx)
-	movdqa	%xmm0, 0x40(%edx)
-	movdqa	%xmm0, 0x50(%edx)
-	movdqa	%xmm0, 0x60(%edx)
-	movdqa	%xmm0, 0x70(%edx)
-	lea	128(%edx), %edx
-	jae	L(128bytesormore_normal)
-
-L(128bytesless_normal):
-	add	$128, %ecx
-	BRANCH_TO_JMPTBL_ENTRY(L(table_16_128bytes))
-
-	ALIGN(4)
-L(128bytes_L2_normal):
-	prefetcht0	0x380(%edx)
-	prefetcht0	0x3c0(%edx)
-	sub	$128, %ecx
-	movdqa	%xmm0, (%edx)
-	movaps	%xmm0, 0x10(%edx)
-	movaps	%xmm0, 0x20(%edx)
-	movaps	%xmm0, 0x30(%edx)
-	movaps	%xmm0, 0x40(%edx)
-	movaps	%xmm0, 0x50(%edx)
-	movaps	%xmm0, 0x60(%edx)
-	movaps	%xmm0, 0x70(%edx)
-	add	$128, %edx
-	cmp	$128, %ecx
-	jae	L(128bytes_L2_normal)
-
-L(128bytesless_L2_normal):
-	BRANCH_TO_JMPTBL_ENTRY(L(table_16_128bytes))
-
-	RESTORE_EBX_STATE
-L(128bytesormore_nt_start):
-	sub	%ebx, %ecx
-	mov	%ebx, %eax
-	and	$0x7f, %eax
-	add	%eax, %ecx
-	movd	%xmm0, %eax
-	ALIGN(4)
-L(128bytesormore_shared_cache_loop):
-	prefetcht0	0x3c0(%edx)
-	prefetcht0	0x380(%edx)
-	sub	$0x80, %ebx
-	movdqa	%xmm0, (%edx)
-	movdqa	%xmm0, 0x10(%edx)
-	movdqa	%xmm0, 0x20(%edx)
-	movdqa	%xmm0, 0x30(%edx)
-	movdqa	%xmm0, 0x40(%edx)
-	movdqa	%xmm0, 0x50(%edx)
-	movdqa	%xmm0, 0x60(%edx)
-	movdqa	%xmm0, 0x70(%edx)
-	add	$0x80, %edx
-	cmp	$0x80, %ebx
-	jae	L(128bytesormore_shared_cache_loop)
-	cmp	$0x80, %ecx
-	jb	L(shared_cache_loop_end)
-	ALIGN(4)
-L(128bytesormore_nt):
-	sub	$0x80, %ecx
-	movntdq	%xmm0, (%edx)
-	movntdq	%xmm0, 0x10(%edx)
-	movntdq	%xmm0, 0x20(%edx)
-	movntdq	%xmm0, 0x30(%edx)
-	movntdq	%xmm0, 0x40(%edx)
-	movntdq	%xmm0, 0x50(%edx)
-	movntdq	%xmm0, 0x60(%edx)
-	movntdq	%xmm0, 0x70(%edx)
-	add	$0x80, %edx
-	cmp	$0x80, %ecx
-	jae	L(128bytesormore_nt)
-	sfence
-L(shared_cache_loop_end):
-	POP(%ebx)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_16_128bytes))
-
-
-	.pushsection .rodata.sse2,"a",@progbits
-	ALIGN(2)
-L(table_16_128bytes):
-	.int	JMPTBL(L(aligned_16_0bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_1bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_2bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_3bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_4bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_5bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_6bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_7bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_8bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_9bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_10bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_11bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_12bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_13bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_14bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_15bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_16bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_17bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_18bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_19bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_20bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_21bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_22bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_23bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_24bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_25bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_26bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_27bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_28bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_29bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_30bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_31bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_32bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_33bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_34bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_35bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_36bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_37bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_38bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_39bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_40bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_41bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_42bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_43bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_44bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_45bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_46bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_47bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_48bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_49bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_50bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_51bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_52bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_53bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_54bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_55bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_56bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_57bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_58bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_59bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_60bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_61bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_62bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_63bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_64bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_65bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_66bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_67bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_68bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_69bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_70bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_71bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_72bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_73bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_74bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_75bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_76bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_77bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_78bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_79bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_80bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_81bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_82bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_83bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_84bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_85bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_86bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_87bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_88bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_89bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_90bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_91bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_92bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_93bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_94bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_95bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_96bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_97bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_98bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_99bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_100bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_101bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_102bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_103bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_104bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_105bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_106bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_107bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_108bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_109bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_110bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_111bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_112bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_113bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_114bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_115bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_116bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_117bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_118bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_119bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_120bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_121bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_122bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_123bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_124bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_125bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_126bytes), L(table_16_128bytes))
-	.int	JMPTBL(L(aligned_16_127bytes), L(table_16_128bytes))
-	.popsection
-
-	ALIGN(4)
-L(aligned_16_112bytes):
-	movdqa	%xmm0, -112(%edx)
-L(aligned_16_96bytes):
-	movdqa	%xmm0, -96(%edx)
-L(aligned_16_80bytes):
-	movdqa	%xmm0, -80(%edx)
-L(aligned_16_64bytes):
-	movdqa	%xmm0, -64(%edx)
-L(aligned_16_48bytes):
-	movdqa	%xmm0, -48(%edx)
-L(aligned_16_32bytes):
-	movdqa	%xmm0, -32(%edx)
-L(aligned_16_16bytes):
-	movdqa	%xmm0, -16(%edx)
-L(aligned_16_0bytes):
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(aligned_16_113bytes):
-	movdqa	%xmm0, -113(%edx)
-L(aligned_16_97bytes):
-	movdqa	%xmm0, -97(%edx)
-L(aligned_16_81bytes):
-	movdqa	%xmm0, -81(%edx)
-L(aligned_16_65bytes):
-	movdqa	%xmm0, -65(%edx)
-L(aligned_16_49bytes):
-	movdqa	%xmm0, -49(%edx)
-L(aligned_16_33bytes):
-	movdqa	%xmm0, -33(%edx)
-L(aligned_16_17bytes):
-	movdqa	%xmm0, -17(%edx)
-L(aligned_16_1bytes):
-	movb	%al, -1(%edx)
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(aligned_16_114bytes):
-	movdqa	%xmm0, -114(%edx)
-L(aligned_16_98bytes):
-	movdqa	%xmm0, -98(%edx)
-L(aligned_16_82bytes):
-	movdqa	%xmm0, -82(%edx)
-L(aligned_16_66bytes):
-	movdqa	%xmm0, -66(%edx)
-L(aligned_16_50bytes):
-	movdqa	%xmm0, -50(%edx)
-L(aligned_16_34bytes):
-	movdqa	%xmm0, -34(%edx)
-L(aligned_16_18bytes):
-	movdqa	%xmm0, -18(%edx)
-L(aligned_16_2bytes):
-	movw	%ax, -2(%edx)
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(aligned_16_115bytes):
-	movdqa	%xmm0, -115(%edx)
-L(aligned_16_99bytes):
-	movdqa	%xmm0, -99(%edx)
-L(aligned_16_83bytes):
-	movdqa	%xmm0, -83(%edx)
-L(aligned_16_67bytes):
-	movdqa	%xmm0, -67(%edx)
-L(aligned_16_51bytes):
-	movdqa	%xmm0, -51(%edx)
-L(aligned_16_35bytes):
-	movdqa	%xmm0, -35(%edx)
-L(aligned_16_19bytes):
-	movdqa	%xmm0, -19(%edx)
-L(aligned_16_3bytes):
-	movw	%ax, -3(%edx)
-	movb	%al, -1(%edx)
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(aligned_16_116bytes):
-	movdqa	%xmm0, -116(%edx)
-L(aligned_16_100bytes):
-	movdqa	%xmm0, -100(%edx)
-L(aligned_16_84bytes):
-	movdqa	%xmm0, -84(%edx)
-L(aligned_16_68bytes):
-	movdqa	%xmm0, -68(%edx)
-L(aligned_16_52bytes):
-	movdqa	%xmm0, -52(%edx)
-L(aligned_16_36bytes):
-	movdqa	%xmm0, -36(%edx)
-L(aligned_16_20bytes):
-	movdqa	%xmm0, -20(%edx)
-L(aligned_16_4bytes):
-	movl	%eax, -4(%edx)
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(aligned_16_117bytes):
-	movdqa	%xmm0, -117(%edx)
-L(aligned_16_101bytes):
-	movdqa	%xmm0, -101(%edx)
-L(aligned_16_85bytes):
-	movdqa	%xmm0, -85(%edx)
-L(aligned_16_69bytes):
-	movdqa	%xmm0, -69(%edx)
-L(aligned_16_53bytes):
-	movdqa	%xmm0, -53(%edx)
-L(aligned_16_37bytes):
-	movdqa	%xmm0, -37(%edx)
-L(aligned_16_21bytes):
-	movdqa	%xmm0, -21(%edx)
-L(aligned_16_5bytes):
-	movl	%eax, -5(%edx)
-	movb	%al, -1(%edx)
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(aligned_16_118bytes):
-	movdqa	%xmm0, -118(%edx)
-L(aligned_16_102bytes):
-	movdqa	%xmm0, -102(%edx)
-L(aligned_16_86bytes):
-	movdqa	%xmm0, -86(%edx)
-L(aligned_16_70bytes):
-	movdqa	%xmm0, -70(%edx)
-L(aligned_16_54bytes):
-	movdqa	%xmm0, -54(%edx)
-L(aligned_16_38bytes):
-	movdqa	%xmm0, -38(%edx)
-L(aligned_16_22bytes):
-	movdqa	%xmm0, -22(%edx)
-L(aligned_16_6bytes):
-	movl	%eax, -6(%edx)
-	movw	%ax, -2(%edx)
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(aligned_16_119bytes):
-	movdqa	%xmm0, -119(%edx)
-L(aligned_16_103bytes):
-	movdqa	%xmm0, -103(%edx)
-L(aligned_16_87bytes):
-	movdqa	%xmm0, -87(%edx)
-L(aligned_16_71bytes):
-	movdqa	%xmm0, -71(%edx)
-L(aligned_16_55bytes):
-	movdqa	%xmm0, -55(%edx)
-L(aligned_16_39bytes):
-	movdqa	%xmm0, -39(%edx)
-L(aligned_16_23bytes):
-	movdqa	%xmm0, -23(%edx)
-L(aligned_16_7bytes):
-	movl	%eax, -7(%edx)
-	movw	%ax, -3(%edx)
-	movb	%al, -1(%edx)
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(aligned_16_120bytes):
-	movdqa	%xmm0, -120(%edx)
-L(aligned_16_104bytes):
-	movdqa	%xmm0, -104(%edx)
-L(aligned_16_88bytes):
-	movdqa	%xmm0, -88(%edx)
-L(aligned_16_72bytes):
-	movdqa	%xmm0, -72(%edx)
-L(aligned_16_56bytes):
-	movdqa	%xmm0, -56(%edx)
-L(aligned_16_40bytes):
-	movdqa	%xmm0, -40(%edx)
-L(aligned_16_24bytes):
-	movdqa	%xmm0, -24(%edx)
-L(aligned_16_8bytes):
-	movq	%xmm0, -8(%edx)
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(aligned_16_121bytes):
-	movdqa	%xmm0, -121(%edx)
-L(aligned_16_105bytes):
-	movdqa	%xmm0, -105(%edx)
-L(aligned_16_89bytes):
-	movdqa	%xmm0, -89(%edx)
-L(aligned_16_73bytes):
-	movdqa	%xmm0, -73(%edx)
-L(aligned_16_57bytes):
-	movdqa	%xmm0, -57(%edx)
-L(aligned_16_41bytes):
-	movdqa	%xmm0, -41(%edx)
-L(aligned_16_25bytes):
-	movdqa	%xmm0, -25(%edx)
-L(aligned_16_9bytes):
-	movq	%xmm0, -9(%edx)
-	movb	%al, -1(%edx)
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(aligned_16_122bytes):
-	movdqa	%xmm0, -122(%edx)
-L(aligned_16_106bytes):
-	movdqa	%xmm0, -106(%edx)
-L(aligned_16_90bytes):
-	movdqa	%xmm0, -90(%edx)
-L(aligned_16_74bytes):
-	movdqa	%xmm0, -74(%edx)
-L(aligned_16_58bytes):
-	movdqa	%xmm0, -58(%edx)
-L(aligned_16_42bytes):
-	movdqa	%xmm0, -42(%edx)
-L(aligned_16_26bytes):
-	movdqa	%xmm0, -26(%edx)
-L(aligned_16_10bytes):
-	movq	%xmm0, -10(%edx)
-	movw	%ax, -2(%edx)
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(aligned_16_123bytes):
-	movdqa	%xmm0, -123(%edx)
-L(aligned_16_107bytes):
-	movdqa	%xmm0, -107(%edx)
-L(aligned_16_91bytes):
-	movdqa	%xmm0, -91(%edx)
-L(aligned_16_75bytes):
-	movdqa	%xmm0, -75(%edx)
-L(aligned_16_59bytes):
-	movdqa	%xmm0, -59(%edx)
-L(aligned_16_43bytes):
-	movdqa	%xmm0, -43(%edx)
-L(aligned_16_27bytes):
-	movdqa	%xmm0, -27(%edx)
-L(aligned_16_11bytes):
-	movq	%xmm0, -11(%edx)
-	movw	%ax, -3(%edx)
-	movb	%al, -1(%edx)
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(aligned_16_124bytes):
-	movdqa	%xmm0, -124(%edx)
-L(aligned_16_108bytes):
-	movdqa	%xmm0, -108(%edx)
-L(aligned_16_92bytes):
-	movdqa	%xmm0, -92(%edx)
-L(aligned_16_76bytes):
-	movdqa	%xmm0, -76(%edx)
-L(aligned_16_60bytes):
-	movdqa	%xmm0, -60(%edx)
-L(aligned_16_44bytes):
-	movdqa	%xmm0, -44(%edx)
-L(aligned_16_28bytes):
-	movdqa	%xmm0, -28(%edx)
-L(aligned_16_12bytes):
-	movq	%xmm0, -12(%edx)
-	movl	%eax, -4(%edx)
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(aligned_16_125bytes):
-	movdqa	%xmm0, -125(%edx)
-L(aligned_16_109bytes):
-	movdqa	%xmm0, -109(%edx)
-L(aligned_16_93bytes):
-	movdqa	%xmm0, -93(%edx)
-L(aligned_16_77bytes):
-	movdqa	%xmm0, -77(%edx)
-L(aligned_16_61bytes):
-	movdqa	%xmm0, -61(%edx)
-L(aligned_16_45bytes):
-	movdqa	%xmm0, -45(%edx)
-L(aligned_16_29bytes):
-	movdqa	%xmm0, -29(%edx)
-L(aligned_16_13bytes):
-	movq	%xmm0, -13(%edx)
-	movl	%eax, -5(%edx)
-	movb	%al, -1(%edx)
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(aligned_16_126bytes):
-	movdqa	%xmm0, -126(%edx)
-L(aligned_16_110bytes):
-	movdqa	%xmm0, -110(%edx)
-L(aligned_16_94bytes):
-	movdqa	%xmm0, -94(%edx)
-L(aligned_16_78bytes):
-	movdqa	%xmm0, -78(%edx)
-L(aligned_16_62bytes):
-	movdqa	%xmm0, -62(%edx)
-L(aligned_16_46bytes):
-	movdqa	%xmm0, -46(%edx)
-L(aligned_16_30bytes):
-	movdqa	%xmm0, -30(%edx)
-L(aligned_16_14bytes):
-	movq	%xmm0, -14(%edx)
-	movl	%eax, -6(%edx)
-	movw	%ax, -2(%edx)
-	SETRTNVAL
-	RETURN
-
-	ALIGN(4)
-L(aligned_16_127bytes):
-	movdqa	%xmm0, -127(%edx)
-L(aligned_16_111bytes):
-	movdqa	%xmm0, -111(%edx)
-L(aligned_16_95bytes):
-	movdqa	%xmm0, -95(%edx)
-L(aligned_16_79bytes):
-	movdqa	%xmm0, -79(%edx)
-L(aligned_16_63bytes):
-	movdqa	%xmm0, -63(%edx)
-L(aligned_16_47bytes):
-	movdqa	%xmm0, -47(%edx)
-L(aligned_16_31bytes):
-	movdqa	%xmm0, -31(%edx)
-L(aligned_16_15bytes):
-	movq	%xmm0, -15(%edx)
-	movl	%eax, -7(%edx)
-	movw	%ax, -3(%edx)
-	movb	%al, -1(%edx)
-	SETRTNVAL
-	RETURN_END
-
-END(memset_atom)
diff --git a/libc/arch-x86/string/sse2-memset-slm.S b/libc/arch-x86/string/sse2-memset-slm.S
index e4c8fa1..ec2ee52 100644
--- a/libc/arch-x86/string/sse2-memset-slm.S
+++ b/libc/arch-x86/string/sse2-memset-slm.S
@@ -79,7 +79,7 @@
     /* We loaded the jump table and adjusted EDX. Go.  */	\
     jmp		*%ebx
 
-ENTRY(__memset_chk_generic)
+ENTRY(__memset_chk)
   ENTRANCE
 
   movl LEN(%esp), %ecx
@@ -88,11 +88,11 @@
 
   POP(%ebx) // Undo ENTRANCE without returning.
   jmp __memset_chk_fail
-END(__memset_chk_generic)
+END(__memset_chk)
 
 	.section .text.sse2,"ax",@progbits
 	ALIGN(4)
-ENTRY(memset_generic)
+ENTRY(memset)
 	ENTRANCE
 
 	movl	LEN(%esp), %ecx
@@ -755,4 +755,4 @@
 	SETRTNVAL
 	RETURN_END
 
-END(memset_generic)
+END(memset)
diff --git a/libc/arch-x86/string/sse2-stpcpy-slm.S b/libc/arch-x86/string/sse2-stpcpy-slm.S
old mode 100755
new mode 100644
diff --git a/libc/arch-x86/string/sse2-strcpy-slm.S b/libc/arch-x86/string/sse2-strcpy-slm.S
old mode 100755
new mode 100644
index 22ceeab..b5d84b5
--- a/libc/arch-x86/string/sse2-strcpy-slm.S
+++ b/libc/arch-x86/string/sse2-strcpy-slm.S
@@ -79,7 +79,7 @@
 #define POP(REG) popl REG; CFI_POP (REG)
 
 #ifndef STRCPY
-# define STRCPY  strcpy_generic
+# define STRCPY  strcpy
 #endif
 
 #ifdef USE_AS_STPNCPY
diff --git a/libc/arch-x86/string/sse2-strlen-slm.S b/libc/arch-x86/string/sse2-strlen-slm.S
old mode 100755
new mode 100644
index b805ad6..27cc025
--- a/libc/arch-x86/string/sse2-strlen-slm.S
+++ b/libc/arch-x86/string/sse2-strlen-slm.S
@@ -29,7 +29,7 @@
 */
 
 #ifndef STRLEN
-# define STRLEN strlen_generic
+# define STRLEN strlen
 #endif
 
 #ifndef L
diff --git a/libc/arch-x86/string/sse2-strncpy-slm.S b/libc/arch-x86/string/sse2-strncpy-slm.S
old mode 100755
new mode 100644
index aff7fb9..591419f
--- a/libc/arch-x86/string/sse2-strncpy-slm.S
+++ b/libc/arch-x86/string/sse2-strncpy-slm.S
@@ -29,5 +29,5 @@
 */

 

 #define USE_AS_STRNCPY

-#define STRCPY strncpy_generic

+#define STRCPY strncpy

 #include "sse2-strcpy-slm.S"

diff --git a/libc/arch-x86/string/sse2-wcschr-atom.S b/libc/arch-x86/string/sse2-wcschr-atom.S
deleted file mode 100644
index 729302b..0000000
--- a/libc/arch-x86/string/sse2-wcschr-atom.S
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
-Copyright (c) 2011 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.
-*/
-
-#ifndef L
-# define L(label)	.L##label
-#endif
-
-#ifndef cfi_startproc
-# define cfi_startproc	.cfi_startproc
-#endif
-
-#ifndef cfi_endproc
-# define cfi_endproc	.cfi_endproc
-#endif
-
-#ifndef cfi_rel_offset
-# define cfi_rel_offset(reg, off)	.cfi_rel_offset reg, off
-#endif
-
-#ifndef cfi_restore
-# define cfi_restore(reg)	.cfi_restore reg
-#endif
-
-#ifndef cfi_adjust_cfa_offset
-# define cfi_adjust_cfa_offset(off)	.cfi_adjust_cfa_offset off
-#endif
-
-#ifndef ENTRY
-# define ENTRY(name)	\
-	.type name,  @function;	\
-	.globl name;	\
-	.p2align 4;	\
-name:	\
-	cfi_startproc
-#endif
-
-#ifndef END
-# define END(name)	\
-	cfi_endproc;	\
-	.size name,	.-name
-#endif
-
-#define CFI_PUSH(REG)	\
-	cfi_adjust_cfa_offset (4);	\
-	cfi_rel_offset (REG, 0)
-
-#define CFI_POP(REG)	\
-	cfi_adjust_cfa_offset (-4);	\
-	cfi_restore (REG)
-
-#define PUSH(REG)	pushl REG; CFI_PUSH (REG)
-#define POP(REG)	popl REG; CFI_POP (REG)
-
-#define PARMS	4
-
-
-#define STR1  PARMS
-#define STR2  STR1+4
-
-	.text
-ENTRY (wcschr)
-
-	mov	STR1(%esp), %ecx
-	movd	STR2(%esp), %xmm1
-
-	mov	%ecx, %eax
-	punpckldq %xmm1, %xmm1
-	pxor	%xmm2, %xmm2
-	punpckldq %xmm1, %xmm1
-
-	and	$63, %eax
-	cmp	$48, %eax
-	ja	L(cross_cache)
-
-	movdqu	(%ecx), %xmm0
-	pcmpeqd	%xmm0, %xmm2
-	pcmpeqd	%xmm1, %xmm0
-	pmovmskb %xmm2, %edx
-	pmovmskb %xmm0, %eax
-	or	%eax, %edx
-	jnz	L(matches)
-	and	$-16, %ecx
-	jmp	L(loop)
-
-	.p2align 4
-L(cross_cache):
-	PUSH	(%edi)
-	mov	%ecx, %edi
-	mov	%eax, %ecx
-	and	$-16, %edi
-	and	$15, %ecx
-	movdqa	(%edi), %xmm0
-	pcmpeqd	%xmm0, %xmm2
-	pcmpeqd	%xmm1, %xmm0
-	pmovmskb %xmm2, %edx
-	pmovmskb %xmm0, %eax
-
-	sarl	%cl, %edx
-	sarl	%cl, %eax
-	test	%eax, %eax
-	jz	L(unaligned_no_match)
-
-	add	%edi, %ecx
-	POP	(%edi)
-
-	test	%edx, %edx
-	jz	L(match_case1)
-	test	%al, %al
-	jz	L(match_higth_case2)
-	test	$15, %al
-	jnz	L(match_case2_4)
-	test	$15, %dl
-	jnz	L(return_null)
-	lea	4(%ecx), %eax
-	ret
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(unaligned_no_match):
-	mov	%edi, %ecx
-	POP	(%edi)
-
-	test	%edx, %edx
-	jnz	L(return_null)
-
-	pxor	%xmm2, %xmm2
-
-/* Loop start on aligned string.  */
-	.p2align 4
-L(loop):
-	add	$16, %ecx
-	movdqa	(%ecx), %xmm0
-	pcmpeqd	%xmm0, %xmm2
-	pcmpeqd	%xmm1, %xmm0
-	pmovmskb %xmm2, %edx
-	pmovmskb %xmm0, %eax
-	or	%eax, %edx
-	jnz	L(matches)
-	add	$16, %ecx
-
-	movdqa	(%ecx), %xmm0
-	pcmpeqd	%xmm0, %xmm2
-	pcmpeqd	%xmm1, %xmm0
-	pmovmskb %xmm2, %edx
-	pmovmskb %xmm0, %eax
-	or	%eax, %edx
-	jnz	L(matches)
-	add	$16, %ecx
-
-	movdqa	(%ecx), %xmm0
-	pcmpeqd	%xmm0, %xmm2
-	pcmpeqd	%xmm1, %xmm0
-	pmovmskb %xmm2, %edx
-	pmovmskb %xmm0, %eax
-	or	%eax, %edx
-	jnz	L(matches)
-	add	$16, %ecx
-
-	movdqa	(%ecx), %xmm0
-	pcmpeqd	%xmm0, %xmm2
-	pcmpeqd	%xmm1, %xmm0
-	pmovmskb %xmm2, %edx
-	pmovmskb %xmm0, %eax
-	or	%eax, %edx
-	jz	L(loop)
-
-	.p2align 4
-L(matches):
-	pmovmskb %xmm2, %edx
-	test	%eax, %eax
-	jz	L(return_null)
-	test	%edx, %edx
-	jz	L(match_case1)
-
-	.p2align 4
-L(match_case2):
-	test	%al, %al
-	jz	L(match_higth_case2)
-	test	$15, %al
-	jnz	L(match_case2_4)
-	test	$15, %dl
-	jnz	L(return_null)
-	lea	4(%ecx), %eax
-	ret
-
-	.p2align 4
-L(match_case2_4):
-	mov	%ecx, %eax
-	ret
-
-	.p2align 4
-L(match_higth_case2):
-	test	%dl, %dl
-	jnz	L(return_null)
-	test	$15, %ah
-	jnz	L(match_case2_12)
-	test	$15, %dh
-	jnz	L(return_null)
-	lea	12(%ecx), %eax
-	ret
-
-	.p2align 4
-L(match_case2_12):
-	lea	8(%ecx), %eax
-	ret
-
-	.p2align 4
-L(match_case1):
-	test	%al, %al
-	jz	L(match_higth_case1)
-
-	test	$0x01, %al
-	jnz	L(exit0)
-	lea	4(%ecx), %eax
-	ret
-
-	.p2align 4
-L(match_higth_case1):
-	test	$0x01, %ah
-	jnz	L(exit3)
-	lea	12(%ecx), %eax
-	ret
-
-	.p2align 4
-L(exit0):
-	mov	%ecx, %eax
-	ret
-
-	.p2align 4
-L(exit3):
-	lea	8(%ecx), %eax
-	ret
-
-	.p2align 4
-L(return_null):
-	xor	%eax, %eax
-	ret
-
-END (wcschr)
diff --git a/libc/arch-x86/string/sse2-wcscmp-atom.S b/libc/arch-x86/string/sse2-wcscmp-atom.S
deleted file mode 100644
index 8867d28..0000000
--- a/libc/arch-x86/string/sse2-wcscmp-atom.S
+++ /dev/null
@@ -1,1062 +0,0 @@
-/*
-Copyright (c) 2011 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.
-*/
-
-#ifndef L
-# define L(label)	.L##label
-#endif
-
-#ifndef cfi_startproc
-# define cfi_startproc	.cfi_startproc
-#endif
-
-#ifndef cfi_endproc
-# define cfi_endproc	.cfi_endproc
-#endif
-
-#ifndef cfi_rel_offset
-# define cfi_rel_offset(reg, off)	.cfi_rel_offset reg, off
-#endif
-
-#ifndef cfi_restore
-# define cfi_restore(reg)	.cfi_restore reg
-#endif
-
-#ifndef cfi_adjust_cfa_offset
-# define cfi_adjust_cfa_offset(off)	.cfi_adjust_cfa_offset off
-#endif
-
-#ifndef ENTRY
-# define ENTRY(name)	\
-	.type name, @function;	\
-	.globl name;	\
-	.p2align 4;	\
-name:	\
-	cfi_startproc
-#endif
-
-#ifndef END
-# define END(name)	\
-	cfi_endproc;	\
-	.size name, .-name
-#endif
-
-#define CFI_PUSH(REG)	\
-	cfi_adjust_cfa_offset (4);	\
-	cfi_rel_offset (REG, 0)
-
-#define CFI_POP(REG)	\
-	cfi_adjust_cfa_offset (-4);	\
-	cfi_restore (REG)
-
-#define PUSH(REG) pushl REG; CFI_PUSH (REG)
-#define POP(REG) popl REG; CFI_POP (REG)
-
-#define ENTRANCE PUSH(%esi); PUSH(%edi)
-#define RETURN  POP(%edi); POP(%esi); ret; CFI_PUSH(%esi); CFI_PUSH(%edi);
-#define PARMS  4
-#define STR1  PARMS
-#define STR2  STR1+4
-
-	.text
-ENTRY (wcscmp)
-/*
-	* This implementation uses SSE to compare up to 16 bytes at a time.
-*/
-	mov	STR1(%esp), %edx
-	mov	STR2(%esp), %eax
-
-	mov	(%eax), %ecx
-	cmp	%ecx, (%edx)
-	jne	L(neq)
-	test	%ecx, %ecx
-	jz	L(eq)
-
-	mov	4(%eax), %ecx
-	cmp	%ecx, 4(%edx)
-	jne	L(neq)
-	test	%ecx, %ecx
-	jz	L(eq)
-
-	mov	8(%eax), %ecx
-	cmp	%ecx, 8(%edx)
-	jne	L(neq)
-	test	%ecx, %ecx
-	jz	L(eq)
-
-	mov	12(%eax), %ecx
-	cmp	%ecx, 12(%edx)
-	jne	L(neq)
-	test	%ecx, %ecx
-	jz	L(eq)
-
-	ENTRANCE
-	add	$16, %eax
-	add	$16, %edx
-
-	mov	%eax, %esi
-	mov	%edx, %edi
-	pxor	%xmm0, %xmm0		/* clear %xmm0 for null char checks */
-	mov	%al, %ch
-	mov	%dl, %cl
-	and	$63, %eax		/* esi alignment in cache line */
-	and	$63, %edx		/* edi alignment in cache line */
-	and	$15, %cl
-	jz	L(continue_00)
-	cmp	$16, %edx
-	jb	L(continue_0)
-	cmp	$32, %edx
-	jb	L(continue_16)
-	cmp	$48, %edx
-	jb	L(continue_32)
-
-L(continue_48):
-	and	$15, %ch
-	jz	L(continue_48_00)
-	cmp	$16, %eax
-	jb	L(continue_0_48)
-	cmp	$32, %eax
-	jb	L(continue_16_48)
-	cmp	$48, %eax
-	jb	L(continue_32_48)
-
-	.p2align 4
-L(continue_48_48):
-	mov	(%esi), %ecx
-	cmp	%ecx, (%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	4(%esi), %ecx
-	cmp	%ecx, 4(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	8(%esi), %ecx
-	cmp	%ecx, 8(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	12(%esi), %ecx
-	cmp	%ecx, 12(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	movdqu	16(%edi), %xmm1
-	movdqu	16(%esi), %xmm2
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm2, %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_16)
-
-	movdqu	32(%edi), %xmm1
-	movdqu	32(%esi), %xmm2
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm2, %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_32)
-
-	movdqu	48(%edi), %xmm1
-	movdqu	48(%esi), %xmm2
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm2, %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_48)
-
-	add	$64, %esi
-	add	$64, %edi
-	jmp	L(continue_48_48)
-
-L(continue_0):
-	and	$15, %ch
-	jz	L(continue_0_00)
-	cmp	$16, %eax
-	jb	L(continue_0_0)
-	cmp	$32, %eax
-	jb	L(continue_0_16)
-	cmp	$48, %eax
-	jb	L(continue_0_32)
-
-	.p2align 4
-L(continue_0_48):
-	mov	(%esi), %ecx
-	cmp	%ecx, (%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	4(%esi), %ecx
-	cmp	%ecx, 4(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	8(%esi), %ecx
-	cmp	%ecx, 8(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	12(%esi), %ecx
-	cmp	%ecx, 12(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	movdqu	16(%edi), %xmm1
-	movdqu	16(%esi), %xmm2
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm2, %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_16)
-
-	movdqu	32(%edi), %xmm1
-	movdqu	32(%esi), %xmm2
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm2, %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_32)
-
-	mov	48(%esi), %ecx
-	cmp	%ecx, 48(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	52(%esi), %ecx
-	cmp	%ecx, 52(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	56(%esi), %ecx
-	cmp	%ecx, 56(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	60(%esi), %ecx
-	cmp	%ecx, 60(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	add	$64, %esi
-	add	$64, %edi
-	jmp	L(continue_0_48)
-
-	.p2align 4
-L(continue_00):
-	and	$15, %ch
-	jz	L(continue_00_00)
-	cmp	$16, %eax
-	jb	L(continue_00_0)
-	cmp	$32, %eax
-	jb	L(continue_00_16)
-	cmp	$48, %eax
-	jb	L(continue_00_32)
-
-	.p2align 4
-L(continue_00_48):
-	pcmpeqd	(%edi), %xmm0
-	mov	(%edi), %eax
-	pmovmskb %xmm0, %ecx
-	test	%ecx, %ecx
-	jnz	L(less4_double_words1)
-
-	cmp	(%esi), %eax
-	jne	L(nequal)
-
-	mov	4(%edi), %eax
-	cmp	4(%esi), %eax
-	jne	L(nequal)
-
-	mov	8(%edi), %eax
-	cmp	8(%esi), %eax
-	jne	L(nequal)
-
-	mov	12(%edi), %eax
-	cmp	12(%esi), %eax
-	jne	L(nequal)
-
-	movdqu	16(%esi), %xmm2
-	pcmpeqd	%xmm2, %xmm0		/* Any null double_word? */
-	pcmpeqd	16(%edi), %xmm2		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm2		/* packed sub of comparison results*/
-	pmovmskb %xmm2, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_16)
-
-	movdqu	32(%esi), %xmm2
-	pcmpeqd	%xmm2, %xmm0		/* Any null double_word? */
-	pcmpeqd	32(%edi), %xmm2		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm2		/* packed sub of comparison results*/
-	pmovmskb %xmm2, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_32)
-
-	movdqu	48(%esi), %xmm2
-	pcmpeqd	%xmm2, %xmm0		/* Any null double_word? */
-	pcmpeqd	48(%edi), %xmm2		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm2		/* packed sub of comparison results*/
-	pmovmskb %xmm2, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_48)
-
-	add	$64, %esi
-	add	$64, %edi
-	jmp	L(continue_00_48)
-
-	.p2align 4
-L(continue_32):
-	and	$15, %ch
-	jz	L(continue_32_00)
-	cmp	$16, %eax
-	jb	L(continue_0_32)
-	cmp	$32, %eax
-	jb	L(continue_16_32)
-	cmp	$48, %eax
-	jb	L(continue_32_32)
-
-	.p2align 4
-L(continue_32_48):
-	mov	(%esi), %ecx
-	cmp	%ecx, (%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	4(%esi), %ecx
-	cmp	%ecx, 4(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	8(%esi), %ecx
-	cmp	%ecx, 8(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	12(%esi), %ecx
-	cmp	%ecx, 12(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	16(%esi), %ecx
-	cmp	%ecx, 16(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	20(%esi), %ecx
-	cmp	%ecx, 20(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	24(%esi), %ecx
-	cmp	%ecx, 24(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	28(%esi), %ecx
-	cmp	%ecx, 28(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	movdqu	32(%edi), %xmm1
-	movdqu	32(%esi), %xmm2
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm2, %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_32)
-
-	movdqu	48(%edi), %xmm1
-	movdqu	48(%esi), %xmm2
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm2, %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_48)
-
-	add	$64, %esi
-	add	$64, %edi
-	jmp	L(continue_32_48)
-
-	.p2align 4
-L(continue_16):
-	and	$15, %ch
-	jz	L(continue_16_00)
-	cmp	$16, %eax
-	jb	L(continue_0_16)
-	cmp	$32, %eax
-	jb	L(continue_16_16)
-	cmp	$48, %eax
-	jb	L(continue_16_32)
-
-	.p2align 4
-L(continue_16_48):
-	mov	(%esi), %ecx
-	cmp	%ecx, (%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	4(%esi), %ecx
-	cmp	%ecx, 4(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	8(%esi), %ecx
-	cmp	%ecx, 8(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	12(%esi), %ecx
-	cmp	%ecx, 12(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	movdqu	16(%edi), %xmm1
-	movdqu	16(%esi), %xmm2
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm2, %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_16)
-
-	mov	32(%esi), %ecx
-	cmp	%ecx, 32(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	36(%esi), %ecx
-	cmp	%ecx, 36(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	40(%esi), %ecx
-	cmp	%ecx, 40(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	44(%esi), %ecx
-	cmp	%ecx, 44(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	movdqu	48(%edi), %xmm1
-	movdqu	48(%esi), %xmm2
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm2, %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_48)
-
-	add	$64, %esi
-	add	$64, %edi
-	jmp	L(continue_16_48)
-
-	.p2align 4
-L(continue_00_00):
-	movdqa	(%edi), %xmm1
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	(%esi), %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words)
-
-	movdqa	16(%edi), %xmm3
-	pcmpeqd	%xmm3, %xmm0		/* Any null double_word? */
-	pcmpeqd	16(%esi), %xmm3		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm3		/* packed sub of comparison results*/
-	pmovmskb %xmm3, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_16)
-
-	movdqa	32(%edi), %xmm5
-	pcmpeqd	%xmm5, %xmm0		/* Any null double_word? */
-	pcmpeqd	32(%esi), %xmm5		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm5		/* packed sub of comparison results*/
-	pmovmskb %xmm5, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_32)
-
-	movdqa	48(%edi), %xmm1
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	48(%esi), %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_48)
-
-	add	$64, %esi
-	add	$64, %edi
-	jmp	L(continue_00_00)
-
-	.p2align 4
-L(continue_00_32):
-	movdqu	(%esi), %xmm2
-	pcmpeqd	%xmm2, %xmm0		/* Any null double_word? */
-	pcmpeqd	(%edi), %xmm2		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm2		/* packed sub of comparison results*/
-	pmovmskb %xmm2, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words)
-
-	add	$16, %esi
-	add	$16, %edi
-	jmp	L(continue_00_48)
-
-	.p2align 4
-L(continue_00_16):
-	movdqu	(%esi), %xmm2
-	pcmpeqd	%xmm2, %xmm0		/* Any null double_word? */
-	pcmpeqd	(%edi), %xmm2		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm2		/* packed sub of comparison results*/
-	pmovmskb %xmm2, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words)
-
-	movdqu	16(%esi), %xmm2
-	pcmpeqd	%xmm2, %xmm0		/* Any null double_word? */
-	pcmpeqd	16(%edi), %xmm2		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm2		/* packed sub of comparison results*/
-	pmovmskb %xmm2, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_16)
-
-	add	$32, %esi
-	add	$32, %edi
-	jmp	L(continue_00_48)
-
-	.p2align 4
-L(continue_00_0):
-	movdqu	(%esi), %xmm2
-	pcmpeqd	%xmm2, %xmm0		/* Any null double_word? */
-	pcmpeqd	(%edi), %xmm2		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm2		/* packed sub of comparison results*/
-	pmovmskb %xmm2, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words)
-
-	movdqu	16(%esi), %xmm2
-	pcmpeqd	%xmm2, %xmm0		/* Any null double_word? */
-	pcmpeqd	16(%edi), %xmm2		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm2		/* packed sub of comparison results*/
-	pmovmskb %xmm2, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_16)
-
-	movdqu	32(%esi), %xmm2
-	pcmpeqd	%xmm2, %xmm0		/* Any null double_word? */
-	pcmpeqd	32(%edi), %xmm2		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm2		/* packed sub of comparison results*/
-	pmovmskb %xmm2, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_32)
-
-	add	$48, %esi
-	add	$48, %edi
-	jmp	L(continue_00_48)
-
-	.p2align 4
-L(continue_48_00):
-	pcmpeqd	(%esi), %xmm0
-	mov	(%edi), %eax
-	pmovmskb %xmm0, %ecx
-	test	%ecx, %ecx
-	jnz	L(less4_double_words1)
-
-	cmp	(%esi), %eax
-	jne	L(nequal)
-
-	mov	4(%edi), %eax
-	cmp	4(%esi), %eax
-	jne	L(nequal)
-
-	mov	8(%edi), %eax
-	cmp	8(%esi), %eax
-	jne	L(nequal)
-
-	mov	12(%edi), %eax
-	cmp	12(%esi), %eax
-	jne	L(nequal)
-
-	movdqu	16(%edi), %xmm1
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	16(%esi), %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_16)
-
-	movdqu	32(%edi), %xmm1
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	32(%esi), %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_32)
-
-	movdqu	48(%edi), %xmm1
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	48(%esi), %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_48)
-
-	add	$64, %esi
-	add	$64, %edi
-	jmp	L(continue_48_00)
-
-	.p2align 4
-L(continue_32_00):
-	movdqu	(%edi), %xmm1
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	(%esi), %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words)
-
-	add	$16, %esi
-	add	$16, %edi
-	jmp	L(continue_48_00)
-
-	.p2align 4
-L(continue_16_00):
-	movdqu	(%edi), %xmm1
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	(%esi), %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words)
-
-	movdqu	16(%edi), %xmm1
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	16(%esi), %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_16)
-
-	add	$32, %esi
-	add	$32, %edi
-	jmp	L(continue_48_00)
-
-	.p2align 4
-L(continue_0_00):
-	movdqu	(%edi), %xmm1
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	(%esi), %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words)
-
-	movdqu	16(%edi), %xmm1
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	16(%esi), %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_16)
-
-	movdqu	32(%edi), %xmm1
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	32(%esi), %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_32)
-
-	add	$48, %esi
-	add	$48, %edi
-	jmp	L(continue_48_00)
-
-	.p2align 4
-L(continue_32_32):
-	movdqu	(%edi), %xmm1
-	movdqu	(%esi), %xmm2
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm2, %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words)
-
-	add	$16, %esi
-	add	$16, %edi
-	jmp	L(continue_48_48)
-
-	.p2align 4
-L(continue_16_16):
-	movdqu	(%edi), %xmm1
-	movdqu	(%esi), %xmm2
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm2, %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words)
-
-	movdqu	16(%edi), %xmm3
-	movdqu	16(%esi), %xmm4
-	pcmpeqd	%xmm3, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm4, %xmm3		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm3		/* packed sub of comparison results*/
-	pmovmskb %xmm3, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_16)
-
-	add	$32, %esi
-	add	$32, %edi
-	jmp	L(continue_48_48)
-
-	.p2align 4
-L(continue_0_0):
-	movdqu	(%edi), %xmm1
-	movdqu	(%esi), %xmm2
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm2, %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words)
-
-	movdqu	16(%edi), %xmm3
-	movdqu	16(%esi), %xmm4
-	pcmpeqd	%xmm3, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm4, %xmm3		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm3		/* packed sub of comparison results*/
-	pmovmskb %xmm3, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_16)
-
-	movdqu	32(%edi), %xmm1
-	movdqu	32(%esi), %xmm2
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm2, %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_32)
-
-	add	$48, %esi
-	add	$48, %edi
-	jmp	L(continue_48_48)
-
-	.p2align 4
-L(continue_0_16):
-	movdqu	(%edi), %xmm1
-	movdqu	(%esi), %xmm2
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm2, %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words)
-
-	movdqu	16(%edi), %xmm1
-	movdqu	16(%esi), %xmm2
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm2, %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words_16)
-
-	add	$32, %esi
-	add	$32, %edi
-	jmp	L(continue_32_48)
-
-	.p2align 4
-L(continue_0_32):
-	movdqu	(%edi), %xmm1
-	movdqu	(%esi), %xmm2
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm2, %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words)
-
-	add	$16, %esi
-	add	$16, %edi
-	jmp	L(continue_16_48)
-
-	.p2align 4
-L(continue_16_32):
-	movdqu	(%edi), %xmm1
-	movdqu	(%esi), %xmm2
-	pcmpeqd	%xmm1, %xmm0		/* Any null double_word? */
-	pcmpeqd	%xmm2, %xmm1		/* compare first 4 double_words for equality */
-	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
-	pmovmskb %xmm1, %edx
-	sub	$0xffff, %edx		/* if first 4 double_words are same, edx == 0xffff */
-	jnz	L(less4_double_words)
-
-	add	$16, %esi
-	add	$16, %edi
-	jmp	L(continue_32_48)
-
-	.p2align 4
-L(less4_double_words1):
-	cmp	(%esi), %eax
-	jne	L(nequal)
-	test	%eax, %eax
-	jz	L(equal)
-
-	mov	4(%esi), %ecx
-	cmp	%ecx, 4(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	8(%esi), %ecx
-	cmp	%ecx, 8(%edi)
-	jne	L(nequal)
-	test	%ecx, %ecx
-	jz	L(equal)
-
-	mov	12(%esi), %ecx
-	cmp	%ecx, 12(%edi)
-	jne	L(nequal)
-	xor	%eax, %eax
-	RETURN
-
-	.p2align 4
-L(less4_double_words):
-	xor	%eax, %eax
-	test	%dl, %dl
-	jz	L(next_two_double_words)
-	and	$15, %dl
-	jz	L(second_double_word)
-	mov	(%esi), %ecx
-	cmp	%ecx, (%edi)
-	jne	L(nequal)
-	RETURN
-
-	.p2align 4
-L(second_double_word):
-	mov	4(%esi), %ecx
-	cmp	%ecx, 4(%edi)
-	jne	L(nequal)
-	RETURN
-
-	.p2align 4
-L(next_two_double_words):
-	and	$15, %dh
-	jz	L(fourth_double_word)
-	mov	8(%esi), %ecx
-	cmp	%ecx, 8(%edi)
-	jne	L(nequal)
-	RETURN
-
-	.p2align 4
-L(fourth_double_word):
-	mov	12(%esi), %ecx
-	cmp	%ecx, 12(%edi)
-	jne	L(nequal)
-	RETURN
-
-	.p2align 4
-L(less4_double_words_16):
-	xor	%eax, %eax
-	test	%dl, %dl
-	jz	L(next_two_double_words_16)
-	and	$15, %dl
-	jz	L(second_double_word_16)
-	mov	16(%esi), %ecx
-	cmp	%ecx, 16(%edi)
-	jne	L(nequal)
-	RETURN
-
-	.p2align 4
-L(second_double_word_16):
-	mov	20(%esi), %ecx
-	cmp	%ecx, 20(%edi)
-	jne	L(nequal)
-	RETURN
-
-	.p2align 4
-L(next_two_double_words_16):
-	and	$15, %dh
-	jz	L(fourth_double_word_16)
-	mov	24(%esi), %ecx
-	cmp	%ecx, 24(%edi)
-	jne	L(nequal)
-	RETURN
-
-	.p2align 4
-L(fourth_double_word_16):
-	mov	28(%esi), %ecx
-	cmp	%ecx, 28(%edi)
-	jne	L(nequal)
-	RETURN
-
-	.p2align 4
-L(less4_double_words_32):
-	xor	%eax, %eax
-	test	%dl, %dl
-	jz	L(next_two_double_words_32)
-	and	$15, %dl
-	jz	L(second_double_word_32)
-	mov	32(%esi), %ecx
-	cmp	%ecx, 32(%edi)
-	jne	L(nequal)
-	RETURN
-
-	.p2align 4
-L(second_double_word_32):
-	mov	36(%esi), %ecx
-	cmp	%ecx, 36(%edi)
-	jne	L(nequal)
-	RETURN
-
-	.p2align 4
-L(next_two_double_words_32):
-	and	$15, %dh
-	jz	L(fourth_double_word_32)
-	mov	40(%esi), %ecx
-	cmp	%ecx, 40(%edi)
-	jne	L(nequal)
-	RETURN
-
-	.p2align 4
-L(fourth_double_word_32):
-	mov	44(%esi), %ecx
-	cmp	%ecx, 44(%edi)
-	jne	L(nequal)
-	RETURN
-
-	.p2align 4
-L(less4_double_words_48):
-	xor	%eax, %eax
-	test	%dl, %dl
-	jz	L(next_two_double_words_48)
-	and	$15, %dl
-	jz	L(second_double_word_48)
-	mov	48(%esi), %ecx
-	cmp	%ecx, 48(%edi)
-	jne	L(nequal)
-	RETURN
-
-	.p2align 4
-L(second_double_word_48):
-	mov	52(%esi), %ecx
-	cmp	%ecx, 52(%edi)
-	jne	L(nequal)
-	RETURN
-
-	.p2align 4
-L(next_two_double_words_48):
-	and	$15, %dh
-	jz	L(fourth_double_word_48)
-	mov	56(%esi), %ecx
-	cmp	%ecx, 56(%edi)
-	jne	L(nequal)
-	RETURN
-
-	.p2align 4
-L(fourth_double_word_48):
-	mov	60(%esi), %ecx
-	cmp	%ecx, 60(%edi)
-	jne	L(nequal)
-	RETURN
-
-	.p2align 4
-L(nequal):
-	mov	$1, %eax
-	jg	L(return)
-	neg	%eax
-	RETURN
-
-	.p2align 4
-L(return):
-	RETURN
-
-	.p2align 4
-L(equal):
-	xorl	%eax, %eax
-	RETURN
-
-	CFI_POP (%edi)
-	CFI_POP (%esi)
-
-	.p2align 4
-L(neq):
-	mov	$1, %eax
-	jg	L(neq_bigger)
-	neg	%eax
-
-L(neq_bigger):
-	ret
-
-	.p2align 4
-L(eq):
-	xorl	%eax, %eax
-	ret
-
-END (wcscmp)
-
diff --git a/libc/arch-x86/string/sse2-wcslen-atom.S b/libc/arch-x86/string/sse2-wcslen-atom.S
deleted file mode 100644
index 2f10db4..0000000
--- a/libc/arch-x86/string/sse2-wcslen-atom.S
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
-Copyright (c) 2011 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.
-*/
-
-#ifndef USE_AS_WCSCAT
-
-# ifndef L
-#  define L(label)	.L##label
-# endif
-
-# ifndef cfi_startproc
-#  define cfi_startproc	.cfi_startproc
-# endif
-
-# ifndef cfi_endproc
-#  define cfi_endproc	.cfi_endproc
-# endif
-
-# ifndef ENTRY
-#  define ENTRY(name)	\
-	.type name,  @function;	\
-	.globl name;	\
-	.p2align 4;	\
-name:	\
-	cfi_startproc
-# endif
-
-# ifndef END
-#  define END(name)	\
-	cfi_endproc;	\
-	.size name, .-name
-# endif
-
-# define PARMS	4
-# define STR	PARMS
-# define RETURN ret
-
-	.text
-ENTRY (wcslen)
-	mov	STR(%esp), %edx
-#endif
-	cmpl	$0, (%edx)
-	jz	L(exit_tail0)
-	cmpl	$0, 4(%edx)
-	jz	L(exit_tail1)
-	cmpl	$0, 8(%edx)
-	jz	L(exit_tail2)
-	cmpl	$0, 12(%edx)
-	jz	L(exit_tail3)
-	cmpl	$0, 16(%edx)
-	jz	L(exit_tail4)
-	cmpl	$0, 20(%edx)
-	jz	L(exit_tail5)
-	cmpl	$0, 24(%edx)
-	jz	L(exit_tail6)
-	cmpl	$0, 28(%edx)
-	jz	L(exit_tail7)
-
-	pxor	%xmm0, %xmm0
-
-	lea	32(%edx), %eax
-	lea	-16(%eax), %ecx
-	and	$-16, %eax
-
-	pcmpeqd	(%eax), %xmm0
-	pmovmskb %xmm0, %edx
-	pxor	%xmm1, %xmm1
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	(%eax), %xmm1
-	pmovmskb %xmm1, %edx
-	pxor	%xmm2, %xmm2
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	(%eax), %xmm2
-	pmovmskb %xmm2, %edx
-	pxor	%xmm3, %xmm3
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	(%eax), %xmm0
-	pmovmskb %xmm0, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	(%eax), %xmm1
-	pmovmskb %xmm1, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	(%eax), %xmm2
-	pmovmskb %xmm2, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	(%eax), %xmm0
-	pmovmskb %xmm0, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	(%eax), %xmm1
-	pmovmskb %xmm1, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	(%eax), %xmm2
-	pmovmskb %xmm2, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	(%eax), %xmm0
-	pmovmskb %xmm0, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	(%eax), %xmm1
-	pmovmskb %xmm1, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	(%eax), %xmm2
-	pmovmskb %xmm2, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	and	$-0x40, %eax
-
-	.p2align 4
-L(aligned_64_loop):
-	movaps	(%eax), %xmm0
-	movaps	16(%eax), %xmm1
-	movaps	32(%eax), %xmm2
-	movaps	48(%eax), %xmm6
-
-	pminub	%xmm1, %xmm0
-	pminub	%xmm6, %xmm2
-	pminub	%xmm0, %xmm2
-	pcmpeqd	%xmm3, %xmm2
-	pmovmskb %xmm2, %edx
-	lea	64(%eax), %eax
-	test	%edx, %edx
-	jz	L(aligned_64_loop)
-
-	pcmpeqd	-64(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	48(%ecx), %ecx
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	%xmm1, %xmm3
-	pmovmskb %xmm3, %edx
-	lea	-16(%ecx), %ecx
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	-32(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	-16(%ecx), %ecx
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqd	%xmm6, %xmm3
-	pmovmskb %xmm3, %edx
-	lea	-16(%ecx), %ecx
-	test	%edx, %edx
-	jnz	L(exit)
-
-	jmp	L(aligned_64_loop)
-
-	.p2align 4
-L(exit):
-	sub	%ecx, %eax
-	shr	$2, %eax
-	test	%dl, %dl
-	jz	L(exit_high)
-
-	mov	%dl, %cl
-	and	$15, %cl
-	jz	L(exit_1)
-	RETURN
-
-	.p2align 4
-L(exit_high):
-	mov	%dh, %ch
-	and	$15, %ch
-	jz	L(exit_3)
-	add	$2, %eax
-	RETURN
-
-	.p2align 4
-L(exit_1):
-	add	$1, %eax
-	RETURN
-
-	.p2align 4
-L(exit_3):
-	add	$3, %eax
-	RETURN
-
-	.p2align 4
-L(exit_tail0):
-	xor	%eax, %eax
-	RETURN
-
-	.p2align 4
-L(exit_tail1):
-	mov	$1, %eax
-	RETURN
-
-	.p2align 4
-L(exit_tail2):
-	mov	$2, %eax
-	RETURN
-
-	.p2align 4
-L(exit_tail3):
-	mov	$3, %eax
-	RETURN
-
-	.p2align 4
-L(exit_tail4):
-	mov	$4, %eax
-	RETURN
-
-	.p2align 4
-L(exit_tail5):
-	mov	$5, %eax
-	RETURN
-
-	.p2align 4
-L(exit_tail6):
-	mov	$6, %eax
-	RETURN
-
-	.p2align 4
-L(exit_tail7):
-	mov	$7, %eax
-#ifndef USE_AS_WCSCAT
-	RETURN
-
-END (wcslen)
-#endif
diff --git a/libc/arch-x86/string/sse2-wcsrchr-atom.S b/libc/arch-x86/string/sse2-wcsrchr-atom.S
deleted file mode 100644
index 1a55df2..0000000
--- a/libc/arch-x86/string/sse2-wcsrchr-atom.S
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
-Copyright (c) 2011 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.
-*/
-
-#ifndef L
-# define L(label)	.L##label
-#endif
-
-#ifndef cfi_startproc
-# define cfi_startproc	.cfi_startproc
-#endif
-
-#ifndef cfi_endproc
-# define cfi_endproc	.cfi_endproc
-#endif
-
-#ifndef cfi_rel_offset
-# define cfi_rel_offset(reg, off)	.cfi_rel_offset reg, off
-#endif
-
-#ifndef cfi_restore
-# define cfi_restore(reg)	.cfi_restore reg
-#endif
-
-#ifndef cfi_adjust_cfa_offset
-# define cfi_adjust_cfa_offset(off)	.cfi_adjust_cfa_offset off
-#endif
-
-#ifndef ENTRY
-# define ENTRY(name)	\
-	.type name, @function;	\
-	.globl name;	\
-	.p2align 4;	\
-name:	\
-	cfi_startproc
-#endif
-
-#ifndef END
-# define END(name)	\
-	cfi_endproc;	\
-	.size name, .-name
-#endif
-
-#define CFI_PUSH(REG)	\
-	cfi_adjust_cfa_offset (4);	\
-	cfi_rel_offset (REG, 0)
-
-#define CFI_POP(REG)	\
-	cfi_adjust_cfa_offset (-4);	\
-	cfi_restore (REG)
-
-#define PUSH(REG)	pushl REG;	CFI_PUSH (REG)
-#define POP(REG)	popl REG;	CFI_POP (REG)
-
-#define PARMS  8
-#define ENTRANCE PUSH(%edi);
-#define RETURN  POP(%edi);	ret;	CFI_PUSH(%edi);
-
-#define STR1  PARMS
-#define STR2  STR1+4
-
-	.text
-ENTRY (wcsrchr)
-
-	ENTRANCE
-	mov	STR1(%esp), %ecx
-	movd	STR2(%esp), %xmm1
-
-	mov	%ecx, %edi
-	punpckldq %xmm1, %xmm1
-	pxor	%xmm2, %xmm2
-	punpckldq %xmm1, %xmm1
-
-/* ECX has OFFSET. */
-	and	$63, %ecx
-	cmp	$48, %ecx
-	ja	L(crosscache)
-
-/* unaligned string. */
-	movdqu	(%edi), %xmm0
-	pcmpeqd	%xmm0, %xmm2
-	pcmpeqd	%xmm1, %xmm0
-/* Find where NULL is.  */
-	pmovmskb %xmm2, %ecx
-/* Check if there is a match.  */
-	pmovmskb %xmm0, %eax
-	add	$16, %edi
-
-	test	%eax, %eax
-	jnz	L(unaligned_match1)
-
-	test	%ecx, %ecx
-	jnz	L(return_null)
-
-	and	$-16, %edi
-
-	PUSH	(%esi)
-
-	xor	%edx, %edx
-	jmp	L(loop)
-
-	CFI_POP	(%esi)
-
-	.p2align 4
-L(unaligned_match1):
-	test	%ecx, %ecx
-	jnz	L(prolog_find_zero_1)
-
-	PUSH	(%esi)
-
-/* Save current match */
-	mov	%eax, %edx
-	mov	%edi, %esi
-	and	$-16, %edi
-	jmp	L(loop)
-
-	CFI_POP	(%esi)
-
-	.p2align 4
-L(crosscache):
-/* Hancle unaligned string.  */
-	and	$15, %ecx
-	and	$-16, %edi
-	pxor	%xmm3, %xmm3
-	movdqa	(%edi), %xmm0
-	pcmpeqd	%xmm0, %xmm3
-	pcmpeqd	%xmm1, %xmm0
-/* Find where NULL is.  */
-	pmovmskb %xmm3, %edx
-/* Check if there is a match.  */
-	pmovmskb %xmm0, %eax
-/* Remove the leading bytes.  */
-	shr	%cl, %edx
-	shr	%cl, %eax
-	add	$16, %edi
-
-	test	%eax, %eax
-	jnz	L(unaligned_match)
-
-	test	%edx, %edx
-	jnz	L(return_null)
-
-	PUSH	(%esi)
-
-	xor	%edx, %edx
-	jmp	L(loop)
-
-	CFI_POP	(%esi)
-
-	.p2align 4
-L(unaligned_match):
-	test	%edx, %edx
-	jnz	L(prolog_find_zero)
-
-	PUSH	(%esi)
-
-	mov	%eax, %edx
-	lea	(%edi, %ecx), %esi
-
-/* Loop start on aligned string.  */
-	.p2align 4
-L(loop):
-	movdqa	(%edi), %xmm0
-	pcmpeqd	%xmm0, %xmm2
-	add	$16, %edi
-	pcmpeqd	%xmm1, %xmm0
-	pmovmskb %xmm2, %ecx
-	pmovmskb %xmm0, %eax
-	or	%eax, %ecx
-	jnz	L(matches)
-
-	movdqa	(%edi), %xmm3
-	pcmpeqd	%xmm3, %xmm2
-	add	$16, %edi
-	pcmpeqd	%xmm1, %xmm3
-	pmovmskb %xmm2, %ecx
-	pmovmskb %xmm3, %eax
-	or	%eax, %ecx
-	jnz	L(matches)
-
-	movdqa	(%edi), %xmm4
-	pcmpeqd	%xmm4, %xmm2
-	add	$16, %edi
-	pcmpeqd	%xmm1, %xmm4
-	pmovmskb %xmm2, %ecx
-	pmovmskb %xmm4, %eax
-	or	%eax, %ecx
-	jnz	L(matches)
-
-	movdqa	(%edi), %xmm5
-	pcmpeqd	%xmm5, %xmm2
-	add	$16, %edi
-	pcmpeqd	%xmm1, %xmm5
-	pmovmskb %xmm2, %ecx
-	pmovmskb %xmm5, %eax
-	or	%eax, %ecx
-	jz	L(loop)
-
-	.p2align 4
-L(matches):
-	test	%eax, %eax
-	jnz	L(match)
-L(return_value):
-	test	%edx, %edx
-	jz	L(return_null_1)
-	mov	%edx, %eax
-	mov	%esi, %edi
-
-	POP	(%esi)
-
-	test	%ah, %ah
-	jnz	L(match_third_or_fourth_wchar)
-	test	$15 << 4, %al
-	jnz	L(match_second_wchar)
-	lea	-16(%edi), %eax
-	RETURN
-
-	CFI_PUSH	(%esi)
-
-	.p2align 4
-L(return_null_1):
-	POP	(%esi)
-
-	xor	%eax, %eax
-	RETURN
-
-	CFI_PUSH	(%esi)
-
-	.p2align 4
-L(match):
-	pmovmskb %xmm2, %ecx
-	test	%ecx, %ecx
-	jnz	L(find_zero)
-/* save match info */
-	mov	%eax, %edx
-	mov	%edi, %esi
-	jmp	L(loop)
-
-	.p2align 4
-L(find_zero):
-	test	%cl, %cl
-	jz	L(find_zero_in_third_or_fourth_wchar)
-	test	$15, %cl
-	jz	L(find_zero_in_second_wchar)
-	and	$1, %eax
-	jz	L(return_value)
-
-	POP	(%esi)
-
-	lea	-16(%edi), %eax
-	RETURN
-
-	CFI_PUSH	(%esi)
-
-	.p2align 4
-L(find_zero_in_second_wchar):
-	and	$(1 << 5) - 1, %eax
-	jz	L(return_value)
-
-	POP	(%esi)
-
-	test	$15 << 4, %al
-	jnz	L(match_second_wchar)
-	lea	-16(%edi), %eax
-	RETURN
-
-	CFI_PUSH	(%esi)
-
-	.p2align 4
-L(find_zero_in_third_or_fourth_wchar):
-	test	$15, %ch
-	jz	L(find_zero_in_fourth_wchar)
-	and	$(1 << 9) - 1, %eax
-	jz	L(return_value)
-
-	POP	(%esi)
-
-	test	%ah, %ah
-	jnz	L(match_third_wchar)
-	test	$15 << 4, %al
-	jnz	L(match_second_wchar)
-	lea	-16(%edi), %eax
-	RETURN
-
-	CFI_PUSH	(%esi)
-
-	.p2align 4
-L(find_zero_in_fourth_wchar):
-
-	POP	(%esi)
-
-	test	%ah, %ah
-	jnz	L(match_third_or_fourth_wchar)
-	test	$15 << 4, %al
-	jnz	L(match_second_wchar)
-	lea	-16(%edi), %eax
-	RETURN
-
-	CFI_PUSH	(%esi)
-
-	.p2align 4
-L(match_second_wchar):
-	lea	-12(%edi), %eax
-	RETURN
-
-	.p2align 4
-L(match_third_or_fourth_wchar):
-	test	$15 << 4, %ah
-	jnz	L(match_fourth_wchar)
-	lea	-8(%edi), %eax
-	RETURN
-
-	.p2align 4
-L(match_third_wchar):
-	lea	-8(%edi), %eax
-	RETURN
-
-	.p2align 4
-L(match_fourth_wchar):
-	lea	-4(%edi), %eax
-	RETURN
-
-	.p2align 4
-L(return_null):
-	xor	%eax, %eax
-	RETURN
-
-	.p2align 4
-L(prolog_find_zero):
-	add	%ecx, %edi
-	mov     %edx, %ecx
-L(prolog_find_zero_1):
-	test	%cl, %cl
-	jz	L(prolog_find_zero_in_third_or_fourth_wchar)
-	test	$15, %cl
-	jz	L(prolog_find_zero_in_second_wchar)
-	and	$1, %eax
-	jz	L(return_null)
-
-	lea	-16(%edi), %eax
-	RETURN
-
-	.p2align 4
-L(prolog_find_zero_in_second_wchar):
-	and	$(1 << 5) - 1, %eax
-	jz	L(return_null)
-
-	test	$15 << 4, %al
-	jnz	L(match_second_wchar)
-	lea	-16(%edi), %eax
-	RETURN
-
-	.p2align 4
-L(prolog_find_zero_in_third_or_fourth_wchar):
-	test	$15, %ch
-	jz	L(prolog_find_zero_in_fourth_wchar)
-	and	$(1 << 9) - 1, %eax
-	jz	L(return_null)
-
-	test	%ah, %ah
-	jnz	L(match_third_wchar)
-	test	$15 << 4, %al
-	jnz	L(match_second_wchar)
-	lea	-16(%edi), %eax
-	RETURN
-
-	.p2align 4
-L(prolog_find_zero_in_fourth_wchar):
-	test	%ah, %ah
-	jnz	L(match_third_or_fourth_wchar)
-	test	$15 << 4, %al
-	jnz	L(match_second_wchar)
-	lea	-16(%edi), %eax
-	RETURN
-
-END (wcsrchr)
diff --git a/libc/arch-x86/string/sse4-memcmp-slm.S b/libc/arch-x86/string/sse4-memcmp-slm.S
old mode 100755
new mode 100644
diff --git a/libc/arch-x86/string/sse4-wmemcmp-slm.S b/libc/arch-x86/string/sse4-wmemcmp-slm.S
deleted file mode 100755
index 2bf92f5..0000000
--- a/libc/arch-x86/string/sse4-wmemcmp-slm.S
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-Copyright (c) 2014, 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 USE_AS_WMEMCMP
-#define MEMCMP wmemcmp_sse4
-#include "sse4-memcmp-slm.S"
diff --git a/libc/arch-x86/string/ssse3-memcpy-atom.S b/libc/arch-x86/string/ssse3-memcpy-atom.S
deleted file mode 100644
index 83e1985..0000000
--- a/libc/arch-x86/string/ssse3-memcpy-atom.S
+++ /dev/null
@@ -1,3124 +0,0 @@
-/*
-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 FOR_ATOM
-
-#ifndef MEMCPY
-# define MEMCPY	memcpy_atom
-#endif
-
-#ifndef L
-# define L(label)	.L##label
-#endif
-
-#ifndef cfi_startproc
-# define cfi_startproc	.cfi_startproc
-#endif
-
-#ifndef cfi_endproc
-# define cfi_endproc	.cfi_endproc
-#endif
-
-#ifndef cfi_rel_offset
-# define cfi_rel_offset(reg, off)	.cfi_rel_offset reg, off
-#endif
-
-#ifndef cfi_restore
-# define cfi_restore(reg)	.cfi_restore reg
-#endif
-
-#ifndef cfi_adjust_cfa_offset
-# define cfi_adjust_cfa_offset(off)	.cfi_adjust_cfa_offset off
-#endif
-
-#ifndef ENTRY
-# define ENTRY(name)		\
-	.type name,  @function;		\
-	.globl name;		\
-	.p2align 4;		\
-name:		\
-	cfi_startproc
-#endif
-
-#ifndef END
-# define END(name)		\
-	cfi_endproc;		\
-	.size name, .-name
-#endif
-
-#define DEST		PARMS
-#define SRC		DEST+4
-#define LEN		SRC+4
-
-#define CFI_PUSH(REG)		\
-  cfi_adjust_cfa_offset (4);		\
-  cfi_rel_offset (REG, 0)
-
-#define CFI_POP(REG)		\
-  cfi_adjust_cfa_offset (-4);		\
-  cfi_restore (REG)
-
-#define PUSH(REG)	pushl REG; CFI_PUSH (REG)
-#define POP(REG)	popl REG; CFI_POP (REG)
-
-#if (defined SHARED || defined __PIC__)
-# define PARMS		8		/* Preserve EBX.  */
-# define ENTRANCE	PUSH (%ebx);
-# define RETURN_END	POP (%ebx); ret
-# define RETURN		RETURN_END; CFI_PUSH (%ebx)
-# define JMPTBL(I, B)	I - B
-
-# define SETUP_PIC_REG(x)	call	__x86.get_pc_thunk.x
-
-/* Load an entry in a jump table into EBX and branch to it.  TABLE is a
-	jump table with relative offsets.  INDEX is a register contains the
-	index into the jump table.   SCALE is the scale of INDEX. */
-
-# define BRANCH_TO_JMPTBL_ENTRY(TABLE, INDEX, SCALE)		\
-    /* We first load PC into EBX.  */		\
-	SETUP_PIC_REG(bx);		\
-    /* Get the address of the jump table.  */		\
-	addl	$(TABLE - .), %ebx;		\
-    /* Get the entry and convert the relative offset to the		\
-	absolute	address.  */		\
-	addl	(%ebx, INDEX, SCALE), %ebx;		\
-    /* We loaded the jump table.  Go.  */		\
-	jmp	*%ebx
-#else
-
-# define PARMS		4
-# define ENTRANCE
-# define RETURN_END	ret
-# define RETURN		RETURN_END
-# define JMPTBL(I, B)	I
-
-/* Branch to an entry in a jump table.  TABLE is a jump table with
-	absolute offsets.  INDEX is a register contains the index into the
-	jump table.  SCALE is the scale of INDEX. */
-
-# define BRANCH_TO_JMPTBL_ENTRY(TABLE, INDEX, SCALE)		\
-	jmp	*TABLE(, INDEX, SCALE)
-#endif
-
-	.section .text.ssse3,"ax",@progbits
-ENTRY (MEMCPY)
-	ENTRANCE
-	movl	LEN(%esp), %ecx
-	movl	SRC(%esp), %eax
-	movl	DEST(%esp), %edx
-
-#ifdef USE_AS_MEMMOVE
-	cmp	%eax, %edx
-	jb	L(copy_forward)
-	je	L(fwd_write_0bytes)
-	cmp	$32, %ecx
-	jae	L(memmove_bwd)
-	jmp	L(bk_write_less32bytes_2)
-
-	.p2align 4
-L(memmove_bwd):
-	add	%ecx, %eax
-	cmp	%eax, %edx
-	movl	SRC(%esp), %eax
-	jb	L(copy_backward)
-
-L(copy_forward):
-#endif
-	cmp	$48, %ecx
-	jae	L(48bytesormore)
-
-L(fwd_write_less32bytes):
-#ifndef USE_AS_MEMMOVE
-	cmp	%dl, %al
-	jb	L(bk_write)
-#endif
-	add	%ecx, %edx
-	add	%ecx, %eax
-	BRANCH_TO_JMPTBL_ENTRY (L(table_48bytes_fwd), %ecx, 4)
-#ifndef USE_AS_MEMMOVE
-	.p2align 4
-L(bk_write):
-	BRANCH_TO_JMPTBL_ENTRY (L(table_48_bytes_bwd), %ecx, 4)
-#endif
-
-	.p2align 4
-L(48bytesormore):
-#ifndef USE_AS_MEMMOVE
-	movlpd	(%eax), %xmm0
-	movlpd	8(%eax), %xmm1
-	movlpd	%xmm0, (%edx)
-	movlpd	%xmm1, 8(%edx)
-#else
-	movdqu	(%eax), %xmm0
-#endif
-	PUSH (%edi)
-	movl	%edx, %edi
-	and	$-16, %edx
-	add	$16, %edx
-	sub	%edx, %edi
-	add	%edi, %ecx
-	sub	%edi, %eax
-
-#ifdef SHARED_CACHE_SIZE_HALF
-	cmp	$SHARED_CACHE_SIZE_HALF, %ecx
-#else
-# if (defined SHARED || defined __PIC__)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_shared_cache_size_half@GOTOFF(%ebx), %ecx
-# else
-	cmp	__x86_shared_cache_size_half, %ecx
-# endif
-#endif
-
-	mov	%eax, %edi
-	jae	L(large_page)
-	and	$0xf, %edi
-	jz	L(shl_0)
-	BRANCH_TO_JMPTBL_ENTRY (L(shl_table), %edi, 4)
-
-	.p2align 4
-L(shl_0):
-#ifdef USE_AS_MEMMOVE
-	movl	DEST+4(%esp), %edi
-	movdqu	%xmm0, (%edi)
-#endif
-	xor	%edi, %edi
-	cmp	$127, %ecx
-	ja	L(shl_0_gobble)
-	lea	-32(%ecx), %ecx
-
-	.p2align 4
-L(shl_0_loop):
-	movdqa	(%eax, %edi), %xmm0
-	movdqa	16(%eax, %edi), %xmm1
-	sub	$32, %ecx
-	movdqa	%xmm0, (%edx, %edi)
-	movdqa	%xmm1, 16(%edx, %edi)
-	lea	32(%edi), %edi
-	jb	L(shl_0_end)
-
-	movdqa	(%eax, %edi), %xmm0
-	movdqa	16(%eax, %edi), %xmm1
-	sub	$32, %ecx
-	movdqa	%xmm0, (%edx, %edi)
-	movdqa	%xmm1, 16(%edx, %edi)
-	lea	32(%edi), %edi
-	jb	L(shl_0_end)
-
-	movdqa	(%eax, %edi), %xmm0
-	movdqa	16(%eax, %edi), %xmm1
-	sub	$32, %ecx
-	movdqa	%xmm0, (%edx, %edi)
-	movdqa	%xmm1, 16(%edx, %edi)
-	lea	32(%edi), %edi
-	jb	L(shl_0_end)
-
-	movdqa	(%eax, %edi), %xmm0
-	movdqa	16(%eax, %edi), %xmm1
-	sub	$32, %ecx
-	movdqa	%xmm0, (%edx, %edi)
-	movdqa	%xmm1, 16(%edx, %edi)
-	lea	32(%edi), %edi
-
-L(shl_0_end):
-	lea	32(%ecx), %ecx
-	add	%ecx, %edi
-	add	%edi, %edx
-	add	%edi, %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY (L(table_48bytes_fwd_align), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(shl_0_gobble):
-#ifdef DATA_CACHE_SIZE_HALF
-	cmp	$DATA_CACHE_SIZE_HALF, %ecx
-#else
-# if (defined SHARED || defined __PIC__)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
-# else
-	cmp	__x86_data_cache_size_half, %ecx
-# endif
-#endif
-	POP	(%edi)
-	lea	-128(%ecx), %ecx
-	jae	L(shl_0_gobble_mem_loop)
-
-	.p2align 4
-L(shl_0_gobble_cache_loop):
-	movdqa	(%eax), %xmm0
-	movdqa	0x10(%eax), %xmm1
-	movdqa	0x20(%eax), %xmm2
-	movdqa	0x30(%eax), %xmm3
-	movdqa	0x40(%eax), %xmm4
-	movdqa	0x50(%eax), %xmm5
-	movdqa	0x60(%eax), %xmm6
-	movdqa	0x70(%eax), %xmm7
-	lea	0x80(%eax), %eax
-	sub	$128, %ecx
-	movdqa	%xmm0, (%edx)
-	movdqa	%xmm1, 0x10(%edx)
-	movdqa	%xmm2, 0x20(%edx)
-	movdqa	%xmm3, 0x30(%edx)
-	movdqa	%xmm4, 0x40(%edx)
-	movdqa	%xmm5, 0x50(%edx)
-	movdqa	%xmm6, 0x60(%edx)
-	movdqa	%xmm7, 0x70(%edx)
-	lea	0x80(%edx), %edx
-
-	jae	L(shl_0_gobble_cache_loop)
-	cmp	$-0x40, %ecx
-	lea	0x80(%ecx), %ecx
-	jl	L(shl_0_cache_less_64bytes)
-
-	movdqa	(%eax), %xmm0
-	sub	$0x40, %ecx
-	movdqa	0x10(%eax), %xmm1
-	movdqa	%xmm0, (%edx)
-	movdqa	%xmm1, 0x10(%edx)
-	movdqa	0x20(%eax), %xmm0
-	movdqa	0x30(%eax), %xmm1
-	add	$0x40, %eax
-	movdqa	%xmm0, 0x20(%edx)
-	movdqa	%xmm1, 0x30(%edx)
-	add	$0x40, %edx
-
-L(shl_0_cache_less_64bytes):
-	cmp	$0x20, %ecx
-	jb	L(shl_0_cache_less_32bytes)
-	movdqa	(%eax), %xmm0
-	sub	$0x20, %ecx
-	movdqa	0x10(%eax), %xmm1
-	add	$0x20, %eax
-	movdqa	%xmm0, (%edx)
-	movdqa	%xmm1, 0x10(%edx)
-	add	$0x20, %edx
-
-L(shl_0_cache_less_32bytes):
-	cmp	$0x10, %ecx
-	jb	L(shl_0_cache_less_16bytes)
-	sub	$0x10, %ecx
-	movdqa	(%eax), %xmm0
-	add	$0x10, %eax
-	movdqa	%xmm0, (%edx)
-	add	$0x10, %edx
-
-L(shl_0_cache_less_16bytes):
-	add	%ecx, %edx
-	add	%ecx, %eax
-	BRANCH_TO_JMPTBL_ENTRY (L(table_48bytes_fwd), %ecx, 4)
-
-	.p2align 4
-L(shl_0_gobble_mem_loop):
-	prefetcht0 0x1c0(%eax)
-	prefetcht0 0x280(%eax)
-	prefetcht0 0x1c0(%edx)
-
-	movdqa	(%eax), %xmm0
-	movdqa	0x10(%eax), %xmm1
-	movdqa	0x20(%eax), %xmm2
-	movdqa	0x30(%eax), %xmm3
-	movdqa	0x40(%eax), %xmm4
-	movdqa	0x50(%eax), %xmm5
-	movdqa	0x60(%eax), %xmm6
-	movdqa	0x70(%eax), %xmm7
-	lea	0x80(%eax), %eax
-	sub	$0x80, %ecx
-	movdqa	%xmm0, (%edx)
-	movdqa	%xmm1, 0x10(%edx)
-	movdqa	%xmm2, 0x20(%edx)
-	movdqa	%xmm3, 0x30(%edx)
-	movdqa	%xmm4, 0x40(%edx)
-	movdqa	%xmm5, 0x50(%edx)
-	movdqa	%xmm6, 0x60(%edx)
-	movdqa	%xmm7, 0x70(%edx)
-	lea	0x80(%edx), %edx
-
-	jae	L(shl_0_gobble_mem_loop)
-	cmp	$-0x40, %ecx
-	lea	0x80(%ecx), %ecx
-	jl	L(shl_0_mem_less_64bytes)
-
-	movdqa	(%eax), %xmm0
-	sub	$0x40, %ecx
-	movdqa	0x10(%eax), %xmm1
-
-	movdqa	%xmm0, (%edx)
-	movdqa	%xmm1, 0x10(%edx)
-
-	movdqa	0x20(%eax), %xmm0
-	movdqa	0x30(%eax), %xmm1
-	add	$0x40, %eax
-
-	movdqa	%xmm0, 0x20(%edx)
-	movdqa	%xmm1, 0x30(%edx)
-	add	$0x40, %edx
-
-L(shl_0_mem_less_64bytes):
-	cmp	$0x20, %ecx
-	jb	L(shl_0_mem_less_32bytes)
-	movdqa	(%eax), %xmm0
-	sub	$0x20, %ecx
-	movdqa	0x10(%eax), %xmm1
-	add	$0x20, %eax
-	movdqa	%xmm0, (%edx)
-	movdqa	%xmm1, 0x10(%edx)
-	add	$0x20, %edx
-
-L(shl_0_mem_less_32bytes):
-	cmp	$0x10, %ecx
-	jb	L(shl_0_mem_less_16bytes)
-	sub	$0x10, %ecx
-	movdqa	(%eax), %xmm0
-	add	$0x10, %eax
-	movdqa	%xmm0, (%edx)
-	add	$0x10, %edx
-
-L(shl_0_mem_less_16bytes):
-	add	%ecx, %edx
-	add	%ecx, %eax
-	BRANCH_TO_JMPTBL_ENTRY (L(table_48bytes_fwd_align), %ecx, 4)
-
-	.p2align 4
-L(shl_1):
-#ifndef USE_AS_MEMMOVE
-	movaps	-1(%eax), %xmm1
-#else
-	movl	DEST+4(%esp), %edi
-	movaps	-1(%eax), %xmm1
-	movdqu	%xmm0, (%edi)
-#endif
-#ifdef DATA_CACHE_SIZE_HALF
-	cmp	$DATA_CACHE_SIZE_HALF, %ecx
-#else
-# if (defined SHARED || defined __PIC__)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
-# else
-	cmp	__x86_data_cache_size_half, %ecx
-# endif
-#endif
-	jb L(sh_1_no_prefetch)
-
-	lea	-64(%ecx), %ecx
-
-	.p2align 4
-L(Shl1LoopStart):
-	prefetcht0 0x1c0(%eax)
-	prefetcht0 0x1c0(%edx)
-	movaps	15(%eax), %xmm2
-	movaps	31(%eax), %xmm3
-	movaps	47(%eax), %xmm4
-	movaps	63(%eax), %xmm5
-	movaps	%xmm5, %xmm7
-	palignr	$1, %xmm4, %xmm5
-	palignr	$1, %xmm3, %xmm4
-	movaps	%xmm5, 48(%edx)
-	palignr	$1, %xmm2, %xmm3
-	lea	64(%eax), %eax
-	palignr	$1, %xmm1, %xmm2
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm7, %xmm1
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	sub	$64, %ecx
-	ja	L(Shl1LoopStart)
-
-L(Shl1LoopLeave):
-	add	$32, %ecx
-	jle	L(shl_end_0)
-
-	movaps	15(%eax), %xmm2
-	movaps	31(%eax), %xmm3
-	palignr	$1, %xmm2, %xmm3
-	palignr	$1, %xmm1, %xmm2
-	movaps	%xmm2, (%edx)
-	movaps	%xmm3, 16(%edx)
-	lea	32(%edx, %ecx), %edx
-	lea	32(%eax, %ecx), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(sh_1_no_prefetch):
-	lea	-32(%ecx), %ecx
-	lea	-1(%eax), %eax
-	xor	%edi, %edi
-
-	.p2align 4
-L(sh_1_no_prefetch_loop):
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm4
-	palignr	$1, %xmm2, %xmm3
-	palignr	$1, %xmm1, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jb	L(sh_1_end_no_prefetch_loop)
-
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm1
-	palignr	$1, %xmm2, %xmm3
-	palignr	$1, %xmm4, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jae	L(sh_1_no_prefetch_loop)
-
-L(sh_1_end_no_prefetch_loop):
-	lea	32(%ecx), %ecx
-	add	%ecx, %edi
-	add	%edi, %edx
-	lea	1(%edi, %eax), %eax
-	POP	(%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(shl_2):
-#ifndef USE_AS_MEMMOVE
-	movaps	-2(%eax), %xmm1
-#else
-	movl	DEST+4(%esp), %edi
-	movaps	-2(%eax), %xmm1
-	movdqu	%xmm0, (%edi)
-#endif
-#ifdef DATA_CACHE_SIZE_HALF
-	cmp	$DATA_CACHE_SIZE_HALF, %ecx
-#else
-# if (defined SHARED || defined __PIC__)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
-# else
-	cmp	__x86_data_cache_size_half, %ecx
-# endif
-#endif
-	jb L(sh_2_no_prefetch)
-
-	lea	-64(%ecx), %ecx
-
-	.p2align 4
-L(Shl2LoopStart):
-	prefetcht0 0x1c0(%eax)
-	prefetcht0 0x1c0(%edx)
-	movaps	14(%eax), %xmm2
-	movaps	30(%eax), %xmm3
-	movaps	46(%eax), %xmm4
-	movaps	62(%eax), %xmm5
-	movaps	%xmm5, %xmm7
-	palignr	$2, %xmm4, %xmm5
-	palignr	$2, %xmm3, %xmm4
-	movaps	%xmm5, 48(%edx)
-	palignr	$2, %xmm2, %xmm3
-	lea	64(%eax), %eax
-	palignr	$2, %xmm1, %xmm2
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm7, %xmm1
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	sub	$64, %ecx
-	ja	L(Shl2LoopStart)
-
-L(Shl2LoopLeave):
-	add	$32, %ecx
-	jle	L(shl_end_0)
-
-	movaps	14(%eax), %xmm2
-	movaps	30(%eax), %xmm3
-	palignr	$2, %xmm2, %xmm3
-	palignr	$2, %xmm1, %xmm2
-	movaps	%xmm2, (%edx)
-	movaps	%xmm3, 16(%edx)
-	lea	32(%edx, %ecx), %edx
-	lea	32(%eax, %ecx), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(sh_2_no_prefetch):
-	lea	-32(%ecx), %ecx
-	lea	-2(%eax), %eax
-	xor	%edi, %edi
-
-	.p2align 4
-L(sh_2_no_prefetch_loop):
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm4
-	palignr	$2, %xmm2, %xmm3
-	palignr	$2, %xmm1, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jb	L(sh_2_end_no_prefetch_loop)
-
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm1
-	palignr	$2, %xmm2, %xmm3
-	palignr	$2, %xmm4, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jae	L(sh_2_no_prefetch_loop)
-
-L(sh_2_end_no_prefetch_loop):
-	lea	32(%ecx), %ecx
-	add	%ecx, %edi
-	add	%edi, %edx
-	lea	2(%edi, %eax), %eax
-	POP	(%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(shl_3):
-#ifndef USE_AS_MEMMOVE
-	movaps	-3(%eax), %xmm1
-#else
-	movl	DEST+4(%esp), %edi
-	movaps	-3(%eax), %xmm1
-	movdqu	%xmm0, (%edi)
-#endif
-#ifdef DATA_CACHE_SIZE_HALF
-	cmp	$DATA_CACHE_SIZE_HALF, %ecx
-#else
-# if (defined SHARED || defined __PIC__)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
-# else
-	cmp	__x86_data_cache_size_half, %ecx
-# endif
-#endif
-	jb L(sh_3_no_prefetch)
-
-	lea	-64(%ecx), %ecx
-
-	.p2align 4
-L(Shl3LoopStart):
-	prefetcht0 0x1c0(%eax)
-	prefetcht0 0x1c0(%edx)
-	movaps	13(%eax), %xmm2
-	movaps	29(%eax), %xmm3
-	movaps	45(%eax), %xmm4
-	movaps	61(%eax), %xmm5
-	movaps	%xmm5, %xmm7
-	palignr	$3, %xmm4, %xmm5
-	palignr	$3, %xmm3, %xmm4
-	movaps	%xmm5, 48(%edx)
-	palignr	$3, %xmm2, %xmm3
-	lea	64(%eax), %eax
-	palignr	$3, %xmm1, %xmm2
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm7, %xmm1
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	sub	$64, %ecx
-	ja	L(Shl3LoopStart)
-
-L(Shl3LoopLeave):
-	add	$32, %ecx
-	jle	L(shl_end_0)
-
-	movaps	13(%eax), %xmm2
-	movaps	29(%eax), %xmm3
-	palignr	$3, %xmm2, %xmm3
-	palignr	$3, %xmm1, %xmm2
-	movaps	%xmm2, (%edx)
-	movaps	%xmm3, 16(%edx)
-	lea	32(%edx, %ecx), %edx
-	lea	32(%eax, %ecx), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(sh_3_no_prefetch):
-	lea	-32(%ecx), %ecx
-	lea	-3(%eax), %eax
-	xor	%edi, %edi
-
-	.p2align 4
-L(sh_3_no_prefetch_loop):
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm4
-	palignr	$3, %xmm2, %xmm3
-	palignr	$3, %xmm1, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-
-	jb	L(sh_3_end_no_prefetch_loop)
-
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm1
-	palignr	$3, %xmm2, %xmm3
-	palignr	$3, %xmm4, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-
-	jae	L(sh_3_no_prefetch_loop)
-
-L(sh_3_end_no_prefetch_loop):
-	lea	32(%ecx), %ecx
-	add	%ecx, %edi
-	add	%edi, %edx
-	lea	3(%edi, %eax), %eax
-	POP	(%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(shl_4):
-#ifndef USE_AS_MEMMOVE
-	movaps	-4(%eax), %xmm1
-#else
-	movl	DEST+4(%esp), %edi
-	movaps	-4(%eax), %xmm1
-	movdqu	%xmm0, (%edi)
-#endif
-#ifdef DATA_CACHE_SIZE_HALF
-	cmp	$DATA_CACHE_SIZE_HALF, %ecx
-#else
-# if (defined SHARED || defined __PIC__)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
-# else
-	cmp	__x86_data_cache_size_half, %ecx
-# endif
-#endif
-	jb L(sh_4_no_prefetch)
-
-	lea	-64(%ecx), %ecx
-
-	.p2align 4
-L(Shl4LoopStart):
-	prefetcht0 0x1c0(%eax)
-	prefetcht0 0x1c0(%edx)
-	movaps	12(%eax), %xmm2
-	movaps	28(%eax), %xmm3
-	movaps	44(%eax), %xmm4
-	movaps	60(%eax), %xmm5
-	movaps	%xmm5, %xmm7
-	palignr	$4, %xmm4, %xmm5
-	palignr	$4, %xmm3, %xmm4
-	movaps	%xmm5, 48(%edx)
-	palignr	$4, %xmm2, %xmm3
-	lea	64(%eax), %eax
-	palignr	$4, %xmm1, %xmm2
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm7, %xmm1
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	sub	$64, %ecx
-	ja	L(Shl4LoopStart)
-
-L(Shl4LoopLeave):
-	add	$32, %ecx
-	jle	L(shl_end_0)
-
-	movaps	12(%eax), %xmm2
-	movaps	28(%eax), %xmm3
-	palignr	$4, %xmm2, %xmm3
-	palignr	$4, %xmm1, %xmm2
-	movaps	%xmm2, (%edx)
-	movaps	%xmm3, 16(%edx)
-	lea	32(%edx, %ecx), %edx
-	lea	32(%eax, %ecx), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(sh_4_no_prefetch):
-	lea	-32(%ecx), %ecx
-	lea	-4(%eax), %eax
-	xor	%edi, %edi
-
-	.p2align 4
-L(sh_4_no_prefetch_loop):
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm4
-	palignr	$4, %xmm2, %xmm3
-	palignr	$4, %xmm1, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-
-	jb	L(sh_4_end_no_prefetch_loop)
-
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm1
-	palignr	$4, %xmm2, %xmm3
-	palignr	$4, %xmm4, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-
-	jae	L(sh_4_no_prefetch_loop)
-
-L(sh_4_end_no_prefetch_loop):
-	lea	32(%ecx), %ecx
-	add	%ecx, %edi
-	add	%edi, %edx
-	lea	4(%edi, %eax), %eax
-	POP	(%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(shl_5):
-#ifndef USE_AS_MEMMOVE
-	movaps	-5(%eax), %xmm1
-#else
-	movl	DEST+4(%esp), %edi
-	movaps	-5(%eax), %xmm1
-	movdqu	%xmm0, (%edi)
-#endif
-#ifdef DATA_CACHE_SIZE_HALF
-	cmp	$DATA_CACHE_SIZE_HALF, %ecx
-#else
-# if (defined SHARED || defined __PIC__)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
-# else
-	cmp	__x86_data_cache_size_half, %ecx
-# endif
-#endif
-	jb L(sh_5_no_prefetch)
-
-	lea	-64(%ecx), %ecx
-
-	.p2align 4
-L(Shl5LoopStart):
-	prefetcht0 0x1c0(%eax)
-	prefetcht0 0x1c0(%edx)
-	movaps	11(%eax), %xmm2
-	movaps	27(%eax), %xmm3
-	movaps	43(%eax), %xmm4
-	movaps	59(%eax), %xmm5
-	movaps	%xmm5, %xmm7
-	palignr	$5, %xmm4, %xmm5
-	palignr	$5, %xmm3, %xmm4
-	movaps	%xmm5, 48(%edx)
-	palignr	$5, %xmm2, %xmm3
-	lea	64(%eax), %eax
-	palignr	$5, %xmm1, %xmm2
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm7, %xmm1
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	sub	$64, %ecx
-	ja	L(Shl5LoopStart)
-
-L(Shl5LoopLeave):
-	add	$32, %ecx
-	jle	L(shl_end_0)
-
-	movaps	11(%eax), %xmm2
-	movaps	27(%eax), %xmm3
-	palignr	$5, %xmm2, %xmm3
-	palignr	$5, %xmm1, %xmm2
-	movaps	%xmm2, (%edx)
-	movaps	%xmm3, 16(%edx)
-	lea	32(%edx, %ecx), %edx
-	lea	32(%eax, %ecx), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(sh_5_no_prefetch):
-	lea	-32(%ecx), %ecx
-	lea	-5(%eax), %eax
-	xor	%edi, %edi
-
-	.p2align 4
-L(sh_5_no_prefetch_loop):
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm4
-	palignr	$5, %xmm2, %xmm3
-	palignr	$5, %xmm1, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-
-	jb	L(sh_5_end_no_prefetch_loop)
-
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm1
-	palignr	$5, %xmm2, %xmm3
-	palignr	$5, %xmm4, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-
-	jae	L(sh_5_no_prefetch_loop)
-
-L(sh_5_end_no_prefetch_loop):
-	lea	32(%ecx), %ecx
-	add	%ecx, %edi
-	add	%edi, %edx
-	lea	5(%edi, %eax), %eax
-	POP	(%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(shl_6):
-#ifndef USE_AS_MEMMOVE
-	movaps	-6(%eax), %xmm1
-#else
-	movl	DEST+4(%esp), %edi
-	movaps	-6(%eax), %xmm1
-	movdqu	%xmm0, (%edi)
-#endif
-#ifdef DATA_CACHE_SIZE_HALF
-	cmp	$DATA_CACHE_SIZE_HALF, %ecx
-#else
-# if (defined SHARED || defined __PIC__)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
-# else
-	cmp	__x86_data_cache_size_half, %ecx
-# endif
-#endif
-	jb L(sh_6_no_prefetch)
-
-	lea	-64(%ecx), %ecx
-
-	.p2align 4
-L(Shl6LoopStart):
-	prefetcht0 0x1c0(%eax)
-	prefetcht0 0x1c0(%edx)
-	movaps	10(%eax), %xmm2
-	movaps	26(%eax), %xmm3
-	movaps	42(%eax), %xmm4
-	movaps	58(%eax), %xmm5
-	movaps	%xmm5, %xmm7
-	palignr	$6, %xmm4, %xmm5
-	palignr	$6, %xmm3, %xmm4
-	movaps	%xmm5, 48(%edx)
-	palignr	$6, %xmm2, %xmm3
-	lea	64(%eax), %eax
-	palignr	$6, %xmm1, %xmm2
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm7, %xmm1
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	sub	$64, %ecx
-	ja	L(Shl6LoopStart)
-
-L(Shl6LoopLeave):
-	add	$32, %ecx
-	jle	L(shl_end_0)
-
-	movaps	10(%eax), %xmm2
-	movaps	26(%eax), %xmm3
-	palignr	$6, %xmm2, %xmm3
-	palignr	$6, %xmm1, %xmm2
-	movaps	%xmm2, (%edx)
-	movaps	%xmm3, 16(%edx)
-	lea	32(%edx, %ecx), %edx
-	lea	32(%eax, %ecx), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(sh_6_no_prefetch):
-	lea	-32(%ecx), %ecx
-	lea	-6(%eax), %eax
-	xor	%edi, %edi
-
-	.p2align 4
-L(sh_6_no_prefetch_loop):
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm4
-	palignr	$6, %xmm2, %xmm3
-	palignr	$6, %xmm1, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-
-	jb	L(sh_6_end_no_prefetch_loop)
-
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm1
-	palignr	$6, %xmm2, %xmm3
-	palignr	$6, %xmm4, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-
-	jae	L(sh_6_no_prefetch_loop)
-
-L(sh_6_end_no_prefetch_loop):
-	lea	32(%ecx), %ecx
-	add	%ecx, %edi
-	add	%edi, %edx
-	lea	6(%edi, %eax), %eax
-	POP	(%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(shl_7):
-#ifndef USE_AS_MEMMOVE
-	movaps	-7(%eax), %xmm1
-#else
-	movl	DEST+4(%esp), %edi
-	movaps	-7(%eax), %xmm1
-	movdqu	%xmm0, (%edi)
-#endif
-#ifdef DATA_CACHE_SIZE_HALF
-	cmp	$DATA_CACHE_SIZE_HALF, %ecx
-#else
-# if (defined SHARED || defined __PIC__)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
-# else
-	cmp	__x86_data_cache_size_half, %ecx
-# endif
-#endif
-	jb L(sh_7_no_prefetch)
-
-	lea	-64(%ecx), %ecx
-
-	.p2align 4
-L(Shl7LoopStart):
-	prefetcht0 0x1c0(%eax)
-	prefetcht0 0x1c0(%edx)
-	movaps	9(%eax), %xmm2
-	movaps	25(%eax), %xmm3
-	movaps	41(%eax), %xmm4
-	movaps	57(%eax), %xmm5
-	movaps	%xmm5, %xmm7
-	palignr	$7, %xmm4, %xmm5
-	palignr	$7, %xmm3, %xmm4
-	movaps	%xmm5, 48(%edx)
-	palignr	$7, %xmm2, %xmm3
-	lea	64(%eax), %eax
-	palignr	$7, %xmm1, %xmm2
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm7, %xmm1
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	sub	$64, %ecx
-	ja	L(Shl7LoopStart)
-
-L(Shl7LoopLeave):
-	add	$32, %ecx
-	jle	L(shl_end_0)
-
-	movaps	9(%eax), %xmm2
-	movaps	25(%eax), %xmm3
-	palignr	$7, %xmm2, %xmm3
-	palignr	$7, %xmm1, %xmm2
-	movaps	%xmm2, (%edx)
-	movaps	%xmm3, 16(%edx)
-	lea	32(%edx, %ecx), %edx
-	lea	32(%eax, %ecx), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(sh_7_no_prefetch):
-	lea	-32(%ecx), %ecx
-	lea	-7(%eax), %eax
-	xor	%edi, %edi
-
-	.p2align 4
-L(sh_7_no_prefetch_loop):
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm4
-	palignr	$7, %xmm2, %xmm3
-	palignr	$7, %xmm1, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jb	L(sh_7_end_no_prefetch_loop)
-
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm1
-	palignr	$7, %xmm2, %xmm3
-	palignr	$7, %xmm4, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jae	L(sh_7_no_prefetch_loop)
-
-L(sh_7_end_no_prefetch_loop):
-	lea	32(%ecx), %ecx
-	add	%ecx, %edi
-	add	%edi, %edx
-	lea	7(%edi, %eax), %eax
-	POP	(%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(shl_8):
-#ifndef USE_AS_MEMMOVE
-	movaps	-8(%eax), %xmm1
-#else
-	movl	DEST+4(%esp), %edi
-	movaps	-8(%eax), %xmm1
-	movdqu	%xmm0, (%edi)
-#endif
-#ifdef DATA_CACHE_SIZE_HALF
-	cmp	$DATA_CACHE_SIZE_HALF, %ecx
-#else
-# if (defined SHARED || defined __PIC__)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
-# else
-	cmp	__x86_data_cache_size_half, %ecx
-# endif
-#endif
-	jb L(sh_8_no_prefetch)
-
-	lea	-64(%ecx), %ecx
-
-	.p2align 4
-L(Shl8LoopStart):
-	prefetcht0 0x1c0(%eax)
-	prefetcht0 0x1c0(%edx)
-	movaps	8(%eax), %xmm2
-	movaps	24(%eax), %xmm3
-	movaps	40(%eax), %xmm4
-	movaps	56(%eax), %xmm5
-	movaps	%xmm5, %xmm7
-	palignr	$8, %xmm4, %xmm5
-	palignr	$8, %xmm3, %xmm4
-	movaps	%xmm5, 48(%edx)
-	palignr	$8, %xmm2, %xmm3
-	lea	64(%eax), %eax
-	palignr	$8, %xmm1, %xmm2
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm7, %xmm1
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	sub	$64, %ecx
-	ja	L(Shl8LoopStart)
-
-L(LoopLeave8):
-	add	$32, %ecx
-	jle	L(shl_end_0)
-
-	movaps	8(%eax), %xmm2
-	movaps	24(%eax), %xmm3
-	palignr	$8, %xmm2, %xmm3
-	palignr	$8, %xmm1, %xmm2
-	movaps	%xmm2, (%edx)
-	movaps	%xmm3, 16(%edx)
-	lea	32(%edx, %ecx), %edx
-	lea	32(%eax, %ecx), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(sh_8_no_prefetch):
-	lea	-32(%ecx), %ecx
-	lea	-8(%eax), %eax
-	xor	%edi, %edi
-
-	.p2align 4
-L(sh_8_no_prefetch_loop):
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm4
-	palignr	$8, %xmm2, %xmm3
-	palignr	$8, %xmm1, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jb	L(sh_8_end_no_prefetch_loop)
-
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm1
-	palignr	$8, %xmm2, %xmm3
-	palignr	$8, %xmm4, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jae	L(sh_8_no_prefetch_loop)
-
-L(sh_8_end_no_prefetch_loop):
-	lea	32(%ecx), %ecx
-	add	%ecx, %edi
-	add	%edi, %edx
-	lea	8(%edi, %eax), %eax
-	POP	(%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(shl_9):
-#ifndef USE_AS_MEMMOVE
-	movaps	-9(%eax), %xmm1
-#else
-	movl	DEST+4(%esp), %edi
-	movaps	-9(%eax), %xmm1
-	movdqu	%xmm0, (%edi)
-#endif
-#ifdef DATA_CACHE_SIZE_HALF
-	cmp	$DATA_CACHE_SIZE_HALF, %ecx
-#else
-# if (defined SHARED || defined __PIC__)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
-# else
-	cmp	__x86_data_cache_size_half, %ecx
-# endif
-#endif
-	jb L(sh_9_no_prefetch)
-
-	lea	-64(%ecx), %ecx
-
-	.p2align 4
-L(Shl9LoopStart):
-	prefetcht0 0x1c0(%eax)
-	prefetcht0 0x1c0(%edx)
-	movaps	7(%eax), %xmm2
-	movaps	23(%eax), %xmm3
-	movaps	39(%eax), %xmm4
-	movaps	55(%eax), %xmm5
-	movaps	%xmm5, %xmm7
-	palignr	$9, %xmm4, %xmm5
-	palignr	$9, %xmm3, %xmm4
-	movaps	%xmm5, 48(%edx)
-	palignr	$9, %xmm2, %xmm3
-	lea	64(%eax), %eax
-	palignr	$9, %xmm1, %xmm2
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm7, %xmm1
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	sub	$64, %ecx
-	ja	L(Shl9LoopStart)
-
-L(Shl9LoopLeave):
-	add	$32, %ecx
-	jle	L(shl_end_0)
-
-	movaps	7(%eax), %xmm2
-	movaps	23(%eax), %xmm3
-	palignr	$9, %xmm2, %xmm3
-	palignr	$9, %xmm1, %xmm2
-
-	movaps	%xmm2, (%edx)
-	movaps	%xmm3, 16(%edx)
-	lea	32(%edx, %ecx), %edx
-	lea	32(%eax, %ecx), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(sh_9_no_prefetch):
-	lea	-32(%ecx), %ecx
-	lea	-9(%eax), %eax
-	xor	%edi, %edi
-
-	.p2align 4
-L(sh_9_no_prefetch_loop):
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm4
-	palignr	$9, %xmm2, %xmm3
-	palignr	$9, %xmm1, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jb	L(sh_9_end_no_prefetch_loop)
-
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm1
-	palignr	$9, %xmm2, %xmm3
-	palignr	$9, %xmm4, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jae	L(sh_9_no_prefetch_loop)
-
-L(sh_9_end_no_prefetch_loop):
-	lea	32(%ecx), %ecx
-	add	%ecx, %edi
-	add	%edi, %edx
-	lea	9(%edi, %eax), %eax
-	POP	(%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(shl_10):
-#ifndef USE_AS_MEMMOVE
-	movaps	-10(%eax), %xmm1
-#else
-	movl	DEST+4(%esp), %edi
-	movaps	-10(%eax), %xmm1
-	movdqu	%xmm0, (%edi)
-#endif
-#ifdef DATA_CACHE_SIZE_HALF
-	cmp	$DATA_CACHE_SIZE_HALF, %ecx
-#else
-# if (defined SHARED || defined __PIC__)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
-# else
-	cmp	__x86_data_cache_size_half, %ecx
-# endif
-#endif
-	jb L(sh_10_no_prefetch)
-
-	lea	-64(%ecx), %ecx
-
-	.p2align 4
-L(Shl10LoopStart):
-	prefetcht0 0x1c0(%eax)
-	prefetcht0 0x1c0(%edx)
-	movaps	6(%eax), %xmm2
-	movaps	22(%eax), %xmm3
-	movaps	38(%eax), %xmm4
-	movaps	54(%eax), %xmm5
-	movaps	%xmm5, %xmm7
-	palignr	$10, %xmm4, %xmm5
-	palignr	$10, %xmm3, %xmm4
-	movaps	%xmm5, 48(%edx)
-	palignr	$10, %xmm2, %xmm3
-	lea	64(%eax), %eax
-	palignr	$10, %xmm1, %xmm2
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm7, %xmm1
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	sub	$64, %ecx
-	ja	L(Shl10LoopStart)
-
-L(Shl10LoopLeave):
-	add	$32, %ecx
-	jle	L(shl_end_0)
-
-	movaps	6(%eax), %xmm2
-	movaps	22(%eax), %xmm3
-	palignr	$10, %xmm2, %xmm3
-	palignr	$10, %xmm1, %xmm2
-
-	movaps	%xmm2, (%edx)
-	movaps	%xmm3, 16(%edx)
-	lea	32(%edx, %ecx), %edx
-	lea	32(%eax, %ecx), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(sh_10_no_prefetch):
-	lea	-32(%ecx), %ecx
-	lea	-10(%eax), %eax
-	xor	%edi, %edi
-
-	.p2align 4
-L(sh_10_no_prefetch_loop):
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm4
-	palignr	$10, %xmm2, %xmm3
-	palignr	$10, %xmm1, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jb	L(sh_10_end_no_prefetch_loop)
-
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm1
-	palignr	$10, %xmm2, %xmm3
-	palignr	$10, %xmm4, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jae	L(sh_10_no_prefetch_loop)
-
-L(sh_10_end_no_prefetch_loop):
-	lea	32(%ecx), %ecx
-	add	%ecx, %edi
-	add	%edi, %edx
-	lea	10(%edi, %eax), %eax
-	POP	(%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(shl_11):
-#ifndef USE_AS_MEMMOVE
-	movaps	-11(%eax), %xmm1
-#else
-	movl	DEST+4(%esp), %edi
-	movaps	-11(%eax), %xmm1
-	movdqu	%xmm0, (%edi)
-#endif
-#ifdef DATA_CACHE_SIZE_HALF
-	cmp	$DATA_CACHE_SIZE_HALF, %ecx
-#else
-# if (defined SHARED || defined __PIC__)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
-# else
-	cmp	__x86_data_cache_size_half, %ecx
-# endif
-#endif
-	jb L(sh_11_no_prefetch)
-
-	lea	-64(%ecx), %ecx
-
-	.p2align 4
-L(Shl11LoopStart):
-	prefetcht0 0x1c0(%eax)
-	prefetcht0 0x1c0(%edx)
-	movaps	5(%eax), %xmm2
-	movaps	21(%eax), %xmm3
-	movaps	37(%eax), %xmm4
-	movaps	53(%eax), %xmm5
-	movaps	%xmm5, %xmm7
-	palignr	$11, %xmm4, %xmm5
-	palignr	$11, %xmm3, %xmm4
-	movaps	%xmm5, 48(%edx)
-	palignr	$11, %xmm2, %xmm3
-	lea	64(%eax), %eax
-	palignr	$11, %xmm1, %xmm2
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm7, %xmm1
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	sub	$64, %ecx
-	ja	L(Shl11LoopStart)
-
-L(Shl11LoopLeave):
-	add	$32, %ecx
-	jle	L(shl_end_0)
-
-	movaps	5(%eax), %xmm2
-	movaps	21(%eax), %xmm3
-	palignr	$11, %xmm2, %xmm3
-	palignr	$11, %xmm1, %xmm2
-
-	movaps	%xmm2, (%edx)
-	movaps	%xmm3, 16(%edx)
-	lea	32(%edx, %ecx), %edx
-	lea	32(%eax, %ecx), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(sh_11_no_prefetch):
-	lea	-32(%ecx), %ecx
-	lea	-11(%eax), %eax
-	xor	%edi, %edi
-
-	.p2align 4
-L(sh_11_no_prefetch_loop):
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm4
-	palignr	$11, %xmm2, %xmm3
-	palignr	$11, %xmm1, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jb	L(sh_11_end_no_prefetch_loop)
-
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm1
-	palignr	$11, %xmm2, %xmm3
-	palignr	$11, %xmm4, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jae	L(sh_11_no_prefetch_loop)
-
-L(sh_11_end_no_prefetch_loop):
-	lea	32(%ecx), %ecx
-	add	%ecx, %edi
-	add	%edi, %edx
-	lea	11(%edi, %eax), %eax
-	POP	(%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(shl_12):
-#ifndef USE_AS_MEMMOVE
-	movaps	-12(%eax), %xmm1
-#else
-	movl	DEST+4(%esp), %edi
-	movaps	-12(%eax), %xmm1
-	movdqu	%xmm0, (%edi)
-#endif
-#ifdef DATA_CACHE_SIZE_HALF
-	cmp	$DATA_CACHE_SIZE_HALF, %ecx
-#else
-# if (defined SHARED || defined __PIC__)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
-# else
-	cmp	__x86_data_cache_size_half, %ecx
-# endif
-#endif
-	jb L(sh_12_no_prefetch)
-
-	lea	-64(%ecx), %ecx
-
-	.p2align 4
-L(Shl12LoopStart):
-	prefetcht0 0x1c0(%eax)
-	prefetcht0 0x1c0(%edx)
-	movaps	4(%eax), %xmm2
-	movaps	20(%eax), %xmm3
-	movaps	36(%eax), %xmm4
-	movaps	52(%eax), %xmm5
-	movaps	%xmm5, %xmm7
-	palignr	$12, %xmm4, %xmm5
-	palignr	$12, %xmm3, %xmm4
-	movaps	%xmm5, 48(%edx)
-	palignr	$12, %xmm2, %xmm3
-	lea	64(%eax), %eax
-	palignr	$12, %xmm1, %xmm2
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm7, %xmm1
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	sub	$64, %ecx
-	ja	L(Shl12LoopStart)
-
-L(Shl12LoopLeave):
-	add	$32, %ecx
-	jle	L(shl_end_0)
-
-	movaps	4(%eax), %xmm2
-	movaps	20(%eax), %xmm3
-	palignr	$12, %xmm2, %xmm3
-	palignr	$12, %xmm1, %xmm2
-
-	movaps	%xmm2, (%edx)
-	movaps	%xmm3, 16(%edx)
-	lea	32(%edx, %ecx), %edx
-	lea	32(%eax, %ecx), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(sh_12_no_prefetch):
-	lea	-32(%ecx), %ecx
-	lea	-12(%eax), %eax
-	xor	%edi, %edi
-
-	.p2align 4
-L(sh_12_no_prefetch_loop):
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm4
-	palignr	$12, %xmm2, %xmm3
-	palignr	$12, %xmm1, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jb	L(sh_12_end_no_prefetch_loop)
-
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm1
-	palignr	$12, %xmm2, %xmm3
-	palignr	$12, %xmm4, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jae	L(sh_12_no_prefetch_loop)
-
-L(sh_12_end_no_prefetch_loop):
-	lea	32(%ecx), %ecx
-	add	%ecx, %edi
-	add	%edi, %edx
-	lea	12(%edi, %eax), %eax
-	POP	(%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(shl_13):
-#ifndef USE_AS_MEMMOVE
-	movaps	-13(%eax), %xmm1
-#else
-	movl	DEST+4(%esp), %edi
-	movaps	-13(%eax), %xmm1
-	movdqu	%xmm0, (%edi)
-#endif
-#ifdef DATA_CACHE_SIZE_HALF
-	cmp	$DATA_CACHE_SIZE_HALF, %ecx
-#else
-# if (defined SHARED || defined __PIC__)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
-# else
-	cmp	__x86_data_cache_size_half, %ecx
-# endif
-#endif
-	jb L(sh_13_no_prefetch)
-
-	lea	-64(%ecx), %ecx
-
-	.p2align 4
-L(Shl13LoopStart):
-	prefetcht0 0x1c0(%eax)
-	prefetcht0 0x1c0(%edx)
-	movaps	3(%eax), %xmm2
-	movaps	19(%eax), %xmm3
-	movaps	35(%eax), %xmm4
-	movaps	51(%eax), %xmm5
-	movaps	%xmm5, %xmm7
-	palignr	$13, %xmm4, %xmm5
-	palignr	$13, %xmm3, %xmm4
-	movaps	%xmm5, 48(%edx)
-	palignr	$13, %xmm2, %xmm3
-	lea	64(%eax), %eax
-	palignr	$13, %xmm1, %xmm2
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm7, %xmm1
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	sub	$64, %ecx
-	ja	L(Shl13LoopStart)
-
-L(Shl13LoopLeave):
-	add	$32, %ecx
-	jle	L(shl_end_0)
-
-	movaps	3(%eax), %xmm2
-	movaps	19(%eax), %xmm3
-	palignr	$13, %xmm2, %xmm3
-	palignr	$13, %xmm1, %xmm2
-
-	movaps	%xmm2, (%edx)
-	movaps	%xmm3, 16(%edx)
-	lea	32(%edx, %ecx), %edx
-	lea	32(%eax, %ecx), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(sh_13_no_prefetch):
-	lea	-32(%ecx), %ecx
-	lea	-13(%eax), %eax
-	xor	%edi, %edi
-
-	.p2align 4
-L(sh_13_no_prefetch_loop):
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm4
-	palignr	$13, %xmm2, %xmm3
-	palignr	$13, %xmm1, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jb	L(sh_13_end_no_prefetch_loop)
-
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm1
-	palignr	$13, %xmm2, %xmm3
-	palignr	$13, %xmm4, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jae	L(sh_13_no_prefetch_loop)
-
-L(sh_13_end_no_prefetch_loop):
-	lea	32(%ecx), %ecx
-	add	%ecx, %edi
-	add	%edi, %edx
-	lea	13(%edi, %eax), %eax
-	POP	(%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(shl_14):
-#ifndef USE_AS_MEMMOVE
-	movaps	-14(%eax), %xmm1
-#else
-	movl	DEST+4(%esp), %edi
-	movaps	-14(%eax), %xmm1
-	movdqu	%xmm0, (%edi)
-#endif
-#ifdef DATA_CACHE_SIZE_HALF
-	cmp	$DATA_CACHE_SIZE_HALF, %ecx
-#else
-# if (defined SHARED || defined __PIC__)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
-# else
-	cmp	__x86_data_cache_size_half, %ecx
-# endif
-#endif
-	jb L(sh_14_no_prefetch)
-
-	lea	-64(%ecx), %ecx
-
-	.p2align 4
-L(Shl14LoopStart):
-	prefetcht0 0x1c0(%eax)
-	prefetcht0 0x1c0(%edx)
-	movaps	2(%eax), %xmm2
-	movaps	18(%eax), %xmm3
-	movaps	34(%eax), %xmm4
-	movaps	50(%eax), %xmm5
-	movaps	%xmm5, %xmm7
-	palignr	$14, %xmm4, %xmm5
-	palignr	$14, %xmm3, %xmm4
-	movaps	%xmm5, 48(%edx)
-	palignr	$14, %xmm2, %xmm3
-	lea	64(%eax), %eax
-	palignr	$14, %xmm1, %xmm2
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm7, %xmm1
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	sub	$64, %ecx
-	ja	L(Shl14LoopStart)
-
-L(Shl14LoopLeave):
-	add	$32, %ecx
-	jle	L(shl_end_0)
-
-	movaps	2(%eax), %xmm2
-	movaps	18(%eax), %xmm3
-	palignr	$14, %xmm2, %xmm3
-	palignr	$14, %xmm1, %xmm2
-
-	movaps	%xmm2, (%edx)
-	movaps	%xmm3, 16(%edx)
-	lea	32(%edx, %ecx), %edx
-	lea	32(%eax, %ecx), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(sh_14_no_prefetch):
-	lea	-32(%ecx), %ecx
-	lea	-14(%eax), %eax
-	xor	%edi, %edi
-
-	.p2align 4
-L(sh_14_no_prefetch_loop):
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm4
-	palignr	$14, %xmm2, %xmm3
-	palignr	$14, %xmm1, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jb	L(sh_14_end_no_prefetch_loop)
-
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm1
-	palignr	$14, %xmm2, %xmm3
-	palignr	$14, %xmm4, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jae	L(sh_14_no_prefetch_loop)
-
-L(sh_14_end_no_prefetch_loop):
-	lea	32(%ecx), %ecx
-	add	%ecx, %edi
-	add	%edi, %edx
-	lea	14(%edi, %eax), %eax
-	POP	(%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(shl_15):
-#ifndef USE_AS_MEMMOVE
-	movaps	-15(%eax), %xmm1
-#else
-	movl	DEST+4(%esp), %edi
-	movaps	-15(%eax), %xmm1
-	movdqu	%xmm0, (%edi)
-#endif
-#ifdef DATA_CACHE_SIZE_HALF
-	cmp	$DATA_CACHE_SIZE_HALF, %ecx
-#else
-# if (defined SHARED || defined __PIC__)
-	SETUP_PIC_REG(bx)
-	add	$_GLOBAL_OFFSET_TABLE_, %ebx
-	cmp	__x86_data_cache_size_half@GOTOFF(%ebx), %ecx
-# else
-	cmp	__x86_data_cache_size_half, %ecx
-# endif
-#endif
-	jb L(sh_15_no_prefetch)
-
-	lea	-64(%ecx), %ecx
-
-	.p2align 4
-L(Shl15LoopStart):
-	prefetcht0 0x1c0(%eax)
-	prefetcht0 0x1c0(%edx)
-	movaps	1(%eax), %xmm2
-	movaps	17(%eax), %xmm3
-	movaps	33(%eax), %xmm4
-	movaps	49(%eax), %xmm5
-	movaps	%xmm5, %xmm7
-	palignr	$15, %xmm4, %xmm5
-	palignr	$15, %xmm3, %xmm4
-	movaps	%xmm5, 48(%edx)
-	palignr	$15, %xmm2, %xmm3
-	lea	64(%eax), %eax
-	palignr	$15, %xmm1, %xmm2
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm7, %xmm1
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	sub	$64, %ecx
-	ja	L(Shl15LoopStart)
-
-L(Shl15LoopLeave):
-	add	$32, %ecx
-	jle	L(shl_end_0)
-
-	movaps	1(%eax), %xmm2
-	movaps	17(%eax), %xmm3
-	palignr	$15, %xmm2, %xmm3
-	palignr	$15, %xmm1, %xmm2
-
-	movaps	%xmm2, (%edx)
-	movaps	%xmm3, 16(%edx)
-	lea	32(%edx, %ecx), %edx
-	lea	32(%eax, %ecx), %eax
-	POP (%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(sh_15_no_prefetch):
-	lea	-32(%ecx), %ecx
-	lea	-15(%eax), %eax
-	xor	%edi, %edi
-
-	.p2align 4
-L(sh_15_no_prefetch_loop):
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm4
-	palignr	$15, %xmm2, %xmm3
-	palignr	$15, %xmm1, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jb	L(sh_15_end_no_prefetch_loop)
-
-	movdqa	16(%eax, %edi), %xmm2
-	sub	$32, %ecx
-	movdqa	32(%eax, %edi), %xmm3
-	movdqa	%xmm3, %xmm1
-	palignr	$15, %xmm2, %xmm3
-	palignr	$15, %xmm4, %xmm2
-	lea	32(%edi), %edi
-	movdqa	%xmm2, -32(%edx, %edi)
-	movdqa	%xmm3, -16(%edx, %edi)
-	jae	L(sh_15_no_prefetch_loop)
-
-L(sh_15_end_no_prefetch_loop):
-	lea	32(%ecx), %ecx
-	add	%ecx, %edi
-	add	%edi, %edx
-	lea	15(%edi, %eax), %eax
-	POP	(%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(shl_end_0):
-	lea	32(%ecx), %ecx
-	lea	(%edx, %ecx), %edx
-	lea	(%eax, %ecx), %eax
-	POP	(%edi)
-	BRANCH_TO_JMPTBL_ENTRY(L(table_48bytes_fwd), %ecx, 4)
-
-	.p2align 4
-L(fwd_write_44bytes):
-	movq	-44(%eax), %xmm0
-	movq	%xmm0, -44(%edx)
-L(fwd_write_36bytes):
-	movq	-36(%eax), %xmm0
-	movq	%xmm0, -36(%edx)
-L(fwd_write_28bytes):
-	movq	-28(%eax), %xmm0
-	movq	%xmm0, -28(%edx)
-L(fwd_write_20bytes):
-	movq	-20(%eax), %xmm0
-	movq	%xmm0, -20(%edx)
-L(fwd_write_12bytes):
-	movq	-12(%eax), %xmm0
-	movq	%xmm0, -12(%edx)
-L(fwd_write_4bytes):
-	movl	-4(%eax), %ecx
-	movl	%ecx, -4(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_40bytes):
-	movq	-40(%eax), %xmm0
-	movq	%xmm0, -40(%edx)
-L(fwd_write_32bytes):
-	movq	-32(%eax), %xmm0
-	movq	%xmm0, -32(%edx)
-L(fwd_write_24bytes):
-	movq	-24(%eax), %xmm0
-	movq	%xmm0, -24(%edx)
-L(fwd_write_16bytes):
-	movq	-16(%eax), %xmm0
-	movq	%xmm0, -16(%edx)
-L(fwd_write_8bytes):
-	movq	-8(%eax), %xmm0
-	movq	%xmm0, -8(%edx)
-L(fwd_write_0bytes):
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_5bytes):
-	movl	-5(%eax), %ecx
-	movl	-4(%eax), %eax
-	movl	%ecx, -5(%edx)
-	movl	%eax, -4(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_45bytes):
-	movq	-45(%eax), %xmm0
-	movq	%xmm0, -45(%edx)
-L(fwd_write_37bytes):
-	movq	-37(%eax), %xmm0
-	movq	%xmm0, -37(%edx)
-L(fwd_write_29bytes):
-	movq	-29(%eax), %xmm0
-	movq	%xmm0, -29(%edx)
-L(fwd_write_21bytes):
-	movq	-21(%eax), %xmm0
-	movq	%xmm0, -21(%edx)
-L(fwd_write_13bytes):
-	movq	-13(%eax), %xmm0
-	movq	%xmm0, -13(%edx)
-	movl	-5(%eax), %ecx
-	movl	%ecx, -5(%edx)
-	movzbl	-1(%eax), %ecx
-	movb	%cl, -1(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_41bytes):
-	movq	-41(%eax), %xmm0
-	movq	%xmm0, -41(%edx)
-L(fwd_write_33bytes):
-	movq	-33(%eax), %xmm0
-	movq	%xmm0, -33(%edx)
-L(fwd_write_25bytes):
-	movq	-25(%eax), %xmm0
-	movq	%xmm0, -25(%edx)
-L(fwd_write_17bytes):
-	movq	-17(%eax), %xmm0
-	movq	%xmm0, -17(%edx)
-L(fwd_write_9bytes):
-	movq	-9(%eax), %xmm0
-	movq	%xmm0, -9(%edx)
-L(fwd_write_1bytes):
-	movzbl	-1(%eax), %ecx
-	movb	%cl, -1(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_46bytes):
-	movq	-46(%eax), %xmm0
-	movq	%xmm0, -46(%edx)
-L(fwd_write_38bytes):
-	movq	-38(%eax), %xmm0
-	movq	%xmm0, -38(%edx)
-L(fwd_write_30bytes):
-	movq	-30(%eax), %xmm0
-	movq	%xmm0, -30(%edx)
-L(fwd_write_22bytes):
-	movq	-22(%eax), %xmm0
-	movq	%xmm0, -22(%edx)
-L(fwd_write_14bytes):
-	movq	-14(%eax), %xmm0
-	movq	%xmm0, -14(%edx)
-L(fwd_write_6bytes):
-	movl	-6(%eax), %ecx
-	movl	%ecx, -6(%edx)
-	movzwl	-2(%eax), %ecx
-	movw	%cx, -2(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_42bytes):
-	movq	-42(%eax), %xmm0
-	movq	%xmm0, -42(%edx)
-L(fwd_write_34bytes):
-	movq	-34(%eax), %xmm0
-	movq	%xmm0, -34(%edx)
-L(fwd_write_26bytes):
-	movq	-26(%eax), %xmm0
-	movq	%xmm0, -26(%edx)
-L(fwd_write_18bytes):
-	movq	-18(%eax), %xmm0
-	movq	%xmm0, -18(%edx)
-L(fwd_write_10bytes):
-	movq	-10(%eax), %xmm0
-	movq	%xmm0, -10(%edx)
-L(fwd_write_2bytes):
-	movzwl	-2(%eax), %ecx
-	movw	%cx, -2(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_47bytes):
-	movq	-47(%eax), %xmm0
-	movq	%xmm0, -47(%edx)
-L(fwd_write_39bytes):
-	movq	-39(%eax), %xmm0
-	movq	%xmm0, -39(%edx)
-L(fwd_write_31bytes):
-	movq	-31(%eax), %xmm0
-	movq	%xmm0, -31(%edx)
-L(fwd_write_23bytes):
-	movq	-23(%eax), %xmm0
-	movq	%xmm0, -23(%edx)
-L(fwd_write_15bytes):
-	movq	-15(%eax), %xmm0
-	movq	%xmm0, -15(%edx)
-L(fwd_write_7bytes):
-	movl	-7(%eax), %ecx
-	movl	%ecx, -7(%edx)
-	movzwl	-3(%eax), %ecx
-	movzbl	-1(%eax), %eax
-	movw	%cx, -3(%edx)
-	movb	%al, -1(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_43bytes):
-	movq	-43(%eax), %xmm0
-	movq	%xmm0, -43(%edx)
-L(fwd_write_35bytes):
-	movq	-35(%eax), %xmm0
-	movq	%xmm0, -35(%edx)
-L(fwd_write_27bytes):
-	movq	-27(%eax), %xmm0
-	movq	%xmm0, -27(%edx)
-L(fwd_write_19bytes):
-	movq	-19(%eax), %xmm0
-	movq	%xmm0, -19(%edx)
-L(fwd_write_11bytes):
-	movq	-11(%eax), %xmm0
-	movq	%xmm0, -11(%edx)
-L(fwd_write_3bytes):
-	movzwl	-3(%eax), %ecx
-	movzbl	-1(%eax), %eax
-	movw	%cx, -3(%edx)
-	movb	%al, -1(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_40bytes_align):
-	movdqa	-40(%eax), %xmm0
-	movdqa	%xmm0, -40(%edx)
-L(fwd_write_24bytes_align):
-	movdqa	-24(%eax), %xmm0
-	movdqa	%xmm0, -24(%edx)
-L(fwd_write_8bytes_align):
-	movq	-8(%eax), %xmm0
-	movq	%xmm0, -8(%edx)
-L(fwd_write_0bytes_align):
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_32bytes_align):
-	movdqa	-32(%eax), %xmm0
-	movdqa	%xmm0, -32(%edx)
-L(fwd_write_16bytes_align):
-	movdqa	-16(%eax), %xmm0
-	movdqa	%xmm0, -16(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_5bytes_align):
-	movl	-5(%eax), %ecx
-	movl	-4(%eax), %eax
-	movl	%ecx, -5(%edx)
-	movl	%eax, -4(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_45bytes_align):
-	movdqa	-45(%eax), %xmm0
-	movdqa	%xmm0, -45(%edx)
-L(fwd_write_29bytes_align):
-	movdqa	-29(%eax), %xmm0
-	movdqa	%xmm0, -29(%edx)
-L(fwd_write_13bytes_align):
-	movq	-13(%eax), %xmm0
-	movq	%xmm0, -13(%edx)
-	movl	-5(%eax), %ecx
-	movl	%ecx, -5(%edx)
-	movzbl	-1(%eax), %ecx
-	movb	%cl, -1(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_37bytes_align):
-	movdqa	-37(%eax), %xmm0
-	movdqa	%xmm0, -37(%edx)
-L(fwd_write_21bytes_align):
-	movdqa	-21(%eax), %xmm0
-	movdqa	%xmm0, -21(%edx)
-	movl	-5(%eax), %ecx
-	movl	%ecx, -5(%edx)
-	movzbl	-1(%eax), %ecx
-	movb	%cl, -1(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_41bytes_align):
-	movdqa	-41(%eax), %xmm0
-	movdqa	%xmm0, -41(%edx)
-L(fwd_write_25bytes_align):
-	movdqa	-25(%eax), %xmm0
-	movdqa	%xmm0, -25(%edx)
-L(fwd_write_9bytes_align):
-	movq	-9(%eax), %xmm0
-	movq	%xmm0, -9(%edx)
-L(fwd_write_1bytes_align):
-	movzbl	-1(%eax), %ecx
-	movb	%cl, -1(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_33bytes_align):
-	movdqa	-33(%eax), %xmm0
-	movdqa	%xmm0, -33(%edx)
-L(fwd_write_17bytes_align):
-	movdqa	-17(%eax), %xmm0
-	movdqa	%xmm0, -17(%edx)
-	movzbl	-1(%eax), %ecx
-	movb	%cl, -1(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_46bytes_align):
-	movdqa	-46(%eax), %xmm0
-	movdqa	%xmm0, -46(%edx)
-L(fwd_write_30bytes_align):
-	movdqa	-30(%eax), %xmm0
-	movdqa	%xmm0, -30(%edx)
-L(fwd_write_14bytes_align):
-	movq	-14(%eax), %xmm0
-	movq	%xmm0, -14(%edx)
-L(fwd_write_6bytes_align):
-	movl	-6(%eax), %ecx
-	movl	%ecx, -6(%edx)
-	movzwl	-2(%eax), %ecx
-	movw	%cx, -2(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_38bytes_align):
-	movdqa	-38(%eax), %xmm0
-	movdqa	%xmm0, -38(%edx)
-L(fwd_write_22bytes_align):
-	movdqa	-22(%eax), %xmm0
-	movdqa	%xmm0, -22(%edx)
-	movl	-6(%eax), %ecx
-	movl	%ecx, -6(%edx)
-	movzwl	-2(%eax), %ecx
-	movw	%cx, -2(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_42bytes_align):
-	movdqa	-42(%eax), %xmm0
-	movdqa	%xmm0, -42(%edx)
-L(fwd_write_26bytes_align):
-	movdqa	-26(%eax), %xmm0
-	movdqa	%xmm0, -26(%edx)
-L(fwd_write_10bytes_align):
-	movq	-10(%eax), %xmm0
-	movq	%xmm0, -10(%edx)
-L(fwd_write_2bytes_align):
-	movzwl	-2(%eax), %ecx
-	movw	%cx, -2(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_34bytes_align):
-	movdqa	-34(%eax), %xmm0
-	movdqa	%xmm0, -34(%edx)
-L(fwd_write_18bytes_align):
-	movdqa	-18(%eax), %xmm0
-	movdqa	%xmm0, -18(%edx)
-	movzwl	-2(%eax), %ecx
-	movw	%cx, -2(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_47bytes_align):
-	movdqa	-47(%eax), %xmm0
-	movdqa	%xmm0, -47(%edx)
-L(fwd_write_31bytes_align):
-	movdqa	-31(%eax), %xmm0
-	movdqa	%xmm0, -31(%edx)
-L(fwd_write_15bytes_align):
-	movq	-15(%eax), %xmm0
-	movq	%xmm0, -15(%edx)
-L(fwd_write_7bytes_align):
-	movl	-7(%eax), %ecx
-	movl	%ecx, -7(%edx)
-	movzwl	-3(%eax), %ecx
-	movzbl	-1(%eax), %eax
-	movw	%cx, -3(%edx)
-	movb	%al, -1(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_39bytes_align):
-	movdqa	-39(%eax), %xmm0
-	movdqa	%xmm0, -39(%edx)
-L(fwd_write_23bytes_align):
-	movdqa	-23(%eax), %xmm0
-	movdqa	%xmm0, -23(%edx)
-	movl	-7(%eax), %ecx
-	movl	%ecx, -7(%edx)
-	movzwl	-3(%eax), %ecx
-	movzbl	-1(%eax), %eax
-	movw	%cx, -3(%edx)
-	movb	%al, -1(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_43bytes_align):
-	movdqa	-43(%eax), %xmm0
-	movdqa	%xmm0, -43(%edx)
-L(fwd_write_27bytes_align):
-	movdqa	-27(%eax), %xmm0
-	movdqa	%xmm0, -27(%edx)
-L(fwd_write_11bytes_align):
-	movq	-11(%eax), %xmm0
-	movq	%xmm0, -11(%edx)
-L(fwd_write_3bytes_align):
-	movzwl	-3(%eax), %ecx
-	movzbl	-1(%eax), %eax
-	movw	%cx, -3(%edx)
-	movb	%al, -1(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_35bytes_align):
-	movdqa	-35(%eax), %xmm0
-	movdqa	%xmm0, -35(%edx)
-L(fwd_write_19bytes_align):
-	movdqa	-19(%eax), %xmm0
-	movdqa	%xmm0, -19(%edx)
-	movzwl	-3(%eax), %ecx
-	movzbl	-1(%eax), %eax
-	movw	%cx, -3(%edx)
-	movb	%al, -1(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_44bytes_align):
-	movdqa	-44(%eax), %xmm0
-	movdqa	%xmm0, -44(%edx)
-L(fwd_write_28bytes_align):
-	movdqa	-28(%eax), %xmm0
-	movdqa	%xmm0, -28(%edx)
-L(fwd_write_12bytes_align):
-	movq	-12(%eax), %xmm0
-	movq	%xmm0, -12(%edx)
-L(fwd_write_4bytes_align):
-	movl	-4(%eax), %ecx
-	movl	%ecx, -4(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(fwd_write_36bytes_align):
-	movdqa	-36(%eax), %xmm0
-	movdqa	%xmm0, -36(%edx)
-L(fwd_write_20bytes_align):
-	movdqa	-20(%eax), %xmm0
-	movdqa	%xmm0, -20(%edx)
-	movl	-4(%eax), %ecx
-	movl	%ecx, -4(%edx)
-#ifdef USE_AS_MEMPCPY
-	movl	%edx, %eax
-#else
-	movl	DEST(%esp), %eax
-#endif
-	RETURN_END
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(large_page):
-	movdqu	(%eax), %xmm1
-#ifdef USE_AS_MEMMOVE
-	movl	DEST+4(%esp), %edi
-	movdqu	%xmm0, (%edi)
-#endif
-	lea	16(%eax), %eax
-	movntdq	%xmm1, (%edx)
-	lea	16(%edx), %edx
-	lea	-0x90(%ecx), %ecx
-	POP (%edi)
-
-	.p2align 4
-L(large_page_loop):
-	movdqu	(%eax), %xmm0
-	movdqu	0x10(%eax), %xmm1
-	movdqu	0x20(%eax), %xmm2
-	movdqu	0x30(%eax), %xmm3
-	movdqu	0x40(%eax), %xmm4
-	movdqu	0x50(%eax), %xmm5
-	movdqu	0x60(%eax), %xmm6
-	movdqu	0x70(%eax), %xmm7
-	lea	0x80(%eax), %eax
-
-	sub	$0x80, %ecx
-	movntdq	%xmm0, (%edx)
-	movntdq	%xmm1, 0x10(%edx)
-	movntdq	%xmm2, 0x20(%edx)
-	movntdq	%xmm3, 0x30(%edx)
-	movntdq	%xmm4, 0x40(%edx)
-	movntdq	%xmm5, 0x50(%edx)
-	movntdq	%xmm6, 0x60(%edx)
-	movntdq	%xmm7, 0x70(%edx)
-	lea	0x80(%edx), %edx
-	jae	L(large_page_loop)
-	cmp	$-0x40, %ecx
-	lea	0x80(%ecx), %ecx
-	jl	L(large_page_less_64bytes)
-
-	movdqu	(%eax), %xmm0
-	movdqu	0x10(%eax), %xmm1
-	movdqu	0x20(%eax), %xmm2
-	movdqu	0x30(%eax), %xmm3
-	lea	0x40(%eax), %eax
-
-	movntdq	%xmm0, (%edx)
-	movntdq	%xmm1, 0x10(%edx)
-	movntdq	%xmm2, 0x20(%edx)
-	movntdq	%xmm3, 0x30(%edx)
-	lea	0x40(%edx), %edx
-	sub	$0x40, %ecx
-L(large_page_less_64bytes):
-	cmp	$32, %ecx
-	jb	L(large_page_less_32bytes)
-	movdqu	(%eax), %xmm0
-	movdqu	0x10(%eax), %xmm1
-	lea	0x20(%eax), %eax
-	movntdq	%xmm0, (%edx)
-	movntdq	%xmm1, 0x10(%edx)
-	lea	0x20(%edx), %edx
-	sub	$0x20, %ecx
-L(large_page_less_32bytes):
-	add	%ecx, %edx
-	add	%ecx, %eax
-	sfence
-	BRANCH_TO_JMPTBL_ENTRY (L(table_48bytes_fwd), %ecx, 4)
-
-	.p2align 4
-L(bk_write_44bytes):
-	movq	36(%eax), %xmm0
-	movq	%xmm0, 36(%edx)
-L(bk_write_36bytes):
-	movq	28(%eax), %xmm0
-	movq	%xmm0, 28(%edx)
-L(bk_write_28bytes):
-	movq	20(%eax), %xmm0
-	movq	%xmm0, 20(%edx)
-L(bk_write_20bytes):
-	movq	12(%eax), %xmm0
-	movq	%xmm0, 12(%edx)
-L(bk_write_12bytes):
-	movq	4(%eax), %xmm0
-	movq	%xmm0, 4(%edx)
-L(bk_write_4bytes):
-	movl	(%eax), %ecx
-	movl	%ecx, (%edx)
-L(bk_write_0bytes):
-	movl	DEST(%esp), %eax
-#ifdef USE_AS_MEMPCPY
-	movl	LEN(%esp), %ecx
-	add	%ecx, %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(bk_write_40bytes):
-	movq	32(%eax), %xmm0
-	movq	%xmm0, 32(%edx)
-L(bk_write_32bytes):
-	movq	24(%eax), %xmm0
-	movq	%xmm0, 24(%edx)
-L(bk_write_24bytes):
-	movq	16(%eax), %xmm0
-	movq	%xmm0, 16(%edx)
-L(bk_write_16bytes):
-	movq	8(%eax), %xmm0
-	movq	%xmm0, 8(%edx)
-L(bk_write_8bytes):
-	movq	(%eax), %xmm0
-	movq	%xmm0, (%edx)
-	movl	DEST(%esp), %eax
-#ifdef USE_AS_MEMPCPY
-	movl	LEN(%esp), %ecx
-	add	%ecx, %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(bk_write_45bytes):
-	movq	37(%eax), %xmm0
-	movq	%xmm0, 37(%edx)
-L(bk_write_37bytes):
-	movq	29(%eax), %xmm0
-	movq	%xmm0, 29(%edx)
-L(bk_write_29bytes):
-	movq	21(%eax), %xmm0
-	movq	%xmm0, 21(%edx)
-L(bk_write_21bytes):
-	movq	13(%eax), %xmm0
-	movq	%xmm0, 13(%edx)
-L(bk_write_13bytes):
-	movq	5(%eax), %xmm0
-	movq	%xmm0, 5(%edx)
-L(bk_write_5bytes):
-	movl	1(%eax), %ecx
-	movl	%ecx, 1(%edx)
-L(bk_write_1bytes):
-	movzbl	(%eax), %ecx
-	movb	%cl, (%edx)
-	movl	DEST(%esp), %eax
-#ifdef USE_AS_MEMPCPY
-	movl	LEN(%esp), %ecx
-	add	%ecx, %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(bk_write_41bytes):
-	movq	33(%eax), %xmm0
-	movq	%xmm0, 33(%edx)
-L(bk_write_33bytes):
-	movq	25(%eax), %xmm0
-	movq	%xmm0, 25(%edx)
-L(bk_write_25bytes):
-	movq	17(%eax), %xmm0
-	movq	%xmm0, 17(%edx)
-L(bk_write_17bytes):
-	movq	9(%eax), %xmm0
-	movq	%xmm0, 9(%edx)
-L(bk_write_9bytes):
-	movq	1(%eax), %xmm0
-	movq	%xmm0, 1(%edx)
-	movzbl	(%eax), %ecx
-	movb	%cl, (%edx)
-	movl	DEST(%esp), %eax
-#ifdef USE_AS_MEMPCPY
-	movl	LEN(%esp), %ecx
-	add	%ecx, %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(bk_write_46bytes):
-	movq	38(%eax), %xmm0
-	movq	%xmm0, 38(%edx)
-L(bk_write_38bytes):
-	movq	30(%eax), %xmm0
-	movq	%xmm0, 30(%edx)
-L(bk_write_30bytes):
-	movq	22(%eax), %xmm0
-	movq	%xmm0, 22(%edx)
-L(bk_write_22bytes):
-	movq	14(%eax), %xmm0
-	movq	%xmm0, 14(%edx)
-L(bk_write_14bytes):
-	movq	6(%eax), %xmm0
-	movq	%xmm0, 6(%edx)
-L(bk_write_6bytes):
-	movl	2(%eax), %ecx
-	movl	%ecx, 2(%edx)
-	movzwl	(%eax), %ecx
-	movw	%cx, (%edx)
-	movl	DEST(%esp), %eax
-#ifdef USE_AS_MEMPCPY
-	movl	LEN(%esp), %ecx
-	add	%ecx, %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(bk_write_42bytes):
-	movq	34(%eax), %xmm0
-	movq	%xmm0, 34(%edx)
-L(bk_write_34bytes):
-	movq	26(%eax), %xmm0
-	movq	%xmm0, 26(%edx)
-L(bk_write_26bytes):
-	movq	18(%eax), %xmm0
-	movq	%xmm0, 18(%edx)
-L(bk_write_18bytes):
-	movq	10(%eax), %xmm0
-	movq	%xmm0, 10(%edx)
-L(bk_write_10bytes):
-	movq	2(%eax), %xmm0
-	movq	%xmm0, 2(%edx)
-L(bk_write_2bytes):
-	movzwl	(%eax), %ecx
-	movw	%cx, (%edx)
-	movl	DEST(%esp), %eax
-#ifdef USE_AS_MEMPCPY
-	movl	LEN(%esp), %ecx
-	add	%ecx, %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(bk_write_47bytes):
-	movq	39(%eax), %xmm0
-	movq	%xmm0, 39(%edx)
-L(bk_write_39bytes):
-	movq	31(%eax), %xmm0
-	movq	%xmm0, 31(%edx)
-L(bk_write_31bytes):
-	movq	23(%eax), %xmm0
-	movq	%xmm0, 23(%edx)
-L(bk_write_23bytes):
-	movq	15(%eax), %xmm0
-	movq	%xmm0, 15(%edx)
-L(bk_write_15bytes):
-	movq	7(%eax), %xmm0
-	movq	%xmm0, 7(%edx)
-L(bk_write_7bytes):
-	movl	3(%eax), %ecx
-	movl	%ecx, 3(%edx)
-	movzwl	1(%eax), %ecx
-	movw	%cx, 1(%edx)
-	movzbl	(%eax), %eax
-	movb	%al, (%edx)
-	movl	DEST(%esp), %eax
-#ifdef USE_AS_MEMPCPY
-	movl	LEN(%esp), %ecx
-	add	%ecx, %eax
-#endif
-	RETURN
-
-	.p2align 4
-L(bk_write_43bytes):
-	movq	35(%eax), %xmm0
-	movq	%xmm0, 35(%edx)
-L(bk_write_35bytes):
-	movq	27(%eax), %xmm0
-	movq	%xmm0, 27(%edx)
-L(bk_write_27bytes):
-	movq	19(%eax), %xmm0
-	movq	%xmm0, 19(%edx)
-L(bk_write_19bytes):
-	movq	11(%eax), %xmm0
-	movq	%xmm0, 11(%edx)
-L(bk_write_11bytes):
-	movq	3(%eax), %xmm0
-	movq	%xmm0, 3(%edx)
-L(bk_write_3bytes):
-	movzwl	1(%eax), %ecx
-	movw	%cx, 1(%edx)
-	movzbl	(%eax), %eax
-	movb	%al, (%edx)
-	movl	DEST(%esp), %eax
-#ifdef USE_AS_MEMPCPY
-	movl	LEN(%esp), %ecx
-	add	%ecx, %eax
-#endif
-	RETURN_END
-
-
-	.pushsection .rodata.ssse3,"a",@progbits
-	.p2align 2
-L(table_48bytes_fwd):
-	.int	JMPTBL (L(fwd_write_0bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_1bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_2bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_3bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_4bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_5bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_6bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_7bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_8bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_9bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_10bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_11bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_12bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_13bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_14bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_15bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_16bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_17bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_18bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_19bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_20bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_21bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_22bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_23bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_24bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_25bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_26bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_27bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_28bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_29bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_30bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_31bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_32bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_33bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_34bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_35bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_36bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_37bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_38bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_39bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_40bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_41bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_42bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_43bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_44bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_45bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_46bytes), L(table_48bytes_fwd))
-	.int	JMPTBL (L(fwd_write_47bytes), L(table_48bytes_fwd))
-
-	.p2align 2
-L(table_48bytes_fwd_align):
-	.int	JMPTBL (L(fwd_write_0bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_1bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_2bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_3bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_4bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_5bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_6bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_7bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_8bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_9bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_10bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_11bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_12bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_13bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_14bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_15bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_16bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_17bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_18bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_19bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_20bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_21bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_22bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_23bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_24bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_25bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_26bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_27bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_28bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_29bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_30bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_31bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_32bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_33bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_34bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_35bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_36bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_37bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_38bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_39bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_40bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_41bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_42bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_43bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_44bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_45bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_46bytes_align), L(table_48bytes_fwd_align))
-	.int	JMPTBL (L(fwd_write_47bytes_align), L(table_48bytes_fwd_align))
-
-	.p2align 2
-L(shl_table):
-	.int	JMPTBL (L(shl_0), L(shl_table))
-	.int	JMPTBL (L(shl_1), L(shl_table))
-	.int	JMPTBL (L(shl_2), L(shl_table))
-	.int	JMPTBL (L(shl_3), L(shl_table))
-	.int	JMPTBL (L(shl_4), L(shl_table))
-	.int	JMPTBL (L(shl_5), L(shl_table))
-	.int	JMPTBL (L(shl_6), L(shl_table))
-	.int	JMPTBL (L(shl_7), L(shl_table))
-	.int	JMPTBL (L(shl_8), L(shl_table))
-	.int	JMPTBL (L(shl_9), L(shl_table))
-	.int	JMPTBL (L(shl_10), L(shl_table))
-	.int	JMPTBL (L(shl_11), L(shl_table))
-	.int	JMPTBL (L(shl_12), L(shl_table))
-	.int	JMPTBL (L(shl_13), L(shl_table))
-	.int	JMPTBL (L(shl_14), L(shl_table))
-	.int	JMPTBL (L(shl_15), L(shl_table))
-
-	.p2align 2
-L(table_48_bytes_bwd):
-	.int	JMPTBL (L(bk_write_0bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_1bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_2bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_3bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_4bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_5bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_6bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_7bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_8bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_9bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_10bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_11bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_12bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_13bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_14bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_15bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_16bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_17bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_18bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_19bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_20bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_21bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_22bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_23bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_24bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_25bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_26bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_27bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_28bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_29bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_30bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_31bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_32bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_33bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_34bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_35bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_36bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_37bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_38bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_39bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_40bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_41bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_42bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_43bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_44bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_45bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_46bytes), L(table_48_bytes_bwd))
-	.int	JMPTBL (L(bk_write_47bytes), L(table_48_bytes_bwd))
-
-	.popsection
-
-#ifdef USE_AS_MEMMOVE
-	.p2align 4
-L(copy_backward):
-	PUSH (%edi)
-	movl	%eax, %edi
-	lea	(%ecx,%edx,1),%edx
-	lea	(%ecx,%edi,1),%edi
-	testl	$0x3, %edx
-	jnz	L(bk_align)
-
-L(bk_aligned_4):
-	cmp	$64, %ecx
-	jae	L(bk_write_more64bytes)
-
-L(bk_write_64bytesless):
-	cmp	$32, %ecx
-	jb	L(bk_write_less32bytes)
-
-L(bk_write_more32bytes):
-	/* Copy 32 bytes at a time.  */
-	sub	$32, %ecx
-	movq	-8(%edi), %xmm0
-	movq	%xmm0, -8(%edx)
-	movq	-16(%edi), %xmm0
-	movq	%xmm0, -16(%edx)
-	movq	-24(%edi), %xmm0
-	movq	%xmm0, -24(%edx)
-	movq	-32(%edi), %xmm0
-	movq	%xmm0, -32(%edx)
-	sub	$32, %edx
-	sub	$32, %edi
-
-L(bk_write_less32bytes):
-	movl	%edi, %eax
-	sub	%ecx, %edx
-	sub	%ecx, %eax
-	POP (%edi)
-L(bk_write_less32bytes_2):
-	BRANCH_TO_JMPTBL_ENTRY (L(table_48_bytes_bwd), %ecx, 4)
-
-	CFI_PUSH (%edi)
-
-	.p2align 4
-L(bk_align):
-	cmp	$8, %ecx
-	jbe	L(bk_write_less32bytes)
-	testl	$1, %edx
-	/* We get here only if (EDX & 3 ) != 0 so if (EDX & 1) ==0,
-	then	(EDX & 2) must be != 0.  */
-	jz	L(bk_got2)
-	sub	$1, %edi
-	sub	$1, %ecx
-	sub	$1, %edx
-	movzbl	(%edi), %eax
-	movb	%al, (%edx)
-
-	testl	$2, %edx
-	jz	L(bk_aligned_4)
-
-L(bk_got2):
-	sub	$2, %edi
-	sub	$2, %ecx
-	sub	$2, %edx
-	movzwl	(%edi), %eax
-	movw	%ax, (%edx)
-	jmp	L(bk_aligned_4)
-
-	.p2align 4
-L(bk_write_more64bytes):
-	/* Check alignment of last byte.  */
-	testl	$15, %edx
-	jz	L(bk_ssse3_cpy_pre)
-
-/* EDX is aligned 4 bytes, but not 16 bytes.  */
-L(bk_ssse3_align):
-	sub	$4, %edi
-	sub	$4, %ecx
-	sub	$4, %edx
-	movl	(%edi), %eax
-	movl	%eax, (%edx)
-
-	testl	$15, %edx
-	jz	L(bk_ssse3_cpy_pre)
-
-	sub	$4, %edi
-	sub	$4, %ecx
-	sub	$4, %edx
-	movl	(%edi), %eax
-	movl	%eax, (%edx)
-
-	testl	$15, %edx
-	jz	L(bk_ssse3_cpy_pre)
-
-	sub	$4, %edi
-	sub	$4, %ecx
-	sub	$4, %edx
-	movl	(%edi), %eax
-	movl	%eax, (%edx)
-
-L(bk_ssse3_cpy_pre):
-	cmp	$64, %ecx
-	jb	L(bk_write_more32bytes)
-
-	.p2align 4
-L(bk_ssse3_cpy):
-	sub	$64, %edi
-	sub	$64, %ecx
-	sub	$64, %edx
-	movdqu	0x30(%edi), %xmm3
-	movdqa	%xmm3, 0x30(%edx)
-	movdqu	0x20(%edi), %xmm2
-	movdqa	%xmm2, 0x20(%edx)
-	movdqu	0x10(%edi), %xmm1
-	movdqa	%xmm1, 0x10(%edx)
-	movdqu	(%edi), %xmm0
-	movdqa	%xmm0, (%edx)
-	cmp	$64, %ecx
-	jae	L(bk_ssse3_cpy)
-	jmp	L(bk_write_64bytesless)
-
-#endif
-
-END (MEMCPY)
diff --git a/libc/arch-x86/string/ssse3-memmove-atom.S b/libc/arch-x86/string/ssse3-memmove-atom.S
deleted file mode 100644
index 3572eac..0000000
--- a/libc/arch-x86/string/ssse3-memmove-atom.S
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-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/string/ssse3-strcat-atom.S b/libc/arch-x86/string/ssse3-strcat-atom.S
index 8d8e89d..b851d9e 100644
--- a/libc/arch-x86/string/ssse3-strcat-atom.S
+++ b/libc/arch-x86/string/ssse3-strcat-atom.S
@@ -87,7 +87,7 @@
 #define POP(REG)	popl REG; CFI_POP (REG)
 
 #ifndef STRCAT
-# define STRCAT	strcat_ssse3
+# define STRCAT	strcat
 #endif
 
 #define PARMS	4
diff --git a/libc/arch-x86/string/ssse3-strcmp-atom.S b/libc/arch-x86/string/ssse3-strcmp-atom.S
index 08f6d4a..ee253b9 100644
--- a/libc/arch-x86/string/ssse3-strcmp-atom.S
+++ b/libc/arch-x86/string/ssse3-strcmp-atom.S
@@ -108,7 +108,7 @@
 #endif
 
 #ifndef STRCMP
-# define STRCMP strcmp_ssse3
+# define STRCMP strcmp
 #endif
 
 	.section .text.ssse3,"ax",@progbits
diff --git a/libc/arch-x86/string/ssse3-strlcat-atom.S b/libc/arch-x86/string/ssse3-strlcat-atom.S
deleted file mode 100644
index 055b489..0000000
--- a/libc/arch-x86/string/ssse3-strlcat-atom.S
+++ /dev/null
@@ -1,1225 +0,0 @@
-/*
-Copyright (c) 2011, 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.
-*/
-
-/* Optimized strlcat with SSSE3 */
-
-#ifndef cfi_startproc
-# define cfi_startproc	.cfi_startproc
-#endif
-
-#ifndef cfi_endproc
-# define cfi_endproc	.cfi_endproc
-#endif
-
-#ifndef cfi_rel_offset
-# define cfi_rel_offset(reg, off)	.cfi_rel_offset reg, off
-#endif
-
-#ifndef cfi_restore
-# define cfi_restore(reg)	.cfi_restore reg
-#endif
-
-#ifndef cfi_adjust_cfa_offset
-# define cfi_adjust_cfa_offset(off)	.cfi_adjust_cfa_offset off
-#endif
-
-#ifndef ENTRY
-# define ENTRY(name)	\
-	.type name,  @function;	\
-	.globl name;	\
-	.p2align 4;	\
-name:	\
-	cfi_startproc
-#endif
-
-#ifndef END
-# define END(name)	\
-	cfi_endproc;	\
-	.size name, .-name
-#endif
-
-#define CFI_PUSH(REG)	\
-	cfi_adjust_cfa_offset (4);	\
-	cfi_rel_offset (REG, 0)
-
-#define CFI_POP(REG)	\
-	cfi_adjust_cfa_offset (-4);	\
-	cfi_restore (REG)
-
-#define PUSH(REG)	pushl	REG;	CFI_PUSH (REG)
-#define POP(REG)	popl	REG;	CFI_POP (REG)
-#define L(label)	.L##Prolog_##label
-
-#define DST	4
-#define SRC	DST+8
-#define LEN	SRC+4
-
-	.text
-ENTRY (strlcat_ssse3)
-	mov	DST(%esp), %edx
-	PUSH	(%ebx)
-	mov	LEN(%esp), %ebx
-	sub	$4, %ebx
-	jbe	L(len_less4_prolog)
-
-#define RETURN	jmp	L(StrcpyStep)
-#define edi	ebx
-
-#define USE_AS_STRNLEN
-#define USE_AS_STRCAT
-#define USE_AS_STRLCAT
-
-#include "sse2-strlen-atom.S"
-
-	.p2align 4
-L(StrcpyStep):
-
-#undef edi
-#undef L
-#define L(label) .L##label
-#undef RETURN
-#define RETURN	POP (%ebx); ret; CFI_PUSH (%ebx);
-#define RETURN1	POP (%edi); POP (%ebx); ret; CFI_PUSH (%ebx); CFI_PUSH (%edi)
-
-        movl	SRC(%esp), %ecx
-	movl	LEN(%esp), %ebx
-
-	cmp	%eax, %ebx
-	je	L(CalculateLengthOfSrcProlog)
-	sub	%eax, %ebx
-
-	test	%ebx, %ebx
-	jz	L(CalculateLengthOfSrcProlog)
-
-	mov	DST + 4(%esp), %edx
-
-	PUSH	(%edi)
-	add	%eax, %edx
-	mov	%ecx, %edi
-	sub	%eax, %edi
-
-	cmp	$8, %ebx
-	jbe	L(StrncpyExit8Bytes)
-
-	cmpb	$0, (%ecx)
-	jz	L(Exit1)
-	cmpb	$0, 1(%ecx)
-	jz	L(Exit2)
-	cmpb	$0, 2(%ecx)
-	jz	L(Exit3)
-	cmpb	$0, 3(%ecx)
-	jz	L(Exit4)
-	cmpb	$0, 4(%ecx)
-	jz	L(Exit5)
-	cmpb	$0, 5(%ecx)
-	jz	L(Exit6)
-	cmpb	$0, 6(%ecx)
-	jz	L(Exit7)
-	cmpb	$0, 7(%ecx)
-	jz	L(Exit8)
-	cmp	$16, %ebx
-	jb	L(StrncpyExit15Bytes)
-	cmpb	$0, 8(%ecx)
-	jz	L(Exit9)
-	cmpb	$0, 9(%ecx)
-	jz	L(Exit10)
-	cmpb	$0, 10(%ecx)
-	jz	L(Exit11)
-	cmpb	$0, 11(%ecx)
-	jz	L(Exit12)
-	cmpb	$0, 12(%ecx)
-	jz	L(Exit13)
-	cmpb	$0, 13(%ecx)
-	jz	L(Exit14)
-	cmpb	$0, 14(%ecx)
-	jz	L(Exit15)
-	cmpb	$0, 15(%ecx)
-	jz	L(Exit16)
-	cmp	$16, %ebx
-	je	L(StrlcpyExit16)
-
-#define USE_AS_STRNCPY
-#include "ssse3-strcpy-atom.S"
-
-	.p2align 4
-L(CopyFrom1To16Bytes):
-	add	%esi, %edx
-	add	%esi, %ecx
-
-	POP	(%esi)
-	test	%al, %al
-	jz	L(ExitHigh8)
-
-L(CopyFrom1To16BytesLess8):
-	mov	%al, %ah
-	and	$15, %ah
-	jz	L(ExitHigh4)
-
-	test	$0x01, %al
-	jnz	L(Exit1)
-	test	$0x02, %al
-	jnz	L(Exit2)
-	test	$0x04, %al
-	jnz	L(Exit3)
-L(Exit4):
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-
-	lea	3(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(ExitHigh4):
-	test	$0x10, %al
-	jnz	L(Exit5)
-	test	$0x20, %al
-	jnz	L(Exit6)
-	test	$0x40, %al
-	jnz	L(Exit7)
-L(Exit8):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-
-	lea	7(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(ExitHigh8):
-	mov	%ah, %al
-	and	$15, %al
-	jz	L(ExitHigh12)
-
-	test	$0x01, %ah
-	jnz	L(Exit9)
-	test	$0x02, %ah
-	jnz	L(Exit10)
-	test	$0x04, %ah
-	jnz	L(Exit11)
-L(Exit12):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	8(%ecx), %eax
-	movl	%eax, 8(%edx)
-
-	lea	11(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(ExitHigh12):
-	test	$0x10, %ah
-	jnz	L(Exit13)
-	test	$0x20, %ah
-	jnz	L(Exit14)
-	test	$0x40, %ah
-	jnz	L(Exit15)
-L(Exit16):
-	movlpd	(%ecx), %xmm0
-	movlpd	8(%ecx), %xmm1
-	movlpd	%xmm0, (%edx)
-	movlpd	%xmm1, 8(%edx)
-
-	lea	15(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	CFI_PUSH(%esi)
-
-	.p2align 4
-L(CopyFrom1To16BytesCase2):
-	add	$16, %ebx
-	add	%esi, %ecx
-	add	%esi, %edx
-
-	POP	(%esi)
-
-	test	%al, %al
-	jz	L(ExitHighCase2)
-
-	cmp	$8, %ebx
-	ja	L(CopyFrom1To16BytesLess8)
-
-	test	$0x01, %al
-	jnz	L(Exit1)
-	cmp	$1, %ebx
-	je	L(StrlcpyExit1)
-	test	$0x02, %al
-	jnz	L(Exit2)
-	cmp	$2, %ebx
-	je	L(StrlcpyExit2)
-	test	$0x04, %al
-	jnz	L(Exit3)
-	cmp	$3, %ebx
-	je	L(StrlcpyExit3)
-	test	$0x08, %al
-	jnz	L(Exit4)
-	cmp	$4, %ebx
-	je	L(StrlcpyExit4)
-	test	$0x10, %al
-	jnz	L(Exit5)
-	cmp	$5, %ebx
-	je	L(StrlcpyExit5)
-	test	$0x20, %al
-	jnz	L(Exit6)
-	cmp	$6, %ebx
-	je	L(StrlcpyExit6)
-	test	$0x40, %al
-	jnz	L(Exit7)
-	cmp	$7, %ebx
-	je	L(StrlcpyExit7)
-	test	$0x80, %al
-	jnz	L(Exit8)
-	jmp	L(StrlcpyExit8)
-
-	.p2align 4
-L(ExitHighCase2):
-	cmp	$8, %ebx
-	jbe	L(CopyFrom1To16BytesLess8Case3)
-
-	test	$0x01, %ah
-	jnz	L(Exit9)
-	cmp	$9, %ebx
-	je	L(StrlcpyExit9)
-	test	$0x02, %ah
-	jnz	L(Exit10)
-	cmp	$10, %ebx
-	je	L(StrlcpyExit10)
-	test	$0x04, %ah
-	jnz	L(Exit11)
-	cmp	$11, %ebx
-	je	L(StrlcpyExit11)
-	test	$0x8, %ah
-	jnz	L(Exit12)
-	cmp	$12, %ebx
-	je	L(StrlcpyExit12)
-	test	$0x10, %ah
-	jnz	L(Exit13)
-	cmp	$13, %ebx
-	je	L(StrlcpyExit13)
-	test	$0x20, %ah
-	jnz	L(Exit14)
-	cmp	$14, %ebx
-	je	L(StrlcpyExit14)
-	test	$0x40, %ah
-	jnz	L(Exit15)
-	cmp	$15, %ebx
-	je	L(StrlcpyExit15)
-	test	$0x80, %ah
-	jnz	L(Exit16)
-	jmp	L(StrlcpyExit16)
-
-	CFI_PUSH(%esi)
-
-	.p2align 4
-L(CopyFrom1To16BytesCase2OrCase3):
-	test	%eax, %eax
-	jnz	L(CopyFrom1To16BytesCase2)
-
-	.p2align 4
-L(CopyFrom1To16BytesCase3):
-	add	$16, %ebx
-	add	%esi, %edx
-	add	%esi, %ecx
-
-	POP	(%esi)
-
-	cmp	$8, %ebx
-	ja	L(ExitHigh8Case3)
-
-L(CopyFrom1To16BytesLess8Case3):
-	cmp	$4, %ebx
-	ja	L(ExitHigh4Case3)
-
-	cmp	$1, %ebx
-	je	L(StrlcpyExit1)
-	cmp	$2, %ebx
-	je	L(StrlcpyExit2)
-	cmp	$3, %ebx
-	je	L(StrlcpyExit3)
-L(StrlcpyExit4):
-	movb	%bh, 3(%edx)
-	movw	(%ecx), %ax
-	movw	%ax, (%edx)
-	movb	2(%ecx), %al
-	movb	%al, 2(%edx)
-
-	lea	4(%ecx), %edx
-	mov	%edi, %ecx
-	POP	(%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(ExitHigh4Case3):
-	cmp	$5, %ebx
-	je	L(StrlcpyExit5)
-	cmp	$6, %ebx
-	je	L(StrlcpyExit6)
-	cmp	$7, %ebx
-	je	L(StrlcpyExit7)
-L(StrlcpyExit8):
-	movb	%bh, 7(%edx)
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movl	3(%ecx), %eax
-	movl	%eax, 3(%edx)
-
-	lea	8(%ecx), %edx
-	mov	%edi, %ecx
-	POP	(%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(ExitHigh8Case3):
-	cmp	$12, %ebx
-	ja	L(ExitHigh12Case3)
-
-	cmp	$9, %ebx
-	je	L(StrlcpyExit9)
-	cmp	$10, %ebx
-	je	L(StrlcpyExit10)
-	cmp	$11, %ebx
-	je	L(StrlcpyExit11)
-L(StrlcpyExit12):
-	movb	%bh, 11(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	7(%ecx), %eax
-	movl	%eax, 7(%edx)
-
-	lea	12(%ecx), %edx
-	mov	%edi, %ecx
-	POP	(%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(ExitHigh12Case3):
-	cmp	$13, %ebx
-	je	L(StrlcpyExit13)
-	cmp	$14, %ebx
-	je	L(StrlcpyExit14)
-	cmp	$15, %ebx
-	je	L(StrlcpyExit15)
-L(StrlcpyExit16):
-	movb	%bh, 15(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	7(%ecx), %xmm0
-	movlpd	%xmm0, 7(%edx)
-
-	lea	16(%ecx), %edx
-	mov	%edi, %ecx
-	POP	(%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(StrlcpyExit1):
-	movb	%bh, (%edx)
-
-	lea	1(%ecx), %edx
-	mov	%edi, %ecx
-	POP	(%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit1):
-	movb	(%ecx), %al
-	movb	%al, (%edx)
-
-	mov	%ecx, %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit2):
-	movb	%bh, 1(%edx)
-	movb	(%ecx), %al
-	movb	%al, (%edx)
-
-	lea	2(%ecx), %edx
-	mov	%edi, %ecx
-	POP	(%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit2):
-	movw	(%ecx), %ax
-	movw	%ax, (%edx)
-	movl	%edi, %eax
-
-	lea	1(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit3):
-	movb	%bh, 2(%edx)
-	movw	(%ecx), %ax
-	movw	%ax, (%edx)
-
-	lea	3(%ecx), %edx
-	mov	%edi, %ecx
-	POP	(%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit3):
-	movw	(%ecx), %ax
-	movw	%ax, (%edx)
-	movb	2(%ecx), %al
-	movb	%al, 2(%edx)
-
-	lea	2(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit5):
-	movb	%bh, 4(%edx)
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movl	%edi, %eax
-
-	lea	5(%ecx), %edx
-	mov	%edi, %ecx
-	POP	(%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit5):
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movb	4(%ecx), %al
-	movb	%al, 4(%edx)
-
-	lea	4(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit6):
-	movb	%bh, 5(%edx)
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movb	4(%ecx), %al
-	movb	%al, 4(%edx)
-
-	lea	6(%ecx), %edx
-	mov	%edi, %ecx
-	POP	(%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit6):
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movw	4(%ecx), %ax
-	movw	%ax, 4(%edx)
-
-	lea	5(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit7):
-	movb	%bh, 6(%edx)
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movw	4(%ecx), %ax
-	movw	%ax, 4(%edx)
-
-	lea	7(%ecx), %edx
-	mov	%edi, %ecx
-	POP	(%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit7):
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movl	3(%ecx), %eax
-	movl	%eax, 3(%edx)
-
-	lea	6(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit9):
-	movb	%bh, 8(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-
-	lea	9(%ecx), %edx
-	mov	%edi, %ecx
-	POP	(%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit9):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movb	8(%ecx), %al
-	movb	%al, 8(%edx)
-
-	lea	8(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit10):
-	movb	%bh, 9(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movb	8(%ecx), %al
-	movb	%al, 8(%edx)
-
-	lea	10(%ecx), %edx
-	mov	%edi, %ecx
-	POP	(%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit10):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movw	8(%ecx), %ax
-	movw	%ax, 8(%edx)
-
-	lea	9(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit11):
-	movb	%bh, 10(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movw	8(%ecx), %ax
-	movw	%ax, 8(%edx)
-
-	lea	11(%ecx), %edx
-	mov	%edi, %ecx
-	POP	(%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit11):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	7(%ecx), %eax
-	movl	%eax, 7(%edx)
-
-	lea	10(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit13):
-	movb	%bh, 12(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	8(%ecx), %eax
-	movl	%eax, 8(%edx)
-
-	lea	13(%ecx), %edx
-	mov	%edi, %ecx
-	POP	(%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit13):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	5(%ecx), %xmm0
-	movlpd	%xmm0, 5(%edx)
-
-	lea	12(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit14):
-	movb	%bh, 13(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	5(%ecx), %xmm0
-	movlpd	%xmm0, 5(%edx)
-
-	lea	14(%ecx), %edx
-	mov	%edi, %ecx
-	POP	(%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit14):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	6(%ecx), %xmm0
-	movlpd	%xmm0, 6(%edx)
-
-	lea	13(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit15):
-	movb	%bh, 14(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	6(%ecx), %xmm0
-	movlpd	%xmm0, 6(%edx)
-
-	lea	15(%ecx), %edx
-	mov	%edi, %ecx
-	POP	(%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit15):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	7(%ecx), %xmm0
-	movlpd	%xmm0, 7(%edx)
-
-	lea	14(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrncpyExit15Bytes):
-	cmp	$12, %ebx
-	ja	L(StrncpyExit15Bytes1)
-
-	cmpb	$0, 8(%ecx)
-	jz	L(Exit9)
-	cmp	$9, %ebx
-	je	L(StrlcpyExit9)
-
-	cmpb	$0, 9(%ecx)
-	jz	L(Exit10)
-	cmp	$10, %ebx
-	je	L(StrlcpyExit10)
-
-	cmpb	$0, 10(%ecx)
-	jz	L(Exit11)
-	cmp	$11, %ebx
-	je	L(StrlcpyExit11)
-
-	cmpb	$0, 11(%ecx)
-	jz	L(Exit12)
-	jmp	L(StrlcpyExit12)
-
-	.p2align 4
-L(StrncpyExit15Bytes1):
-	cmpb	$0, 8(%ecx)
-	jz	L(Exit9)
-	cmpb	$0, 9(%ecx)
-	jz	L(Exit10)
-	cmpb	$0, 10(%ecx)
-	jz	L(Exit11)
-	cmpb	$0, 11(%ecx)
-	jz	L(Exit12)
-
-	cmpb	$0, 12(%ecx)
-	jz	L(Exit13)
-	cmp	$13, %ebx
-	je	L(StrlcpyExit13)
-
-	cmpb	$0, 13(%ecx)
-	jz	L(Exit14)
-	cmp	$14, %ebx
-	je	L(StrlcpyExit14)
-
-	cmpb	$0, 14(%ecx)
-	jz	L(Exit15)
-	jmp	L(StrlcpyExit15)
-
-	.p2align 4
-L(StrncpyExit8Bytes):
-	cmp	$4, %ebx
-	ja	L(StrncpyExit8Bytes1)
-
-	cmpb	$0, (%ecx)
-	jz	L(Exit1)
-	cmp	$1, %ebx
-	je	L(StrlcpyExit1)
-
-	cmpb	$0, 1(%ecx)
-	jz	L(Exit2)
-	cmp	$2, %ebx
-	je	L(StrlcpyExit2)
-
-	cmpb	$0, 2(%ecx)
-	jz	L(Exit3)
-	cmp	$3, %ebx
-	je	L(StrlcpyExit3)
-
-	cmpb	$0, 3(%ecx)
-	jz	L(Exit4)
-	jmp	L(StrlcpyExit4)
-
-	.p2align 4
-L(StrncpyExit8Bytes1):
-	cmpb	$0, (%ecx)
-	jz	L(Exit1)
-	cmpb	$0, 1(%ecx)
-	jz	L(Exit2)
-	cmpb	$0, 2(%ecx)
-	jz	L(Exit3)
-	cmpb	$0, 3(%ecx)
-	jz	L(Exit4)
-
-	cmpb	$0, 4(%ecx)
-	jz	L(Exit5)
-	cmp	$5, %ebx
-	je	L(StrlcpyExit5)
-
-	cmpb	$0, 5(%ecx)
-	jz	L(Exit6)
-	cmp	$6, %ebx
-	je	L(StrlcpyExit6)
-
-	cmpb	$0, 6(%ecx)
-	jz	L(Exit7)
-	cmp	$7, %ebx
-	je	L(StrlcpyExit7)
-
-	cmpb	$0, 7(%ecx)
-	jz	L(Exit8)
-	jmp	L(StrlcpyExit8)
-
-	CFI_POP	(%edi)
-
-
-	.p2align 4
-L(Prolog_return_start_len):
-	movl	LEN(%esp), %ebx
-        movl	SRC(%esp), %ecx
-L(CalculateLengthOfSrcProlog):
-	mov	%ecx, %edx
-	sub	%ebx, %ecx
-
-	.p2align 4
-L(CalculateLengthOfSrc):
-	cmpb	$0, (%edx)
-	jz	L(exit_tail0)
-	cmpb	$0, 1(%edx)
-	jz	L(exit_tail1)
-	cmpb	$0, 2(%edx)
-	jz	L(exit_tail2)
-	cmpb	$0, 3(%edx)
-	jz	L(exit_tail3)
-
-	cmpb	$0, 4(%edx)
-	jz	L(exit_tail4)
-	cmpb	$0, 5(%edx)
-	jz	L(exit_tail5)
-	cmpb	$0, 6(%edx)
-	jz	L(exit_tail6)
-	cmpb	$0, 7(%edx)
-	jz	L(exit_tail7)
-
-	cmpb	$0, 8(%edx)
-	jz	L(exit_tail8)
-	cmpb	$0, 9(%edx)
-	jz	L(exit_tail9)
-	cmpb	$0, 10(%edx)
-	jz	L(exit_tail10)
-	cmpb	$0, 11(%edx)
-	jz	L(exit_tail11)
-
-	cmpb	$0, 12(%edx)
-	jz	L(exit_tail12)
-	cmpb	$0, 13(%edx)
-	jz	L(exit_tail13)
-	cmpb	$0, 14(%edx)
-	jz	L(exit_tail14)
-	cmpb	$0, 15(%edx)
-	jz	L(exit_tail15)
-
-	pxor	%xmm0, %xmm0
-	lea	16(%edx), %eax
-	add	$16, %ecx
-	and	$-16, %eax
-
-	pcmpeqb	(%eax), %xmm0
-	pmovmskb %xmm0, %edx
-	pxor	%xmm1, %xmm1
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm1
-	pmovmskb %xmm1, %edx
-	pxor	%xmm2, %xmm2
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm2
-	pmovmskb %xmm2, %edx
-	pxor	%xmm3, %xmm3
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm0
-	pmovmskb %xmm0, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm1
-	pmovmskb %xmm1, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm2
-	pmovmskb %xmm2, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm0
-	pmovmskb %xmm0, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm1
-	pmovmskb %xmm1, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm2
-	pmovmskb %xmm2, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm0
-	pmovmskb %xmm0, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm1
-	pmovmskb %xmm1, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm2
-	pmovmskb %xmm2, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	and	$-0x40, %eax
-
-	.p2align 4
-L(aligned_64_loop):
-	movaps	(%eax), %xmm0
-	movaps	16(%eax), %xmm1
-	movaps	32(%eax), %xmm2
-	movaps	48(%eax), %xmm6
-	pminub	%xmm1, %xmm0
-	pminub	%xmm6, %xmm2
-	pminub	%xmm0, %xmm2
-	pcmpeqb	%xmm3, %xmm2
-	pmovmskb %xmm2, %edx
-	lea	64(%eax), %eax
-	test	%edx, %edx
-	jz	L(aligned_64_loop)
-
-	pcmpeqb	-64(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	48(%ecx), %ecx
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	%xmm1, %xmm3
-	pmovmskb %xmm3, %edx
-	lea	-16(%ecx), %ecx
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	-32(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	-16(%ecx), %ecx
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	%xmm6, %xmm3
-	pmovmskb %xmm3, %edx
-	lea	-16(%ecx), %ecx
-
-	.p2align 4
-L(exit):
-	sub	%ecx, %eax
-	test	%dl, %dl
-	jz	L(exit_more_8)
-
-	mov	%dl, %cl
-	and	$15, %cl
-	jz	L(exit_more_4)
-	test	$0x01, %dl
-	jnz	L(exit_0)
-	test	$0x02, %dl
-	jnz	L(exit_1)
-	test	$0x04, %dl
-	jnz	L(exit_2)
-	add	$3, %eax
-	RETURN
-
-	.p2align 4
-L(exit_more_4):
-	test	$0x10, %dl
-	jnz	L(exit_4)
-	test	$0x20, %dl
-	jnz	L(exit_5)
-	test	$0x40, %dl
-	jnz	L(exit_6)
-	add	$7, %eax
-	RETURN
-
-	.p2align 4
-L(exit_more_8):
-	mov	%dh, %ch
-	and	$15, %ch
-	jz	L(exit_more_12)
-	test	$0x01, %dh
-	jnz	L(exit_8)
-	test	$0x02, %dh
-	jnz	L(exit_9)
-	test	$0x04, %dh
-	jnz	L(exit_10)
-	add	$11, %eax
-	RETURN
-
-	.p2align 4
-L(exit_more_12):
-	test	$0x10, %dh
-	jnz	L(exit_12)
-	test	$0x20, %dh
-	jnz	L(exit_13)
-	test	$0x40, %dh
-	jnz	L(exit_14)
-	add	$15, %eax
-L(exit_0):
-	RETURN
-
-	.p2align 4
-L(exit_1):
-	add	$1, %eax
-	RETURN
-
-L(exit_2):
-	add	$2, %eax
-	RETURN
-
-L(exit_3):
-	add	$3, %eax
-	RETURN
-
-L(exit_4):
-	add	$4, %eax
-	RETURN
-
-L(exit_5):
-	add	$5, %eax
-	RETURN
-
-L(exit_6):
-	add	$6, %eax
-	RETURN
-
-L(exit_7):
-	add	$7, %eax
-	RETURN
-
-L(exit_8):
-	add	$8, %eax
-	RETURN
-
-L(exit_9):
-	add	$9, %eax
-	RETURN
-
-L(exit_10):
-	add	$10, %eax
-	RETURN
-
-L(exit_11):
-	add	$11, %eax
-	RETURN
-
-L(exit_12):
-	add	$12, %eax
-	RETURN
-
-L(exit_13):
-	add	$13, %eax
-	RETURN
-
-L(exit_14):
-	add	$14, %eax
-	RETURN
-
-L(exit_15):
-	add	$15, %eax
-	RETURN
-
-L(exit_tail0):
-	mov	%edx, %eax
-	sub	%ecx, %eax
-	RETURN
-
-	.p2align 4
-L(exit_tail1):
-	lea	1(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail2):
-	lea	2(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail3):
-	lea	3(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail4):
-	lea	4(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail5):
-	lea	5(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail6):
-	lea	6(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail7):
-	lea	7(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail8):
-	lea	8(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail9):
-	lea	9(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail10):
-	lea	10(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail11):
-	lea	11(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail12):
-	lea	12(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail13):
-	lea	13(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail14):
-	lea	14(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail15):
-	lea	15(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-END (strlcat)
diff --git a/libc/arch-x86/string/ssse3-strlcpy-atom.S b/libc/arch-x86/string/ssse3-strlcpy-atom.S
deleted file mode 100644
index 1671da6..0000000
--- a/libc/arch-x86/string/ssse3-strlcpy-atom.S
+++ /dev/null
@@ -1,1403 +0,0 @@
-/*
-Copyright (c) 2011, 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 USE_AS_STRNCPY
-#define STRCPY strlcpy_ssse3
-#define STRLEN strlcpy_ssse3
-#define USE_AS_STRLCPY
-#include "ssse3-strcpy-atom.S"
-
-	.p2align 4
-L(CopyFrom1To16Bytes):
-	add	%esi, %edx
-	add	%esi, %ecx
-
-	POP	(%esi)
-	test	%al, %al
-	jz	L(ExitHigh8)
-
-L(CopyFrom1To16BytesLess8):
-	mov	%al, %ah
-	and	$15, %ah
-	jz	L(ExitHigh4)
-
-	test	$0x01, %al
-	jnz	L(Exit1)
-	test	$0x02, %al
-	jnz	L(Exit2)
-	test	$0x04, %al
-	jnz	L(Exit3)
-L(Exit4):
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-
-	lea	3(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(ExitHigh4):
-	test	$0x10, %al
-	jnz	L(Exit5)
-	test	$0x20, %al
-	jnz	L(Exit6)
-	test	$0x40, %al
-	jnz	L(Exit7)
-L(Exit8):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-
-	lea	7(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(ExitHigh8):
-	mov	%ah, %al
-	and	$15, %al
-	jz	L(ExitHigh12)
-
-	test	$0x01, %ah
-	jnz	L(Exit9)
-	test	$0x02, %ah
-	jnz	L(Exit10)
-	test	$0x04, %ah
-	jnz	L(Exit11)
-L(Exit12):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	8(%ecx), %eax
-	movl	%eax, 8(%edx)
-
-	lea	11(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(ExitHigh12):
-	test	$0x10, %ah
-	jnz	L(Exit13)
-	test	$0x20, %ah
-	jnz	L(Exit14)
-	test	$0x40, %ah
-	jnz	L(Exit15)
-L(Exit16):
-	movlpd	(%ecx), %xmm0
-	movlpd	8(%ecx), %xmm1
-	movlpd	%xmm0, (%edx)
-	movlpd	%xmm1, 8(%edx)
-
-	lea	15(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	CFI_PUSH(%esi)
-
-	.p2align 4
-L(CopyFrom1To16BytesCase2):
-	add	$16, %ebx
-	add	%esi, %ecx
-        add     %esi, %edx
-
-	POP	(%esi)
-
-        test    %al, %al
-        jz      L(ExitHighCase2)
-
-        cmp     $8, %ebx
-        ja      L(CopyFrom1To16BytesLess8)
-
-	test	$0x01, %al
-	jnz	L(Exit1)
-	cmp	$1, %ebx
-	je	L(StrlcpyExit1)
-	test	$0x02, %al
-	jnz	L(Exit2)
-	cmp	$2, %ebx
-	je	L(StrlcpyExit2)
-	test	$0x04, %al
-	jnz	L(Exit3)
-	cmp	$3, %ebx
-	je	L(StrlcpyExit3)
-	test	$0x08, %al
-	jnz	L(Exit4)
-	cmp	$4, %ebx
-	je	L(StrlcpyExit4)
-	test	$0x10, %al
-	jnz	L(Exit5)
-	cmp	$5, %ebx
-	je	L(StrlcpyExit5)
-	test	$0x20, %al
-	jnz	L(Exit6)
-	cmp	$6, %ebx
-	je	L(StrlcpyExit6)
-	test	$0x40, %al
-	jnz	L(Exit7)
-	cmp	$7, %ebx
-	je	L(StrlcpyExit7)
-	test	$0x80, %al
-	jnz	L(Exit8)
-	jmp	L(StrlcpyExit8)
-
-	.p2align 4
-L(ExitHighCase2):
-        cmp     $8, %ebx
-        jbe      L(CopyFrom1To16BytesLess8Case3)
-
-	test	$0x01, %ah
-	jnz	L(Exit9)
-	cmp	$9, %ebx
-	je	L(StrlcpyExit9)
-	test	$0x02, %ah
-	jnz	L(Exit10)
-	cmp	$10, %ebx
-	je	L(StrlcpyExit10)
-	test	$0x04, %ah
-	jnz	L(Exit11)
-	cmp	$11, %ebx
-	je	L(StrlcpyExit11)
-	test	$0x8, %ah
-	jnz	L(Exit12)
-	cmp	$12, %ebx
-	je	L(StrlcpyExit12)
-	test	$0x10, %ah
-	jnz	L(Exit13)
-	cmp	$13, %ebx
-	je	L(StrlcpyExit13)
-	test	$0x20, %ah
-	jnz	L(Exit14)
-	cmp	$14, %ebx
-	je	L(StrlcpyExit14)
-	test	$0x40, %ah
-	jnz	L(Exit15)
-	cmp	$15, %ebx
-	je	L(StrlcpyExit15)
-	test	$0x80, %ah
-	jnz	L(Exit16)
-	jmp	L(StrlcpyExit16)
-
-	CFI_PUSH(%esi)
-
-	.p2align 4
-L(CopyFrom1To16BytesCase2OrCase3):
-	test	%eax, %eax
-	jnz	L(CopyFrom1To16BytesCase2)
-
-	.p2align 4
-L(CopyFrom1To16BytesCase3):
-	add	$16, %ebx
-	add	%esi, %edx
-	add	%esi, %ecx
-
-	POP	(%esi)
-
-	cmp	$8, %ebx
-	ja	L(ExitHigh8Case3)
-
-L(CopyFrom1To16BytesLess8Case3):
-	cmp	$4, %ebx
-	ja	L(ExitHigh4Case3)
-
-	cmp	$1, %ebx
-	je	L(StrlcpyExit1)
-	cmp	$2, %ebx
-	je	L(StrlcpyExit2)
-	cmp	$3, %ebx
-	je	L(StrlcpyExit3)
-L(StrlcpyExit4):
-	movb	%bh, 3(%edx)
-	movw	(%ecx), %ax
-	movw	%ax, (%edx)
-	movb	2(%ecx), %al
-	movb	%al, 2(%edx)
-
-	lea	4(%ecx), %edx
-	mov	%edi, %ecx
-        POP     (%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(ExitHigh4Case3):
-	cmp	$5, %ebx
-	je	L(StrlcpyExit5)
-	cmp	$6, %ebx
-	je	L(StrlcpyExit6)
-	cmp	$7, %ebx
-	je	L(StrlcpyExit7)
-L(StrlcpyExit8):
-	movb	%bh, 7(%edx)
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movl	3(%ecx), %eax
-	movl	%eax, 3(%edx)
-
-	lea	8(%ecx), %edx
-	mov	%edi, %ecx
-        POP     (%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(ExitHigh8Case3):
-	cmp	$12, %ebx
-	ja	L(ExitHigh12Case3)
-
-	cmp	$9, %ebx
-	je	L(StrlcpyExit9)
-	cmp	$10, %ebx
-	je	L(StrlcpyExit10)
-	cmp	$11, %ebx
-	je	L(StrlcpyExit11)
-L(StrlcpyExit12):
-	movb	%bh, 11(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	7(%ecx), %eax
-	movl	%eax, 7(%edx)
-
-	lea	12(%ecx), %edx
-	mov	%edi, %ecx
-        POP     (%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(ExitHigh12Case3):
-	cmp	$13, %ebx
-	je	L(StrlcpyExit13)
-	cmp	$14, %ebx
-	je	L(StrlcpyExit14)
-	cmp	$15, %ebx
-	je	L(StrlcpyExit15)
-L(StrlcpyExit16):
-	movb	%bh, 15(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	7(%ecx), %xmm0
-	movlpd	%xmm0, 7(%edx)
-
-	lea	16(%ecx), %edx
-	mov	%edi, %ecx
-        POP     (%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(StrlcpyExit1):
-	movb	%bh, (%edx)
-
-	lea	1(%ecx), %edx
-	mov	%edi, %ecx
-        POP     (%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit1):
-	movb	(%ecx), %al
-	movb	%al, (%edx)
-
-	mov	%ecx, %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit2):
-	movb	%bh, 1(%edx)
-	movb	(%ecx), %al
-	movb	%al, (%edx)
-
-	lea	2(%ecx), %edx
-	mov	%edi, %ecx
-        POP     (%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit2):
-	movw	(%ecx), %ax
-	movw	%ax, (%edx)
-	movl	%edi, %eax
-
-	lea	1(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit3):
-	movb	%bh, 2(%edx)
-	movw	(%ecx), %ax
-	movw	%ax, (%edx)
-
-	lea	3(%ecx), %edx
-	mov	%edi, %ecx
-        POP     (%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit3):
-	movw	(%ecx), %ax
-	movw	%ax, (%edx)
-	movb	2(%ecx), %al
-	movb	%al, 2(%edx)
-
-	lea	2(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit5):
-	movb	%bh, 4(%edx)
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movl	%edi, %eax
-
-	lea	5(%ecx), %edx
-	mov	%edi, %ecx
-        POP     (%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit5):
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movb	4(%ecx), %al
-	movb	%al, 4(%edx)
-
-	lea	4(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit6):
-	movb	%bh, 5(%edx)
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movb	4(%ecx), %al
-	movb	%al, 4(%edx)
-
-	lea	6(%ecx), %edx
-	mov	%edi, %ecx
-        POP     (%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit6):
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movw	4(%ecx), %ax
-	movw	%ax, 4(%edx)
-
-	lea	5(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit7):
-	movb	%bh, 6(%edx)
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movw	4(%ecx), %ax
-	movw	%ax, 4(%edx)
-
-	lea	7(%ecx), %edx
-	mov	%edi, %ecx
-        POP     (%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit7):
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movl	3(%ecx), %eax
-	movl	%eax, 3(%edx)
-
-	lea	6(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit9):
-	movb	%bh, 8(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-
-	lea	9(%ecx), %edx
-	mov	%edi, %ecx
-        POP     (%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit9):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movb	8(%ecx), %al
-	movb	%al, 8(%edx)
-
-	lea	8(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit10):
-	movb	%bh, 9(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movb	8(%ecx), %al
-	movb	%al, 8(%edx)
-
-	lea	10(%ecx), %edx
-	mov	%edi, %ecx
-        POP     (%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit10):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movw	8(%ecx), %ax
-	movw	%ax, 8(%edx)
-
-	lea	9(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit11):
-	movb	%bh, 10(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movw	8(%ecx), %ax
-	movw	%ax, 8(%edx)
-
-	lea	11(%ecx), %edx
-	mov	%edi, %ecx
-        POP     (%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit11):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	7(%ecx), %eax
-	movl	%eax, 7(%edx)
-
-	lea	10(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit13):
-	movb	%bh, 12(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	8(%ecx), %eax
-	movl	%eax, 8(%edx)
-
-	lea	13(%ecx), %edx
-	mov	%edi, %ecx
-        POP     (%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit13):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	5(%ecx), %xmm0
-	movlpd	%xmm0, 5(%edx)
-
-	lea	12(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit14):
-	movb	%bh, 13(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	5(%ecx), %xmm0
-	movlpd	%xmm0, 5(%edx)
-
-	lea	14(%ecx), %edx
-	mov	%edi, %ecx
-        POP     (%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit14):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	6(%ecx), %xmm0
-	movlpd	%xmm0, 6(%edx)
-
-	lea	13(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-	.p2align 4
-L(StrlcpyExit15):
-	movb	%bh, 14(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	6(%ecx), %xmm0
-	movlpd	%xmm0, 6(%edx)
-
-	lea	15(%ecx), %edx
-	mov	%edi, %ecx
-        POP     (%edi)
-	jmp	L(CalculateLengthOfSrc)
-        CFI_PUSH     (%edi)
-
-	.p2align 4
-L(Exit15):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	7(%ecx), %xmm0
-	movlpd	%xmm0, 7(%edx)
-
-	lea	14(%ecx), %eax
-	sub	%edi, %eax
-	RETURN1
-
-        CFI_POP (%edi)
-
-	.p2align 4
-L(StrlcpyExit0):
-	movl	$0, %eax
-	RETURN
-
-	.p2align 4
-L(StrncpyExit15Bytes):
-	cmp	$12, %ebx
-	ja	L(StrncpyExit15Bytes1)
-
-	cmpb	$0, 8(%ecx)
-	jz	L(ExitTail9)
-	cmp	$9, %ebx
-	je	L(StrlcpyExitTail9)
-
-	cmpb	$0, 9(%ecx)
-	jz	L(ExitTail10)
-	cmp	$10, %ebx
-	je	L(StrlcpyExitTail10)
-
-	cmpb	$0, 10(%ecx)
-	jz	L(ExitTail11)
-	cmp	$11, %ebx
-	je	L(StrlcpyExitTail11)
-
-	cmpb	$0, 11(%ecx)
-	jz	L(ExitTail12)
-
-	movb	%bh, 11(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	7(%ecx), %eax
-	movl	%eax, 7(%edx)
-
-	lea	12(%ecx), %edx
-	jmp	L(CalculateLengthOfSrc)
-
-	.p2align 4
-L(StrncpyExit15Bytes1):
-	cmpb	$0, 8(%ecx)
-	jz	L(ExitTail9)
-	cmpb	$0, 9(%ecx)
-	jz	L(ExitTail10)
-	cmpb	$0, 10(%ecx)
-	jz	L(ExitTail11)
-	cmpb	$0, 11(%ecx)
-	jz	L(ExitTail12)
-
-	cmpb	$0, 12(%ecx)
-	jz	L(ExitTail13)
-	cmp	$13, %ebx
-	je	L(StrlcpyExitTail13)
-
-	cmpb	$0, 13(%ecx)
-	jz	L(ExitTail14)
-	cmp	$14, %ebx
-	je	L(StrlcpyExitTail14)
-
-	cmpb	$0, 14(%ecx)
-	jz	L(ExitTail15)
-
-	movb	%bh, 14(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	6(%ecx), %xmm0
-	movlpd	%xmm0, 6(%edx)
-
-	lea	15(%ecx), %edx
-	jmp	L(CalculateLengthOfSrc)
-
-	.p2align 4
-L(StrncpyExit8Bytes):
-	cmp	$4, %ebx
-	ja	L(StrncpyExit8Bytes1)
-
-	test	%ebx, %ebx
-	jz	L(StrlcpyExitTail0)
-
-	cmpb	$0, (%ecx)
-	jz	L(ExitTail1)
-	cmp	$1, %ebx
-	je	L(StrlcpyExitTail1)
-
-	cmpb	$0, 1(%ecx)
-	jz	L(ExitTail2)
-	cmp	$2, %ebx
-	je	L(StrlcpyExitTail2)
-
-	cmpb	$0, 2(%ecx)
-	jz	L(ExitTail3)
-	cmp	$3, %ebx
-	je	L(StrlcpyExitTail3)
-
-	cmpb	$0, 3(%ecx)
-	jz	L(ExitTail4)
-
-	movb	%bh, 3(%edx)
-	movw	(%ecx), %ax
-	movw	%ax, (%edx)
-	movb	2(%ecx), %al
-	movb	%al, 2(%edx)
-
-	lea	4(%ecx), %edx
-	jmp	L(CalculateLengthOfSrc)
-
-	.p2align 4
-L(StrncpyExit8Bytes1):
-	cmpb	$0, (%ecx)
-	jz	L(ExitTail1)
-	cmpb	$0, 1(%ecx)
-	jz	L(ExitTail2)
-	cmpb	$0, 2(%ecx)
-	jz	L(ExitTail3)
-	cmpb	$0, 3(%ecx)
-	jz	L(ExitTail4)
-
-	cmpb	$0, 4(%ecx)
-	jz	L(ExitTail5)
-	cmp	$5, %ebx
-	je	L(StrlcpyExitTail5)
-
-	cmpb	$0, 5(%ecx)
-	jz	L(ExitTail6)
-	cmp	$6, %ebx
-	je	L(StrlcpyExitTail6)
-
-	cmpb	$0, 6(%ecx)
-	jz	L(ExitTail7)
-	cmp	$7, %ebx
-	je	L(StrlcpyExitTail7)
-
-	cmpb	$0, 7(%ecx)
-	jz	L(ExitTail8)
-
-	movb	%bh, 7(%edx)
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movl	3(%ecx), %eax
-	movl	%eax, 3(%edx)
-
-	lea	8(%ecx), %edx
-	jmp	L(CalculateLengthOfSrc)
-
-	.p2align 4
-L(StrlcpyExitTail0):
-	mov	%ecx, %edx
-	jmp	L(CalculateLengthOfSrc)
-
-	.p2align 4
-L(StrlcpyExitTail1):
-	movb	%bh, (%edx)
-
-	lea	1(%ecx), %edx
-	jmp	L(CalculateLengthOfSrc)
-
-	.p2align 4
-L(ExitTail1):
-	movb	(%ecx), %al
-	movb	%al, (%edx)
-
-	mov	$0, %eax
-	RETURN
-
-	.p2align 4
-L(StrlcpyExitTail2):
-	movb	%bh, 1(%edx)
-	movb	(%ecx), %al
-	movb	%al, (%edx)
-
-	lea	2(%ecx), %edx
-	jmp	L(CalculateLengthOfSrc)
-
-	.p2align 4
-L(ExitTail2):
-	movw	(%ecx), %ax
-	movw	%ax, (%edx)
-	movl	%edx, %eax
-
-	mov	$1, %eax
-	RETURN
-
-	.p2align 4
-L(StrlcpyExitTail3):
-	movb	%bh, 2(%edx)
-	movw	(%ecx), %ax
-	movw	%ax, (%edx)
-
-	lea	3(%ecx), %edx
-	jmp	L(CalculateLengthOfSrc)
-
-	.p2align 4
-L(ExitTail3):
-	movw	(%ecx), %ax
-	movw	%ax, (%edx)
-	movb	2(%ecx), %al
-	movb	%al, 2(%edx)
-
-	mov	$2, %eax
-	RETURN
-
-	.p2align 4
-L(ExitTail4):
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-
-	mov	$3, %eax
-	RETURN
-
-	.p2align 4
-L(StrlcpyExitTail5):
-	movb	%bh, 4(%edx)
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movl	%edx, %eax
-
-	lea	5(%ecx), %edx
-	jmp	L(CalculateLengthOfSrc)
-
-	.p2align 4
-L(ExitTail5):
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movb	4(%ecx), %al
-	movb	%al, 4(%edx)
-
-	mov	$4, %eax
-	RETURN
-
-	.p2align 4
-L(StrlcpyExitTail6):
-	movb	%bh, 5(%edx)
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movb	4(%ecx), %al
-	movb	%al, 4(%edx)
-
-	lea	6(%ecx), %edx
-	jmp	L(CalculateLengthOfSrc)
-
-	.p2align 4
-L(ExitTail6):
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movw	4(%ecx), %ax
-	movw	%ax, 4(%edx)
-
-	mov	$5, %eax
-	RETURN
-
-	.p2align 4
-L(StrlcpyExitTail7):
-	movb	%bh, 6(%edx)
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movw	4(%ecx), %ax
-	movw	%ax, 4(%edx)
-
-	lea	7(%ecx), %edx
-	jmp	L(CalculateLengthOfSrc)
-
-	.p2align 4
-L(ExitTail7):
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movl	3(%ecx), %eax
-	movl	%eax, 3(%edx)
-
-	mov	$6, %eax
-	RETURN
-
-	.p2align 4
-L(ExitTail8):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-
-	mov	$7, %eax
-	RETURN
-
-	.p2align 4
-L(StrlcpyExitTail9):
-	movb	%bh, 8(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-
-	lea	9(%ecx), %edx
-	jmp	L(CalculateLengthOfSrc)
-
-	.p2align 4
-L(ExitTail9):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movb	8(%ecx), %al
-	movb	%al, 8(%edx)
-
-	mov	$8, %eax
-	RETURN
-
-	.p2align 4
-L(StrlcpyExitTail10):
-	movb	%bh, 9(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movb	8(%ecx), %al
-	movb	%al, 8(%edx)
-
-	lea	10(%ecx), %edx
-	jmp	L(CalculateLengthOfSrc)
-
-	.p2align 4
-L(ExitTail10):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movw	8(%ecx), %ax
-	movw	%ax, 8(%edx)
-
-	mov	$9, %eax
-	RETURN
-
-	.p2align 4
-L(StrlcpyExitTail11):
-	movb	%bh, 10(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movw	8(%ecx), %ax
-	movw	%ax, 8(%edx)
-
-	lea	11(%ecx), %edx
-	jmp	L(CalculateLengthOfSrc)
-
-	.p2align 4
-L(ExitTail11):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	7(%ecx), %eax
-	movl	%eax, 7(%edx)
-
-	mov	$10, %eax
-	RETURN
-
-	.p2align 4
-L(ExitTail12):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	8(%ecx), %eax
-	movl	%eax, 8(%edx)
-
-	mov	$11, %eax
-	RETURN
-
-	.p2align 4
-L(StrlcpyExitTail13):
-	movb	%bh, 12(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	8(%ecx), %eax
-	movl	%eax, 8(%edx)
-
-	lea	13(%ecx), %edx
-	jmp	L(CalculateLengthOfSrc)
-
-	.p2align 4
-L(ExitTail13):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	5(%ecx), %xmm0
-	movlpd	%xmm0, 5(%edx)
-
-	mov	$12, %eax
-	RETURN
-
-	.p2align 4
-L(StrlcpyExitTail14):
-	movb	%bh, 13(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	5(%ecx), %xmm0
-	movlpd	%xmm0, 5(%edx)
-
-	lea	14(%ecx), %edx
-	jmp	L(CalculateLengthOfSrc)
-
-	.p2align 4
-L(ExitTail14):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	6(%ecx), %xmm0
-	movlpd	%xmm0, 6(%edx)
-
-	mov	$13, %eax
-	RETURN
-
-	.p2align 4
-L(ExitTail15):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	7(%ecx), %xmm0
-	movlpd	%xmm0, 7(%edx)
-
-	mov	$14, %eax
-	RETURN
-
-	.p2align 4
-L(StrlcpyExitTail16):
-	movb	%bh, 15(%edx)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movlpd	7(%ecx), %xmm0
-	movlpd	%xmm0, 7(%edx)
-
-	lea	16(%ecx), %edx
-	jmp	L(CalculateLengthOfSrc)
-
-	.p2align 4
-L(ExitTail16):
-	movlpd	(%ecx), %xmm0
-	movlpd	8(%ecx), %xmm1
-	movlpd	%xmm0, (%edx)
-	movlpd	%xmm1, 8(%edx)
-
-	mov	$15, %eax
-	RETURN
-
-	.p2align 4
-L(CalculateLengthOfSrc):
-	xor	%eax, %eax
-	cmpb	$0, (%edx)
-	jz	L(exit_tail0)
-	cmpb	$0, 1(%edx)
-	jz	L(exit_tail1)
-	cmpb	$0, 2(%edx)
-	jz	L(exit_tail2)
-	cmpb	$0, 3(%edx)
-	jz	L(exit_tail3)
-
-	cmpb	$0, 4(%edx)
-	jz	L(exit_tail4)
-	cmpb	$0, 5(%edx)
-	jz	L(exit_tail5)
-	cmpb	$0, 6(%edx)
-	jz	L(exit_tail6)
-	cmpb	$0, 7(%edx)
-	jz	L(exit_tail7)
-
-	cmpb	$0, 8(%edx)
-	jz	L(exit_tail8)
-	cmpb	$0, 9(%edx)
-	jz	L(exit_tail9)
-	cmpb	$0, 10(%edx)
-	jz	L(exit_tail10)
-	cmpb	$0, 11(%edx)
-	jz	L(exit_tail11)
-
-	cmpb	$0, 12(%edx)
-	jz	L(exit_tail12)
-	cmpb	$0, 13(%edx)
-	jz	L(exit_tail13)
-	cmpb	$0, 14(%edx)
-	jz	L(exit_tail14)
-	cmpb	$0, 15(%edx)
-	jz	L(exit_tail15)
-
-	pxor	%xmm0, %xmm0
-	lea	16(%edx), %eax
-	add	$16, %ecx
-	and	$-16, %eax
-
-	pcmpeqb	(%eax), %xmm0
-	pmovmskb %xmm0, %edx
-	pxor	%xmm1, %xmm1
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm1
-	pmovmskb %xmm1, %edx
-	pxor	%xmm2, %xmm2
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm2
-	pmovmskb %xmm2, %edx
-	pxor	%xmm3, %xmm3
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm0
-	pmovmskb %xmm0, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm1
-	pmovmskb %xmm1, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm2
-	pmovmskb %xmm2, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm0
-	pmovmskb %xmm0, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm1
-	pmovmskb %xmm1, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm2
-	pmovmskb %xmm2, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm0
-	pmovmskb %xmm0, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm1
-	pmovmskb %xmm1, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm2
-	pmovmskb %xmm2, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	16(%eax), %eax
-	test	%edx, %edx
-	jnz	L(exit)
-
-	and	$-0x40, %eax
-
-	.p2align 4
-L(aligned_64_loop):
-	movaps	(%eax), %xmm0
-	movaps	16(%eax), %xmm1
-	movaps	32(%eax), %xmm2
-	movaps	48(%eax), %xmm6
-	pminub	%xmm1, %xmm0
-	pminub	%xmm6, %xmm2
-	pminub	%xmm0, %xmm2
-	pcmpeqb	%xmm3, %xmm2
-	pmovmskb %xmm2, %edx
-	lea	64(%eax), %eax
-	test	%edx, %edx
-	jz	L(aligned_64_loop)
-
-	pcmpeqb	-64(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	48(%ecx), %ecx
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	%xmm1, %xmm3
-	pmovmskb %xmm3, %edx
-	lea	-16(%ecx), %ecx
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	-32(%eax), %xmm3
-	pmovmskb %xmm3, %edx
-	lea	-16(%ecx), %ecx
-	test	%edx, %edx
-	jnz	L(exit)
-
-	pcmpeqb	%xmm6, %xmm3
-	pmovmskb %xmm3, %edx
-	lea	-16(%ecx), %ecx
-
-	.p2align 4
-L(exit):
-	sub	%ecx, %eax
-	test	%dl, %dl
-	jz	L(exit_more_8)
-
-	mov	%dl, %cl
-	and	$15, %cl
-	jz	L(exit_more_4)
-	test	$0x01, %dl
-	jnz	L(exit_0)
-	test	$0x02, %dl
-	jnz	L(exit_1)
-	test	$0x04, %dl
-	jnz	L(exit_2)
-	add	$3, %eax
-	RETURN
-
-	.p2align 4
-L(exit_more_4):
-	test	$0x10, %dl
-	jnz	L(exit_4)
-	test	$0x20, %dl
-	jnz	L(exit_5)
-	test	$0x40, %dl
-	jnz	L(exit_6)
-	add	$7, %eax
-	RETURN
-
-	.p2align 4
-L(exit_more_8):
-	mov	%dh, %ch
-	and	$15, %ch
-	jz	L(exit_more_12)
-	test	$0x01, %dh
-	jnz	L(exit_8)
-	test	$0x02, %dh
-	jnz	L(exit_9)
-	test	$0x04, %dh
-	jnz	L(exit_10)
-	add	$11, %eax
-	RETURN
-
-	.p2align 4
-L(exit_more_12):
-	test	$0x10, %dh
-	jnz	L(exit_12)
-	test	$0x20, %dh
-	jnz	L(exit_13)
-	test	$0x40, %dh
-	jnz	L(exit_14)
-	add	$15, %eax
-L(exit_0):
-	RETURN
-
-	.p2align 4
-L(exit_1):
-	add	$1, %eax
-	RETURN
-
-L(exit_2):
-	add	$2, %eax
-	RETURN
-
-L(exit_3):
-	add	$3, %eax
-	RETURN
-
-L(exit_4):
-	add	$4, %eax
-	RETURN
-
-L(exit_5):
-	add	$5, %eax
-	RETURN
-
-L(exit_6):
-	add	$6, %eax
-	RETURN
-
-L(exit_7):
-	add	$7, %eax
-	RETURN
-
-L(exit_8):
-	add	$8, %eax
-	RETURN
-
-L(exit_9):
-	add	$9, %eax
-	RETURN
-
-L(exit_10):
-	add	$10, %eax
-	RETURN
-
-L(exit_11):
-	add	$11, %eax
-	RETURN
-
-L(exit_12):
-	add	$12, %eax
-	RETURN
-
-L(exit_13):
-	add	$13, %eax
-	RETURN
-
-L(exit_14):
-	add	$14, %eax
-	RETURN
-
-L(exit_15):
-	add	$15, %eax
-	RETURN
-
-L(exit_tail0):
-	mov	%edx, %eax
-	sub	%ecx, %eax
-	RETURN
-
-	.p2align 4
-L(exit_tail1):
-	lea	1(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail2):
-	lea	2(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail3):
-	lea	3(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail4):
-	lea	4(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail5):
-	lea	5(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail6):
-	lea	6(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail7):
-	lea	7(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail8):
-	lea	8(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail9):
-	lea	9(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail10):
-	lea	10(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail11):
-	lea	11(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail12):
-	lea	12(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail13):
-	lea	13(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail14):
-	lea	14(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-L(exit_tail15):
-	lea	15(%edx), %eax
-	sub	%ecx, %eax
-	RETURN
-
-END (STRCPY)
-
diff --git a/libc/arch-x86/string/ssse3-strncat-atom.S b/libc/arch-x86/string/ssse3-strncat-atom.S
index ccb08a7..5618771 100644
--- a/libc/arch-x86/string/ssse3-strncat-atom.S
+++ b/libc/arch-x86/string/ssse3-strncat-atom.S
@@ -28,7 +28,7 @@
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#define STRCAT  strncat_ssse3
+#define STRCAT  strncat
 #define USE_AS_STRNCAT
 
 #include "ssse3-strcat-atom.S"
diff --git a/libc/arch-x86/string/ssse3-strncmp-atom.S b/libc/arch-x86/string/ssse3-strncmp-atom.S
index 2bf5002..234f728 100644
--- a/libc/arch-x86/string/ssse3-strncmp-atom.S
+++ b/libc/arch-x86/string/ssse3-strncmp-atom.S
@@ -30,6 +30,5 @@
 
 
 #define USE_AS_STRNCMP
-#define STRCMP  strncmp_ssse3
+#define STRCMP  strncmp
 #include "ssse3-strcmp-atom.S"
-
diff --git a/libc/arch-x86/string/ssse3-strncpy-atom.S b/libc/arch-x86/string/ssse3-strncpy-atom.S
deleted file mode 100644
index 0c27ffe..0000000
--- a/libc/arch-x86/string/ssse3-strncpy-atom.S
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-Copyright (c) 2011, 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 USE_AS_STRNCPY
-#define STRCPY strncpy_atom
-#include "ssse3-strcpy-atom.S"
diff --git a/libc/arch-x86/string/ssse3-wcscat-atom.S b/libc/arch-x86/string/ssse3-wcscat-atom.S
deleted file mode 100644
index a307983..0000000
--- a/libc/arch-x86/string/ssse3-wcscat-atom.S
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
-Copyright (c) 2011 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.
-*/
-
-#ifndef L
-# define L(label)	.L##label
-#endif
-
-#ifndef cfi_startproc
-# define cfi_startproc                  .cfi_startproc
-#endif
-
-#ifndef cfi_endproc
-# define cfi_endproc                    .cfi_endproc
-#endif
-
-#ifndef cfi_rel_offset
-# define cfi_rel_offset(reg, off)	.cfi_rel_offset reg, off
-#endif
-
-#ifndef cfi_restore
-# define cfi_restore(reg)	.cfi_restore reg
-#endif
-
-#ifndef cfi_adjust_cfa_offset
-# define cfi_adjust_cfa_offset(off)	.cfi_adjust_cfa_offset off
-#endif
-
-#ifndef ENTRY
-# define ENTRY(name)	\
-	.type name,  @function;	\
-	.globl name;	\
-	.p2align 4;	\
-name:	\
-	cfi_startproc
-#endif
-
-#ifndef END
-# define END(name)	\
-	cfi_endproc;	\
-	.size name, .-name
-#endif
-
-#define CFI_PUSH(REG)	\
-	cfi_adjust_cfa_offset (4);	\
-	cfi_rel_offset (REG, 0)
-
-#define CFI_POP(REG)	\
-	cfi_adjust_cfa_offset (-4);	\
-	cfi_restore (REG)
-
-#define PUSH(REG)	pushl REG;	CFI_PUSH (REG)
-#define POP(REG)	popl REG;	CFI_POP (REG)
-
-#define PARMS  4
-#define STR1  PARMS+4
-#define STR2  STR1+4
-
-#define USE_AS_WCSCAT
-
-.text
-ENTRY (wcscat_ssse3)
-	PUSH    (%edi)
-	mov	STR1(%esp), %edi
-	mov	%edi, %edx
-
-#define RETURN  jmp L(WcscpyAtom)
-#include "sse2-wcslen-atom.S"
-
-L(WcscpyAtom):
-	shl	$2, %eax
-	mov	STR2(%esp), %ecx
-	lea	(%edi, %eax), %edx
-
-	cmpl	$0, (%ecx)
-	jz	L(Exit4)
-	cmpl	$0, 4(%ecx)
-	jz	L(Exit8)
-	cmpl	$0, 8(%ecx)
-	jz	L(Exit12)
-	cmpl	$0, 12(%ecx)
-	jz	L(Exit16)
-
-#undef RETURN
-#define RETURN  POP(%edi);	ret;	CFI_PUSH(%edi)
-#include "ssse3-wcscpy-atom.S"
-
-END (wcscat_ssse3)
diff --git a/libc/arch-x86/string/ssse3-wcscpy-atom.S b/libc/arch-x86/string/ssse3-wcscpy-atom.S
deleted file mode 100644
index 80aa15f..0000000
--- a/libc/arch-x86/string/ssse3-wcscpy-atom.S
+++ /dev/null
@@ -1,652 +0,0 @@
-/*
-Copyright (c) 2011, 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.
-*/
-
-#ifndef USE_AS_WCSCAT
-
-# ifndef L
-#  define L(label)	.L##label
-# endif
-
-# ifndef cfi_startproc
-#  define cfi_startproc	.cfi_startproc
-# endif
-
-# ifndef cfi_endproc
-#  define cfi_endproc	.cfi_endproc
-# endif
-
-# ifndef cfi_rel_offset
-#  define cfi_rel_offset(reg, off)	.cfi_rel_offset reg, off
-# endif
-
-# ifndef cfi_restore
-#  define cfi_restore(reg)	.cfi_restore reg
-# endif
-
-# ifndef cfi_adjust_cfa_offset
-#  define cfi_adjust_cfa_offset(off)	.cfi_adjust_cfa_offset off
-# endif
-
-# ifndef ENTRY
-#  define ENTRY(name)	\
-	.type name, @function;	\
-	.globl name;	\
-	.p2align 4;	\
-name:	\
-	cfi_startproc
-# endif
-
-# ifndef END
-#  define END(name)	\
-	cfi_endproc;	\
-	.size name, .-name
-# endif
-
-# define CFI_PUSH(REG)	\
-	cfi_adjust_cfa_offset (4);	\
-	cfi_rel_offset (REG, 0)
-
-# define CFI_POP(REG)	\
-	cfi_adjust_cfa_offset (-4);	\
-	cfi_restore (REG)
-
-# define PUSH(REG)	pushl REG; CFI_PUSH (REG)
-# define POP(REG)	popl REG; CFI_POP (REG)
-
-# define PARMS	4
-# define RETURN	POP (%edi); ret; CFI_PUSH (%edi)
-
-# define STR1	PARMS
-# define STR2	STR1+4
-# define LEN	STR2+4
-
-.text
-ENTRY (wcscpy_ssse3)
-	mov	STR1(%esp), %edx
-	mov	STR2(%esp), %ecx
-
-	cmpl	$0, (%ecx)
-	jz	L(ExitTail4)
-	cmpl	$0, 4(%ecx)
-	jz	L(ExitTail8)
-	cmpl	$0, 8(%ecx)
-	jz	L(ExitTail12)
-	cmpl	$0, 12(%ecx)
-	jz	L(ExitTail16)
-
-	PUSH	(%edi)
-	mov	%edx, %edi
-#endif
-	PUSH	(%esi)
-	lea	16(%ecx), %esi
-
-	and	$-16, %esi
-
-	pxor	%xmm0, %xmm0
-	pcmpeqd	(%esi), %xmm0
-	movdqu	(%ecx), %xmm1
-	movdqu	%xmm1, (%edx)
-
-	pmovmskb %xmm0, %eax
-	sub	%ecx, %esi
-
-	test	%eax, %eax
-	jnz	L(CopyFrom1To16Bytes)
-
-	mov	%edx, %eax
-	lea	16(%edx), %edx
-	and	$-16, %edx
-	sub	%edx, %eax
-
-	sub	%eax, %ecx
-	mov	%ecx, %eax
-	and	$0xf, %eax
-	mov	$0, %esi
-
-	jz	L(Align16Both)
-	cmp	$4, %eax
-	je	L(Shl4)
-	cmp	$8, %eax
-	je	L(Shl8)
-	jmp	L(Shl12)
-
-L(Align16Both):
-	movaps	(%ecx), %xmm1
-	movaps	16(%ecx), %xmm2
-	movaps	%xmm1, (%edx)
-	pcmpeqd	%xmm2, %xmm0
-	pmovmskb %xmm0, %eax
-	lea	16(%esi), %esi
-
-	test	%eax, %eax
-	jnz	L(CopyFrom1To16Bytes)
-
-	movaps	16(%ecx, %esi), %xmm3
-	movaps	%xmm2, (%edx, %esi)
-	pcmpeqd	%xmm3, %xmm0
-	pmovmskb %xmm0, %eax
-	lea	16(%esi), %esi
-
-	test	%eax, %eax
-	jnz	L(CopyFrom1To16Bytes)
-
-	movaps	16(%ecx, %esi), %xmm4
-	movaps	%xmm3, (%edx, %esi)
-	pcmpeqd	%xmm4, %xmm0
-	pmovmskb %xmm0, %eax
-	lea	16(%esi), %esi
-
-	test	%eax, %eax
-	jnz	L(CopyFrom1To16Bytes)
-
-	movaps	16(%ecx, %esi), %xmm1
-	movaps	%xmm4, (%edx, %esi)
-	pcmpeqd	%xmm1, %xmm0
-	pmovmskb %xmm0, %eax
-	lea	16(%esi), %esi
-
-	test	%eax, %eax
-	jnz	L(CopyFrom1To16Bytes)
-
-	movaps	16(%ecx, %esi), %xmm2
-	movaps	%xmm1, (%edx, %esi)
-	pcmpeqd	%xmm2, %xmm0
-	pmovmskb %xmm0, %eax
-	lea	16(%esi), %esi
-
-	test	%eax, %eax
-	jnz	L(CopyFrom1To16Bytes)
-
-	movaps	16(%ecx, %esi), %xmm3
-	movaps	%xmm2, (%edx, %esi)
-	pcmpeqd	%xmm3, %xmm0
-	pmovmskb %xmm0, %eax
-	lea	16(%esi), %esi
-
-	test	%eax, %eax
-	jnz	L(CopyFrom1To16Bytes)
-
-	movaps	%xmm3, (%edx, %esi)
-	mov	%ecx, %eax
-	lea	16(%ecx, %esi), %ecx
-	and	$-0x40, %ecx
-	sub	%ecx, %eax
-	sub	%eax, %edx
-
-	mov	$-0x40, %esi
-
-L(Aligned64Loop):
-	movaps	(%ecx), %xmm2
-	movaps	32(%ecx), %xmm3
-	movaps	%xmm2, %xmm4
-	movaps	16(%ecx), %xmm5
-	movaps	%xmm3, %xmm6
-	movaps	48(%ecx), %xmm7
-	pminub	%xmm5, %xmm2
-	pminub	%xmm7, %xmm3
-	pminub	%xmm2, %xmm3
-	lea	64(%edx), %edx
-	pcmpeqd	%xmm0, %xmm3
-	lea	64(%ecx), %ecx
-	pmovmskb %xmm3, %eax
-
-	test	%eax, %eax
-	jnz	L(Aligned64Leave)
-	movaps	%xmm4, -64(%edx)
-	movaps	%xmm5, -48(%edx)
-	movaps	%xmm6, -32(%edx)
-	movaps	%xmm7, -16(%edx)
-	jmp	L(Aligned64Loop)
-
-L(Aligned64Leave):
-	pcmpeqd	%xmm4, %xmm0
-	pmovmskb %xmm0, %eax
-	test	%eax, %eax
-	jnz	L(CopyFrom1To16Bytes)
-
-	pcmpeqd	%xmm5, %xmm0
-	pmovmskb %xmm0, %eax
-	movaps	%xmm4, -64(%edx)
-	lea	16(%esi), %esi
-	test	%eax, %eax
-	jnz	L(CopyFrom1To16Bytes)
-
-	pcmpeqd	%xmm6, %xmm0
-	pmovmskb %xmm0, %eax
-	movaps	%xmm5, -48(%edx)
-	lea	16(%esi), %esi
-	test	%eax, %eax
-	jnz	L(CopyFrom1To16Bytes)
-
-	movaps	%xmm6, -32(%edx)
-	pcmpeqd	%xmm7, %xmm0
-	pmovmskb %xmm0, %eax
-	lea	16(%esi), %esi
-	test	%eax, %eax
-	jnz	L(CopyFrom1To16Bytes)
-
-	mov	$-0x40, %esi
-	movaps	%xmm7, -16(%edx)
-	jmp	L(Aligned64Loop)
-
-	.p2align 4
-L(Shl4):
-	movaps	-4(%ecx), %xmm1
-	movaps	12(%ecx), %xmm2
-L(Shl4Start):
-	pcmpeqd	%xmm2, %xmm0
-	pmovmskb %xmm0, %eax
-	movaps	%xmm2, %xmm3
-
-	test	%eax, %eax
-	jnz	L(Shl4LoopExit)
-
-	palignr	$4, %xmm1, %xmm2
-	movaps	%xmm2, (%edx)
-	movaps	28(%ecx), %xmm2
-
-	pcmpeqd	%xmm2, %xmm0
-	lea	16(%edx), %edx
-	pmovmskb %xmm0, %eax
-	lea	16(%ecx), %ecx
-	movaps	%xmm2, %xmm1
-
-	test	%eax, %eax
-	jnz	L(Shl4LoopExit)
-
-	palignr	$4, %xmm3, %xmm2
-	movaps	%xmm2, (%edx)
-	movaps	28(%ecx), %xmm2
-
-	pcmpeqd	%xmm2, %xmm0
-	lea	16(%edx), %edx
-	pmovmskb %xmm0, %eax
-	lea	16(%ecx), %ecx
-	movaps	%xmm2, %xmm3
-
-	test	%eax, %eax
-	jnz	L(Shl4LoopExit)
-
-	palignr	$4, %xmm1, %xmm2
-	movaps	%xmm2, (%edx)
-	movaps	28(%ecx), %xmm2
-
-	pcmpeqd	%xmm2, %xmm0
-	lea	16(%edx), %edx
-	pmovmskb %xmm0, %eax
-	lea	16(%ecx), %ecx
-
-	test	%eax, %eax
-	jnz	L(Shl4LoopExit)
-
-	palignr	$4, %xmm3, %xmm2
-	movaps	%xmm2, (%edx)
-	lea	28(%ecx), %ecx
-	lea	16(%edx), %edx
-
-	mov	%ecx, %eax
-	and	$-0x40, %ecx
-	sub	%ecx, %eax
-	lea	-12(%ecx), %ecx
-	sub	%eax, %edx
-
-	movaps	-4(%ecx), %xmm1
-
-L(Shl4LoopStart):
-	movaps	12(%ecx), %xmm2
-	movaps	28(%ecx), %xmm3
-	movaps	%xmm3, %xmm6
-	movaps	44(%ecx), %xmm4
-	movaps	%xmm4, %xmm7
-	movaps	60(%ecx), %xmm5
-	pminub	%xmm2, %xmm6
-	pminub	%xmm5, %xmm7
-	pminub	%xmm6, %xmm7
-	pcmpeqd	%xmm0, %xmm7
-	pmovmskb %xmm7, %eax
-	movaps	%xmm5, %xmm7
-	palignr	$4, %xmm4, %xmm5
-	palignr	$4, %xmm3, %xmm4
-	test	%eax, %eax
-	jnz	L(Shl4Start)
-
-	palignr	$4, %xmm2, %xmm3
-	lea	64(%ecx), %ecx
-	palignr	$4, %xmm1, %xmm2
-	movaps	%xmm7, %xmm1
-	movaps	%xmm5, 48(%edx)
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	jmp	L(Shl4LoopStart)
-
-L(Shl4LoopExit):
-	movlpd	(%ecx), %xmm0
-	movl	8(%ecx), %esi
-	movlpd	%xmm0, (%edx)
-	movl	%esi, 8(%edx)
-	POP	(%esi)
-	add	$12, %edx
-	add	$12, %ecx
-	test	%al, %al
-	jz	L(ExitHigh)
-	test	$0x01, %al
-	jnz	L(Exit4)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	%edi, %eax
-	RETURN
-
-	CFI_PUSH	(%esi)
-
-	.p2align 4
-L(Shl8):
-	movaps	-8(%ecx), %xmm1
-	movaps	8(%ecx), %xmm2
-L(Shl8Start):
-	pcmpeqd	%xmm2, %xmm0
-	pmovmskb %xmm0, %eax
-	movaps	%xmm2, %xmm3
-
-	test	%eax, %eax
-	jnz	L(Shl8LoopExit)
-
-	palignr	$8, %xmm1, %xmm2
-	movaps	%xmm2, (%edx)
-	movaps	24(%ecx), %xmm2
-
-	pcmpeqd	%xmm2, %xmm0
-	lea	16(%edx), %edx
-	pmovmskb %xmm0, %eax
-	lea	16(%ecx), %ecx
-	movaps	%xmm2, %xmm1
-
-	test	%eax, %eax
-	jnz	L(Shl8LoopExit)
-
-	palignr	$8, %xmm3, %xmm2
-	movaps	%xmm2, (%edx)
-	movaps	24(%ecx), %xmm2
-
-	pcmpeqd	%xmm2, %xmm0
-	lea	16(%edx), %edx
-	pmovmskb %xmm0, %eax
-	lea	16(%ecx), %ecx
-	movaps	%xmm2, %xmm3
-
-	test	%eax, %eax
-	jnz	L(Shl8LoopExit)
-
-	palignr	$8, %xmm1, %xmm2
-	movaps	%xmm2, (%edx)
-	movaps	24(%ecx), %xmm2
-
-	pcmpeqd	%xmm2, %xmm0
-	lea	16(%edx), %edx
-	pmovmskb %xmm0, %eax
-	lea	16(%ecx), %ecx
-
-	test	%eax, %eax
-	jnz	L(Shl8LoopExit)
-
-	palignr	$8, %xmm3, %xmm2
-	movaps	%xmm2, (%edx)
-	lea	24(%ecx), %ecx
-	lea	16(%edx), %edx
-
-	mov	%ecx, %eax
-	and	$-0x40, %ecx
-	sub	%ecx, %eax
-	lea	-8(%ecx), %ecx
-	sub	%eax, %edx
-
-	movaps	-8(%ecx), %xmm1
-
-L(Shl8LoopStart):
-	movaps	8(%ecx), %xmm2
-	movaps	24(%ecx), %xmm3
-	movaps	%xmm3, %xmm6
-	movaps	40(%ecx), %xmm4
-	movaps	%xmm4, %xmm7
-	movaps	56(%ecx), %xmm5
-	pminub	%xmm2, %xmm6
-	pminub	%xmm5, %xmm7
-	pminub	%xmm6, %xmm7
-	pcmpeqd	%xmm0, %xmm7
-	pmovmskb %xmm7, %eax
-	movaps	%xmm5, %xmm7
-	palignr	$8, %xmm4, %xmm5
-	palignr	$8, %xmm3, %xmm4
-	test	%eax, %eax
-	jnz	L(Shl8Start)
-
-	palignr	$8, %xmm2, %xmm3
-	lea	64(%ecx), %ecx
-	palignr	$8, %xmm1, %xmm2
-	movaps	%xmm7, %xmm1
-	movaps	%xmm5, 48(%edx)
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	jmp	L(Shl8LoopStart)
-
-L(Shl8LoopExit):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	POP	(%esi)
-	add	$8, %edx
-	add	$8, %ecx
-	test	%al, %al
-	jz	L(ExitHigh)
-	test	$0x01, %al
-	jnz	L(Exit4)
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	%edi, %eax
-	RETURN
-
-	CFI_PUSH	(%esi)
-
-	.p2align 4
-L(Shl12):
-	movaps	-12(%ecx), %xmm1
-	movaps	4(%ecx), %xmm2
-L(Shl12Start):
-	pcmpeqd	%xmm2, %xmm0
-	pmovmskb %xmm0, %eax
-	movaps	%xmm2, %xmm3
-
-	test	%eax, %eax
-	jnz	L(Shl12LoopExit)
-
-	palignr	$12, %xmm1, %xmm2
-	movaps	%xmm2, (%edx)
-	movaps	20(%ecx), %xmm2
-
-	pcmpeqd	%xmm2, %xmm0
-	lea	16(%edx), %edx
-	pmovmskb %xmm0, %eax
-	lea	16(%ecx), %ecx
-	movaps	%xmm2, %xmm1
-
-	test	%eax, %eax
-	jnz	L(Shl12LoopExit)
-
-	palignr	$12, %xmm3, %xmm2
-	movaps	%xmm2, (%edx)
-	movaps	20(%ecx), %xmm2
-
-	pcmpeqd	%xmm2, %xmm0
-	lea	16(%edx), %edx
-	pmovmskb %xmm0, %eax
-	lea	16(%ecx), %ecx
-	movaps	%xmm2, %xmm3
-
-	test	%eax, %eax
-	jnz	L(Shl12LoopExit)
-
-	palignr	$12, %xmm1, %xmm2
-	movaps	%xmm2, (%edx)
-	movaps	20(%ecx), %xmm2
-
-	pcmpeqd	%xmm2, %xmm0
-	lea	16(%edx), %edx
-	pmovmskb %xmm0, %eax
-	lea	16(%ecx), %ecx
-
-	test	%eax, %eax
-	jnz	L(Shl12LoopExit)
-
-	palignr	$12, %xmm3, %xmm2
-	movaps	%xmm2, (%edx)
-	lea	20(%ecx), %ecx
-	lea	16(%edx), %edx
-
-	mov	%ecx, %eax
-	and	$-0x40, %ecx
-	sub	%ecx, %eax
-	lea	-4(%ecx), %ecx
-	sub	%eax, %edx
-
-	movaps	-12(%ecx), %xmm1
-
-L(Shl12LoopStart):
-	movaps	4(%ecx), %xmm2
-	movaps	20(%ecx), %xmm3
-	movaps	%xmm3, %xmm6
-	movaps	36(%ecx), %xmm4
-	movaps	%xmm4, %xmm7
-	movaps	52(%ecx), %xmm5
-	pminub	%xmm2, %xmm6
-	pminub	%xmm5, %xmm7
-	pminub	%xmm6, %xmm7
-	pcmpeqd	%xmm0, %xmm7
-	pmovmskb %xmm7, %eax
-	movaps	%xmm5, %xmm7
-	palignr	$12, %xmm4, %xmm5
-	palignr	$12, %xmm3, %xmm4
-	test	%eax, %eax
-	jnz	L(Shl12Start)
-
-	palignr	$12, %xmm2, %xmm3
-	lea	64(%ecx), %ecx
-	palignr	$12, %xmm1, %xmm2
-	movaps	%xmm7, %xmm1
-	movaps	%xmm5, 48(%edx)
-	movaps	%xmm4, 32(%edx)
-	movaps	%xmm3, 16(%edx)
-	movaps	%xmm2, (%edx)
-	lea	64(%edx), %edx
-	jmp	L(Shl12LoopStart)
-
-L(Shl12LoopExit):
-	movl	(%ecx), %esi
-	movl	%esi, (%edx)
-	mov	$4, %esi
-
-	.p2align 4
-L(CopyFrom1To16Bytes):
-	add	%esi, %edx
-	add	%esi, %ecx
-
-	POP	(%esi)
-	test	%al, %al
-	jz	L(ExitHigh)
-	test	$0x01, %al
-	jnz	L(Exit4)
-L(Exit8):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	%edi, %eax
-	RETURN
-
-	.p2align 4
-L(ExitHigh):
-	test	$0x01, %ah
-	jnz	L(Exit12)
-L(Exit16):
-	movdqu	(%ecx), %xmm0
-	movdqu	%xmm0, (%edx)
-	movl	%edi, %eax
-	RETURN
-
-	.p2align 4
-L(Exit4):
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movl	%edi, %eax
-	RETURN
-
-	.p2align 4
-L(Exit12):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	8(%ecx), %eax
-	movl	%eax, 8(%edx)
-	movl	%edi, %eax
-	RETURN
-
-CFI_POP	(%edi)
-
-	.p2align 4
-L(ExitTail4):
-	movl	(%ecx), %eax
-	movl	%eax, (%edx)
-	movl	%edx, %eax
-	ret
-
-	.p2align 4
-L(ExitTail8):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	%edx, %eax
-	ret
-
-	.p2align 4
-L(ExitTail12):
-	movlpd	(%ecx), %xmm0
-	movlpd	%xmm0, (%edx)
-	movl	8(%ecx), %eax
-	movl	%eax, 8(%edx)
-	movl	%edx, %eax
-	ret
-
-	.p2align 4
-L(ExitTail16):
-	movdqu	(%ecx), %xmm0
-	movdqu	%xmm0, (%edx)
-	movl	%edx, %eax
-	ret
-
-#ifndef USE_AS_WCSCAT
-END (wcscpy_ssse3)
-#endif
diff --git a/libc/arch-x86/string/ssse3-wmemcmp-atom.S b/libc/arch-x86/string/ssse3-wmemcmp-atom.S
deleted file mode 100644
index a81b78b..0000000
--- a/libc/arch-x86/string/ssse3-wmemcmp-atom.S
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-Copyright (c) 2011, 2012, 2013 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 MEMCMP  wmemcmp_atom
-
-#define USE_WCHAR
-#define USE_AS_WMEMCMP 1
-#include "ssse3-memcmp-atom.S"
diff --git a/libc/arch-x86_64/bionic/__set_tls.c b/libc/arch-x86_64/bionic/__set_tls.c
index 10fd36f..9460a03 100644
--- a/libc/arch-x86_64/bionic/__set_tls.c
+++ b/libc/arch-x86_64/bionic/__set_tls.c
@@ -27,11 +27,12 @@
  */
 
 #include <sys/cdefs.h>
-#include <asm/prctl.h>
-#include <stdint.h>
 
-extern int __arch_prctl(int, unsigned long);
+// ARCH_SET_FS is not exposed via <sys/prctl.h> or <linux/prctl.h>.
+#include <asm/prctl.h>
+
+extern int arch_prctl(int, unsigned long);
 
 __LIBC_HIDDEN__ int __set_tls(void* ptr) {
-  return __arch_prctl(ARCH_SET_FS, (uintptr_t) ptr);
+  return arch_prctl(ARCH_SET_FS, (unsigned long) ptr);
 }
diff --git a/libc/arch-x86_64/dynamic_function_dispatch.cpp b/libc/arch-x86_64/dynamic_function_dispatch.cpp
index c846ded..cbe68a3 100644
--- a/libc/arch-x86_64/dynamic_function_dispatch.cpp
+++ b/libc/arch-x86_64/dynamic_function_dispatch.cpp
@@ -32,18 +32,18 @@
 
 extern "C" {
 
-typedef int memset_func(void* __dst, int __ch, size_t __n);
 DEFINE_IFUNC_FOR(memset) {
   __builtin_cpu_init();
-  if (__builtin_cpu_supports("avx2")) RETURN_FUNC(memset_func, memset_avx2);
-  RETURN_FUNC(memset_func, memset_generic);
+  if (__builtin_cpu_supports("avx2")) RETURN_FUNC(memset_func_t, memset_avx2);
+  RETURN_FUNC(memset_func_t, memset_generic);
 }
+MEMSET_SHIM()
 
-typedef void* __memset_chk_func(void* s, int c, size_t n, size_t n2);
 DEFINE_IFUNC_FOR(__memset_chk) {
   __builtin_cpu_init();
-  if (__builtin_cpu_supports("avx2")) RETURN_FUNC(__memset_chk_func, __memset_chk_avx2);
-  RETURN_FUNC(__memset_chk_func, __memset_chk_generic);
+  if (__builtin_cpu_supports("avx2")) RETURN_FUNC(__memset_chk_func_t, __memset_chk_avx2);
+  RETURN_FUNC(__memset_chk_func_t, __memset_chk_generic);
 }
+__MEMSET_CHK_SHIM()
 
 }  // extern "C"
diff --git a/libc/arch-x86_64/static_function_dispatch.S b/libc/arch-x86_64/static_function_dispatch.S
deleted file mode 100644
index 93ff5f2..0000000
--- a/libc/arch-x86_64/static_function_dispatch.S
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2022 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 <private/bionic_asm.h>
-
-#define FUNCTION_DELEGATE(name, impl) \
-ENTRY(name); \
-    jmp impl; \
-END(name)
-
-FUNCTION_DELEGATE(memset, memset_generic)
-FUNCTION_DELEGATE(__memset_chk, __memset_chk_generic)
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
index 1b539f2..0d557f1 100644
--- a/libc/bionic/__libc_init_main_thread.cpp
+++ b/libc/bionic/__libc_init_main_thread.cpp
@@ -44,7 +44,7 @@
 // Declared in "private/bionic_ssp.h".
 uintptr_t __stack_chk_guard = 0;
 
-static pthread_internal_t main_thread;
+BIONIC_USED_BEFORE_LINKER_RELOCATES static pthread_internal_t main_thread;
 
 // Setup for the main thread. For dynamic executables, this is called by the
 // linker _before_ libc is mapped in memory. This means that all writes to
diff --git a/libc/bionic/android_mallopt.cpp b/libc/bionic/android_mallopt.cpp
new file mode 100644
index 0000000..79e4072
--- /dev/null
+++ b/libc/bionic/android_mallopt.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <stdatomic.h>
+
+#include <platform/bionic/malloc.h>
+#include <private/bionic_globals.h>
+
+#include "gwp_asan_wrappers.h"
+#include "malloc_limit.h"
+
+#if !defined(LIBC_STATIC)
+#include <stdio.h>
+
+#include <private/bionic_defs.h>
+
+#include "malloc_heapprofd.h"
+
+extern bool gZygoteChild;
+extern _Atomic bool gZygoteChildProfileable;
+
+bool WriteMallocLeakInfo(FILE* fp);
+bool GetMallocLeakInfo(android_mallopt_leak_info_t* leak_info);
+bool FreeMallocLeakInfo(android_mallopt_leak_info_t* leak_info);
+#endif
+
+// =============================================================================
+// Platform-internal mallopt variant.
+// =============================================================================
+#if !defined(LIBC_STATIC)
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+#endif
+extern "C" bool android_mallopt(int opcode, void* arg, size_t arg_size) {
+  // Functionality available in both static and dynamic libc.
+  if (opcode == M_GET_DECAY_TIME_ENABLED) {
+    if (arg == nullptr || arg_size != sizeof(bool)) {
+      errno = EINVAL;
+      return false;
+    }
+    *reinterpret_cast<bool*>(arg) = atomic_load(&__libc_globals->decay_time_enabled);
+    return true;
+  }
+  if (opcode == M_INITIALIZE_GWP_ASAN) {
+    if (arg == nullptr || arg_size != sizeof(android_mallopt_gwp_asan_options_t)) {
+      errno = EINVAL;
+      return false;
+    }
+
+    return EnableGwpAsan(*reinterpret_cast<android_mallopt_gwp_asan_options_t*>(arg));
+  }
+  if (opcode == M_MEMTAG_STACK_IS_ON) {
+    if (arg == nullptr || arg_size != sizeof(bool)) {
+      errno = EINVAL;
+      return false;
+    }
+    *reinterpret_cast<bool*>(arg) = atomic_load(&__libc_memtag_stack);
+    return true;
+  }
+  if (opcode == M_SET_ALLOCATION_LIMIT_BYTES) {
+    return LimitEnable(arg, arg_size);
+  }
+
+#if defined(LIBC_STATIC)
+  errno = ENOTSUP;
+  return false;
+#else
+  if (opcode == M_SET_ZYGOTE_CHILD) {
+    if (arg != nullptr || arg_size != 0) {
+      errno = EINVAL;
+      return false;
+    }
+    gZygoteChild = true;
+    return true;
+  }
+  if (opcode == M_INIT_ZYGOTE_CHILD_PROFILING) {
+    if (arg != nullptr || arg_size != 0) {
+      errno = EINVAL;
+      return false;
+    }
+    atomic_store_explicit(&gZygoteChildProfileable, true, memory_order_release);
+    // Also check if heapprofd should start profiling from app startup.
+    HeapprofdInitZygoteChildProfiling();
+    return true;
+  }
+  if (opcode == M_GET_PROCESS_PROFILEABLE) {
+    if (arg == nullptr || arg_size != sizeof(bool)) {
+      errno = EINVAL;
+      return false;
+    }
+    // Native processes are considered profileable. Zygote children are considered
+    // profileable only when appropriately tagged.
+    *reinterpret_cast<bool*>(arg) =
+        !gZygoteChild || atomic_load_explicit(&gZygoteChildProfileable, memory_order_acquire);
+    return true;
+  }
+  if (opcode == M_WRITE_MALLOC_LEAK_INFO_TO_FILE) {
+    if (arg == nullptr || arg_size != sizeof(FILE*)) {
+      errno = EINVAL;
+      return false;
+    }
+    return WriteMallocLeakInfo(reinterpret_cast<FILE*>(arg));
+  }
+  if (opcode == M_GET_MALLOC_LEAK_INFO) {
+    if (arg == nullptr || arg_size != sizeof(android_mallopt_leak_info_t)) {
+      errno = EINVAL;
+      return false;
+    }
+    return GetMallocLeakInfo(reinterpret_cast<android_mallopt_leak_info_t*>(arg));
+  }
+  if (opcode == M_FREE_MALLOC_LEAK_INFO) {
+    if (arg == nullptr || arg_size != sizeof(android_mallopt_leak_info_t)) {
+      errno = EINVAL;
+      return false;
+    }
+    return FreeMallocLeakInfo(reinterpret_cast<android_mallopt_leak_info_t*>(arg));
+  }
+  // Try heapprofd's mallopt, as it handles options not covered here.
+  return HeapprofdMallopt(opcode, arg, arg_size);
+#endif
+}
diff --git a/libc/bionic/bionic_call_ifunc_resolver.cpp b/libc/bionic/bionic_call_ifunc_resolver.cpp
index e44d998..d5a812c 100644
--- a/libc/bionic/bionic_call_ifunc_resolver.cpp
+++ b/libc/bionic/bionic_call_ifunc_resolver.cpp
@@ -31,6 +31,7 @@
 #include <sys/hwprobe.h>
 #include <sys/ifunc.h>
 
+#include "bionic/macros.h"
 #include "private/bionic_auxv.h"
 
 // This code is called in the linker before it has been relocated, so minimize calls into other
@@ -40,8 +41,8 @@
 ElfW(Addr) __bionic_call_ifunc_resolver(ElfW(Addr) resolver_addr) {
 #if defined(__aarch64__)
   typedef ElfW(Addr) (*ifunc_resolver_t)(uint64_t, __ifunc_arg_t*);
-  static __ifunc_arg_t arg;
-  static bool initialized = false;
+  BIONIC_USED_BEFORE_LINKER_RELOCATES static __ifunc_arg_t arg;
+  BIONIC_USED_BEFORE_LINKER_RELOCATES static bool initialized = false;
   if (!initialized) {
     initialized = true;
     arg._size = sizeof(__ifunc_arg_t);
diff --git a/libc/bionic/clock.cpp b/libc/bionic/clock.cpp
index 31e6c3c..45d29b7 100644
--- a/libc/bionic/clock.cpp
+++ b/libc/bionic/clock.cpp
@@ -32,7 +32,7 @@
 
 #include "private/bionic_constants.h"
 
-// http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock.html
+// https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/clock.html
 clock_t clock() {
   timespec ts;
   clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
diff --git a/libc/bionic/fts.c b/libc/bionic/fts.c
index 1287267..c36835e 100644
--- a/libc/bionic/fts.c
+++ b/libc/bionic/fts.c
@@ -29,7 +29,6 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/param.h>	/* ALIGN */
 #include <sys/stat.h>
 
 #include <dirent.h>
@@ -37,6 +36,7 @@
 #include <fcntl.h>
 #include <fts.h>
 #include <limits.h>
+#include <stdalign.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -912,10 +912,14 @@
 	 * be careful that the stat structure is reasonably aligned.  Since the
 	 * fts_name field is declared to be of size 1, the fts_name pointer is
 	 * namelen + 2 before the first possible address of the stat structure.
+	 *
+	 * We can't use the same trick FreeBSD uses here because our fts_name
+	 * is a char[1] rather than a char*. This is also the reason we don't
+	 * need to say `namelen + 1`. We just assume the worst alignment.
 	 */
 	len = sizeof(FTSENT) + namelen;
 	if (!ISSET(FTS_NOSTAT))
-		len += sizeof(struct stat) + ALIGNBYTES;
+		len += alignof(struct stat) + sizeof(struct stat);
 	if ((p = calloc(1, len)) == NULL)
 		return (NULL);
 
@@ -923,7 +927,7 @@
 	p->fts_namelen = namelen;
 	p->fts_instr = FTS_NOINSTR;
 	if (!ISSET(FTS_NOSTAT))
-		p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2);
+		p->fts_statp = (struct stat *)__builtin_align_up(p->fts_name + namelen + 2, alignof(struct stat));
 	memcpy(p->fts_name, name, namelen);
 
 	return (p);
diff --git a/libc/bionic/getauxval.cpp b/libc/bionic/getauxval.cpp
index e188d73..51ff949 100644
--- a/libc/bionic/getauxval.cpp
+++ b/libc/bionic/getauxval.cpp
@@ -26,14 +26,12 @@
  * SUCH DAMAGE.
  */
 
-#include <stddef.h>
-#include <sys/cdefs.h>
-#include <sys/auxv.h>
-#include <private/bionic_auxv.h>
-#include <private/bionic_globals.h>
-#include <private/bionic_ifuncs.h>
 #include <elf.h>
 #include <errno.h>
+#include <private/bionic_auxv.h>
+#include <private/bionic_globals.h>
+#include <stddef.h>
+#include <sys/auxv.h>
 
 // This function needs to be safe to call before TLS is set up, so it can't
 // access errno or the stack protector.
diff --git a/libc/bionic/icu_wrappers.cpp b/libc/bionic/icu_wrappers.cpp
index d9f2745..523f5a6 100644
--- a/libc/bionic/icu_wrappers.cpp
+++ b/libc/bionic/icu_wrappers.cpp
@@ -40,10 +40,3 @@
       reinterpret_cast<u_getIntPropertyValue_t>(__find_icu_symbol("u_getIntPropertyValue"));
   return u_getIntPropertyValue ? u_getIntPropertyValue(wc, property) : 0;
 }
-
-bool __icu_hasBinaryProperty(wint_t wc, UProperty property, int (*fallback)(int)) {
-  typedef UBool (*u_hasBinaryProperty_t)(UChar32, UProperty);
-  static auto u_hasBinaryProperty =
-      reinterpret_cast<u_hasBinaryProperty_t>(__find_icu_symbol("u_hasBinaryProperty"));
-  return u_hasBinaryProperty ? u_hasBinaryProperty(wc, property) : fallback(wc);
-}
diff --git a/libc/bionic/jemalloc_wrapper.cpp b/libc/bionic/jemalloc_wrapper.cpp
index 1bbdb29..63c9fab 100644
--- a/libc/bionic/jemalloc_wrapper.cpp
+++ b/libc/bionic/jemalloc_wrapper.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <errno.h>
+#include <inttypes.h>
 #include <malloc.h>
 #include <sys/param.h>
 #include <unistd.h>
@@ -30,6 +31,7 @@
 size_t je_mallinfo_nbins();
 struct mallinfo je_mallinfo_arena_info(size_t);
 struct mallinfo je_mallinfo_bin_info(size_t, size_t);
+void je_stats_arena(size_t arena_index, void (*callback)(size_t, size_t, size_t));
 
 __END_DECLS
 
@@ -136,29 +138,24 @@
     }
     return 1;
   } else if (param == M_LOG_STATS) {
+    size_t total_bytes = 0;
     for (size_t i = 0; i < je_mallinfo_narenas(); i++) {
       struct mallinfo mi = je_mallinfo_arena_info(i);
-      if (mi.hblkhd != 0) {
-        async_safe_format_log(ANDROID_LOG_INFO, "jemalloc",
-                              "Arena %zu: large bytes %zu huge bytes %zu bin bytes %zu", i,
-                              mi.ordblks, mi.uordblks, mi.fsmblks);
+      size_t arena_bytes = mi.fsmblks + mi.ordblks + mi.uordblks;
+      async_safe_format_log(ANDROID_LOG_INFO, "jemalloc",
+                            "Arena %zu: bin bytes=%zu large bytes=%zu total bytes=%zu", i,
+                            mi.fsmblks, mi.ordblks, arena_bytes);
 
-        for (size_t j = 0; j < je_mallinfo_nbins(); j++) {
-          struct mallinfo mi = je_mallinfo_bin_info(i, j);
-          if (mi.ordblks != 0) {
-            size_t total_allocs = 1;
-            if (mi.uordblks > mi.fordblks) {
-              total_allocs = mi.uordblks - mi.fordblks;
-            }
-            size_t bin_size = mi.ordblks / total_allocs;
-            async_safe_format_log(
-                ANDROID_LOG_INFO, "jemalloc",
-                "  Bin %zu (%zu bytes): allocated bytes %zu nmalloc %zu ndalloc %zu", j, bin_size,
-                mi.ordblks, mi.uordblks, mi.fordblks);
-          }
+      je_stats_arena(i, [](size_t index, size_t size, size_t allocs) {
+        if (allocs != 0) {
+          async_safe_format_log(ANDROID_LOG_INFO, "jemalloc",
+                                "  Size Class %zu(%zu bytes): allocs=%zu total bytes=%zu", index,
+                                size, allocs, allocs * size);
         }
-      }
+      });
+      total_bytes += arena_bytes;
     }
+    async_safe_format_log(ANDROID_LOG_INFO, "jemalloc", "Total Bytes=%zu", total_bytes);
     return 1;
   }
 
diff --git a/libc/bionic/langinfo.cpp b/libc/bionic/langinfo.cpp
index 6f5057c..9645475 100644
--- a/libc/bionic/langinfo.cpp
+++ b/libc/bionic/langinfo.cpp
@@ -98,6 +98,4 @@
   return const_cast<char*>(result);
 }
 
-char* nl_langinfo_l(nl_item item, locale_t) {
-  return nl_langinfo(item);
-}
+__strong_alias(nl_langinfo_l, nl_langinfo)
diff --git a/libc/bionic/time_l.cpp b/libc/bionic/lchmod.cpp
similarity index 84%
rename from libc/bionic/time_l.cpp
rename to libc/bionic/lchmod.cpp
index e5fa9a5..928a724 100644
--- a/libc/bionic/time_l.cpp
+++ b/libc/bionic/lchmod.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,9 +26,11 @@
  * SUCH DAMAGE.
  */
 
-#include <time.h>
-//#include <xlocale.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
 
-char* strptime_l(const char* buf, const char* fmt, struct tm* tm, locale_t) {
-  return strptime(buf, fmt, tm);
+int lchmod(const char* path, mode_t mode) {
+  return fchmodat(AT_FDCWD, path, mode, AT_SYMLINK_NOFOLLOW);
 }
diff --git a/libc/bionic/legacy_32_bit_support.cpp b/libc/bionic/legacy_32_bit_support.cpp
index 4e19ebf..e66126b 100644
--- a/libc/bionic/legacy_32_bit_support.cpp
+++ b/libc/bionic/legacy_32_bit_support.cpp
@@ -161,3 +161,9 @@
   }
   return __mremap(old_address, old_size, new_size, flags, new_address);
 }
+
+// mseal(2) is LP64-only.
+int mseal(void*, size_t, unsigned long) {
+  errno = ENOSYS;
+  return -1;
+}
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index 8c7a49b..94ba7e4 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -210,9 +210,9 @@
 
 extern "C" void scudo_malloc_set_add_large_allocation_slack(int add_slack);
 
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE void __libc_set_target_sdk_version(int target __unused) {
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE void __libc_set_target_sdk_version(int target_api_level __unused) {
 #if defined(USE_SCUDO) && !__has_feature(hwaddress_sanitizer)
-  scudo_malloc_set_add_large_allocation_slack(target < __ANDROID_API_S__);
+  scudo_malloc_set_add_large_allocation_slack(target_api_level < 31);
 #endif
 }
 
diff --git a/libc/bionic/libc_init_mte.cpp b/libc/bionic/libc_init_mte.cpp
new file mode 100644
index 0000000..3c8ef7d
--- /dev/null
+++ b/libc/bionic/libc_init_mte.cpp
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2024 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 <android/api-level.h>
+#include <elf.h>
+#include <errno.h>
+#include <malloc.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/auxv.h>
+#include <sys/mman.h>
+
+#include "async_safe/log.h"
+#include "heap_tagging.h"
+#include "libc_init_common.h"
+#include "platform/bionic/macros.h"
+#include "platform/bionic/mte.h"
+#include "platform/bionic/page.h"
+#include "platform/bionic/reserved_signals.h"
+#include "private/KernelArgumentBlock.h"
+#include "private/bionic_asm.h"
+#include "private/bionic_asm_note.h"
+#include "private/bionic_call_ifunc_resolver.h"
+#include "private/bionic_elf_tls.h"
+#include "private/bionic_globals.h"
+#include "private/bionic_tls.h"
+#include "private/elf_note.h"
+#include "pthread_internal.h"
+#include "sys/system_properties.h"
+#include "sysprop_helpers.h"
+
+#ifdef __aarch64__
+extern "C" const char* __gnu_basename(const char* path);
+
+static HeapTaggingLevel __get_memtag_level_from_note(const ElfW(Phdr) * phdr_start, size_t phdr_ct,
+                                                     const ElfW(Addr) load_bias, bool* stack) {
+  const ElfW(Nhdr) * note;
+  const char* desc;
+  if (!__find_elf_note(NT_ANDROID_TYPE_MEMTAG, "Android", phdr_start, phdr_ct, &note, &desc,
+                       load_bias)) {
+    return M_HEAP_TAGGING_LEVEL_TBI;
+  }
+
+  // Previously (in Android 12), if the note was != 4 bytes, we check-failed
+  // here. Let's be more permissive to allow future expansion.
+  if (note->n_descsz < 4) {
+    async_safe_fatal("unrecognized android.memtag note: n_descsz = %d, expected >= 4",
+                     note->n_descsz);
+  }
+
+  // `desc` is always aligned due to ELF requirements, enforced in __find_elf_note().
+  ElfW(Word) note_val = *reinterpret_cast<const ElfW(Word)*>(desc);
+  *stack = (note_val & NT_MEMTAG_STACK) != 0;
+
+  // Warning: In Android 12, any value outside of bits [0..3] resulted in a check-fail.
+  if (!(note_val & (NT_MEMTAG_HEAP | NT_MEMTAG_STACK))) {
+    async_safe_format_log(ANDROID_LOG_INFO, "libc",
+                          "unrecognised memtag note_val did not specificy heap or stack: %u",
+                          note_val);
+    return M_HEAP_TAGGING_LEVEL_TBI;
+  }
+
+  unsigned mode = note_val & NT_MEMTAG_LEVEL_MASK;
+  switch (mode) {
+    case NT_MEMTAG_LEVEL_NONE:
+      // Note, previously (in Android 12), NT_MEMTAG_LEVEL_NONE was
+      // NT_MEMTAG_LEVEL_DEFAULT, which implied SYNC mode. This was never used
+      // by anyone, but we note it (heh) here for posterity, in case the zero
+      // level becomes meaningful, and binaries with this note can be executed
+      // on Android 12 devices.
+      return M_HEAP_TAGGING_LEVEL_TBI;
+    case NT_MEMTAG_LEVEL_ASYNC:
+      return M_HEAP_TAGGING_LEVEL_ASYNC;
+    case NT_MEMTAG_LEVEL_SYNC:
+    default:
+      // We allow future extensions to specify mode 3 (currently unused), with
+      // the idea that it might be used for ASYMM mode or something else. On
+      // this version of Android, it falls back to SYNC mode.
+      return M_HEAP_TAGGING_LEVEL_SYNC;
+  }
+}
+
+// Returns true if there's an environment setting (either sysprop or env var)
+// that should overwrite the ELF note, and places the equivalent heap tagging
+// level into *level.
+static bool get_environment_memtag_setting(HeapTaggingLevel* level) {
+  static const char kMemtagPrognameSyspropPrefix[] = "arm64.memtag.process.";
+  static const char kMemtagGlobalSysprop[] = "persist.arm64.memtag.default";
+  static const char kMemtagOverrideSyspropPrefix[] =
+      "persist.device_config.memory_safety_native.mode_override.process.";
+
+  const char* progname = __libc_shared_globals()->init_progname;
+  if (progname == nullptr) return false;
+
+  const char* basename = __gnu_basename(progname);
+
+  char options_str[PROP_VALUE_MAX];
+  char sysprop_name[512];
+  async_safe_format_buffer(sysprop_name, sizeof(sysprop_name), "%s%s", kMemtagPrognameSyspropPrefix,
+                           basename);
+  char remote_sysprop_name[512];
+  async_safe_format_buffer(remote_sysprop_name, sizeof(remote_sysprop_name), "%s%s",
+                           kMemtagOverrideSyspropPrefix, basename);
+  const char* sys_prop_names[] = {sysprop_name, remote_sysprop_name, kMemtagGlobalSysprop};
+
+  if (!get_config_from_env_or_sysprops("MEMTAG_OPTIONS", sys_prop_names, arraysize(sys_prop_names),
+                                       options_str, sizeof(options_str))) {
+    return false;
+  }
+
+  if (strcmp("sync", options_str) == 0) {
+    *level = M_HEAP_TAGGING_LEVEL_SYNC;
+  } else if (strcmp("async", options_str) == 0) {
+    *level = M_HEAP_TAGGING_LEVEL_ASYNC;
+  } else if (strcmp("off", options_str) == 0) {
+    *level = M_HEAP_TAGGING_LEVEL_TBI;
+  } else {
+    async_safe_format_log(
+        ANDROID_LOG_ERROR, "libc",
+        "unrecognized memtag level: \"%s\" (options are \"sync\", \"async\", or \"off\").",
+        options_str);
+    return false;
+  }
+
+  return true;
+}
+
+// Returns the initial heap tagging level. Note: This function will never return
+// M_HEAP_TAGGING_LEVEL_NONE, if MTE isn't enabled for this process we enable
+// M_HEAP_TAGGING_LEVEL_TBI.
+static HeapTaggingLevel __get_tagging_level(const memtag_dynamic_entries_t* memtag_dynamic_entries,
+                                            const void* phdr_start, size_t phdr_ct,
+                                            uintptr_t load_bias, bool* stack) {
+  HeapTaggingLevel level = M_HEAP_TAGGING_LEVEL_TBI;
+
+  // If the dynamic entries exist, use those. Otherwise, fall back to the old
+  // Android note, which is still used for fully static executables. When
+  // -fsanitize=memtag* is used in newer toolchains, currently both the dynamic
+  // entries and the old note are created, but we'd expect to move to just the
+  // dynamic entries for dynamically linked executables in the future. In
+  // addition, there's still some cleanup of the build system (that uses a
+  // manually-constructed note) needed. For more information about the dynamic
+  // entries, see:
+  // https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#dynamic-section
+  if (memtag_dynamic_entries && memtag_dynamic_entries->has_memtag_mode) {
+    switch (memtag_dynamic_entries->memtag_mode) {
+      case 0:
+        level = M_HEAP_TAGGING_LEVEL_SYNC;
+        break;
+      case 1:
+        level = M_HEAP_TAGGING_LEVEL_ASYNC;
+        break;
+      default:
+        async_safe_format_log(ANDROID_LOG_INFO, "libc",
+                              "unrecognised DT_AARCH64_MEMTAG_MODE value: %u",
+                              memtag_dynamic_entries->memtag_mode);
+    }
+    *stack = memtag_dynamic_entries->memtag_stack;
+  } else {
+    level = __get_memtag_level_from_note(reinterpret_cast<const ElfW(Phdr)*>(phdr_start), phdr_ct,
+                                         load_bias, stack);
+  }
+
+  // We can't short-circuit the environment override, as `stack` is still inherited from the
+  // binary's settings.
+  get_environment_memtag_setting(&level);
+  return level;
+}
+
+static void __enable_mte_signal_handler(int, siginfo_t* info, void*) {
+  if (info->si_code != SI_TIMER) {
+    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Got BIONIC_ENABLE_MTE not from SI_TIMER");
+    return;
+  }
+  int tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
+  if (tagged_addr_ctrl < 0) {
+    async_safe_fatal("failed to PR_GET_TAGGED_ADDR_CTRL: %m");
+  }
+  if ((tagged_addr_ctrl & PR_MTE_TCF_MASK) != PR_MTE_TCF_NONE) {
+    return;
+  }
+  async_safe_format_log(ANDROID_LOG_INFO, "libc",
+                        "Re-enabling MTE, value: %x (tagged_addr_ctrl %lu)",
+                        info->si_value.sival_int, info->si_value.sival_int & PR_MTE_TCF_MASK);
+  tagged_addr_ctrl =
+      (tagged_addr_ctrl & ~PR_MTE_TCF_MASK) | (info->si_value.sival_int & PR_MTE_TCF_MASK);
+  if (prctl(PR_SET_TAGGED_ADDR_CTRL, tagged_addr_ctrl, 0, 0, 0) < 0) {
+    async_safe_fatal("failed to PR_SET_TAGGED_ADDR_CTRL %d: %m", tagged_addr_ctrl);
+  }
+}
+
+static int64_t __get_memtag_upgrade_secs() {
+  char* env = getenv("BIONIC_MEMTAG_UPGRADE_SECS");
+  if (!env) return 0;
+  int64_t timed_upgrade = 0;
+  static const char kAppProcessName[] = "app_process64";
+  const char* progname = __libc_shared_globals()->init_progname;
+  progname = progname ? __gnu_basename(progname) : nullptr;
+  // disable timed upgrade for zygote, as the thread spawned will violate the requirement
+  // that it be single-threaded.
+  if (!progname || strncmp(progname, kAppProcessName, sizeof(kAppProcessName)) != 0) {
+    char* endptr;
+    timed_upgrade = strtoll(env, &endptr, 10);
+    if (*endptr != '\0' || timed_upgrade < 0) {
+      async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+                            "Invalid value for BIONIC_MEMTAG_UPGRADE_SECS: %s", env);
+      timed_upgrade = 0;
+    }
+  }
+  // Make sure that this does not get passed to potential processes inheriting
+  // this environment.
+  unsetenv("BIONIC_MEMTAG_UPGRADE_SECS");
+  return timed_upgrade;
+}
+
+// Figure out the desired memory tagging mode (sync/async, heap/globals/stack) for this executable.
+// This function is called from the linker before the main executable is relocated.
+__attribute__((no_sanitize("hwaddress", "memtag"))) void __libc_init_mte(
+    const memtag_dynamic_entries_t* memtag_dynamic_entries, const void* phdr_start, size_t phdr_ct,
+    uintptr_t load_bias) {
+  bool memtag_stack = false;
+  HeapTaggingLevel level =
+      __get_tagging_level(memtag_dynamic_entries, phdr_start, phdr_ct, load_bias, &memtag_stack);
+  if (memtag_stack) __libc_shared_globals()->initial_memtag_stack_abi = true;
+
+  if (int64_t timed_upgrade = __get_memtag_upgrade_secs()) {
+    if (level == M_HEAP_TAGGING_LEVEL_ASYNC) {
+      async_safe_format_log(ANDROID_LOG_INFO, "libc",
+                            "Attempting timed MTE upgrade from async to sync.");
+      __libc_shared_globals()->heap_tagging_upgrade_timer_sec = timed_upgrade;
+      level = M_HEAP_TAGGING_LEVEL_SYNC;
+    } else if (level != M_HEAP_TAGGING_LEVEL_SYNC) {
+      async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+                            "Requested timed MTE upgrade from invalid %s to sync. Ignoring.",
+                            DescribeTaggingLevel(level));
+    }
+  }
+  if (level == M_HEAP_TAGGING_LEVEL_SYNC || level == M_HEAP_TAGGING_LEVEL_ASYNC) {
+    unsigned long prctl_arg = PR_TAGGED_ADDR_ENABLE | PR_MTE_TAG_SET_NONZERO;
+    prctl_arg |= (level == M_HEAP_TAGGING_LEVEL_SYNC) ? PR_MTE_TCF_SYNC : PR_MTE_TCF_ASYNC;
+
+    // When entering ASYNC mode, specify that we want to allow upgrading to SYNC by OR'ing in the
+    // SYNC flag. But if the kernel doesn't support specifying multiple TCF modes, fall back to
+    // specifying a single mode.
+    if (prctl(PR_SET_TAGGED_ADDR_CTRL, prctl_arg | PR_MTE_TCF_SYNC, 0, 0, 0) == 0 ||
+        prctl(PR_SET_TAGGED_ADDR_CTRL, prctl_arg, 0, 0, 0) == 0) {
+      __libc_shared_globals()->initial_heap_tagging_level = level;
+
+      struct sigaction action = {};
+      action.sa_flags = SA_SIGINFO | SA_RESTART;
+      action.sa_sigaction = __enable_mte_signal_handler;
+      sigaction(BIONIC_ENABLE_MTE, &action, nullptr);
+      return;
+    }
+  }
+
+  // MTE was either not enabled, or wasn't supported on this device. Try and use
+  // TBI.
+  if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0) == 0) {
+    __libc_shared_globals()->initial_heap_tagging_level = M_HEAP_TAGGING_LEVEL_TBI;
+  }
+  // We did not enable MTE, so we do not need to arm the upgrade timer.
+  __libc_shared_globals()->heap_tagging_upgrade_timer_sec = 0;
+}
+
+// Figure out whether we need to map the stack as PROT_MTE.
+// For dynamic executables, this has to be called after loading all
+// DT_NEEDED libraries, in case one of them needs stack MTE.
+__attribute__((no_sanitize("hwaddress", "memtag"))) void __libc_init_mte_stack(void* stack_top) {
+  if (!__libc_shared_globals()->initial_memtag_stack_abi) {
+    return;
+  }
+
+  // Even if the device doesn't support MTE, we have to allocate stack
+  // history buffers for code compiled for stack MTE. That is because the
+  // codegen expects a buffer to be present in TLS_SLOT_STACK_MTE either
+  // way.
+  __get_bionic_tcb()->tls_slot(TLS_SLOT_STACK_MTE) = __allocate_stack_mte_ringbuffer(0, nullptr);
+
+  if (__libc_mte_enabled()) {
+    __libc_shared_globals()->initial_memtag_stack = true;
+    void* pg_start = reinterpret_cast<void*>(page_start(reinterpret_cast<uintptr_t>(stack_top)));
+    if (mprotect(pg_start, page_size(), PROT_READ | PROT_WRITE | PROT_MTE | PROT_GROWSDOWN)) {
+      async_safe_fatal("error: failed to set PROT_MTE on main thread stack: %m");
+    }
+  }
+}
+
+#else   // __aarch64__
+void __libc_init_mte(const memtag_dynamic_entries_t*, const void*, size_t, uintptr_t) {}
+void __libc_init_mte_stack(void*) {}
+#endif  // __aarch64__
+
+bool __libc_mte_enabled() {
+  HeapTaggingLevel lvl = __libc_shared_globals()->initial_heap_tagging_level;
+  return lvl == M_HEAP_TAGGING_LEVEL_SYNC || lvl == M_HEAP_TAGGING_LEVEL_ASYNC;
+}
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index ac97376..cd96375 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -30,6 +30,7 @@
 #include <elf.h>
 #include <errno.h>
 #include <malloc.h>
+#include <signal.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -156,235 +157,6 @@
 
   layout.finish_layout();
 }
-
-#ifdef __aarch64__
-static HeapTaggingLevel __get_memtag_level_from_note(const ElfW(Phdr) * phdr_start, size_t phdr_ct,
-                                                     const ElfW(Addr) load_bias, bool* stack) {
-  const ElfW(Nhdr) * note;
-  const char* desc;
-  if (!__find_elf_note(NT_ANDROID_TYPE_MEMTAG, "Android", phdr_start, phdr_ct, &note, &desc,
-                       load_bias)) {
-    return M_HEAP_TAGGING_LEVEL_TBI;
-  }
-
-  // Previously (in Android 12), if the note was != 4 bytes, we check-failed
-  // here. Let's be more permissive to allow future expansion.
-  if (note->n_descsz < 4) {
-    async_safe_fatal("unrecognized android.memtag note: n_descsz = %d, expected >= 4",
-                     note->n_descsz);
-  }
-
-  // `desc` is always aligned due to ELF requirements, enforced in __find_elf_note().
-  ElfW(Word) note_val = *reinterpret_cast<const ElfW(Word)*>(desc);
-  *stack = (note_val & NT_MEMTAG_STACK) != 0;
-
-  // Warning: In Android 12, any value outside of bits [0..3] resulted in a check-fail.
-  if (!(note_val & (NT_MEMTAG_HEAP | NT_MEMTAG_STACK))) {
-    async_safe_format_log(ANDROID_LOG_INFO, "libc",
-                          "unrecognised memtag note_val did not specificy heap or stack: %u",
-                          note_val);
-    return M_HEAP_TAGGING_LEVEL_TBI;
-  }
-
-  unsigned mode = note_val & NT_MEMTAG_LEVEL_MASK;
-  switch (mode) {
-    case NT_MEMTAG_LEVEL_NONE:
-      // Note, previously (in Android 12), NT_MEMTAG_LEVEL_NONE was
-      // NT_MEMTAG_LEVEL_DEFAULT, which implied SYNC mode. This was never used
-      // by anyone, but we note it (heh) here for posterity, in case the zero
-      // level becomes meaningful, and binaries with this note can be executed
-      // on Android 12 devices.
-      return M_HEAP_TAGGING_LEVEL_TBI;
-    case NT_MEMTAG_LEVEL_ASYNC:
-      return M_HEAP_TAGGING_LEVEL_ASYNC;
-    case NT_MEMTAG_LEVEL_SYNC:
-    default:
-      // We allow future extensions to specify mode 3 (currently unused), with
-      // the idea that it might be used for ASYMM mode or something else. On
-      // this version of Android, it falls back to SYNC mode.
-      return M_HEAP_TAGGING_LEVEL_SYNC;
-  }
-}
-
-// Returns true if there's an environment setting (either sysprop or env var)
-// that should overwrite the ELF note, and places the equivalent heap tagging
-// level into *level.
-static bool get_environment_memtag_setting(HeapTaggingLevel* level) {
-  static const char kMemtagPrognameSyspropPrefix[] = "arm64.memtag.process.";
-  static const char kMemtagGlobalSysprop[] = "persist.arm64.memtag.default";
-  static const char kMemtagOverrideSyspropPrefix[] =
-      "persist.device_config.memory_safety_native.mode_override.process.";
-
-  const char* progname = __libc_shared_globals()->init_progname;
-  if (progname == nullptr) return false;
-
-  const char* basename = __gnu_basename(progname);
-
-  char options_str[PROP_VALUE_MAX];
-  char sysprop_name[512];
-  async_safe_format_buffer(sysprop_name, sizeof(sysprop_name), "%s%s", kMemtagPrognameSyspropPrefix,
-                           basename);
-  char remote_sysprop_name[512];
-  async_safe_format_buffer(remote_sysprop_name, sizeof(remote_sysprop_name), "%s%s",
-                           kMemtagOverrideSyspropPrefix, basename);
-  const char* sys_prop_names[] = {sysprop_name, remote_sysprop_name, kMemtagGlobalSysprop};
-
-  if (!get_config_from_env_or_sysprops("MEMTAG_OPTIONS", sys_prop_names, arraysize(sys_prop_names),
-                                       options_str, sizeof(options_str))) {
-    return false;
-  }
-
-  if (strcmp("sync", options_str) == 0) {
-    *level = M_HEAP_TAGGING_LEVEL_SYNC;
-  } else if (strcmp("async", options_str) == 0) {
-    *level = M_HEAP_TAGGING_LEVEL_ASYNC;
-  } else if (strcmp("off", options_str) == 0) {
-    *level = M_HEAP_TAGGING_LEVEL_TBI;
-  } else {
-    async_safe_format_log(
-        ANDROID_LOG_ERROR, "libc",
-        "unrecognized memtag level: \"%s\" (options are \"sync\", \"async\", or \"off\").",
-        options_str);
-    return false;
-  }
-
-  return true;
-}
-
-// Returns the initial heap tagging level. Note: This function will never return
-// M_HEAP_TAGGING_LEVEL_NONE, if MTE isn't enabled for this process we enable
-// M_HEAP_TAGGING_LEVEL_TBI.
-static HeapTaggingLevel __get_tagging_level(const memtag_dynamic_entries_t* memtag_dynamic_entries,
-                                            const void* phdr_start, size_t phdr_ct,
-                                            uintptr_t load_bias, bool* stack) {
-  HeapTaggingLevel level = M_HEAP_TAGGING_LEVEL_TBI;
-
-  // If the dynamic entries exist, use those. Otherwise, fall back to the old
-  // Android note, which is still used for fully static executables. When
-  // -fsanitize=memtag* is used in newer toolchains, currently both the dynamic
-  // entries and the old note are created, but we'd expect to move to just the
-  // dynamic entries for dynamically linked executables in the future. In
-  // addition, there's still some cleanup of the build system (that uses a
-  // manually-constructed note) needed. For more information about the dynamic
-  // entries, see:
-  // https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#dynamic-section
-  if (memtag_dynamic_entries && memtag_dynamic_entries->has_memtag_mode) {
-    switch (memtag_dynamic_entries->memtag_mode) {
-      case 0:
-        level = M_HEAP_TAGGING_LEVEL_SYNC;
-        break;
-      case 1:
-        level = M_HEAP_TAGGING_LEVEL_ASYNC;
-        break;
-      default:
-        async_safe_format_log(ANDROID_LOG_INFO, "libc",
-                              "unrecognised DT_AARCH64_MEMTAG_MODE value: %u",
-                              memtag_dynamic_entries->memtag_mode);
-    }
-    *stack = memtag_dynamic_entries->memtag_stack;
-  } else {
-    level = __get_memtag_level_from_note(reinterpret_cast<const ElfW(Phdr)*>(phdr_start), phdr_ct,
-                                         load_bias, stack);
-  }
-
-  // We can't short-circuit the environment override, as `stack` is still inherited from the
-  // binary's settings.
-  get_environment_memtag_setting(&level);
-  return level;
-}
-
-static int64_t __get_memtag_upgrade_secs() {
-  char* env = getenv("BIONIC_MEMTAG_UPGRADE_SECS");
-  if (!env) return 0;
-  int64_t timed_upgrade = 0;
-  static const char kAppProcessName[] = "app_process64";
-  const char* progname = __libc_shared_globals()->init_progname;
-  progname = progname ? __gnu_basename(progname) : nullptr;
-  // disable timed upgrade for zygote, as the thread spawned will violate the requirement
-  // that it be single-threaded.
-  if (!progname || strncmp(progname, kAppProcessName, sizeof(kAppProcessName)) != 0) {
-    char* endptr;
-    timed_upgrade = strtoll(env, &endptr, 10);
-    if (*endptr != '\0' || timed_upgrade < 0) {
-      async_safe_format_log(ANDROID_LOG_ERROR, "libc",
-                            "Invalid value for BIONIC_MEMTAG_UPGRADE_SECS: %s", env);
-      timed_upgrade = 0;
-    }
-  }
-  // Make sure that this does not get passed to potential processes inheriting
-  // this environment.
-  unsetenv("BIONIC_MEMTAG_UPGRADE_SECS");
-  return timed_upgrade;
-}
-
-// Figure out the desired memory tagging mode (sync/async, heap/globals/stack) for this executable.
-// This function is called from the linker before the main executable is relocated.
-__attribute__((no_sanitize("hwaddress", "memtag"))) void __libc_init_mte(
-    const memtag_dynamic_entries_t* memtag_dynamic_entries, const void* phdr_start, size_t phdr_ct,
-    uintptr_t load_bias, void* stack_top) {
-  bool memtag_stack = false;
-  HeapTaggingLevel level =
-      __get_tagging_level(memtag_dynamic_entries, phdr_start, phdr_ct, load_bias, &memtag_stack);
-  // initial_memtag_stack is used by the linker (in linker.cpp) to communicate than any library
-  // linked by this executable enables memtag-stack.
-  // memtag_stack is also set for static executables if they request memtag stack via the note,
-  // in which case it will differ from initial_memtag_stack.
-  if (__libc_shared_globals()->initial_memtag_stack || memtag_stack) {
-    memtag_stack = true;
-    __libc_shared_globals()->initial_memtag_stack_abi = true;
-    __get_bionic_tcb()->tls_slot(TLS_SLOT_STACK_MTE) = __allocate_stack_mte_ringbuffer(0, nullptr);
-  }
-  if (int64_t timed_upgrade = __get_memtag_upgrade_secs()) {
-    if (level == M_HEAP_TAGGING_LEVEL_ASYNC) {
-      async_safe_format_log(ANDROID_LOG_INFO, "libc",
-                            "Attempting timed MTE upgrade from async to sync.");
-      __libc_shared_globals()->heap_tagging_upgrade_timer_sec = timed_upgrade;
-      level = M_HEAP_TAGGING_LEVEL_SYNC;
-    } else if (level != M_HEAP_TAGGING_LEVEL_SYNC) {
-      async_safe_format_log(
-          ANDROID_LOG_ERROR, "libc",
-          "Requested timed MTE upgrade from invalid %s to sync. Ignoring.",
-          DescribeTaggingLevel(level));
-    }
-  }
-  if (level == M_HEAP_TAGGING_LEVEL_SYNC || level == M_HEAP_TAGGING_LEVEL_ASYNC) {
-    unsigned long prctl_arg = PR_TAGGED_ADDR_ENABLE | PR_MTE_TAG_SET_NONZERO;
-    prctl_arg |= (level == M_HEAP_TAGGING_LEVEL_SYNC) ? PR_MTE_TCF_SYNC : PR_MTE_TCF_ASYNC;
-
-    // When entering ASYNC mode, specify that we want to allow upgrading to SYNC by OR'ing in the
-    // SYNC flag. But if the kernel doesn't support specifying multiple TCF modes, fall back to
-    // specifying a single mode.
-    if (prctl(PR_SET_TAGGED_ADDR_CTRL, prctl_arg | PR_MTE_TCF_SYNC, 0, 0, 0) == 0 ||
-        prctl(PR_SET_TAGGED_ADDR_CTRL, prctl_arg, 0, 0, 0) == 0) {
-      __libc_shared_globals()->initial_heap_tagging_level = level;
-      __libc_shared_globals()->initial_memtag_stack = memtag_stack;
-
-      if (memtag_stack) {
-        void* pg_start =
-            reinterpret_cast<void*>(page_start(reinterpret_cast<uintptr_t>(stack_top)));
-        if (mprotect(pg_start, page_size(), PROT_READ | PROT_WRITE | PROT_MTE | PROT_GROWSDOWN)) {
-          async_safe_fatal("error: failed to set PROT_MTE on main thread stack: %m");
-        }
-      }
-
-      return;
-    }
-  }
-
-  // MTE was either not enabled, or wasn't supported on this device. Try and use
-  // TBI.
-  if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0) == 0) {
-    __libc_shared_globals()->initial_heap_tagging_level = M_HEAP_TAGGING_LEVEL_TBI;
-  }
-  // We did not enable MTE, so we do not need to arm the upgrade timer.
-  __libc_shared_globals()->heap_tagging_upgrade_timer_sec = 0;
-  // We also didn't enable memtag_stack.
-  __libc_shared_globals()->initial_memtag_stack = false;
-}
-#else   // __aarch64__
-void __libc_init_mte(const memtag_dynamic_entries_t*, const void*, size_t, uintptr_t, void*) {}
-#endif  // __aarch64__
-
 void __libc_init_profiling_handlers() {
   // The dynamic variant of this function is more interesting, but this
   // at least ensures that static binaries aren't killed by the kernel's
@@ -395,12 +167,11 @@
 }
 
 __attribute__((no_sanitize("memtag"))) __noreturn static void __real_libc_init(
-    void* raw_args, void (*onexit)(void) __unused, int (*slingshot)(int, char**, char**),
-    structors_array_t const* const structors, bionic_tcb* temp_tcb) {
+    KernelArgumentBlock& args, void* raw_args, void (*onexit)(void) __unused,
+    int (*slingshot)(int, char**, char**), structors_array_t const* const structors,
+    bionic_tcb* temp_tcb) {
   BIONIC_STOP_UNWIND;
 
-  // Initialize TLS early so system calls and errno work.
-  KernelArgumentBlock args(raw_args);
   __libc_init_main_thread_early(args, temp_tcb);
   __libc_init_main_thread_late();
   __libc_init_globals();
@@ -411,7 +182,8 @@
   __libc_init_common();
   __libc_init_mte(/*memtag_dynamic_entries=*/nullptr,
                   reinterpret_cast<ElfW(Phdr)*>(getauxval(AT_PHDR)), getauxval(AT_PHNUM),
-                  /*load_bias = */ 0, /*stack_top = */ raw_args);
+                  /*load_bias = */ 0);
+  __libc_init_mte_stack(/*stack_top = */ raw_args);
   __libc_init_scudo();
   __libc_init_profiling_handlers();
   __libc_init_fork_handler();
@@ -447,17 +219,25 @@
 __attribute__((no_sanitize("hwaddress", "memtag"))) __noreturn void __libc_init(
     void* raw_args, void (*onexit)(void) __unused, int (*slingshot)(int, char**, char**),
     structors_array_t const* const structors) {
-  bionic_tcb temp_tcb = {};
+  // We _really_ don't want the compiler to call memset() here,
+  // but it's done so before for riscv64 (http://b/365618934),
+  // so we have to force it to behave.
+  bionic_tcb temp_tcb __attribute__((uninitialized));
+  __builtin_memset_inline(&temp_tcb, 0, sizeof(temp_tcb));
+
+  KernelArgumentBlock args(raw_args);
 #if __has_feature(hwaddress_sanitizer)
   // Install main thread TLS early. It will be initialized later in __libc_init_main_thread. For now
-  // all we need is access to TLS_SLOT_SANITIZER.
+  // all we need is access to TLS_SLOT_SANITIZER and read auxval for the page size.
   __set_tls(&temp_tcb.tls_slot(0));
+  __libc_shared_globals()->auxv = args.auxv;
   // Initialize HWASan enough to run instrumented code. This sets up TLS_SLOT_SANITIZER, among other
   // things.
   __hwasan_init_static();
   // We are ready to run HWASan-instrumented code, proceed with libc initialization...
 #endif
-  __real_libc_init(raw_args, onexit, slingshot, structors, &temp_tcb);
+
+  __real_libc_init(args, raw_args, onexit, slingshot, structors, &temp_tcb);
 }
 
 static int g_target_sdk_version{__ANDROID_API__};
@@ -475,6 +255,6 @@
 // compiled with -ffreestanding to avoid implicit string.h function calls. (It shouldn't strictly
 // be necessary, though.)
 __LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals() {
-  static libc_shared_globals globals;
+  BIONIC_USED_BEFORE_LINKER_RELOCATES static libc_shared_globals globals;
   return &globals;
 }
diff --git a/libc/bionic/lockf.cpp b/libc/bionic/lockf.cpp
index 804ad68..54e13f5 100644
--- a/libc/bionic/lockf.cpp
+++ b/libc/bionic/lockf.cpp
@@ -68,6 +68,12 @@
   return -1;
 }
 
+#if defined(__LP64__)
+// For LP64, off_t == off64_t.
+__strong_alias(lockf, lockf64);
+#else
+// For ILP32 we need a shim that truncates the off64_t to off_t.
 int lockf(int fd, int cmd, off_t length) {
   return lockf64(fd, cmd, length);
 }
+#endif
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 596a1fc..441d884 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -332,44 +332,6 @@
 #endif
 // =============================================================================
 
-// =============================================================================
-// Platform-internal mallopt variant.
-// =============================================================================
-#if defined(LIBC_STATIC)
-extern "C" bool android_mallopt(int opcode, void* arg, size_t arg_size) {
-  if (opcode == M_SET_ALLOCATION_LIMIT_BYTES) {
-    return LimitEnable(arg, arg_size);
-  }
-  if (opcode == M_INITIALIZE_GWP_ASAN) {
-    if (arg == nullptr || arg_size != sizeof(android_mallopt_gwp_asan_options_t)) {
-      errno = EINVAL;
-      return false;
-    }
-
-    return EnableGwpAsan(*reinterpret_cast<android_mallopt_gwp_asan_options_t*>(arg));
-  }
-  if (opcode == M_MEMTAG_STACK_IS_ON) {
-    if (arg == nullptr || arg_size != sizeof(bool)) {
-      errno = EINVAL;
-      return false;
-    }
-    *reinterpret_cast<bool*>(arg) = atomic_load(&__libc_memtag_stack);
-    return true;
-  }
-  if (opcode == M_GET_DECAY_TIME_ENABLED) {
-    if (arg == nullptr || arg_size != sizeof(bool)) {
-      errno = EINVAL;
-      return false;
-    }
-    *reinterpret_cast<bool*>(arg) = atomic_load(&__libc_globals->decay_time_enabled);
-    return true;
-  }
-  errno = ENOTSUP;
-  return false;
-}
-#endif
-// =============================================================================
-
 static constexpr MallocDispatch __libc_malloc_default_dispatch __attribute__((unused)) = {
   Malloc(calloc),
   Malloc(free),
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
index 6db6251..7b6d7d4 100644
--- a/libc/bionic/malloc_common_dynamic.cpp
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -80,7 +80,7 @@
 
 _Atomic bool gGlobalsMutating = false;
 
-static bool gZygoteChild = false;
+bool gZygoteChild = false;
 
 // In a Zygote child process, this is set to true if profiling of this process
 // is allowed. Note that this is set at a later time than gZygoteChild. The
@@ -89,7 +89,7 @@
 // domains if applicable). These two flags are read by the
 // BIONIC_SIGNAL_PROFILER handler, which does nothing if the process is not
 // profileable.
-static _Atomic bool gZygoteChildProfileable = false;
+_Atomic bool gZygoteChildProfileable = false;
 
 // =============================================================================
 
@@ -471,93 +471,6 @@
 }
 // =============================================================================
 
-// =============================================================================
-// Platform-internal mallopt variant.
-// =============================================================================
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-extern "C" bool android_mallopt(int opcode, void* arg, size_t arg_size) {
-  if (opcode == M_SET_ZYGOTE_CHILD) {
-    if (arg != nullptr || arg_size != 0) {
-      errno = EINVAL;
-      return false;
-    }
-    gZygoteChild = true;
-    return true;
-  }
-  if (opcode == M_INIT_ZYGOTE_CHILD_PROFILING) {
-    if (arg != nullptr || arg_size != 0) {
-      errno = EINVAL;
-      return false;
-    }
-    atomic_store_explicit(&gZygoteChildProfileable, true, memory_order_release);
-    // Also check if heapprofd should start profiling from app startup.
-    HeapprofdInitZygoteChildProfiling();
-    return true;
-  }
-  if (opcode == M_GET_PROCESS_PROFILEABLE) {
-    if (arg == nullptr || arg_size != sizeof(bool)) {
-      errno = EINVAL;
-      return false;
-    }
-    // Native processes are considered profileable. Zygote children are considered
-    // profileable only when appropriately tagged.
-    *reinterpret_cast<bool*>(arg) =
-        !gZygoteChild || atomic_load_explicit(&gZygoteChildProfileable, memory_order_acquire);
-    return true;
-  }
-  if (opcode == M_SET_ALLOCATION_LIMIT_BYTES) {
-    return LimitEnable(arg, arg_size);
-  }
-  if (opcode == M_WRITE_MALLOC_LEAK_INFO_TO_FILE) {
-    if (arg == nullptr || arg_size != sizeof(FILE*)) {
-      errno = EINVAL;
-      return false;
-    }
-    return WriteMallocLeakInfo(reinterpret_cast<FILE*>(arg));
-  }
-  if (opcode == M_GET_MALLOC_LEAK_INFO) {
-    if (arg == nullptr || arg_size != sizeof(android_mallopt_leak_info_t)) {
-      errno = EINVAL;
-      return false;
-    }
-    return GetMallocLeakInfo(reinterpret_cast<android_mallopt_leak_info_t*>(arg));
-  }
-  if (opcode == M_FREE_MALLOC_LEAK_INFO) {
-    if (arg == nullptr || arg_size != sizeof(android_mallopt_leak_info_t)) {
-      errno = EINVAL;
-      return false;
-    }
-    return FreeMallocLeakInfo(reinterpret_cast<android_mallopt_leak_info_t*>(arg));
-  }
-  if (opcode == M_INITIALIZE_GWP_ASAN) {
-    if (arg == nullptr || arg_size != sizeof(android_mallopt_gwp_asan_options_t)) {
-      errno = EINVAL;
-      return false;
-    }
-
-    return EnableGwpAsan(*reinterpret_cast<android_mallopt_gwp_asan_options_t*>(arg));
-  }
-  if (opcode == M_MEMTAG_STACK_IS_ON) {
-    if (arg == nullptr || arg_size != sizeof(bool)) {
-      errno = EINVAL;
-      return false;
-    }
-    *reinterpret_cast<bool*>(arg) = atomic_load(&__libc_memtag_stack);
-    return true;
-  }
-  if (opcode == M_GET_DECAY_TIME_ENABLED) {
-    if (arg == nullptr || arg_size != sizeof(bool)) {
-      errno = EINVAL;
-      return false;
-    }
-    *reinterpret_cast<bool*>(arg) = atomic_load(&__libc_globals->decay_time_enabled);
-    return true;
-  }
-  // Try heapprofd's mallopt, as it handles options not covered here.
-  return HeapprofdMallopt(opcode, arg, arg_size);
-}
-// =============================================================================
-
 #if !defined(__LP64__) && defined(__arm__)
 // =============================================================================
 // Old platform only functions that some old 32 bit apps are still using.
diff --git a/libc/bionic/poll.cpp b/libc/bionic/poll.cpp
index 7d80b4c..5b58425 100644
--- a/libc/bionic/poll.cpp
+++ b/libc/bionic/poll.cpp
@@ -48,11 +48,17 @@
   return __ppoll(fds, fd_count, ts_ptr, nullptr, 0);
 }
 
+// The underlying ppoll(2) system call only takes `sigset64_t`.
+#if defined(__LP64__)
+// That's fine for LP64 where `sigset_t` and `sigset64_t` are the same.
+__strong_alias(ppoll, ppoll64);
+#else
+// ILP32 needs a shim.
 int ppoll(pollfd* fds, nfds_t fd_count, const timespec* ts, const sigset_t* ss) {
-  // The underlying `__ppoll` system call only takes `sigset64_t`.
   SigSetConverter set{ss};
   return ppoll64(fds, fd_count, ts, set.ptr);
 }
+#endif
 
 int ppoll64(pollfd* fds, nfds_t fd_count, const timespec* ts, const sigset64_t* ss) {
   // The underlying __ppoll system call modifies its `struct timespec` argument.
@@ -90,12 +96,19 @@
   return result;
 }
 
+// The underlying pselect6(2) system call only takes `sigset64_t`.
+#if defined(__LP64__)
+// That's fine for LP64 where `sigset_t` and `sigset64_t` are the same.
+__strong_alias(pselect, pselect64);
+#else
+// ILP32 needs a shim.
 int pselect(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_fds,
             const timespec* ts, const sigset_t* ss) {
   // The underlying `__pselect6` system call only takes `sigset64_t`.
   SigSetConverter set{ss};
   return pselect64(fd_count, read_fds, write_fds, error_fds, ts, set.ptr);
 }
+#endif
 
 int pselect64(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_fds,
               const timespec* ts, const sigset64_t* ss) {
diff --git a/libc/bionic/posix_timers.cpp b/libc/bionic/posix_timers.cpp
index ccbbfcf..9516059 100644
--- a/libc/bionic/posix_timers.cpp
+++ b/libc/bionic/posix_timers.cpp
@@ -117,7 +117,7 @@
   pthread_kill(timer->callback_thread, TIMER_SIGNAL);
 }
 
-// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_create.html
+// https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/timer_create.html
 int timer_create(clockid_t clock_id, sigevent* evp, timer_t* timer_id) {
   PosixTimer* timer = reinterpret_cast<PosixTimer*>(malloc(sizeof(PosixTimer)));
   if (timer == nullptr) {
@@ -141,7 +141,7 @@
   // Otherwise, this must be SIGEV_THREAD timer...
   timer->callback = evp->sigev_notify_function;
   timer->callback_argument = evp->sigev_value;
-  atomic_init(&timer->deleted, false);
+  atomic_store_explicit(&timer->deleted, false, memory_order_relaxed);
 
   // Check arguments that the kernel doesn't care about but we do.
   if (timer->callback == nullptr) {
@@ -201,7 +201,7 @@
   return 0;
 }
 
-// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_delete.html
+// https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/timer_delete.html
 int timer_delete(timer_t id) {
   int rc = __timer_delete(to_kernel_timer_id(id));
   if (rc == -1) {
@@ -220,12 +220,12 @@
   return 0;
 }
 
-// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_gettime.html
+// https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/timer_gettime.html
 int timer_gettime(timer_t id, itimerspec* ts) {
   return __timer_gettime(to_kernel_timer_id(id), ts);
 }
 
-// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_settime.html
+// https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/timer_settime.html
 // When using timer_settime to disarm a repeatable SIGEV_THREAD timer with a very small
 // period (like below 1ms), the kernel may continue to send events to the callback thread
 // for a few extra times. This behavior is fine because in POSIX standard: The effect of
@@ -235,7 +235,7 @@
   return __timer_settime(timer->kernel_timer_id, flags, ts, ots);
 }
 
-// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_getoverrun.html
+// https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/timer_getoverrun.html
 int timer_getoverrun(timer_t id) {
   return __timer_getoverrun(to_kernel_timer_id(id));
 }
diff --git a/libc/bionic/pthread_barrier.cpp b/libc/bionic/pthread_barrier.cpp
index 1618222..ff048a6 100644
--- a/libc/bionic/pthread_barrier.cpp
+++ b/libc/bionic/pthread_barrier.cpp
@@ -95,8 +95,8 @@
     return EINVAL;
   }
   barrier->init_count = count;
-  atomic_init(&barrier->state, WAIT);
-  atomic_init(&barrier->wait_count, 0);
+  atomic_store_explicit(&barrier->state, WAIT, memory_order_relaxed);
+  atomic_store_explicit(&barrier->wait_count, 0, memory_order_relaxed);
   barrier->pshared = false;
   if (attr != nullptr && (*attr & 1)) {
     barrier->pshared = true;
diff --git a/libc/bionic/pthread_cond.cpp b/libc/bionic/pthread_cond.cpp
index f444676..197fd19 100644
--- a/libc/bionic/pthread_cond.cpp
+++ b/libc/bionic/pthread_cond.cpp
@@ -140,10 +140,10 @@
   if (attr != nullptr) {
     init_state = (*attr & COND_FLAGS_MASK);
   }
-  atomic_init(&cond->state, init_state);
+  atomic_store_explicit(&cond->state, init_state, memory_order_relaxed);
 
 #if defined(__LP64__)
-  atomic_init(&cond->waiters, 0);
+  atomic_store_explicit(&cond->waiters, 0, memory_order_relaxed);
 #endif
 
   return 0;
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index a8d09eb..3fa8ee6 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -118,12 +118,15 @@
 
 static void __init_shadow_call_stack(pthread_internal_t* thread __unused) {
 #if defined(__aarch64__) || defined(__riscv)
-  // Allocate the stack and the guard region.
+  // Allocate the shadow call stack and its guard region.
   char* scs_guard_region = reinterpret_cast<char*>(
-      mmap(nullptr, SCS_GUARD_REGION_SIZE, 0, MAP_PRIVATE | MAP_ANON, -1, 0));
+      mmap(nullptr, SCS_GUARD_REGION_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0));
+  if (scs_guard_region == MAP_FAILED) {
+    async_safe_fatal("failed to allocate shadow stack: %m");
+  }
   thread->shadow_call_stack_guard_region = scs_guard_region;
 
-  // The address is aligned to SCS_SIZE so that we only need to store the lower log2(SCS_SIZE) bits
+  // Align the address to SCS_SIZE so that we only need to store the lower log2(SCS_SIZE) bits
   // in jmp_buf. See the SCS commentary in pthread_internal.h for more detail.
   char* scs_aligned_guard_region =
       reinterpret_cast<char*>(align_up(reinterpret_cast<uintptr_t>(scs_guard_region), SCS_SIZE));
@@ -156,11 +159,11 @@
 int __init_thread(pthread_internal_t* thread) {
   thread->cleanup_stack = nullptr;
 
-  if (__predict_true((thread->attr.flags & PTHREAD_ATTR_FLAG_DETACHED) == 0)) {
-    atomic_init(&thread->join_state, THREAD_NOT_JOINED);
-  } else {
-    atomic_init(&thread->join_state, THREAD_DETACHED);
+  ThreadJoinState state = THREAD_NOT_JOINED;
+  if (__predict_false((thread->attr.flags & PTHREAD_ATTR_FLAG_DETACHED) != 0)) {
+    state = THREAD_DETACHED;
   }
+  atomic_store_explicit(&thread->join_state, state, memory_order_relaxed);
 
   // Set the scheduling policy/priority of the thread if necessary.
   bool need_set = true;
@@ -348,15 +351,20 @@
 
 extern "C" int __rt_sigprocmask(int, const sigset64_t*, sigset64_t*, size_t);
 
-__attribute__((no_sanitize("hwaddress")))
-#ifdef __aarch64__
+__attribute__((no_sanitize("hwaddress", "memtag")))
+#if defined(__aarch64__)
 // This function doesn't return, but it does appear in stack traces. Avoid using return PAC in this
 // function because we may end up resetting IA, which may confuse unwinders due to mismatching keys.
 __attribute__((target("branch-protection=bti")))
 #endif
-static int __pthread_start(void* arg) {
+static int
+__pthread_start(void* arg) {
   pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(arg);
-
+#if defined(__aarch64__)
+  if (thread->should_allocate_stack_mte_ringbuffer) {
+    thread->bionic_tcb->tls_slot(TLS_SLOT_STACK_MTE) = __allocate_stack_mte_ringbuffer(0, thread);
+  }
+#endif
   __hwasan_thread_enter();
 
   // Wait for our creating thread to release us. This lets it have time to
@@ -368,13 +376,13 @@
   __set_stack_and_tls_vma_name(false);
   __init_additional_stacks(thread);
   __rt_sigprocmask(SIG_SETMASK, &thread->start_mask, nullptr, sizeof(thread->start_mask));
-#ifdef __aarch64__
+#if defined(__aarch64__)
   // Chrome's sandbox prevents this prctl, so only reset IA if the target SDK level is high enough.
   // Furthermore, processes loaded from vendor partitions may have their own sandboxes that would
-  // reject the prctl. Because no devices launched with PAC enabled before S, we can avoid issues on
-  // upgrading devices by checking for PAC support before issuing the prctl.
+  // reject the prctl. Because no devices launched with PAC enabled before API level 31, we can
+  // avoid issues on upgrading devices by checking for PAC support before issuing the prctl.
   static const bool pac_supported = getauxval(AT_HWCAP) & HWCAP_PACA;
-  if (pac_supported && android_get_application_target_sdk_version() >= __ANDROID_API_S__) {
+  if (pac_supported && android_get_application_target_sdk_version() >= 31) {
     prctl(PR_PAC_RESET_KEYS, PR_PAC_APIAKEY, 0, 0, 0);
   }
 #endif
@@ -447,9 +455,9 @@
 // This has to be done under g_thread_creation_lock or g_thread_list_lock to avoid racing with
 // __pthread_internal_remap_stack_with_mte.
 #ifdef __aarch64__
-  if (__libc_memtag_stack_abi) {
-    tcb->tls_slot(TLS_SLOT_STACK_MTE) = __allocate_stack_mte_ringbuffer(0, thread);
-  }
+  thread->should_allocate_stack_mte_ringbuffer = __libc_memtag_stack_abi;
+#else
+  thread->should_allocate_stack_mte_ringbuffer = false;
 #endif
 
   sigset64_t block_all_mask;
diff --git a/libc/bionic/pthread_exit.cpp b/libc/bionic/pthread_exit.cpp
index 0181aba..27d05c2 100644
--- a/libc/bionic/pthread_exit.cpp
+++ b/libc/bionic/pthread_exit.cpp
@@ -33,10 +33,11 @@
 #include <string.h>
 #include <sys/mman.h>
 
-#include "private/bionic_constants.h"
-#include "private/bionic_defs.h"
+#include "platform/bionic/mte.h"
 #include "private/ScopedRWLock.h"
 #include "private/ScopedSignalBlocker.h"
+#include "private/bionic_constants.h"
+#include "private/bionic_defs.h"
 #include "pthread_internal.h"
 
 extern "C" __noreturn void _exit_with_stack_teardown(void*, size_t);
@@ -67,7 +68,7 @@
 }
 
 __BIONIC_WEAK_FOR_NATIVE_BRIDGE
-void pthread_exit(void* return_value) {
+__attribute__((no_sanitize("memtag"))) void pthread_exit(void* return_value) {
   // Call dtors for thread_local objects first.
   __cxa_thread_finalize();
 
@@ -138,6 +139,13 @@
   __notify_thread_exit_callbacks();
   __hwasan_thread_exit();
 
+#if defined(__aarch64__)
+  if (void* stack_mte_tls = thread->bionic_tcb->tls_slot(TLS_SLOT_STACK_MTE)) {
+    stack_mte_free_ringbuffer(reinterpret_cast<uintptr_t>(stack_mte_tls));
+  }
+#endif
+  // Everything below this line needs to be no_sanitize("memtag").
+
   if (old_state == THREAD_DETACHED && thread->mmap_size != 0) {
     // We need to free mapped space for detached threads when they exit.
     // That's not something we can do in C.
diff --git a/libc/bionic/time_l.cpp b/libc/bionic/pthread_getaffinity.cpp
similarity index 75%
copy from libc/bionic/time_l.cpp
copy to libc/bionic/pthread_getaffinity.cpp
index e5fa9a5..9ce436c 100644
--- a/libc/bionic/time_l.cpp
+++ b/libc/bionic/pthread_getaffinity.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,9 +26,17 @@
  * SUCH DAMAGE.
  */
 
-#include <time.h>
-//#include <xlocale.h>
+#include <errno.h>
 
-char* strptime_l(const char* buf, const char* fmt, struct tm* tm, locale_t) {
-  return strptime(buf, fmt, tm);
+#include "private/ErrnoRestorer.h"
+#include "pthread_internal.h"
+
+int pthread_getaffinity_np(pthread_t t, size_t cpu_set_size, cpu_set_t* cpu_set) {
+  ErrnoRestorer errno_restorer;
+
+  pid_t tid = __pthread_internal_gettid(t, "pthread_getaffinity_np");
+  if (tid == -1) return ESRCH;
+
+  if (sched_getaffinity(tid, cpu_set_size, cpu_set) == -1) return errno;
+  return 0;
 }
diff --git a/libc/bionic/pthread_internal.cpp b/libc/bionic/pthread_internal.cpp
index 14cc7da..4f2ad0c 100644
--- a/libc/bionic/pthread_internal.cpp
+++ b/libc/bionic/pthread_internal.cpp
@@ -34,6 +34,7 @@
 #include <string.h>
 #include <sys/mman.h>
 #include <sys/prctl.h>
+#include <sys/types.h>
 
 #include <async_safe/log.h>
 #include <bionic/mte.h>
@@ -76,15 +77,6 @@
 }
 
 static void __pthread_internal_free(pthread_internal_t* thread) {
-#ifdef __aarch64__
-  if (void* stack_mte_tls = thread->bionic_tcb->tls_slot(TLS_SLOT_STACK_MTE)) {
-    size_t size =
-        stack_mte_ringbuffer_size_from_pointer(reinterpret_cast<uintptr_t>(stack_mte_tls));
-    void* ptr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(stack_mte_tls) &
-                                        ((1ULL << 56ULL) - 1ULL));
-    munmap(ptr, size);
-  }
-#endif
   if (thread->mmap_size != 0) {
     // Free mapped space, including thread stack and pthread_internal_t.
     munmap(thread->mmap_base, thread->mmap_size);
@@ -216,7 +208,10 @@
   __libc_memtag_stack_abi = true;
 
   for (pthread_internal_t* t = g_thread_list; t != nullptr; t = t->next) {
-    if (t->terminating) continue;
+    // should_allocate_stack_mte_ringbuffer indicates the thread is already
+    // aware that this process requires stack MTE, and will allocate the
+    // ring buffer in __pthread_start.
+    if (t->terminating || t->should_allocate_stack_mte_ringbuffer) continue;
     t->bionic_tcb->tls_slot(TLS_SLOT_STACK_MTE) =
         __allocate_stack_mte_ringbuffer(0, t->is_main() ? nullptr : t);
   }
@@ -264,8 +259,7 @@
   g_func = func;
   g_arg = arg;
 
-  static _Atomic(bool) g_retval;
-  atomic_init(&g_retval, true);
+  static _Atomic(bool) g_retval(true);
 
   auto handler = [](int, siginfo_t*, void*) {
     ErrnoRestorer restorer;
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index 5db42ab..cbaa9a6 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -181,6 +181,7 @@
 
   bionic_tcb* bionic_tcb;
   char stack_mte_ringbuffer_vma_name_buffer[32];
+  bool should_allocate_stack_mte_ringbuffer;
 
   bool is_main() { return start_routine == nullptr; }
 };
diff --git a/libc/bionic/pthread_mutex.cpp b/libc/bionic/pthread_mutex.cpp
index 9b37225..c99717a 100644
--- a/libc/bionic/pthread_mutex.cpp
+++ b/libc/bionic/pthread_mutex.cpp
@@ -182,7 +182,12 @@
         return 0;
     }
     if (ret == EBUSY) {
-        ScopedTrace trace("Contending for pthread mutex");
+        char trace_msg[64];
+        const pid_t owner = atomic_load_explicit(&mutex.owner_tid, memory_order_relaxed)
+                & FUTEX_TID_MASK;
+        snprintf(trace_msg, sizeof(trace_msg),
+                 "Contending for pthread mutex owned by tid: %d", owner);
+        ScopedTrace trace(trace_msg);
         ret = -__futex_pi_lock_ex(&mutex.owner_tid, mutex.shared, use_realtime_clock, abs_timeout);
     }
     return ret;
@@ -504,8 +509,8 @@
     memset(mutex, 0, sizeof(pthread_mutex_internal_t));
 
     if (__predict_true(attr == nullptr)) {
-        atomic_init(&mutex->state, MUTEX_TYPE_BITS_NORMAL);
-        return 0;
+      atomic_store_explicit(&mutex->state, MUTEX_TYPE_BITS_NORMAL, memory_order_relaxed);
+      return 0;
     }
 
     uint16_t state = 0;
@@ -538,13 +543,13 @@
         }
         mutex->pi_mutex_id = id;
 #endif
-        atomic_init(&mutex->state, PI_MUTEX_STATE);
+        atomic_store_explicit(&mutex->state, PI_MUTEX_STATE, memory_order_relaxed);
         PIMutex& pi_mutex = mutex->ToPIMutex();
         pi_mutex.type = *attr & MUTEXATTR_TYPE_MASK;
         pi_mutex.shared = (*attr & MUTEXATTR_SHARED_MASK) != 0;
     } else {
-        atomic_init(&mutex->state, state);
-        atomic_init(&mutex->owner_tid, 0);
+      atomic_store_explicit(&mutex->state, state, memory_order_relaxed);
+      atomic_store_explicit(&mutex->owner_tid, 0, memory_order_relaxed);
     }
     return 0;
 }
diff --git a/libc/bionic/pthread_rwlock.cpp b/libc/bionic/pthread_rwlock.cpp
index 6f3c6fe..92134b4 100644
--- a/libc/bionic/pthread_rwlock.cpp
+++ b/libc/bionic/pthread_rwlock.cpp
@@ -247,7 +247,7 @@
     }
   }
 
-  atomic_init(&rwlock->state, 0);
+  atomic_store_explicit(&rwlock->state, 0, memory_order_relaxed);
   rwlock->pending_lock.init(rwlock->pshared);
   return 0;
 }
diff --git a/libc/arch-x86/generic/string/wcscat.c b/libc/bionic/pthread_setaffinity.cpp
similarity index 74%
copy from libc/arch-x86/generic/string/wcscat.c
copy to libc/bionic/pthread_setaffinity.cpp
index a102551..6db418e 100644
--- a/libc/arch-x86/generic/string/wcscat.c
+++ b/libc/bionic/pthread_setaffinity.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,5 +26,17 @@
  * SUCH DAMAGE.
  */
 
-#define wcscat wcscat_freebsd
-#include <upstream-freebsd/lib/libc/string/wcscat.c>
+#include <errno.h>
+
+#include "private/ErrnoRestorer.h"
+#include "pthread_internal.h"
+
+int pthread_setaffinity_np(pthread_t t, size_t cpu_set_size, const cpu_set_t* cpu_set) {
+  ErrnoRestorer errno_restorer;
+
+  pid_t tid = __pthread_internal_gettid(t, "pthread_setaffinity_np");
+  if (tid == -1) return ESRCH;
+
+  if (sched_setaffinity(tid, cpu_set_size, cpu_set) == -1) return errno;
+  return 0;
+}
diff --git a/libc/bionic/pthread_sigqueue.cpp b/libc/bionic/pthread_sigqueue.cpp
index 93c349e..7c10b25 100644
--- a/libc/bionic/pthread_sigqueue.cpp
+++ b/libc/bionic/pthread_sigqueue.cpp
@@ -40,14 +40,16 @@
 int pthread_sigqueue(pthread_t t, int sig, const union sigval value) {
   ErrnoRestorer errno_restorer;
 
+  pid_t pid = getpid();
+
   pid_t tid = __pthread_internal_gettid(t, "pthread_sigqueue");
   if (tid == -1) return ESRCH;
 
-  siginfo_t siginfo;
-  siginfo.si_code = SI_QUEUE;
-  siginfo.si_pid = getpid();
+  siginfo_t siginfo = { .si_code = SI_QUEUE };
+  siginfo.si_signo = sig;
+  siginfo.si_pid = pid;
   siginfo.si_uid = getuid();
   siginfo.si_value = value;
 
-  return syscall(__NR_rt_tgsigqueueinfo, getpid(), tid, sig, &siginfo) ? errno : 0;
+  return syscall(__NR_rt_tgsigqueueinfo, pid, tid, sig, &siginfo) ? errno : 0;
 }
diff --git a/libc/bionic/semaphore.cpp b/libc/bionic/semaphore.cpp
index 33552a9..2c9b745 100644
--- a/libc/bionic/semaphore.cpp
+++ b/libc/bionic/semaphore.cpp
@@ -113,7 +113,7 @@
   }
 
   atomic_uint* sem_count_ptr = SEM_TO_ATOMIC_POINTER(sem);
-  atomic_init(sem_count_ptr, count);
+  atomic_store_explicit(sem_count_ptr, count, memory_order_relaxed);
   return 0;
 }
 
diff --git a/libc/bionic/signal.cpp b/libc/bionic/signal.cpp
index 2cf9940..5979ed7 100644
--- a/libc/bionic/signal.cpp
+++ b/libc/bionic/signal.cpp
@@ -219,10 +219,8 @@
 }
 
 int sigqueue(pid_t pid, int sig, const sigval value) {
-  siginfo_t info;
-  memset(&info, 0, sizeof(siginfo_t));
+  siginfo_t info = { .si_code = SI_QUEUE };
   info.si_signo = sig;
-  info.si_code = SI_QUEUE;
   info.si_pid = getpid();
   info.si_uid = getuid();
   info.si_value = value;
diff --git a/libc/bionic/sigprocmask.cpp b/libc/bionic/sigprocmask.cpp
index 6d436a6..10e2fa3 100644
--- a/libc/bionic/sigprocmask.cpp
+++ b/libc/bionic/sigprocmask.cpp
@@ -41,18 +41,6 @@
 // can't allow clang to decide to inline sigprocmask.
 //
 
-int sigprocmask(int how,
-                const sigset_t* bionic_new_set,
-                sigset_t* bionic_old_set) __attribute__((__noinline__)) {
-  SigSetConverter new_set{bionic_new_set};
-  SigSetConverter old_set{bionic_old_set};
-  int rc = sigprocmask64(how, new_set.ptr, old_set.ptr);
-  if (rc == 0 && bionic_old_set != nullptr) {
-    old_set.copy_out();
-  }
-  return rc;
-}
-
 int sigprocmask64(int how,
                   const sigset64_t* new_set,
                   sigset64_t* old_set) __attribute__((__noinline__)) {
@@ -70,3 +58,21 @@
   }
   return __rt_sigprocmask(how, mutable_new_set_ptr, old_set, sizeof(*new_set));
 }
+
+#if defined(__LP64__)
+// For LP64, `sigset64_t` and `sigset_t` are the same.
+__strong_alias(sigprocmask, sigprocmask64);
+#else
+// ILP32 needs a shim.
+int sigprocmask(int how,
+                const sigset_t* bionic_new_set,
+                sigset_t* bionic_old_set) __attribute__((__noinline__)) {
+  SigSetConverter new_set{bionic_new_set};
+  SigSetConverter old_set{bionic_old_set};
+  int rc = sigprocmask64(how, new_set.ptr, old_set.ptr);
+  if (rc == 0 && bionic_old_set != nullptr) {
+    old_set.copy_out();
+  }
+  return rc;
+}
+#endif
diff --git a/libc/bionic/spawn.cpp b/libc/bionic/spawn.cpp
index 38f99ad..d97057f 100644
--- a/libc/bionic/spawn.cpp
+++ b/libc/bionic/spawn.cpp
@@ -186,8 +186,8 @@
                        char* const argv[],
                        char* const env[],
                        int exec_fn(const char* path, char* const argv[], char* const env[])) {
-  // See http://man7.org/linux/man-pages/man3/posix_spawn.3.html
-  // and http://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html
+  // See https://man7.org/linux/man-pages/man3/posix_spawn.3.html
+  // and https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/posix_spawn.html
 
   ScopedSignalBlocker ssb;
 
diff --git a/libc/bionic/stdlib_l.cpp b/libc/bionic/stdlib_l.cpp
index 18e9f86..58a9079 100644
--- a/libc/bionic/stdlib_l.cpp
+++ b/libc/bionic/stdlib_l.cpp
@@ -26,34 +26,11 @@
  * SUCH DAMAGE.
  */
 
+#define __BIONIC_STDLIB_INLINE /* Out of line. */
 #include <stdlib.h>
-#include <xlocale.h>
+#include <bits/stdlib_inlines.h>
 
-double strtod_l(const char* s, char** end_ptr, locale_t) {
-  return strtod(s, end_ptr);
-}
-
-float strtof_l(const char* s, char** end_ptr, locale_t) {
-  return strtof(s, end_ptr);
-}
-
-long strtol_l(const char* s, char** end_ptr, int base, locale_t) {
-  return strtol(s, end_ptr, base);
-}
-
+// strtold_l was introduced in API level 21, so it isn't polyfilled any more.
 long double strtold_l(const char* s, char** end_ptr, locale_t) {
   return strtold(s, end_ptr);
 }
-
-long long strtoll_l(const char* s, char** end_ptr, int base, locale_t) {
-  return strtoll(s, end_ptr, base);
-}
-
-unsigned long strtoul_l(const char* s, char** end_ptr, int base, locale_t) {
-  return strtoul(s, end_ptr, base);
-}
-
-unsigned long long strtoull_l(const char* s, char** end_ptr, int base, locale_t) {
-  return strtoull(s, end_ptr, base);
-}
-
diff --git a/libc/bionic/strerror.cpp b/libc/bionic/strerror.cpp
index 743130d..c41b547 100644
--- a/libc/bionic/strerror.cpp
+++ b/libc/bionic/strerror.cpp
@@ -102,3 +102,4 @@
   strerror_r(error_number, result, sizeof(tls.strerror_buf));
   return result;
 }
+__strong_alias(strerror_l, strerror);
diff --git a/libc/bionic/string_l.cpp b/libc/bionic/string_l.cpp
index 66bfb0e..84396bf 100644
--- a/libc/bionic/string_l.cpp
+++ b/libc/bionic/string_l.cpp
@@ -33,10 +33,6 @@
   return strcoll(s1, s2);
 }
 
-char* strerror_l(int error, locale_t) {
-  return strerror(error);
-}
-
 size_t strxfrm_l(char* dst, const char* src, size_t n, locale_t) {
   return strxfrm(dst, src, n);
 }
diff --git a/libc/bionic/strsignal.cpp b/libc/bionic/strsignal.cpp
index f18b6d0..29c22e2 100644
--- a/libc/bionic/strsignal.cpp
+++ b/libc/bionic/strsignal.cpp
@@ -27,29 +27,29 @@
  */
 
 #include <signal.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "bionic/pthread_internal.h"
 
+// Maps regular signals like SIGSEGV to strings like "Segmentation fault".
+// Signal 0 and all the real-time signals are just nullptr, but that's the ABI.
 const char* const sys_siglist[NSIG] = {
 #define __BIONIC_SIGDEF(signal_number, signal_description) [signal_number] = signal_description,
 #include "private/bionic_sigdefs.h"
 };
 
+// Maps regular signals like SIGSEGV to strings like "SEGV".
+// Signal 0 and all the real-time signals are just nullptr, but that's the ABI.
 const char* const sys_signame[NSIG] = {
 #define __BIONIC_SIGDEF(signal_number, unused) [signal_number] = &(#signal_number)[3],
 #include "private/bionic_sigdefs.h"
 };
 
 extern "C" __LIBC_HIDDEN__ const char* __strsignal(int signal_number, char* buf, size_t buf_len) {
-  const char* signal_name = nullptr;
-  if (signal_number >= 0 && signal_number < NSIG) {
-    signal_name = sys_siglist[signal_number];
+  if (signal_number >= SIGHUP && signal_number < SIGSYS) {
+    return sys_siglist[signal_number];
   }
-  if (signal_name != nullptr) {
-    return signal_name;
-  }
-
   const char* prefix = "Unknown";
   if (signal_number >= SIGRTMIN && signal_number <= SIGRTMAX) {
     prefix = "Real-time";
@@ -66,3 +66,72 @@
   bionic_tls& tls = __get_bionic_tls();
   return const_cast<char*>(__strsignal(signal_number, tls.strsignal_buf, sizeof(tls.strsignal_buf)));
 }
+
+int sig2str(int sig, char* str) {
+  if (sig >= SIGHUP && sig <= SIGSYS) {
+    strcpy(str, sys_signame[sig]);
+    return 0;
+  }
+  if (sig == SIGRTMIN) {
+    strcpy(str, "RTMIN");
+    return 0;
+  }
+  if (sig == SIGRTMAX) {
+    strcpy(str, "RTMAX");
+    return 0;
+  }
+  if (sig > SIGRTMIN && sig < SIGRTMAX) {
+    if (sig - SIGRTMIN <= SIGRTMAX - sig) {
+      sprintf(str, "RTMIN+%d", sig - SIGRTMIN);
+    } else {
+      sprintf(str, "RTMAX-%d", SIGRTMAX - sig);
+    }
+    return 0;
+  }
+  return -1;
+}
+
+int str2sig(const char* str, int* sig) {
+  // A name in our list, like "SEGV"?
+  for (size_t i = SIGHUP; i <= SIGSYS; ++i) {
+    if (!strcmp(str, sys_signame[i])) {
+      *sig = i;
+      return 0;
+    }
+  }
+
+  // The two named special cases?
+  if (!strcmp(str, "RTMIN")) {
+    *sig = SIGRTMIN;
+    return 0;
+  }
+  if (!strcmp(str, "RTMAX")) {
+    *sig = SIGRTMAX;
+    return 0;
+  }
+
+  // Must be either an integer corresponding to a regular signal such as "9",
+  // or a string of the form "RTMIN+%d" or "RTMAX-%d".
+  int base = 0;
+  if (!strncmp(str, "RTMIN+", 6)) {
+    base = SIGRTMIN;
+    str += 5;
+  } else if (!strncmp(str, "RTMAX-", 6)) {
+    base = SIGRTMAX;
+    str += 5;
+  }
+  char* end = nullptr;
+  errno = 0;
+  int offset = strtol(str, &end, 10);
+  if (errno || *end) return -1;
+
+  // Reject out of range integers (like "666"),
+  // and out of range real-time signals (like "RTMIN+666" or "RTMAX-666").
+  int result = base + offset;
+  bool regular = (base == 0 && result >= SIGHUP && result <= SIGSYS);
+  bool realtime = (result >= SIGRTMIN && result <= SIGRTMAX);
+  if (!regular && !realtime) return -1;
+
+  *sig = result;
+  return 0;
+}
diff --git a/libc/bionic/strtol.cpp b/libc/bionic/strtol.cpp
index def7921..607145d 100644
--- a/libc/bionic/strtol.cpp
+++ b/libc/bionic/strtol.cpp
@@ -142,34 +142,42 @@
 long strtol(const char* s, char** end, int base) {
   return StrToI<long, LONG_MIN, LONG_MAX, char>(s, end, base);
 }
+__strong_alias(strtol_l, strtol);
 
 long wcstol(const wchar_t* s, wchar_t** end, int base) {
   return StrToI<long, LONG_MIN, LONG_MAX, wchar_t>(s, end, base);
 }
+__strong_alias(wcstol_l, wcstol);
 
 long long strtoll(const char* s, char** end, int base) {
   return StrToI<long long, LLONG_MIN, LLONG_MAX, char>(s, end, base);
 }
+__strong_alias(strtoll_l, strtoll);
 
 long long wcstoll(const wchar_t* s, wchar_t** end, int base) {
   return StrToI<long long, LLONG_MIN, LLONG_MAX, wchar_t>(s, end, base);
 }
+__strong_alias(wcstoll_l, wcstoll);
 
 unsigned long strtoul(const char* s, char** end, int base) {
   return StrToI<unsigned long, 0, ULONG_MAX, char>(s, end, base);
 }
+__strong_alias(strtoul_l, strtoul);
 
 unsigned long wcstoul(const wchar_t* s, wchar_t** end, int base) {
   return StrToI<unsigned long, 0, ULONG_MAX, wchar_t>(s, end, base);
 }
+__strong_alias(wcstoul_l, wcstoul);
 
 unsigned long long strtoull(const char* s, char** end, int base) {
   return StrToI<unsigned long long, 0, ULLONG_MAX, char>(s, end, base);
 }
+__strong_alias(strtoull_l, strtoull);
 
 unsigned long long wcstoull(const wchar_t* s, wchar_t** end, int base) {
   return StrToI<unsigned long long, 0, ULLONG_MAX, wchar_t>(s, end, base);
 }
+__strong_alias(wcstoull_l, wcstoull);
 
 uintmax_t strtoumax(const char* s, char** end, int base) {
   return StrToI<uintmax_t, 0, UINTMAX_MAX, char>(s, end, base);
diff --git a/libc/bionic/sync_file_range.cpp b/libc/bionic/sync_file_range.cpp
index 7f60882..e7b904d 100644
--- a/libc/bionic/sync_file_range.cpp
+++ b/libc/bionic/sync_file_range.cpp
@@ -28,13 +28,12 @@
 
 #include <fcntl.h>
 
-extern "C" int __sync_file_range(int, off64_t, off64_t, unsigned int);
-extern "C" int __sync_file_range2(int, unsigned int, off64_t, off64_t);
-
-int sync_file_range(int fd, off64_t offset, off64_t length, unsigned int flags) {
 #if __arm__
+// Only arm32 is missing the sync_file_range() syscall,
+// and needs us to manually re-order arguments for it.
+// (Because arm32 needs register pairs for 64-bit values to start on an even register.)
+extern "C" int __sync_file_range2(int, unsigned int, off64_t, off64_t);
+int sync_file_range(int fd, off64_t offset, off64_t length, unsigned int flags) {
   return __sync_file_range2(fd, flags, offset, length);
-#else
-  return __sync_file_range(fd, offset, length, flags);
-#endif
 }
+#endif
diff --git a/libc/bionic/system.cpp b/libc/bionic/system.cpp
index 93d7497..8349498 100644
--- a/libc/bionic/system.cpp
+++ b/libc/bionic/system.cpp
@@ -38,7 +38,7 @@
 
 int system(const char* command) {
   // "The system() function shall always return non-zero when command is NULL."
-  // http://pubs.opengroup.org/onlinepubs/9699919799/functions/system.html
+  // https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/system.html
   if (command == nullptr) return 1;
 
   ScopedSignalBlocker sigchld_blocker(SIGCHLD);
diff --git a/libc/bionic/system_property_api.cpp b/libc/bionic/system_property_api.cpp
index 8fdea59..ed30fc2 100644
--- a/libc/bionic/system_property_api.cpp
+++ b/libc/bionic/system_property_api.cpp
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
+#include <sys/system_properties.h>
 
 #include <async_safe/CHECK.h>
 #include <system_properties/prop_area.h>
diff --git a/libc/bionic/system_property_set.cpp b/libc/bionic/system_property_set.cpp
index 73cf151..9d73445 100644
--- a/libc/bionic/system_property_set.cpp
+++ b/libc/bionic/system_property_set.cpp
@@ -34,11 +34,10 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
+#include <sys/system_properties.h>
 #include <sys/types.h>
 #include <sys/uio.h>
 #include <sys/un.h>
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
 #include <unistd.h>
 
 #include <async_safe/log.h>
diff --git a/libc/bionic/wchar_l.cpp b/libc/bionic/wchar_l.cpp
index 1e7a231..b2c4a00 100644
--- a/libc/bionic/wchar_l.cpp
+++ b/libc/bionic/wchar_l.cpp
@@ -41,34 +41,6 @@
   return wcscoll(ws1, ws2);
 }
 
-double wcstod_l(const wchar_t* s, wchar_t** end_ptr, locale_t) {
-  return wcstod(s, end_ptr);
-}
-
-float wcstof_l(const wchar_t* s, wchar_t** end_ptr, locale_t) {
-  return wcstof(s, end_ptr);
-}
-
-long wcstol_l(const wchar_t* s, wchar_t** end_ptr, int base, locale_t) {
-  return wcstol(s, end_ptr, base);
-}
-
-long long wcstoll_l(const wchar_t* s, wchar_t** end_ptr, int base, locale_t) {
-  return wcstoll(s, end_ptr, base);
-}
-
-unsigned long wcstoul_l(const wchar_t* s, wchar_t** end_ptr, int base, locale_t) {
-  return wcstoul(s, end_ptr, base);
-}
-
-unsigned long long wcstoull_l(const wchar_t* s, wchar_t** end_ptr, int base, locale_t) {
-  return wcstoull(s, end_ptr, base);
-}
-
-long double wcstold_l(const wchar_t* s, wchar_t** end_ptr, locale_t) {
-  return wcstold(s, end_ptr);
-}
-
 size_t wcsxfrm_l(wchar_t* dst, const wchar_t* src, size_t n, locale_t) {
   return wcsxfrm(dst, src, n);
 }
diff --git a/libc/bionic/wcstod.cpp b/libc/bionic/wcstod.cpp
index c82d788..00c8a08 100644
--- a/libc/bionic/wcstod.cpp
+++ b/libc/bionic/wcstod.cpp
@@ -94,11 +94,14 @@
 float wcstof(const wchar_t* s, wchar_t** end) {
   return wcstod<float>(s, end, strtof);
 }
+__strong_alias(wcstof_l, wcstof);
 
 double wcstod(const wchar_t* s, wchar_t** end) {
   return wcstod<double>(s, end, strtod);
 }
+__strong_alias(wcstod_l, wcstod);
 
 long double wcstold(const wchar_t* s, wchar_t** end) {
   return wcstod<long double>(s, end, strtold);
 }
+__strong_alias(wcstold_l, wcstold);
diff --git a/libc/bionic/wctype.cpp b/libc/bionic/wctype.cpp
index b37f17b..94597d9 100644
--- a/libc/bionic/wctype.cpp
+++ b/libc/bionic/wctype.cpp
@@ -54,46 +54,62 @@
   WC_TYPE_MAX
 };
 
-int iswalnum(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_POSIX_ALNUM, isalnum); }
-int iswalpha(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_ALPHABETIC, isalpha); }
-int iswblank(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_POSIX_BLANK, isblank); }
-int iswgraph(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_POSIX_GRAPH, isgraph); }
-int iswlower(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_LOWERCASE, islower); }
-int iswprint(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_POSIX_PRINT, isprint); }
-int iswspace(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_WHITE_SPACE, isspace); }
-int iswupper(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_UPPERCASE, isupper); }
-int iswxdigit(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_POSIX_XDIGIT, isxdigit); }
+static u_hasBinaryProperty_t __find_u_hasBinaryProperty() {
+  static auto u_hasBinaryProperty =
+      reinterpret_cast<u_hasBinaryProperty_t>(__find_icu_symbol("u_hasBinaryProperty"));
+  return u_hasBinaryProperty;
+}
+
+#define DO_ISW(icu_constant, narrow_fn) \
+  u_hasBinaryProperty_t u_hasBinaryProperty; \
+  if (__predict_true(wc < 0x80) || \
+      !(u_hasBinaryProperty = __find_u_hasBinaryProperty())) { \
+    return narrow_fn(wc); \
+  } \
+  return u_hasBinaryProperty(wc, icu_constant); \
+
+int iswalnum(wint_t wc) { DO_ISW(UCHAR_POSIX_ALNUM, isalnum); }
+__strong_alias(iswalnum_l, iswalnum);
+int iswalpha(wint_t wc) { DO_ISW(UCHAR_ALPHABETIC, isalpha); }
+__strong_alias(iswalpha_l, iswalpha);
+int iswblank(wint_t wc) { DO_ISW(UCHAR_POSIX_BLANK, isblank); }
+__strong_alias(iswblank_l, iswblank);
+int iswgraph(wint_t wc) { DO_ISW(UCHAR_POSIX_GRAPH, isgraph); }
+__strong_alias(iswgraph_l, iswgraph);
+int iswlower(wint_t wc) { DO_ISW(UCHAR_LOWERCASE, islower); }
+__strong_alias(iswlower_l, iswlower);
+int iswprint(wint_t wc) { DO_ISW(UCHAR_POSIX_PRINT, isprint); }
+__strong_alias(iswprint_l, iswprint);
+int iswspace(wint_t wc) { DO_ISW(UCHAR_WHITE_SPACE, isspace); }
+__strong_alias(iswspace_l, iswspace);
+int iswupper(wint_t wc) { DO_ISW(UCHAR_UPPERCASE, isupper); }
+__strong_alias(iswupper_l, iswupper);
+int iswxdigit(wint_t wc) { DO_ISW(UCHAR_POSIX_XDIGIT, isxdigit); }
+__strong_alias(iswxdigit_l, iswxdigit);
 
 int iswcntrl(wint_t wc) {
+  if (wc < 0x80) return iscntrl(wc);
   typedef int8_t (*FnT)(UChar32);
   static auto u_charType = reinterpret_cast<FnT>(__find_icu_symbol("u_charType"));
   return u_charType ? (u_charType(wc) == U_CONTROL_CHAR) : iscntrl(wc);
 }
+__strong_alias(iswcntrl_l, iswcntrl);
 
 int iswdigit(wint_t wc) {
+  if (wc < 0x80) return isdigit(wc);
   typedef UBool (*FnT)(UChar32);
   static auto u_isdigit = reinterpret_cast<FnT>(__find_icu_symbol("u_isdigit"));
   return u_isdigit ? u_isdigit(wc) : isdigit(wc);
 }
+__strong_alias(iswdigit_l, iswdigit);
 
 int iswpunct(wint_t wc) {
+  if (wc < 0x80) return ispunct(wc);
   typedef UBool (*FnT)(UChar32);
   static auto u_ispunct = reinterpret_cast<FnT>(__find_icu_symbol("u_ispunct"));
   return u_ispunct ? u_ispunct(wc) : ispunct(wc);
 }
-
-int iswalnum_l(wint_t c, locale_t) { return iswalnum(c); }
-int iswalpha_l(wint_t c, locale_t) { return iswalpha(c); }
-int iswblank_l(wint_t c, locale_t) { return iswblank(c); }
-int iswcntrl_l(wint_t c, locale_t) { return iswcntrl(c); }
-int iswdigit_l(wint_t c, locale_t) { return iswdigit(c); }
-int iswgraph_l(wint_t c, locale_t) { return iswgraph(c); }
-int iswlower_l(wint_t c, locale_t) { return iswlower(c); }
-int iswprint_l(wint_t c, locale_t) { return iswprint(c); }
-int iswpunct_l(wint_t c, locale_t) { return iswpunct(c); }
-int iswspace_l(wint_t c, locale_t) { return iswspace(c); }
-int iswupper_l(wint_t c, locale_t) { return iswupper(c); }
-int iswxdigit_l(wint_t c, locale_t) { return iswxdigit(c); }
+__strong_alias(iswpunct_l, iswpunct);
 
 int iswctype(wint_t wc, wctype_t char_class) {
   if (char_class < WC_TYPE_ALNUM || char_class > WC_TYPE_XDIGIT) return 0;
@@ -103,10 +119,7 @@
   };
   return fns[char_class - WC_TYPE_ALNUM](wc);
 }
-
-int iswctype_l(wint_t wc, wctype_t char_class, locale_t) {
-  return iswctype(wc, char_class);
-}
+__strong_alias(iswctype_l, iswctype);
 
 wint_t towlower(wint_t wc) {
   if (wc < 0x80) return tolower(wc);
@@ -115,6 +128,7 @@
   static auto u_tolower = reinterpret_cast<FnT>(__find_icu_symbol("u_tolower"));
   return u_tolower ? u_tolower(wc) : tolower(wc);
 }
+__strong_alias(towlower_l, towlower);
 
 wint_t towupper(wint_t wc) {
   if (wc < 0x80) return toupper(wc);
@@ -123,9 +137,7 @@
   static auto u_toupper = reinterpret_cast<FnT>(__find_icu_symbol("u_toupper"));
   return u_toupper ? u_toupper(wc) : toupper(wc);
 }
-
-wint_t towupper_l(wint_t c, locale_t) { return towupper(c); }
-wint_t towlower_l(wint_t c, locale_t) { return towlower(c); }
+__strong_alias(towupper_l, towupper);
 
 wctype_t wctype(const char* property) {
   static const char* const  properties[WC_TYPE_MAX - 1] = {
@@ -139,10 +151,7 @@
   }
   return static_cast<wctype_t>(0);
 }
-
-wctype_t wctype_l(const char* property, locale_t) {
-  return wctype(property);
-}
+__strong_alias(wctype_l, wctype);
 
 static wctrans_t wctrans_tolower = wctrans_t(1);
 static wctrans_t wctrans_toupper = wctrans_t(2);
@@ -153,10 +162,7 @@
   errno = EINVAL;
   return nullptr;
 }
-
-wctrans_t wctrans_l(const char* name, locale_t) {
-  return wctrans(name);
-}
+__strong_alias(wctrans_l, wctrans);
 
 wint_t towctrans(wint_t c, wctrans_t t) {
   if (t == wctrans_tolower) return towlower(c);
@@ -164,7 +170,4 @@
   errno = EINVAL;
   return c;
 }
-
-wint_t towctrans_l(wint_t c, wctrans_t t, locale_t) {
-  return towctrans(c, t);
-}
+__strong_alias(towctrans_l, towctrans);
diff --git a/libc/bionic/wcwidth.cpp b/libc/bionic/wcwidth.cpp
index 4582ef7..776321f 100644
--- a/libc/bionic/wcwidth.cpp
+++ b/libc/bionic/wcwidth.cpp
@@ -73,7 +73,9 @@
 
   // Hangeul choseong filler U+115F is default ignorable, so we check default
   // ignorability only after we've already handled Hangeul jamo above.
-  if (__icu_hasBinaryProperty(wc, UCHAR_DEFAULT_IGNORABLE_CODE_POINT, nullptr)) return 0;
+  static auto u_hasBinaryProperty =
+      reinterpret_cast<u_hasBinaryProperty_t>(__find_icu_symbol("u_hasBinaryProperty"));
+  if (u_hasBinaryProperty && u_hasBinaryProperty(wc, UCHAR_DEFAULT_IGNORABLE_CODE_POINT)) return 0;
 
   // A few weird special cases where EastAsianWidth is not helpful for us.
   if (wc >= 0x3248 && wc <= 0x4dff) {
diff --git a/libc/dns/net/gethnamaddr.c b/libc/dns/net/gethnamaddr.c
index add124f..1ffabfa 100644
--- a/libc/dns/net/gethnamaddr.c
+++ b/libc/dns/net/gethnamaddr.c
@@ -495,7 +495,7 @@
 	*he = NO_RECOVERY;
 	return NULL;
 success:
-	bp = (char *)ALIGN(bp);
+	bp = __builtin_align_up(bp, sizeof(uintptr_t));
 	n = (int)(ap - aliases);
 	qlen = (n + 1) * sizeof(*hent->h_aliases);
 	if ((size_t)(ep - bp) < qlen)
@@ -616,7 +616,7 @@
 	}
 
 	// Fix alignment after variable-length data.
-	ptr = (char*)ALIGN(ptr);
+	ptr = __builtin_align_up(ptr, sizeof(uintptr_t));
 
 	int aliases_len = ((int)(aliases - aliases_ptrs) + 1) * sizeof(*hp->h_aliases);
 	if (ptr + aliases_len > hbuf_end) {
@@ -653,7 +653,7 @@
 	}
 
 	// Fix alignment after variable-length data.
-	ptr = (char*)ALIGN(ptr);
+	ptr = __builtin_align_up(ptr, sizeof(uintptr_t));
 
 	int addrs_len = ((int)(addr_p - addr_ptrs) + 1) * sizeof(*hp->h_addr_list);
 	if (ptr + addrs_len > hbuf_end) {
diff --git a/libc/dns/net/sethostent.c b/libc/dns/net/sethostent.c
index 5c4bdb5..8ea4315 100644
--- a/libc/dns/net/sethostent.c
+++ b/libc/dns/net/sethostent.c
@@ -198,7 +198,7 @@
 				HENT_SCOPY(aliases[anum], hp->h_aliases[anum],
 				    ptr, len);
 			}
-			ptr = (void *)ALIGN(ptr);
+			ptr = __builtin_align_up(ptr, sizeof(uintptr_t));
 			if ((size_t)(ptr - buf) >= info->buflen)
 				goto nospc;
 		}
diff --git a/libc/execinfo/include/execinfo.h b/libc/execinfo/include/execinfo.h
index e092c00..c8f9e21 100644
--- a/libc/execinfo/include/execinfo.h
+++ b/libc/execinfo/include/execinfo.h
@@ -30,8 +30,10 @@
 
 /*
  * This file is exported as part of libexecinfo for use with musl, which doesn't
- * define __INTRODUCED_IN.  Stub it out.
+ * define __INTRODUCED_IN or __BIONIC_AVAILABILITY_GUARD.  Stub them out.
  */
 #define __INTRODUCED_IN(x)
+#define __BIONIC_AVAILABILITY_GUARD(x) 1
 #include <bionic/execinfo.h>
+#undef __BIONIC_AVAILABILITY_GUARD
 #undef __INTRODUCED_IN
diff --git a/libc/include/alloca.h b/libc/include/alloca.h
index e05dea6..2786e2f 100644
--- a/libc/include/alloca.h
+++ b/libc/include/alloca.h
@@ -36,7 +36,7 @@
 #include <sys/cdefs.h>
 
 /**
- * [alloca(3)](http://man7.org/linux/man-pages/man3/alloca.3.html) allocates space on the stack.
+ * [alloca(3)](https://man7.org/linux/man-pages/man3/alloca.3.html) allocates space on the stack.
  *
  * New code should not use alloca because it cannot report failure.
  * Use regular heap allocation instead.
diff --git a/libc/include/android/api-level.h b/libc/include/android/api-level.h
index 1bde3a5..c9536c1 100644
--- a/libc/include/android/api-level.h
+++ b/libc/include/android/api-level.h
@@ -189,7 +189,11 @@
  *
  * Available since API level 24.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 int android_get_application_target_sdk_version() __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 
 #if __ANDROID_API__ < 29
 
diff --git a/libc/include/android/crash_detail.h b/libc/include/android/crash_detail.h
index 946a3ab..fd1312a 100644
--- a/libc/include/android/crash_detail.h
+++ b/libc/include/android/crash_detail.h
@@ -33,9 +33,10 @@
  * @brief Attach extra information to android crashes.
  */
 
-#include <stddef.h>
 #include <sys/cdefs.h>
 
+#include <stddef.h>
+
 __BEGIN_DECLS
 
 typedef struct crash_detail_t crash_detail_t;
@@ -79,6 +80,8 @@
  *
  * \return a handle to the extra crash detail.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(35)
 crash_detail_t* _Nullable android_crash_detail_register(
     const void* _Nonnull name, size_t name_size, const void* _Nullable data, size_t data_size) __INTRODUCED_IN(35);
 
@@ -122,5 +125,7 @@
  * \param name_size number of bytes of the buffer pointed to by name
  */
 void android_crash_detail_replace_name(crash_detail_t* _Nonnull crash_detail, const void* _Nonnull name, size_t name_size) __INTRODUCED_IN(35);
+#endif /* __BIONIC_AVAILABILITY_GUARD(35) */
+
 
 __END_DECLS
diff --git a/libc/include/android/dlext.h b/libc/include/android/dlext.h
index b42e5b2..d8d2752 100644
--- a/libc/include/android/dlext.h
+++ b/libc/include/android/dlext.h
@@ -16,10 +16,11 @@
 
 #pragma once
 
+#include <sys/cdefs.h>
+
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
-#include <sys/cdefs.h>
 #include <sys/types.h>  /* for off64_t */
 
 /**
@@ -30,7 +31,7 @@
 /**
  * \file
  * Advanced dynamic library opening support. Most users will want to use
- * the standard [dlopen(3)](http://man7.org/linux/man-pages/man3/dlopen.3.html)
+ * the standard [dlopen(3)](https://man7.org/linux/man-pages/man3/dlopen.3.html)
  * functionality in `<dlfcn.h>` instead.
  */
 
@@ -174,7 +175,7 @@
 
 /**
  * Opens the given library. The `__filename` and `__flags` arguments are
- * the same as for [dlopen(3)](http://man7.org/linux/man-pages/man3/dlopen.3.html),
+ * the same as for [dlopen(3)](https://man7.org/linux/man-pages/man3/dlopen.3.html),
  * with the Android-specific flags supplied via the `flags` member of `__info`.
  */
 void* _Nullable android_dlopen_ext(const char* _Nullable __filename, int __flags, const android_dlextinfo* _Nullable __info);
diff --git a/libc/include/android/fdsan.h b/libc/include/android/fdsan.h
index 4540498..a04fc7e 100644
--- a/libc/include/android/fdsan.h
+++ b/libc/include/android/fdsan.h
@@ -28,9 +28,10 @@
 
 #pragma once
 
+#include <sys/cdefs.h>
+
 #include <stdbool.h>
 #include <stdint.h>
-#include <sys/cdefs.h>
 
 __BEGIN_DECLS
 
@@ -134,6 +135,8 @@
 /*
  * Create an owner tag with the specified type and least significant 56 bits of tag.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(29)
 uint64_t android_fdsan_create_owner_tag(enum android_fdsan_owner_type type, uint64_t tag) __INTRODUCED_IN(29) __attribute__((__weak__));
 
 /*
@@ -168,6 +171,8 @@
  * Get an owner tag's value, with the type masked off.
  */
 uint64_t android_fdsan_get_tag_value(uint64_t tag) __INTRODUCED_IN(29);
+#endif /* __BIONIC_AVAILABILITY_GUARD(29) */
+
 
 enum android_fdsan_error_level {
   // No errors.
@@ -186,6 +191,8 @@
 /*
  * Get the error level.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(29)
 enum android_fdsan_error_level android_fdsan_get_error_level() __INTRODUCED_IN(29) __attribute__((__weak__));
 
 /*
@@ -203,9 +210,15 @@
  * (e.g. postfork).
  */
 enum android_fdsan_error_level android_fdsan_set_error_level(enum android_fdsan_error_level new_level) __INTRODUCED_IN(29) __attribute__((__weak__));
+#endif /* __BIONIC_AVAILABILITY_GUARD(29) */
+
 
 /*
  * Set the error level to the global setting if available, or a default value.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(30)
 enum android_fdsan_error_level android_fdsan_set_error_level_from_property(enum android_fdsan_error_level default_level) __INTRODUCED_IN(30) __attribute__((__weak__));
+#endif /* __BIONIC_AVAILABILITY_GUARD(30) */
+
 __END_DECLS
diff --git a/libc/include/android/legacy_stdlib_inlines.h b/libc/include/android/legacy_stdlib_inlines.h
index f0985fe..d228e67 100644
--- a/libc/include/android/legacy_stdlib_inlines.h
+++ b/libc/include/android/legacy_stdlib_inlines.h
@@ -30,26 +30,9 @@
 
 #include <sys/cdefs.h>
 
-
 #if __ANDROID_API__ < 26
 
-#include <stdlib.h>
-#include <xlocale.h>
-
-__BEGIN_DECLS
-
-static __inline double strtod_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, locale_t _Nonnull __l) {
-  return strtod(__s, __end_ptr);
-}
-
-static __inline float strtof_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, locale_t _Nonnull __l) {
-  return strtof(__s, __end_ptr);
-}
-
-static __inline long strtol_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base, locale_t _Nonnull __l) {
-  return strtol(__s, __end_ptr, __base);
-}
-
-__END_DECLS
+#define __BIONIC_THREADS_INLINE static __inline
+#include <bits/stdlib_inlines.h>
 
 #endif
diff --git a/libc/include/android/set_abort_message.h b/libc/include/android/set_abort_message.h
index a778057..6ad5678 100644
--- a/libc/include/android/set_abort_message.h
+++ b/libc/include/android/set_abort_message.h
@@ -33,10 +33,11 @@
  * @brief The android_set_abort_message() function.
  */
 
+#include <sys/cdefs.h>
+
 #include <stddef.h>
 #include <stdint.h>
 #include <string.h>
-#include <sys/cdefs.h>
 
 __BEGIN_DECLS
 
diff --git a/libc/include/android/versioning.h b/libc/include/android/versioning.h
index 6bab291..1cf6e51 100644
--- a/libc/include/android/versioning.h
+++ b/libc/include/android/versioning.h
@@ -16,45 +16,54 @@
 
 #pragma once
 
-// The `annotate` attribute always pulls the annotated (inline) function into the object files, thus
-// we should only annotate headers when we are running versioner.
-#if defined(__BIONIC_VERSIONER)
-
-#define __INTRODUCED_IN(api_level) __attribute__((__annotate__("introduced_in=" #api_level)))
-#define __INTRODUCED_IN_NO_GUARD_FOR_NDK(api_level) __attribute__((__annotate__("introduced_in=" #api_level))) __VERSIONER_NO_GUARD
-#define __DEPRECATED_IN(api_level, msg) __attribute__((__annotate__("deprecated_in=" #api_level)))
-#define __REMOVED_IN(api_level, msg) __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 __VERSIONER_NO_GUARD __attribute__((__annotate__("versioner_no_guard")))
-#define __VERSIONER_FORTIFY_INLINE __attribute__((__annotate__("versioner_fortify_inline")))
-
-#else
-
-// When headers are not processed by the versioner (i.e. compiled into object files),
-// the availability attributed is emitted instead. The clang compiler will make the symbol weak
-// when targeting old api_level and enforce the reference to the symbol to be guarded with
-// __builtin_available(android api_level, *).
-
-// The 'strict' flag is required for NDK clients where the use of "-Wunguarded-availability" cannot
-// be enforced. In the case, the absence of 'strict' makes it possible to call an unavailable API
-// without the __builtin_available check, which will cause a link error at runtime.
-// Android platform build system defines this macro along with -Wunguarded-availability
-//
-// The _NO_GUARD_FOR_NDK variants keep the __VERSIONER_NO_GUARD behavior working for the NDK. This
-// allows libc++ to refer to these functions in inlines without needing to guard them, needed since
-// libc++ doesn't currently guard these calls. There's no risk to the apps though because using
-// those APIs will still cause a link error.
+/**
+ * @def __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__
+ *
+ * Controls whether calling APIs newer than the developer's minSdkVersion are a
+ * build error (when not defined) or allowed as a weak reference with a
+ * __builtin_available() guard (when defined).
+ *
+ * See https://developer.android.com/ndk/guides/using-newer-apis for more
+ * details.
+ */
 #if defined(__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__)
+// In this mode, Clang will emit weak references to the APIs if the
+// minSdkVersion is less than the __what argument. This allows the libraries to
+// load even on systems too old to contain the API, but calls must be guarded
+// with `__builtin_available(android api_level, *)` to avoid segfaults.
 #define __BIONIC_AVAILABILITY(__what, ...) __attribute__((__availability__(android,__what __VA_OPT__(,) __VA_ARGS__)))
-#define __INTRODUCED_IN_NO_GUARD_FOR_NDK(api_level) __INTRODUCED_IN(api_level)
+
+// When the caller is using weak API references, we should expose the decls for
+// APIs which are not available in the caller's minSdkVersion, otherwise there's
+// no way to take advantage of the weak references.
+#define __BIONIC_AVAILABILITY_GUARD(api_level) 1
 #else
+// The 'strict' flag is required for NDK clients where the code was not written
+// to handle the case where the API was available at build-time but not at
+// run-time. Most 3p code ported to Android was not written to use
+// `__builtin_available()` for run-time availability checking, and so would not
+// compile in this mode (or worse, if the build doesn't use
+// -Werror=unguarded-availability, it would build but crash at runtime).
 #define __BIONIC_AVAILABILITY(__what, ...) __attribute__((__availability__(android,strict,__what __VA_OPT__(,) __VA_ARGS__)))
-#define __INTRODUCED_IN_NO_GUARD_FOR_NDK(api_level)
+
+// When the caller is using strict API references, we hide APIs which are not
+// available in the caller's minSdkVersion. This is a bionic-only deviation in
+// behavior from the rest of the NDK headers, but it's necessary to maintain
+// source compatibility with 3p libraries that either can't correctly detect API
+// availability (either incorrectly detecting as always-available or as
+// never-available, but neither is true), or define their own polyfills which
+// conflict with our declarations.
+//
+// https://github.com/android/ndk/issues/2081
+#define __BIONIC_AVAILABILITY_GUARD(api_level) (__ANDROID_MIN_SDK_VERSION__ >= (api_level))
 #endif
 
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc23-extensions"
+// Passing no argument for the '...' parameter of a variadic macro is a C23 extension
 #define __INTRODUCED_IN(api_level) __BIONIC_AVAILABILITY(introduced=api_level)
+#pragma clang diagnostic pop
+
 #define __DEPRECATED_IN(api_level, msg) __BIONIC_AVAILABILITY(deprecated=api_level, message=msg)
 #define __REMOVED_IN(api_level, msg) __BIONIC_AVAILABILITY(obsoleted=api_level, message=msg)
 
@@ -71,14 +80,3 @@
 #define __INTRODUCED_IN_32(api_level)
 #define __INTRODUCED_IN_64(api_level) __BIONIC_AVAILABILITY(introduced=api_level)
 #endif
-
-#define __VERSIONER_NO_GUARD
-#define __VERSIONER_FORTIFY_INLINE
-
-#endif  // defined(__BIONIC_VERSIONER)
-
-// Vendor modules do not follow SDK versioning. Ignore NDK guards for vendor modules.
-#if defined(__ANDROID_VENDOR__)
-#undef __BIONIC_AVAILABILITY
-#define __BIONIC_AVAILABILITY(api_level, ...)
-#endif // defined(__ANDROID_VENDOR__)
diff --git a/libc/include/arpa/ftp.h b/libc/include/arpa/ftp.h
index 081c037..fecbf7f 100644
--- a/libc/include/arpa/ftp.h
+++ b/libc/include/arpa/ftp.h
@@ -34,6 +34,8 @@
 #ifndef _ARPA_FTP_H_
 #define	_ARPA_FTP_H_
 
+#include <sys/cdefs.h>
+
 /* Definitions for FTP; see RFC-765. */
 
 /*
diff --git a/libc/include/arpa/inet.h b/libc/include/arpa/inet.h
index f00f2c1..ce9dd93 100644
--- a/libc/include/arpa/inet.h
+++ b/libc/include/arpa/inet.h
@@ -29,9 +29,10 @@
 #ifndef _ARPA_INET_H_
 #define _ARPA_INET_H_
 
+#include <sys/cdefs.h>
+
 #include <netinet/in.h>
 #include <stdint.h>
-#include <sys/cdefs.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
diff --git a/libc/include/arpa/nameser.h b/libc/include/arpa/nameser.h
index 97109ee..3e0025e 100644
--- a/libc/include/arpa/nameser.h
+++ b/libc/include/arpa/nameser.h
@@ -55,9 +55,10 @@
 
 #define BIND_4_COMPAT
 
-#include <sys/types.h>
 #include <sys/cdefs.h>
 
+#include <sys/types.h>
+
 /*
  * Revision information.  This is the release date in YYYYMMDD format.
  * It can change every day so the right thing to do with it is use it
@@ -547,6 +548,8 @@
 #define ns_sprintrrf __ns_sprintrrf
 #endif
 
+
+#if __BIONIC_AVAILABILITY_GUARD(22)
 int ns_msg_getflag(ns_msg __handle, int __flag) __INTRODUCED_IN(22);
 uint16_t ns_get16(const u_char* _Nonnull __src) __INTRODUCED_IN(22);
 uint32_t ns_get32(const u_char* _Nonnull __src) __INTRODUCED_IN(22);
@@ -570,6 +573,8 @@
 
 int ns_makecanon(const char* _Nonnull __src, char* _Nonnull __dst, size_t __dst_size) __INTRODUCED_IN(22);
 int ns_samename(const char* _Nonnull __lhs, const char* _Nonnull __rhs) __INTRODUCED_IN(22);
+#endif /* __BIONIC_AVAILABILITY_GUARD(22) */
+
 
 __END_DECLS
 
diff --git a/libc/include/arpa/nameser_compat.h b/libc/include/arpa/nameser_compat.h
index e4e9335..027e5ca 100644
--- a/libc/include/arpa/nameser_compat.h
+++ b/libc/include/arpa/nameser_compat.h
@@ -40,9 +40,10 @@
 #ifndef _ARPA_NAMESER_COMPAT_
 #define	_ARPA_NAMESER_COMPAT_
 
-#include <endian.h>
 #include <sys/cdefs.h>
 
+#include <endian.h>
+
 #define	__BIND		19950621	/* (DEAD) interface version stamp. */
 
 /*
diff --git a/libc/include/arpa/telnet.h b/libc/include/arpa/telnet.h
index 758e9b8..30d8f21 100644
--- a/libc/include/arpa/telnet.h
+++ b/libc/include/arpa/telnet.h
@@ -33,6 +33,8 @@
 #ifndef _ARPA_TELNET_H_
 #define	_ARPA_TELNET_H_
 
+#include <sys/cdefs.h>
+
 /*
  * Definitions for the TELNET protocol.
  */
diff --git a/libc/include/bits/bionic_multibyte_result.h b/libc/include/bits/bionic_multibyte_result.h
index 0d5cf21..930e67c 100644
--- a/libc/include/bits/bionic_multibyte_result.h
+++ b/libc/include/bits/bionic_multibyte_result.h
@@ -34,9 +34,10 @@
  * conversion APIs defined by C.
  */
 
-#include <stddef.h>
 #include <sys/cdefs.h>
 
+#include <stddef.h>
+
 __BEGIN_DECLS
 
 /**
diff --git a/libc/include/bits/fcntl.h b/libc/include/bits/fcntl.h
index ee5a6e1..e3f3548 100644
--- a/libc/include/bits/fcntl.h
+++ b/libc/include/bits/fcntl.h
@@ -38,7 +38,7 @@
 __BEGIN_DECLS
 
 /**
- * [fcntl(3)](http://man7.org/linux/man-pages/man2/fcntl.2.html) performs various operations
+ * [fcntl(3)](https://man7.org/linux/man-pages/man2/fcntl.2.html) performs various operations
  * on file descriptors.
  *
  * The return value depends on the operation.
diff --git a/libc/include/bits/fortify/poll.h b/libc/include/bits/fortify/poll.h
index f2e27d7..1b4a5bf 100644
--- a/libc/include/bits/fortify/poll.h
+++ b/libc/include/bits/fortify/poll.h
@@ -30,9 +30,17 @@
 #error "Never include this file directly; instead, include <poll.h>"
 #endif
 
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int __poll_chk(struct pollfd* _Nullable, nfds_t, int, size_t) __INTRODUCED_IN(23);
 int __ppoll_chk(struct pollfd* _Nullable, nfds_t, const struct timespec* _Nullable, const sigset_t* _Nullable, size_t) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int __ppoll64_chk(struct pollfd* _Nullable, nfds_t, const struct timespec* _Nullable, const sigset64_t* _Nullable, size_t) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 #if defined(__BIONIC_FORTIFY)
 #define __bos_fd_count_trivially_safe(bos_val, fds, fd_count)              \
diff --git a/libc/include/bits/fortify/socket.h b/libc/include/bits/fortify/socket.h
index 02f94cc..bd626f9 100644
--- a/libc/include/bits/fortify/socket.h
+++ b/libc/include/bits/fortify/socket.h
@@ -30,8 +30,11 @@
 #error "Never include this file directly; instead, include <sys/socket.h>"
 #endif
 
-extern ssize_t __sendto_chk(int, const void* _Nonnull, size_t, size_t, int, const struct sockaddr* _Nullable,
-        socklen_t) __INTRODUCED_IN(26);
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
+ssize_t __sendto_chk(int, const void* _Nonnull, size_t, size_t, int, const struct sockaddr* _Nullable, socklen_t) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 ssize_t __recvfrom_chk(int, void* _Nullable, size_t, size_t, int, struct sockaddr* _Nullable, socklen_t* _Nullable);
 
 #if defined(__BIONIC_FORTIFY)
diff --git a/libc/include/bits/fortify/stdio.h b/libc/include/bits/fortify/stdio.h
index e4607e0..f9faeba 100644
--- a/libc/include/bits/fortify/stdio.h
+++ b/libc/include/bits/fortify/stdio.h
@@ -31,8 +31,12 @@
 #endif
 
 char* _Nullable __fgets_chk(char* _Nonnull, int, FILE* _Nonnull, size_t);
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 size_t __fread_chk(void* _Nonnull, size_t, size_t, FILE* _Nonnull, size_t) __INTRODUCED_IN(24);
 size_t __fwrite_chk(const void* _Nonnull, size_t, size_t, FILE* _Nonnull, size_t) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 
 #if defined(__BIONIC_FORTIFY) && !defined(__BIONIC_NO_STDIO_FORTIFY)
 
diff --git a/libc/include/bits/fortify/string.h b/libc/include/bits/fortify/string.h
index 7df0b05..6f0ee4a 100644
--- a/libc/include/bits/fortify/string.h
+++ b/libc/include/bits/fortify/string.h
@@ -30,15 +30,19 @@
 #error "Never include this file directly; instead, include <string.h>"
 #endif
 
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 void* _Nullable __memchr_chk(const void* _Nonnull, int, size_t, size_t) __INTRODUCED_IN(23);
 void* _Nullable __memrchr_chk(const void* _Nonnull, int, size_t, size_t) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 char* _Nonnull __stpncpy_chk2(char* _Nonnull, const char* _Nonnull, size_t, size_t, size_t);
 char* _Nonnull __strncpy_chk2(char* _Nonnull, const char* _Nonnull, size_t, size_t, size_t);
 size_t __strlcpy_chk(char* _Nonnull, const char* _Nonnull, size_t, size_t);
 size_t __strlcat_chk(char* _Nonnull, const char* _Nonnull, size_t, size_t);
 
 #if defined(__BIONIC_FORTIFY)
-extern void* _Nullable __memrchr_real(const void* _Nonnull, int, size_t) __RENAME(memrchr);
+void* _Nullable __memrchr_real(const void* _Nonnull, int, size_t) __RENAME(memrchr);
 
 #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
 /* No diag -- clang diagnoses misuses of this on its own.  */
@@ -220,8 +224,13 @@
 }
 
 #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
-__BIONIC_FORTIFY_INLINE
-size_t strlen(const char* _Nonnull const s __pass_object_size0) __overloadable {
+/*
+ * Clang, when parsing C, can fold strlen to a constant without LLVM's help.
+ * This doesn't apply to overloads of strlen, so write this differently. We
+ * can't use `__pass_object_size0` here, but that's fine: it doesn't help much
+ * on __always_inline functions.
+ */
+extern __always_inline __inline__ __attribute__((gnu_inline)) size_t strlen(const char* _Nonnull s) {
     return __strlen_chk(s, __bos0(s));
 }
 #endif
diff --git a/libc/include/bits/fortify/unistd.h b/libc/include/bits/fortify/unistd.h
index 7eda1a6..9acb942 100644
--- a/libc/include/bits/fortify/unistd.h
+++ b/libc/include/bits/fortify/unistd.h
@@ -29,24 +29,52 @@
 #error "Never include this file directly; instead, include <unistd.h>"
 #endif
 
-char* _Nullable __getcwd_chk(char* _Nullable, size_t, size_t) __INTRODUCED_IN(24);
 
+#if __BIONIC_AVAILABILITY_GUARD(24)
+char* _Nullable __getcwd_chk(char* _Nullable, size_t, size_t) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
+
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 ssize_t __pread_chk(int, void* _Nonnull, size_t, off_t, size_t) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 ssize_t __pread_real(int, void* _Nonnull, size_t, off_t) __RENAME(pread);
 
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 ssize_t __pread64_chk(int, void* _Nonnull, size_t, off64_t, size_t) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 ssize_t __pread64_real(int, void* _Nonnull, size_t, off64_t) __RENAME(pread64);
 
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 ssize_t __pwrite_chk(int, const void* _Nonnull, size_t, off_t, size_t) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 ssize_t __pwrite_real(int, const void* _Nonnull, size_t, off_t) __RENAME(pwrite);
 
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 ssize_t __pwrite64_chk(int, const void* _Nonnull, size_t, off64_t, size_t) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 ssize_t __pwrite64_real(int, const void* _Nonnull, size_t, off64_t) __RENAME(pwrite64);
 
 ssize_t __read_chk(int, void* __BIONIC_COMPLICATED_NULLNESS, size_t, size_t);
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 ssize_t __write_chk(int, const void* __BIONIC_COMPLICATED_NULLNESS, size_t, size_t) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 ssize_t __readlink_chk(const char* _Nonnull, char* _Nonnull, size_t, size_t) __INTRODUCED_IN(23);
 ssize_t __readlinkat_chk(int dirfd, const char* _Nonnull, char* _Nonnull, size_t, size_t) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 #if defined(__BIONIC_FORTIFY)
 
diff --git a/libc/include/bits/getentropy.h b/libc/include/bits/getentropy.h
index a5a14f7..c878470 100644
--- a/libc/include/bits/getentropy.h
+++ b/libc/include/bits/getentropy.h
@@ -39,7 +39,7 @@
 __BEGIN_DECLS
 
 /**
- * [getentropy(3)](http://man7.org/linux/man-pages/man3/getentropy.3.html) fills the given buffer
+ * [getentropy(3)](https://man7.org/linux/man-pages/man3/getentropy.3.html) fills the given buffer
  * with random bytes.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -48,6 +48,10 @@
  *
  * See also arc4random_buf() which is available in all API levels.
  */
-int getentropy(void* _Nonnull __buffer, size_t __buffer_size) __wur __INTRODUCED_IN(28);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
+__nodiscard int getentropy(void* _Nonnull __buffer, size_t __buffer_size) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 __END_DECLS
diff --git a/libc/include/bits/getopt.h b/libc/include/bits/getopt.h
index 60a89ed..8fc0463 100644
--- a/libc/include/bits/getopt.h
+++ b/libc/include/bits/getopt.h
@@ -33,7 +33,7 @@
 __BEGIN_DECLS
 
 /**
- * [getopt(3)](http://man7.org/linux/man-pages/man3/getopt.3.html) parses command-line options.
+ * [getopt(3)](https://man7.org/linux/man-pages/man3/getopt.3.html) parses command-line options.
  *
  * Returns the next option character on success, returns -1 if all options have been parsed, and
  * returns `'?'` on error.
diff --git a/libc/include/bits/glibc-syscalls.h b/libc/include/bits/glibc-syscalls.h
index eceb334..8c5a91d 100644
--- a/libc/include/bits/glibc-syscalls.h
+++ b/libc/include/bits/glibc-syscalls.h
@@ -36,9 +36,6 @@
 #if defined(__NR_arch_prctl)
   #define SYS_arch_prctl __NR_arch_prctl
 #endif
-#if defined(__NR_arch_specific_syscall)
-  #define SYS_arch_specific_syscall __NR_arch_specific_syscall
-#endif
 #if defined(__NR_arm_fadvise64_64)
   #define SYS_arm_fadvise64_64 __NR_arm_fadvise64_64
 #endif
@@ -693,6 +690,9 @@
 #if defined(__NR_mremap)
   #define SYS_mremap __NR_mremap
 #endif
+#if defined(__NR_mseal)
+  #define SYS_mseal __NR_mseal
+#endif
 #if defined(__NR_msgctl)
   #define SYS_msgctl __NR_msgctl
 #endif
@@ -1269,9 +1269,6 @@
 #if defined(__NR_syscall)
   #define SYS_syscall __NR_syscall
 #endif
-#if defined(__NR_syscalls)
-  #define SYS_syscalls __NR_syscalls
-#endif
 #if defined(__NR_sysfs)
   #define SYS_sysfs __NR_sysfs
 #endif
@@ -1368,6 +1365,9 @@
 #if defined(__NR_unshare)
   #define SYS_unshare __NR_unshare
 #endif
+#if defined(__NR_uretprobe)
+  #define SYS_uretprobe __NR_uretprobe
+#endif
 #if defined(__NR_uselib)
   #define SYS_uselib __NR_uselib
 #endif
diff --git a/libc/include/bits/ioctl.h b/libc/include/bits/ioctl.h
index 260eb7d..ae75880 100644
--- a/libc/include/bits/ioctl.h
+++ b/libc/include/bits/ioctl.h
@@ -38,7 +38,7 @@
 __BEGIN_DECLS
 
 /**
- * [ioctl(2)](http://man7.org/linux/man-pages/man2/ioctl.2.html) operates on device files.
+ * [ioctl(2)](https://man7.org/linux/man-pages/man2/ioctl.2.html) operates on device files.
  */
 int ioctl(int __fd, int __op, ...);
 
diff --git a/libc/include/bits/lockf.h b/libc/include/bits/lockf.h
index d9f5987..8f922b9 100644
--- a/libc/include/bits/lockf.h
+++ b/libc/include/bits/lockf.h
@@ -48,7 +48,7 @@
 __BEGIN_DECLS
 
 /**
- * [lockf(3)](http://man7.org/linux/man-pages/man3/lockf.3.html) manipulates POSIX file locks.
+ * [lockf(3)](https://man7.org/linux/man-pages/man3/lockf.3.html) manipulates POSIX file locks.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
  *
@@ -56,6 +56,8 @@
  *
  * See also flock().
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 int lockf(int __fd, int __op, off_t __length) __RENAME_IF_FILE_OFFSET64(lockf64) __INTRODUCED_IN(24);
 
 /**
@@ -63,5 +65,7 @@
  * even from a 32-bit process without `_FILE_OFFSET_BITS=64`.
  */
 int lockf64(int __fd, int __op, off64_t __length) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 
 __END_DECLS
diff --git a/libc/include/bits/posix_limits.h b/libc/include/bits/posix_limits.h
index 452f5f6..d98be27 100644
--- a/libc/include/bits/posix_limits.h
+++ b/libc/include/bits/posix_limits.h
@@ -40,7 +40,7 @@
     (((__ANDROID_API__) >= (level)) ? _POSIX_VERSION : __BIONIC_POSIX_FEATURE_MISSING)
 
 /* Availability macros. */
-/* See http://man7.org/linux/man-pages/man7/posixoptions.7.html for documentation. */
+/* See https://man7.org/linux/man-pages/man7/posixoptions.7.html for documentation. */
 /* Keep this list sorted by name. */
 #define _POSIX_ADVISORY_INFO __BIONIC_POSIX_FEATURE_SINCE(23) /* posix_memadvise arrived late. */
 #define _POSIX_ASYNCHRONOUS_IO __BIONIC_POSIX_FEATURE_MISSING
diff --git a/libc/include/bits/pthread_types.h b/libc/include/bits/pthread_types.h
index f359696..e30c4c1 100644
--- a/libc/include/bits/pthread_types.h
+++ b/libc/include/bits/pthread_types.h
@@ -43,7 +43,6 @@
 #endif
 } pthread_attr_t;
 
-#if __ANDROID_API__ >= 24
 typedef struct {
 #if defined(__LP64__)
   int64_t __private[4];
@@ -51,11 +50,8 @@
   int32_t __private[8];
 #endif
 } pthread_barrier_t;
-#endif
 
-#if __ANDROID_API__ >= 24
 typedef int pthread_barrierattr_t;
-#endif
 
 typedef struct {
 #if defined(__LP64__)
@@ -91,7 +87,6 @@
 
 typedef long pthread_rwlockattr_t;
 
-#if __ANDROID_API__ >= 24
 typedef struct {
 #if defined(__LP64__)
   int64_t __private;
@@ -99,6 +94,5 @@
   int32_t __private[2];
 #endif
 } pthread_spinlock_t;
-#endif
 
 typedef long pthread_t;
diff --git a/libc/include/bits/seek_constants.h b/libc/include/bits/seek_constants.h
index 6f3f22d..a4fffb2 100644
--- a/libc/include/bits/seek_constants.h
+++ b/libc/include/bits/seek_constants.h
@@ -33,6 +33,8 @@
  * @brief The `SEEK_` constants.
  */
 
+#include <sys/cdefs.h>
+
 /** Seek to an absolute offset. */
 #define SEEK_SET 0
 /** Seek relative to the current offset. */
@@ -46,7 +48,7 @@
  * Seek to the first data (non-hole) location in the file
  * greater than or equal to the given offset.
  *
- * See [lseek(2)](http://man7.org/linux/man-pages/man2/lseek.2.html).
+ * See [lseek(2)](https://man7.org/linux/man-pages/man2/lseek.2.html).
  */
 #define SEEK_DATA 3
 
@@ -54,7 +56,7 @@
  * Seek to the first hole (non-data) location in the file
  * greater than or equal to the given offset.
  *
- * See [lseek(2)](http://man7.org/linux/man-pages/man2/lseek.2.html).
+ * See [lseek(2)](https://man7.org/linux/man-pages/man2/lseek.2.html).
  */
 #define SEEK_HOLE 4
 
diff --git a/libc/include/bits/stdatomic.h b/libc/include/bits/stdatomic.h
index c74eafd..ebdc9e5 100644
--- a/libc/include/bits/stdatomic.h
+++ b/libc/include/bits/stdatomic.h
@@ -134,6 +134,8 @@
 	memory_order_seq_cst = __ATOMIC_SEQ_CST
 } memory_order;
 
+#define kill_dependency(y) (y)
+
 /*
  * 7.17.4 Fences.
  */
diff --git a/libc/bionic/time_l.cpp b/libc/include/bits/stdlib_inlines.h
similarity index 70%
copy from libc/bionic/time_l.cpp
copy to libc/include/bits/stdlib_inlines.h
index e5fa9a5..fffca19 100644
--- a/libc/bionic/time_l.cpp
+++ b/libc/include/bits/stdlib_inlines.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,9 +26,23 @@
  * SUCH DAMAGE.
  */
 
-#include <time.h>
-//#include <xlocale.h>
+#pragma once
 
-char* strptime_l(const char* buf, const char* fmt, struct tm* tm, locale_t) {
-  return strptime(buf, fmt, tm);
+#include <xlocale.h>
+#include <sys/cdefs.h>
+
+#if !defined(__BIONIC_STDLIB_INLINE)
+#define __BIONIC_STDLIB_INLINE static __inline
+#endif
+
+__BEGIN_DECLS
+
+__BIONIC_STDLIB_INLINE double strtod_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, locale_t _Nonnull __l) {
+  return strtod(__s, __end_ptr);
 }
+
+__BIONIC_STDLIB_INLINE float strtof_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, locale_t _Nonnull __l) {
+  return strtof(__s, __end_ptr);
+}
+
+__END_DECLS
diff --git a/libc/include/bits/strcasecmp.h b/libc/include/bits/strcasecmp.h
index 23acbe5..d76cec9 100644
--- a/libc/include/bits/strcasecmp.h
+++ b/libc/include/bits/strcasecmp.h
@@ -40,7 +40,7 @@
 __BEGIN_DECLS
 
 /**
- * [strcasecmp(3)](http://man7.org/linux/man-pages/man3/strcasecmp.3.html) compares two strings
+ * [strcasecmp(3)](https://man7.org/linux/man-pages/man3/strcasecmp.3.html) compares two strings
  * ignoring case.
  *
  * Returns an integer less than, equal to, or greater than zero if the first string is less than,
@@ -51,10 +51,14 @@
 /**
  * Like strcasecmp() but taking a `locale_t`.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int strcasecmp_l(const char* _Nonnull __s1, const char* _Nonnull __s2, locale_t _Nonnull __l) __attribute_pure__ __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 /**
- * [strncasecmp(3)](http://man7.org/linux/man-pages/man3/strncasecmp.3.html) compares the first
+ * [strncasecmp(3)](https://man7.org/linux/man-pages/man3/strncasecmp.3.html) compares the first
  * `n` bytes of two strings ignoring case.
  *
  * Returns an integer less than, equal to, or greater than zero if the first `n` bytes of the
@@ -66,6 +70,10 @@
 /**
  * Like strncasecmp() but taking a `locale_t`.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int strncasecmp_l(const char* _Nonnull __s1, const char* _Nonnull __s2, size_t __n, locale_t _Nonnull __l) __attribute_pure__ __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 __END_DECLS
diff --git a/libc/include/bits/swab.h b/libc/include/bits/swab.h
index 9591c2e..da2865a 100644
--- a/libc/include/bits/swab.h
+++ b/libc/include/bits/swab.h
@@ -28,8 +28,9 @@
 
 #pragma once
 
-#include <stdint.h>
 #include <sys/cdefs.h>
+
+#include <stdint.h>
 #include <sys/types.h>
 
 #if !defined(__BIONIC_SWAB_INLINE)
diff --git a/libc/include/bits/termios_inlines.h b/libc/include/bits/termios_inlines.h
index a884b59..bb04e4d 100644
--- a/libc/include/bits/termios_inlines.h
+++ b/libc/include/bits/termios_inlines.h
@@ -29,8 +29,9 @@
 #ifndef _BITS_TERMIOS_INLINES_H_
 #define _BITS_TERMIOS_INLINES_H_
 
-#include <errno.h>
 #include <sys/cdefs.h>
+
+#include <errno.h>
 #include <sys/ioctl.h>
 #include <sys/types.h>
 
diff --git a/libc/include/bits/termios_winsize_inlines.h b/libc/include/bits/termios_winsize_inlines.h
index ae246e4..86777b0 100644
--- a/libc/include/bits/termios_winsize_inlines.h
+++ b/libc/include/bits/termios_winsize_inlines.h
@@ -28,8 +28,9 @@
 
 #pragma once
 
-#include <errno.h>
 #include <sys/cdefs.h>
+
+#include <errno.h>
 #include <sys/ioctl.h>
 #include <sys/types.h>
 
diff --git a/libc/include/bits/threads_inlines.h b/libc/include/bits/threads_inlines.h
index 459866e..ab294c1 100644
--- a/libc/include/bits/threads_inlines.h
+++ b/libc/include/bits/threads_inlines.h
@@ -28,6 +28,8 @@
 
 #pragma once
 
+#include <sys/cdefs.h>
+
 #include <threads.h>
 
 #include <errno.h>
@@ -116,13 +118,10 @@
   return __bionic_thrd_error(pthread_mutex_unlock(__mtx));
 }
 
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wnullability-completeness"
 struct __bionic_thrd_data {
-  thrd_start_t __func;
-  void* __arg;
+  thrd_start_t _Nonnull __func;
+  void* _Nullable __arg;
 };
-#pragma clang diagnostic pop
 
 static __inline void* _Nonnull __bionic_thrd_trampoline(void* _Nonnull __arg) {
   struct __bionic_thrd_data __data =
diff --git a/libc/include/bits/wctype.h b/libc/include/bits/wctype.h
index 11d5fde..d0cffec 100644
--- a/libc/include/bits/wctype.h
+++ b/libc/include/bits/wctype.h
@@ -58,8 +58,12 @@
 int iswctype(wint_t __wc, wctype_t __type);
 
 typedef const void* wctrans_t;
-wint_t towctrans(wint_t __wc, wctrans_t _Nonnull __transform) __INTRODUCED_IN_NO_GUARD_FOR_NDK(26);
-wctrans_t _Nullable wctrans(const char* _Nonnull __name) __INTRODUCED_IN_NO_GUARD_FOR_NDK(26);
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
+wint_t towctrans(wint_t __wc, wctrans_t _Nonnull __transform) __INTRODUCED_IN(26);
+wctrans_t _Nullable wctrans(const char* _Nonnull __name) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 __END_DECLS
 
diff --git a/libc/include/byteswap.h b/libc/include/byteswap.h
index 0773426..a679ea0 100644
--- a/libc/include/byteswap.h
+++ b/libc/include/byteswap.h
@@ -37,19 +37,19 @@
 #include <sys/endian.h>
 
 /**
- * [bswap_16(3)](http://man7.org/linux/man-pages/man3/bswap_16.3.html) swaps the bytes in a
+ * [bswap_16(3)](https://man7.org/linux/man-pages/man3/bswap_16.3.html) swaps the bytes in a
  * 16-bit value.
  */
 #define bswap_16(x) __swap16(x)
 
 /**
- * [bswap_32(3)](http://man7.org/linux/man-pages/man3/bswap_32.3.html) swaps the bytes in a
+ * [bswap_32(3)](https://man7.org/linux/man-pages/man3/bswap_32.3.html) swaps the bytes in a
  * 32-bit value.
  */
 #define bswap_32(x) __swap32(x)
 
 /**
- * [bswap_64(3)](http://man7.org/linux/man-pages/man3/bswap_64.3.html) swaps the bytes in a
+ * [bswap_64(3)](https://man7.org/linux/man-pages/man3/bswap_64.3.html) swaps the bytes in a
  * 64-bit value.
  */
 #define bswap_64(x) __swap64(x)
diff --git a/libc/include/complex.h b/libc/include/complex.h
index f205abd..1115862 100644
--- a/libc/include/complex.h
+++ b/libc/include/complex.h
@@ -53,76 +53,190 @@
 
 /* 7.3.5 Trigonometric functions */
 /* 7.3.5.1 The cacos functions */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 double complex cacos(double complex __z) __INTRODUCED_IN(23);
 float complex cacosf(float complex __z) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 long double complex cacosl(long double complex __z) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 /* 7.3.5.2 The casin functions */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 double complex casin(double complex __z) __INTRODUCED_IN(23);
 float complex casinf(float complex __z) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 long double complex casinl(long double complex __z) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 /* 7.3.5.1 The catan functions */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 double complex catan(double complex __z) __INTRODUCED_IN(23);
 float complex catanf(float complex __z) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 long double complex catanl(long double complex __z) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 /* 7.3.5.1 The ccos functions */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 double complex ccos(double complex __z) __INTRODUCED_IN(23);
 float complex ccosf(float complex __z) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 long double complex ccosl(long double complex __z) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 /* 7.3.5.1 The csin functions */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 double complex csin(double complex __z) __INTRODUCED_IN(23);
 float complex csinf(float complex __z) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 long double complex csinl(long double complex __z) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 /* 7.3.5.1 The ctan functions */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 double complex ctan(double complex __z) __INTRODUCED_IN(23);
 float complex ctanf(float complex __z) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 long double complex ctanl(long double complex __z) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 /* 7.3.6 Hyperbolic functions */
 /* 7.3.6.1 The cacosh functions */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 double complex cacosh(double complex __z) __INTRODUCED_IN(23);
 float complex cacoshf(float complex __z) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 long double complex cacoshl(long double complex __z) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 /* 7.3.6.2 The casinh functions */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 double complex casinh(double complex __z) __INTRODUCED_IN(23);
 float complex casinhf(float complex __z) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 long double complex casinhl(long double complex __z) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 /* 7.3.6.3 The catanh functions */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 double complex catanh(double complex __z) __INTRODUCED_IN(23);
 float complex catanhf(float complex __z) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 long double complex catanhl(long double complex __z) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 /* 7.3.6.4 The ccosh functions */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 double complex ccosh(double complex __z) __INTRODUCED_IN(23);
 float complex ccoshf(float complex __z) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 long double complex ccoshl(long double complex __z) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 /* 7.3.6.5 The csinh functions */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 double complex csinh(double complex __z) __INTRODUCED_IN(23);
 float complex csinhf(float complex __z) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 long double complex csinhl(long double complex __z) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 /* 7.3.6.6 The ctanh functions */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 double complex ctanh(double complex __z) __INTRODUCED_IN(23);
 float complex ctanhf(float complex __z) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 long double complex ctanhl(long double complex __z) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 /* 7.3.7 Exponential and logarithmic functions */
 /* 7.3.7.1 The cexp functions */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 double complex cexp(double complex __z) __INTRODUCED_IN(23);
 float complex cexpf(float complex __z) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 long double complex cexpl(long double complex __z) __INTRODUCED_IN(26);
 /* 7.3.7.2 The clog functions */
 double complex clog(double complex __z) __INTRODUCED_IN(26);
 float complex clogf(float complex __z) __INTRODUCED_IN(26);
 long double complex clogl(long double complex __z) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 /* 7.3.8 Power and absolute-value functions */
 /* 7.3.8.1 The cabs functions */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 double cabs(double complex __z) __INTRODUCED_IN(23);
 float cabsf(float complex __z) __INTRODUCED_IN(23);
 long double cabsl(long double complex __z) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 /* 7.3.8.2 The cpow functions */
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 double complex cpow(double complex __x, double complex __z) __INTRODUCED_IN(26);
 float complex cpowf(float complex __x, float complex __z) __INTRODUCED_IN(26);
 long double complex cpowl(long double complex __x, long double complex __z) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 /* 7.3.8.3 The csqrt functions */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 double complex csqrt(double complex __z) __INTRODUCED_IN(23);
 float complex csqrtf(float complex __z) __INTRODUCED_IN(23);
 long double complex csqrtl(long double complex __z) __INTRODUCED_IN(23);
@@ -148,6 +262,8 @@
 double creal(double complex __z) __INTRODUCED_IN(23);
 float crealf(float complex __z) __INTRODUCED_IN(23);
 long double creall(long double complex __z) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 __END_DECLS
 
diff --git a/libc/include/ctype.h b/libc/include/ctype.h
index cb926a4..dc3f673 100644
--- a/libc/include/ctype.h
+++ b/libc/include/ctype.h
@@ -95,7 +95,7 @@
 
 /** Internal implementation detail. Do not use. */
 __attribute__((__no_sanitize__("unsigned-integer-overflow")))
-static inline int __bionic_ctype_in_range(unsigned __lo, int __ch, unsigned __hi) {
+__BIONIC_CTYPE_INLINE int __bionic_ctype_in_range(unsigned __lo, int __ch, unsigned __hi) {
   return (__BIONIC_CAST(static_cast, unsigned, __ch) - __lo) < (__hi - __lo + 1);
 }
 
diff --git a/libc/include/dirent.h b/libc/include/dirent.h
index 4f5d0fb..8058cfb 100644
--- a/libc/include/dirent.h
+++ b/libc/include/dirent.h
@@ -33,8 +33,9 @@
  * @brief Directory entry iteration.
  */
 
-#include <stdint.h>
 #include <sys/cdefs.h>
+
+#include <stdint.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
@@ -90,7 +91,7 @@
 typedef struct DIR DIR;
 
 /**
- * [opendir(3)](http://man7.org/linux/man-pages/man3/opendir.3.html)
+ * [opendir(3)](https://man7.org/linux/man-pages/man3/opendir.3.html)
  * opens a directory stream for the directory at `__path`.
  *
  * Returns null and sets `errno` on failure.
@@ -98,7 +99,7 @@
 DIR* _Nullable opendir(const char* _Nonnull __path);
 
 /**
- * [fopendir(3)](http://man7.org/linux/man-pages/man3/opendir.3.html)
+ * [fopendir(3)](https://man7.org/linux/man-pages/man3/opendir.3.html)
  * opens a directory stream for the directory at `__dir_fd`.
  *
  * Returns null and sets `errno` on failure.
@@ -106,7 +107,7 @@
 DIR* _Nullable fdopendir(int __dir_fd);
 
 /**
- * [readdir(3)](http://man7.org/linux/man-pages/man3/readdir.3.html)
+ * [readdir(3)](https://man7.org/linux/man-pages/man3/readdir.3.html)
  * returns the next directory entry in the given directory.
  *
  * Returns a pointer to a directory entry on success,
@@ -116,7 +117,7 @@
 struct dirent* _Nullable readdir(DIR* _Nonnull __dir);
 
 /**
- * [readdir64(3)](http://man7.org/linux/man-pages/man3/readdir.3.html)
+ * [readdir64(3)](https://man7.org/linux/man-pages/man3/readdir.3.html)
  * returns the next directory entry in the given directory.
  *
  * Returns a pointer to a directory entry on success,
@@ -129,7 +130,7 @@
 int readdir64_r(DIR* _Nonnull __dir, struct dirent64* _Nonnull __entry, struct dirent64* _Nullable * _Nonnull __buffer) __attribute__((__deprecated__("readdir64_r is deprecated; use readdir64 instead")));
 
 /**
- * [closedir(3)](http://man7.org/linux/man-pages/man3/closedir.3.html)
+ * [closedir(3)](https://man7.org/linux/man-pages/man3/closedir.3.html)
  * closes a directory stream.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
@@ -137,22 +138,24 @@
 int closedir(DIR* _Nonnull __dir);
 
 /**
- * [rewinddir(3)](http://man7.org/linux/man-pages/man3/rewinddir.3.html)
+ * [rewinddir(3)](https://man7.org/linux/man-pages/man3/rewinddir.3.html)
  * rewinds a directory stream to the first entry.
  */
 void rewinddir(DIR* _Nonnull __dir);
 
 /**
- * [seekdir(3)](http://man7.org/linux/man-pages/man3/seekdir.3.html)
+ * [seekdir(3)](https://man7.org/linux/man-pages/man3/seekdir.3.html)
  * seeks a directory stream to the given entry, which must be a value returned
  * by telldir().
  *
  * Available since API level 23.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 void seekdir(DIR* _Nonnull __dir, long __location) __INTRODUCED_IN(23);
 
 /**
- * [telldir(3)](http://man7.org/linux/man-pages/man3/telldir.3.html)
+ * [telldir(3)](https://man7.org/linux/man-pages/man3/telldir.3.html)
  * returns a value representing the current position in the directory
  * for use with seekdir().
  *
@@ -161,9 +164,11 @@
  * Available since API level 23.
  */
 long telldir(DIR* _Nonnull __dir) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 /**
- * [dirfd(3)](http://man7.org/linux/man-pages/man3/dirfd.3.html)
+ * [dirfd(3)](https://man7.org/linux/man-pages/man3/dirfd.3.html)
  * returns the file descriptor backing the given directory stream.
  *
  * Returns a file descriptor on success and returns -1 and sets `errno` on failure.
@@ -171,19 +176,19 @@
 int dirfd(DIR* _Nonnull __dir);
 
 /**
- * [alphasort](http://man7.org/linux/man-pages/man3/alphasort.3.html) is a
+ * [alphasort](https://man7.org/linux/man-pages/man3/alphasort.3.html) is a
  * comparator for use with scandir() that uses strcoll().
  */
 int alphasort(const struct dirent* _Nonnull * _Nonnull __lhs, const struct dirent* _Nonnull * _Nonnull __rhs);
 
 /**
- * [alphasort64](http://man7.org/linux/man-pages/man3/alphasort.3.html) is a
+ * [alphasort64](https://man7.org/linux/man-pages/man3/alphasort.3.html) is a
  * comparator for use with scandir64() that uses strcmp().
  */
 int alphasort64(const struct dirent64* _Nonnull * _Nonnull __lhs, const struct dirent64* _Nonnull * _Nonnull __rhs);
 
 /**
- * [scandir(3)](http://man7.org/linux/man-pages/man3/scandir.3.html)
+ * [scandir(3)](https://man7.org/linux/man-pages/man3/scandir.3.html)
  * scans all the directory `__path`, filtering entries with `__filter` and
  * sorting them with qsort() using the given `__comparator`, and storing them
  * into `__name_list`. Passing NULL as the filter accepts all entries.
@@ -195,7 +200,7 @@
 int scandir(const char* _Nonnull __path, struct dirent* _Nonnull * _Nonnull * _Nonnull __name_list, int (* _Nullable __filter)(const struct dirent* _Nonnull), int (* _Nullable __comparator)(const struct dirent* _Nonnull * _Nonnull, const struct dirent* _Nonnull * _Nonnull));
 
 /**
- * [scandir64(3)](http://man7.org/linux/man-pages/man3/scandir.3.html)
+ * [scandir64(3)](https://man7.org/linux/man-pages/man3/scandir.3.html)
  * scans all the directory `__path`, filtering entries with `__filter` and
  * sorting them with qsort() using the given `__comparator`, and storing them
  * into `__name_list`. Passing NULL as the filter accepts all entries.
@@ -209,7 +214,7 @@
 #if defined(__USE_GNU)
 
 /**
- * [scandirat64(3)](http://man7.org/linux/man-pages/man3/scandirat.3.html)
+ * [scandirat64(3)](https://man7.org/linux/man-pages/man3/scandirat.3.html)
  * scans all the directory referenced by the pair of `__dir_fd` and `__path`,
  * filtering entries with `__filter` and sorting them with qsort() using the
  * given `__comparator`, and storing them into `__name_list`. Passing NULL as
@@ -221,10 +226,12 @@
  *
  * Available since API level 24.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 int scandirat64(int __dir_fd, const char* _Nonnull __path, struct dirent64* _Nonnull * _Nonnull * _Nonnull __name_list, int (* _Nullable __filter)(const struct dirent64* _Nonnull), int (* _Nullable __comparator)(const struct dirent64* _Nonnull * _Nonnull, const struct dirent64* _Nonnull * _Nonnull)) __INTRODUCED_IN(24);
 
 /**
- * [scandirat(3)](http://man7.org/linux/man-pages/man3/scandirat.3.html)
+ * [scandirat(3)](https://man7.org/linux/man-pages/man3/scandirat.3.html)
  * scans all the directory referenced by the pair of `__dir_fd` and `__path`,
  * filtering entries with `__filter` and sorting them with qsort() using the
  * given `__comparator`, and storing them into `__name_list`. Passing NULL as
@@ -237,6 +244,8 @@
  * Available since API level 24.
  */
 int scandirat(int __dir_fd, const char* _Nonnull __path, struct dirent* _Nonnull * _Nonnull * _Nonnull __name_list, int (* _Nullable __filter)(const struct dirent* _Nonnull), int (* _Nullable __comparator)(const struct dirent* _Nonnull * _Nonnull, const struct dirent* _Nonnull * _Nonnull)) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 
 #endif
 
diff --git a/libc/include/dlfcn.h b/libc/include/dlfcn.h
index d65a409..81045fd 100644
--- a/libc/include/dlfcn.h
+++ b/libc/include/dlfcn.h
@@ -28,9 +28,21 @@
 
 #pragma once
 
-#include <stdint.h>
 #include <sys/cdefs.h>
 
+#include <stdint.h>
+
+/**
+ * @addtogroup libdl Dynamic Linker
+ * @{
+ */
+
+/**
+ * \file
+ * Standard dynamic library support.
+ * See also the Android-specific functionality in `<android/dlext.h>`.
+ */
+
 __BEGIN_DECLS
 
 /**
@@ -48,9 +60,11 @@
 } Dl_info;
 
 /**
- * [dlopen(3)](http://man7.org/linux/man-pages/man3/dlopen.3.html)
+ * [dlopen(3)](https://man7.org/linux/man-pages/man3/dlopen.3.html)
  * loads the given shared library.
  *
+ * See also android_dlopen_ext().
+ *
  * Returns a pointer to an opaque handle for use with other <dlfcn.h> functions
  * on success, and returns NULL on failure, in which case dlerror() can be used
  * to retrieve the specific error.
@@ -58,7 +72,7 @@
 void* _Nullable dlopen(const char* _Nullable __filename, int __flag);
 
 /**
- * [dlclose(3)](http://man7.org/linux/man-pages/man3/dlclose.3.html)
+ * [dlclose(3)](https://man7.org/linux/man-pages/man3/dlclose.3.html)
  * decrements the reference count for the given shared library (and
  * any libraries brought in by that library's DT_NEEDED entries).
  *
@@ -84,7 +98,7 @@
 int dlclose(void* _Nonnull __handle);
 
 /**
- * [dlerror(3)](http://man7.org/linux/man-pages/man3/dlerror.3.html)
+ * [dlerror(3)](https://man7.org/linux/man-pages/man3/dlerror.3.html)
  * returns a human-readable error message describing the most recent
  * failure from one of the <dlfcn.h> functions on the calling thread.
  *
@@ -97,7 +111,7 @@
 char* _Nullable dlerror(void);
 
 /**
- * [dlsym(3)](http://man7.org/linux/man-pages/man3/dlsym.3.html)
+ * [dlsym(3)](https://man7.org/linux/man-pages/man3/dlsym.3.html)
  * returns a pointer to the symbol with the given name in the shared
  * library represented by the given handle. The handle may have been
  * returned from dlopen(), or can be RTLD_DEFAULT or RTLD_NEXT.
@@ -108,7 +122,7 @@
 void* _Nullable dlsym(void* __BIONIC_COMPLICATED_NULLNESS __handle, const char* _Nullable __symbol);
 
 /**
- * [dlvsym(3)](http://man7.org/linux/man-pages/man3/dlvsym.3.html)
+ * [dlvsym(3)](https://man7.org/linux/man-pages/man3/dlvsym.3.html)
  * returns a pointer to the symbol with the given name and version in the shared
  * library represented by the given handle. The handle may have been
  * returned from dlopen(), or can be RTLD_DEFAULT or RTLD_NEXT.
@@ -116,10 +130,14 @@
  * Returns the address of the symbol on success, and returns NULL on failure,
  * in which case dlerror() can be used to retrieve the specific error.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 void* _Nullable dlvsym(void* __BIONIC_COMPLICATED_NULLNESS __handle, const char* _Nullable __symbol, const char* _Nullable __version) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 
 /**
- * [dladdr(3)](http://man7.org/linux/man-pages/man3/dladdr.3.html)
+ * [dladdr(3)](https://man7.org/linux/man-pages/man3/dladdr.3.html)
  * returns information about the symbol at the given address.
  *
  * Returns non-zero on success, and returns 0 on failure. Note that unlike
@@ -186,3 +204,5 @@
 #endif
 
 __END_DECLS
+
+/** @} */
diff --git a/libc/include/elf.h b/libc/include/elf.h
index 374d5bb..24454d7 100644
--- a/libc/include/elf.h
+++ b/libc/include/elf.h
@@ -272,14 +272,12 @@
 
 /* riscv64 psabi. */
 
-/* FreeBSD is missing these, found in
+/*
  * https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#relocations
- * so I've sent https://github.com/freebsd/freebsd-src/pull/1141 upstream.
+ * Missing from FreeBSD and the Linux uapi headers.
+ * TODO: upstreamed to FreeBSD as https://github.com/freebsd/freebsd-src/pull/1141.
  */
 #define R_RISCV_TLSDESC 12
-#define R_RISCV_PLT32 59
-#define R_RISCV_SET_ULEB128 60
-#define R_RISCV_SUB_ULEB128 61
 #define R_RISCV_TLSDESC_HI20 62
 #define R_RISCV_TLSDESC_LOAD_LO12 63
 #define R_RISCV_TLSDESC_ADD_LO12 64
diff --git a/libc/include/err.h b/libc/include/err.h
index af44514..4a1841b 100644
--- a/libc/include/err.h
+++ b/libc/include/err.h
@@ -36,14 +36,15 @@
  * @brief BSD error reporting functions. See `<error.h>` for the GNU equivalent.
  */
 
-#include <stdarg.h>
 #include <sys/cdefs.h>
+
+#include <stdarg.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
 
 /**
- * [err(3)](http://man7.org/linux/man-pages/man3/err.3.html) outputs the program name,
+ * [err(3)](https://man7.org/linux/man-pages/man3/err.3.html) outputs the program name,
  * the printf()-like formatted message, and the result of strerror() if `errno` is non-zero.
  *
  * Calls exit() with `__status`.
@@ -53,7 +54,7 @@
 __noreturn void err(int __status, const char* _Nullable __fmt, ...) __printflike(2, 3);
 
 /**
- * [verr(3)](http://man7.org/linux/man-pages/man3/verr.3.html) outputs the program name,
+ * [verr(3)](https://man7.org/linux/man-pages/man3/verr.3.html) outputs the program name,
  * the vprintf()-like formatted message, and the result of strerror() if `errno` is non-zero.
  *
  * Calls exit() with `__status`.
@@ -63,7 +64,7 @@
 __noreturn void verr(int __status, const char* _Nullable __fmt, va_list __args) __printflike(2, 0);
 
 /**
- * [errx(3)](http://man7.org/linux/man-pages/man3/errx.3.html) outputs the program name, and
+ * [errx(3)](https://man7.org/linux/man-pages/man3/errx.3.html) outputs the program name, and
  * the printf()-like formatted message.
  *
  * Calls exit() with `__status`.
@@ -73,7 +74,7 @@
 __noreturn void errx(int __status, const char* _Nullable __fmt, ...) __printflike(2, 3);
 
 /**
- * [verrx(3)](http://man7.org/linux/man-pages/man3/err.3.html) outputs the program name, and
+ * [verrx(3)](https://man7.org/linux/man-pages/man3/err.3.html) outputs the program name, and
  * the vprintf()-like formatted message.
  *
  * Calls exit() with `__status`.
@@ -83,7 +84,7 @@
 __noreturn void verrx(int __status, const char* _Nullable __fmt, va_list __args) __printflike(2, 0);
 
 /**
- * [warn(3)](http://man7.org/linux/man-pages/man3/warn.3.html) outputs the program name,
+ * [warn(3)](https://man7.org/linux/man-pages/man3/warn.3.html) outputs the program name,
  * the printf()-like formatted message, and the result of strerror() if `errno` is non-zero.
  *
  * New code should consider error() in `<error.h>`.
@@ -91,7 +92,7 @@
 void warn(const char* _Nullable __fmt, ...) __printflike(1, 2);
 
 /**
- * [vwarn(3)](http://man7.org/linux/man-pages/man3/vwarn.3.html) outputs the program name,
+ * [vwarn(3)](https://man7.org/linux/man-pages/man3/vwarn.3.html) outputs the program name,
  * the vprintf()-like formatted message, and the result of strerror() if `errno` is non-zero.
  *
  * New code should consider error() in `<error.h>`.
@@ -99,7 +100,7 @@
 void vwarn(const char* _Nullable __fmt, va_list __args) __printflike(1, 0);
 
 /**
- * [warnx(3)](http://man7.org/linux/man-pages/man3/warnx.3.html) outputs the program name, and
+ * [warnx(3)](https://man7.org/linux/man-pages/man3/warnx.3.html) outputs the program name, and
  * the printf()-like formatted message.
  *
  * New code should consider error() in `<error.h>`.
@@ -107,7 +108,7 @@
 void warnx(const char* _Nullable __fmt, ...) __printflike(1, 2);
 
 /**
- * [vwarnx(3)](http://man7.org/linux/man-pages/man3/warn.3.html) outputs the program name, and
+ * [vwarnx(3)](https://man7.org/linux/man-pages/man3/warn.3.html) outputs the program name, and
  * the vprintf()-like formatted message.
  *
  * New code should consider error() in `<error.h>`.
diff --git a/libc/include/errno.h b/libc/include/errno.h
index 12ebdf7..0b79592 100644
--- a/libc/include/errno.h
+++ b/libc/include/errno.h
@@ -52,7 +52,7 @@
 int* _Nonnull __errno(void) __attribute_const__;
 
 /**
- * [errno(3)](http://man7.org/linux/man-pages/man3/errno.3.html) is the last error on the calling
+ * [errno(3)](https://man7.org/linux/man-pages/man3/errno.3.html) is the last error on the calling
  * thread.
  */
 #define errno (*__errno())
diff --git a/libc/include/error.h b/libc/include/error.h
index 187ee17..a9bdc24 100644
--- a/libc/include/error.h
+++ b/libc/include/error.h
@@ -38,16 +38,18 @@
 __BEGIN_DECLS
 
 /**
- * [error_print_progname(3)](http://man7.org/linux/man-pages/man3/error_print_progname.3.html) is
+ * [error_print_progname(3)](https://man7.org/linux/man-pages/man3/error_print_progname.3.html) is
  * a function pointer that, if non-null, is called by error() instead of prefixing errors with the
  * program name.
  *
  * Available since API level 23.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 extern void (* _Nullable error_print_progname)(void) __INTRODUCED_IN(23);
 
 /**
- * [error_message_count(3)](http://man7.org/linux/man-pages/man3/error_message_count.3.html) is
+ * [error_message_count(3)](https://man7.org/linux/man-pages/man3/error_message_count.3.html) is
  * a global count of the number of calls to error() and error_at_line().
  *
  * Available since API level 23.
@@ -55,7 +57,7 @@
 extern unsigned int error_message_count __INTRODUCED_IN(23);
 
 /**
- * [error_one_per_line(3)](http://man7.org/linux/man-pages/man3/error_one_per_line.3.html) is
+ * [error_one_per_line(3)](https://man7.org/linux/man-pages/man3/error_one_per_line.3.html) is
  * a global flag that if non-zero disables printing multiple errors with the same filename and
  * line number.
  *
@@ -64,7 +66,7 @@
 extern int error_one_per_line __INTRODUCED_IN(23);
 
 /**
- * [error(3)](http://man7.org/linux/man-pages/man3/error.3.html) formats the given printf()-like
+ * [error(3)](https://man7.org/linux/man-pages/man3/error.3.html) formats the given printf()-like
  * error message, preceded by the program name. Calls exit if `__status` is non-zero, and appends
  * the result of strerror() if `__errno` is non-zero.
  *
@@ -73,7 +75,7 @@
 void error(int __status, int __errno, const char* _Nonnull __fmt, ...) __printflike(3, 4) __INTRODUCED_IN(23);
 
 /**
- * [error_at_line(3)](http://man7.org/linux/man-pages/man3/error_at_line.3.html) formats the given
+ * [error_at_line(3)](https://man7.org/linux/man-pages/man3/error_at_line.3.html) formats the given
  * printf()-like error message, preceded by the program name and the given filename and line number.
  * Calls exit if `__status` is non-zero, and appends the result of strerror() if `__errno` is
  * non-zero.
@@ -81,5 +83,7 @@
  * Available since API level 23.
  */
 void error_at_line(int __status, int __errno, const char* _Nonnull __filename, unsigned int __line_number, const char* _Nonnull __fmt, ...) __printflike(5, 6) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 __END_DECLS
diff --git a/libc/include/execinfo.h b/libc/include/execinfo.h
index 88f4ae7..84b637c 100644
--- a/libc/include/execinfo.h
+++ b/libc/include/execinfo.h
@@ -47,6 +47,8 @@
  *
  * Available since API level 33.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(33)
 int backtrace(void* _Nonnull * _Nonnull buffer, int size) __INTRODUCED_IN(33);
 
 /**
@@ -70,5 +72,7 @@
  * Available since API level 33.
  */
 void backtrace_symbols_fd(void* _Nonnull const* _Nonnull buffer, int size, int fd) __INTRODUCED_IN(33);
+#endif /* __BIONIC_AVAILABILITY_GUARD(33) */
+
 
 __END_DECLS
diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h
index 16ce6fa..2bd1fc6 100644
--- a/libc/include/fcntl.h
+++ b/libc/include/fcntl.h
@@ -93,17 +93,15 @@
 /** Flag for splice(). */
 #define SPLICE_F_GIFT 8
 
-#if __ANDROID_API__ >= 26
 /** Flag for sync_file_range(). */
 #define SYNC_FILE_RANGE_WAIT_BEFORE 1
 /** Flag for sync_file_range(). */
 #define SYNC_FILE_RANGE_WRITE 2
 /** Flag for sync_file_range(). */
 #define SYNC_FILE_RANGE_WAIT_AFTER 4
-#endif
 
 /**
- * [creat(2)](http://man7.org/linux/man-pages/man2/creat.2.html)
+ * [creat(2)](https://man7.org/linux/man-pages/man2/creat.2.html)
  * creates a file.
  *
  * Returns a new file descriptor on success and returns -1 and sets `errno` on
@@ -114,7 +112,7 @@
 int creat64(const char* _Nonnull __path, mode_t __mode);
 
 /**
- * [openat(2)](http://man7.org/linux/man-pages/man2/openat.2.html)
+ * [openat(2)](https://man7.org/linux/man-pages/man2/openat.2.html)
  * opens (and possibly creates) a file.
  *
  * Returns a new file descriptor on success and returns -1 and sets `errno` on
@@ -125,7 +123,7 @@
 int openat64(int __dir_fd, const char* _Nonnull __path, int __flags, ...);
 
 /**
- * [open(2)](http://man7.org/linux/man-pages/man2/open.2.html)
+ * [open(2)](https://man7.org/linux/man-pages/man2/open.2.html)
  * opens (and possibly creates) a file.
  *
  * Returns a new file descriptor on success and returns -1 and sets `errno` on
@@ -136,7 +134,7 @@
 int open64(const char* _Nonnull __path, int __flags, ...);
 
 /**
- * [splice(2)](http://man7.org/linux/man-pages/man2/splice.2.html)
+ * [splice(2)](https://man7.org/linux/man-pages/man2/splice.2.html)
  * splices data to/from a pipe.
  *
  * Valid flags are `SPLICE_F_MOVE`, `SPLICE_F_NONBLOCK`, `SPLICE_F_MORE`, and
@@ -148,7 +146,7 @@
 ssize_t splice(int __in_fd, off64_t* __BIONIC_COMPLICATED_NULLNESS __in_offset, int __out_fd, off64_t* __BIONIC_COMPLICATED_NULLNESS __out_offset, size_t __length, unsigned int __flags);
 
 /**
- * [tee(2)](http://man7.org/linux/man-pages/man2/tee.2.html)
+ * [tee(2)](https://man7.org/linux/man-pages/man2/tee.2.html)
  * duplicates data from one pipe to another.
  *
  * Valid flags are `SPLICE_F_MOVE`, `SPLICE_F_NONBLOCK`, `SPLICE_F_MORE`, and
@@ -160,7 +158,7 @@
 ssize_t tee(int __in_fd, int __out_fd, size_t __length, unsigned int __flags);
 
 /**
- * [vmsplice(2)](http://man7.org/linux/man-pages/man2/vmsplice.2.html)
+ * [vmsplice(2)](https://man7.org/linux/man-pages/man2/vmsplice.2.html)
  * splices data to/from a pipe.
  *
  * Valid flags are `SPLICE_F_MOVE`, `SPLICE_F_NONBLOCK`, `SPLICE_F_MORE`, and
@@ -172,7 +170,7 @@
 ssize_t vmsplice(int __fd, const struct iovec* _Nonnull __iov, size_t __count, unsigned int __flags);
 
 /**
- * [fallocate(2)](http://man7.org/linux/man-pages/man2/fallocate.2.html)
+ * [fallocate(2)](https://man7.org/linux/man-pages/man2/fallocate.2.html)
  * is a Linux-specific extension of posix_fallocate().
  *
  * Valid flags are `FALLOC_FL_KEEP_SIZE`, `FALLOC_FL_PUNCH_HOLE`,
@@ -187,7 +185,7 @@
 int fallocate64(int __fd, int __mode, off64_t __offset, off64_t __length);
 
 /**
- * [posix_fadvise(2)](http://man7.org/linux/man-pages/man2/posix_fadvise.2.html)
+ * [posix_fadvise(2)](https://man7.org/linux/man-pages/man2/posix_fadvise.2.html)
  * declares an expected access pattern for file data.
  *
  * Valid flags are `POSIX_FADV_NORMAL`, `POSIX_FADV_RANDOM`,
@@ -201,7 +199,7 @@
 int posix_fadvise64(int __fd, off64_t __offset, off64_t __length, int __advice);
 
 /**
- * [posix_fallocate(2)](http://man7.org/linux/man-pages/man2/posix_fallocate.2.html)
+ * [posix_fallocate(2)](https://man7.org/linux/man-pages/man2/posix_fallocate.2.html)
  * allocates file space.
  *
  * Returns 0 on success and returns an error number on failure.
@@ -213,7 +211,7 @@
 #if defined(__USE_GNU)
 
 /**
- * [readahead(2)](http://man7.org/linux/man-pages/man2/readahead.2.html)
+ * [readahead(2)](https://man7.org/linux/man-pages/man2/readahead.2.html)
  * initiates readahead for the given file.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
@@ -221,7 +219,7 @@
 ssize_t readahead(int __fd, off64_t __offset, size_t __length);
 
 /**
- * [sync_file_range(2)](http://man7.org/linux/man-pages/man2/sync_file_range.2.html)
+ * [sync_file_range(2)](https://man7.org/linux/man-pages/man2/sync_file_range.2.html)
  * syncs part of a file with disk.
  *
  * Valid flags are `SYNC_FILE_RANGE_WAIT_BEFORE`, `SYNC_FILE_RANGE_WRITE`, and
@@ -229,7 +227,11 @@
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 int sync_file_range(int __fd, off64_t __offset, off64_t __length, unsigned int __flags) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 #endif
 
diff --git a/libc/include/fenv.h b/libc/include/fenv.h
index f7dcc8e..4c1d490 100644
--- a/libc/include/fenv.h
+++ b/libc/include/fenv.h
@@ -49,7 +49,7 @@
 __BEGIN_DECLS
 
 /**
- * [feclearexcept(3)](http://man7.org/linux/man-pages/man3/feclearexcept.3.html)
+ * [feclearexcept(3)](https://man7.org/linux/man-pages/man3/feclearexcept.3.html)
  * clears the given `exceptions` in hardware.
  *
  * Returns 0 on success, and returns non-zero on failure.
@@ -57,7 +57,7 @@
 int feclearexcept(int __exceptions);
 
 /**
- * [fegetexceptflag(3)](http://man7.org/linux/man-pages/man3/fegetexceptflag.3.html)
+ * [fegetexceptflag(3)](https://man7.org/linux/man-pages/man3/fegetexceptflag.3.html)
  * copies the state of the given `exceptions` from hardware into `*flag_ptr`.
  * See fesetexceptflag().
  *
@@ -66,7 +66,7 @@
 int fegetexceptflag(fexcept_t* _Nonnull __flag_ptr, int __exceptions);
 
 /**
- * [feraiseexcept(3)](http://man7.org/linux/man-pages/man3/feraiseexcept.3.html)
+ * [feraiseexcept(3)](https://man7.org/linux/man-pages/man3/feraiseexcept.3.html)
  * raises the given `exceptions` in hardware.
  *
  * Returns 0 on success, and returns non-zero on failure.
@@ -74,7 +74,7 @@
 int feraiseexcept(int __exceptions);
 
 /**
- * [fesetexceptflag(3)](http://man7.org/linux/man-pages/man3/fesetexceptflag.3.html)
+ * [fesetexceptflag(3)](https://man7.org/linux/man-pages/man3/fesetexceptflag.3.html)
  * copies the state of the given `exceptions` from `*flag_ptr` into hardware.
  * See fesetexceptflag().
  *
@@ -83,7 +83,7 @@
 int fesetexceptflag(const fexcept_t* _Nonnull __flag_ptr, int __exceptions);
 
 /**
- * [fetestexcept(3)](http://man7.org/linux/man-pages/man3/fetestexcept.3.html)
+ * [fetestexcept(3)](https://man7.org/linux/man-pages/man3/fetestexcept.3.html)
  * tests whether the given `exceptions` are set in hardware.
  *
  * Returns the currently-set subset of `exceptions`.
@@ -91,7 +91,7 @@
 int fetestexcept(int __exceptions);
 
 /**
- * [fegetround(3)](http://man7.org/linux/man-pages/man3/fegetround.3.html)
+ * [fegetround(3)](https://man7.org/linux/man-pages/man3/fegetround.3.html)
  * returns the current rounding mode.
  *
  * Returns the rounding mode on success, and returns a negative value on failure.
@@ -99,7 +99,7 @@
 int fegetround(void);
 
 /**
- * [fesetround(3)](http://man7.org/linux/man-pages/man3/fesetround.3.html)
+ * [fesetround(3)](https://man7.org/linux/man-pages/man3/fesetround.3.html)
  * sets the current rounding mode.
  *
  * Returns 0 on success, and returns non-zero on failure.
@@ -107,7 +107,7 @@
 int fesetround(int __rounding_mode);
 
 /**
- * [fegetenv(3)](http://man7.org/linux/man-pages/man3/fegetenv.3.html)
+ * [fegetenv(3)](https://man7.org/linux/man-pages/man3/fegetenv.3.html)
  * gets the current floating-point environment. See fesetenv().
  *
  * Returns 0 on success, and returns non-zero on failure.
@@ -115,7 +115,7 @@
 int fegetenv(fenv_t* _Nonnull __env);
 
 /**
- * [feholdexcept(3)](http://man7.org/linux/man-pages/man3/feholdexcept.3.html)
+ * [feholdexcept(3)](https://man7.org/linux/man-pages/man3/feholdexcept.3.html)
  * gets the current floating-point environment, clears the status flags, and
  * ignores floating point exceptions. See fesetenv()/feupdateenv().
  *
@@ -124,7 +124,7 @@
 int feholdexcept(fenv_t* _Nonnull __env);
 
 /**
- * [fesetenv(3)](http://man7.org/linux/man-pages/man3/fesetenv.3.html)
+ * [fesetenv(3)](https://man7.org/linux/man-pages/man3/fesetenv.3.html)
  * sets the current floating-point environment. See fegetenv().
  *
  * Returns 0 on success, and returns non-zero on failure.
@@ -132,7 +132,7 @@
 int fesetenv(const fenv_t* _Nonnull __env);
 
 /**
- * [feupdateenv(3)](http://man7.org/linux/man-pages/man3/feupdateenv.3.html)
+ * [feupdateenv(3)](https://man7.org/linux/man-pages/man3/feupdateenv.3.html)
  * sets the current floating-point environment to `*env` but with currently-raised
  * exceptions still raised. See fesetenv().
  *
@@ -141,7 +141,7 @@
 int feupdateenv(const fenv_t* _Nonnull __env);
 
 /**
- * [feenableexcept(3)](http://man7.org/linux/man-pages/man3/feenableexcept.3.html)
+ * [feenableexcept(3)](https://man7.org/linux/man-pages/man3/feenableexcept.3.html)
  * sets the given `exceptions` to trap, if the hardware supports it. This is not
  * generally useful on Android, because only x86/x86-64 can trap.
  *
@@ -150,7 +150,7 @@
 int feenableexcept(int __exceptions);
 
 /**
- * [fedisableexcept(3)](http://man7.org/linux/man-pages/man3/fedisableexcept.3.html)
+ * [fedisableexcept(3)](https://man7.org/linux/man-pages/man3/fedisableexcept.3.html)
  * sets the given `exceptions` to not trap, if the hardware supports it. This is not
  * generally useful on Android, because only x86/x86-64 can trap.
  *
@@ -159,7 +159,7 @@
 int fedisableexcept(int __exceptions);
 
 /**
- * [fegetexcept(3)](http://man7.org/linux/man-pages/man3/fegetexcept.3.html)
+ * [fegetexcept(3)](https://man7.org/linux/man-pages/man3/fegetexcept.3.html)
  * returns the exceptions that currently trap. This is not generally useful on
  * Android, because only x86/x86-64 can trap.
  *
diff --git a/libc/include/fnmatch.h b/libc/include/fnmatch.h
index 1788a27..e3b17fd 100644
--- a/libc/include/fnmatch.h
+++ b/libc/include/fnmatch.h
@@ -60,7 +60,7 @@
 #define FNM_FILE_NAME    FNM_PATHNAME
 
 /**
- * [fnmatch(3)](http://man7.org/linux/man-pages/man3/fnmatch.3.html) matches `__string` against
+ * [fnmatch(3)](https://man7.org/linux/man-pages/man3/fnmatch.3.html) matches `__string` against
  * the shell wildcard `__pattern`.
  *
  * Returns 0 on success, and returns `FNM_NOMATCH` on failure.
diff --git a/libc/include/getopt.h b/libc/include/getopt.h
index c1c0442..1a30eb7 100644
--- a/libc/include/getopt.h
+++ b/libc/include/getopt.h
@@ -70,12 +70,12 @@
 __BEGIN_DECLS
 
 /**
- * [getopt_long(3)](http://man7.org/linux/man-pages/man3/getopt.3.html) parses command-line options.
+ * [getopt_long(3)](https://man7.org/linux/man-pages/man3/getopt.3.html) parses command-line options.
  */
 int getopt_long(int __argc, char* _Nonnull const* _Nonnull __argv, const char* _Nonnull __options, const struct option* _Nonnull __long_options, int* _Nullable __long_index);
 
 /**
- * [getopt_long_only(3)](http://man7.org/linux/man-pages/man3/getopt.3.html) parses command-line options.
+ * [getopt_long_only(3)](https://man7.org/linux/man-pages/man3/getopt.3.html) parses command-line options.
  */
 int getopt_long_only(int __argc, char* _Nonnull const* _Nonnull __argv, const char* _Nonnull __options, const struct option* _Nonnull __long_options, int* _Nullable __long_index);
 
diff --git a/libc/include/glob.h b/libc/include/glob.h
index 2c2b8d1..ccdf2e9 100644
--- a/libc/include/glob.h
+++ b/libc/include/glob.h
@@ -92,8 +92,12 @@
 
 __BEGIN_DECLS
 
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int glob(const char* _Nonnull __pattern, int __flags, int (* _Nullable __error_callback)(const char* _Nonnull __failure_path, int __failure_errno), glob_t* _Nonnull __result_ptr) __INTRODUCED_IN(28);
 void globfree(glob_t* _Nonnull __result_ptr) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 __END_DECLS
 
diff --git a/libc/include/grp.h b/libc/include/grp.h
index 2451db5..a48c046 100644
--- a/libc/include/grp.h
+++ b/libc/include/grp.h
@@ -51,12 +51,20 @@
 struct group* _Nullable getgrnam(const char* _Nonnull __name);
 
 /* Note: Android has thousands and thousands of ids to iterate through. */
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 struct group* _Nullable getgrent(void) __INTRODUCED_IN(26);
 
 void setgrent(void) __INTRODUCED_IN(26);
 void endgrent(void) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 int getgrgid_r(gid_t __gid, struct group* __BIONIC_COMPLICATED_NULLNESS __group, char* _Nonnull __buf, size_t __n, struct group* _Nullable * _Nonnull __result) __INTRODUCED_IN(24);
 int getgrnam_r(const char* _Nonnull __name, struct group* __BIONIC_COMPLICATED_NULLNESS __group, char* _Nonnull __buf, size_t __n, struct group* _Nullable *_Nonnull __result) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 int getgrouplist(const char* _Nonnull __user, gid_t __group, gid_t* __BIONIC_COMPLICATED_NULLNESS __groups, int* _Nonnull __group_count);
 int initgroups(const char* _Nonnull __user, gid_t __group);
 
diff --git a/libc/include/iconv.h b/libc/include/iconv.h
index 27e04bb..35328ee 100644
--- a/libc/include/iconv.h
+++ b/libc/include/iconv.h
@@ -47,7 +47,7 @@
 typedef struct __iconv_t* iconv_t;
 
 /**
- * [iconv_open(3)](http://man7.org/linux/man-pages/man3/iconv_open.3.html) allocates a new converter
+ * [iconv_open(3)](https://man7.org/linux/man-pages/man3/iconv_open.3.html) allocates a new converter
  * from `__src_encoding` to `__dst_encoding`.
  *
  * Android supports the `utf8`, `ascii`, `usascii`, `utf16be`, `utf16le`, `utf32be`, `utf32le`,
@@ -60,10 +60,12 @@
  *
  * Available since API level 28.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 iconv_t _Nonnull iconv_open(const char* _Nonnull __dst_encoding, const char* _Nonnull __src_encoding) __INTRODUCED_IN(28);
 
 /**
- * [iconv(3)](http://man7.org/linux/man-pages/man3/iconv.3.html) converts characters from one
+ * [iconv(3)](https://man7.org/linux/man-pages/man3/iconv.3.html) converts characters from one
  * encoding to another.
  *
  * Returns the number of characters converted on success and returns `((size_t) -1)` and
@@ -74,7 +76,7 @@
 size_t iconv(iconv_t _Nonnull __converter, char* _Nullable * _Nullable __src_buf, size_t* __BIONIC_COMPLICATED_NULLNESS __src_bytes_left, char* _Nullable * _Nullable __dst_buf, size_t* __BIONIC_COMPLICATED_NULLNESS __dst_bytes_left) __INTRODUCED_IN(28);
 
 /**
- * [iconv_close(3)](http://man7.org/linux/man-pages/man3/iconv_close.3.html) deallocates a converter
+ * [iconv_close(3)](https://man7.org/linux/man-pages/man3/iconv_close.3.html) deallocates a converter
  * returned by iconv_open().
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
@@ -82,5 +84,7 @@
  * Available since API level 28.
  */
 int iconv_close(iconv_t _Nonnull __converter) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 __END_DECLS
diff --git a/libc/include/ifaddrs.h b/libc/include/ifaddrs.h
index 7c0dcbf..87d2947 100644
--- a/libc/include/ifaddrs.h
+++ b/libc/include/ifaddrs.h
@@ -72,7 +72,7 @@
 #define ifa_dstaddr ifa_ifu.ifu_dstaddr
 
 /**
- * [getifaddrs(3)](http://man7.org/linux/man-pages/man3/getifaddrs.3.html) creates a linked list
+ * [getifaddrs(3)](https://man7.org/linux/man-pages/man3/getifaddrs.3.html) creates a linked list
  * of `struct ifaddrs`. The list must be freed by freeifaddrs().
  *
  * Returns 0 and stores the list in `*__list_ptr` on success,
@@ -80,14 +80,18 @@
  *
  * Available since API level 24.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 int getifaddrs(struct ifaddrs* _Nullable * _Nonnull __list_ptr) __INTRODUCED_IN(24);
 
 /**
- * [freeifaddrs(3)](http://man7.org/linux/man-pages/man3/freeifaddrs.3.html) frees a linked list
+ * [freeifaddrs(3)](https://man7.org/linux/man-pages/man3/freeifaddrs.3.html) frees a linked list
  * of `struct ifaddrs` returned by getifaddrs().
  *
  * Available since API level 24.
  */
 void freeifaddrs(struct ifaddrs* _Nullable __ptr) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 
 __END_DECLS
diff --git a/libc/include/inttypes.h b/libc/include/inttypes.h
index 9fcd9f3..790030e 100644
--- a/libc/include/inttypes.h
+++ b/libc/include/inttypes.h
@@ -19,8 +19,8 @@
 #ifndef	_INTTYPES_H_
 #define	_INTTYPES_H_
 
-#include <stdint.h>
 #include <sys/cdefs.h>
+#include <stdint.h>
 
 #ifdef __LP64__
 #define __PRI_64_prefix  "l"
diff --git a/libc/include/langinfo.h b/libc/include/langinfo.h
index 2b43892..b9d695c 100644
--- a/libc/include/langinfo.h
+++ b/libc/include/langinfo.h
@@ -92,8 +92,12 @@
 #define NOEXPR 54
 #define CRNCYSTR 55
 
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 char* _Nonnull nl_langinfo(nl_item __item) __INTRODUCED_IN(26);
 char* _Nonnull nl_langinfo_l(nl_item __item, locale_t _Nonnull __l) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 __END_DECLS
 
diff --git a/libc/include/libgen.h b/libc/include/libgen.h
index 474f066..8f2ea2b 100644
--- a/libc/include/libgen.h
+++ b/libc/include/libgen.h
@@ -41,7 +41,7 @@
 __BEGIN_DECLS
 
 /**
- * [basename(3)](http://man7.org/linux/man-pages/man3/basename.3.html)
+ * [basename(3)](https://man7.org/linux/man-pages/man3/basename.3.html)
  * returns the final component of the given path.
  *
  * See `<string.h>` for the GNU basename(). Including `<libgen.h>`,
@@ -59,7 +59,7 @@
 #define basename __posix_basename
 
 /**
- * [dirname(3)](http://man7.org/linux/man-pages/man3/dirname.3.html)
+ * [dirname(3)](https://man7.org/linux/man-pages/man3/dirname.3.html)
  * returns all but the final component of the given path.
  *
  * Note that Android's cv-qualifiers differ from POSIX; Android's implementation doesn't
diff --git a/libc/include/limits.h b/libc/include/limits.h
index e1f566c..5e9ce59 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -1,6 +1,3 @@
-/*	$OpenBSD: limits.h,v 1.13 2005/12/31 19:29:38 millert Exp $	*/
-/*	$NetBSD: limits.h,v 1.7 1994/10/26 00:56:00 cgd Exp $	*/
-
 /*
  * Copyright (c) 1988 The Regents of the University of California.
  * All rights reserved.
@@ -32,108 +29,101 @@
  *	@(#)limits.h	5.9 (Berkeley) 4/3/91
  */
 
-#ifndef _LIMITS_H_
-#define _LIMITS_H_
+#pragma once
+
+/**
+ * @file limits.h
+ * @brief Constants relating to implementation limits.
+ *
+ * This file is included via `#include_next` from the clang header of the same
+ * name that provides all the limits that the compiler is responsible for,
+ * primarily those relating to integer types defined by the C standard.
+ * This file defines the additional limits defined by POSIX.
+ */
+
+/*
+ * The Android build system has bionic _before_ the clang headers,
+ * so although the claim above that clang does an `#include_next`
+ * of this file is true for the NDK, it's not true for the OS,
+ * and we need to paper over that difference here until/unless
+ * the OS build changes.
+ */
+#if __has_include_next(<limits.h>)
+#include_next <limits.h>
+#endif
 
 #include <sys/cdefs.h>
 
 /* Historically bionic exposed the content of <float.h> from <limits.h> and <sys/limits.h> too. */
 #include <float.h>
 
+/* Many of the POSIX limits come from the kernel. */
 #include <linux/limits.h>
 
-#define PASS_MAX		128	/* _PASSWORD_LEN from <pwd.h> */
-
-#define NL_ARGMAX		9
-#define NL_LANGMAX		14
-#define NL_MSGMAX		32767
-#define NL_NMAX			1
-#define NL_SETMAX		255
-#define NL_TEXTMAX		255
-
-#define TMP_MAX                 308915776
-
-/* TODO: get all these from the compiler's <limits.h>? */
-
-#define CHAR_BIT 8
-#ifdef __LP64__
-# define LONG_BIT 64
-#else
-# define LONG_BIT 32
+/*
+ * bionic always exposed these alternative names,
+ * but clang's <limits.h> considers them GNU extensions,
+ * and may or may not have defined them.
+ */
+#ifndef LONG_LONG_MIN
+/** Non-portable synonym; use LLONG_MIN directly instead. */
+#define LONG_LONG_MIN LLONG_MIN
 #endif
+#ifndef LONG_LONG_MAX
+/** Non-portable synonym; use LLONG_MAX directly instead. */
+#define LONG_LONG_MAX LLONG_MAX
+#endif
+#ifndef ULONG_LONG_MAX
+/** Non-portable synonym; use ULLONG_MAX directly instead. */
+#define ULONG_LONG_MAX ULLONG_MAX
+#endif
+
+/** Maximum number of positional arguments in a printf()/scanf() format string. */
+#define NL_ARGMAX 9
+/** Maximum number of bytes in a $LANG name. */
+#define NL_LANGMAX 14
+/** Irrelevant with Android's <nl_types.h>. */
+#define NL_MSGMAX 32767
+/** Obsolete; removed from POSIX. */
+#define NL_NMAX 1
+/** Irrelevant with Android's <nl_types.h>. */
+#define NL_SETMAX 255
+/** Irrelevant with Android's <nl_types.h>. */
+#define NL_TEXTMAX 255
+
+/** Obsolete; removed from POSIX. */
+#define PASS_MAX 128
+/** Obsolete; removed from POSIX. */
+#define TMP_MAX 308915776
+
+/** Number of bits in a `long` (POSIX). */
+#if __LP64__
+#define LONG_BIT 64
+#else
+#define LONG_BIT 32
+#endif
+/** Number of bits in a "word" of `int` (POSIX). */
 #define WORD_BIT 32
 
-#define	SCHAR_MAX	0x7f		/* max value for a signed char */
-#define SCHAR_MIN	(-0x7f-1)	/* min value for a signed char */
-
-#define	UCHAR_MAX	0xffU		/* max value for an unsigned char */
-#ifdef __CHAR_UNSIGNED__
-# define CHAR_MIN	0		/* min value for a char */
-# define CHAR_MAX	0xff		/* max value for a char */
-#else
-# define CHAR_MAX	0x7f
-# define CHAR_MIN	(-0x7f-1)
-#endif
-
-#define	USHRT_MAX	0xffffU		/* max value for an unsigned short */
-#define	SHRT_MAX	0x7fff		/* max value for a short */
-#define SHRT_MIN        (-0x7fff-1)     /* min value for a short */
-
-#define	UINT_MAX	0xffffffffU	/* max value for an unsigned int */
-#define	INT_MAX		0x7fffffff	/* max value for an int */
-#define	INT_MIN		(-0x7fffffff-1)	/* min value for an int */
-
-#ifdef __LP64__
-# define ULONG_MAX	0xffffffffffffffffUL     /* max value for unsigned long */
-# define LONG_MAX	0x7fffffffffffffffL      /* max value for a signed long */
-# define LONG_MIN	(-0x7fffffffffffffffL-1) /* min value for a signed long */
-#else
-# define ULONG_MAX	0xffffffffUL	/* max value for an unsigned long */
-# define LONG_MAX	0x7fffffffL	/* max value for a long */
-# define LONG_MIN	(-0x7fffffffL-1)/* min value for a long */
-#endif
-
-# define ULLONG_MAX	0xffffffffffffffffULL     /* max value for unsigned long long */
-# define LLONG_MAX	0x7fffffffffffffffLL      /* max value for a signed long long */
-# define LLONG_MIN	(-0x7fffffffffffffffLL-1) /* min value for a signed long long */
-
-/* GLibc compatibility definitions.
-   Note that these are defined by GCC's <limits.h>
-   only when __GNU_LIBRARY__ is defined, i.e. when
-   targetting GLibc. */
-#ifndef LONG_LONG_MIN
-#define LONG_LONG_MIN  LLONG_MIN
-#endif
-
-#ifndef LONG_LONG_MAX
-#define LONG_LONG_MAX  LLONG_MAX
-#endif
-
-#ifndef ULONG_LONG_MAX
-#define ULONG_LONG_MAX  ULLONG_MAX
-#endif
-
-#if defined(__USE_BSD) || defined(__BIONIC__) /* Historically bionic exposed these. */
-# define UID_MAX	UINT_MAX	/* max value for a uid_t */
-# define GID_MAX	UINT_MAX	/* max value for a gid_t */
-#if defined(__LP64__)
+/** Maximum value of a uid_t. */
+#define UID_MAX UINT_MAX
+/** Maximum value of a gid_t. */
+#define GID_MAX UINT_MAX
+/** Maximum value of a size_t. */
 #define SIZE_T_MAX ULONG_MAX
-#else
-#define SIZE_T_MAX UINT_MAX
-#endif
-#endif
-
-#if defined(__LP64__)
+/** Maximum value of a ssize_t. */
 #define SSIZE_MAX LONG_MAX
-#else
-#define SSIZE_MAX INT_MAX
-#endif
 
+/** Maximum number of bytes in a multibyte character. */
 #define MB_LEN_MAX 4
 
+/** Default process priority. */
 #define NZERO 20
 
+/** Maximum number of struct iovec that can be passed in a single readv()/writev(). */
 #define IOV_MAX 1024
+
+/** Maximum value for a semaphore. */
 #define SEM_VALUE_MAX 0x3fffffff
 
 /** Do not use: prefer getline() or asprintf() rather than hard-coding an arbitrary size. */
@@ -142,12 +132,17 @@
 /* POSIX says these belong in <unistd.h> but BSD has some in <limits.h>. */
 #include <bits/posix_limits.h>
 
+/** Maximum length of a hostname returned by gethostname(). */
 #define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
+
+/** Maximum length of a login name. */
 #define LOGIN_NAME_MAX 256
+
+/** Maximum length of terminal device name. */
 #define TTY_NAME_MAX 32
 
-/* >= _POSIX_THREAD_DESTRUCTOR_ITERATIONS */
-#define PTHREAD_DESTRUCTOR_ITERATIONS 4
+/** Maximum number of attempts to destroy thread-specific data when a thread exits. */
+#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
 
 /**
  * The number of calls to pthread_key_create() without intervening calls to
@@ -156,7 +151,5 @@
  */
 #define PTHREAD_KEYS_MAX 128
 
-/** bionic has no specific limit on the number of threads. */
+/** bionic has no fixed limit on the number of threads. */
 #undef PTHREAD_THREADS_MAX
-
-#endif /* !_LIMITS_H_ */
diff --git a/libc/include/link.h b/libc/include/link.h
index ee1fc42..331070e 100644
--- a/libc/include/link.h
+++ b/libc/include/link.h
@@ -33,8 +33,9 @@
  * @brief Extra dynamic linker functionality (see also <dlfcn.h>).
  */
 
-#include <stdint.h>
 #include <sys/cdefs.h>
+
+#include <stdint.h>
 #include <sys/types.h>
 
 #include <elf.h>
@@ -99,7 +100,7 @@
 };
 
 /**
- * [dl_iterate_phdr(3)](http://man7.org/linux/man-pages/man3/dl_iterate_phdr.3.html)
+ * [dl_iterate_phdr(3)](https://man7.org/linux/man-pages/man3/dl_iterate_phdr.3.html)
  * calls the given callback once for every loaded shared object. The size
  * argument to the callback lets you determine whether you have a smaller
  * `dl_phdr_info` from before API level 30, or the newer full one.
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index 3ebc1be..ac27467 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -34,7 +34,7 @@
 #define __BIONIC_ALLOC_SIZE(...) __attribute__((__alloc_size__(__VA_ARGS__)))
 
 /**
- * [malloc(3)](http://man7.org/linux/man-pages/man3/malloc.3.html) allocates
+ * [malloc(3)](https://man7.org/linux/man-pages/man3/malloc.3.html) allocates
  * memory on the heap.
  *
  * Returns a pointer to the allocated memory on success and returns a null
@@ -55,29 +55,29 @@
  * other processes. Obviously this is not the case for apps, which will
  * be killed in preference to killing other processes.
  */
-void* _Nullable malloc(size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(1) __wur;
+__nodiscard void* _Nullable malloc(size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(1);
 
 /**
- * [calloc(3)](http://man7.org/linux/man-pages/man3/calloc.3.html) allocates
+ * [calloc(3)](https://man7.org/linux/man-pages/man3/calloc.3.html) allocates
  * and clears memory on the heap.
  *
  * Returns a pointer to the allocated memory on success and returns a null
  * pointer and sets `errno` on failure (but see the notes for malloc()).
  */
-void* _Nullable calloc(size_t __item_count, size_t __item_size) __mallocfunc __BIONIC_ALLOC_SIZE(1,2) __wur;
+__nodiscard void* _Nullable calloc(size_t __item_count, size_t __item_size) __mallocfunc __BIONIC_ALLOC_SIZE(1,2);
 
 /**
- * [realloc(3)](http://man7.org/linux/man-pages/man3/realloc.3.html) resizes
+ * [realloc(3)](https://man7.org/linux/man-pages/man3/realloc.3.html) resizes
  * allocated memory on the heap.
  *
  * Returns a pointer (which may be different from `__ptr`) to the resized
  * memory on success and returns a null pointer and sets `errno` on failure
  * (but see the notes for malloc()).
  */
-void* _Nullable realloc(void* _Nullable __ptr, size_t __byte_count) __BIONIC_ALLOC_SIZE(2) __wur;
+__nodiscard void* _Nullable realloc(void* _Nullable __ptr, size_t __byte_count) __BIONIC_ALLOC_SIZE(2);
 
 /**
- * [reallocarray(3)](http://man7.org/linux/man-pages/man3/realloc.3.html) resizes
+ * [reallocarray(3)](https://man7.org/linux/man-pages/man3/realloc.3.html) resizes
  * allocated memory on the heap.
  *
  * Equivalent to `realloc(__ptr, __item_count * __item_size)` but fails if the
@@ -87,16 +87,28 @@
  * memory on success and returns a null pointer and sets `errno` on failure
  * (but see the notes for malloc()).
  */
-void* _Nullable reallocarray(void* _Nullable __ptr, size_t __item_count, size_t __item_size) __BIONIC_ALLOC_SIZE(2, 3) __wur __INTRODUCED_IN(29);
+#if __ANDROID_API__ >= 29
+__nodiscard void* _Nullable reallocarray(void* _Nullable __ptr, size_t __item_count, size_t __item_size) __BIONIC_ALLOC_SIZE(2, 3) __INTRODUCED_IN(29);
+#elif defined(__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__)
+#include <errno.h>
+static __inline __nodiscard void* _Nullable reallocarray(void* _Nullable __ptr, size_t __item_count, size_t __item_size) __BIONIC_ALLOC_SIZE(2, 3) {
+  size_t __new_size;
+  if (__builtin_mul_overflow(__item_count, __item_size, &__new_size)) {
+    errno = ENOMEM;
+    return NULL;
+  }
+  return realloc(__ptr, __new_size);
+}
+#endif
 
 /**
- * [free(3)](http://man7.org/linux/man-pages/man3/free.3.html) deallocates
+ * [free(3)](https://man7.org/linux/man-pages/man3/free.3.html) deallocates
  * memory on the heap.
  */
 void free(void* _Nullable __ptr);
 
 /**
- * [memalign(3)](http://man7.org/linux/man-pages/man3/memalign.3.html) allocates
+ * [memalign(3)](https://man7.org/linux/man-pages/man3/memalign.3.html) allocates
  * memory on the heap with the required alignment.
  *
  * Returns a pointer to the allocated memory on success and returns a null
@@ -104,13 +116,13 @@
  *
  * See also posix_memalign().
  */
-void* _Nullable memalign(size_t __alignment, size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(2) __wur;
+__nodiscard void* _Nullable memalign(size_t __alignment, size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(2);
 
 /**
- * [malloc_usable_size(3)](http://man7.org/linux/man-pages/man3/malloc_usable_size.3.html)
+ * [malloc_usable_size(3)](https://man7.org/linux/man-pages/man3/malloc_usable_size.3.html)
  * returns the actual size of the given heap block.
  */
-size_t malloc_usable_size(const void* _Nullable __ptr) __wur;
+__nodiscard size_t malloc_usable_size(const void* _Nullable __ptr);
 
 #define __MALLINFO_BODY \
   /** Total number of non-mmapped bytes currently allocated from OS. */ \
@@ -140,7 +152,7 @@
 #endif
 
 /**
- * [mallinfo(3)](http://man7.org/linux/man-pages/man3/mallinfo.3.html) returns
+ * [mallinfo(3)](https://man7.org/linux/man-pages/man3/mallinfo.3.html) returns
  * information about the current state of the heap. Note that mallinfo() is
  * inherently unreliable and consider using malloc_info() instead.
  */
@@ -152,14 +164,14 @@
 struct mallinfo2 { __MALLINFO_BODY };
 
 /**
- * [mallinfo2(3)](http://man7.org/linux/man-pages/man3/mallinfo2.3.html) returns
+ * [mallinfo2(3)](https://man7.org/linux/man-pages/man3/mallinfo2.3.html) returns
  * information about the current state of the heap. Note that mallinfo2() is
  * inherently unreliable and consider using malloc_info() instead.
  */
 struct mallinfo2 mallinfo2(void) __RENAME(mallinfo);
 
 /**
- * [malloc_info(3)](http://man7.org/linux/man-pages/man3/malloc_info.3.html)
+ * [malloc_info(3)](https://man7.org/linux/man-pages/man3/malloc_info.3.html)
  * writes information about the current state of the heap to the given stream.
  *
  * The XML structure for malloc_info() is as follows:
@@ -183,7 +195,11 @@
  *
  * Available since API level 23.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int malloc_info(int __must_be_zero, FILE* _Nonnull __fp) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 /**
  * mallopt() option to set the decay time. Valid values are -1, 0 and 1.
@@ -349,17 +365,21 @@
 #define M_LOG_STATS (-205)
 
 /**
- * [mallopt(3)](http://man7.org/linux/man-pages/man3/mallopt.3.html) modifies
+ * [mallopt(3)](https://man7.org/linux/man-pages/man3/mallopt.3.html) modifies
  * heap behavior. Values of `__option` are the `M_` constants from this header.
  *
  * Returns 1 on success, 0 on error.
  *
  * Available since API level 26.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 int mallopt(int __option, int __value) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 /**
- * [__malloc_hook(3)](http://man7.org/linux/man-pages/man3/__malloc_hook.3.html)
+ * [__malloc_hook(3)](https://man7.org/linux/man-pages/man3/__malloc_hook.3.html)
  * is called to implement malloc(). By default this points to the system's
  * implementation.
  *
@@ -367,10 +387,12 @@
  *
  * See also: [extra documentation](https://android.googlesource.com/platform/bionic/+/main/libc/malloc_hooks/README.md)
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 extern void* _Nonnull (*volatile _Nonnull __malloc_hook)(size_t __byte_count, const void* _Nonnull __caller) __INTRODUCED_IN(28);
 
 /**
- * [__realloc_hook(3)](http://man7.org/linux/man-pages/man3/__realloc_hook.3.html)
+ * [__realloc_hook(3)](https://man7.org/linux/man-pages/man3/__realloc_hook.3.html)
  * is called to implement realloc(). By default this points to the system's
  * implementation.
  *
@@ -381,7 +403,7 @@
 extern void* _Nonnull (*volatile _Nonnull __realloc_hook)(void* _Nullable __ptr, size_t __byte_count, const void* _Nonnull __caller) __INTRODUCED_IN(28);
 
 /**
- * [__free_hook(3)](http://man7.org/linux/man-pages/man3/__free_hook.3.html)
+ * [__free_hook(3)](https://man7.org/linux/man-pages/man3/__free_hook.3.html)
  * is called to implement free(). By default this points to the system's
  * implementation.
  *
@@ -392,7 +414,7 @@
 extern void (*volatile _Nonnull __free_hook)(void* _Nullable __ptr, const void* _Nonnull __caller) __INTRODUCED_IN(28);
 
 /**
- * [__memalign_hook(3)](http://man7.org/linux/man-pages/man3/__memalign_hook.3.html)
+ * [__memalign_hook(3)](https://man7.org/linux/man-pages/man3/__memalign_hook.3.html)
  * is called to implement memalign(). By default this points to the system's
  * implementation.
  *
@@ -401,5 +423,7 @@
  * See also: [extra documentation](https://android.googlesource.com/platform/bionic/+/main/libc/malloc_hooks/README.md)
  */
 extern void* _Nonnull (*volatile _Nonnull __memalign_hook)(size_t __alignment, size_t __byte_count, const void* _Nonnull __caller) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 __END_DECLS
diff --git a/libc/include/math.h b/libc/include/math.h
index 343ab98..59161bf 100644
--- a/libc/include/math.h
+++ b/libc/include/math.h
@@ -350,7 +350,11 @@
 double gamma_r(double __x, int* _Nonnull __sign);
 double lgamma_r(double __x, int* _Nonnull __sign);
 double significand(double __x);
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 long double lgammal_r(long double __x, int* _Nonnull __sign) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 long double significandl(long double __x);
 float dremf(float __x, float __y);
 int finitef(float __x) __attribute_const__;
diff --git a/libc/include/mntent.h b/libc/include/mntent.h
index 9a31838..4c03602 100644
--- a/libc/include/mntent.h
+++ b/libc/include/mntent.h
@@ -29,8 +29,9 @@
 #ifndef _MNTENT_H_
 #define _MNTENT_H_
 
-#include <stdio.h>
 #include <sys/cdefs.h>
+
+#include <stdio.h>
 #include <paths.h>  /* for _PATH_MOUNTED */
 
 #define MOUNTED _PATH_MOUNTED
@@ -61,7 +62,11 @@
 struct mntent* _Nullable getmntent(FILE* _Nonnull __fp);
 struct mntent* _Nullable getmntent_r(FILE* _Nonnull __fp, struct mntent* _Nonnull __entry, char* _Nonnull __buf, int __size);
 FILE* _Nullable setmntent(const char* _Nonnull __filename, const char* _Nonnull __type);
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 char* _Nullable hasmntopt(const struct mntent* _Nonnull __entry, const char* _Nonnull __option) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 __END_DECLS
 
diff --git a/libc/include/net/if.h b/libc/include/net/if.h
index 79b4195..50bc74c 100644
--- a/libc/include/net/if.h
+++ b/libc/include/net/if.h
@@ -29,9 +29,10 @@
 #ifndef _NET_IF_H_
 #define _NET_IF_H_
 
+#include <sys/cdefs.h>
+
 #include <sys/socket.h>
 #include <linux/if.h>
-#include <sys/cdefs.h>
 
 #ifndef IF_NAMESIZE
 #define IF_NAMESIZE IFNAMSIZ
@@ -46,8 +47,12 @@
 
 char* _Nullable if_indextoname(unsigned __index, char* _Nonnull __buf);
 unsigned if_nametoindex(const char* _Nonnull __name);
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 struct if_nameindex* _Nullable if_nameindex(void) __INTRODUCED_IN(24);
 void if_freenameindex(struct if_nameindex* _Nullable __ptr) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 
 __END_DECLS
 
diff --git a/libc/include/netdb.h b/libc/include/netdb.h
index 88214d5..04aaf5c 100644
--- a/libc/include/netdb.h
+++ b/libc/include/netdb.h
@@ -212,28 +212,52 @@
 void herror(const char* _Nonnull __s);
 const char* _Nonnull hstrerror(int __error);
 struct hostent* _Nullable gethostbyaddr(const void* _Nonnull __addr, socklen_t __length, int __type);
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int gethostbyaddr_r(const void* _Nonnull __addr, socklen_t __length, int __type, struct hostent* _Nonnull __ret, char* _Nonnull __buf, size_t __buf_size, struct hostent* _Nullable * _Nonnull __result, int* _Nonnull __h_errno_ptr) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 struct hostent* _Nullable gethostbyname(const char* _Nonnull __name);
 int gethostbyname_r(const char* _Nonnull __name, struct hostent* _Nonnull __ret, char* _Nonnull __buf, size_t __buf_size, struct hostent* _Nullable * _Nonnull __result, int* _Nonnull __h_errno_ptr);
 struct hostent* _Nullable gethostbyname2(const char* _Nonnull __name, int __af);
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int gethostbyname2_r(const char* _Nonnull __name, int __af, struct hostent* _Nonnull __ret, char* _Nonnull __buf, size_t __buf_size, struct hostent* _Nullable * _Nonnull __result, int* _Nonnull __h_errno_ptr) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 void endhostent(void) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 struct hostent* _Nullable gethostent(void);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 void sethostent(int __stay_open) __INTRODUCED_IN(28);
 
 /* These functions are obsolete. None of these functions return anything but nullptr. */
 void endnetent(void) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 struct netent* _Nullable getnetbyaddr(uint32_t __net, int __type);
 struct netent* _Nullable getnetbyname(const char* _Nonnull __name);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 struct netent* _Nullable getnetent(void) __INTRODUCED_IN(28);
 void setnetent(int __stay_open) __INTRODUCED_IN(28);
 
 /* None of these functions return anything but nullptr. */
 void endprotoent(void) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 struct protoent* _Nullable getprotobyname(const char* _Nonnull __name);
 struct protoent* _Nullable getprotobynumber(int __proto);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 struct protoent* _Nullable getprotoent(void) __INTRODUCED_IN(28);
 void setprotoent(int __stay_open) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 /* These functions return entries from a built-in database. */
 void endservent(void);
diff --git a/libc/include/netinet/ether.h b/libc/include/netinet/ether.h
index 4af7eda..a847385 100644
--- a/libc/include/netinet/ether.h
+++ b/libc/include/netinet/ether.h
@@ -39,7 +39,7 @@
 __BEGIN_DECLS
 
 /**
- * [ether_ntoa(3)](http://man7.org/linux/man-pages/man3/ether_ntoa.3.html) returns a string
+ * [ether_ntoa(3)](https://man7.org/linux/man-pages/man3/ether_ntoa.3.html) returns a string
  * representation of the given Ethernet (MAC) address.
  *
  * Returns a pointer to a static buffer.
@@ -47,7 +47,7 @@
 char* _Nonnull ether_ntoa(const struct ether_addr* _Nonnull __addr);
 
 /**
- * [ether_ntoa_r(3)](http://man7.org/linux/man-pages/man3/ether_ntoa_r.3.html) returns a string
+ * [ether_ntoa_r(3)](https://man7.org/linux/man-pages/man3/ether_ntoa_r.3.html) returns a string
  * representation of the given Ethernet (MAC) address.
  *
  * Returns a pointer to the given buffer.
@@ -55,7 +55,7 @@
 char* _Nonnull ether_ntoa_r(const struct ether_addr* _Nonnull __addr, char* _Nonnull __buf);
 
 /**
- * [ether_aton(3)](http://man7.org/linux/man-pages/man3/ether_aton.3.html) returns an `ether_addr`
+ * [ether_aton(3)](https://man7.org/linux/man-pages/man3/ether_aton.3.html) returns an `ether_addr`
  * corresponding to the given Ethernet (MAC) address string.
  *
  * Returns a pointer to a static buffer, or NULL if the given string isn't a valid MAC address.
@@ -63,7 +63,7 @@
 struct ether_addr* _Nullable ether_aton(const char* _Nonnull __ascii);
 
 /**
- * [ether_aton_r(3)](http://man7.org/linux/man-pages/man3/ether_aton_r.3.html) returns an
+ * [ether_aton_r(3)](https://man7.org/linux/man-pages/man3/ether_aton_r.3.html) returns an
  * `ether_addr` corresponding to the given Ethernet (MAC) address string.
  *
  * Returns a pointer to the given buffer, or NULL if the given string isn't a valid MAC address.
diff --git a/libc/include/netinet/icmp6.h b/libc/include/netinet/icmp6.h
index 2b237a8..ebd9f6c 100644
--- a/libc/include/netinet/icmp6.h
+++ b/libc/include/netinet/icmp6.h
@@ -65,9 +65,10 @@
 #ifndef _NETINET_ICMP6_H_
 #define _NETINET_ICMP6_H_
 
-#include <netinet/in.h> /* android-added: glibc source compatibility. */
 #include <sys/cdefs.h>
 
+#include <netinet/in.h> /* android-added: glibc source compatibility. */
+
 #define ICMPV6_PLD_MAXLEN	1232	/* IPV6_MMTU - sizeof(struct ip6_hdr)
 					   - sizeof(struct icmp6_hdr) */
 
diff --git a/libc/include/netinet/in.h b/libc/include/netinet/in.h
index 163e614..d4ce302 100644
--- a/libc/include/netinet/in.h
+++ b/libc/include/netinet/in.h
@@ -28,9 +28,10 @@
 
 #pragma once
 
+#include <sys/cdefs.h>
+
 #include <endian.h>
 #include <netinet/in6.h>
-#include <sys/cdefs.h>
 #include <sys/socket.h>
 
 #include <linux/in.h>
diff --git a/libc/include/netinet/in6.h b/libc/include/netinet/in6.h
index ae20f83..44b3e3e 100644
--- a/libc/include/netinet/in6.h
+++ b/libc/include/netinet/in6.h
@@ -89,7 +89,7 @@
   (IN6_IS_ADDR_MULTICAST(a) && (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_GLOBAL))
 
 #define IN6_ARE_ADDR_EQUAL(a, b) \
-  (memcmp(&(a)->s6_addr[0], &(b)->s6_addr[0], sizeof(struct in6_addr)) == 0)
+  (__builtin_memcmp(&(a)->s6_addr[0], &(b)->s6_addr[0], sizeof(struct in6_addr)) == 0)
 
 #define INET6_ADDRSTRLEN 46
 
diff --git a/libc/include/nl_types.h b/libc/include/nl_types.h
index f4d7f43..172d80d 100644
--- a/libc/include/nl_types.h
+++ b/libc/include/nl_types.h
@@ -56,16 +56,18 @@
 typedef int nl_item;
 
 /**
- * [catopen(3)](http://man7.org/linux/man-pages/man3/catopen.3.html) opens a message catalog.
+ * [catopen(3)](https://man7.org/linux/man-pages/man3/catopen.3.html) opens a message catalog.
  *
  * On Android, this always returns failure: `((nl_catd) -1)`.
  *
  * Available since API level 28.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 nl_catd _Nonnull catopen(const char* _Nonnull __name, int __flag) __INTRODUCED_IN(26);
 
 /**
- * [catgets(3)](http://man7.org/linux/man-pages/man3/catgets.3.html) translates the given message
+ * [catgets(3)](https://man7.org/linux/man-pages/man3/catgets.3.html) translates the given message
  * using the given message catalog.
  *
  * On Android, this always returns `__msg`.
@@ -75,10 +77,12 @@
 char* _Nonnull catgets(nl_catd _Nonnull __catalog, int __set_number, int __msg_number, const char* _Nonnull __msg) __INTRODUCED_IN(26);
 
 /**
- * [catclose(3)](http://man7.org/linux/man-pages/man3/catclose.3.html) closes a message catalog.
+ * [catclose(3)](https://man7.org/linux/man-pages/man3/catclose.3.html) closes a message catalog.
  *
  * On Android, this always returns -1 with `errno` set to `EBADF`.
  */
 int catclose(nl_catd _Nonnull __catalog) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 __END_DECLS
diff --git a/libc/include/poll.h b/libc/include/poll.h
index 6bdc886..e57f812 100644
--- a/libc/include/poll.h
+++ b/libc/include/poll.h
@@ -44,7 +44,7 @@
 typedef unsigned int nfds_t;
 
 /**
- * [poll(3)](http://man7.org/linux/man-pages/man3/poll.3.html) waits on a set of file descriptors.
+ * [poll(3)](https://man7.org/linux/man-pages/man3/poll.3.html) waits on a set of file descriptors.
  *
  * Returns the number of ready file descriptors on success, 0 for timeout,
  * and returns -1 and sets `errno` on failure.
@@ -52,7 +52,7 @@
 int poll(struct pollfd* _Nullable __fds, nfds_t __count, int __timeout_ms);
 
 /**
- * [ppoll(3)](http://man7.org/linux/man-pages/man3/ppoll.3.html) waits on a set of file descriptors
+ * [ppoll(3)](https://man7.org/linux/man-pages/man3/ppoll.3.html) waits on a set of file descriptors
  * or a signal. Set `__timeout` to null for no timeout. Set `__mask` to null to not set the signal
  * mask.
  *
@@ -64,7 +64,11 @@
 /**
  * Like ppoll() but allows setting a signal mask with RT signals even from a 32-bit process.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int ppoll64(struct pollfd* _Nullable  __fds, nfds_t __count, const struct timespec* _Nullable __timeout, const sigset64_t* _Nullable __mask) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
 #define _POLL_H_
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index ef41e2d..cdf1b8c 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -33,11 +33,12 @@
  * @brief POSIX threads.
  */
 
+#include <sys/cdefs.h>
+
 #include <limits.h>
 #include <bits/page_size.h>
 #include <bits/pthread_types.h>
 #include <sched.h>
-#include <sys/cdefs.h>
 #include <sys/types.h>
 #include <time.h>
 
@@ -70,9 +71,7 @@
 
 #define PTHREAD_ONCE_INIT 0
 
-#if __ANDROID_API__ >= 24
 #define PTHREAD_BARRIER_SERIAL_THREAD (-1)
-#endif
 
 #if defined(__LP64__)
 #define PTHREAD_STACK_MIN 16384
@@ -100,7 +99,11 @@
 int pthread_attr_destroy(pthread_attr_t* _Nonnull __attr);
 int pthread_attr_getdetachstate(const pthread_attr_t* _Nonnull __attr, int* _Nonnull __state);
 int pthread_attr_getguardsize(const pthread_attr_t* _Nonnull __attr, size_t* _Nonnull __size);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int pthread_attr_getinheritsched(const pthread_attr_t* _Nonnull __attr, int* _Nonnull __flag) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 int pthread_attr_getschedparam(const pthread_attr_t* _Nonnull __attr, struct sched_param* _Nonnull __param);
 int pthread_attr_getschedpolicy(const pthread_attr_t* _Nonnull __attr, int* _Nonnull __policy);
 int pthread_attr_getscope(const pthread_attr_t* _Nonnull __attr, int* _Nonnull __scope);
@@ -109,7 +112,11 @@
 int pthread_attr_init(pthread_attr_t* _Nonnull __attr);
 int pthread_attr_setdetachstate(pthread_attr_t* _Nonnull __attr, int __state);
 int pthread_attr_setguardsize(pthread_attr_t* _Nonnull __attr, size_t __size);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int pthread_attr_setinheritsched(pthread_attr_t* _Nonnull __attr, int __flag) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 int pthread_attr_setschedparam(pthread_attr_t* _Nonnull __attr, const struct sched_param* _Nonnull __param);
 int pthread_attr_setschedpolicy(pthread_attr_t* _Nonnull __attr, int __policy);
 int pthread_attr_setscope(pthread_attr_t* _Nonnull __attr, int __scope);
@@ -124,8 +131,12 @@
 int pthread_condattr_setpshared(pthread_condattr_t* _Nonnull __attr, int __shared);
 
 int pthread_cond_broadcast(pthread_cond_t* _Nonnull __cond);
+
+#if __BIONIC_AVAILABILITY_GUARD(30)
 int pthread_cond_clockwait(pthread_cond_t* _Nonnull __cond, pthread_mutex_t* _Nonnull __mutex, clockid_t __clock,
                            const struct timespec* _Nullable __timeout) __INTRODUCED_IN(30);
+#endif /* __BIONIC_AVAILABILITY_GUARD(30) */
+
 int pthread_cond_destroy(pthread_cond_t* _Nonnull __cond);
 int pthread_cond_init(pthread_cond_t* _Nonnull __cond, const pthread_condattr_t* _Nullable __attr);
 int pthread_cond_signal(pthread_cond_t* _Nonnull __cond);
@@ -140,24 +151,15 @@
  * Note that pthread_cond_clockwait() allows specifying an arbitrary clock and has superseded this
  * function.
  */
+
+#if (!defined(__LP64__)) || (defined(__LP64__) && __ANDROID_API__ >= 28)
 int pthread_cond_timedwait_monotonic_np(pthread_cond_t* _Nonnull __cond, pthread_mutex_t* _Nonnull __mutex,
                                         const struct timespec* _Nullable __timeout) __INTRODUCED_IN_64(28);
+#endif /* (!defined(__LP64__)) || (defined(__LP64__) && __ANDROID_API__ >= 28) */
+
 int pthread_cond_wait(pthread_cond_t* _Nonnull __cond, pthread_mutex_t* _Nonnull __mutex);
 
-#if defined(__clang__)
-/*
- * Disable -Wbuiltin-requires-header because clang confuses this declaration with the one defined in
- * "llvm/tools/clang/include/clang/Basic/Builtins.def", which did not define any formal arguments.
- * It seems to be an upstream bug and the fix (https://reviews.llvm.org/D58531) is still under
- * review. Thus, let's disable the warning for this function declaration.
- */
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wbuiltin-requires-header"
-#endif
-int pthread_create(pthread_t* _Nonnull __pthread_ptr, pthread_attr_t const* _Nullable __attr, void* _Nonnull (* _Nonnull __start_routine)(void* _Nonnull), void* _Nullable);
-#if defined(__clang__)
-#pragma clang diagnostic pop
-#endif
+int pthread_create(pthread_t* _Nonnull __pthread_ptr, pthread_attr_t const* _Nullable __attr, void* _Nullable (* _Nonnull __start_routine)(void* _Nullable), void* _Nullable);
 
 int pthread_detach(pthread_t __pthread);
 void pthread_exit(void* _Nullable __return_value) __noreturn;
@@ -202,14 +204,26 @@
 int pthread_mutexattr_destroy(pthread_mutexattr_t* _Nonnull __attr);
 int pthread_mutexattr_getpshared(const pthread_mutexattr_t* _Nonnull __attr, int* _Nonnull __shared);
 int pthread_mutexattr_gettype(const pthread_mutexattr_t* _Nonnull __attr, int* _Nonnull __type);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int pthread_mutexattr_getprotocol(const pthread_mutexattr_t* _Nonnull __attr, int* _Nonnull __protocol) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 int pthread_mutexattr_init(pthread_mutexattr_t* _Nonnull __attr);
 int pthread_mutexattr_setpshared(pthread_mutexattr_t* _Nonnull __attr, int __shared);
 int pthread_mutexattr_settype(pthread_mutexattr_t* _Nonnull __attr, int __type);
-int pthread_mutexattr_setprotocol(pthread_mutexattr_t* _Nonnull __attr, int __protocol) __INTRODUCED_IN(28);
 
+#if __BIONIC_AVAILABILITY_GUARD(28)
+int pthread_mutexattr_setprotocol(pthread_mutexattr_t* _Nonnull __attr, int __protocol) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
+
+
+#if __BIONIC_AVAILABILITY_GUARD(30)
 int pthread_mutex_clocklock(pthread_mutex_t* _Nonnull __mutex, clockid_t __clock,
                             const struct timespec* _Nullable __abstime) __INTRODUCED_IN(30);
+#endif /* __BIONIC_AVAILABILITY_GUARD(30) */
+
 int pthread_mutex_destroy(pthread_mutex_t* _Nonnull __mutex);
 int pthread_mutex_init(pthread_mutex_t* _Nonnull __mutex, const pthread_mutexattr_t* _Nullable __attr);
 int pthread_mutex_lock(pthread_mutex_t* _Nonnull __mutex);
@@ -224,8 +238,12 @@
  * Note that pthread_mutex_clocklock() allows specifying an arbitrary clock and has superseded this
  * function.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int pthread_mutex_timedlock_monotonic_np(pthread_mutex_t* _Nonnull __mutex, const struct timespec* _Nullable __timeout)
     __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 int pthread_mutex_trylock(pthread_mutex_t* _Nonnull __mutex);
 int pthread_mutex_unlock(pthread_mutex_t* _Nonnull __mutex);
 
@@ -235,60 +253,121 @@
 int pthread_rwlockattr_destroy(pthread_rwlockattr_t* _Nonnull __attr);
 int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t* _Nonnull __attr, int* _Nonnull __shared);
 int pthread_rwlockattr_setpshared(pthread_rwlockattr_t* _Nonnull __attr, int __shared);
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t* _Nonnull __attr, int* _Nonnull __kind)
   __INTRODUCED_IN(23);
 int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t* _Nonnull __attr, int __kind) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
 
+
+
+#if __BIONIC_AVAILABILITY_GUARD(30)
 int pthread_rwlock_clockrdlock(pthread_rwlock_t* _Nonnull __rwlock, clockid_t __clock,
                                const struct timespec* _Nullable __timeout) __INTRODUCED_IN(30);
 int pthread_rwlock_clockwrlock(pthread_rwlock_t* _Nonnull __rwlock, clockid_t __clock,
                                const struct timespec* _Nullable __timeout) __INTRODUCED_IN(30);
+#endif /* __BIONIC_AVAILABILITY_GUARD(30) */
+
 int pthread_rwlock_destroy(pthread_rwlock_t* _Nonnull __rwlock);
 int pthread_rwlock_init(pthread_rwlock_t* _Nonnull __rwlock, const pthread_rwlockattr_t* _Nullable __attr);
 int pthread_rwlock_rdlock(pthread_rwlock_t* _Nonnull __rwlock);
 int pthread_rwlock_timedrdlock(pthread_rwlock_t* _Nonnull __rwlock, const struct timespec* _Nullable __timeout);
 /* See the comment on pthread_mutex_timedlock_monotonic_np for usage of this function. */
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int pthread_rwlock_timedrdlock_monotonic_np(pthread_rwlock_t* _Nonnull __rwlock,
                                             const struct timespec* _Nullable __timeout) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 int pthread_rwlock_timedwrlock(pthread_rwlock_t* _Nonnull __rwlock, const struct timespec* _Nullable __timeout);
 /* See the comment on pthread_mutex_timedlock_monotonic_np for usage of this function. */
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int pthread_rwlock_timedwrlock_monotonic_np(pthread_rwlock_t* _Nonnull __rwlock,
                                             const struct timespec* _Nullable __timeout) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 int pthread_rwlock_tryrdlock(pthread_rwlock_t* _Nonnull __rwlock);
 int pthread_rwlock_trywrlock(pthread_rwlock_t* _Nonnull __rwlock);
 int pthread_rwlock_unlock(pthread_rwlock_t* _Nonnull __rwlock);
 int pthread_rwlock_wrlock(pthread_rwlock_t* _Nonnull __rwlock);
 
-#if __ANDROID_API__ >= 24
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 int pthread_barrierattr_init(pthread_barrierattr_t* _Nonnull __attr) __INTRODUCED_IN(24);
 int pthread_barrierattr_destroy(pthread_barrierattr_t* _Nonnull __attr) __INTRODUCED_IN(24);
 int pthread_barrierattr_getpshared(const pthread_barrierattr_t* _Nonnull __attr, int* _Nonnull __shared) __INTRODUCED_IN(24);
 int pthread_barrierattr_setpshared(pthread_barrierattr_t* _Nonnull __attr, int __shared) __INTRODUCED_IN(24);
-#endif
 
-#if __ANDROID_API__ >= 24
 int pthread_barrier_init(pthread_barrier_t* _Nonnull __barrier, const pthread_barrierattr_t* _Nullable __attr, unsigned __count) __INTRODUCED_IN(24);
 int pthread_barrier_destroy(pthread_barrier_t* _Nonnull __barrier) __INTRODUCED_IN(24);
 int pthread_barrier_wait(pthread_barrier_t* _Nonnull __barrier) __INTRODUCED_IN(24);
-#endif
 
-#if __ANDROID_API__ >= 24
 int pthread_spin_destroy(pthread_spinlock_t* _Nonnull __spinlock) __INTRODUCED_IN(24);
 int pthread_spin_init(pthread_spinlock_t* _Nonnull __spinlock, int __shared) __INTRODUCED_IN(24);
 int pthread_spin_lock(pthread_spinlock_t* _Nonnull __spinlock) __INTRODUCED_IN(24);
 int pthread_spin_trylock(pthread_spinlock_t* _Nonnull __spinlock) __INTRODUCED_IN(24);
 int pthread_spin_unlock(pthread_spinlock_t* _Nonnull __spinlock) __INTRODUCED_IN(24);
-#endif
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 
 pthread_t pthread_self(void) __attribute_const__;
 
-#if defined(__USE_GNU)
+#if defined(__USE_GNU) && __BIONIC_AVAILABILITY_GUARD(26)
+/**
+ * [pthread_getname_np(3)](https://man7.org/linux/man-pages/man3/pthread_getname_np.3.html)
+ * gets the name of the given thread.
+ * Names are at most 16 bytes (including '\0').
+ *
+ * Returns 0 on success and returns an error number on failure.
+ *
+ * Available since API level 26.
+ */
 int pthread_getname_np(pthread_t __pthread, char* _Nonnull __buf, size_t __n) __INTRODUCED_IN(26);
 #endif
-/* TODO: this should be __USE_GNU too. */
+
+/**
+ * [pthread_setname_np(3)](https://man7.org/linux/man-pages/man3/pthread_setname_np.3.html)
+ * sets the name of the given thread.
+ * Names are at most 16 bytes (including '\0').
+ * Truncation must be done by the caller;
+ * calls with longer names will fail with ERANGE.
+ *
+ * Returns 0 on success and returns an error number on failure.
+ *
+ * This should only have been available under _GNU_SOURCE,
+ * but is always available on Android by historical accident.
+ */
 int pthread_setname_np(pthread_t __pthread, const char* _Nonnull __name);
 
 /**
+ * [pthread_getaffinity_np(3)](https://man7.org/linux/man-pages/man3/pthread_getaffinity_np.3.html)
+ * gets the CPU affinity mask for the given thread.
+ *
+ * Returns 0 on success and returns an error number on failure.
+ *
+ * Available since API level 36.
+ * See sched_getaffinity() and pthread_gettid_np() for greater portability.
+ */
+#if defined(__USE_GNU) && __BIONIC_AVAILABILITY_GUARD(36)
+int pthread_getaffinity_np(pthread_t __pthread, size_t __cpu_set_size, cpu_set_t* __cpu_set) __INTRODUCED_IN(36);
+#endif
+
+/**
+ * [pthread_setaffinity_np(3)](https://man7.org/linux/man-pages/man3/pthread_setaffinity_np.3.html)
+ * sets the CPU affinity mask for the given thread.
+ *
+ * Returns 0 on success and returns an error number on failure.
+ *
+ * Available since API level 36.
+ * See sched_getaffinity() and pthread_gettid_np() for greater portability.
+ */
+#if defined(__USE_GNU) && __BIONIC_AVAILABILITY_GUARD(36)
+int pthread_setaffinity_np(pthread_t __pthread, size_t __cpu_set_size, const cpu_set_t* __cpu_set) __INTRODUCED_IN(36);
+#endif
+
+/**
  * [pthread_setschedparam(3)](https://man7.org/linux/man-pages/man3/pthread_setschedparam.3.html)
  * sets the scheduler policy and parameters of the given thread.
  *
@@ -322,7 +401,11 @@
  *
  * Available since API level 28.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int pthread_setschedprio(pthread_t __pthread, int __priority) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 int pthread_setspecific(pthread_key_t __key, const void* _Nullable __value);
 
diff --git a/libc/include/pty.h b/libc/include/pty.h
index be447d6..92d7fbb 100644
--- a/libc/include/pty.h
+++ b/libc/include/pty.h
@@ -41,7 +41,7 @@
 __BEGIN_DECLS
 
 /**
- * [openpty(3)](http://man7.org/linux/man-pages/man3/openpty.3.html) finds
+ * [openpty(3)](https://man7.org/linux/man-pages/man3/openpty.3.html) finds
  * a free pseudoterminal and configures it with the given terminal and window
  * size settings.
  *
@@ -49,10 +49,12 @@
  *
  * Available since API level 23.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int openpty(int* _Nonnull __pty_fd, int* _Nonnull __tty_fd, char* _Nullable __tty_name, const struct termios* _Nullable __termios_ptr, const struct winsize* _Nullable __winsize_ptr) __INTRODUCED_IN(23);
 
 /**
- * [forkpty(3)](http://man7.org/linux/man-pages/man3/forkpty.3.html) creates
+ * [forkpty(3)](https://man7.org/linux/man-pages/man3/forkpty.3.html) creates
  * a new process connected to a pseudoterminal from openpty().
  *
  * Returns 0 in the child/the pid of the child in the parent on success,
@@ -61,5 +63,7 @@
  * Available since API level 23.
  */
 int forkpty(int* _Nonnull __parent_pty_fd, char* _Nullable __child_tty_name, const struct termios* _Nullable __termios_ptr, const struct winsize* _Nullable __winsize_ptr) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 __END_DECLS
diff --git a/libc/include/pwd.h b/libc/include/pwd.h
index 2b17fbf..09592bc 100644
--- a/libc/include/pwd.h
+++ b/libc/include/pwd.h
@@ -84,10 +84,14 @@
 struct passwd* _Nullable getpwuid(uid_t __uid);
 
 /* Note: Android has thousands and thousands of ids to iterate through */
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 struct passwd* _Nullable getpwent(void) __INTRODUCED_IN(26);
 
 void setpwent(void) __INTRODUCED_IN(26);
 void endpwent(void) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 int getpwnam_r(const char* _Nonnull __name, struct passwd* _Nonnull __pwd, char* _Nonnull __buf, size_t __n, struct passwd* _Nullable * _Nonnull __result);
 int getpwuid_r(uid_t __uid, struct passwd* _Nonnull __pwd, char* _Nonnull __buf, size_t __n, struct passwd* _Nullable * _Nonnull __result);
diff --git a/libc/include/resolv.h b/libc/include/resolv.h
index f25484a..c49cefc 100644
--- a/libc/include/resolv.h
+++ b/libc/include/resolv.h
@@ -29,9 +29,10 @@
 #ifndef _RESOLV_H_
 #define _RESOLV_H_
 
+#include <sys/cdefs.h>
+
 #include <sys/param.h>
 #include <sys/types.h>
-#include <sys/cdefs.h>
 #include <sys/socket.h>
 #include <stdio.h>
 #include <arpa/nameser.h>
@@ -60,7 +61,11 @@
 int res_search(const char* _Nonnull __name, int __class, int __type, u_char* _Nonnull __answer, int __answer_size);
 
 #define res_randomid __res_randomid
+
+#if __BIONIC_AVAILABILITY_GUARD(29)
 u_int __res_randomid(void) __INTRODUCED_IN(29);
+#endif /* __BIONIC_AVAILABILITY_GUARD(29) */
+
 
 __END_DECLS
 
diff --git a/libc/include/sched.h b/libc/include/sched.h
index 9f043b6..7a2dcad 100644
--- a/libc/include/sched.h
+++ b/libc/include/sched.h
@@ -33,9 +33,10 @@
  * @brief Thread execution scheduling.
  */
 
+#include <sys/cdefs.h>
+
 #include <bits/timespec.h>
 #include <linux/sched.h>
-#include <sys/cdefs.h>
 
 __BEGIN_DECLS
 
@@ -45,42 +46,42 @@
  *
  * (Linux's name for POSIX's SCHED_OTHER.)
  *
- * See [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html)
+ * See [sched(7)](https://man7.org/linux/man-pages/man7/sched.7.html)
  */
 
 /*
  * @def SCHED_FIFO
  * The real-time first-in/first-out scheduling policy.
  *
- * See [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html)
+ * See [sched(7)](https://man7.org/linux/man-pages/man7/sched.7.html)
  */
 
 /*
  * @def SCHED_RR
  * The real-time round-robin policy. (See also SCHED_NORMAL/SCHED_OTHER.)
  *
- * See [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html)
+ * See [sched(7)](https://man7.org/linux/man-pages/man7/sched.7.html)
  */
 
 /*
  * @def SCHED_BATCH
  * The batch scheduling policy.
  *
- * See [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html)
+ * See [sched(7)](https://man7.org/linux/man-pages/man7/sched.7.html)
  */
 
 /*
  * @def SCHED_IDLE
  * The low priority "only when otherwise idle" scheduling priority.
  *
- * See [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html)
+ * See [sched(7)](https://man7.org/linux/man-pages/man7/sched.7.html)
  */
 
 /*
  * @def SCHED_DEADLINE
  * The deadline scheduling policy.
  *
- * See [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html)
+ * See [sched(7)](https://man7.org/linux/man-pages/man7/sched.7.html)
  */
 
 /*
@@ -116,7 +117,7 @@
 int sched_getscheduler(pid_t __pid);
 
 /**
- * [sched_yield(2)](http://man7.org/linux/man-pages/man2/sched_yield.2.html)
+ * [sched_yield(2)](https://man7.org/linux/man-pages/man2/sched_yield.2.html)
  * voluntarily gives up using the CPU so that another thread can run.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
@@ -124,7 +125,7 @@
 int sched_yield(void);
 
 /**
- * [sched_get_priority_max(2)](http://man7.org/linux/man-pages/man2/sched_get_priority_max.2.html)
+ * [sched_get_priority_max(2)](https://man7.org/linux/man-pages/man2/sched_get_priority_max.2.html)
  * gets the maximum priority value allowed for the given scheduling policy.
  *
  * Returns a priority on success and returns -1 and sets `errno` on failure.
@@ -132,7 +133,7 @@
 int sched_get_priority_max(int __policy);
 
 /**
- * [sched_get_priority_min(2)](http://man7.org/linux/man-pages/man2/sched_get_priority_min.2.html)
+ * [sched_get_priority_min(2)](https://man7.org/linux/man-pages/man2/sched_get_priority_min.2.html)
  * gets the minimum priority value allowed for the given scheduling policy.
  *
  * Returns a priority on success and returns -1 and sets `errno` on failure.
@@ -140,7 +141,7 @@
 int sched_get_priority_min(int __policy);
 
 /**
- * [sched_setparam(2)](http://man7.org/linux/man-pages/man2/sched_setparam.2.html)
+ * [sched_setparam(2)](https://man7.org/linux/man-pages/man2/sched_setparam.2.html)
  * sets the scheduling parameters for the given thread.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
@@ -148,7 +149,7 @@
 int sched_setparam(pid_t __pid, const struct sched_param* _Nonnull __param);
 
 /**
- * [sched_getparam(2)](http://man7.org/linux/man-pages/man2/sched_getparam.2.html)
+ * [sched_getparam(2)](https://man7.org/linux/man-pages/man2/sched_getparam.2.html)
  * gets the scheduling parameters for the given thread.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
@@ -156,7 +157,7 @@
 int sched_getparam(pid_t __pid, struct sched_param* _Nonnull __param);
 
 /**
- * [sched_rr_get_interval(2)](http://man7.org/linux/man-pages/man2/sched_rr_get_interval.2.html)
+ * [sched_rr_get_interval(2)](https://man7.org/linux/man-pages/man2/sched_rr_get_interval.2.html)
  * queries the round-robin time quantum for the given thread.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
@@ -166,7 +167,7 @@
 #if defined(__USE_GNU)
 
 /**
- * [clone(2)](http://man7.org/linux/man-pages/man2/clone.2.html)
+ * [clone(2)](https://man7.org/linux/man-pages/man2/clone.2.html)
  * creates a new child process.
  *
  * Returns the pid of the child to the caller on success and
@@ -175,7 +176,7 @@
 int clone(int (* __BIONIC_COMPLICATED_NULLNESS __fn)(void* __BIONIC_COMPLICATED_NULLNESS ), void* __BIONIC_COMPLICATED_NULLNESS __child_stack, int __flags, void* _Nullable __arg, ...);
 
 /**
- * [unshare(2)](http://man7.org/linux/man-pages/man2/unshare.2.html)
+ * [unshare(2)](https://man7.org/linux/man-pages/man2/unshare.2.html)
  * disassociates part of the caller's execution context.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
@@ -183,7 +184,7 @@
 int unshare(int __flags);
 
 /**
- * [setns(2)](http://man7.org/linux/man-pages/man2/setns.2.html)
+ * [setns(2)](https://man7.org/linux/man-pages/man2/setns.2.html)
  * reassociates a thread with a different namespace.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
@@ -191,7 +192,7 @@
 int setns(int __fd, int __ns_type);
 
 /**
- * [sched_getcpu(3)](http://man7.org/linux/man-pages/man3/sched_getcpu.3.html)
+ * [sched_getcpu(3)](https://man7.org/linux/man-pages/man3/sched_getcpu.3.html)
  * reports which CPU the caller is running on.
  *
  * Returns a non-negative CPU number on success and returns -1 and sets
@@ -219,7 +220,7 @@
 } cpu_set_t;
 
 /**
- * [sched_setaffinity(2)](http://man7.org/linux/man-pages/man2/sched_setaffinity.2.html)
+ * [sched_setaffinity(2)](https://man7.org/linux/man-pages/man2/sched_setaffinity.2.html)
  * sets the CPU affinity mask for the given thread.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
@@ -227,7 +228,7 @@
 int sched_setaffinity(pid_t __pid, size_t __set_size, const cpu_set_t* _Nonnull __set);
 
 /**
- * [sched_getaffinity(2)](http://man7.org/linux/man-pages/man2/sched_getaffinity.2.html)
+ * [sched_getaffinity(2)](https://man7.org/linux/man-pages/man2/sched_getaffinity.2.html)
  * gets the CPU affinity mask for the given thread.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
diff --git a/libc/include/search.h b/libc/include/search.h
index fe897d1..2f43d91 100644
--- a/libc/include/search.h
+++ b/libc/include/search.h
@@ -64,19 +64,19 @@
 __BEGIN_DECLS
 
 /**
- * [insque(3)](http://man7.org/linux/man-pages/man3/insque.3.html) inserts
+ * [insque(3)](https://man7.org/linux/man-pages/man3/insque.3.html) inserts
  * an item in a queue (an intrusive doubly-linked list).
  */
 void insque(void* _Nonnull __element, void* _Nullable __previous);
 
 /**
- * [remque(3)](http://man7.org/linux/man-pages/man3/remque.3.html) removes
+ * [remque(3)](https://man7.org/linux/man-pages/man3/remque.3.html) removes
  * an item from a queue (an intrusive doubly-linked list).
  */
 void remque(void* _Nonnull __element);
 
 /**
- * [hcreate(3)](http://man7.org/linux/man-pages/man3/hcreate.3.html)
+ * [hcreate(3)](https://man7.org/linux/man-pages/man3/hcreate.3.html)
  * initializes the global hash table, with space for at least `__n` elements.
  *
  * See hcreate_r() if you need more than one hash table.
@@ -85,10 +85,12 @@
  *
  * Available since API level 28.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int hcreate(size_t __n) __INTRODUCED_IN(28);
 
 /**
- * [hdestroy(3)](http://man7.org/linux/man-pages/man3/hdestroy.3.html) destroys
+ * [hdestroy(3)](https://man7.org/linux/man-pages/man3/hdestroy.3.html) destroys
  * the global hash table.
  *
  * See hdestroy_r() if you need more than one hash table.
@@ -98,7 +100,7 @@
 void hdestroy(void) __INTRODUCED_IN(28);
 
 /**
- * [hsearch(3)](http://man7.org/linux/man-pages/man3/hsearch.3.html) finds or
+ * [hsearch(3)](https://man7.org/linux/man-pages/man3/hsearch.3.html) finds or
  * inserts `__entry` in the global hash table, based on `__action`.
  *
  * See hsearch_r() if you need more than one hash table.
@@ -109,21 +111,25 @@
  * Available since API level 28.
  */
 ENTRY* _Nullable hsearch(ENTRY __entry, ACTION __action) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 #if defined(__USE_BSD) || defined(__USE_GNU)
 
 /**
- * [hcreate_r(3)](http://man7.org/linux/man-pages/man3/hcreate_r.3.html)
+ * [hcreate_r(3)](https://man7.org/linux/man-pages/man3/hcreate_r.3.html)
  * initializes a hash table `__table` with space for at least `__n` elements.
  *
  * Returns *non-zero* on success and returns 0 and sets `errno` on failure.
  *
  * Available since API level 28.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int hcreate_r(size_t __n, struct hsearch_data* _Nonnull __table) __INTRODUCED_IN(28);
 
 /**
- * [hdestroy_r(3)](http://man7.org/linux/man-pages/man3/hdestroy_r.3.html) destroys
+ * [hdestroy_r(3)](https://man7.org/linux/man-pages/man3/hdestroy_r.3.html) destroys
  * the hash table `__table`.
  *
  * Available since API level 28.
@@ -131,7 +137,7 @@
 void hdestroy_r(struct hsearch_data* _Nonnull __table) __INTRODUCED_IN(28);
 
 /**
- * [hsearch_r(3)](http://man7.org/linux/man-pages/man3/hsearch_r.3.html) finds or
+ * [hsearch_r(3)](https://man7.org/linux/man-pages/man3/hsearch_r.3.html) finds or
  * inserts `__entry` in the hash table `__table`, based on `__action`.
  *
  * Returns *non-zero* on success and returns 0 and sets `errno` on failure.
@@ -140,11 +146,13 @@
  * Available since API level 28.
  */
 int hsearch_r(ENTRY __entry, ACTION __action, ENTRY* _Nullable * _Nonnull __result, struct hsearch_data* _Nonnull __table) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 #endif
 
 /**
- * [lfind(3)](http://man7.org/linux/man-pages/man3/lfind.3.html) brute-force
+ * [lfind(3)](https://man7.org/linux/man-pages/man3/lfind.3.html) brute-force
  * searches the unsorted array `__array` (of `__count` items each of size `__size`)
  * for `__key`, using `__comparator`.
  *
@@ -155,7 +163,7 @@
 void* _Nullable lfind(const void* _Nonnull __key, const void* _Nonnull __array, size_t* _Nonnull __count, size_t __size, int (* _Nonnull __comparator)(const void* _Nonnull, const void* _Nonnull));
 
 /**
- * [lsearch(3)](http://man7.org/linux/man-pages/man3/lsearch.3.html) brute-force
+ * [lsearch(3)](https://man7.org/linux/man-pages/man3/lsearch.3.html) brute-force
  * searches the unsorted array `__array` (of `__count` items each of size `__size`)
  * for `__key`, using `__comparator`.
  *
@@ -168,7 +176,7 @@
 void* _Nonnull lsearch(const void* _Nonnull __key, void* _Nonnull __array, size_t* _Nonnull __count, size_t __size, int (* _Nonnull __comparator)(const void* _Nonnull, const void* _Nonnull));
 
 /**
- * [tdelete(3)](http://man7.org/linux/man-pages/man3/tdelete.3.html) searches
+ * [tdelete(3)](https://man7.org/linux/man-pages/man3/tdelete.3.html) searches
  * for and removes an element in the tree `*__root_ptr`. The search is performed
  * using `__comparator`.
  *
@@ -177,13 +185,13 @@
 void* _Nullable tdelete(const void* _Nonnull __key, void* _Nullable * _Nullable __root_ptr, int (* _Nonnull __comparator)(const void* _Nonnull, const void* _Nonnull));
 
 /**
- * [tdestroy(3)](http://man7.org/linux/man-pages/man3/tdestroy.3.html) destroys
+ * [tdestroy(3)](https://man7.org/linux/man-pages/man3/tdestroy.3.html) destroys
  * the hash table `__root` using `__free_fn` on each node.
  */
 void tdestroy(void* _Nullable __root, void (* _Nullable __free_fn)(void* _Nullable));
 
 /**
- * [tfind(3)](http://man7.org/linux/man-pages/man3/tfind.3.html) searches
+ * [tfind(3)](https://man7.org/linux/man-pages/man3/tfind.3.html) searches
  * for an element in the tree `*__root_ptr`. The search is performed using
  * `__comparator`.
  *
@@ -192,7 +200,7 @@
 void* _Nullable tfind(const void* _Nonnull __key, void* _Nullable const* _Nullable __root_ptr, int (* _Nonnull __comparator)(const void* _Nonnull, const void* _Nonnull));
 
 /**
- * [tsearch(3)](http://man7.org/linux/man-pages/man3/tsearch.3.html) searches
+ * [tsearch(3)](https://man7.org/linux/man-pages/man3/tsearch.3.html) searches
  * for an element in the tree `*__root_ptr`. The search is performed using
  * `__comparator`.
  *
@@ -203,7 +211,7 @@
 void* _Nullable tsearch(const void* _Nonnull __key, void* _Nullable * _Nullable __root_ptr, int (* _Nonnull __comparator)(const void* _Nonnull, const void* _Nonnull));
 
 /**
- * [twalk(3)](http://man7.org/linux/man-pages/man3/twalk.3.html) calls
+ * [twalk(3)](https://man7.org/linux/man-pages/man3/twalk.3.html) calls
  * `__visitor` on every node in the tree.
  */
 void twalk(const void* _Nullable __root, void (* _Nullable __visitor)(const void* _Nullable, VISIT, int));
diff --git a/libc/include/semaphore.h b/libc/include/semaphore.h
index 6ad9ea3..9c4702d 100644
--- a/libc/include/semaphore.h
+++ b/libc/include/semaphore.h
@@ -45,7 +45,11 @@
 
 #define SEM_FAILED __BIONIC_CAST(reinterpret_cast, sem_t*, 0)
 
+
+#if __BIONIC_AVAILABILITY_GUARD(30)
 int sem_clockwait(sem_t* _Nonnull __sem, clockid_t __clock, const struct timespec* _Nonnull __ts) __INTRODUCED_IN(30);
+#endif /* __BIONIC_AVAILABILITY_GUARD(30) */
+
 int sem_destroy(sem_t* _Nonnull __sem);
 int sem_getvalue(sem_t* _Nonnull __sem, int* _Nonnull __value);
 int sem_init(sem_t* _Nonnull __sem, int __shared, unsigned int __value);
@@ -59,7 +63,11 @@
  * Note that sem_clockwait() allows specifying an arbitrary clock and has superseded this
  * function.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int sem_timedwait_monotonic_np(sem_t* _Nonnull __sem, const struct timespec* _Nonnull __ts) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 int sem_trywait(sem_t* _Nonnull __sem);
 int sem_wait(sem_t* _Nonnull __sem);
 
diff --git a/libc/include/setjmp.h b/libc/include/setjmp.h
index 0aaaac5..6c141cb 100644
--- a/libc/include/setjmp.h
+++ b/libc/include/setjmp.h
@@ -111,7 +111,7 @@
 __noreturn void longjmp(jmp_buf __env, int __value);
 
 /**
- * [sigsetjmp(3)](http://man7.org/linux/man-pages/man3/sigsetjmp.3.html)
+ * [sigsetjmp(3)](https://man7.org/linux/man-pages/man3/sigsetjmp.3.html)
  * sets the target of a future siglongjmp() call, saving or not saving the
  * current signal mask based on the second argument.
  *
@@ -121,7 +121,7 @@
 int sigsetjmp(sigjmp_buf __env, int __save_signal_mask) __returns_twice;
 
 /**
- * [siglongjmp(3)](http://man7.org/linux/man-pages/man3/siglongjmp.3.html)
+ * [siglongjmp(3)](https://man7.org/linux/man-pages/man3/siglongjmp.3.html)
  * transfers control back to the site of the sigsetjmp() call that initialized
  * the given jump buffer, returning the given value.
  *
diff --git a/libc/include/signal.h b/libc/include/signal.h
index 9d47bcc..38dcbde 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -60,31 +60,73 @@
 #define si_timerid si_tid /* glibc compatibility. */
 
 int sigaction(int __signal, const struct sigaction* _Nullable __new_action, struct sigaction* _Nullable __old_action);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int sigaction64(int __signal, const struct sigaction64* _Nullable __new_action, struct sigaction64* _Nullable __old_action) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 int siginterrupt(int __signal, int __flag);
 
 sighandler_t _Nonnull signal(int __signal, sighandler_t _Nullable __handler);
 int sigaddset(sigset_t* _Nonnull __set, int __signal);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int sigaddset64(sigset64_t* _Nonnull __set, int __signal) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 int sigdelset(sigset_t* _Nonnull __set, int __signal);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int sigdelset64(sigset64_t* _Nonnull __set, int __signal) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 int sigemptyset(sigset_t* _Nonnull __set);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int sigemptyset64(sigset64_t* _Nonnull __set) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 int sigfillset(sigset_t* _Nonnull __set);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int sigfillset64(sigset64_t* _Nonnull __set) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 int sigismember(const sigset_t* _Nonnull __set, int __signal);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int sigismember64(const sigset64_t* _Nonnull __set, int __signal) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 int sigpending(sigset_t* _Nonnull __set);
-int sigpending64(sigset64_t* _Nonnull __set) __INTRODUCED_IN(28);
-int sigprocmask(int __how, const sigset_t* _Nullable __new_set, sigset_t* _Nullable __old_set);
-int sigprocmask64(int __how, const sigset64_t* _Nullable __new_set, sigset64_t* _Nullable __old_set) __INTRODUCED_IN(28);
-int sigsuspend(const sigset_t* _Nonnull __mask);
-int sigsuspend64(const sigset64_t* _Nonnull __mask) __INTRODUCED_IN(28);
-int sigwait(const sigset_t* _Nonnull __set, int* _Nonnull __signal);
-int sigwait64(const sigset64_t* _Nonnull __set, int* _Nonnull __signal) __INTRODUCED_IN(28);
 
+#if __BIONIC_AVAILABILITY_GUARD(28)
+int sigpending64(sigset64_t* _Nonnull __set) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
+int sigprocmask(int __how, const sigset_t* _Nullable __new_set, sigset_t* _Nullable __old_set);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
+int sigprocmask64(int __how, const sigset64_t* _Nullable __new_set, sigset64_t* _Nullable __old_set) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
+int sigsuspend(const sigset_t* _Nonnull __mask);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
+int sigsuspend64(const sigset64_t* _Nonnull __mask) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
+int sigwait(const sigset_t* _Nonnull __set, int* _Nonnull __signal);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
+int sigwait64(const sigset64_t* _Nonnull __set, int* _Nonnull __signal) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
+
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 int sighold(int __signal)
   __attribute__((__deprecated__("use sigprocmask() or pthread_sigmask() instead")))
   __INTRODUCED_IN(26);
@@ -97,6 +139,8 @@
   __INTRODUCED_IN(26);
 sighandler_t _Nonnull sigset(int __signal, sighandler_t _Nullable __handler)
   __attribute__((__deprecated__("use sigaction() instead"))) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 int raise(int __signal);
 int kill(pid_t __pid, int __signal);
@@ -110,17 +154,73 @@
 
 int pthread_kill(pthread_t __pthread, int __signal);
 #if defined(__USE_GNU)
+
+#if __BIONIC_AVAILABILITY_GUARD(29)
 int pthread_sigqueue(pthread_t __pthread, int __signal, const union sigval __value) __INTRODUCED_IN(29);
+#endif /* __BIONIC_AVAILABILITY_GUARD(29) */
+
 #endif
 
 int pthread_sigmask(int __how, const sigset_t* _Nullable __new_set, sigset_t* _Nullable __old_set);
-int pthread_sigmask64(int __how, const sigset64_t* _Nullable __new_set, sigset64_t* _Nullable __old_set) __INTRODUCED_IN(28);
 
+#if __BIONIC_AVAILABILITY_GUARD(28)
+int pthread_sigmask64(int __how, const sigset64_t* _Nullable __new_set, sigset64_t* _Nullable __old_set) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
+
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int sigqueue(pid_t __pid, int __signal, const union sigval __value) __INTRODUCED_IN(23);
 int sigtimedwait(const sigset_t* _Nonnull __set, siginfo_t* _Nullable __info, const struct timespec* _Nullable __timeout) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int sigtimedwait64(const sigset64_t* _Nonnull __set, siginfo_t* _Nullable __info, const struct timespec* _Nullable __timeout) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int sigwaitinfo(const sigset_t* _Nonnull __set, siginfo_t* _Nullable __info) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int sigwaitinfo64(const sigset64_t* _Nonnull __set, siginfo_t* _Nullable __info) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
+
+/**
+ * Buffer size suitable for any call to sig2str().
+ */
+#define SIG2STR_MAX 32
+
+/**
+ * [sig2str(3)](https://man7.org/linux/man-pages/man3/sig2str.3.html)
+ * converts the integer corresponding to SIGSEGV (say) into a string
+ * like "SEGV" (not including the "SIG" used in the constants).
+ * SIG2STR_MAX is a safe size to use for the buffer.
+ *
+ * Returns 0 on success, and returns -1 _without_ setting errno otherwise.
+ *
+ * Available since API level 36.
+ */
+
+#if __BIONIC_AVAILABILITY_GUARD(36)
+int sig2str(int __signal, char* _Nonnull __buf) __INTRODUCED_IN(36);
+
+/**
+ * [str2sig(3)](https://man7.org/linux/man-pages/man3/str2sig.3.html)
+ * converts a string like "SEGV" (not including the "SIG" used in the constants)
+ * into the integer corresponding to SIGSEGV.
+ *
+ * Returns 0 on success, and returns -1 _without_ setting errno otherwise.
+ *
+ * Available since API level 36.
+ */
+int str2sig(const char* _Nonnull __name, int* _Nonnull __signal) __INTRODUCED_IN(36);
+#endif /* __BIONIC_AVAILABILITY_GUARD(36) */
+
 
 __END_DECLS
 
diff --git a/libc/include/spawn.h b/libc/include/spawn.h
index 3ce402f..b105754 100644
--- a/libc/include/spawn.h
+++ b/libc/include/spawn.h
@@ -46,14 +46,19 @@
 #define POSIX_SPAWN_USEVFORK 64
 #define POSIX_SPAWN_SETSID 128
 #endif
-// mark all fds (except stdin/out/err) as close-on-exec prior to executing registered file actions
+/**
+ * Used with posix_spawnattr_setflags() to mark all fds except
+ * stdin/stdout/stderr as O_CLOEXEC prior to executing registered file actions.
+ */
 #define POSIX_SPAWN_CLOEXEC_DEFAULT 256
 
 typedef struct __posix_spawnattr* posix_spawnattr_t;
 typedef struct __posix_spawn_file_actions* posix_spawn_file_actions_t;
 
-int posix_spawn(pid_t* _Nullable __pid, const char* _Nonnull __path, const posix_spawn_file_actions_t _Nullable * _Nullable __actions, const posix_spawnattr_t _Nullable * _Nullable __attr, char* const _Nonnull __argv[_Nonnull], char* const _Nullable __env[_Nullable]) __INTRODUCED_IN(28);
-int posix_spawnp(pid_t* _Nullable __pid, const char* _Nonnull __file, const posix_spawn_file_actions_t _Nullable * _Nullable __actions, const posix_spawnattr_t _Nullable * _Nullable __attr, char* const _Nonnull __argv[_Nonnull], char* const _Nullable __env[_Nullable]) __INTRODUCED_IN(28);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
+int posix_spawn(pid_t* _Nullable __pid, const char* _Nonnull __path, const posix_spawn_file_actions_t _Nullable * _Nullable __actions, const posix_spawnattr_t _Nullable * _Nullable __attr, char* const _Nullable __argv[_Nullable], char* const _Nullable __env[_Nullable]) __INTRODUCED_IN(28);
+int posix_spawnp(pid_t* _Nullable __pid, const char* _Nonnull __file, const posix_spawn_file_actions_t _Nullable * _Nullable __actions, const posix_spawnattr_t _Nullable * _Nullable __attr, char* const _Nullable __argv[_Nullable], char* const _Nullable __env[_Nullable]) __INTRODUCED_IN(28);
 
 int posix_spawnattr_init(posix_spawnattr_t _Nullable * _Nonnull __attr) __INTRODUCED_IN(28);
 int posix_spawnattr_destroy(posix_spawnattr_t _Nonnull * _Nonnull __attr) __INTRODUCED_IN(28);
@@ -86,9 +91,15 @@
 int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t _Nonnull * _Nonnull __actions, int __fd, const char* _Nonnull __path, int __flags, mode_t __mode) __INTRODUCED_IN(28);
 int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t _Nonnull * _Nonnull __actions, int __fd) __INTRODUCED_IN(28);
 int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t _Nonnull * _Nonnull __actions, int __fd, int __new_fd) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
 
+
+
+#if __BIONIC_AVAILABILITY_GUARD(34)
 int posix_spawn_file_actions_addchdir_np(posix_spawn_file_actions_t _Nonnull * _Nonnull __actions, const char* _Nonnull __path) __INTRODUCED_IN(34);
 int posix_spawn_file_actions_addfchdir_np(posix_spawn_file_actions_t _Nonnull * _Nonnull __actions, int __fd) __INTRODUCED_IN(34);
+#endif /* __BIONIC_AVAILABILITY_GUARD(34) */
+
 
 __END_DECLS
 
diff --git a/libc/include/stdint.h b/libc/include/stdint.h
index 322a81c..772fe8b 100644
--- a/libc/include/stdint.h
+++ b/libc/include/stdint.h
@@ -29,9 +29,10 @@
 #ifndef _STDINT_H
 #define _STDINT_H
 
+#include <sys/cdefs.h>
+
 #include <bits/wchar_limits.h>
 #include <stddef.h>
-#include <sys/cdefs.h>
 
 typedef signed char __int8_t;
 typedef unsigned char __uint8_t;
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index 279c658..2c2dc01 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -105,10 +105,10 @@
 
 void clearerr(FILE* _Nonnull __fp);
 int fclose(FILE* _Nonnull __fp);
-__wur int feof(FILE* _Nonnull __fp);
-__wur int ferror(FILE* _Nonnull __fp);
+__nodiscard int feof(FILE* _Nonnull __fp);
+__nodiscard int ferror(FILE* _Nonnull __fp);
 int fflush(FILE* _Nullable __fp);
-__wur int fgetc(FILE* _Nonnull __fp);
+__nodiscard int fgetc(FILE* _Nonnull __fp);
 char* _Nullable fgets(char* _Nonnull __buf, int __size, FILE* _Nonnull __fp);
 int fprintf(FILE* _Nonnull __fp , const char* _Nonnull __fmt, ...) __printflike(2, 3);
 int fputc(int __ch, FILE* _Nonnull __fp);
@@ -116,8 +116,8 @@
 size_t fread(void* _Nonnull __buf, size_t __size, size_t __count, FILE* _Nonnull __fp);
 int fscanf(FILE* _Nonnull __fp, const char* _Nonnull __fmt, ...) __scanflike(2, 3);
 size_t fwrite(const void* _Nonnull __buf, size_t __size, size_t __count, FILE* _Nonnull __fp);
-__wur int getc(FILE* _Nonnull __fp);
-__wur int getchar(void);
+__nodiscard int getc(FILE* _Nonnull __fp);
+__nodiscard int getchar(void);
 ssize_t getdelim(char* _Nullable * _Nonnull __line_ptr, size_t* _Nonnull __line_length_ptr, int __delimiter, FILE* _Nonnull __fp);
 ssize_t getline(char* _Nullable * _Nonnull __line_ptr, size_t* _Nonnull __line_length_ptr, FILE* _Nonnull __fp);
 
@@ -154,7 +154,7 @@
     __warnattr("tempnam is unsafe, use mkstemp or tmpfile instead");
 
 /**
- * [rename(2)](http://man7.org/linux/man-pages/man2/rename.2.html) changes
+ * [rename(2)](https://man7.org/linux/man-pages/man2/rename.2.html) changes
  * the name or location of a file.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -162,7 +162,7 @@
 int rename(const char* _Nonnull __old_path, const char* _Nonnull __new_path);
 
 /**
- * [renameat(2)](http://man7.org/linux/man-pages/man2/renameat.2.html) changes
+ * [renameat(2)](https://man7.org/linux/man-pages/man2/renameat.2.html) changes
  * the name or location of a file, interpreting relative paths using an fd.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -172,84 +172,116 @@
 #if defined(__USE_GNU)
 
 /**
- * Flag for [renameat2(2)](http://man7.org/linux/man-pages/man2/renameat2.2.html)
+ * Flag for [renameat2(2)](https://man7.org/linux/man-pages/man2/renameat2.2.html)
  * to fail if the new path already exists.
  */
 #define RENAME_NOREPLACE (1<<0)
 
 /**
- * Flag for [renameat2(2)](http://man7.org/linux/man-pages/man2/renameat2.2.html)
+ * Flag for [renameat2(2)](https://man7.org/linux/man-pages/man2/renameat2.2.html)
  * to atomically exchange the two paths.
  */
 #define RENAME_EXCHANGE (1<<1)
 
 /**
- * Flag for [renameat2(2)](http://man7.org/linux/man-pages/man2/renameat2.2.html)
+ * Flag for [renameat2(2)](https://man7.org/linux/man-pages/man2/renameat2.2.html)
  * to create a union/overlay filesystem object.
  */
 #define RENAME_WHITEOUT (1<<2)
 
 /**
- * [renameat2(2)](http://man7.org/linux/man-pages/man2/renameat2.2.html) changes
+ * [renameat2(2)](https://man7.org/linux/man-pages/man2/renameat2.2.html) changes
  * the name or location of a file, interpreting relative paths using an fd,
  * with optional `RENAME_` flags.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(30)
 int renameat2(int __old_dir_fd, const char* _Nonnull __old_path, int __new_dir_fd, const char* _Nonnull __new_path, unsigned __flags) __INTRODUCED_IN(30);
+#endif /* __BIONIC_AVAILABILITY_GUARD(30) */
+
 
 #endif
 
 int fseek(FILE* _Nonnull __fp, long __offset, int __whence);
-__wur long ftell(FILE* _Nonnull __fp);
+__nodiscard long ftell(FILE* _Nonnull __fp);
 
 /* See https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md */
 #if defined(__USE_FILE_OFFSET64)
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 int fgetpos(FILE* _Nonnull __fp, fpos_t* _Nonnull __pos) __RENAME(fgetpos64) __INTRODUCED_IN(24);
 int fsetpos(FILE* _Nonnull __fp, const fpos_t* _Nonnull __pos) __RENAME(fsetpos64) __INTRODUCED_IN(24);
 int fseeko(FILE* _Nonnull __fp, off_t __offset, int __whence) __RENAME(fseeko64) __INTRODUCED_IN(24);
-__wur off_t ftello(FILE* _Nonnull __fp) __RENAME(ftello64) __INTRODUCED_IN(24);
+__nodiscard off_t ftello(FILE* _Nonnull __fp) __RENAME(ftello64) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 #  if defined(__USE_BSD)
 /* If __read_fn and __write_fn are both nullptr, it will cause EINVAL */
-__wur FILE* _Nullable funopen(const void* _Nullable __cookie,
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
+__nodiscard FILE* _Nullable funopen(const void* _Nullable __cookie,
               int (* __BIONIC_COMPLICATED_NULLNESS __read_fn)(void* _Nonnull, char* _Nonnull, int),
               int (* __BIONIC_COMPLICATED_NULLNESS __write_fn)(void* _Nonnull, const char* _Nonnull, int),
               fpos_t (* _Nullable __seek_fn)(void* _Nonnull, fpos_t, int),
               int (* _Nullable __close_fn)(void* _Nonnull)) __RENAME(funopen64) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 #  endif
 #else
 int fgetpos(FILE* _Nonnull __fp, fpos_t* _Nonnull __pos);
 int fsetpos(FILE* _Nonnull __fp, const fpos_t* _Nonnull __pos);
 int fseeko(FILE* _Nonnull __fp, off_t __offset, int __whence);
-__wur off_t ftello(FILE* _Nonnull __fp);
+__nodiscard off_t ftello(FILE* _Nonnull __fp);
 #  if defined(__USE_BSD)
 /* If __read_fn and __write_fn are both nullptr, it will cause EINVAL */
-__wur FILE* _Nullable funopen(const void* _Nullable __cookie,
+__nodiscard FILE* _Nullable funopen(const void* _Nullable __cookie,
               int (* __BIONIC_COMPLICATED_NULLNESS __read_fn)(void* _Nonnull, char* _Nonnull, int),
               int (* __BIONIC_COMPLICATED_NULLNESS __write_fn)(void* _Nonnull, const char* _Nonnull, int),
               fpos_t (* _Nullable __seek_fn)(void* _Nonnull, fpos_t, int),
               int (* _Nullable __close_fn)(void* _Nonnull));
 #  endif
 #endif
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 int fgetpos64(FILE* _Nonnull __fp, fpos64_t* _Nonnull __pos) __INTRODUCED_IN(24);
 int fsetpos64(FILE* _Nonnull __fp, const fpos64_t* _Nonnull __pos) __INTRODUCED_IN(24);
 int fseeko64(FILE* _Nonnull __fp, off64_t __offset, int __whence) __INTRODUCED_IN(24);
-__wur off64_t ftello64(FILE* _Nonnull __fp) __INTRODUCED_IN(24);
+__nodiscard off64_t ftello64(FILE* _Nonnull __fp) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 #if defined(__USE_BSD)
 /* If __read_fn and __write_fn are both nullptr, it will cause EINVAL */
-__wur FILE* _Nullable funopen64(const void* _Nullable __cookie,
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
+__nodiscard FILE* _Nullable funopen64(const void* _Nullable __cookie,
                 int (* __BIONIC_COMPLICATED_NULLNESS __read_fn)(void* _Nonnull, char* _Nonnull, int),
                 int (* __BIONIC_COMPLICATED_NULLNESS __write_fn)(void* _Nonnull, const char* _Nonnull, int),
                 fpos64_t (* _Nullable __seek_fn)(void* _Nonnull, fpos64_t, int),
                 int (* _Nullable __close_fn)(void* _Nonnull)) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 #endif
 
-__wur FILE* _Nullable fopen(const char* _Nonnull __path, const char* _Nonnull __mode);
-__wur FILE* _Nullable fopen64(const char* _Nonnull __path, const char* _Nonnull __mode) __INTRODUCED_IN(24);
+__nodiscard FILE* _Nullable fopen(const char* _Nonnull __path, const char* _Nonnull __mode);
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
+__nodiscard FILE* _Nullable fopen64(const char* _Nonnull __path, const char* _Nonnull __mode) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 FILE* _Nullable freopen(const char* _Nullable __path, const char* _Nonnull __mode, FILE* _Nonnull __fp);
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 FILE* _Nullable freopen64(const char* _Nullable __path, const char* _Nonnull __mode, FILE* _Nonnull __fp) __INTRODUCED_IN(24);
-__wur FILE* _Nullable tmpfile(void);
-__wur FILE* _Nullable tmpfile64(void) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
+__nodiscard FILE* _Nullable tmpfile(void);
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
+__nodiscard FILE* _Nullable tmpfile64(void) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 
 int snprintf(char* __BIONIC_COMPLICATED_NULLNESS __buf, size_t __size, const char* _Nonnull __fmt, ...) __printflike(3, 4);
 int vfscanf(FILE* _Nonnull __fp, const char* _Nonnull __fmt, va_list __args) __scanflike(2, 0);
@@ -258,22 +290,30 @@
 int vsscanf(const char* _Nonnull __s, const char* _Nonnull __fmt, va_list __args) __scanflike(2, 0);
 
 #define L_ctermid 1024 /* size for ctermid() */
-char* _Nonnull ctermid(char* _Nullable __buf) __INTRODUCED_IN(26);
 
-__wur FILE* _Nullable fdopen(int __fd, const char* _Nonnull __mode);
-__wur int fileno(FILE* _Nonnull __fp);
+#if __BIONIC_AVAILABILITY_GUARD(26)
+char* _Nonnull ctermid(char* _Nullable __buf) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
+
+__nodiscard FILE* _Nullable fdopen(int __fd, const char* _Nonnull __mode);
+__nodiscard int fileno(FILE* _Nonnull __fp);
 int pclose(FILE* _Nonnull __fp);
-__wur FILE* _Nullable popen(const char* _Nonnull __command, const char* _Nonnull __mode);
+__nodiscard FILE* _Nullable popen(const char* _Nonnull __command, const char* _Nonnull __mode);
 void flockfile(FILE* _Nonnull  __fp);
 int ftrylockfile(FILE* _Nonnull __fp);
 void funlockfile(FILE* _Nonnull __fp);
-__wur int getc_unlocked(FILE* _Nonnull __fp);
-__wur int getchar_unlocked(void);
+__nodiscard int getc_unlocked(FILE* _Nonnull __fp);
+__nodiscard int getchar_unlocked(void);
 int putc_unlocked(int __ch, FILE* _Nonnull __fp);
 int putchar_unlocked(int __ch);
 
-__wur FILE* _Nullable fmemopen(void* _Nullable __buf, size_t __size, const char* _Nonnull __mode) __INTRODUCED_IN(23);
-__wur FILE* _Nullable open_memstream(char* _Nonnull * _Nonnull __ptr, size_t* _Nonnull __size_ptr) __INTRODUCED_IN(23);
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
+__nodiscard FILE* _Nullable fmemopen(void* _Nullable __buf, size_t __size, const char* _Nonnull __mode) __INTRODUCED_IN(23);
+__nodiscard FILE* _Nullable open_memstream(char* _Nonnull * _Nonnull __ptr, size_t* _Nonnull __size_ptr) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 #if defined(__USE_BSD) || defined(__BIONIC__) /* Historically bionic exposed these. */
 int  asprintf(char* _Nullable * _Nonnull __s_ptr, const char* _Nonnull __fmt, ...) __printflike(2, 3);
@@ -282,25 +322,41 @@
 void setbuffer(FILE* _Nonnull __fp, char* _Nullable __buf, int __size);
 int setlinebuf(FILE* _Nonnull __fp);
 int vasprintf(char* _Nullable * _Nonnull __s_ptr, const char* _Nonnull __fmt, va_list __args) __printflike(2, 0);
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 void clearerr_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
-__wur int feof_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
-__wur int ferror_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
-__wur int fileno_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(24);
+__nodiscard int feof_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
+__nodiscard int ferror_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
+__nodiscard int fileno_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 #define fropen(cookie, fn) funopen(cookie, fn, 0, 0, 0)
 #define fwopen(cookie, fn) funopen(cookie, 0, fn, 0, 0)
 #endif
 
 #if defined(__USE_BSD)
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int fflush_unlocked(FILE* _Nullable __fp) __INTRODUCED_IN(28);
-__wur int fgetc_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(28);
+__nodiscard int fgetc_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(28);
 int fputc_unlocked(int __ch, FILE* _Nonnull __fp) __INTRODUCED_IN(28);
 size_t fread_unlocked(void* _Nonnull __buf, size_t __size, size_t __count, FILE* _Nonnull __fp) __INTRODUCED_IN(28);
 size_t fwrite_unlocked(const void* _Nonnull __buf, size_t __size, size_t __count, FILE* _Nonnull __fp) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 #endif
 
 #if defined(__USE_GNU)
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int fputs_unlocked(const char* _Nonnull __s, FILE* _Nonnull __fp) __INTRODUCED_IN(28);
 char* _Nullable fgets_unlocked(char* _Nonnull __buf, int __size, FILE* _Nonnull __fp) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 #endif
 
 #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
diff --git a/libc/include/stdio_ext.h b/libc/include/stdio_ext.h
index 8b106a6..9ff07da 100644
--- a/libc/include/stdio_ext.h
+++ b/libc/include/stdio_ext.h
@@ -39,68 +39,90 @@
 __BEGIN_DECLS
 
 /**
- * [__fbufsize(3)](http://man7.org/linux/man-pages/man3/__fbufsize.3.html) returns the size of
+ * [__fbufsize(3)](https://man7.org/linux/man-pages/man3/__fbufsize.3.html) returns the size of
  * the stream's buffer.
  *
  * Available since API level 23.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 size_t __fbufsize(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
 
 /**
- * [__freadable(3)](http://man7.org/linux/man-pages/man3/__freadable.3.html) returns non-zero if
+ * [__freadable(3)](https://man7.org/linux/man-pages/man3/__freadable.3.html) returns non-zero if
  * the stream allows reading, 0 otherwise.
  *
  * Available since API level 23.
  */
 int __freadable(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 /**
- * [__freading(3)](http://man7.org/linux/man-pages/man3/__freading.3.html) returns non-zero if
+ * [__freading(3)](https://man7.org/linux/man-pages/man3/__freading.3.html) returns non-zero if
  * the stream's last operation was a read, 0 otherwise.
  *
  * Available since API level 28.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int __freading(FILE* _Nonnull __fp) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 /**
- * [__fwritable(3)](http://man7.org/linux/man-pages/man3/__fwritable.3.html) returns non-zero if
+ * [__fwritable(3)](https://man7.org/linux/man-pages/man3/__fwritable.3.html) returns non-zero if
  * the stream allows writing, 0 otherwise.
  *
  * Available since API level 23.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int __fwritable(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 /**
- * [__fwriting(3)](http://man7.org/linux/man-pages/man3/__fwriting.3.html) returns non-zero if
+ * [__fwriting(3)](https://man7.org/linux/man-pages/man3/__fwriting.3.html) returns non-zero if
  * the stream's last operation was a write, 0 otherwise.
  *
  * Available since API level 28.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int __fwriting(FILE* _Nonnull __fp) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 /**
- * [__flbf(3)](http://man7.org/linux/man-pages/man3/__flbf.3.html) returns non-zero if
+ * [__flbf(3)](https://man7.org/linux/man-pages/man3/__flbf.3.html) returns non-zero if
  * the stream is line-buffered, 0 otherwise.
  *
  * Available since API level 23.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int __flbf(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 /**
- * [__fpurge(3)](http://man7.org/linux/man-pages/man3/__fpurge.3.html) discards the contents of
+ * [__fpurge(3)](https://man7.org/linux/man-pages/man3/__fpurge.3.html) discards the contents of
  * the stream's buffer.
- *
- * Available since API level 23.
  */
-void __fpurge(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
+void __fpurge(FILE* _Nonnull __fp) __RENAME(fpurge);
 
 /**
- * [__fpending(3)](http://man7.org/linux/man-pages/man3/__fpending.3.html) returns the number of
+ * [__fpending(3)](https://man7.org/linux/man-pages/man3/__fpending.3.html) returns the number of
  * bytes in the output buffer. See __freadahead() for the input buffer.
  *
  * Available since API level 23.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 size_t __fpending(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 /**
  * __freadahead(3) returns the number of bytes in the input buffer.
@@ -108,15 +130,23 @@
  *
  * Available since API level 34.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(34)
 size_t __freadahead(FILE* _Nonnull __fp) __INTRODUCED_IN(34);
+#endif /* __BIONIC_AVAILABILITY_GUARD(34) */
+
 
 /**
- * [_flushlbf(3)](http://man7.org/linux/man-pages/man3/_flushlbf.3.html) flushes all
+ * [_flushlbf(3)](https://man7.org/linux/man-pages/man3/_flushlbf.3.html) flushes all
  * line-buffered streams.
  *
  * Available since API level 23.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 void _flushlbf(void) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 /**
  * `__fseterr` sets the
@@ -124,7 +154,11 @@
  *
  * Available since API level 28.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 void __fseterr(FILE* _Nonnull __fp) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 /** __fsetlocking() constant to query locking type. */
 #define FSETLOCKING_QUERY 0
@@ -134,13 +168,17 @@
 #define FSETLOCKING_BYCALLER 2
 
 /**
- * [__fsetlocking(3)](http://man7.org/linux/man-pages/man3/__fsetlocking.3.html) sets the
+ * [__fsetlocking(3)](https://man7.org/linux/man-pages/man3/__fsetlocking.3.html) sets the
  * stream's locking mode to one of the `FSETLOCKING_` types.
  *
  * Returns the current locking style, `FSETLOCKING_INTERNAL` or `FSETLOCKING_BYCALLER`.
  *
  * Available since API level 23.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int __fsetlocking(FILE* _Nonnull __fp, int __type) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 __END_DECLS
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index d0efc4c..7081d7c 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -29,11 +29,12 @@
 #ifndef _STDLIB_H
 #define _STDLIB_H
 
+#include <sys/cdefs.h>
+
 #include <alloca.h>
 #include <bits/wait.h>
 #include <malloc.h>
 #include <stddef.h>
-#include <sys/cdefs.h>
 #include <xlocale.h>
 
 __BEGIN_DECLS
@@ -59,37 +60,44 @@
 char* _Nullable mkdtemp(char* _Nonnull __template);
 char* _Nullable mktemp(char* _Nonnull __template) __attribute__((__deprecated__("mktemp is unsafe, use mkstemp or tmpfile instead")));
 
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int mkostemp64(char* _Nonnull __template, int __flags) __INTRODUCED_IN(23);
 int mkostemp(char* _Nonnull __template, int __flags) __INTRODUCED_IN(23);
 int mkostemps64(char* _Nonnull __template, int __suffix_length, int __flags) __INTRODUCED_IN(23);
 int mkostemps(char* _Nonnull __template, int __suffix_length, int __flags) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 int mkstemp64(char* _Nonnull __template);
 int mkstemp(char* _Nonnull __template);
-int mkstemps64(char* _Nonnull __template, int __flags) __INTRODUCED_IN(23);
-int mkstemps(char* _Nonnull __template, int __flags);
 
-long strtol(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base);
-long long strtoll(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base);
-unsigned long strtoul(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base);
-unsigned long long strtoull(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base);
+#if __BIONIC_AVAILABILITY_GUARD(23)
+int mkstemps64(char* _Nonnull __template, int __flags) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+int mkstemps(char* _Nonnull __template, int __flags);
 
 int posix_memalign(void* _Nullable * _Nullable __memptr, size_t __alignment, size_t __size);
 
-void* _Nullable aligned_alloc(size_t __alignment, size_t __size) __INTRODUCED_IN(28);
+/**
+ * [aligned_alloc(3)](https://man7.org/linux/man-pages/man3/aligned_alloc.3.html)
+ * allocates the given number of bytes with the given alignment.
+ *
+ * Returns a pointer to the allocated memory on success and returns a null
+ * pointer and sets `errno` on failure.
+ *
+ * Available since API level 28.
+ */
 
-double strtod(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr);
-long double strtold(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr);
+#if __BIONIC_AVAILABILITY_GUARD(28)
+__nodiscard void* _Nullable aligned_alloc(size_t __alignment, size_t __size) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
 
-unsigned long strtoul_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base, locale_t _Nonnull __l) __INTRODUCED_IN(26);
 
-int atoi(const char* _Nonnull __s) __attribute_pure__;
-long atol(const char* _Nonnull __s) __attribute_pure__;
-long long atoll(const char* _Nonnull __s) __attribute_pure__;
-
-__wur char* _Nullable realpath(const char* _Nonnull __path, char* _Nullable __resolved);
+__nodiscard char* _Nullable realpath(const char* _Nonnull __path, char* _Nullable __resolved);
 
 /**
- * [system(3)](http://man7.org/linux/man-pages/man3/system.3.html) executes
+ * [system(3)](https://man7.org/linux/man-pages/man3/system.3.html) executes
  * the given command in a new shell process.
  *
  * On Android, the special case of `system(NULL)` always returns 1,
@@ -100,21 +108,38 @@
  * or permanently (for lack of permission, say).
  *
  * Returns -1 and sets errno if process creation fails; returns a
- * [waitpid(2)](http://man7.org/linux/man-pages/man2/waitpid.2.html)
+ * [waitpid(2)](https://man7.org/linux/man-pages/man2/waitpid.2.html)
  * status otherwise.
  */
 int system(const char* _Nonnull __command);
 
 /**
- * [bsearch(3)](http://man7.org/linux/man-pages/man3/bsearch.3.html) searches
+ * [bsearch(3)](https://man7.org/linux/man-pages/man3/bsearch.3.html) searches
  * a sorted array.
  *
  * Returns a pointer to a matching item on success,
  * or NULL if no matching item is found.
  */
-__wur void* _Nullable bsearch(const void* _Nonnull __key, const void* _Nullable __base, size_t __nmemb, size_t __size, int (* _Nonnull __comparator)(const void* _Nonnull __lhs, const void* _Nonnull __rhs));
+__nodiscard void* _Nullable bsearch(const void* _Nonnull __key, const void* _Nullable __base, size_t __nmemb, size_t __size, int (* _Nonnull __comparator)(const void* _Nonnull __lhs, const void* _Nonnull __rhs));
 
-void qsort(void* _Nullable __base, size_t __nmemb, size_t __size, int (* _Nonnull __comparator)(const void* _Nullable __lhs, const void* _Nullable __rhs));
+/**
+ * [qsort(3)](https://man7.org/linux/man-pages/man3/qsort.3.html) sorts an array
+ * of n elements each of the given size, using the given comparator.
+ */
+void qsort(void* _Nullable __array, size_t __n, size_t __size, int (* _Nonnull __comparator)(const void* _Nullable __lhs, const void* _Nullable __rhs));
+
+/**
+ * [qsort_r(3)](https://man7.org/linux/man-pages/man3/qsort_r.3.html) sorts an
+ * array of n elements each of the given size, using the given comparator,
+ * and passing the given context argument to the comparator.
+ *
+ * Available since API level 36.
+ */
+
+#if __BIONIC_AVAILABILITY_GUARD(36)
+void qsort_r(void* _Nullable __array, size_t __n, size_t __size, int (* _Nonnull __comparator)(const void* _Nullable __lhs, const void* _Nullable __rhs, void* _Nullable __context), void* _Nullable __context) __INTRODUCED_IN(36);
+#endif /* __BIONIC_AVAILABILITY_GUARD(36) */
+
 
 uint32_t arc4random(void);
 uint32_t arc4random_uniform(uint32_t __upper_bound);
@@ -127,7 +152,11 @@
 double drand48(void);
 double erand48(unsigned short __xsubi[_Nonnull 3]);
 long jrand48(unsigned short __xsubi[_Nonnull 3]);
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 void lcong48(unsigned short __param[_Nonnull 7]) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 long lrand48(void);
 long mrand48(void);
 long nrand48(unsigned short __xsubi[_Nonnull 3]);
@@ -143,7 +172,11 @@
 int ptsname_r(int __fd, char* _Nonnull __buf, size_t __n);
 int unlockpt(int __fd);
 
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 int getsubopt(char* _Nonnull * _Nonnull __option, char* _Nonnull const* _Nonnull __tokens, char* _Nullable * _Nonnull __value_ptr) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 typedef struct {
   int quot;
@@ -167,19 +200,27 @@
 lldiv_t lldiv(long long __numerator, long long __denominator) __attribute_const__;
 
 /**
- * [getloadavg(3)](http://man7.org/linux/man-pages/man3/getloadavg.3.html) queries the
+ * [getloadavg(3)](https://man7.org/linux/man-pages/man3/getloadavg.3.html) queries the
  * number of runnable processes averaged over time. The Linux kernel supports averages
  * over the last 1, 5, and 15 minutes.
  *
  * Returns the number of samples written to `__averages` (at most 3), and returns -1 on failure.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(29)
 int getloadavg(double __averages[_Nonnull], int __n) __INTRODUCED_IN(29);
+#endif /* __BIONIC_AVAILABILITY_GUARD(29) */
+
 
 /* BSD compatibility. */
 const char* _Nullable getprogname(void);
 void setprogname(const char* _Nonnull __name);
 
-int mblen(const char* _Nullable __s, size_t __n) __INTRODUCED_IN_NO_GUARD_FOR_NDK(26);
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
+int mblen(const char* _Nullable __s, size_t __n) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 size_t mbstowcs(wchar_t* _Nullable __dst, const char* _Nullable __src, size_t __n);
 int mbtowc(wchar_t* _Nullable __wc_ptr, const char*  _Nullable __s, size_t __n);
 int wctomb(char* _Nullable __dst, wchar_t __wc);
@@ -197,22 +238,134 @@
 long labs(long __x) __attribute_const__;
 long long llabs(long long __x) __attribute_const__;
 
-float strtof(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr);
-double atof(const char* _Nonnull __s) __attribute_pure__;
 int rand(void);
 void srand(unsigned int __seed);
 long random(void);
 void srandom(unsigned int __seed);
 int grantpt(int __fd);
 
+/**
+ * [atof(3)](https://man7.org/linux/man-pages/man3/atof.3.html) converts a
+ * string to a double.
+ *
+ * Returns the double; use strtof() or strtod() if you need to detect errors.
+ */
+double atof(const char* _Nonnull __s) __attribute_pure__;
+
+/**
+ * [atoi(3)](https://man7.org/linux/man-pages/man3/atoi.3.html) converts a
+ * string to an int.
+ *
+ * Returns the int or 0 on error; use strtol() if you need to detect errors.
+ */
+int atoi(const char* _Nonnull __s) __attribute_pure__;
+
+/**
+ * [atol(3)](https://man7.org/linux/man-pages/man3/atol.3.html) converts a
+ * string to a long.
+ *
+ * Returns the long or 0 on error; use strtol() if you need to detect errors.
+ */
+long atol(const char* _Nonnull __s) __attribute_pure__;
+
+/**
+ * [atoll(3)](https://man7.org/linux/man-pages/man3/atoll.3.html) converts a
+ * string to a long long.
+ *
+ * Returns the long long or 0 on error; use strtol() if you need to detect errors.
+ */
+long long atoll(const char* _Nonnull __s) __attribute_pure__;
+
+/**
+ * [strtol(3)](https://man7.org/linux/man-pages/man3/strtol.3.html) converts a
+ * string to a long.
+ *
+ * Returns the long.
+ * `__end_ptr` is set to the last character in `__s` that was converted.
+ * errno is set to ERANGE if the result overflowed or underflowed.
+ */
+long strtol(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base);
+
+/** Equivalent to strtol() on Android. */
+long strtol_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int, locale_t _Nonnull __l) __RENAME(strtol);
+
+/**
+ * [strtoll(3)](https://man7.org/linux/man-pages/man3/strtoll.3.html) converts a
+ * string to a long long.
+ *
+ * Returns the long long.
+ * `__end_ptr` is set to the last character in `__s` that was converted.
+ * errno is set to ERANGE if the result overflowed or underflowed.
+ */
+long long strtoll(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base);
+
+/** Equivalent to strtoll() on Android. */
 long long strtoll_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base, locale_t _Nonnull __l);
+
+/**
+ * [strtoul(3)](https://man7.org/linux/man-pages/man3/strtoul.3.html) converts a
+ * string to an unsigned long.
+ *
+ * Returns the unsigned long.
+ * `__end_ptr` is set to the last character in `__s` that was converted.
+ * errno is set to ERANGE if the result overflowed or underflowed.
+ */
+unsigned long strtoul(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base);
+
+/** Equivalent to strtoul() on Android. */
+unsigned long strtoul_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base, locale_t _Nonnull __l) __RENAME(strtoul);
+
+/**
+ * [strtoull(3)](https://man7.org/linux/man-pages/man3/strtoull.3.html) converts a
+ * string to an unsigned long long.
+ *
+ * Returns the unsigned long long.
+ * `__end_ptr` is set to the last character in `__s` that was converted.
+ * errno is set to ERANGE if the result overflowed or underflowed.
+ */
+unsigned long long strtoull(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base);
+
+/** Equivalent to strtoull() on Android. */
 unsigned long long strtoull_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base, locale_t _Nonnull __l);
+
+/**
+ * [strtof(3)](https://man7.org/linux/man-pages/man3/strtof.3.html) converts a
+ * string to a float.
+ *
+ * Returns the float.
+ * `__end_ptr` is set to the last character in `__s` that was converted.
+ * errno is set to ERANGE if the result overflowed or underflowed.
+ */
+float strtof(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr);
+
+/**
+ * [strtod(3)](https://man7.org/linux/man-pages/man3/strtod.3.html) converts a
+ * string to a double.
+ *
+ * Returns the double.
+ * `__end_ptr` is set to the last character in `__s` that was converted.
+ * errno is set to ERANGE if the result overflowed or underflowed.
+ */
+double strtod(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr);
+
+/**
+ * [strtold(3)](https://man7.org/linux/man-pages/man3/strtold.3.html) converts a
+ * string to a long double.
+ *
+ * Returns the long double.
+ * `__end_ptr` is set to the last character in `__s` that was converted.
+ * errno is set to ERANGE if the result overflowed or underflowed.
+ */
+long double strtold(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr);
+
+/** Equivalent to strtold() on Android. */
 long double strtold_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, locale_t _Nonnull __l);
 
 #if __ANDROID_API__ >= 26
+/** Equivalent to strtod() on Android. */
 double strtod_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, locale_t _Nonnull __l) __INTRODUCED_IN(26);
+/** Equivalent to strtof() on Android. */
 float strtof_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, locale_t _Nonnull __l) __INTRODUCED_IN(26);
-long strtol_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int, locale_t _Nonnull __l) __INTRODUCED_IN(26);
 #else
 // Implemented as static inlines before 26.
 #endif
diff --git a/libc/include/string.h b/libc/include/string.h
index 47bdd72..79aac91 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -52,12 +52,16 @@
 int memcmp(const void* _Nonnull __lhs, const void* _Nonnull __rhs, size_t __n) __attribute_pure__;
 void* _Nonnull memcpy(void* _Nonnull, const void* _Nonnull, size_t);
 #if defined(__USE_GNU)
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 void* _Nonnull mempcpy(void* _Nonnull __dst, const void* _Nonnull __src, size_t __n) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 #endif
 void* _Nonnull memmove(void* _Nonnull __dst, const void* _Nonnull __src, size_t __n);
 
 /**
- * [memset(3)](http://man7.org/linux/man-pages/man3/memset.3.html) writes the
+ * [memset(3)](https://man7.org/linux/man-pages/man3/memset.3.html) writes the
  * bottom 8 bits of the given int to the next `n` bytes of `dst`.
  *
  * Returns `dst`.
@@ -65,13 +69,17 @@
 void* _Nonnull memset(void* _Nonnull __dst, int __ch, size_t __n);
 
 /**
- * [memset_explicit(3)](http://man7.org/linux/man-pages/man3/memset_explicit.3.html)
+ * [memset_explicit(3)](https://man7.org/linux/man-pages/man3/memset_explicit.3.html)
  * writes the bottom 8 bits of the given int to the next `n` bytes of `dst`,
  * but won't be optimized out by the compiler.
  *
  * Returns `dst`.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(34)
 void* _Nonnull memset_explicit(void* _Nonnull __dst, int __ch, size_t __n) __INTRODUCED_IN(34);
+#endif /* __BIONIC_AVAILABILITY_GUARD(34) */
+
 
 void* _Nullable memmem(const void* _Nonnull __haystack, size_t __haystack_size, const void* _Nonnull __needle, size_t __needle_size) __attribute_pure__;
 
@@ -79,10 +87,18 @@
 char* _Nullable __strchr_chk(const char* _Nonnull __s, int __ch, size_t __n);
 #if defined(__USE_GNU)
 #if defined(__cplusplus)
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 extern "C++" char* _Nonnull strchrnul(char* _Nonnull __s, int __ch) __RENAME(strchrnul) __attribute_pure__ __INTRODUCED_IN(24);
 extern "C++" const char* _Nonnull strchrnul(const char* _Nonnull __s, int __ch) __RENAME(strchrnul) __attribute_pure__ __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 #else
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 char* _Nonnull strchrnul(const char* _Nonnull __s, int __ch) __attribute_pure__ __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 #endif
 #endif
 
@@ -108,8 +124,35 @@
 char* _Nullable strtok(char* _Nullable __s, const char* _Nonnull __delimiter);
 char* _Nullable strtok_r(char* _Nullable __s, const char* _Nonnull __delimiter, char* _Nonnull * _Nonnull __pos_ptr);
 
+/**
+ * [strerror(3)](https://man7.org/linux/man-pages/man3/strerror.3.html)
+ * returns a string describing the given errno value.
+ * `strerror(EINVAL)` would return "Invalid argument", for example.
+ *
+ * On Android, unknown errno values return a string such as "Unknown error 666".
+ * These unknown errno value strings live in thread-local storage, and are valid
+ * until the next call of strerror() on the same thread.
+ *
+ * Returns a pointer to a string.
+ */
 char* _Nonnull strerror(int __errno_value);
-char* _Nonnull strerror_l(int __errno_value, locale_t _Nonnull __l) __INTRODUCED_IN(23);
+
+/**
+ * Equivalent to strerror() on Android where only C/POSIX locales are available.
+ */
+char* _Nonnull strerror_l(int __errno_value, locale_t _Nonnull __l) __RENAME(strerror);
+
+/**
+ * [strerror_r(3)](https://man7.org/linux/man-pages/man3/strerror_r.3.html)
+ * writes a string describing the given errno value into the given buffer.
+ *
+ * There are two variants of this function, POSIX and GNU.
+ * The GNU variant returns a pointer to the buffer.
+ * The POSIX variant returns 0 on success or an errno value on failure.
+ *
+ * The GNU variant is available since API level 23 if `_GNU_SOURCE` is defined.
+ * The POSIX variant is available otherwise.
+ */
 #if defined(__USE_GNU) && __ANDROID_API__ >= 23
 char* _Nonnull strerror_r(int __errno_value, char* _Nullable __buf, size_t __n) __RENAME(__gnu_strerror_r) __INTRODUCED_IN(23);
 #else /* POSIX */
@@ -117,7 +160,7 @@
 #endif
 
 /**
- * [strerrorname_np(3)](http://man7.org/linux/man-pages/man3/strerrordesc_np.3.html)
+ * [strerrorname_np(3)](https://man7.org/linux/man-pages/man3/strerrordesc_np.3.html)
  * returns the name of the errno constant corresponding to its argument.
  * `strerrorname_np(38)` would return "ENOSYS", because `ENOSYS` is errno 38. This
  * is mostly useful for error reporting in cases where a string like "ENOSYS" is
@@ -129,11 +172,15 @@
  * Available since API level 35.
  */
 #if defined(__USE_GNU)
+
+#if __BIONIC_AVAILABILITY_GUARD(35)
 const char* _Nullable strerrorname_np(int __errno_value) __INTRODUCED_IN(35);
+#endif /* __BIONIC_AVAILABILITY_GUARD(35) */
+
 #endif
 
 /**
- * [strerrordesc_np(3)](http://man7.org/linux/man-pages/man3/strerrordesc_np.3.html)
+ * [strerrordesc_np(3)](https://man7.org/linux/man-pages/man3/strerrordesc_np.3.html)
  * is like strerror() but without localization. Since Android's strerror()
  * does not localize, this is the same as strerror() on Android.
  *
@@ -172,10 +219,18 @@
  * It doesn't modify its argument, and in C++ it's const-correct.
  */
 #if defined(__cplusplus)
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 extern "C++" char* _Nonnull basename(char* _Nullable __path) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
 extern "C++" const char* _Nonnull basename(const char* _Nonnull __path) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 #else
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 char* _Nonnull basename(const char* _Nonnull __path) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 #endif
 #endif
 
@@ -185,11 +240,10 @@
 
 /* Const-correct overloads. Placed after FORTIFY so we call those functions, if possible. */
 #if defined(__cplusplus)
-/*
- * Use two enable_ifs so these overloads don't conflict with + are preferred over libcxx's. This can
- * be reduced to 1 after libcxx recognizes that we have const-correct overloads.
- */
-#define __prefer_this_overload __enable_if(true, "preferred overload") __enable_if(true, "")
+/* libcxx tries to provide these. Suppress that, since libcxx's impl doesn't respect FORTIFY. */
+#define __CORRECT_ISO_CPP_STRING_H_PROTO
+/* Used to make these preferable over regular <string.h> signatures for overload resolution. */
+#define __prefer_this_overload __enable_if(true, "")
 extern "C++" {
 inline __always_inline
 void* _Nullable __bionic_memchr(const void* _Nonnull const s __pass_object_size, int c, size_t n) {
diff --git a/libc/include/strings.h b/libc/include/strings.h
index 4b8cc08..7543edc 100644
--- a/libc/include/strings.h
+++ b/libc/include/strings.h
@@ -43,8 +43,9 @@
  * @brief Extra string functions.
  */
 
-#include <sys/types.h>
 #include <sys/cdefs.h>
+
+#include <sys/types.h>
 #include <xlocale.h>
 
 #include <bits/strcasecmp.h>
@@ -72,7 +73,7 @@
 }
 
 /**
- * [ffs(3)](http://man7.org/linux/man-pages/man3/ffs.3.html) finds the
+ * [ffs(3)](https://man7.org/linux/man-pages/man3/ffs.3.html) finds the
  * first set bit in `__n`.
  *
  * Returns 0 if no bit is set, or the index of the lowest set bit (counting
@@ -83,7 +84,7 @@
 }
 
 /**
- * [ffsl(3)](http://man7.org/linux/man-pages/man3/ffsl.3.html) finds the
+ * [ffsl(3)](https://man7.org/linux/man-pages/man3/ffsl.3.html) finds the
  * first set bit in `__n`.
  *
  * Returns 0 if no bit is set, or the index of the lowest set bit (counting
@@ -94,7 +95,7 @@
 }
 
 /**
- * [ffsll(3)](http://man7.org/linux/man-pages/man3/ffsll.3.html) finds the
+ * [ffsll(3)](https://man7.org/linux/man-pages/man3/ffsll.3.html) finds the
  * first set bit in `__n`.
  *
  * Returns 0 if no bit is set, or the index of the lowest set bit (counting
diff --git a/libc/include/sys/_system_properties.h b/libc/include/sys/_system_properties.h
index 078e857..12cafec 100644
--- a/libc/include/sys/_system_properties.h
+++ b/libc/include/sys/_system_properties.h
@@ -1,150 +1 @@
-/*
- * 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.
- */
-
-#ifndef _INCLUDE_SYS__SYSTEM_PROPERTIES_H
-#define _INCLUDE_SYS__SYSTEM_PROPERTIES_H
-
-#include <sys/cdefs.h>
-#include <stdint.h>
-
-#ifndef _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#error you should #include <sys/system_properties.h> instead
-#endif
-
 #include <sys/system_properties.h>
-
-__BEGIN_DECLS
-
-#define PROP_SERVICE_NAME "property_service"
-#define PROP_SERVICE_FOR_SYSTEM_NAME "property_service_for_system"
-#define PROP_DIRNAME "/dev/__properties__"
-
-#define PROP_MSG_SETPROP 1
-#define PROP_MSG_SETPROP2 0x00020001
-
-#define PROP_SUCCESS 0
-#define PROP_ERROR_READ_CMD 0x0004
-#define PROP_ERROR_READ_DATA 0x0008
-#define PROP_ERROR_READ_ONLY_PROPERTY 0x000B
-#define PROP_ERROR_INVALID_NAME 0x0010
-#define PROP_ERROR_INVALID_VALUE 0x0014
-#define PROP_ERROR_PERMISSION_DENIED 0x0018
-#define PROP_ERROR_INVALID_CMD 0x001B
-#define PROP_ERROR_HANDLE_CONTROL_MESSAGE 0x0020
-#define PROP_ERROR_SET_FAILED 0x0024
-
-/*
-** This was previously for testing, but now that SystemProperties is its own testable class,
-** there is never a reason to call this function and its implementation simply returns -1.
-*/
-int __system_property_set_filename(const char* __unused __filename);
-
-/*
-** Initialize the area to be used to store properties.  Can
-** only be done by a single process that has write access to
-** the property area.
-*/
-int __system_property_area_init(void);
-
-/* Read the global serial number of the system properties
-**
-** Called to predict if a series of cached __system_property_find
-** objects will have seen __system_property_serial values change.
-** But also aids the converse, as changes in the global serial can
-** also be used to predict if a failed __system_property_find
-** could in-turn now find a new object; thus preventing the
-** cycles of effort to poll __system_property_find.
-**
-** Typically called at beginning of a cache cycle to signal if _any_ possible
-** changes have occurred since last. If there is, one may check each individual
-** __system_property_serial to confirm dirty, or __system_property_find
-** to check if the property now exists. If a call to __system_property_add
-** or __system_property_update has completed between two calls to
-** __system_property_area_serial then the second call will return a larger
-** value than the first call. Beware of race conditions as changes to the
-** properties are not atomic, the main value of this call is to determine
-** whether the expensive __system_property_find is worth retrying to see if
-** a property now exists.
-**
-** Returns the serial number on success, -1 on error.
-*/
-uint32_t __system_property_area_serial(void);
-
-/* Add a new system property.  Can only be done by a single
-** process that has write access to the property area, and
-** that process must handle sequencing to ensure the property
-** does not already exist and that only one property is added
-** or updated at a time.
-**
-** Returns 0 on success, -1 if the property area is full.
-*/
-int __system_property_add(const char* _Nonnull __name, unsigned int __name_length, const char* _Nonnull __value, unsigned int __value_length);
-
-/* Update the value of a system property returned by
-** __system_property_find.  Can only be done by a single process
-** that has write access to the property area, and that process
-** must handle sequencing to ensure that only one property is
-** updated at a time.
-**
-** Returns 0 on success, -1 if the parameters are incorrect.
-*/
-int __system_property_update(prop_info* _Nonnull __pi, const char* _Nonnull __value, unsigned int __value_length);
-
-/* Read the serial number of a system property returned by
-** __system_property_find.
-**
-** Returns the serial number on success, -1 on error.
-*/
-uint32_t __system_property_serial(const prop_info* _Nonnull __pi);
-
-/* Initialize the system properties area in read only mode.
- * Should be done by all processes that need to read system
- * properties.
- *
- * Returns 0 on success, -1 otherwise.
- */
-int __system_properties_init(void);
-
-/*
- * Reloads the system properties from disk.
- * Not intended for use by any apps except the Zygote. Should only be called from the main thread.
- *
- * NOTE: Any pointers received from methods such as __system_property_find should be assumed to be
- * invalid after this method is called.
- *
- * Returns 0 on success, -1 if the system properties failed to re-initialize (same conditions as
- * __system properties_init)
- */
-int __system_properties_zygote_reload(void) __INTRODUCED_IN(__ANDROID_API_V__);
-
-/* Deprecated: use __system_property_wait instead. */
-uint32_t __system_property_wait_any(uint32_t __old_serial);
-
-__END_DECLS
-
-#endif
diff --git a/libc/include/sys/auxv.h b/libc/include/sys/auxv.h
index b664e2a..732f944 100644
--- a/libc/include/sys/auxv.h
+++ b/libc/include/sys/auxv.h
@@ -40,7 +40,7 @@
 __BEGIN_DECLS
 
 /**
- * [getauxval(3)](http://man7.org/linux/man-pages/man3/getauxval.3.html) returns values from
+ * [getauxval(3)](https://man7.org/linux/man-pages/man3/getauxval.3.html) returns values from
  * the ELF auxiliary vector passed by the kernel.
  *
  * Returns the corresponding value on success,
diff --git a/libc/include/sys/cachectl.h b/libc/include/sys/cachectl.h
index b5fabe3..d06d683 100644
--- a/libc/include/sys/cachectl.h
+++ b/libc/include/sys/cachectl.h
@@ -48,7 +48,7 @@
 
 /**
  * __riscv_flush_icache(2) flushes the instruction cache for the given range of addresses.
- * The address range is currently (Linux 6.4) ignored, so both pointers may be null.
+ * The address range is currently (Linux 6.12) ignored, so both pointers may be null.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
  */
diff --git a/libc/include/sys/capability.h b/libc/include/sys/capability.h
index b43bbf0..3d1d896 100644
--- a/libc/include/sys/capability.h
+++ b/libc/include/sys/capability.h
@@ -39,7 +39,7 @@
 __BEGIN_DECLS
 
 /**
- * [capget(2)](http://man7.org/linux/man-pages/man2/capget.2.html) gets the calling
+ * [capget(2)](https://man7.org/linux/man-pages/man2/capget.2.html) gets the calling
  * thread's capabilities.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -47,7 +47,7 @@
 int capget(cap_user_header_t _Nonnull __hdr_ptr, cap_user_data_t _Nullable __data_ptr);
 
 /**
- * [capset(2)](http://man7.org/linux/man-pages/man2/capset.2.html) sets the calling
+ * [capset(2)](https://man7.org/linux/man-pages/man2/capset.2.html) sets the calling
  * thread's capabilities.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 5d1718e..9bd35bb 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -140,7 +140,8 @@
 #define	__predict_true(exp)	__builtin_expect((exp) != 0, 1)
 #define	__predict_false(exp)	__builtin_expect((exp) != 0, 0)
 
-#define __wur __attribute__((__warn_unused_result__))
+#define __nodiscard __attribute__((__warn_unused_result__))
+#define __wur __nodiscard
 
 #define __errorattr(msg) __attribute__((__unavailable__(msg)))
 #define __warnattr(msg) __attribute__((__deprecated__(msg)))
@@ -264,7 +265,7 @@
  * having stack protectors detracts from that (b/182948263).
  */
 #  define __BIONIC_FORTIFY_INLINE static __inline __attribute__((__no_stack_protector__)) \
-      __always_inline __VERSIONER_FORTIFY_INLINE
+      __always_inline
 /*
  * We should use __BIONIC_FORTIFY_VARIADIC instead of __BIONIC_FORTIFY_INLINE
  * for variadic functions because compilers cannot inline them.
diff --git a/libc/include/sys/epoll.h b/libc/include/sys/epoll.h
index 2bad655..bec7c64 100644
--- a/libc/include/sys/epoll.h
+++ b/libc/include/sys/epoll.h
@@ -42,8 +42,8 @@
 __BEGIN_DECLS
 
 /**
- * [epoll_create(2)](http://man7.org/linux/man-pages/man2/epoll_create.2.html)
- * creates a new [epoll](http://man7.org/linux/man-pages/man7/epoll.7.html)
+ * [epoll_create(2)](https://man7.org/linux/man-pages/man2/epoll_create.2.html)
+ * creates a new [epoll](https://man7.org/linux/man-pages/man7/epoll.7.html)
  * file descriptor.
  *
  * Returns a new file descriptor on success and returns -1 and sets `errno` on
@@ -52,8 +52,8 @@
 int epoll_create(int __size);
 
 /**
- * [epoll_create1(2)](http://man7.org/linux/man-pages/man2/epoll_create1.2.html)
- * creates a new [epoll](http://man7.org/linux/man-pages/man7/epoll.7.html)
+ * [epoll_create1(2)](https://man7.org/linux/man-pages/man2/epoll_create1.2.html)
+ * creates a new [epoll](https://man7.org/linux/man-pages/man7/epoll.7.html)
  * file descriptor with the given flags.
  *
  * Returns a new file descriptor on success and returns -1 and sets `errno` on
@@ -62,7 +62,7 @@
 int epoll_create1(int __flags);
 
 /**
- * [epoll_ctl(2)](http://man7.org/linux/man-pages/man2/epoll_ctl.2.html)
+ * [epoll_ctl(2)](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html)
  * adds/modifies/removes file descriptors from the given epoll file descriptor.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
@@ -70,7 +70,7 @@
 int epoll_ctl(int __epoll_fd, int __op, int __fd, struct epoll_event* __BIONIC_COMPLICATED_NULLNESS __event);
 
 /**
- * [epoll_wait(2)](http://man7.org/linux/man-pages/man2/epoll_wait.2.html)
+ * [epoll_wait(2)](https://man7.org/linux/man-pages/man2/epoll_wait.2.html)
  * waits for an event on the given epoll file descriptor.
  *
  * Returns the number of ready file descriptors on success, 0 on timeout,
@@ -88,13 +88,19 @@
  *
  * Available since API level 28.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int epoll_pwait64(int __epoll_fd, struct epoll_event* _Nonnull __events, int __event_count, int __timeout_ms, const sigset64_t* _Nullable __mask) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 /**
  * Like epoll_pwait() but with a `struct timespec` timeout, for nanosecond resolution.
  *
  * Available since API level 35.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(35)
 int epoll_pwait2(int __epoll_fd, struct epoll_event* _Nonnull __events, int __event_count, const struct timespec* _Nullable __timeout, const sigset_t* _Nullable __mask) __INTRODUCED_IN(35);
 
 /**
@@ -103,5 +109,7 @@
  * Available since API level 35.
  */
 int epoll_pwait2_64(int __epoll_fd, struct epoll_event* _Nonnull __events, int __event_count, const struct timespec* _Nullable __timeout, const sigset64_t* _Nullable __mask) __INTRODUCED_IN(35);
+#endif /* __BIONIC_AVAILABILITY_GUARD(35) */
+
 
 __END_DECLS
diff --git a/libc/include/sys/eventfd.h b/libc/include/sys/eventfd.h
index 1ad11e3..3000737 100644
--- a/libc/include/sys/eventfd.h
+++ b/libc/include/sys/eventfd.h
@@ -35,18 +35,22 @@
 
 #include <sys/cdefs.h>
 #include <fcntl.h>
+#include <linux/eventfd.h>
 
 __BEGIN_DECLS
 
-/** The eventfd() flag to provide semaphore-like semantics for reads. */
-#define EFD_SEMAPHORE (1 << 0)
-/** The eventfd() flag for a close-on-exec file descriptor. */
-#define EFD_CLOEXEC O_CLOEXEC
-/** The eventfd() flag for a non-blocking file descriptor. */
-#define EFD_NONBLOCK O_NONBLOCK
+/*! \macro EFD_SEMAPHORE
+ * The eventfd() flag to provide semaphore-like semantics for reads.
+ */
+/*! \macro EFD_CLOEXEC
+ * The eventfd() flag for a close-on-exec file descriptor.
+ */
+/*! \macro EFD_NONBLOCK
+ * The eventfd() flag for a non-blocking file descriptor.
+ */
 
 /**
- * [eventfd(2)](http://man7.org/linux/man-pages/man2/eventfd.2.html) creates a file descriptor
+ * [eventfd(2)](https://man7.org/linux/man-pages/man2/eventfd.2.html) creates a file descriptor
  * for event notification.
  *
  * Returns a new file descriptor on success, and returns -1 and sets `errno` on failure.
@@ -57,7 +61,7 @@
 typedef uint64_t eventfd_t;
 
 /**
- * [eventfd_read(3)](http://man7.org/linux/man-pages/man2/eventfd.2.html) is a convenience
+ * [eventfd_read(3)](https://man7.org/linux/man-pages/man2/eventfd.2.html) is a convenience
  * wrapper to read an `eventfd_t` from an eventfd file descriptor.
  *
  * Returns 0 on success, or returns -1 otherwise.
@@ -65,7 +69,7 @@
 int eventfd_read(int __fd, eventfd_t* _Nonnull __value);
 
 /**
- * [eventfd_write(3)](http://man7.org/linux/man-pages/man2/eventfd.2.html) is a convenience
+ * [eventfd_write(3)](https://man7.org/linux/man-pages/man2/eventfd.2.html) is a convenience
  * wrapper to write an `eventfd_t` to an eventfd file descriptor.
  *
  * Returns 0 on success, or returns -1 otherwise.
diff --git a/libc/include/sys/file.h b/libc/include/sys/file.h
index ccdfeea..45117fa 100644
--- a/libc/include/sys/file.h
+++ b/libc/include/sys/file.h
@@ -41,7 +41,7 @@
 __BEGIN_DECLS
 
 /**
- * [flock(2)](http://man7.org/linux/man-pages/man2/flock.2.html) performs
+ * [flock(2)](https://man7.org/linux/man-pages/man2/flock.2.html) performs
  * advisory file lock operations.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
diff --git a/libc/include/sys/fsuid.h b/libc/include/sys/fsuid.h
index 273749f..eeb5783 100644
--- a/libc/include/sys/fsuid.h
+++ b/libc/include/sys/fsuid.h
@@ -39,7 +39,7 @@
 __BEGIN_DECLS
 
 /**
- * [setfsuid(2)](http://man7.org/linux/man-pages/man2/setfsuid.2.html) sets the UID used for
+ * [setfsuid(2)](https://man7.org/linux/man-pages/man2/setfsuid.2.html) sets the UID used for
  * filesystem checks.
  *
  * Returns the previous UID.
@@ -47,7 +47,7 @@
 int setfsuid(uid_t __uid);
 
 /**
- * [setfsgid(2)](http://man7.org/linux/man-pages/man2/setfsgid.2.html) sets the GID used for
+ * [setfsgid(2)](https://man7.org/linux/man-pages/man2/setfsgid.2.html) sets the GID used for
  * filesystem checks.
  *
  * Returns the previous GID.
diff --git a/libc/include/sys/inotify.h b/libc/include/sys/inotify.h
index f070857..75ed542 100644
--- a/libc/include/sys/inotify.h
+++ b/libc/include/sys/inotify.h
@@ -33,13 +33,9 @@
 #include <sys/types.h>
 #include <stdint.h>
 #include <linux/inotify.h>
-#include <asm/fcntl.h> /* For O_CLOEXEC and O_NONBLOCK. */
 
 __BEGIN_DECLS
 
-#define IN_CLOEXEC O_CLOEXEC
-#define IN_NONBLOCK O_NONBLOCK
-
 int inotify_init(void);
 int inotify_init1(int __flags);
 int inotify_add_watch(int __fd, const char* _Nonnull __path, uint32_t __mask);
diff --git a/libc/include/sys/io.h b/libc/include/sys/io.h
index d187b78..11f3f3a 100644
--- a/libc/include/sys/io.h
+++ b/libc/include/sys/io.h
@@ -42,7 +42,7 @@
 __BEGIN_DECLS
 
 /**
- * [iopl(2)](http://man7.org/linux/man-pages/man2/iopl.2.html) changes the I/O
+ * [iopl(2)](https://man7.org/linux/man-pages/man2/iopl.2.html) changes the I/O
  * privilege level for all x86/x8-64 I/O ports, for the calling thread.
  *
  * New callers should use ioperm() instead.
@@ -58,7 +58,7 @@
 #endif
 
 /**
- * [ioperm(2)](http://man7.org/linux/man-pages/man2/ioperm.2.html) sets the I/O
+ * [ioperm(2)](https://man7.org/linux/man-pages/man2/ioperm.2.html) sets the I/O
  * permissions for the given number of x86/x86-64 I/O ports, starting at the
  * given port.
  *
diff --git a/libc/include/sys/ipc.h b/libc/include/sys/ipc.h
index 2e2b8cf..f557ce5 100644
--- a/libc/include/sys/ipc.h
+++ b/libc/include/sys/ipc.h
@@ -47,7 +47,7 @@
 __BEGIN_DECLS
 
 /**
- * [ftok(3)](http://man7.org/linux/man-pages/man3/ftok.3.html) converts a path and id to a
+ * [ftok(3)](https://man7.org/linux/man-pages/man3/ftok.3.html) converts a path and id to a
  * System V IPC key.
  *
  * Returns a key on success, and returns -1 and sets `errno` on failure.
diff --git a/libc/include/sys/klog.h b/libc/include/sys/klog.h
index b60c2c4..237d2e2 100644
--- a/libc/include/sys/klog.h
+++ b/libc/include/sys/klog.h
@@ -61,7 +61,7 @@
 #define KLOG_SIZE_BUFFER 10
 
 /**
- * [klogctl(2)](http://man7.org/linux/man-pages/man2/syslog.2.html) operates on the kernel log.
+ * [klogctl(2)](https://man7.org/linux/man-pages/man2/syslog.2.html) operates on the kernel log.
  *
  * This system call is not available to applications.
  * Use syslog() or `<android/log.h>` instead.
diff --git a/libc/include/sys/mman.h b/libc/include/sys/mman.h
index 823c9ba..38cbf2f 100644
--- a/libc/include/sys/mman.h
+++ b/libc/include/sys/mman.h
@@ -43,7 +43,7 @@
 #define MAP_FAILED __BIONIC_CAST(reinterpret_cast, void*, -1)
 
 /**
- * [mmap(2)](http://man7.org/linux/man-pages/man2/mmap.2.html)
+ * [mmap(2)](https://man7.org/linux/man-pages/man2/mmap.2.html)
  * creates a memory mapping for the given range.
  *
  * Returns the address of the mapping on success,
@@ -63,7 +63,7 @@
 void* _Nonnull mmap64(void* _Nullable __addr, size_t __size, int __prot, int __flags, int __fd, off64_t __offset);
 
 /**
- * [munmap(2)](http://man7.org/linux/man-pages/man2/munmap.2.html)
+ * [munmap(2)](https://man7.org/linux/man-pages/man2/munmap.2.html)
  * deletes a memory mapping for the given range.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -71,7 +71,7 @@
 int munmap(void* _Nonnull __addr, size_t __size);
 
 /**
- * [msync(2)](http://man7.org/linux/man-pages/man2/msync.2.html)
+ * [msync(2)](https://man7.org/linux/man-pages/man2/msync.2.html)
  * flushes changes to a memory-mapped file to disk.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -79,7 +79,7 @@
 int msync(void* _Nonnull __addr, size_t __size, int __flags);
 
 /**
- * [mprotect(2)](http://man7.org/linux/man-pages/man2/mprotect.2.html)
+ * [mprotect(2)](https://man7.org/linux/man-pages/man2/mprotect.2.html)
  * sets the protection on a memory region.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -93,7 +93,7 @@
 #define MREMAP_FIXED    2
 
 /**
- * [mremap(2)](http://man7.org/linux/man-pages/man2/mremap.2.html)
+ * [mremap(2)](https://man7.org/linux/man-pages/man2/mremap.2.html)
  * expands or shrinks an existing memory mapping.
  *
  * Returns the address of the mapping on success,
@@ -102,7 +102,7 @@
 void* _Nonnull mremap(void* _Nonnull __old_addr, size_t __old_size, size_t __new_size, int __flags, ...);
 
 /**
- * [mlockall(2)](http://man7.org/linux/man-pages/man2/mlockall.2.html)
+ * [mlockall(2)](https://man7.org/linux/man-pages/man2/mlockall.2.html)
  * locks pages (preventing swapping).
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -110,7 +110,7 @@
 int mlockall(int __flags);
 
 /**
- * [munlockall(2)](http://man7.org/linux/man-pages/man2/munlockall.2.html)
+ * [munlockall(2)](https://man7.org/linux/man-pages/man2/munlockall.2.html)
  * unlocks pages (allowing swapping).
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -118,7 +118,7 @@
 int munlockall(void);
 
 /**
- * [mlock(2)](http://man7.org/linux/man-pages/man2/mlock.2.html)
+ * [mlock(2)](https://man7.org/linux/man-pages/man2/mlock.2.html)
  * locks pages (preventing swapping).
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -126,17 +126,21 @@
 int mlock(const void* _Nonnull __addr, size_t __size);
 
 /**
- * [mlock2(2)](http://man7.org/linux/man-pages/man2/mlock.2.html)
+ * [mlock2(2)](https://man7.org/linux/man-pages/man2/mlock.2.html)
  * locks pages (preventing swapping), with optional flags.
  *
  * Available since API level 30.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(30)
 int mlock2(const void* _Nonnull __addr, size_t __size, int __flags) __INTRODUCED_IN(30);
+#endif /* __BIONIC_AVAILABILITY_GUARD(30) */
+
 
 /**
- * [munlock(2)](http://man7.org/linux/man-pages/man2/munlock.2.html)
+ * [munlock(2)](https://man7.org/linux/man-pages/man2/munlock.2.html)
  * unlocks pages (allowing swapping).
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -144,7 +148,7 @@
 int munlock(const void* _Nonnull __addr, size_t __size);
 
 /**
- * [mincore(2)](http://man7.org/linux/man-pages/man2/mincore.2.html)
+ * [mincore(2)](https://man7.org/linux/man-pages/man2/mincore.2.html)
  * tests whether pages are resident in memory.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -152,7 +156,7 @@
 int mincore(void* _Nonnull __addr, size_t __size, unsigned char* _Nonnull __vector);
 
 /**
- * [madvise(2)](http://man7.org/linux/man-pages/man2/madvise.2.html)
+ * [madvise(2)](https://man7.org/linux/man-pages/man2/madvise.2.html)
  * gives the kernel advice about future usage patterns.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -160,7 +164,7 @@
 int madvise(void* _Nonnull __addr, size_t __size, int __advice);
 
 /**
- * [process_madvise(2)](http://man7.org/linux/man-pages/man2/process_madvise.2.html)
+ * [process_madvise(2)](https://man7.org/linux/man-pages/man2/process_madvise.2.html)
  * works just like madvise(2) but applies to the process specified by the given
  * PID file descriptor.
  *
@@ -171,19 +175,27 @@
  *
  * Returns the number of bytes advised on success, and returns -1 and sets `errno` on failure.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(31)
 ssize_t process_madvise(int __pid_fd, const struct iovec* _Nonnull __iov, size_t __count, int __advice, unsigned __flags) __INTRODUCED_IN(31);
+#endif /* __BIONIC_AVAILABILITY_GUARD(31) */
+
 
 #if defined(__USE_GNU)
 
 /**
- * [memfd_create(2)](http://man7.org/linux/man-pages/man2/memfd_create.2.html)
+ * [memfd_create(2)](https://man7.org/linux/man-pages/man2/memfd_create.2.html)
  * creates an anonymous file.
  *
  * Available since API level 30.
  *
  * Returns an fd on success, and returns -1 and sets `errno` on failure.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(30)
 int memfd_create(const char* _Nonnull __name, unsigned __flags) __INTRODUCED_IN(30);
+#endif /* __BIONIC_AVAILABILITY_GUARD(30) */
+
 
 #endif
 
@@ -212,7 +224,7 @@
 #endif
 
 /**
- * [posix_madvise(3)](http://man7.org/linux/man-pages/man3/posix_madvise.3.html)
+ * [posix_madvise(3)](https://man7.org/linux/man-pages/man3/posix_madvise.3.html)
  * gives the kernel advice about future usage patterns.
  *
  * Available since API level 23.
@@ -220,6 +232,26 @@
  *
  * Returns 0 on success, and returns a positive error number on failure.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int posix_madvise(void* _Nonnull __addr, size_t __size, int __advice) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
+
+/**
+ * [mseal(2)](https://man7.org/linux/man-pages/man2/mseal.2.html)
+ * seals the given range to prevent modifications such as mprotect() calls.
+ *
+ * Available since API level 36.
+ * Requires a Linux 6.10 or newer kernel.
+ * Always fails for 32-bit processes.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
+
+#if __BIONIC_AVAILABILITY_GUARD(36)
+int mseal(void* _Nonnull __addr, size_t __size, unsigned long __flags) __INTRODUCED_IN(36);
+#endif /* __BIONIC_AVAILABILITY_GUARD(36) */
+
 
 __END_DECLS
diff --git a/libc/include/sys/mount.h b/libc/include/sys/mount.h
index aace205..0880c98 100644
--- a/libc/include/sys/mount.h
+++ b/libc/include/sys/mount.h
@@ -50,7 +50,7 @@
 #define UMOUNT_NOFOLLOW 8
 
 /**
- * [mount(2)](http://man7.org/linux/man-pages/man2/mount.2.html) mounts the filesystem `source` at
+ * [mount(2)](https://man7.org/linux/man-pages/man2/mount.2.html) mounts the filesystem `source` at
  * the mount point `target`.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -58,7 +58,7 @@
 int mount(const char* __BIONIC_COMPLICATED_NULLNESS __source, const char* _Nonnull __target, const char* __BIONIC_COMPLICATED_NULLNESS __fs_type, unsigned long __flags, const void* _Nullable __data);
 
 /**
- * [umount(2)](http://man7.org/linux/man-pages/man2/umount.2.html) unmounts the filesystem at
+ * [umount(2)](https://man7.org/linux/man-pages/man2/umount.2.html) unmounts the filesystem at
  * the given mount point.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -66,7 +66,7 @@
 int umount(const char* _Nonnull __target);
 
 /**
- * [umount2(2)](http://man7.org/linux/man-pages/man2/umount2.2.html) unmounts the filesystem at
+ * [umount2(2)](https://man7.org/linux/man-pages/man2/umount2.2.html) unmounts the filesystem at
  * the given mount point, according to the supplied flags.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
diff --git a/libc/include/sys/msg.h b/libc/include/sys/msg.h
index 26071b1..8b619be 100644
--- a/libc/include/sys/msg.h
+++ b/libc/include/sys/msg.h
@@ -46,6 +46,8 @@
 typedef __kernel_ulong_t msglen_t;
 
 /** Not useful on Android; disallowed by SELinux. */
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 int msgctl(int __msg_id, int __op, struct msqid_ds* _Nullable __buf) __INTRODUCED_IN(26);
 /** Not useful on Android; disallowed by SELinux. */
 int msgget(key_t __key, int __flags) __INTRODUCED_IN(26);
@@ -53,5 +55,7 @@
 ssize_t msgrcv(int __msg_id, void* _Nonnull __msgbuf_ptr, size_t __size, long __type, int __flags) __INTRODUCED_IN(26);
 /** Not useful on Android; disallowed by SELinux. */
 int msgsnd(int __msg_id, const void* _Nonnull __msgbuf_ptr, size_t __size, int __flags) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 __END_DECLS
diff --git a/libc/include/sys/param.h b/libc/include/sys/param.h
index 1c991ae..99b6a07 100644
--- a/libc/include/sys/param.h
+++ b/libc/include/sys/param.h
@@ -33,10 +33,11 @@
  * @brief Various macros.
  */
 
+#include <sys/cdefs.h>
+
 #include <endian.h>
 #include <limits.h>
 #include <linux/param.h>
-#include <sys/cdefs.h>
 
 /** The unit of `st_blocks` in `struct stat`. */
 #define DEV_BSIZE 512
diff --git a/libc/include/sys/personality.h b/libc/include/sys/personality.h
index 9eb992f..34d1a1a 100644
--- a/libc/include/sys/personality.h
+++ b/libc/include/sys/personality.h
@@ -39,7 +39,7 @@
 __BEGIN_DECLS
 
 /**
- * [personality(2)](http://man7.org/linux/man-pages/man2/personality.2.html) sets the calling
+ * [personality(2)](https://man7.org/linux/man-pages/man2/personality.2.html) sets the calling
  * process' personality.
  *
  * Returns the previous persona on success, and returns -1 and sets `errno` on failure.
diff --git a/libc/include/sys/pidfd.h b/libc/include/sys/pidfd.h
index 30455bb..aaf49c9 100644
--- a/libc/include/sys/pidfd.h
+++ b/libc/include/sys/pidfd.h
@@ -49,6 +49,8 @@
  *
  * Available since API level 31.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(31)
 int pidfd_open(pid_t __pid, unsigned int __flags) __INTRODUCED_IN(31);
 
 /**
@@ -72,5 +74,7 @@
  * Available since API level 31.
  */
 int pidfd_send_signal(int __pidfd, int __sig, siginfo_t * _Nullable __info, unsigned int __flags) __INTRODUCED_IN(31);
+#endif /* __BIONIC_AVAILABILITY_GUARD(31) */
+
 
 __END_DECLS
diff --git a/libc/include/sys/prctl.h b/libc/include/sys/prctl.h
index 1c80415..4e0b4b5 100644
--- a/libc/include/sys/prctl.h
+++ b/libc/include/sys/prctl.h
@@ -40,7 +40,7 @@
 __BEGIN_DECLS
 
 /**
- * [prctl(2)](http://man7.org/linux/man-pages/man2/prctl.2.html) performs a variety of
+ * [prctl(2)](https://man7.org/linux/man-pages/man2/prctl.2.html) performs a variety of
  * operations based on the `PR_` constant passed as the first argument.
  *
  * Returns -1 and sets `errno` on failure; success values vary by option.
diff --git a/libc/include/sys/quota.h b/libc/include/sys/quota.h
index 37f8925..af09674 100644
--- a/libc/include/sys/quota.h
+++ b/libc/include/sys/quota.h
@@ -45,12 +45,16 @@
 __BEGIN_DECLS
 
 /**
- * [quotactl(2)](http://man7.org/linux/man-pages/man2/quotactl.2.html) manipulates disk quotas.
+ * [quotactl(2)](https://man7.org/linux/man-pages/man2/quotactl.2.html) manipulates disk quotas.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
  *
  * Available since API level 26.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 int quotactl(int __op, const char* _Nullable __special, int __id, char* __BIONIC_COMPLICATED_NULLNESS __addr) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 __END_DECLS
diff --git a/libc/include/sys/random.h b/libc/include/sys/random.h
index 2ff5349..23d2c3a 100644
--- a/libc/include/sys/random.h
+++ b/libc/include/sys/random.h
@@ -43,7 +43,7 @@
 __BEGIN_DECLS
 
 /**
- * [getrandom(2)](http://man7.org/linux/man-pages/man2/getrandom.2.html) fills the given buffer
+ * [getrandom(2)](https://man7.org/linux/man-pages/man2/getrandom.2.html) fills the given buffer
  * with random bytes.
  *
  * Returns the number of bytes copied on success, and returns -1 and sets `errno` on failure.
@@ -52,6 +52,10 @@
  *
  * See also arc4random_buf() which is available in all API levels.
  */
-ssize_t getrandom(void* _Nonnull __buffer, size_t __buffer_size, unsigned int __flags) __wur __INTRODUCED_IN(28);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
+__nodiscard ssize_t getrandom(void* _Nonnull __buffer, size_t __buffer_size, unsigned int __flags) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 __END_DECLS
diff --git a/libc/include/sys/reboot.h b/libc/include/sys/reboot.h
index 5d9e1a7..f4bc861 100644
--- a/libc/include/sys/reboot.h
+++ b/libc/include/sys/reboot.h
@@ -50,7 +50,7 @@
 #define RB_POWER_OFF LINUX_REBOOT_CMD_POWER_OFF
 
 /**
- * [reboot(2)](http://man7.org/linux/man-pages/man2/reboot.2.html) reboots the device.
+ * [reboot(2)](https://man7.org/linux/man-pages/man2/reboot.2.html) reboots the device.
  *
  * Does not return on successful reboot, returns 0 if CAD was successfully enabled/disabled,
  * and returns -1 and sets `errno` on failure.
diff --git a/libc/include/sys/resource.h b/libc/include/sys/resource.h
index 6743343..05ef2c2 100644
--- a/libc/include/sys/resource.h
+++ b/libc/include/sys/resource.h
@@ -54,7 +54,11 @@
 
 int getrusage(int __who, struct rusage* _Nonnull __usage);
 
+
+#if (!defined(__LP64__) && __ANDROID_API__ >= 24) || (defined(__LP64__))
 int prlimit(pid_t __pid, int __resource, const struct rlimit* _Nullable __new_limit, struct rlimit* _Nullable __old_limit) __INTRODUCED_IN_32(24) __INTRODUCED_IN_64(21);
+#endif /* (!defined(__LP64__) && __ANDROID_API__ >= 24) || (defined(__LP64__)) */
+
 int prlimit64(pid_t __pid, int __resource, const struct rlimit64* _Nullable __new_limit, struct rlimit64* _Nullable __old_limit);
 
 __END_DECLS
diff --git a/libc/include/sys/select.h b/libc/include/sys/select.h
index 84c2621..a7227b0 100644
--- a/libc/include/sys/select.h
+++ b/libc/include/sys/select.h
@@ -44,7 +44,7 @@
 typedef unsigned long fd_mask;
 
 /**
- * The limit on the largest fd that can be used with this API.
+ * The limit on the largest fd that can be used with fd_set.
  * Use <poll.h> instead.
  */
 #define FD_SETSIZE 1024
@@ -52,6 +52,9 @@
 
 /**
  * The type of a file descriptor set. Limited to 1024 fds.
+ * The underlying system calls do not have this limit,
+ * and callers can allocate their own sets with calloc().
+ *
  * Use <poll.h> instead.
  */
 typedef struct {
@@ -60,34 +63,31 @@
 
 #define __FDELT(fd) ((fd) / NFDBITS)
 #define __FDMASK(fd) (1UL << ((fd) % NFDBITS))
-#define __FDS_BITS(type,set) (__BIONIC_CAST(static_cast, type, set)->fds_bits)
-
-/* Inline loop so we don't have to declare memset. */
-#define FD_ZERO(set) \
-  do { \
-    size_t __i; \
-    for (__i = 0; __i < sizeof(fd_set)/sizeof(fd_mask); ++__i) { \
-      (set)->fds_bits[__i] = 0; \
-    } \
-  } while (0)
+#define __FDS_BITS(type, set) (__BIONIC_CAST(static_cast, type, set)->fds_bits)
 
 void __FD_CLR_chk(int, fd_set* _Nonnull , size_t);
 void __FD_SET_chk(int, fd_set* _Nonnull, size_t);
 int __FD_ISSET_chk(int, const fd_set* _Nonnull, size_t);
 
-#define __FD_CLR(fd, set) (__FDS_BITS(fd_set*,set)[__FDELT(fd)] &= ~__FDMASK(fd))
-#define __FD_SET(fd, set) (__FDS_BITS(fd_set*,set)[__FDELT(fd)] |= __FDMASK(fd))
-#define __FD_ISSET(fd, set) ((__FDS_BITS(const fd_set*,set)[__FDELT(fd)] & __FDMASK(fd)) != 0)
+/** FD_CLR() with no bounds checking for users that allocated their own set. */
+#define __FD_CLR(fd, set) (__FDS_BITS(fd_set*, set)[__FDELT(fd)] &= ~__FDMASK(fd))
+/** FD_SET() with no bounds checking for users that allocated their own set. */
+#define __FD_SET(fd, set) (__FDS_BITS(fd_set*, set)[__FDELT(fd)] |= __FDMASK(fd))
+/** FD_ISSET() with no bounds checking for users that allocated their own set. */
+#define __FD_ISSET(fd, set) ((__FDS_BITS(const fd_set*, set)[__FDELT(fd)] & __FDMASK(fd)) != 0)
 
-/** Removes `fd` from the given set. Use <poll.h> instead. */
+/** Removes all 1024 fds from the given set. Use <poll.h> instead. */
+#define FD_ZERO(set) __builtin_memset(set, 0, sizeof(*__BIONIC_CAST(static_cast, const fd_set*, set)))
+
+/** Removes `fd` from the given set. Limited to fds under 1024. Use <poll.h> instead. */
 #define FD_CLR(fd, set) __FD_CLR_chk(fd, set, __bos(set))
-/** Adds `fd` to the given set. Use <poll.h> instead. */
+/** Adds `fd` to the given set. Limited to fds under 1024. Use <poll.h> instead. */
 #define FD_SET(fd, set) __FD_SET_chk(fd, set, __bos(set))
-/** Tests whether `fd` is in the given set. Use <poll.h> instead. */
+/** Tests whether `fd` is in the given set. Limited to fds under 1024. Use <poll.h> instead. */
 #define FD_ISSET(fd, set) __FD_ISSET_chk(fd, set, __bos(set))
 
 /**
- * [select(2)](http://man7.org/linux/man-pages/man2/select.2.html) waits on a
+ * [select(2)](https://man7.org/linux/man-pages/man2/select.2.html) waits on a
  * set of file descriptors.
  *
  * Use poll() instead.
@@ -98,7 +98,7 @@
 int select(int __max_fd_plus_one, fd_set* _Nullable __read_fds, fd_set* _Nullable __write_fds, fd_set* _Nullable __exception_fds, struct timeval* _Nullable __timeout);
 
 /**
- * [pselect(2)](http://man7.org/linux/man-pages/man2/select.2.html) waits on a
+ * [pselect(2)](https://man7.org/linux/man-pages/man2/select.2.html) waits on a
  * set of file descriptors.
  *
  * Use ppoll() instead.
@@ -109,7 +109,7 @@
 int pselect(int __max_fd_plus_one, fd_set* _Nullable __read_fds, fd_set* _Nullable __write_fds, fd_set* _Nullable __exception_fds, const struct timespec* _Nullable __timeout, const sigset_t* _Nullable __mask);
 
 /**
- * [pselect64(2)](http://man7.org/linux/man-pages/man2/select.2.html) waits on a
+ * [pselect64(2)](https://man7.org/linux/man-pages/man2/select.2.html) waits on a
  * set of file descriptors.
  *
  * Use ppoll64() instead.
@@ -119,6 +119,10 @@
  *
  * Available since API level 28.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int pselect64(int __max_fd_plus_one, fd_set* _Nullable __read_fds, fd_set* _Nullable __write_fds, fd_set* _Nullable __exception_fds, const struct timespec* _Nullable __timeout, const sigset64_t* _Nullable __mask) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 __END_DECLS
diff --git a/libc/include/sys/sem.h b/libc/include/sys/sem.h
index 5682282..72f567e 100644
--- a/libc/include/sys/sem.h
+++ b/libc/include/sys/sem.h
@@ -51,12 +51,20 @@
   void* _Nullable __pad;
 };
 
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 int semctl(int __sem_id, int __sem_num, int __op, ...) __INTRODUCED_IN(26);
 int semget(key_t __key, int __sem_count, int __flags) __INTRODUCED_IN(26);
 int semop(int __sem_id, struct sembuf* _Nonnull __ops, size_t __op_count) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 #if defined(__USE_GNU)
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 int semtimedop(int __sem_id, struct sembuf* _Nonnull __ops, size_t __op_count, const struct timespec* _Nullable __timeout) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 #endif
 
 __END_DECLS
diff --git a/libc/include/sys/sendfile.h b/libc/include/sys/sendfile.h
index 26522a6..ac623e7 100644
--- a/libc/include/sys/sendfile.h
+++ b/libc/include/sys/sendfile.h
@@ -43,7 +43,7 @@
 ssize_t sendfile(int __out_fd, int __in_fd, off_t* _Nullable __offset, size_t __count) __RENAME(sendfile64);
 #else
 /**
- * [sendfile(2)](http://man7.org/linux/man-pages/man2/sendfile.2.html) copies data directly
+ * [sendfile(2)](https://man7.org/linux/man-pages/man2/sendfile.2.html) copies data directly
  * between two file descriptors.
  *
  * Returns the number of bytes copied on success, and returns -1 and sets `errno` on failure.
diff --git a/libc/include/sys/shm.h b/libc/include/sys/shm.h
index 8ab3d9a..a960781 100644
--- a/libc/include/sys/shm.h
+++ b/libc/include/sys/shm.h
@@ -48,6 +48,8 @@
 typedef unsigned long shmatt_t;
 
 /** Not useful on Android; disallowed by SELinux. */
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 void* _Nonnull shmat(int __shm_id, const void* _Nullable __addr, int __flags) __INTRODUCED_IN(26);
 /** Not useful on Android; disallowed by SELinux. */
 int shmctl(int __shm_id, int __op, struct shmid_ds* _Nullable __buf) __INTRODUCED_IN(26);
@@ -55,5 +57,7 @@
 int shmdt(const void* _Nonnull __addr) __INTRODUCED_IN(26);
 /** Not useful on Android; disallowed by SELinux. */
 int shmget(key_t __key, size_t __size, int __flags) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 __END_DECLS
diff --git a/libc/include/sys/signalfd.h b/libc/include/sys/signalfd.h
index 2be9bdc..eaea525 100644
--- a/libc/include/sys/signalfd.h
+++ b/libc/include/sys/signalfd.h
@@ -41,7 +41,7 @@
 __BEGIN_DECLS
 
 /**
- * [signalfd(2)](http://man7.org/linux/man-pages/man2/signalfd.2.html) creates/manipulates a
+ * [signalfd(2)](https://man7.org/linux/man-pages/man2/signalfd.2.html) creates/manipulates a
  * file descriptor for reading signal events.
  *
  * Returns the file descriptor on success, and returns -1 and sets `errno` on failure.
@@ -51,6 +51,10 @@
 /**
  * Like signalfd() but allows setting a signal mask with RT signals even from a 32-bit process.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int signalfd64(int __fd, const sigset64_t* _Nonnull __mask, int __flags) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 __END_DECLS
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index f916573..0b4b248 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -33,9 +33,10 @@
  * @brief File status.
  */
 
+#include <sys/cdefs.h>
+
 #include <bits/timespec.h>
 #include <linux/stat.h>
-#include <sys/cdefs.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
@@ -99,7 +100,13 @@
 
 #endif
 
+/** The file information returned by fstat()/fstatat()/lstat()/stat(). */
 struct stat { __STAT64_BODY };
+
+/**
+ * A synonym for `struct stat` on Android,
+ * provided for source compatibility with other systems.
+ */
 struct stat64 { __STAT64_BODY };
 
 #undef __STAT64_BODY
@@ -136,32 +143,153 @@
 #define S_TYPEISSHM(__sb) 0
 #define S_TYPEISTMO(__sb) 0
 
+/**
+ * [chmod(2)](https://man7.org/linux/man-pages/man2/chmod.2.html)
+ * changes the mode of a file given a path.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int chmod(const char* _Nonnull __path, mode_t __mode);
+
+/**
+ * [fchmod(2)](https://man7.org/linux/man-pages/man2/fchmod.2.html)
+ * changes the mode of a file given a file descriptor.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int fchmod(int __fd, mode_t __mode);
+
+/**
+ * [fchmodat(2)](https://man7.org/linux/man-pages/man2/fchmodat.2.html)
+ * changes the mode of a file.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
+int fchmodat(int __dir_fd, const char* _Nonnull __path, mode_t __mode, int __flags);
+
+/**
+ * [chmod(2)](https://man7.org/linux/man-pages/man2/chmod.2.html)
+ * changes the mode of a file given a path, without following symlinks.
+ *
+ * Equivalent to `fchmodat(AT_FDCWD, path, mode, AT_SYMLINK_NOFOLLOW)`.
+ *
+ * Available since API 36.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
+
+#if __BIONIC_AVAILABILITY_GUARD(36)
+int lchmod(const char* _Nonnull __path, mode_t __mode) __INTRODUCED_IN(36);
+#endif /* __BIONIC_AVAILABILITY_GUARD(36) */
+
+
+/**
+ * [mkdir(2)](https://man7.org/linux/man-pages/man2/mkdir.2.html)
+ * creates a directory.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int mkdir(const char* _Nonnull __path, mode_t __mode);
 
+/**
+ * [mkdirat(2)](https://man7.org/linux/man-pages/man2/mkdirat.2.html)
+ * creates a directory.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
+int mkdirat(int __dir_fd, const char* _Nonnull __path, mode_t __mode);
+
+/**
+ * [fstat(2)](https://man7.org/linux/man-pages/man2/fstat.2.html)
+ * gets file status given a file descriptor.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int fstat(int __fd, struct stat* _Nonnull __buf);
+
+/** An alias for fstat(). */
 int fstat64(int __fd, struct stat64* _Nonnull __buf);
+
+/**
+ * [fstatat(2)](https://man7.org/linux/man-pages/man2/fstatat.2.html)
+ * gets file status.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int fstatat(int __dir_fd, const char* _Nonnull __path, struct stat* _Nonnull __buf, int __flags);
+
+/** An alias for fstatat(). */
 int fstatat64(int __dir_fd, const char* _Nonnull __path, struct stat64* _Nonnull __buf, int __flags);
+
+/**
+ * [lstat(2)](https://man7.org/linux/man-pages/man2/lstat.2.html)
+ * gets file status given a path, without following symlinks.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int lstat(const char* _Nonnull __path, struct stat* _Nonnull __buf);
+
+/** An alias for lstat(). */
 int lstat64(const char* _Nonnull __path, struct stat64* _Nonnull __buf);
+
+/**
+ * [stat(2)](https://man7.org/linux/man-pages/man2/stat.2.html)
+ * gets file status given a path.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int stat(const char* _Nonnull __path, struct stat* _Nonnull __buf);
+
+/** An alias for stat(). */
 int stat64(const char* _Nonnull __path, struct stat64* _Nonnull __buf);
 
+/**
+ * [mknod(2)](https://man7.org/linux/man-pages/man2/mknod.2.html)
+ * creates a directory, special, or regular file.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int mknod(const char* _Nonnull __path, mode_t __mode, dev_t __dev);
+
+/**
+ * [mknodat(2)](https://man7.org/linux/man-pages/man2/mknodat.2.html)
+ * creates a directory, special, or regular file.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
+int mknodat(int __dir_fd, const char* _Nonnull __path, mode_t __mode, dev_t __dev);
+
+/**
+ * [umask(2)](https://man7.org/linux/man-pages/man2/umask.2.html)
+ * gets and sets the process-wide file mode creation mask.
+ *
+ * Returns the previous file mode creation mask.
+ */
 mode_t umask(mode_t __mask);
 
 #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
 #include <bits/fortify/stat.h>
 #endif
 
+/**
+ * [mkfifo(2)](https://man7.org/linux/man-pages/man2/mkfifo.2.html)
+ * creates a FIFO.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
 int mkfifo(const char* _Nonnull __path, mode_t __mode);
-int mkfifoat(int __dir_fd, const char* _Nonnull __path, mode_t __mode) __INTRODUCED_IN(23);
 
-int fchmodat(int __dir_fd, const char* _Nonnull __path, mode_t __mode, int __flags);
-int mkdirat(int __dir_fd, const char* _Nonnull __path, mode_t __mode);
-int mknodat(int __dir_fd, const char* _Nonnull __path, mode_t __mode, dev_t __dev);
+/**
+ * [mkfifoat(2)](https://man7.org/linux/man-pages/man2/mkfifoat.2.html)
+ * creates a FIFO.
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
+int mkfifoat(int __dir_fd, const char* _Nonnull __path, mode_t __mode) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 /**
  * Used in the tv_nsec field of an argument to utimensat()/futimens()
@@ -205,14 +333,18 @@
 
 #if defined(__USE_GNU)
 /**
- * [statx(2)](http://man7.org/linux/man-pages/man2/statx.2.html) returns
+ * [statx(2)](https://man7.org/linux/man-pages/man2/statx.2.html) returns
  * extended file status information.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
  *
  * Available since API level 30.
  */
-int statx(int __dir_fd, const char* _Nonnull __path, int __flags, unsigned __mask, struct statx* _Nonnull __buf) __INTRODUCED_IN(30);
+
+#if __BIONIC_AVAILABILITY_GUARD(30)
+int statx(int __dir_fd, const char* _Nullable __path, int __flags, unsigned __mask, struct statx* _Nonnull __buf) __INTRODUCED_IN(30);
+#endif /* __BIONIC_AVAILABILITY_GUARD(30) */
+
 #endif
 
 __END_DECLS
diff --git a/libc/include/sys/statvfs.h b/libc/include/sys/statvfs.h
index 7bc5e63..860824b 100644
--- a/libc/include/sys/statvfs.h
+++ b/libc/include/sys/statvfs.h
@@ -21,8 +21,9 @@
  * @brief Filesystem statistics.
  */
 
-#include <stdint.h>
 #include <sys/cdefs.h>
+
+#include <stdint.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
@@ -92,7 +93,7 @@
 #define ST_NOSYMFOLLOW 0x2000
 
 /**
- * [statvfs(3)](http://man7.org/linux/man-pages/man3/statvfs.3.html)
+ * [statvfs(3)](https://man7.org/linux/man-pages/man3/statvfs.3.html)
  * queries filesystem statistics for the given path.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -100,7 +101,7 @@
 int statvfs(const char* _Nonnull __path, struct statvfs* _Nonnull __buf);
 
 /**
- * [fstatvfs(3)](http://man7.org/linux/man-pages/man3/fstatvfs.3.html)
+ * [fstatvfs(3)](https://man7.org/linux/man-pages/man3/fstatvfs.3.html)
  * queries filesystem statistics for the given file descriptor.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
diff --git a/libc/include/sys/swap.h b/libc/include/sys/swap.h
index 474aed7..2aaf86e 100644
--- a/libc/include/sys/swap.h
+++ b/libc/include/sys/swap.h
@@ -52,14 +52,14 @@
 #define SWAP_FLAG_PRIO_SHIFT 0
 
 /**
- * [swapon(2)](http://man7.org/linux/man-pages/man2/swapon.2.html) enables swapping.
+ * [swapon(2)](https://man7.org/linux/man-pages/man2/swapon.2.html) enables swapping.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
  */
 int swapon(const char* _Nonnull __path,  int __flags);
 
 /**
- * [swapoff(2)](http://man7.org/linux/man-pages/man2/swapoff.2.html) disables swapping.
+ * [swapoff(2)](https://man7.org/linux/man-pages/man2/swapoff.2.html) disables swapping.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
  */
diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h
index a49323d..9341ffb 100644
--- a/libc/include/sys/syscall.h
+++ b/libc/include/sys/syscall.h
@@ -29,9 +29,10 @@
 #ifndef _SYS_SYSCALL_H_
 #define _SYS_SYSCALL_H_
 
+#include <sys/cdefs.h>
+
 #include <asm/unistd.h> /* Linux kernel __NR_* names. */
 #include <bits/glibc-syscalls.h> /* glibc-compatible SYS_* aliases. */
-#include <sys/cdefs.h>
 
 /* The syscall function itself is declared in <unistd.h>, not here. */
 
diff --git a/libc/include/sys/sysinfo.h b/libc/include/sys/sysinfo.h
index cae5c49..ed6a007 100644
--- a/libc/include/sys/sysinfo.h
+++ b/libc/include/sys/sysinfo.h
@@ -39,24 +39,26 @@
 __BEGIN_DECLS
 
 /**
- * [sysinfo(2)](http://man7.org/linux/man-pages/man2/sysinfo.2.html) queries system information.
+ * [sysinfo(2)](https://man7.org/linux/man-pages/man2/sysinfo.2.html) queries system information.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
  */
 int sysinfo(struct sysinfo* _Nonnull __info);
 
 /**
- * [get_nprocs_conf(3)](http://man7.org/linux/man-pages/man3/get_nprocs_conf.3.html) returns
+ * [get_nprocs_conf(3)](https://man7.org/linux/man-pages/man3/get_nprocs_conf.3.html) returns
  * the total number of processors in the system.
  *
  * Available since API level 23.
  *
  * See also sysconf().
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int get_nprocs_conf(void) __INTRODUCED_IN(23);
 
 /**
- * [get_nprocs(3)](http://man7.org/linux/man-pages/man3/get_nprocs.3.html) returns
+ * [get_nprocs(3)](https://man7.org/linux/man-pages/man3/get_nprocs.3.html) returns
  * the number of processors in the system that are currently on-line.
  *
  * Available since API level 23.
@@ -66,7 +68,7 @@
 int get_nprocs(void) __INTRODUCED_IN(23);
 
 /**
- * [get_phys_pages(3)](http://man7.org/linux/man-pages/man3/get_phys_pages.3.html) returns
+ * [get_phys_pages(3)](https://man7.org/linux/man-pages/man3/get_phys_pages.3.html) returns
  * the total number of physical pages in the system.
  *
  * Available since API level 23.
@@ -76,7 +78,7 @@
 long get_phys_pages(void) __INTRODUCED_IN(23);
 
 /**
- * [get_avphys_pages(3)](http://man7.org/linux/man-pages/man3/get_avphys_pages.3.html) returns
+ * [get_avphys_pages(3)](https://man7.org/linux/man-pages/man3/get_avphys_pages.3.html) returns
  * the number of physical pages in the system that are currently available.
  *
  * Available since API level 23.
@@ -84,5 +86,7 @@
  * See also sysconf().
  */
 long get_avphys_pages(void) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 __END_DECLS
diff --git a/libc/include/sys/system_properties.h b/libc/include/sys/system_properties.h
index ae94db5..1303079 100644
--- a/libc/include/sys/system_properties.h
+++ b/libc/include/sys/system_properties.h
@@ -71,9 +71,13 @@
  *
  * Available since API level 26.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 void __system_property_read_callback(const prop_info* _Nonnull __pi,
     void (* _Nonnull __callback)(void* _Nullable __cookie, const char* _Nonnull __name, const char* _Nonnull __value, uint32_t __serial),
     void* _Nullable __cookie) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 /**
  * Passes a `prop_info` for each system property to the provided
@@ -101,8 +105,12 @@
  * Available since API level 26.
  */
 struct timespec;
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 bool __system_property_wait(const prop_info* _Nullable __pi, uint32_t __old_serial, uint32_t* _Nonnull __new_serial_ptr, const struct timespec* _Nullable __relative_timeout)
     __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 /**
  * Deprecated: there's no limit on the length of a property name since
@@ -110,11 +118,140 @@
  */
 #define PROP_NAME_MAX   32
 
+/** Deprecated. Use __system_property_foreach() instead. */
+const prop_info* _Nullable __system_property_find_nth(unsigned __n);
 /** Deprecated. Use __system_property_read_callback() instead. */
 int __system_property_read(const prop_info* _Nonnull __pi, char* _Nullable __name, char* _Nonnull __value);
 /** Deprecated. Use __system_property_read_callback() instead. */
 int __system_property_get(const char* _Nonnull __name, char* _Nonnull __value);
-/** Deprecated. Use __system_property_foreach() instead. */
-const prop_info* _Nullable __system_property_find_nth(unsigned __n);
+/** Deprecated: use __system_property_wait() instead. */
+uint32_t __system_property_wait_any(uint32_t __old_serial);
+
+/**
+ * Reads the global serial number of the system properties _area_.
+ *
+ * Called to predict if a series of cached __system_property_find()
+ * objects will have seen __system_property_serial() values change.
+ * Also aids the converse, as changes in the global serial can
+ * also be used to predict if a failed __system_property_find()
+ * could in turn now find a new object; thus preventing the
+ * cycles of effort to poll __system_property_find().
+ *
+ * Typically called at beginning of a cache cycle to signal if _any_ possible
+ * changes have occurred since last. If there is, one may check each individual
+ * __system_property_serial() to confirm dirty, or __system_property_find()
+ * to check if the property now exists. If a call to __system_property_add()
+ * or __system_property_update() has completed between two calls to
+ * __system_property_area_serial() then the second call will return a larger
+ * value than the first call. Beware of race conditions as changes to the
+ * properties are not atomic, the main value of this call is to determine
+ * whether the expensive __system_property_find() is worth retrying to see if
+ * a property now exists.
+ *
+ * Returns the serial number on success, -1 on error.
+ */
+uint32_t __system_property_area_serial(void);
+
+/**
+ * Reads the serial number of a specific system property previously returned by
+ * __system_property_find(). This is a cheap way to check whether a system
+ * property has changed or not.
+ *
+ * Returns the serial number on success, -1 on error.
+ */
+uint32_t __system_property_serial(const prop_info* _Nonnull __pi);
+
+//
+// libc implementation detail.
+//
+
+/**
+ * Initializes the system properties area in read-only mode.
+ *
+ * This is called automatically during libc initialization,
+ * so user code should never need to call this.
+ *
+ * Returns 0 on success, -1 otherwise.
+ */
+int __system_properties_init(void);
+
+//
+// init implementation details.
+//
+
+#define PROP_SERVICE_NAME "property_service"
+#define PROP_SERVICE_FOR_SYSTEM_NAME "property_service_for_system"
+#define PROP_DIRNAME "/dev/__properties__"
+
+// Messages sent to init.
+#define PROP_MSG_SETPROP 1
+#define PROP_MSG_SETPROP2 0x00020001
+
+// Status codes returned by init (but not passed from libc to the caller).
+#define PROP_SUCCESS 0
+#define PROP_ERROR_READ_CMD 0x0004
+#define PROP_ERROR_READ_DATA 0x0008
+#define PROP_ERROR_READ_ONLY_PROPERTY 0x000B
+#define PROP_ERROR_INVALID_NAME 0x0010
+#define PROP_ERROR_INVALID_VALUE 0x0014
+#define PROP_ERROR_PERMISSION_DENIED 0x0018
+#define PROP_ERROR_INVALID_CMD 0x001B
+#define PROP_ERROR_HANDLE_CONTROL_MESSAGE 0x0020
+#define PROP_ERROR_SET_FAILED 0x0024
+
+/**
+ * Initializes the area to be used to store properties.
+ *
+ * Can only be done by the process that has write access to the property area,
+ * typically init.
+ *
+ * See __system_properties_init() for the equivalent for all other processes.
+ */
+int __system_property_area_init(void);
+
+/**
+ * Adds a new system property.
+ * Can only be done by the process that has write access to the property area --
+ * typically init -- which must handle sequencing to ensure that only one property is
+ * updated at a time.
+ *
+ * Returns 0 on success, -1 if the property area is full.
+ */
+int __system_property_add(const char* _Nonnull __name, unsigned int __name_length, const char* _Nonnull __value, unsigned int __value_length);
+
+/**
+ * Updates the value of a system property returned by __system_property_find().
+ * Can only be done by the process that has write access to the property area --
+ * typically init -- which must handle sequencing to ensure that only one property is
+ * updated at a time.
+ *
+ * Returns 0 on success, -1 if the parameters are incorrect.
+ */
+int __system_property_update(prop_info* _Nonnull __pi, const char* _Nonnull __value, unsigned int __value_length);
+
+/**
+ * Reloads the system properties from disk.
+ * Not intended for use by any apps except the Zygote.
+ * Should only be called from the main thread.
+ *
+ * Pointers received from functions such as __system_property_find()
+ * may be invalidated by calls to this function.
+ *
+ * Returns 0 on success, -1 otherwise.
+ *
+ * Available since API level 35.
+ */
+
+#if __BIONIC_AVAILABILITY_GUARD(35)
+int __system_properties_zygote_reload(void) __INTRODUCED_IN(35);
+#endif /* __BIONIC_AVAILABILITY_GUARD(35) */
+
+
+/**
+ * Deprecated: previously for testing, but now that SystemProperties is its own
+ * testable class, there is never a reason to call this function and its
+ * implementation simply returns -1.
+ */
+int __system_property_set_filename(const char* _Nullable __unused __filename);
 
 __END_DECLS
diff --git a/libc/include/sys/thread_properties.h b/libc/include/sys/thread_properties.h
index efd212a..b6214ee 100644
--- a/libc/include/sys/thread_properties.h
+++ b/libc/include/sys/thread_properties.h
@@ -50,6 +50,8 @@
  *
  * Available since API level 31.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(31)
 void __libc_get_static_tls_bounds(void* _Nonnull * _Nonnull __static_tls_begin,
                                   void* _Nonnull * _Nonnull __static_tls_end) __INTRODUCED_IN(31);
 
@@ -93,5 +95,7 @@
                           void* _Nonnull __dynamic_tls_end),
     void (* _Nonnull __on_destruction)(void* _Nonnull __dynamic_tls_begin,
                              void* _Nonnull __dynamic_tls_end)) __INTRODUCED_IN(31);
+#endif /* __BIONIC_AVAILABILITY_GUARD(31) */
+
 
 __END_DECLS
diff --git a/libc/include/sys/time.h b/libc/include/sys/time.h
index 6ba7a37..d12c306 100644
--- a/libc/include/sys/time.h
+++ b/libc/include/sys/time.h
@@ -47,8 +47,12 @@
 int utimes(const char* _Nonnull __path, const struct timeval __times[_Nullable 2]);
 
 #if defined(__USE_BSD)
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 int futimes(int __fd, const struct timeval __times[_Nullable 2]) __INTRODUCED_IN(26);
 int lutimes(const char* _Nonnull __path, const struct timeval __times[_Nullable 2]) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 #endif
 
 #if defined(__USE_GNU)
@@ -65,7 +69,11 @@
  *
  * Available since API level 26.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 int futimesat(int __dir_fd, const char* __BIONIC_COMPLICATED_NULLNESS __path, const struct timeval __times[_Nullable 2]) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 #endif
 
 #define timerclear(a)   \
diff --git a/libc/include/sys/timerfd.h b/libc/include/sys/timerfd.h
index de1f55b..f7f1ffa 100644
--- a/libc/include/sys/timerfd.h
+++ b/libc/include/sys/timerfd.h
@@ -33,20 +33,24 @@
  * @brief Timer file descriptors.
  */
 
-#include <fcntl.h> /* For O_CLOEXEC and O_NONBLOCK. */
-#include <time.h>
 #include <sys/cdefs.h>
+
+#include <fcntl.h>
+#include <linux/timerfd.h>
+#include <time.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
 
-/** The timerfd_create() flag for a close-on-exec file descriptor. */
-#define TFD_CLOEXEC O_CLOEXEC
-/** The timerfd_create() flag for a non-blocking file descriptor. */
-#define TFD_NONBLOCK O_NONBLOCK
+/*! \macro TFD_CLOEXEC
+ * The timerfd_create() flag for a close-on-exec file descriptor.
+ */
+/*! \macro TFD_NONBLOCK
+ * The timerfd_create() flag for a non-blocking file descriptor.
+ */
 
 /**
- * [timerfd_create(2)](http://man7.org/linux/man-pages/man2/timerfd_create.2.html) creates a
+ * [timerfd_create(2)](https://man7.org/linux/man-pages/man2/timerfd_create.2.html) creates a
  * timer file descriptor.
  *
  * Returns the new file descriptor on success, and returns -1 and sets `errno` on failure.
@@ -59,7 +63,7 @@
 #define TFD_TIMER_CANCEL_ON_SET (1 << 1)
 
 /**
- * [timerfd_settime(2)](http://man7.org/linux/man-pages/man2/timerfd_settime.2.html) starts or
+ * [timerfd_settime(2)](https://man7.org/linux/man-pages/man2/timerfd_settime.2.html) starts or
  * stops a timer.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -67,7 +71,7 @@
 int timerfd_settime(int __fd, int __flags, const struct itimerspec* _Nonnull __new_value, struct itimerspec* _Nullable __old_value);
 
 /**
- * [timerfd_gettime(2)](http://man7.org/linux/man-pages/man2/timerfd_gettime.2.html) queries the
+ * [timerfd_gettime(2)](https://man7.org/linux/man-pages/man2/timerfd_gettime.2.html) queries the
  * current timer settings.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
diff --git a/libc/include/sys/times.h b/libc/include/sys/times.h
index 8b6e91d..ac6ec18 100644
--- a/libc/include/sys/times.h
+++ b/libc/include/sys/times.h
@@ -40,7 +40,7 @@
 __BEGIN_DECLS
 
 /**
- * [times(2)](http://man7.org/linux/man-pages/man2/times.2.html) fills a buffer with the
+ * [times(2)](https://man7.org/linux/man-pages/man2/times.2.html) fills a buffer with the
  * calling process' CPU usage.
  *
  * Returns a (possibly overflowed) absolute time on success,
diff --git a/libc/include/sys/timex.h b/libc/include/sys/timex.h
index 4823edf..6fb58e4 100644
--- a/libc/include/sys/timex.h
+++ b/libc/include/sys/timex.h
@@ -40,12 +40,14 @@
 __BEGIN_DECLS
 
 /**
- * [adjtimex(2)](http://man7.org/linux/man-pages/man2/adjtimex.2.html) adjusts the kernel clock.
+ * [adjtimex(2)](https://man7.org/linux/man-pages/man2/adjtimex.2.html) adjusts the kernel clock.
  *
  * Returns the clock state on success, and returns -1 and sets `errno` on failure.
  *
  * Available since API level 24.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 int adjtimex(struct timex* _Nonnull __buf) __INTRODUCED_IN(24);
 
 /**
@@ -56,5 +58,7 @@
  * Available since API level 24.
  */
 int clock_adjtime(clockid_t __clock, struct timex* _Nonnull __tx) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 
 __END_DECLS
diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h
index 4622a4e..0446260 100644
--- a/libc/include/sys/types.h
+++ b/libc/include/sys/types.h
@@ -29,9 +29,10 @@
 #ifndef _SYS_TYPES_H_
 #define _SYS_TYPES_H_
 
+#include <sys/cdefs.h>
+
 #include <stddef.h>
 #include <stdint.h>
-#include <sys/cdefs.h>
 
 #include <linux/types.h>
 #include <linux/posix_types.h>
diff --git a/libc/include/sys/uio.h b/libc/include/sys/uio.h
index c8c64ae..eff3b14 100644
--- a/libc/include/sys/uio.h
+++ b/libc/include/sys/uio.h
@@ -40,7 +40,7 @@
 __BEGIN_DECLS
 
 /**
- * [readv(2)](http://man7.org/linux/man-pages/man2/readv.2.html) reads
+ * [readv(2)](https://man7.org/linux/man-pages/man2/readv.2.html) reads
  * from an fd into the `__count` buffers described by `__iov`.
  *
  * Returns the number of bytes read on success,
@@ -49,7 +49,7 @@
 ssize_t readv(int __fd, const struct iovec* _Nonnull __iov, int __count);
 
 /**
- * [writev(2)](http://man7.org/linux/man-pages/man2/writev.2.html) writes
+ * [writev(2)](https://man7.org/linux/man-pages/man2/writev.2.html) writes
  * to an fd from the `__count` buffers described by `__iov`.
  *
  * Returns the number of bytes written on success,
@@ -60,7 +60,7 @@
 #if defined(__USE_GNU)
 
 /**
- * [preadv(2)](http://man7.org/linux/man-pages/man2/preadv.2.html) reads
+ * [preadv(2)](https://man7.org/linux/man-pages/man2/preadv.2.html) reads
  * from an fd into the `__count` buffers described by `__iov`, starting at
  * offset `__offset` into the file.
  *
@@ -69,10 +69,12 @@
  *
  * Available since API level 24.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(24)
 ssize_t preadv(int __fd, const struct iovec* _Nonnull __iov, int __count, off_t __offset) __RENAME_IF_FILE_OFFSET64(preadv64) __INTRODUCED_IN(24);
 
 /**
- * [pwritev(2)](http://man7.org/linux/man-pages/man2/pwritev.2.html) writes
+ * [pwritev(2)](https://man7.org/linux/man-pages/man2/pwritev.2.html) writes
  * to an fd from the `__count` buffers described by `__iov`, starting at offset
  * `__offset` into the file.
  *
@@ -96,9 +98,11 @@
  * Available since API level 24.
  */
 ssize_t pwritev64(int __fd, const struct iovec* _Nonnull __iov, int __count, off64_t __offset) __INTRODUCED_IN(24);
+#endif /* __BIONIC_AVAILABILITY_GUARD(24) */
+
 
 /**
- * [preadv2(2)](http://man7.org/linux/man-pages/man2/preadv2.2.html) reads
+ * [preadv2(2)](https://man7.org/linux/man-pages/man2/preadv2.2.html) reads
  * from an fd into the `__count` buffers described by `__iov`, starting at
  * offset `__offset` into the file, with the given flags.
  *
@@ -107,10 +111,12 @@
  *
  * Available since API level 33.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(33)
 ssize_t preadv2(int __fd, const struct iovec* _Nonnull __iov, int __count, off_t __offset, int __flags) __RENAME_IF_FILE_OFFSET64(preadv64v2) __INTRODUCED_IN(33);
 
 /**
- * [pwritev2(2)](http://man7.org/linux/man-pages/man2/pwritev2.2.html) writes
+ * [pwritev2(2)](https://man7.org/linux/man-pages/man2/pwritev2.2.html) writes
  * to an fd from the `__count` buffers described by `__iov`, starting at offset
  * `__offset` into the file, with the given flags.
  *
@@ -134,9 +140,11 @@
  * Available since API level 33.
  */
 ssize_t pwritev64v2(int __fd, const struct iovec* _Nonnull __iov, int __count, off64_t __offset, int __flags) __INTRODUCED_IN(33);
+#endif /* __BIONIC_AVAILABILITY_GUARD(33) */
+
 
 /**
- * [process_vm_readv(2)](http://man7.org/linux/man-pages/man2/process_vm_readv.2.html)
+ * [process_vm_readv(2)](https://man7.org/linux/man-pages/man2/process_vm_readv.2.html)
  * reads from the address space of another process.
  *
  * Returns the number of bytes read on success,
@@ -144,10 +152,12 @@
  *
  * Available since API level 23.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 ssize_t process_vm_readv(pid_t __pid, const struct iovec* __BIONIC_COMPLICATED_NULLNESS __local_iov, unsigned long __local_iov_count, const struct iovec* __BIONIC_COMPLICATED_NULLNESS __remote_iov, unsigned long __remote_iov_count, unsigned long __flags) __INTRODUCED_IN(23);
 
 /**
- * [process_vm_writev(2)](http://man7.org/linux/man-pages/man2/process_vm_writev.2.html)
+ * [process_vm_writev(2)](https://man7.org/linux/man-pages/man2/process_vm_writev.2.html)
  * writes to the address space of another process.
  *
  * Returns the number of bytes read on success,
@@ -156,6 +166,8 @@
  * Available since API level 23.
  */
 ssize_t process_vm_writev(pid_t __pid, const struct iovec* __BIONIC_COMPLICATED_NULLNESS __local_iov, unsigned long __local_iov_count, const struct iovec* __BIONIC_COMPLICATED_NULLNESS __remote_iov, unsigned long __remote_iov_count, unsigned long __flags) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 #endif
 
diff --git a/libc/include/sys/un.h b/libc/include/sys/un.h
index 83c1d17..c2bfcb0 100644
--- a/libc/include/sys/un.h
+++ b/libc/include/sys/un.h
@@ -33,9 +33,10 @@
  * @brief Unix domain sockets.
  */
 
+#include <sys/cdefs.h>
+
 #include <bits/sa_family_t.h>
 #include <linux/un.h>
-#include <sys/cdefs.h>
 
 #if defined(__USE_BSD) || defined(__USE_GNU)
 #include <string.h>
diff --git a/libc/include/sys/utsname.h b/libc/include/sys/utsname.h
index aa8c1a0..23d1282 100644
--- a/libc/include/sys/utsname.h
+++ b/libc/include/sys/utsname.h
@@ -57,7 +57,7 @@
 };
 
 /**
- * [uname(2)](http://man7.org/linux/man-pages/man2/uname.2.html) returns information
+ * [uname(2)](https://man7.org/linux/man-pages/man2/uname.2.html) returns information
  * about the kernel.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
diff --git a/libc/include/sys/vfs.h b/libc/include/sys/vfs.h
index 3579799..5d078be 100644
--- a/libc/include/sys/vfs.h
+++ b/libc/include/sys/vfs.h
@@ -29,8 +29,9 @@
 #ifndef _SYS_VFS_H_
 #define _SYS_VFS_H_
 
-#include <stdint.h>
 #include <sys/cdefs.h>
+
+#include <stdint.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
@@ -40,6 +41,8 @@
 typedef __fsid_t fsid_t;
 
 #if defined(__LP64__)
+/* We can't just use the kernel struct statfs directly here because
+ * it's reused for both struct statfs *and* struct statfs64. */
 #define __STATFS64_BODY \
   uint64_t f_type; \
   uint64_t f_bsize; \
diff --git a/libc/include/sys/wait.h b/libc/include/sys/wait.h
index 5208366..632aa43 100644
--- a/libc/include/sys/wait.h
+++ b/libc/include/sys/wait.h
@@ -28,8 +28,9 @@
 
 #pragma once
 
-#include <bits/wait.h>
 #include <sys/cdefs.h>
+
+#include <bits/wait.h>
 #include <sys/types.h>
 #include <sys/resource.h>
 #include <linux/wait.h>
diff --git a/libc/include/sys/xattr.h b/libc/include/sys/xattr.h
index 745f50c..ebe4eb8 100644
--- a/libc/include/sys/xattr.h
+++ b/libc/include/sys/xattr.h
@@ -33,14 +33,15 @@
  * @brief Extended attribute functions.
  */
 
-#include <linux/xattr.h>
 #include <sys/cdefs.h>
+
+#include <linux/xattr.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
 
 /**
- * [fsetxattr(2)](http://man7.org/linux/man-pages/man2/fsetxattr.2.html)
+ * [fsetxattr(2)](https://man7.org/linux/man-pages/man2/fsetxattr.2.html)
  * sets an extended attribute on the file referred to by the given file
  * descriptor.
  *
@@ -55,7 +56,7 @@
 int fsetxattr(int __fd, const char* _Nonnull __name, const void* _Nullable __value, size_t __size, int __flags);
 
 /**
- * [setxattr(2)](http://man7.org/linux/man-pages/man2/setxattr.2.html)
+ * [setxattr(2)](https://man7.org/linux/man-pages/man2/setxattr.2.html)
  * sets an extended attribute on the file referred to by the given path.
  *
  * A `size` of 0 can be used to set an empty value, in which case `value` is
@@ -69,7 +70,7 @@
 int setxattr(const char* _Nonnull __path, const char* _Nonnull __name, const void* _Nullable __value, size_t __size, int __flags);
 
 /**
- * [lsetxattr(2)](http://man7.org/linux/man-pages/man2/lsetxattr.2.html)
+ * [lsetxattr(2)](https://man7.org/linux/man-pages/man2/lsetxattr.2.html)
  * sets an extended attribute on the file referred to by the given path, which
  * is the link itself rather than its target in the case of a symbolic link.
  *
@@ -84,7 +85,7 @@
 int lsetxattr(const char* _Nonnull __path, const char* _Nonnull __name, const void* _Nullable __value, size_t __size, int __flags);
 
 /**
- * [fgetxattr(2)](http://man7.org/linux/man-pages/man2/fgetxattr.2.html)
+ * [fgetxattr(2)](https://man7.org/linux/man-pages/man2/fgetxattr.2.html)
  * gets an extended attribute on the file referred to by the given file
  * descriptor.
  *
@@ -96,7 +97,7 @@
 ssize_t fgetxattr(int __fd, const char* _Nonnull __name, void* _Nullable __value, size_t __size);
 
 /**
- * [getxattr(2)](http://man7.org/linux/man-pages/man2/getxattr.2.html)
+ * [getxattr(2)](https://man7.org/linux/man-pages/man2/getxattr.2.html)
  * gets an extended attribute on the file referred to by the given path.
  *
  * A `size` of 0 can be used to query the current length, in which case `value` is ignored and may be null.
@@ -107,7 +108,7 @@
 ssize_t getxattr(const char* _Nonnull __path, const char* _Nonnull __name, void* _Nullable __value, size_t __size);
 
 /**
- * [lgetxattr(2)](http://man7.org/linux/man-pages/man2/lgetxattr.2.html)
+ * [lgetxattr(2)](https://man7.org/linux/man-pages/man2/lgetxattr.2.html)
  * gets an extended attribute on the file referred to by the given path, which
  * is the link itself rather than its target in the case of a symbolic link.
  *
@@ -119,7 +120,7 @@
 ssize_t lgetxattr(const char* _Nonnull __path, const char* _Nonnull __name, void* _Nullable __value, size_t __size);
 
 /**
- * [flistxattr(2)](http://man7.org/linux/man-pages/man2/flistxattr.2.html)
+ * [flistxattr(2)](https://man7.org/linux/man-pages/man2/flistxattr.2.html)
  * lists the extended attributes on the file referred to by the given file
  * descriptor.
  *
@@ -131,7 +132,7 @@
 ssize_t flistxattr(int __fd, char* _Nullable __list, size_t __size);
 
 /**
- * [listxattr(2)](http://man7.org/linux/man-pages/man2/listxattr.2.html)
+ * [listxattr(2)](https://man7.org/linux/man-pages/man2/listxattr.2.html)
  * lists the extended attributes on the file referred to by the given path.
  *
  * A `size` of 0 can be used to query the current length, in which case `list` is ignored and may be null.
@@ -142,7 +143,7 @@
 ssize_t listxattr(const char* _Nonnull __path, char* _Nullable __list, size_t __size);
 
 /**
- * [llistxattr(2)](http://man7.org/linux/man-pages/man2/llistxattr.2.html)
+ * [llistxattr(2)](https://man7.org/linux/man-pages/man2/llistxattr.2.html)
  * lists the extended attributes on the file referred to by the given path, which
  * is the link itself rather than its target in the case of a symbolic link.
  *
@@ -154,7 +155,7 @@
 ssize_t llistxattr(const char* _Nonnull __path, char* _Nullable __list, size_t __size);
 
 /**
- * [fremovexattr(2)](http://man7.org/linux/man-pages/man2/fremovexattr.2.html)
+ * [fremovexattr(2)](https://man7.org/linux/man-pages/man2/fremovexattr.2.html)
  * removes an extended attribute on the file referred to by the given file
  * descriptor.
  *
@@ -163,7 +164,7 @@
 int fremovexattr(int __fd, const char* _Nonnull __name);
 
 /**
- * [lremovexattr(2)](http://man7.org/linux/man-pages/man2/lremovexattr.2.html)
+ * [lremovexattr(2)](https://man7.org/linux/man-pages/man2/lremovexattr.2.html)
  * removes an extended attribute on the file referred to by the given path, which
  * is the link itself rather than its target in the case of a symbolic link.
  *
@@ -172,7 +173,7 @@
 int lremovexattr(const char* _Nonnull __path, const char* _Nonnull __name);
 
 /**
- * [removexattr(2)](http://man7.org/linux/man-pages/man2/removexattr.2.html)
+ * [removexattr(2)](https://man7.org/linux/man-pages/man2/removexattr.2.html)
  * removes an extended attribute on the file referred to by the given path.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
diff --git a/libc/include/syslog.h b/libc/include/syslog.h
index 1e2fcc4..7a594f1 100644
--- a/libc/include/syslog.h
+++ b/libc/include/syslog.h
@@ -56,8 +56,9 @@
 
 #pragma once
 
-#include <stdio.h>
 #include <sys/cdefs.h>
+
+#include <stdio.h>
 #include <stdarg.h>
 
 __BEGIN_DECLS
@@ -212,34 +213,34 @@
 #endif
 
 /**
- * [closelog(3)](http://man7.org/linux/man-pages/man3/closelog.3.html) does
+ * [closelog(3)](https://man7.org/linux/man-pages/man3/closelog.3.html) does
  * nothing on Android.
  */
 void closelog(void);
 
 /**
- * [openlog(3)](http://man7.org/linux/man-pages/man3/openlog.3.html) sets
+ * [openlog(3)](https://man7.org/linux/man-pages/man3/openlog.3.html) sets
  * the log tag to `__prefix`, which can be NULL to return to the default of
  * getprogname(). On Android, the other two arguments are ignored.
  */
 void openlog(const char* _Nullable __prefix, int __option, int __facility);
 
 /**
- * [setlogmask(3)](http://man7.org/linux/man-pages/man3/setlogmask.3.html)
+ * [setlogmask(3)](https://man7.org/linux/man-pages/man3/setlogmask.3.html)
  * sets which log priorities will actually be logged. See `LOG_MASK` and
  * `LOG_UPTO`.
  */
 int setlogmask(int __mask);
 
 /**
- * [syslog(3)](http://man7.org/linux/man-pages/man3/syslog.3.html) formats
+ * [syslog(3)](https://man7.org/linux/man-pages/man3/syslog.3.html) formats
  * the printf()-like message and logs it with the given priority, unless
  * suppressed by setlogmask(). On Android, the output goes to logcat.
  */
 void syslog(int __priority, const char* _Nonnull __fmt, ...) __printflike(2, 3);
 
 /**
- * [vsyslog(3)](http://man7.org/linux/man-pages/man3/vsyslog.3.html) formats
+ * [vsyslog(3)](https://man7.org/linux/man-pages/man3/vsyslog.3.html) formats
  * the vprintf()-like message and logs it with the given priority, unless
  * suppressed by setlogmask(). On Android, the output goes to logcat.
  */
diff --git a/libc/include/termios.h b/libc/include/termios.h
index 7abff5d..5eecfcd 100644
--- a/libc/include/termios.h
+++ b/libc/include/termios.h
@@ -46,25 +46,25 @@
 // in cfmakeraw() and cfsetspeed() until 28.
 
 /**
- * [cfgetispeed(3)](http://man7.org/linux/man-pages/man3/cfgetispeed.3.html)
+ * [cfgetispeed(3)](https://man7.org/linux/man-pages/man3/cfgetispeed.3.html)
  * returns the terminal input baud rate.
  */
 speed_t cfgetispeed(const struct termios* _Nonnull __t);
 
 /**
- * [cfgetospeed(3)](http://man7.org/linux/man-pages/man3/cfgetospeed.3.html)
+ * [cfgetospeed(3)](https://man7.org/linux/man-pages/man3/cfgetospeed.3.html)
  * returns the terminal output baud rate.
  */
 speed_t cfgetospeed(const struct termios* _Nonnull __t);
 
 /**
- * [cfmakeraw(3)](http://man7.org/linux/man-pages/man3/cfmakeraw.3.html)
+ * [cfmakeraw(3)](https://man7.org/linux/man-pages/man3/cfmakeraw.3.html)
  * configures the terminal for "raw" mode.
  */
 void cfmakeraw(struct termios* _Nonnull __t);
 
 /**
- * [cfsetspeed(3)](http://man7.org/linux/man-pages/man3/cfsetspeed.3.html)
+ * [cfsetspeed(3)](https://man7.org/linux/man-pages/man3/cfsetspeed.3.html)
  * sets the terminal input and output baud rate.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
@@ -72,7 +72,7 @@
 int cfsetspeed(struct termios* _Nonnull __t, speed_t __speed);
 
 /**
- * [cfsetispeed(3)](http://man7.org/linux/man-pages/man3/cfsetispeed.3.html)
+ * [cfsetispeed(3)](https://man7.org/linux/man-pages/man3/cfsetispeed.3.html)
  * sets the terminal input baud rate.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
@@ -80,7 +80,7 @@
 int cfsetispeed(struct termios* _Nonnull _t, speed_t __speed);
 
 /**
- * [cfsetospeed(3)](http://man7.org/linux/man-pages/man3/cfsetospeed.3.html)
+ * [cfsetospeed(3)](https://man7.org/linux/man-pages/man3/cfsetospeed.3.html)
  * sets the terminal output baud rate.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
@@ -88,7 +88,7 @@
 int cfsetospeed(struct termios* _Nonnull __t, speed_t __speed);
 
 /**
- * [tcdrain(3)](http://man7.org/linux/man-pages/man3/tcdrain.3.html)
+ * [tcdrain(3)](https://man7.org/linux/man-pages/man3/tcdrain.3.html)
  * waits until all output has been written.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
@@ -96,7 +96,7 @@
 int tcdrain(int __fd);
 
 /**
- * [tcflow(3)](http://man7.org/linux/man-pages/man3/tcflow.3.html)
+ * [tcflow(3)](https://man7.org/linux/man-pages/man3/tcflow.3.html)
  * suspends (`TCOOFF`) or resumes (`TCOON`) output, or transmits a
  * stop (`TCIOFF`) or start (`TCION`) to suspend or resume input.
  *
@@ -105,7 +105,7 @@
 int tcflow(int __fd, int __action);
 
 /**
- * [tcflush(3)](http://man7.org/linux/man-pages/man3/tcflush.3.html)
+ * [tcflush(3)](https://man7.org/linux/man-pages/man3/tcflush.3.html)
  * discards pending input (`TCIFLUSH`), output (`TCOFLUSH`), or
  * both (`TCIOFLUSH`). (In `<stdio.h>` terminology, this is a purge rather
  * than a flush.)
@@ -115,7 +115,7 @@
 int tcflush(int __fd, int __queue);
 
 /**
- * [tcgetattr(3)](http://man7.org/linux/man-pages/man3/tcgetattr.3.html)
+ * [tcgetattr(3)](https://man7.org/linux/man-pages/man3/tcgetattr.3.html)
  * reads the configuration of the given terminal.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
@@ -123,7 +123,7 @@
 int tcgetattr(int __fd, struct termios* _Nonnull __t);
 
 /**
- * [tcgetsid(3)](http://man7.org/linux/man-pages/man3/tcgetsid.3.html)
+ * [tcgetsid(3)](https://man7.org/linux/man-pages/man3/tcgetsid.3.html)
  * returns the session id corresponding to the given fd.
  *
  * Returns a non-negative session id on success and
@@ -132,7 +132,7 @@
 pid_t tcgetsid(int __fd);
 
 /**
- * [tcsendbreak(3)](http://man7.org/linux/man-pages/man3/tcsendbreak.3.html)
+ * [tcsendbreak(3)](https://man7.org/linux/man-pages/man3/tcsendbreak.3.html)
  * sends a break.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
@@ -140,7 +140,7 @@
 int tcsendbreak(int __fd, int __duration);
 
 /**
- * [tcsetattr(3)](http://man7.org/linux/man-pages/man3/tcsetattr.3.html)
+ * [tcsetattr(3)](https://man7.org/linux/man-pages/man3/tcsetattr.3.html)
  * writes the configuration of the given terminal.
  *
  * Returns 0 on success and returns -1 and sets `errno` on failure.
diff --git a/libc/include/threads.h b/libc/include/threads.h
index b1008de..1074fa4 100644
--- a/libc/include/threads.h
+++ b/libc/include/threads.h
@@ -72,8 +72,10 @@
   thrd_timedout = 4,
 };
 
-#if !defined(__cplusplus)
-#define thread_local _Thread_local
+/* `thread_local` is a keyword in C++11 and C23; C11 had `_Thread_local` instead. */
+#if !defined(__cplusplus) && (__STDC_VERSION__ >= 201112L && __STDC_VERSION__ < 202311L)
+# undef thread_local
+# define thread_local _Thread_local
 #endif
 
 __BEGIN_DECLS
diff --git a/libc/include/time.h b/libc/include/time.h
index f448851..6c9b761 100644
--- a/libc/include/time.h
+++ b/libc/include/time.h
@@ -100,7 +100,7 @@
 #define TM_ZONE tm_zone
 
 /**
- * [time(2)](http://man7.org/linux/man-pages/man2/time.2.html) returns
+ * [time(2)](https://man7.org/linux/man-pages/man2/time.2.html) returns
  * the number of seconds since the Unix epoch (1970-01-01 00:00:00 +0000).
  *
  * Returns the time in seconds on success, and returns -1 and sets `errno` on failure.
@@ -108,7 +108,7 @@
 time_t time(time_t* _Nullable __t);
 
 /**
- * [nanosleep(2)](http://man7.org/linux/man-pages/man2/nanosleep.2.html) sleeps
+ * [nanosleep(2)](https://man7.org/linux/man-pages/man2/nanosleep.2.html) sleeps
  * for at least the given time (or until a signal arrives).
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure. If the sleep
@@ -118,7 +118,7 @@
 int nanosleep(const struct timespec* _Nonnull __duration, struct timespec* _Nullable __remainder);
 
 /**
- * [asctime(3)](http://man7.org/linux/man-pages/man3/asctime.3p.html) formats
+ * [asctime(3)](https://man7.org/linux/man-pages/man3/asctime.3p.html) formats
  * the time `tm` as a string.
  *
  * Returns a pointer to a string on success, and returns NULL on failure.
@@ -130,7 +130,7 @@
 char* _Nullable asctime(const struct tm* _Nonnull __tm);
 
 /**
- * [asctime_r(3)](http://man7.org/linux/man-pages/man3/asctime_r.3p.html) formats
+ * [asctime_r(3)](https://man7.org/linux/man-pages/man3/asctime_r.3p.html) formats
  * the time `tm` as a string in the given buffer `buf`.
  *
  * Returns a pointer to a string on success, and returns NULL on failure.
@@ -140,7 +140,7 @@
 char* _Nullable asctime_r(const struct tm* _Nonnull __tm, char* _Nonnull __buf);
 
 /**
- * [difftime(3)](http://man7.org/linux/man-pages/man3/difftime.3.html) returns
+ * [difftime(3)](https://man7.org/linux/man-pages/man3/difftime.3.html) returns
  * the difference between two times.
  *
  * Returns the difference in seconds.
@@ -148,7 +148,7 @@
 double difftime(time_t __lhs, time_t __rhs);
 
 /**
- * [mktime(3)](http://man7.org/linux/man-pages/man3/mktime.3p.html) converts
+ * [mktime(3)](https://man7.org/linux/man-pages/man3/mktime.3p.html) converts
  * broken-down time `tm` into the number of seconds since the Unix epoch.
  *
  * See tzset() for details of how the timezone is set, and mktime_rz()
@@ -166,10 +166,14 @@
  *
  * Available since API level 35.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(35)
 time_t mktime_z(timezone_t _Nonnull __tz, struct tm* _Nonnull __tm) __INTRODUCED_IN(35);
+#endif /* __BIONIC_AVAILABILITY_GUARD(35) */
+
 
 /**
- * [localtime(3)](http://man7.org/linux/man-pages/man3/localtime.3p.html) converts
+ * [localtime(3)](https://man7.org/linux/man-pages/man3/localtime.3p.html) converts
  * the number of seconds since the Unix epoch in `t` to a broken-down time, taking
  * the device's timezone into account.
  *
@@ -180,7 +184,7 @@
 struct tm* _Nullable localtime(const time_t* _Nonnull __t);
 
 /**
- * [localtime_r(3)](http://man7.org/linux/man-pages/man3/localtime_r.3p.html) converts
+ * [localtime_r(3)](https://man7.org/linux/man-pages/man3/localtime_r.3p.html) converts
  * the number of seconds since the Unix epoch in `t` to a broken-down time.
  * That broken-down time will be written to the given struct `tm`.
  *
@@ -200,7 +204,11 @@
  *
  * Available since API level 35.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(35)
 struct tm* _Nullable localtime_rz(timezone_t _Nonnull __tz, const time_t* _Nonnull __t, struct tm* _Nonnull __tm) __INTRODUCED_IN(35);
+#endif /* __BIONIC_AVAILABILITY_GUARD(35) */
+
 
 /**
  * Inverse of localtime().
@@ -208,7 +216,7 @@
 time_t timelocal(struct tm* _Nonnull __tm);
 
 /**
- * [gmtime(3)](http://man7.org/linux/man-pages/man3/gmtime.3p.html) converts
+ * [gmtime(3)](https://man7.org/linux/man-pages/man3/gmtime.3p.html) converts
  * the number of seconds since the Unix epoch in `t` to a broken-down time, using
  * UTC (historically also known as GMT).
  *
@@ -219,7 +227,7 @@
 struct tm* _Nullable gmtime(const time_t* _Nonnull __t);
 
 /**
- * [gmtime_r(3)](http://man7.org/linux/man-pages/man3/gmtime_r.3p.html) converts
+ * [gmtime_r(3)](https://man7.org/linux/man-pages/man3/gmtime_r.3p.html) converts
  * the number of seconds since the Unix epoch in `t` to a broken-down time, using
  * UTC (historically also known as GMT).
  *
@@ -235,7 +243,7 @@
 time_t timegm(struct tm* _Nonnull __tm);
 
 /**
- * [strptime(3)](http://man7.org/linux/man-pages/man3/strptime.3.html) parses
+ * [strptime(3)](https://man7.org/linux/man-pages/man3/strptime.3.html) parses
  * a string `s` assuming format `fmt` into broken-down time `tm`.
  *
  * Returns a pointer to the first character _not_ parsed, or null if no characters were parsed.
@@ -245,10 +253,10 @@
 /**
  * Equivalent to strptime() on Android where only C/POSIX locales are available.
  */
-char* _Nullable strptime_l(const char* _Nonnull __s, const char* _Nonnull __fmt, struct tm* _Nonnull __tm, locale_t _Nonnull __l) __strftimelike(2) __INTRODUCED_IN(28);
+char* _Nullable strptime_l(const char* _Nonnull __s, const char* _Nonnull __fmt, struct tm* _Nonnull __tm, locale_t _Nonnull __l) __strftimelike(2) __RENAME(strptime);
 
 /**
- * [strftime(3)](http://man7.org/linux/man-pages/man3/strftime.3.html) formats
+ * [strftime(3)](https://man7.org/linux/man-pages/man3/strftime.3.html) formats
  * a broken-down time `tm` into the buffer `buf` using format `fmt`.
  *
  * Returns a pointer to the first character _not_ parsed, or null if no characters were parsed.
@@ -261,7 +269,7 @@
 size_t strftime_l(char* _Nonnull __buf, size_t __n, const char* _Nonnull __fmt, const struct tm* _Nullable __tm, locale_t _Nonnull __l) __strftimelike(3);
 
 /**
- * [ctime(3)](http://man7.org/linux/man-pages/man3/ctime.3p.html) formats
+ * [ctime(3)](https://man7.org/linux/man-pages/man3/ctime.3p.html) formats
  * the time `tm` as a string.
  *
  * Returns a pointer to a string on success, and returns NULL on failure.
@@ -273,7 +281,7 @@
 char* _Nullable ctime(const time_t* _Nonnull __t);
 
 /**
- * [ctime_r(3)](http://man7.org/linux/man-pages/man3/ctime.3p.html) formats
+ * [ctime_r(3)](https://man7.org/linux/man-pages/man3/ctime.3p.html) formats
  * the time `tm` as a string in the given buffer `buf`.
  *
  * Returns a pointer to a string on success, and returns NULL on failure.
@@ -283,7 +291,7 @@
 char* _Nullable ctime_r(const time_t* _Nonnull __t, char* _Nonnull __buf);
 
 /**
- * [tzset(3)](http://man7.org/linux/man-pages/man3/tzset.3.html) tells
+ * [tzset(3)](https://man7.org/linux/man-pages/man3/tzset.3.html) tells
  * libc that the timezone has changed.
  *
  * tzset() on Android looks at both the system property
@@ -314,6 +322,8 @@
  *
  * Available since API level 35.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(35)
 timezone_t _Nullable tzalloc(const char* _Nullable __id) __INTRODUCED_IN(35);
 
 /**
@@ -326,9 +336,11 @@
  * Available since API level 35.
  */
 void tzfree(timezone_t _Nullable __tz) __INTRODUCED_IN(35);
+#endif /* __BIONIC_AVAILABILITY_GUARD(35) */
+
 
 /**
- * [clock(3)](http://man7.org/linux/man-pages/man3/clock.3.html)
+ * [clock(3)](https://man7.org/linux/man-pages/man3/clock.3.html)
  * returns an approximation of CPU time used, equivalent to
  * `clock_gettime(CLOCK_PROCESS_CPUTIME_ID)` but with more confusing
  * units. Use `CLOCKS_PER_SEC` to convert the result to seconds.
@@ -340,15 +352,19 @@
 clock_t clock(void);
 
 /**
- * [clock_getcpuclockid(3)](http://man7.org/linux/man-pages/man3/clock_getcpuclockid.3.html)
+ * [clock_getcpuclockid(3)](https://man7.org/linux/man-pages/man3/clock_getcpuclockid.3.html)
  * gets the clock ID of the cpu-time clock for the given `pid`.
  *
  * Returns 0 on success, and returns -1 and returns an error number on failure.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int clock_getcpuclockid(pid_t __pid, clockid_t* _Nonnull __clock) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 /**
- * [clock_getres(2)](http://man7.org/linux/man-pages/man2/clock_getres.2.html)
+ * [clock_getres(2)](https://man7.org/linux/man-pages/man2/clock_getres.2.html)
  * gets the resolution of the given clock.
  *
  * Returns 0 on success, and returns -1 and returns an error number on failure.
@@ -356,7 +372,7 @@
 int clock_getres(clockid_t __clock, struct timespec* _Nullable __resolution);
 
 /**
- * [clock_gettime(2)](http://man7.org/linux/man-pages/man2/clock_gettime.2.html)
+ * [clock_gettime(2)](https://man7.org/linux/man-pages/man2/clock_gettime.2.html)
  * gets the time according to the given clock.
  *
  * Returns 0 on success, and returns -1 and returns an error number on failure.
@@ -364,7 +380,7 @@
 int clock_gettime(clockid_t __clock, struct timespec* _Nonnull __ts);
 
 /**
- * [clock_nanosleep(2)](http://man7.org/linux/man-pages/man2/clock_nanosleep.2.html)
+ * [clock_nanosleep(2)](https://man7.org/linux/man-pages/man2/clock_nanosleep.2.html)
  * sleeps for the given time (or until the given time if the TIMER_ABSTIME flag
  * is used), as measured by the given clock.
  *
@@ -375,7 +391,7 @@
 int clock_nanosleep(clockid_t __clock, int __flags, const struct timespec* _Nonnull __time, struct timespec* _Nullable __remainder);
 
 /**
- * [clock_settime(2)](http://man7.org/linux/man-pages/man2/clock_settime.2.html)
+ * [clock_settime(2)](https://man7.org/linux/man-pages/man2/clock_settime.2.html)
  * sets the time for the given clock.
  *
  * Returns 0 on success, and returns -1 and returns an error number on failure.
@@ -383,7 +399,7 @@
 int clock_settime(clockid_t __clock, const struct timespec* _Nonnull __ts);
 
 /**
- * [timer_create(2)](http://man7.org/linux/man-pages/man2/timer_create.2.html)
+ * [timer_create(2)](https://man7.org/linux/man-pages/man2/timer_create.2.html)
  * creates a POSIX timer.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -391,7 +407,7 @@
 int timer_create(clockid_t __clock, struct sigevent* _Nullable __event, timer_t _Nonnull * _Nonnull __timer_ptr);
 
 /**
- * [timer_delete(2)](http://man7.org/linux/man-pages/man2/timer_delete.2.html)
+ * [timer_delete(2)](https://man7.org/linux/man-pages/man2/timer_delete.2.html)
  * destroys a POSIX timer.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -399,7 +415,7 @@
 int timer_delete(timer_t _Nonnull __timer);
 
 /**
- * [timer_settime(2)](http://man7.org/linux/man-pages/man2/timer_settime.2.html)
+ * [timer_settime(2)](https://man7.org/linux/man-pages/man2/timer_settime.2.html)
  * starts or stops a POSIX timer.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -407,7 +423,7 @@
 int timer_settime(timer_t _Nonnull __timer, int __flags, const struct itimerspec* _Nonnull __new_value, struct itimerspec* _Nullable __old_value);
 
 /**
- * [timer_gettime(2)](http://man7.org/linux/man-pages/man2/timer_gettime.2.html)
+ * [timer_gettime(2)](https://man7.org/linux/man-pages/man2/timer_gettime.2.html)
  * gets the time until the given timer next fires.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
@@ -415,7 +431,7 @@
 int timer_gettime(timer_t _Nonnull _timer, struct itimerspec* _Nonnull __ts);
 
 /**
- * [timer_getoverrun(2)](http://man7.org/linux/man-pages/man2/timer_getoverrun.2.html)
+ * [timer_getoverrun(2)](https://man7.org/linux/man-pages/man2/timer_getoverrun.2.html)
  * gets the overrun count (the number of times the timer should have fired, but
  * didn't) for the last time the timer fired.
  *
@@ -459,7 +475,11 @@
  * Available since API level 29 for TIME_UTC; other bases arrived later.
  * Code for Android should prefer clock_gettime().
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(29)
 int timespec_get(struct timespec* _Nonnull __ts, int __base) __INTRODUCED_IN(29);
+#endif /* __BIONIC_AVAILABILITY_GUARD(29) */
+
 
 /**
  * timespec_getres(3) is equivalent to clock_getres() for the clock corresponding to the given base.
@@ -469,6 +489,10 @@
  * Available since API level 35.
  * Code for Android should prefer clock_gettime().
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(35)
 int timespec_getres(struct timespec* _Nonnull __ts, int __base) __INTRODUCED_IN(35);
+#endif /* __BIONIC_AVAILABILITY_GUARD(35) */
+
 
 __END_DECLS
diff --git a/libc/include/uchar.h b/libc/include/uchar.h
index 626372a..94efb2d 100644
--- a/libc/include/uchar.h
+++ b/libc/include/uchar.h
@@ -33,9 +33,10 @@
  * @brief Unicode functions.
  */
 
-#include <stddef.h>
 #include <sys/cdefs.h>
 
+#include <stddef.h>
+
 #include <bits/bionic_multibyte_result.h>
 #include <bits/mbstate_t.h>
 
@@ -55,7 +56,7 @@
 #define __STD_UTF_32__ 1
 
 /**
- * [c16rtomb(3)](http://man7.org/linux/man-pages/man3/c16rtomb.3.html) converts a single UTF-16
+ * [c16rtomb(3)](https://man7.org/linux/man-pages/man3/c16rtomb.3.html) converts a single UTF-16
  * character to UTF-8.
  *
  * Returns the number of bytes written to `__buf` on success, and returns -1 and sets `errno`
@@ -64,7 +65,7 @@
 size_t c16rtomb(char* _Nullable __buf, char16_t __ch16, mbstate_t* _Nullable __ps);
 
 /**
- * [c32rtomb(3)](http://man7.org/linux/man-pages/man3/c32rtomb.3.html) converts a single UTF-32
+ * [c32rtomb(3)](https://man7.org/linux/man-pages/man3/c32rtomb.3.html) converts a single UTF-32
  * character to UTF-8.
  *
  * Returns the number of bytes written to `__buf` on success, and returns -1 and sets `errno`
@@ -73,13 +74,13 @@
 size_t c32rtomb(char* _Nullable __buf, char32_t __ch32, mbstate_t* _Nullable __ps);
 
 /**
- * [mbrtoc16(3)](http://man7.org/linux/man-pages/man3/mbrtoc16.3.html) converts the next UTF-8
+ * [mbrtoc16(3)](https://man7.org/linux/man-pages/man3/mbrtoc16.3.html) converts the next UTF-8
  * sequence to a UTF-16 code point.
  */
 size_t mbrtoc16(char16_t* _Nullable __ch16, const char* _Nullable __s, size_t __n, mbstate_t* _Nullable __ps);
 
 /**
- * [mbrtoc32(3)](http://man7.org/linux/man-pages/man3/mbrtoc32.3.html) converts the next UTF-8
+ * [mbrtoc32(3)](https://man7.org/linux/man-pages/man3/mbrtoc32.3.html) converts the next UTF-8
  * sequence to a UTF-32 code point.
  */
 size_t mbrtoc32(char32_t* _Nullable __ch32, const char* _Nullable __s, size_t __n, mbstate_t* _Nullable __ps);
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 2552ca8..e623339 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -28,8 +28,9 @@
 
 #pragma once
 
-#include <stddef.h>
 #include <sys/cdefs.h>
+
+#include <stddef.h>
 #include <sys/types.h>
 #include <sys/select.h>
 
@@ -79,7 +80,7 @@
 __noreturn void _exit(int __status);
 
 /**
- * [fork(2)](http://man7.org/linux/man-pages/man2/fork.2.html) creates a new
+ * [fork(2)](https://man7.org/linux/man-pages/man2/fork.2.html) creates a new
  * process. fork() runs any handlers set by pthread_atfork().
  *
  * Returns 0 in the child, the pid of the child in the parent,
@@ -100,10 +101,14 @@
  *
  * Available since API level 35.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(35)
 pid_t _Fork(void) __INTRODUCED_IN(35);
+#endif /* __BIONIC_AVAILABILITY_GUARD(35) */
+
 
 /**
- * [vfork(2)](http://man7.org/linux/man-pages/man2/vfork.2.html) creates a new
+ * [vfork(2)](https://man7.org/linux/man-pages/man2/vfork.2.html) creates a new
  * process. vfork() differs from fork() in that it does not run any handlers
  * set by pthread_atfork(), and the parent is suspended until the child calls
  * exec() or exits.
@@ -114,7 +119,7 @@
 pid_t vfork(void) __returns_twice;
 
 /**
- * [getpid(2)](http://man7.org/linux/man-pages/man2/getpid.2.html) returns
+ * [getpid(2)](https://man7.org/linux/man-pages/man2/getpid.2.html) returns
  * the caller's process ID.
  *
  * Returns the caller's process ID.
@@ -122,7 +127,7 @@
 pid_t  getpid(void);
 
 /**
- * [gettid(2)](http://man7.org/linux/man-pages/man2/gettid.2.html) returns
+ * [gettid(2)](https://man7.org/linux/man-pages/man2/gettid.2.html) returns
  * the caller's thread ID.
  *
  * Returns the caller's thread ID.
@@ -145,12 +150,16 @@
 int execlp(const char* _Nonnull __file, const char* _Nullable __arg0, ...) __attribute__((__sentinel__));
 int execle(const char* _Nonnull __path, const char* _Nullable __arg0, ... /*,  char* const* __envp */)
     __attribute__((__sentinel__(1)));
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int fexecve(int __fd, char* _Nullable const* _Nullable __argv, char* _Nullable const* _Nullable __envp) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 int nice(int __incr);
 
 /**
- * [setegid(2)](http://man7.org/linux/man-pages/man2/setegid.2.html) sets
+ * [setegid(2)](https://man7.org/linux/man-pages/man2/setegid.2.html) sets
  * the effective group ID.
  *
  * On Android, this function only affects the calling thread, not all threads
@@ -161,7 +170,7 @@
 int setegid(gid_t __gid);
 
 /**
- * [seteuid(2)](http://man7.org/linux/man-pages/man2/seteuid.2.html) sets
+ * [seteuid(2)](https://man7.org/linux/man-pages/man2/seteuid.2.html) sets
  * the effective user ID.
  *
  * On Android, this function only affects the calling thread, not all threads
@@ -172,7 +181,7 @@
 int seteuid(uid_t __uid);
 
 /**
- * [setgid(2)](http://man7.org/linux/man-pages/man2/setgid.2.html) sets
+ * [setgid(2)](https://man7.org/linux/man-pages/man2/setgid.2.html) sets
  * the group ID.
  *
  * On Android, this function only affects the calling thread, not all threads
@@ -183,7 +192,7 @@
 int setgid(gid_t __gid);
 
 /**
- * [setregid(2)](http://man7.org/linux/man-pages/man2/setregid.2.html) sets
+ * [setregid(2)](https://man7.org/linux/man-pages/man2/setregid.2.html) sets
  * the real and effective group IDs (use -1 to leave an ID unchanged).
  *
  * On Android, this function only affects the calling thread, not all threads
@@ -194,7 +203,7 @@
 int setregid(gid_t __rgid, gid_t __egid);
 
 /**
- * [setresgid(2)](http://man7.org/linux/man-pages/man2/setresgid.2.html) sets
+ * [setresgid(2)](https://man7.org/linux/man-pages/man2/setresgid.2.html) sets
  * the real, effective, and saved group IDs (use -1 to leave an ID unchanged).
  *
  * On Android, this function only affects the calling thread, not all threads
@@ -205,7 +214,7 @@
 int setresgid(gid_t __rgid, gid_t __egid, gid_t __sgid);
 
 /**
- * [setresuid(2)](http://man7.org/linux/man-pages/man2/setresuid.2.html) sets
+ * [setresuid(2)](https://man7.org/linux/man-pages/man2/setresuid.2.html) sets
  * the real, effective, and saved user IDs (use -1 to leave an ID unchanged).
  *
  * On Android, this function only affects the calling thread, not all threads
@@ -216,7 +225,7 @@
 int setresuid(uid_t __ruid, uid_t __euid, uid_t __suid);
 
 /**
- * [setreuid(2)](http://man7.org/linux/man-pages/man2/setreuid.2.html) sets
+ * [setreuid(2)](https://man7.org/linux/man-pages/man2/setreuid.2.html) sets
  * the real and effective group IDs (use -1 to leave an ID unchanged).
  *
  * On Android, this function only affects the calling thread, not all threads
@@ -227,7 +236,7 @@
 int setreuid(uid_t __ruid, uid_t __euid);
 
 /**
- * [setuid(2)](http://man7.org/linux/man-pages/man2/setuid.2.html) sets
+ * [setuid(2)](https://man7.org/linux/man-pages/man2/setuid.2.html) sets
  * the user ID.
  *
  * On Android, this function only affects the calling thread, not all threads
@@ -246,7 +255,11 @@
 int getresuid(uid_t* _Nonnull __ruid, uid_t* _Nonnull __euid, uid_t* _Nonnull __suid);
 int getresgid(gid_t* _Nonnull __rgid, gid_t* _Nonnull __egid, gid_t* _Nonnull __sgid);
 char* _Nullable getlogin(void);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int getlogin_r(char* _Nonnull __buffer, size_t __buffer_size) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 
 long fpathconf(int __fd, int __name);
 long pathconf(const char* _Nonnull __path, int __name);
@@ -257,8 +270,29 @@
 int linkat(int __old_dir_fd, const char* _Nonnull __old_path, int __new_dir_fd, const char* _Nonnull __new_path, int __flags);
 int unlink(const char* _Nonnull __path);
 int unlinkat(int __dirfd, const char* _Nonnull __path, int __flags);
+
+/**
+ * [chdir(2)](https://man7.org/linux/man-pages/man2/chdir.2.html) changes
+ * the current working directory to the given path.
+ *
+ * This function affects all threads in the process, so is generally a bad idea
+ * on Android where most code will be running in a multi-threaded context.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
 int chdir(const char* _Nonnull __path);
+
+/**
+ * [fchdir(2)](https://man7.org/linux/man-pages/man2/chdir.2.html) changes
+ * the current working directory to the given fd.
+ *
+ * This function affects all threads in the process, so is generally a bad idea
+ * on Android where most code will be running in a multi-threaded context.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
 int fchdir(int __fd);
+
 int rmdir(const char* _Nonnull __path);
 int pipe(int __fds[_Nonnull 2]);
 #if defined(__USE_GNU)
@@ -277,7 +311,11 @@
 
 void sync(void);
 #if defined(__USE_GNU)
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 int syncfs(int __fd) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 #endif
 
 int close(int __fd);
@@ -339,7 +377,11 @@
 int usleep(useconds_t __microseconds);
 
 int gethostname(char* _Nonnull _buf, size_t __buf_size);
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int sethostname(const char* _Nonnull __name, size_t __n) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 int brk(void* _Nonnull __addr);
 void* _Nullable sbrk(ptrdiff_t __increment);
@@ -382,8 +424,12 @@
     } while (_rc == -1 && errno == EINTR); \
     _rc; })
 
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 int getdomainname(char* _Nonnull __buf, size_t __buf_size) __INTRODUCED_IN(26);
 int setdomainname(const char* _Nonnull __name, size_t __n) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 /**
  * [copy_file_range(2)](https://man7.org/linux/man-pages/man2/copy_file_range.2.html) copies
@@ -394,7 +440,11 @@
  * Returns the number of bytes copied on success, and returns -1 and sets
  * `errno` on failure.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(34)
 ssize_t copy_file_range(int __fd_in, off64_t* _Nullable __off_in, int __fd_out, off64_t* _Nullable __off_out, size_t __length, unsigned int __flags) __INTRODUCED_IN(34);
+#endif /* __BIONIC_AVAILABILITY_GUARD(34) */
+
 
 #if __ANDROID_API__ >= 28
 void swab(const void* _Nonnull __src, void* _Nonnull __dst, ssize_t __byte_count) __INTRODUCED_IN(28);
@@ -414,7 +464,11 @@
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(34)
 int close_range(unsigned int __min_fd, unsigned int __max_fd, int __flags) __INTRODUCED_IN(34);
+#endif /* __BIONIC_AVAILABILITY_GUARD(34) */
+
 
 #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
 #define _UNISTD_H_
diff --git a/libc/include/utime.h b/libc/include/utime.h
index 4d181a8..f06a028 100644
--- a/libc/include/utime.h
+++ b/libc/include/utime.h
@@ -40,7 +40,7 @@
 __BEGIN_DECLS
 
 /**
- * [utime(2)](http://man7.org/linux/man-pages/man2/utime.2.html) changes the access and
+ * [utime(2)](https://man7.org/linux/man-pages/man2/utime.2.html) changes the access and
  * modification time of `__filename`. If `__times` is null, the current time is used.
  *
  * New code should prefer utimensat().
diff --git a/libc/include/utmp.h b/libc/include/utmp.h
index d249f8a..1674491 100644
--- a/libc/include/utmp.h
+++ b/libc/include/utmp.h
@@ -131,6 +131,10 @@
  *
  * Available since API level 23.
  */
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int login_tty(int __fd) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 
 __END_DECLS
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index c4e9679..56594dc 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -58,7 +58,7 @@
 size_t mbrlen(const char* _Nullable __s, size_t __n, mbstate_t* _Nullable __ps);
 size_t mbrtowc(wchar_t* _Nullable __buf, const char* _Nullable __s, size_t __n, mbstate_t* _Nullable __ps);
 size_t mbsrtowcs(wchar_t* _Nullable __dst, const char* _Nullable * _Nonnull __src, size_t __dst_n, mbstate_t* _Nullable __ps);
-size_t mbsrtowcs_l(wchar_t* _Nullable __dst, const char* _Nullable * _Nonnull __src, size_t __dst_n, mbstate_t* _Nullable __ps, locale_t _Nonnull __l) __INTRODUCED_IN(35);
+size_t mbsrtowcs_l(wchar_t* _Nullable __dst, const char* _Nullable * _Nonnull __src, size_t __dst_n, mbstate_t* _Nullable __ps, locale_t _Nonnull __l) __RENAME(mbsrtowcs);
 size_t mbsnrtowcs(wchar_t* _Nullable __dst, const char* _Nullable * _Nullable  __src, size_t __src_n, size_t __dst_n, mbstate_t* _Nullable __ps);
 wint_t putwc(wchar_t __wc, FILE* _Nonnull __fp);
 wint_t putwchar(wchar_t __wc);
@@ -75,7 +75,11 @@
 wchar_t* _Nonnull wcpncpy(wchar_t* _Nonnull __dst, const wchar_t* _Nonnull __src, size_t __n);
 size_t wcrtomb(char* _Nullable __buf, wchar_t __wc, mbstate_t* _Nullable __ps);
 int wcscasecmp(const wchar_t* _Nonnull __lhs, const wchar_t* _Nonnull __rhs);
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int wcscasecmp_l(const wchar_t* _Nonnull __lhs, const wchar_t* _Nonnull __rhs, locale_t _Nonnull __l) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 wchar_t* _Nonnull wcscat(wchar_t* _Nonnull __dst, const wchar_t* _Nonnull __src);
 wchar_t* _Nullable wcschr(const wchar_t * _Nonnull __s, wchar_t __wc);
 int wcscmp(const wchar_t* _Nonnull __lhs, const wchar_t* _Nonnull __rhs);
@@ -83,10 +87,18 @@
 wchar_t* _Nonnull wcscpy(wchar_t* _Nonnull __dst, const wchar_t* _Nonnull __src);
 size_t wcscspn(const wchar_t* _Nonnull __s, const wchar_t* _Nonnull __accept);
 size_t wcsftime(wchar_t* _Nonnull __buf, size_t __n, const wchar_t* _Nullable __fmt, const struct tm* _Nonnull __tm);
+
+#if __BIONIC_AVAILABILITY_GUARD(28)
 size_t wcsftime_l(wchar_t* _Nonnull __buf, size_t __n, const wchar_t* _Nullable __fmt, const struct tm* _Nonnull __tm, locale_t _Nonnull __l) __INTRODUCED_IN(28);
+#endif /* __BIONIC_AVAILABILITY_GUARD(28) */
+
 size_t wcslen(const wchar_t* _Nonnull __s);
 int wcsncasecmp(const wchar_t* _Nonnull __lhs, const wchar_t* _Nonnull __rhs, size_t __n);
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 int wcsncasecmp_l(const wchar_t* _Nonnull __lhs, const wchar_t* _Nonnull __rhs, size_t __n, locale_t _Nonnull __l) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 wchar_t* _Nonnull wcsncat(wchar_t* _Nonnull __dst, const wchar_t* _Nonnull __src, size_t __n);
 int wcsncmp(const wchar_t* _Nonnull __lhs, const wchar_t* _Nonnull __rhs, size_t __n);
 wchar_t* _Nonnull wcsncpy(wchar_t* _Nonnull __dst, const wchar_t* _Nonnull __src, size_t __n);
@@ -94,20 +106,20 @@
 wchar_t* _Nullable wcspbrk(const wchar_t* _Nonnull __s, const wchar_t* _Nonnull __accept);
 wchar_t* _Nullable wcsrchr(const wchar_t* _Nonnull __s, wchar_t __wc);
 size_t wcsrtombs(char* _Nullable __dst, const wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __src, size_t __dst_n, mbstate_t* _Nullable __ps);
-size_t wcsrtombs_l(char* _Nullable __dst, const wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __src, size_t __dst_n, mbstate_t* _Nullable __ps, locale_t _Nonnull __l) __INTRODUCED_IN(35);
+size_t wcsrtombs_l(char* _Nullable __dst, const wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __src, size_t __dst_n, mbstate_t* _Nullable __ps, locale_t _Nonnull __l) __RENAME(wcsrtombs);
 size_t wcsspn(const wchar_t* _Nonnull __s, const wchar_t* _Nonnull __accept);
 wchar_t* _Nullable wcsstr(const wchar_t* _Nonnull __haystack, const wchar_t* _Nonnull __needle);
 double wcstod(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr);
-double wcstod_l(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, locale_t _Nonnull __l) __INTRODUCED_IN(28);
+double wcstod_l(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, locale_t _Nonnull __l) __RENAME(wcstod);
 float wcstof(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr);
-float wcstof_l(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, locale_t _Nonnull __l) __INTRODUCED_IN(28);
+float wcstof_l(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, locale_t _Nonnull __l) __RENAME(wcstof);
 wchar_t* _Nullable wcstok(wchar_t* _Nullable __s, const wchar_t* _Nonnull __delimiter, wchar_t* _Nonnull * _Nonnull __ptr);
 long wcstol(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, int __base);
-long wcstol_l(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, int __base, locale_t _Nonnull __l) __INTRODUCED_IN(28);
+long wcstol_l(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, int __base, locale_t _Nonnull __l) __RENAME(wcstol);
 long long wcstoll(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, int __base);
 long double wcstold(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr);
 unsigned long wcstoul(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, int __base);
-unsigned long wcstoul_l(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, int __base, locale_t _Nonnull __l) __INTRODUCED_IN(28);
+unsigned long wcstoul_l(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, int __base, locale_t _Nonnull __l) __RENAME(wcstoul);
 unsigned long long wcstoull(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, int __base);
 int wcswidth(const wchar_t* _Nonnull __s, size_t __n);
 size_t wcsxfrm(wchar_t* __BIONIC_COMPLICATED_NULLNESS __dst, const wchar_t* _Nonnull __src, size_t __n);
@@ -117,7 +129,11 @@
 int wmemcmp(const wchar_t* _Nullable __lhs, const wchar_t* _Nullable __rhs, size_t __n);
 wchar_t* _Nonnull wmemcpy(wchar_t* _Nonnull __dst, const wchar_t* _Nonnull __src, size_t __n);
 #if defined(__USE_GNU)
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 wchar_t* _Nonnull wmempcpy(wchar_t* _Nonnull __dst, const wchar_t* _Nonnull __src, size_t __n) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 #endif
 wchar_t* _Nonnull wmemmove(wchar_t* _Nonnull __dst, const wchar_t* _Nonnull __src, size_t __n);
 wchar_t* _Nonnull wmemset(wchar_t* _Nonnull __dst, wchar_t __wc, size_t __n);
@@ -133,7 +149,11 @@
 size_t wcslcat(wchar_t* _Nonnull __dst, const wchar_t* _Nonnull __src, size_t __n);
 size_t wcslcpy(wchar_t* _Nonnull __dst, const wchar_t* _Nonnull __src, size_t __n);
 
+
+#if __BIONIC_AVAILABILITY_GUARD(23)
 FILE* _Nullable open_wmemstream(wchar_t* _Nonnull * _Nonnull __ptr, size_t* _Nonnull  __size_ptr) __INTRODUCED_IN(23);
+#endif /* __BIONIC_AVAILABILITY_GUARD(23) */
+
 wchar_t* _Nullable wcsdup(const wchar_t* _Nonnull __s);
 size_t wcsnlen(const wchar_t* _Nonnull __s, size_t __n);
 
diff --git a/libc/include/wctype.h b/libc/include/wctype.h
index 4f6f81f..30ec04f 100644
--- a/libc/include/wctype.h
+++ b/libc/include/wctype.h
@@ -29,8 +29,9 @@
 #ifndef _WCTYPE_H_
 #define _WCTYPE_H_
 
-#include <bits/wctype.h>
 #include <sys/cdefs.h>
+
+#include <bits/wctype.h>
 #include <xlocale.h>
 
 __BEGIN_DECLS
@@ -51,8 +52,12 @@
 wint_t towlower_l(wint_t __wc, locale_t _Nonnull __l);
 wint_t towupper_l(wint_t __wc, locale_t _Nonnull __l);
 
+
+#if __BIONIC_AVAILABILITY_GUARD(26)
 wint_t towctrans_l(wint_t __wc, wctrans_t _Nonnull __transform, locale_t _Nonnull __l) __INTRODUCED_IN(26);
 wctrans_t _Nonnull wctrans_l(const char* _Nonnull __name, locale_t _Nonnull __l) __INTRODUCED_IN(26);
+#endif /* __BIONIC_AVAILABILITY_GUARD(26) */
+
 
 wctype_t wctype_l(const char* _Nonnull __name, locale_t _Nonnull __l);
 int iswctype_l(wint_t __wc, wctype_t __transform, locale_t _Nonnull __l);
diff --git a/libc/kernel/android/scsi/scsi/scsi.h b/libc/kernel/android/scsi/scsi/scsi.h
index 3559028..4efeada 100644
--- a/libc/kernel/android/scsi/scsi/scsi.h
+++ b/libc/kernel/android/scsi/scsi/scsi.h
@@ -7,6 +7,7 @@
 #ifndef _SCSI_SCSI_H
 #define _SCSI_SCSI_H
 #include <linux/types.h>
+#include <asm/param.h>
 #include <scsi/scsi_proto.h>
 #include <scsi/scsi_status.h>
 struct ccs_modesel_head {
diff --git a/libc/kernel/android/scsi/scsi/scsi_proto.h b/libc/kernel/android/scsi/scsi/scsi_proto.h
index d873fad..754e12a 100644
--- a/libc/kernel/android/scsi/scsi/scsi_proto.h
+++ b/libc/kernel/android/scsi/scsi/scsi_proto.h
@@ -109,6 +109,7 @@
 #define WRITE_SAME_16 0x93
 #define ZBC_OUT 0x94
 #define ZBC_IN 0x95
+#define WRITE_ATOMIC_16 0x9c
 #define SERVICE_ACTION_BIDIRECTIONAL 0x9d
 #define SERVICE_ACTION_IN_16 0x9e
 #define SERVICE_ACTION_OUT_16 0x9f
diff --git a/libc/kernel/tools/cpp.py b/libc/kernel/tools/cpp.py
index 08b786a..df50806 100755
--- a/libc/kernel/tools/cpp.py
+++ b/libc/kernel/tools/cpp.py
@@ -1430,7 +1430,7 @@
                         state = VAR_DECL
                     elif state == NORMAL and token_id in ['struct', 'typedef',
                                                           'enum', 'union',
-                                                          '__extension__']:
+                                                          '__extension__', '=']:
                         state = OTHER_DECL
                         state_token = token_id
                     elif block.tokens[i].kind == TokenKind.IDENTIFIER:
@@ -2057,7 +2057,7 @@
   struct timeval val2;
 };
 """
-        self.assertEqual(self.parse(text, {"remove": True}), expected)
+        self.assertEqual(self.parse(text, {"remove": None}), expected)
 
     def test_remove_struct_from_end(self):
         text = """\
@@ -2076,7 +2076,7 @@
   struct timeval val2;
 };
 """
-        self.assertEqual(self.parse(text, {"remove": True}), expected)
+        self.assertEqual(self.parse(text, {"remove": None}), expected)
 
     def test_remove_minimal_struct(self):
         text = """\
@@ -2084,7 +2084,7 @@
 };
 """
         expected = "";
-        self.assertEqual(self.parse(text, {"remove": True}), expected)
+        self.assertEqual(self.parse(text, {"remove": None}), expected)
 
     def test_remove_struct_with_struct_fields(self):
         text = """\
@@ -2104,7 +2104,7 @@
   struct remove val2;
 };
 """
-        self.assertEqual(self.parse(text, {"remove": True}), expected)
+        self.assertEqual(self.parse(text, {"remove": None}), expected)
 
     def test_remove_consecutive_structs(self):
         text = """\
@@ -2136,7 +2136,7 @@
   struct timeval val2;
 };
 """
-        self.assertEqual(self.parse(text, {"remove1": True, "remove2": True}), expected)
+        self.assertEqual(self.parse(text, {"remove1": None, "remove2": None}), expected)
 
     def test_remove_multiple_structs(self):
         text = """\
@@ -2169,7 +2169,7 @@
   int val;
 };
 """
-        self.assertEqual(self.parse(text, {"remove1": True, "remove2": True}), expected)
+        self.assertEqual(self.parse(text, {"remove1": None, "remove2": None}), expected)
 
     def test_remove_struct_with_inline_structs(self):
         text = """\
@@ -2194,7 +2194,7 @@
   struct timeval val2;
 };
 """
-        self.assertEqual(self.parse(text, {"remove": True}), expected)
+        self.assertEqual(self.parse(text, {"remove": None}), expected)
 
     def test_remove_struct_across_blocks(self):
         text = """\
@@ -2219,7 +2219,7 @@
   struct timeval val2;
 };
 """
-        self.assertEqual(self.parse(text, {"remove": True}), expected)
+        self.assertEqual(self.parse(text, {"remove": None}), expected)
 
     def test_remove_struct_across_blocks_multiple_structs(self):
         text = """\
@@ -2246,7 +2246,7 @@
   struct timeval val2;
 };
 """
-        self.assertEqual(self.parse(text, {"remove1": True, "remove2": True}), expected)
+        self.assertEqual(self.parse(text, {"remove1": None, "remove2": None}), expected)
 
     def test_remove_multiple_struct_and_add_includes(self):
         text = """\
@@ -2263,7 +2263,7 @@
 #include <bits/remove1.h>
 #include <bits/remove2.h>
 """
-        self.assertEqual(self.parse(text, {"remove1": False, "remove2": False}), expected)
+        self.assertEqual(self.parse(text, {"remove1": "bits/remove1.h", "remove2": "bits/remove2.h"}), expected)
 
 
 class FullPathTest(unittest.TestCase):
@@ -2580,6 +2580,71 @@
   struct timeval timeval;
   struct itimerval itimerval;
 };
+#include <linux/time.h>
+"""
+        self.assertEqual(self.parse(text), expected)
+
+    def test_var_definition(self):
+        # If we're definining the whole thing, it's probably worth keeping.
+        text = """\
+static const char *kString = "hello world";
+static const int kInteger = 42;
+"""
+        expected = """\
+static const char * kString = "hello world";
+static const int kInteger = 42;
+"""
+        self.assertEqual(self.parse(text), expected)
+
+    def test_struct_array_definition(self):
+        text = """\
+struct descriptor {
+  int args;
+  int size;
+};
+static const struct descriptor[] = {
+  {0, 0},
+  {1, 12},
+  {0, 42},
+};
+"""
+        expected = """\
+struct descriptor {
+  int args;
+  int size;
+};
+static const struct descriptor[] = {
+ {
+    0, 0
+  }
+ , {
+    1, 12
+  }
+ , {
+    0, 42
+  }
+ ,
+};
+"""
+        self.assertEqual(self.parse(text), expected)
+
+    def test_array_definition(self):
+        text = """\
+static const char *arr[] = {
+  "foo",
+  "bar",
+  "baz",
+};
+
+static int another_arr[5] = { 1, 2, 3, 4, 5};
+"""
+        expected = """\
+static const char * arr[] = {
+  "foo", "bar", "baz",
+};
+static int another_arr[5] = {
+  1, 2, 3, 4, 5
+};
 """
         self.assertEqual(self.parse(text), expected)
 
diff --git a/libc/kernel/tools/defaults.py b/libc/kernel/tools/defaults.py
index 06afb25..2994e5e 100644
--- a/libc/kernel/tools/defaults.py
+++ b/libc/kernel/tools/defaults.py
@@ -25,6 +25,23 @@
     # Otherwise, there will be two struct timeval definitions when
     # __kernel_old_timeval is renamed to timeval.
     "__kernel_old_timeval": "1",
+    # Drop the custom byte swap functions and just use the clang builtins.
+    # https://github.com/android/ndk/issues/2107
+    "__arch_swab16": kCppUndefinedMacro,
+    "__arch_swab16p": kCppUndefinedMacro,
+    "__arch_swab16s": kCppUndefinedMacro,
+    "__arch_swab32": kCppUndefinedMacro,
+    "__arch_swab32p": kCppUndefinedMacro,
+    "__arch_swab32s": kCppUndefinedMacro,
+    "__arch_swab64": kCppUndefinedMacro,
+    "__arch_swab64p": kCppUndefinedMacro,
+    "__arch_swab64s": kCppUndefinedMacro,
+    "__arch_swahb32": kCppUndefinedMacro,
+    "__arch_swahb32p": kCppUndefinedMacro,
+    "__arch_swahb32s": kCppUndefinedMacro,
+    "__arch_swahw32": kCppUndefinedMacro,
+    "__arch_swahw32p": kCppUndefinedMacro,
+    "__arch_swahw32s": kCppUndefinedMacro,
     }
 
 # This is the set of known kernel data structures we want to remove from
diff --git a/libc/kernel/tools/update_all.py b/libc/kernel/tools/update_all.py
index ae89a80..331a957 100755
--- a/libc/kernel/tools/update_all.py
+++ b/libc/kernel/tools/update_all.py
@@ -88,15 +88,8 @@
     # Collect the set of all syscalls for all architectures.
     syscalls = set()
     pattern = re.compile(r'^\s*#\s*define\s*__NR_([a-z_]\S+)')
-    for unistd_h in ['kernel/uapi/asm-generic/unistd.h',
-                     'kernel/uapi/asm-arm/asm/unistd.h',
-                     'kernel/uapi/asm-arm/asm/unistd-eabi.h',
-                     'kernel/uapi/asm-arm/asm/unistd-oabi.h',
-                     'kernel/uapi/asm-riscv/asm/unistd.h',
-                     'kernel/uapi/asm-x86/asm/unistd_32.h',
-                     'kernel/uapi/asm-x86/asm/unistd_64.h',
-                     'kernel/uapi/asm-x86/asm/unistd_x32.h']:
-        for line in open(os.path.join(libc_root, unistd_h)):
+    for unistd_h in glob.glob('%s/kernel/uapi/asm-*/asm/unistd*.h' % libc_root):
+        for line in open(unistd_h):
             m = re.search(pattern, line)
             if m:
                 nr_name = m.group(1)
diff --git a/libc/kernel/uapi/asm-arm/asm/unistd-eabi.h b/libc/kernel/uapi/asm-arm/asm/unistd-eabi.h
index 1032131..9c4e459 100644
--- a/libc/kernel/uapi/asm-arm/asm/unistd-eabi.h
+++ b/libc/kernel/uapi/asm-arm/asm/unistd-eabi.h
@@ -420,4 +420,5 @@
 #define __NR_lsm_get_self_attr (__NR_SYSCALL_BASE + 459)
 #define __NR_lsm_set_self_attr (__NR_SYSCALL_BASE + 460)
 #define __NR_lsm_list_modules (__NR_SYSCALL_BASE + 461)
+#define __NR_mseal (__NR_SYSCALL_BASE + 462)
 #endif
diff --git a/libc/kernel/uapi/asm-arm/asm/unistd-oabi.h b/libc/kernel/uapi/asm-arm/asm/unistd-oabi.h
index 1f57604..5060c2f 100644
--- a/libc/kernel/uapi/asm-arm/asm/unistd-oabi.h
+++ b/libc/kernel/uapi/asm-arm/asm/unistd-oabi.h
@@ -432,4 +432,5 @@
 #define __NR_lsm_get_self_attr (__NR_SYSCALL_BASE + 459)
 #define __NR_lsm_set_self_attr (__NR_SYSCALL_BASE + 460)
 #define __NR_lsm_list_modules (__NR_SYSCALL_BASE + 461)
+#define __NR_mseal (__NR_SYSCALL_BASE + 462)
 #endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/unistd.h b/libc/kernel/uapi/asm-arm64/asm/unistd.h
index 7457ebc..178578f 100644
--- a/libc/kernel/uapi/asm-arm64/asm/unistd.h
+++ b/libc/kernel/uapi/asm-arm64/asm/unistd.h
@@ -4,10 +4,4 @@
  * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
  * for more information.
  */
-#define __ARCH_WANT_RENAMEAT
-#define __ARCH_WANT_NEW_STAT
-#define __ARCH_WANT_SET_GET_RLIMIT
-#define __ARCH_WANT_TIME32_SYSCALLS
-#define __ARCH_WANT_SYS_CLONE3
-#define __ARCH_WANT_MEMFD_SECRET
-#include <asm-generic/unistd.h>
+#include <asm/unistd_64.h>
diff --git a/libc/kernel/uapi/asm-arm64/asm/unistd_64.h b/libc/kernel/uapi/asm-arm64/asm/unistd_64.h
new file mode 100644
index 0000000..0a0a1c0
--- /dev/null
+++ b/libc/kernel/uapi/asm-arm64/asm/unistd_64.h
@@ -0,0 +1,327 @@
+/*
+ * This file is auto-generated. Modifications will be lost.
+ *
+ * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
+ * for more information.
+ */
+#ifndef _UAPI_ASM_UNISTD_64_H
+#define _UAPI_ASM_UNISTD_64_H
+#define __NR_io_setup 0
+#define __NR_io_destroy 1
+#define __NR_io_submit 2
+#define __NR_io_cancel 3
+#define __NR_io_getevents 4
+#define __NR_setxattr 5
+#define __NR_lsetxattr 6
+#define __NR_fsetxattr 7
+#define __NR_getxattr 8
+#define __NR_lgetxattr 9
+#define __NR_fgetxattr 10
+#define __NR_listxattr 11
+#define __NR_llistxattr 12
+#define __NR_flistxattr 13
+#define __NR_removexattr 14
+#define __NR_lremovexattr 15
+#define __NR_fremovexattr 16
+#define __NR_getcwd 17
+#define __NR_lookup_dcookie 18
+#define __NR_eventfd2 19
+#define __NR_epoll_create1 20
+#define __NR_epoll_ctl 21
+#define __NR_epoll_pwait 22
+#define __NR_dup 23
+#define __NR_dup3 24
+#define __NR_fcntl 25
+#define __NR_inotify_init1 26
+#define __NR_inotify_add_watch 27
+#define __NR_inotify_rm_watch 28
+#define __NR_ioctl 29
+#define __NR_ioprio_set 30
+#define __NR_ioprio_get 31
+#define __NR_flock 32
+#define __NR_mknodat 33
+#define __NR_mkdirat 34
+#define __NR_unlinkat 35
+#define __NR_symlinkat 36
+#define __NR_linkat 37
+#define __NR_renameat 38
+#define __NR_umount2 39
+#define __NR_mount 40
+#define __NR_pivot_root 41
+#define __NR_nfsservctl 42
+#define __NR_statfs 43
+#define __NR_fstatfs 44
+#define __NR_truncate 45
+#define __NR_ftruncate 46
+#define __NR_fallocate 47
+#define __NR_faccessat 48
+#define __NR_chdir 49
+#define __NR_fchdir 50
+#define __NR_chroot 51
+#define __NR_fchmod 52
+#define __NR_fchmodat 53
+#define __NR_fchownat 54
+#define __NR_fchown 55
+#define __NR_openat 56
+#define __NR_close 57
+#define __NR_vhangup 58
+#define __NR_pipe2 59
+#define __NR_quotactl 60
+#define __NR_getdents64 61
+#define __NR_lseek 62
+#define __NR_read 63
+#define __NR_write 64
+#define __NR_readv 65
+#define __NR_writev 66
+#define __NR_pread64 67
+#define __NR_pwrite64 68
+#define __NR_preadv 69
+#define __NR_pwritev 70
+#define __NR_sendfile 71
+#define __NR_pselect6 72
+#define __NR_ppoll 73
+#define __NR_signalfd4 74
+#define __NR_vmsplice 75
+#define __NR_splice 76
+#define __NR_tee 77
+#define __NR_readlinkat 78
+#define __NR_newfstatat 79
+#define __NR_fstat 80
+#define __NR_sync 81
+#define __NR_fsync 82
+#define __NR_fdatasync 83
+#define __NR_sync_file_range 84
+#define __NR_timerfd_create 85
+#define __NR_timerfd_settime 86
+#define __NR_timerfd_gettime 87
+#define __NR_utimensat 88
+#define __NR_acct 89
+#define __NR_capget 90
+#define __NR_capset 91
+#define __NR_personality 92
+#define __NR_exit 93
+#define __NR_exit_group 94
+#define __NR_waitid 95
+#define __NR_set_tid_address 96
+#define __NR_unshare 97
+#define __NR_futex 98
+#define __NR_set_robust_list 99
+#define __NR_get_robust_list 100
+#define __NR_nanosleep 101
+#define __NR_getitimer 102
+#define __NR_setitimer 103
+#define __NR_kexec_load 104
+#define __NR_init_module 105
+#define __NR_delete_module 106
+#define __NR_timer_create 107
+#define __NR_timer_gettime 108
+#define __NR_timer_getoverrun 109
+#define __NR_timer_settime 110
+#define __NR_timer_delete 111
+#define __NR_clock_settime 112
+#define __NR_clock_gettime 113
+#define __NR_clock_getres 114
+#define __NR_clock_nanosleep 115
+#define __NR_syslog 116
+#define __NR_ptrace 117
+#define __NR_sched_setparam 118
+#define __NR_sched_setscheduler 119
+#define __NR_sched_getscheduler 120
+#define __NR_sched_getparam 121
+#define __NR_sched_setaffinity 122
+#define __NR_sched_getaffinity 123
+#define __NR_sched_yield 124
+#define __NR_sched_get_priority_max 125
+#define __NR_sched_get_priority_min 126
+#define __NR_sched_rr_get_interval 127
+#define __NR_restart_syscall 128
+#define __NR_kill 129
+#define __NR_tkill 130
+#define __NR_tgkill 131
+#define __NR_sigaltstack 132
+#define __NR_rt_sigsuspend 133
+#define __NR_rt_sigaction 134
+#define __NR_rt_sigprocmask 135
+#define __NR_rt_sigpending 136
+#define __NR_rt_sigtimedwait 137
+#define __NR_rt_sigqueueinfo 138
+#define __NR_rt_sigreturn 139
+#define __NR_setpriority 140
+#define __NR_getpriority 141
+#define __NR_reboot 142
+#define __NR_setregid 143
+#define __NR_setgid 144
+#define __NR_setreuid 145
+#define __NR_setuid 146
+#define __NR_setresuid 147
+#define __NR_getresuid 148
+#define __NR_setresgid 149
+#define __NR_getresgid 150
+#define __NR_setfsuid 151
+#define __NR_setfsgid 152
+#define __NR_times 153
+#define __NR_setpgid 154
+#define __NR_getpgid 155
+#define __NR_getsid 156
+#define __NR_setsid 157
+#define __NR_getgroups 158
+#define __NR_setgroups 159
+#define __NR_uname 160
+#define __NR_sethostname 161
+#define __NR_setdomainname 162
+#define __NR_getrlimit 163
+#define __NR_setrlimit 164
+#define __NR_getrusage 165
+#define __NR_umask 166
+#define __NR_prctl 167
+#define __NR_getcpu 168
+#define __NR_gettimeofday 169
+#define __NR_settimeofday 170
+#define __NR_adjtimex 171
+#define __NR_getpid 172
+#define __NR_getppid 173
+#define __NR_getuid 174
+#define __NR_geteuid 175
+#define __NR_getgid 176
+#define __NR_getegid 177
+#define __NR_gettid 178
+#define __NR_sysinfo 179
+#define __NR_mq_open 180
+#define __NR_mq_unlink 181
+#define __NR_mq_timedsend 182
+#define __NR_mq_timedreceive 183
+#define __NR_mq_notify 184
+#define __NR_mq_getsetattr 185
+#define __NR_msgget 186
+#define __NR_msgctl 187
+#define __NR_msgrcv 188
+#define __NR_msgsnd 189
+#define __NR_semget 190
+#define __NR_semctl 191
+#define __NR_semtimedop 192
+#define __NR_semop 193
+#define __NR_shmget 194
+#define __NR_shmctl 195
+#define __NR_shmat 196
+#define __NR_shmdt 197
+#define __NR_socket 198
+#define __NR_socketpair 199
+#define __NR_bind 200
+#define __NR_listen 201
+#define __NR_accept 202
+#define __NR_connect 203
+#define __NR_getsockname 204
+#define __NR_getpeername 205
+#define __NR_sendto 206
+#define __NR_recvfrom 207
+#define __NR_setsockopt 208
+#define __NR_getsockopt 209
+#define __NR_shutdown 210
+#define __NR_sendmsg 211
+#define __NR_recvmsg 212
+#define __NR_readahead 213
+#define __NR_brk 214
+#define __NR_munmap 215
+#define __NR_mremap 216
+#define __NR_add_key 217
+#define __NR_request_key 218
+#define __NR_keyctl 219
+#define __NR_clone 220
+#define __NR_execve 221
+#define __NR_mmap 222
+#define __NR_fadvise64 223
+#define __NR_swapon 224
+#define __NR_swapoff 225
+#define __NR_mprotect 226
+#define __NR_msync 227
+#define __NR_mlock 228
+#define __NR_munlock 229
+#define __NR_mlockall 230
+#define __NR_munlockall 231
+#define __NR_mincore 232
+#define __NR_madvise 233
+#define __NR_remap_file_pages 234
+#define __NR_mbind 235
+#define __NR_get_mempolicy 236
+#define __NR_set_mempolicy 237
+#define __NR_migrate_pages 238
+#define __NR_move_pages 239
+#define __NR_rt_tgsigqueueinfo 240
+#define __NR_perf_event_open 241
+#define __NR_accept4 242
+#define __NR_recvmmsg 243
+#define __NR_wait4 260
+#define __NR_prlimit64 261
+#define __NR_fanotify_init 262
+#define __NR_fanotify_mark 263
+#define __NR_name_to_handle_at 264
+#define __NR_open_by_handle_at 265
+#define __NR_clock_adjtime 266
+#define __NR_syncfs 267
+#define __NR_setns 268
+#define __NR_sendmmsg 269
+#define __NR_process_vm_readv 270
+#define __NR_process_vm_writev 271
+#define __NR_kcmp 272
+#define __NR_finit_module 273
+#define __NR_sched_setattr 274
+#define __NR_sched_getattr 275
+#define __NR_renameat2 276
+#define __NR_seccomp 277
+#define __NR_getrandom 278
+#define __NR_memfd_create 279
+#define __NR_bpf 280
+#define __NR_execveat 281
+#define __NR_userfaultfd 282
+#define __NR_membarrier 283
+#define __NR_mlock2 284
+#define __NR_copy_file_range 285
+#define __NR_preadv2 286
+#define __NR_pwritev2 287
+#define __NR_pkey_mprotect 288
+#define __NR_pkey_alloc 289
+#define __NR_pkey_free 290
+#define __NR_statx 291
+#define __NR_io_pgetevents 292
+#define __NR_rseq 293
+#define __NR_kexec_file_load 294
+#define __NR_pidfd_send_signal 424
+#define __NR_io_uring_setup 425
+#define __NR_io_uring_enter 426
+#define __NR_io_uring_register 427
+#define __NR_open_tree 428
+#define __NR_move_mount 429
+#define __NR_fsopen 430
+#define __NR_fsconfig 431
+#define __NR_fsmount 432
+#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
+#define __NR_close_range 436
+#define __NR_openat2 437
+#define __NR_pidfd_getfd 438
+#define __NR_faccessat2 439
+#define __NR_process_madvise 440
+#define __NR_epoll_pwait2 441
+#define __NR_mount_setattr 442
+#define __NR_quotactl_fd 443
+#define __NR_landlock_create_ruleset 444
+#define __NR_landlock_add_rule 445
+#define __NR_landlock_restrict_self 446
+#define __NR_memfd_secret 447
+#define __NR_process_mrelease 448
+#define __NR_futex_waitv 449
+#define __NR_set_mempolicy_home_node 450
+#define __NR_cachestat 451
+#define __NR_fchmodat2 452
+#define __NR_map_shadow_stack 453
+#define __NR_futex_wake 454
+#define __NR_futex_wait 455
+#define __NR_futex_requeue 456
+#define __NR_statmount 457
+#define __NR_listmount 458
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_set_self_attr 460
+#define __NR_lsm_list_modules 461
+#define __NR_mseal 462
+#endif
diff --git a/libc/kernel/uapi/asm-generic/unistd.h b/libc/kernel/uapi/asm-generic/unistd.h
index c882751..652e7a2 100644
--- a/libc/kernel/uapi/asm-generic/unistd.h
+++ b/libc/kernel/uapi/asm-generic/unistd.h
@@ -381,9 +381,7 @@
 #define __NR_fsmount 432
 #define __NR_fspick 433
 #define __NR_pidfd_open 434
-#ifdef __ARCH_WANT_SYS_CLONE3
 #define __NR_clone3 435
-#endif
 #define __NR_close_range 436
 #define __NR_openat2 437
 #define __NR_pidfd_getfd 438
@@ -412,8 +410,9 @@
 #define __NR_lsm_get_self_attr 459
 #define __NR_lsm_set_self_attr 460
 #define __NR_lsm_list_modules 461
+#define __NR_mseal 462
 #undef __NR_syscalls
-#define __NR_syscalls 462
+#define __NR_syscalls 463
 #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-riscv/asm/hwprobe.h b/libc/kernel/uapi/asm-riscv/asm/hwprobe.h
index 5c82561..2e5f9a4 100644
--- a/libc/kernel/uapi/asm-riscv/asm/hwprobe.h
+++ b/libc/kernel/uapi/asm-riscv/asm/hwprobe.h
@@ -53,6 +53,19 @@
 #define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33)
 #define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34)
 #define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35)
+#define RISCV_HWPROBE_EXT_ZIHINTPAUSE (1ULL << 36)
+#define RISCV_HWPROBE_EXT_ZVE32X (1ULL << 37)
+#define RISCV_HWPROBE_EXT_ZVE32F (1ULL << 38)
+#define RISCV_HWPROBE_EXT_ZVE64X (1ULL << 39)
+#define RISCV_HWPROBE_EXT_ZVE64F (1ULL << 40)
+#define RISCV_HWPROBE_EXT_ZVE64D (1ULL << 41)
+#define RISCV_HWPROBE_EXT_ZIMOP (1ULL << 42)
+#define RISCV_HWPROBE_EXT_ZCA (1ULL << 43)
+#define RISCV_HWPROBE_EXT_ZCB (1ULL << 44)
+#define RISCV_HWPROBE_EXT_ZCD (1ULL << 45)
+#define RISCV_HWPROBE_EXT_ZCF (1ULL << 46)
+#define RISCV_HWPROBE_EXT_ZCMOP (1ULL << 47)
+#define RISCV_HWPROBE_EXT_ZAWRS (1ULL << 48)
 #define RISCV_HWPROBE_KEY_CPUPERF_0 5
 #define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
 #define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0)
@@ -61,5 +74,13 @@
 #define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0)
 #define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0)
 #define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6
+#define RISCV_HWPROBE_KEY_HIGHEST_VIRT_ADDRESS 7
+#define RISCV_HWPROBE_KEY_TIME_CSR_FREQ 8
+#define RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF 9
+#define RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN 0
+#define RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED 1
+#define RISCV_HWPROBE_MISALIGNED_SCALAR_SLOW 2
+#define RISCV_HWPROBE_MISALIGNED_SCALAR_FAST 3
+#define RISCV_HWPROBE_MISALIGNED_SCALAR_UNSUPPORTED 4
 #define RISCV_HWPROBE_WHICH_CPUS (1 << 0)
 #endif
diff --git a/libc/kernel/uapi/asm-riscv/asm/kvm.h b/libc/kernel/uapi/asm-riscv/asm/kvm.h
index 4c759ed..51f4977 100644
--- a/libc/kernel/uapi/asm-riscv/asm/kvm.h
+++ b/libc/kernel/uapi/asm-riscv/asm/kvm.h
@@ -127,6 +127,14 @@
   KVM_RISCV_ISA_EXT_ZFA,
   KVM_RISCV_ISA_EXT_ZTSO,
   KVM_RISCV_ISA_EXT_ZACAS,
+  KVM_RISCV_ISA_EXT_SSCOFPMF,
+  KVM_RISCV_ISA_EXT_ZIMOP,
+  KVM_RISCV_ISA_EXT_ZCA,
+  KVM_RISCV_ISA_EXT_ZCB,
+  KVM_RISCV_ISA_EXT_ZCD,
+  KVM_RISCV_ISA_EXT_ZCF,
+  KVM_RISCV_ISA_EXT_ZCMOP,
+  KVM_RISCV_ISA_EXT_ZAWRS,
   KVM_RISCV_ISA_EXT_MAX,
 };
 enum KVM_RISCV_SBI_EXT_ID {
diff --git a/libc/kernel/uapi/asm-riscv/asm/unistd.h b/libc/kernel/uapi/asm-riscv/asm/unistd.h
index 0c58887..f395f71 100644
--- a/libc/kernel/uapi/asm-riscv/asm/unistd.h
+++ b/libc/kernel/uapi/asm-riscv/asm/unistd.h
@@ -4,18 +4,9 @@
  * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
  * for more information.
  */
-#if defined(__LP64__) && !defined(__SYSCALL_COMPAT)
-#define __ARCH_WANT_NEW_STAT
-#define __ARCH_WANT_SET_GET_RLIMIT
+#include <asm/bitsperlong.h>
+#if __BITS_PER_LONG == 64
+#include <asm/unistd_64.h>
+#else
+#include <asm/unistd_32.h>
 #endif
-#define __ARCH_WANT_SYS_CLONE3
-#define __ARCH_WANT_MEMFD_SECRET
-#include <asm-generic/unistd.h>
-#ifndef __NR_riscv_flush_icache
-#define __NR_riscv_flush_icache (__NR_arch_specific_syscall + 15)
-#endif
-__SYSCALL(__NR_riscv_flush_icache, sys_riscv_flush_icache)
-#ifndef __NR_riscv_hwprobe
-#define __NR_riscv_hwprobe (__NR_arch_specific_syscall + 14)
-#endif
-__SYSCALL(__NR_riscv_hwprobe, sys_riscv_hwprobe)
diff --git a/libc/kernel/uapi/asm-riscv/asm/unistd_32.h b/libc/kernel/uapi/asm-riscv/asm/unistd_32.h
new file mode 100644
index 0000000..864a556
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/unistd_32.h
@@ -0,0 +1,318 @@
+/*
+ * This file is auto-generated. Modifications will be lost.
+ *
+ * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
+ * for more information.
+ */
+#ifndef _UAPI_ASM_UNISTD_32_H
+#define _UAPI_ASM_UNISTD_32_H
+#define __NR_io_setup 0
+#define __NR_io_destroy 1
+#define __NR_io_submit 2
+#define __NR_io_cancel 3
+#define __NR_setxattr 5
+#define __NR_lsetxattr 6
+#define __NR_fsetxattr 7
+#define __NR_getxattr 8
+#define __NR_lgetxattr 9
+#define __NR_fgetxattr 10
+#define __NR_listxattr 11
+#define __NR_llistxattr 12
+#define __NR_flistxattr 13
+#define __NR_removexattr 14
+#define __NR_lremovexattr 15
+#define __NR_fremovexattr 16
+#define __NR_getcwd 17
+#define __NR_lookup_dcookie 18
+#define __NR_eventfd2 19
+#define __NR_epoll_create1 20
+#define __NR_epoll_ctl 21
+#define __NR_epoll_pwait 22
+#define __NR_dup 23
+#define __NR_dup3 24
+#define __NR_fcntl64 25
+#define __NR_inotify_init1 26
+#define __NR_inotify_add_watch 27
+#define __NR_inotify_rm_watch 28
+#define __NR_ioctl 29
+#define __NR_ioprio_set 30
+#define __NR_ioprio_get 31
+#define __NR_flock 32
+#define __NR_mknodat 33
+#define __NR_mkdirat 34
+#define __NR_unlinkat 35
+#define __NR_symlinkat 36
+#define __NR_linkat 37
+#define __NR_umount2 39
+#define __NR_mount 40
+#define __NR_pivot_root 41
+#define __NR_nfsservctl 42
+#define __NR_statfs64 43
+#define __NR_fstatfs64 44
+#define __NR_truncate64 45
+#define __NR_ftruncate64 46
+#define __NR_fallocate 47
+#define __NR_faccessat 48
+#define __NR_chdir 49
+#define __NR_fchdir 50
+#define __NR_chroot 51
+#define __NR_fchmod 52
+#define __NR_fchmodat 53
+#define __NR_fchownat 54
+#define __NR_fchown 55
+#define __NR_openat 56
+#define __NR_close 57
+#define __NR_vhangup 58
+#define __NR_pipe2 59
+#define __NR_quotactl 60
+#define __NR_getdents64 61
+#define __NR_llseek 62
+#define __NR_read 63
+#define __NR_write 64
+#define __NR_readv 65
+#define __NR_writev 66
+#define __NR_pread64 67
+#define __NR_pwrite64 68
+#define __NR_preadv 69
+#define __NR_pwritev 70
+#define __NR_sendfile64 71
+#define __NR_signalfd4 74
+#define __NR_vmsplice 75
+#define __NR_splice 76
+#define __NR_tee 77
+#define __NR_readlinkat 78
+#define __NR_sync 81
+#define __NR_fsync 82
+#define __NR_fdatasync 83
+#define __NR_sync_file_range 84
+#define __NR_timerfd_create 85
+#define __NR_acct 89
+#define __NR_capget 90
+#define __NR_capset 91
+#define __NR_personality 92
+#define __NR_exit 93
+#define __NR_exit_group 94
+#define __NR_waitid 95
+#define __NR_set_tid_address 96
+#define __NR_unshare 97
+#define __NR_set_robust_list 99
+#define __NR_get_robust_list 100
+#define __NR_getitimer 102
+#define __NR_setitimer 103
+#define __NR_kexec_load 104
+#define __NR_init_module 105
+#define __NR_delete_module 106
+#define __NR_timer_create 107
+#define __NR_timer_getoverrun 109
+#define __NR_timer_delete 111
+#define __NR_syslog 116
+#define __NR_ptrace 117
+#define __NR_sched_setparam 118
+#define __NR_sched_setscheduler 119
+#define __NR_sched_getscheduler 120
+#define __NR_sched_getparam 121
+#define __NR_sched_setaffinity 122
+#define __NR_sched_getaffinity 123
+#define __NR_sched_yield 124
+#define __NR_sched_get_priority_max 125
+#define __NR_sched_get_priority_min 126
+#define __NR_restart_syscall 128
+#define __NR_kill 129
+#define __NR_tkill 130
+#define __NR_tgkill 131
+#define __NR_sigaltstack 132
+#define __NR_rt_sigsuspend 133
+#define __NR_rt_sigaction 134
+#define __NR_rt_sigprocmask 135
+#define __NR_rt_sigpending 136
+#define __NR_rt_sigqueueinfo 138
+#define __NR_rt_sigreturn 139
+#define __NR_setpriority 140
+#define __NR_getpriority 141
+#define __NR_reboot 142
+#define __NR_setregid 143
+#define __NR_setgid 144
+#define __NR_setreuid 145
+#define __NR_setuid 146
+#define __NR_setresuid 147
+#define __NR_getresuid 148
+#define __NR_setresgid 149
+#define __NR_getresgid 150
+#define __NR_setfsuid 151
+#define __NR_setfsgid 152
+#define __NR_times 153
+#define __NR_setpgid 154
+#define __NR_getpgid 155
+#define __NR_getsid 156
+#define __NR_setsid 157
+#define __NR_getgroups 158
+#define __NR_setgroups 159
+#define __NR_uname 160
+#define __NR_sethostname 161
+#define __NR_setdomainname 162
+#define __NR_getrusage 165
+#define __NR_umask 166
+#define __NR_prctl 167
+#define __NR_getcpu 168
+#define __NR_getpid 172
+#define __NR_getppid 173
+#define __NR_getuid 174
+#define __NR_geteuid 175
+#define __NR_getgid 176
+#define __NR_getegid 177
+#define __NR_gettid 178
+#define __NR_sysinfo 179
+#define __NR_mq_open 180
+#define __NR_mq_unlink 181
+#define __NR_mq_notify 184
+#define __NR_mq_getsetattr 185
+#define __NR_msgget 186
+#define __NR_msgctl 187
+#define __NR_msgrcv 188
+#define __NR_msgsnd 189
+#define __NR_semget 190
+#define __NR_semctl 191
+#define __NR_semop 193
+#define __NR_shmget 194
+#define __NR_shmctl 195
+#define __NR_shmat 196
+#define __NR_shmdt 197
+#define __NR_socket 198
+#define __NR_socketpair 199
+#define __NR_bind 200
+#define __NR_listen 201
+#define __NR_accept 202
+#define __NR_connect 203
+#define __NR_getsockname 204
+#define __NR_getpeername 205
+#define __NR_sendto 206
+#define __NR_recvfrom 207
+#define __NR_setsockopt 208
+#define __NR_getsockopt 209
+#define __NR_shutdown 210
+#define __NR_sendmsg 211
+#define __NR_recvmsg 212
+#define __NR_readahead 213
+#define __NR_brk 214
+#define __NR_munmap 215
+#define __NR_mremap 216
+#define __NR_add_key 217
+#define __NR_request_key 218
+#define __NR_keyctl 219
+#define __NR_clone 220
+#define __NR_execve 221
+#define __NR_mmap2 222
+#define __NR_fadvise64_64 223
+#define __NR_swapon 224
+#define __NR_swapoff 225
+#define __NR_mprotect 226
+#define __NR_msync 227
+#define __NR_mlock 228
+#define __NR_munlock 229
+#define __NR_mlockall 230
+#define __NR_munlockall 231
+#define __NR_mincore 232
+#define __NR_madvise 233
+#define __NR_remap_file_pages 234
+#define __NR_mbind 235
+#define __NR_get_mempolicy 236
+#define __NR_set_mempolicy 237
+#define __NR_migrate_pages 238
+#define __NR_move_pages 239
+#define __NR_rt_tgsigqueueinfo 240
+#define __NR_perf_event_open 241
+#define __NR_accept4 242
+#define __NR_riscv_hwprobe 258
+#define __NR_riscv_flush_icache 259
+#define __NR_prlimit64 261
+#define __NR_fanotify_init 262
+#define __NR_fanotify_mark 263
+#define __NR_name_to_handle_at 264
+#define __NR_open_by_handle_at 265
+#define __NR_syncfs 267
+#define __NR_setns 268
+#define __NR_sendmmsg 269
+#define __NR_process_vm_readv 270
+#define __NR_process_vm_writev 271
+#define __NR_kcmp 272
+#define __NR_finit_module 273
+#define __NR_sched_setattr 274
+#define __NR_sched_getattr 275
+#define __NR_renameat2 276
+#define __NR_seccomp 277
+#define __NR_getrandom 278
+#define __NR_memfd_create 279
+#define __NR_bpf 280
+#define __NR_execveat 281
+#define __NR_userfaultfd 282
+#define __NR_membarrier 283
+#define __NR_mlock2 284
+#define __NR_copy_file_range 285
+#define __NR_preadv2 286
+#define __NR_pwritev2 287
+#define __NR_pkey_mprotect 288
+#define __NR_pkey_alloc 289
+#define __NR_pkey_free 290
+#define __NR_statx 291
+#define __NR_rseq 293
+#define __NR_kexec_file_load 294
+#define __NR_clock_gettime64 403
+#define __NR_clock_settime64 404
+#define __NR_clock_adjtime64 405
+#define __NR_clock_getres_time64 406
+#define __NR_clock_nanosleep_time64 407
+#define __NR_timer_gettime64 408
+#define __NR_timer_settime64 409
+#define __NR_timerfd_gettime64 410
+#define __NR_timerfd_settime64 411
+#define __NR_utimensat_time64 412
+#define __NR_pselect6_time64 413
+#define __NR_ppoll_time64 414
+#define __NR_io_pgetevents_time64 416
+#define __NR_recvmmsg_time64 417
+#define __NR_mq_timedsend_time64 418
+#define __NR_mq_timedreceive_time64 419
+#define __NR_semtimedop_time64 420
+#define __NR_rt_sigtimedwait_time64 421
+#define __NR_futex_time64 422
+#define __NR_sched_rr_get_interval_time64 423
+#define __NR_pidfd_send_signal 424
+#define __NR_io_uring_setup 425
+#define __NR_io_uring_enter 426
+#define __NR_io_uring_register 427
+#define __NR_open_tree 428
+#define __NR_move_mount 429
+#define __NR_fsopen 430
+#define __NR_fsconfig 431
+#define __NR_fsmount 432
+#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
+#define __NR_close_range 436
+#define __NR_openat2 437
+#define __NR_pidfd_getfd 438
+#define __NR_faccessat2 439
+#define __NR_process_madvise 440
+#define __NR_epoll_pwait2 441
+#define __NR_mount_setattr 442
+#define __NR_quotactl_fd 443
+#define __NR_landlock_create_ruleset 444
+#define __NR_landlock_add_rule 445
+#define __NR_landlock_restrict_self 446
+#define __NR_memfd_secret 447
+#define __NR_process_mrelease 448
+#define __NR_futex_waitv 449
+#define __NR_set_mempolicy_home_node 450
+#define __NR_cachestat 451
+#define __NR_fchmodat2 452
+#define __NR_map_shadow_stack 453
+#define __NR_futex_wake 454
+#define __NR_futex_wait 455
+#define __NR_futex_requeue 456
+#define __NR_statmount 457
+#define __NR_listmount 458
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_set_self_attr 460
+#define __NR_lsm_list_modules 461
+#define __NR_mseal 462
+#endif
diff --git a/libc/kernel/uapi/asm-riscv/asm/unistd_64.h b/libc/kernel/uapi/asm-riscv/asm/unistd_64.h
new file mode 100644
index 0000000..f15b65b
--- /dev/null
+++ b/libc/kernel/uapi/asm-riscv/asm/unistd_64.h
@@ -0,0 +1,328 @@
+/*
+ * This file is auto-generated. Modifications will be lost.
+ *
+ * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
+ * for more information.
+ */
+#ifndef _UAPI_ASM_UNISTD_64_H
+#define _UAPI_ASM_UNISTD_64_H
+#define __NR_io_setup 0
+#define __NR_io_destroy 1
+#define __NR_io_submit 2
+#define __NR_io_cancel 3
+#define __NR_io_getevents 4
+#define __NR_setxattr 5
+#define __NR_lsetxattr 6
+#define __NR_fsetxattr 7
+#define __NR_getxattr 8
+#define __NR_lgetxattr 9
+#define __NR_fgetxattr 10
+#define __NR_listxattr 11
+#define __NR_llistxattr 12
+#define __NR_flistxattr 13
+#define __NR_removexattr 14
+#define __NR_lremovexattr 15
+#define __NR_fremovexattr 16
+#define __NR_getcwd 17
+#define __NR_lookup_dcookie 18
+#define __NR_eventfd2 19
+#define __NR_epoll_create1 20
+#define __NR_epoll_ctl 21
+#define __NR_epoll_pwait 22
+#define __NR_dup 23
+#define __NR_dup3 24
+#define __NR_fcntl 25
+#define __NR_inotify_init1 26
+#define __NR_inotify_add_watch 27
+#define __NR_inotify_rm_watch 28
+#define __NR_ioctl 29
+#define __NR_ioprio_set 30
+#define __NR_ioprio_get 31
+#define __NR_flock 32
+#define __NR_mknodat 33
+#define __NR_mkdirat 34
+#define __NR_unlinkat 35
+#define __NR_symlinkat 36
+#define __NR_linkat 37
+#define __NR_umount2 39
+#define __NR_mount 40
+#define __NR_pivot_root 41
+#define __NR_nfsservctl 42
+#define __NR_statfs 43
+#define __NR_fstatfs 44
+#define __NR_truncate 45
+#define __NR_ftruncate 46
+#define __NR_fallocate 47
+#define __NR_faccessat 48
+#define __NR_chdir 49
+#define __NR_fchdir 50
+#define __NR_chroot 51
+#define __NR_fchmod 52
+#define __NR_fchmodat 53
+#define __NR_fchownat 54
+#define __NR_fchown 55
+#define __NR_openat 56
+#define __NR_close 57
+#define __NR_vhangup 58
+#define __NR_pipe2 59
+#define __NR_quotactl 60
+#define __NR_getdents64 61
+#define __NR_lseek 62
+#define __NR_read 63
+#define __NR_write 64
+#define __NR_readv 65
+#define __NR_writev 66
+#define __NR_pread64 67
+#define __NR_pwrite64 68
+#define __NR_preadv 69
+#define __NR_pwritev 70
+#define __NR_sendfile 71
+#define __NR_pselect6 72
+#define __NR_ppoll 73
+#define __NR_signalfd4 74
+#define __NR_vmsplice 75
+#define __NR_splice 76
+#define __NR_tee 77
+#define __NR_readlinkat 78
+#define __NR_newfstatat 79
+#define __NR_fstat 80
+#define __NR_sync 81
+#define __NR_fsync 82
+#define __NR_fdatasync 83
+#define __NR_sync_file_range 84
+#define __NR_timerfd_create 85
+#define __NR_timerfd_settime 86
+#define __NR_timerfd_gettime 87
+#define __NR_utimensat 88
+#define __NR_acct 89
+#define __NR_capget 90
+#define __NR_capset 91
+#define __NR_personality 92
+#define __NR_exit 93
+#define __NR_exit_group 94
+#define __NR_waitid 95
+#define __NR_set_tid_address 96
+#define __NR_unshare 97
+#define __NR_futex 98
+#define __NR_set_robust_list 99
+#define __NR_get_robust_list 100
+#define __NR_nanosleep 101
+#define __NR_getitimer 102
+#define __NR_setitimer 103
+#define __NR_kexec_load 104
+#define __NR_init_module 105
+#define __NR_delete_module 106
+#define __NR_timer_create 107
+#define __NR_timer_gettime 108
+#define __NR_timer_getoverrun 109
+#define __NR_timer_settime 110
+#define __NR_timer_delete 111
+#define __NR_clock_settime 112
+#define __NR_clock_gettime 113
+#define __NR_clock_getres 114
+#define __NR_clock_nanosleep 115
+#define __NR_syslog 116
+#define __NR_ptrace 117
+#define __NR_sched_setparam 118
+#define __NR_sched_setscheduler 119
+#define __NR_sched_getscheduler 120
+#define __NR_sched_getparam 121
+#define __NR_sched_setaffinity 122
+#define __NR_sched_getaffinity 123
+#define __NR_sched_yield 124
+#define __NR_sched_get_priority_max 125
+#define __NR_sched_get_priority_min 126
+#define __NR_sched_rr_get_interval 127
+#define __NR_restart_syscall 128
+#define __NR_kill 129
+#define __NR_tkill 130
+#define __NR_tgkill 131
+#define __NR_sigaltstack 132
+#define __NR_rt_sigsuspend 133
+#define __NR_rt_sigaction 134
+#define __NR_rt_sigprocmask 135
+#define __NR_rt_sigpending 136
+#define __NR_rt_sigtimedwait 137
+#define __NR_rt_sigqueueinfo 138
+#define __NR_rt_sigreturn 139
+#define __NR_setpriority 140
+#define __NR_getpriority 141
+#define __NR_reboot 142
+#define __NR_setregid 143
+#define __NR_setgid 144
+#define __NR_setreuid 145
+#define __NR_setuid 146
+#define __NR_setresuid 147
+#define __NR_getresuid 148
+#define __NR_setresgid 149
+#define __NR_getresgid 150
+#define __NR_setfsuid 151
+#define __NR_setfsgid 152
+#define __NR_times 153
+#define __NR_setpgid 154
+#define __NR_getpgid 155
+#define __NR_getsid 156
+#define __NR_setsid 157
+#define __NR_getgroups 158
+#define __NR_setgroups 159
+#define __NR_uname 160
+#define __NR_sethostname 161
+#define __NR_setdomainname 162
+#define __NR_getrlimit 163
+#define __NR_setrlimit 164
+#define __NR_getrusage 165
+#define __NR_umask 166
+#define __NR_prctl 167
+#define __NR_getcpu 168
+#define __NR_gettimeofday 169
+#define __NR_settimeofday 170
+#define __NR_adjtimex 171
+#define __NR_getpid 172
+#define __NR_getppid 173
+#define __NR_getuid 174
+#define __NR_geteuid 175
+#define __NR_getgid 176
+#define __NR_getegid 177
+#define __NR_gettid 178
+#define __NR_sysinfo 179
+#define __NR_mq_open 180
+#define __NR_mq_unlink 181
+#define __NR_mq_timedsend 182
+#define __NR_mq_timedreceive 183
+#define __NR_mq_notify 184
+#define __NR_mq_getsetattr 185
+#define __NR_msgget 186
+#define __NR_msgctl 187
+#define __NR_msgrcv 188
+#define __NR_msgsnd 189
+#define __NR_semget 190
+#define __NR_semctl 191
+#define __NR_semtimedop 192
+#define __NR_semop 193
+#define __NR_shmget 194
+#define __NR_shmctl 195
+#define __NR_shmat 196
+#define __NR_shmdt 197
+#define __NR_socket 198
+#define __NR_socketpair 199
+#define __NR_bind 200
+#define __NR_listen 201
+#define __NR_accept 202
+#define __NR_connect 203
+#define __NR_getsockname 204
+#define __NR_getpeername 205
+#define __NR_sendto 206
+#define __NR_recvfrom 207
+#define __NR_setsockopt 208
+#define __NR_getsockopt 209
+#define __NR_shutdown 210
+#define __NR_sendmsg 211
+#define __NR_recvmsg 212
+#define __NR_readahead 213
+#define __NR_brk 214
+#define __NR_munmap 215
+#define __NR_mremap 216
+#define __NR_add_key 217
+#define __NR_request_key 218
+#define __NR_keyctl 219
+#define __NR_clone 220
+#define __NR_execve 221
+#define __NR_mmap 222
+#define __NR_fadvise64 223
+#define __NR_swapon 224
+#define __NR_swapoff 225
+#define __NR_mprotect 226
+#define __NR_msync 227
+#define __NR_mlock 228
+#define __NR_munlock 229
+#define __NR_mlockall 230
+#define __NR_munlockall 231
+#define __NR_mincore 232
+#define __NR_madvise 233
+#define __NR_remap_file_pages 234
+#define __NR_mbind 235
+#define __NR_get_mempolicy 236
+#define __NR_set_mempolicy 237
+#define __NR_migrate_pages 238
+#define __NR_move_pages 239
+#define __NR_rt_tgsigqueueinfo 240
+#define __NR_perf_event_open 241
+#define __NR_accept4 242
+#define __NR_recvmmsg 243
+#define __NR_riscv_hwprobe 258
+#define __NR_riscv_flush_icache 259
+#define __NR_wait4 260
+#define __NR_prlimit64 261
+#define __NR_fanotify_init 262
+#define __NR_fanotify_mark 263
+#define __NR_name_to_handle_at 264
+#define __NR_open_by_handle_at 265
+#define __NR_clock_adjtime 266
+#define __NR_syncfs 267
+#define __NR_setns 268
+#define __NR_sendmmsg 269
+#define __NR_process_vm_readv 270
+#define __NR_process_vm_writev 271
+#define __NR_kcmp 272
+#define __NR_finit_module 273
+#define __NR_sched_setattr 274
+#define __NR_sched_getattr 275
+#define __NR_renameat2 276
+#define __NR_seccomp 277
+#define __NR_getrandom 278
+#define __NR_memfd_create 279
+#define __NR_bpf 280
+#define __NR_execveat 281
+#define __NR_userfaultfd 282
+#define __NR_membarrier 283
+#define __NR_mlock2 284
+#define __NR_copy_file_range 285
+#define __NR_preadv2 286
+#define __NR_pwritev2 287
+#define __NR_pkey_mprotect 288
+#define __NR_pkey_alloc 289
+#define __NR_pkey_free 290
+#define __NR_statx 291
+#define __NR_io_pgetevents 292
+#define __NR_rseq 293
+#define __NR_kexec_file_load 294
+#define __NR_pidfd_send_signal 424
+#define __NR_io_uring_setup 425
+#define __NR_io_uring_enter 426
+#define __NR_io_uring_register 427
+#define __NR_open_tree 428
+#define __NR_move_mount 429
+#define __NR_fsopen 430
+#define __NR_fsconfig 431
+#define __NR_fsmount 432
+#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
+#define __NR_close_range 436
+#define __NR_openat2 437
+#define __NR_pidfd_getfd 438
+#define __NR_faccessat2 439
+#define __NR_process_madvise 440
+#define __NR_epoll_pwait2 441
+#define __NR_mount_setattr 442
+#define __NR_quotactl_fd 443
+#define __NR_landlock_create_ruleset 444
+#define __NR_landlock_add_rule 445
+#define __NR_landlock_restrict_self 446
+#define __NR_memfd_secret 447
+#define __NR_process_mrelease 448
+#define __NR_futex_waitv 449
+#define __NR_set_mempolicy_home_node 450
+#define __NR_cachestat 451
+#define __NR_fchmodat2 452
+#define __NR_map_shadow_stack 453
+#define __NR_futex_wake 454
+#define __NR_futex_wait 455
+#define __NR_futex_requeue 456
+#define __NR_statmount 457
+#define __NR_listmount 458
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_set_self_attr 460
+#define __NR_lsm_list_modules 461
+#define __NR_mseal 462
+#endif
diff --git a/libc/kernel/uapi/asm-x86/asm/kvm.h b/libc/kernel/uapi/asm-x86/asm/kvm.h
index 440ffb8..cd647b6 100644
--- a/libc/kernel/uapi/asm-x86/asm/kvm.h
+++ b/libc/kernel/uapi/asm-x86/asm/kvm.h
@@ -94,6 +94,7 @@
 #define KVM_NR_IRQCHIPS 3
 #define KVM_RUN_X86_SMM (1 << 0)
 #define KVM_RUN_X86_BUS_LOCK (1 << 1)
+#define KVM_RUN_X86_GUEST_MODE (1 << 2)
 struct kvm_regs {
   __u64 rax, rbx, rcx, rdx;
   __u64 rsi, rdi, rsp, rbp;
@@ -353,7 +354,10 @@
 #define KVM_STATE_NESTED_VMX_VMCS_SIZE 0x1000
 #define KVM_STATE_NESTED_SVM_VMCB_SIZE 0x1000
 #define KVM_STATE_VMX_PREEMPTION_TIMER_DEADLINE 0x00000001
+#define KVM_X86_GRP_SYSTEM 0
 #define KVM_X86_XCOMP_GUEST_SUPP 0
+#define KVM_X86_GRP_SEV 1
+#define KVM_X86_SEV_VMSA_FEATURES 0
 struct kvm_vmx_nested_state_data {
   __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
   __u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
@@ -528,6 +532,10 @@
   KVM_SEV_CERT_EXPORT,
   KVM_SEV_GET_ATTESTATION_REPORT,
   KVM_SEV_SEND_CANCEL,
+  KVM_SEV_INIT2,
+  KVM_SEV_SNP_LAUNCH_START = 100,
+  KVM_SEV_SNP_LAUNCH_UPDATE,
+  KVM_SEV_SNP_LAUNCH_FINISH,
   KVM_SEV_NR_MAX,
 };
 struct kvm_sev_cmd {
@@ -537,6 +545,13 @@
   __u32 error;
   __u32 sev_fd;
 };
+struct kvm_sev_init {
+  __u64 vmsa_features;
+  __u32 flags;
+  __u16 ghcb_version;
+  __u16 pad1;
+  __u32 pad2[8];
+};
 struct kvm_sev_launch_start {
   __u32 handle;
   __u32 policy;
@@ -633,6 +648,42 @@
   __u32 trans_len;
   __u32 pad2;
 };
+struct kvm_sev_snp_launch_start {
+  __u64 policy;
+  __u8 gosvw[16];
+  __u16 flags;
+  __u8 pad0[6];
+  __u64 pad1[4];
+};
+#define KVM_SEV_SNP_PAGE_TYPE_NORMAL 0x1
+#define KVM_SEV_SNP_PAGE_TYPE_ZERO 0x3
+#define KVM_SEV_SNP_PAGE_TYPE_UNMEASURED 0x4
+#define KVM_SEV_SNP_PAGE_TYPE_SECRETS 0x5
+#define KVM_SEV_SNP_PAGE_TYPE_CPUID 0x6
+struct kvm_sev_snp_launch_update {
+  __u64 gfn_start;
+  __u64 uaddr;
+  __u64 len;
+  __u8 type;
+  __u8 pad0;
+  __u16 flags;
+  __u32 pad1;
+  __u64 pad2[4];
+};
+#define KVM_SEV_SNP_ID_BLOCK_SIZE 96
+#define KVM_SEV_SNP_ID_AUTH_SIZE 4096
+#define KVM_SEV_SNP_FINISH_DATA_SIZE 32
+struct kvm_sev_snp_launch_finish {
+  __u64 id_block_uaddr;
+  __u64 id_auth_uaddr;
+  __u8 id_block_en;
+  __u8 auth_key_en;
+  __u8 vcek_disabled;
+  __u8 host_data[KVM_SEV_SNP_FINISH_DATA_SIZE];
+  __u8 pad0[3];
+  __u16 flags;
+  __u64 pad1[4];
+};
 #define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0)
 #define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (1ULL << 1)
 struct kvm_hyperv_eventfd {
@@ -654,4 +705,7 @@
 #define KVM_EXIT_HYPERCALL_LONG_MODE _BITULL(0)
 #define KVM_X86_DEFAULT_VM 0
 #define KVM_X86_SW_PROTECTED_VM 1
+#define KVM_X86_SEV_VM 2
+#define KVM_X86_SEV_ES_VM 3
+#define KVM_X86_SNP_VM 4
 #endif
diff --git a/libc/kernel/uapi/asm-x86/asm/svm.h b/libc/kernel/uapi/asm-x86/asm/svm.h
index ffbf0b3..4f165fa 100644
--- a/libc/kernel/uapi/asm-x86/asm/svm.h
+++ b/libc/kernel/uapi/asm-x86/asm/svm.h
@@ -117,6 +117,7 @@
 #define SVM_VMGEXIT_AP_CREATE_ON_INIT 0
 #define SVM_VMGEXIT_AP_CREATE 1
 #define SVM_VMGEXIT_AP_DESTROY 2
+#define SVM_VMGEXIT_SNP_RUN_VMPL 0x80000018
 #define SVM_VMGEXIT_HV_FEATURES 0x8000fffd
 #define SVM_VMGEXIT_TERM_REQUEST 0x8000fffe
 #define SVM_VMGEXIT_TERM_REASON(reason_set,reason_code) (((((u64) reason_set) & 0xf)) | ((((u64) reason_code) & 0xff) << 4))
diff --git a/libc/kernel/uapi/asm-x86/asm/unistd_32.h b/libc/kernel/uapi/asm-x86/asm/unistd_32.h
index 72076fd..59c693d 100644
--- a/libc/kernel/uapi/asm-x86/asm/unistd_32.h
+++ b/libc/kernel/uapi/asm-x86/asm/unistd_32.h
@@ -457,4 +457,5 @@
 #define __NR_lsm_get_self_attr 459
 #define __NR_lsm_set_self_attr 460
 #define __NR_lsm_list_modules 461
+#define __NR_mseal 462
 #endif
diff --git a/libc/kernel/uapi/asm-x86/asm/unistd_64.h b/libc/kernel/uapi/asm-x86/asm/unistd_64.h
index 8c4f76e..d5408a3 100644
--- a/libc/kernel/uapi/asm-x86/asm/unistd_64.h
+++ b/libc/kernel/uapi/asm-x86/asm/unistd_64.h
@@ -341,6 +341,7 @@
 #define __NR_statx 332
 #define __NR_io_pgetevents 333
 #define __NR_rseq 334
+#define __NR_uretprobe 335
 #define __NR_pidfd_send_signal 424
 #define __NR_io_uring_setup 425
 #define __NR_io_uring_enter 426
@@ -379,4 +380,5 @@
 #define __NR_lsm_get_self_attr 459
 #define __NR_lsm_set_self_attr 460
 #define __NR_lsm_list_modules 461
+#define __NR_mseal 462
 #endif
diff --git a/libc/kernel/uapi/asm-x86/asm/unistd_x32.h b/libc/kernel/uapi/asm-x86/asm/unistd_x32.h
index 984cfca..fdcf7e6 100644
--- a/libc/kernel/uapi/asm-x86/asm/unistd_x32.h
+++ b/libc/kernel/uapi/asm-x86/asm/unistd_x32.h
@@ -294,6 +294,7 @@
 #define __NR_statx (__X32_SYSCALL_BIT + 332)
 #define __NR_io_pgetevents (__X32_SYSCALL_BIT + 333)
 #define __NR_rseq (__X32_SYSCALL_BIT + 334)
+#define __NR_uretprobe (__X32_SYSCALL_BIT + 335)
 #define __NR_pidfd_send_signal (__X32_SYSCALL_BIT + 424)
 #define __NR_io_uring_setup (__X32_SYSCALL_BIT + 425)
 #define __NR_io_uring_enter (__X32_SYSCALL_BIT + 426)
@@ -323,6 +324,7 @@
 #define __NR_set_mempolicy_home_node (__X32_SYSCALL_BIT + 450)
 #define __NR_cachestat (__X32_SYSCALL_BIT + 451)
 #define __NR_fchmodat2 (__X32_SYSCALL_BIT + 452)
+#define __NR_map_shadow_stack (__X32_SYSCALL_BIT + 453)
 #define __NR_futex_wake (__X32_SYSCALL_BIT + 454)
 #define __NR_futex_wait (__X32_SYSCALL_BIT + 455)
 #define __NR_futex_requeue (__X32_SYSCALL_BIT + 456)
@@ -331,6 +333,7 @@
 #define __NR_lsm_get_self_attr (__X32_SYSCALL_BIT + 459)
 #define __NR_lsm_set_self_attr (__X32_SYSCALL_BIT + 460)
 #define __NR_lsm_list_modules (__X32_SYSCALL_BIT + 461)
+#define __NR_mseal (__X32_SYSCALL_BIT + 462)
 #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 0ad0bc2..7bbd5de 100644
--- a/libc/kernel/uapi/drm/amdgpu_drm.h
+++ b/libc/kernel/uapi/drm/amdgpu_drm.h
@@ -65,6 +65,7 @@
 #define AMDGPU_GEM_CREATE_COHERENT (1 << 13)
 #define AMDGPU_GEM_CREATE_UNCACHED (1 << 14)
 #define AMDGPU_GEM_CREATE_EXT_COHERENT (1 << 15)
+#define AMDGPU_GEM_CREATE_GFX12_DCC (1 << 16)
 struct drm_amdgpu_gem_create_in {
   __u64 bo_size;
   __u64 alignment;
@@ -216,6 +217,14 @@
 #define AMDGPU_TILING_DCC_INDEPENDENT_128B_MASK 0x1
 #define AMDGPU_TILING_SCANOUT_SHIFT 63
 #define AMDGPU_TILING_SCANOUT_MASK 0x1
+#define AMDGPU_TILING_GFX12_SWIZZLE_MODE_SHIFT 0
+#define AMDGPU_TILING_GFX12_SWIZZLE_MODE_MASK 0x7
+#define AMDGPU_TILING_GFX12_DCC_MAX_COMPRESSED_BLOCK_SHIFT 3
+#define AMDGPU_TILING_GFX12_DCC_MAX_COMPRESSED_BLOCK_MASK 0x3
+#define AMDGPU_TILING_GFX12_DCC_NUMBER_TYPE_SHIFT 5
+#define AMDGPU_TILING_GFX12_DCC_NUMBER_TYPE_MASK 0x7
+#define AMDGPU_TILING_GFX12_DCC_DATA_FORMAT_SHIFT 8
+#define AMDGPU_TILING_GFX12_DCC_DATA_FORMAT_MASK 0x3f
 #define AMDGPU_TILING_SET(field,value) (((__u64) (value) & AMDGPU_TILING_ ##field ##_MASK) << AMDGPU_TILING_ ##field ##_SHIFT)
 #define AMDGPU_TILING_GET(value,field) (((__u64) (value) >> AMDGPU_TILING_ ##field ##_SHIFT) & AMDGPU_TILING_ ##field ##_MASK)
 #define AMDGPU_GEM_METADATA_OP_SET_METADATA 1
@@ -744,6 +753,10 @@
 #define AMDGPU_FAMILY_GC_10_3_6 149
 #define AMDGPU_FAMILY_GC_10_3_7 151
 #define AMDGPU_FAMILY_GC_11_5_0 150
+#define AMDGPU_FAMILY_GC_12_0_0 152
+struct drm_color_ctm_3x4 {
+  __u64 matrix[12];
+};
 #ifdef __cplusplus
 }
 #endif
diff --git a/libc/kernel/uapi/drm/drm_fourcc.h b/libc/kernel/uapi/drm/drm_fourcc.h
index 6fd2eb8..4902d6c 100644
--- a/libc/kernel/uapi/drm/drm_fourcc.h
+++ b/libc/kernel/uapi/drm/drm_fourcc.h
@@ -255,12 +255,17 @@
 #define AMD_FMT_MOD_TILE_VER_GFX10 2
 #define AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS 3
 #define AMD_FMT_MOD_TILE_VER_GFX11 4
+#define AMD_FMT_MOD_TILE_VER_GFX12 5
 #define AMD_FMT_MOD_TILE_GFX9_64K_S 9
 #define AMD_FMT_MOD_TILE_GFX9_64K_D 10
 #define AMD_FMT_MOD_TILE_GFX9_64K_S_X 25
 #define AMD_FMT_MOD_TILE_GFX9_64K_D_X 26
 #define AMD_FMT_MOD_TILE_GFX9_64K_R_X 27
 #define AMD_FMT_MOD_TILE_GFX11_256K_R_X 31
+#define AMD_FMT_MOD_TILE_GFX12_256B_2D 1
+#define AMD_FMT_MOD_TILE_GFX12_4K_2D 2
+#define AMD_FMT_MOD_TILE_GFX12_64K_2D 3
+#define AMD_FMT_MOD_TILE_GFX12_256K_2D 4
 #define AMD_FMT_MOD_DCC_BLOCK_64B 0
 #define AMD_FMT_MOD_DCC_BLOCK_128B 1
 #define AMD_FMT_MOD_DCC_BLOCK_256B 2
diff --git a/libc/kernel/uapi/drm/drm_mode.h b/libc/kernel/uapi/drm/drm_mode.h
index 9e6296c..06c91c5 100644
--- a/libc/kernel/uapi/drm/drm_mode.h
+++ b/libc/kernel/uapi/drm/drm_mode.h
@@ -357,15 +357,16 @@
 struct drm_color_ctm {
   __u64 matrix[9];
 };
-struct drm_color_ctm_3x4 {
-  __u64 matrix[12];
-};
 struct drm_color_lut {
   __u16 red;
   __u16 green;
   __u16 blue;
   __u16 reserved;
 };
+struct drm_plane_size_hint {
+  __u16 width;
+  __u16 height;
+};
 struct hdr_metadata_infoframe {
   __u8 eotf;
   __u8 metadata_type;
diff --git a/libc/kernel/uapi/drm/i915_drm.h b/libc/kernel/uapi/drm/i915_drm.h
index 0738cee..b43d8df 100644
--- a/libc/kernel/uapi/drm/i915_drm.h
+++ b/libc/kernel/uapi/drm/i915_drm.h
@@ -365,6 +365,7 @@
 #define I915_PARAM_HAS_USERPTR_PROBE 56
 #define I915_PARAM_OA_TIMESTAMP_FREQUENCY 57
 #define I915_PARAM_PXP_STATUS 58
+#define I915_PARAM_HAS_CONTEXT_FREQ_HINT 59
 struct drm_i915_getparam {
   __s32 param;
   int  * value;
@@ -743,6 +744,8 @@
 #define I915_CONTEXT_PARAM_PERSISTENCE 0xb
 #define I915_CONTEXT_PARAM_RINGSIZE 0xc
 #define I915_CONTEXT_PARAM_PROTECTED_CONTENT 0xd
+#define I915_CONTEXT_PARAM_LOW_LATENCY 0xe
+#define I915_CONTEXT_PARAM_CONTEXT_IMAGE 0xf
   __u64 value;
 };
 struct drm_i915_gem_context_param_sseu {
@@ -797,6 +800,14 @@
 } __attribute__((packed));
 #define I915_DEFINE_CONTEXT_PARAM_ENGINES(name__,N__) struct { __u64 extensions; struct i915_engine_class_instance engines[N__]; \
 } __attribute__((packed)) name__
+struct i915_gem_context_param_context_image {
+  struct i915_engine_class_instance engine;
+  __u32 flags;
+#define I915_CONTEXT_IMAGE_FLAG_ENGINE_INDEX (1u << 0)
+  __u32 size;
+  __u32 mbz;
+  __u64 image;
+} __attribute__((packed));
 struct drm_i915_gem_context_create_ext_setparam {
   struct i915_user_extension base;
   struct drm_i915_gem_context_param param;
diff --git a/libc/kernel/uapi/drm/ivpu_accel.h b/libc/kernel/uapi/drm/ivpu_accel.h
index fcbf6f7..960bd43 100644
--- a/libc/kernel/uapi/drm/ivpu_accel.h
+++ b/libc/kernel/uapi/drm/ivpu_accel.h
@@ -18,12 +18,20 @@
 #define DRM_IVPU_BO_INFO 0x03
 #define DRM_IVPU_SUBMIT 0x05
 #define DRM_IVPU_BO_WAIT 0x06
+#define DRM_IVPU_METRIC_STREAMER_START 0x07
+#define DRM_IVPU_METRIC_STREAMER_STOP 0x08
+#define DRM_IVPU_METRIC_STREAMER_GET_DATA 0x09
+#define DRM_IVPU_METRIC_STREAMER_GET_INFO 0x0a
 #define DRM_IOCTL_IVPU_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_GET_PARAM, struct drm_ivpu_param)
 #define DRM_IOCTL_IVPU_SET_PARAM DRM_IOW(DRM_COMMAND_BASE + DRM_IVPU_SET_PARAM, struct drm_ivpu_param)
 #define DRM_IOCTL_IVPU_BO_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_BO_CREATE, struct drm_ivpu_bo_create)
 #define DRM_IOCTL_IVPU_BO_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_BO_INFO, struct drm_ivpu_bo_info)
 #define DRM_IOCTL_IVPU_SUBMIT DRM_IOW(DRM_COMMAND_BASE + DRM_IVPU_SUBMIT, struct drm_ivpu_submit)
 #define DRM_IOCTL_IVPU_BO_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_BO_WAIT, struct drm_ivpu_bo_wait)
+#define DRM_IOCTL_IVPU_METRIC_STREAMER_START DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_METRIC_STREAMER_START, struct drm_ivpu_metric_streamer_start)
+#define DRM_IOCTL_IVPU_METRIC_STREAMER_STOP DRM_IOW(DRM_COMMAND_BASE + DRM_IVPU_METRIC_STREAMER_STOP, struct drm_ivpu_metric_streamer_stop)
+#define DRM_IOCTL_IVPU_METRIC_STREAMER_GET_DATA DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_METRIC_STREAMER_GET_DATA, struct drm_ivpu_metric_streamer_get_data)
+#define DRM_IOCTL_IVPU_METRIC_STREAMER_GET_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_IVPU_METRIC_STREAMER_GET_INFO, struct drm_ivpu_metric_streamer_get_data)
 #define DRM_IVPU_PARAM_DEVICE_ID 0
 #define DRM_IVPU_PARAM_DEVICE_REVISION 1
 #define DRM_IVPU_PARAM_PLATFORM_TYPE 2
@@ -96,6 +104,22 @@
   __u32 job_status;
   __u32 pad;
 };
+struct drm_ivpu_metric_streamer_start {
+  __u64 metric_group_mask;
+  __u64 sampling_period_ns;
+  __u32 read_period_samples;
+  __u32 sample_size;
+  __u32 max_data_size;
+};
+struct drm_ivpu_metric_streamer_get_data {
+  __u64 metric_group_mask;
+  __u64 buffer_ptr;
+  __u64 buffer_size;
+  __u64 data_size;
+};
+struct drm_ivpu_metric_streamer_stop {
+  __u64 metric_group_mask;
+};
 #ifdef __cplusplus
 }
 #endif
diff --git a/libc/kernel/uapi/drm/msm_drm.h b/libc/kernel/uapi/drm/msm_drm.h
index 4d83744..7ec5ed2 100644
--- a/libc/kernel/uapi/drm/msm_drm.h
+++ b/libc/kernel/uapi/drm/msm_drm.h
@@ -37,6 +37,7 @@
 #define MSM_PARAM_VA_START 0x0e
 #define MSM_PARAM_VA_SIZE 0x0f
 #define MSM_PARAM_HIGHEST_BANK_BIT 0x10
+#define MSM_PARAM_RAYTRACING 0x11
 #define MSM_PARAM_NR_RINGS MSM_PARAM_PRIORITIES
 struct drm_msm_param {
   __u32 pipe;
diff --git a/libc/kernel/uapi/drm/nouveau_drm.h b/libc/kernel/uapi/drm/nouveau_drm.h
index f7d870e..01897af 100644
--- a/libc/kernel/uapi/drm/nouveau_drm.h
+++ b/libc/kernel/uapi/drm/nouveau_drm.h
@@ -25,10 +25,16 @@
 #define NOUVEAU_GETPARAM_EXEC_PUSH_MAX 17
 #define NOUVEAU_GETPARAM_VRAM_BAR_SIZE 18
 #define NOUVEAU_GETPARAM_VRAM_USED 19
+#define NOUVEAU_GETPARAM_HAS_VMA_TILEMODE 20
 struct drm_nouveau_getparam {
   __u64 param;
   __u64 value;
 };
+#define NOUVEAU_FIFO_ENGINE_GR 0x01
+#define NOUVEAU_FIFO_ENGINE_VP 0x02
+#define NOUVEAU_FIFO_ENGINE_PPP 0x04
+#define NOUVEAU_FIFO_ENGINE_BSP 0x08
+#define NOUVEAU_FIFO_ENGINE_CE 0x30
 struct drm_nouveau_channel_alloc {
   __u32 fb_ctxdma_handle;
   __u32 tt_ctxdma_handle;
@@ -44,6 +50,16 @@
 struct drm_nouveau_channel_free {
   __s32 channel;
 };
+struct drm_nouveau_notifierobj_alloc {
+  __u32 channel;
+  __u32 handle;
+  __u32 size;
+  __u32 offset;
+};
+struct drm_nouveau_gpuobj_free {
+  __s32 channel;
+  __u32 handle;
+};
 #define NOUVEAU_GEM_DOMAIN_CPU (1 << 0)
 #define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1)
 #define NOUVEAU_GEM_DOMAIN_GART (1 << 2)
diff --git a/libc/kernel/uapi/drm/panthor_drm.h b/libc/kernel/uapi/drm/panthor_drm.h
new file mode 100644
index 0000000..b45c1dc
--- /dev/null
+++ b/libc/kernel/uapi/drm/panthor_drm.h
@@ -0,0 +1,240 @@
+/*
+ * This file is auto-generated. Modifications will be lost.
+ *
+ * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
+ * for more information.
+ */
+#ifndef _PANTHOR_DRM_H_
+#define _PANTHOR_DRM_H_
+#include "drm.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define DRM_PANTHOR_USER_MMIO_OFFSET_32BIT (1ull << 43)
+#define DRM_PANTHOR_USER_MMIO_OFFSET_64BIT (1ull << 56)
+#define DRM_PANTHOR_USER_MMIO_OFFSET (sizeof(unsigned long) < 8 ? DRM_PANTHOR_USER_MMIO_OFFSET_32BIT : DRM_PANTHOR_USER_MMIO_OFFSET_64BIT)
+#define DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET (DRM_PANTHOR_USER_MMIO_OFFSET | 0)
+enum drm_panthor_ioctl_id {
+  DRM_PANTHOR_DEV_QUERY = 0,
+  DRM_PANTHOR_VM_CREATE,
+  DRM_PANTHOR_VM_DESTROY,
+  DRM_PANTHOR_VM_BIND,
+  DRM_PANTHOR_VM_GET_STATE,
+  DRM_PANTHOR_BO_CREATE,
+  DRM_PANTHOR_BO_MMAP_OFFSET,
+  DRM_PANTHOR_GROUP_CREATE,
+  DRM_PANTHOR_GROUP_DESTROY,
+  DRM_PANTHOR_GROUP_SUBMIT,
+  DRM_PANTHOR_GROUP_GET_STATE,
+  DRM_PANTHOR_TILER_HEAP_CREATE,
+  DRM_PANTHOR_TILER_HEAP_DESTROY,
+};
+#define DRM_IOCTL_PANTHOR(__access,__id,__type) DRM_IO ##__access(DRM_COMMAND_BASE + DRM_PANTHOR_ ##__id, struct drm_panthor_ ##__type)
+#define DRM_IOCTL_PANTHOR_DEV_QUERY DRM_IOCTL_PANTHOR(WR, DEV_QUERY, dev_query)
+#define DRM_IOCTL_PANTHOR_VM_CREATE DRM_IOCTL_PANTHOR(WR, VM_CREATE, vm_create)
+#define DRM_IOCTL_PANTHOR_VM_DESTROY DRM_IOCTL_PANTHOR(WR, VM_DESTROY, vm_destroy)
+#define DRM_IOCTL_PANTHOR_VM_BIND DRM_IOCTL_PANTHOR(WR, VM_BIND, vm_bind)
+#define DRM_IOCTL_PANTHOR_VM_GET_STATE DRM_IOCTL_PANTHOR(WR, VM_GET_STATE, vm_get_state)
+#define DRM_IOCTL_PANTHOR_BO_CREATE DRM_IOCTL_PANTHOR(WR, BO_CREATE, bo_create)
+#define DRM_IOCTL_PANTHOR_BO_MMAP_OFFSET DRM_IOCTL_PANTHOR(WR, BO_MMAP_OFFSET, bo_mmap_offset)
+#define DRM_IOCTL_PANTHOR_GROUP_CREATE DRM_IOCTL_PANTHOR(WR, GROUP_CREATE, group_create)
+#define DRM_IOCTL_PANTHOR_GROUP_DESTROY DRM_IOCTL_PANTHOR(WR, GROUP_DESTROY, group_destroy)
+#define DRM_IOCTL_PANTHOR_GROUP_SUBMIT DRM_IOCTL_PANTHOR(WR, GROUP_SUBMIT, group_submit)
+#define DRM_IOCTL_PANTHOR_GROUP_GET_STATE DRM_IOCTL_PANTHOR(WR, GROUP_GET_STATE, group_get_state)
+#define DRM_IOCTL_PANTHOR_TILER_HEAP_CREATE DRM_IOCTL_PANTHOR(WR, TILER_HEAP_CREATE, tiler_heap_create)
+#define DRM_IOCTL_PANTHOR_TILER_HEAP_DESTROY DRM_IOCTL_PANTHOR(WR, TILER_HEAP_DESTROY, tiler_heap_destroy)
+struct drm_panthor_obj_array {
+  __u32 stride;
+  __u32 count;
+  __u64 array;
+};
+#define DRM_PANTHOR_OBJ_ARRAY(cnt,ptr) {.stride = sizeof((ptr)[0]),.count = (cnt),.array = (__u64) (uintptr_t) (ptr) }
+enum drm_panthor_sync_op_flags {
+  DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_MASK = 0xff,
+  DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_SYNCOBJ = 0,
+  DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_TIMELINE_SYNCOBJ = 1,
+  DRM_PANTHOR_SYNC_OP_WAIT = 0 << 31,
+  DRM_PANTHOR_SYNC_OP_SIGNAL = (int) (1u << 31),
+};
+struct drm_panthor_sync_op {
+  __u32 flags;
+  __u32 handle;
+  __u64 timeline_value;
+};
+enum drm_panthor_dev_query_type {
+  DRM_PANTHOR_DEV_QUERY_GPU_INFO = 0,
+  DRM_PANTHOR_DEV_QUERY_CSIF_INFO,
+};
+struct drm_panthor_gpu_info {
+  __u32 gpu_id;
+#define DRM_PANTHOR_ARCH_MAJOR(x) ((x) >> 28)
+#define DRM_PANTHOR_ARCH_MINOR(x) (((x) >> 24) & 0xf)
+#define DRM_PANTHOR_ARCH_REV(x) (((x) >> 20) & 0xf)
+#define DRM_PANTHOR_PRODUCT_MAJOR(x) (((x) >> 16) & 0xf)
+#define DRM_PANTHOR_VERSION_MAJOR(x) (((x) >> 12) & 0xf)
+#define DRM_PANTHOR_VERSION_MINOR(x) (((x) >> 4) & 0xff)
+#define DRM_PANTHOR_VERSION_STATUS(x) ((x) & 0xf)
+  __u32 gpu_rev;
+  __u32 csf_id;
+#define DRM_PANTHOR_CSHW_MAJOR(x) (((x) >> 26) & 0x3f)
+#define DRM_PANTHOR_CSHW_MINOR(x) (((x) >> 20) & 0x3f)
+#define DRM_PANTHOR_CSHW_REV(x) (((x) >> 16) & 0xf)
+#define DRM_PANTHOR_MCU_MAJOR(x) (((x) >> 10) & 0x3f)
+#define DRM_PANTHOR_MCU_MINOR(x) (((x) >> 4) & 0x3f)
+#define DRM_PANTHOR_MCU_REV(x) ((x) & 0xf)
+  __u32 l2_features;
+  __u32 tiler_features;
+  __u32 mem_features;
+  __u32 mmu_features;
+#define DRM_PANTHOR_MMU_VA_BITS(x) ((x) & 0xff)
+  __u32 thread_features;
+  __u32 max_threads;
+  __u32 thread_max_workgroup_size;
+  __u32 thread_max_barrier_size;
+  __u32 coherency_features;
+  __u32 texture_features[4];
+  __u32 as_present;
+  __u64 shader_present;
+  __u64 l2_present;
+  __u64 tiler_present;
+  __u32 core_features;
+  __u32 pad;
+};
+struct drm_panthor_csif_info {
+  __u32 csg_slot_count;
+  __u32 cs_slot_count;
+  __u32 cs_reg_count;
+  __u32 scoreboard_slot_count;
+  __u32 unpreserved_cs_reg_count;
+  __u32 pad;
+};
+struct drm_panthor_dev_query {
+  __u32 type;
+  __u32 size;
+  __u64 pointer;
+};
+struct drm_panthor_vm_create {
+  __u32 flags;
+  __u32 id;
+  __u64 user_va_range;
+};
+struct drm_panthor_vm_destroy {
+  __u32 id;
+  __u32 pad;
+};
+enum drm_panthor_vm_bind_op_flags {
+  DRM_PANTHOR_VM_BIND_OP_MAP_READONLY = 1 << 0,
+  DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC = 1 << 1,
+  DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED = 1 << 2,
+  DRM_PANTHOR_VM_BIND_OP_TYPE_MASK = (int) (0xfu << 28),
+  DRM_PANTHOR_VM_BIND_OP_TYPE_MAP = 0 << 28,
+  DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP = 1 << 28,
+  DRM_PANTHOR_VM_BIND_OP_TYPE_SYNC_ONLY = 2 << 28,
+};
+struct drm_panthor_vm_bind_op {
+  __u32 flags;
+  __u32 bo_handle;
+  __u64 bo_offset;
+  __u64 va;
+  __u64 size;
+  struct drm_panthor_obj_array syncs;
+};
+enum drm_panthor_vm_bind_flags {
+  DRM_PANTHOR_VM_BIND_ASYNC = 1 << 0,
+};
+struct drm_panthor_vm_bind {
+  __u32 vm_id;
+  __u32 flags;
+  struct drm_panthor_obj_array ops;
+};
+enum drm_panthor_vm_state {
+  DRM_PANTHOR_VM_STATE_USABLE,
+  DRM_PANTHOR_VM_STATE_UNUSABLE,
+};
+struct drm_panthor_vm_get_state {
+  __u32 vm_id;
+  __u32 state;
+};
+enum drm_panthor_bo_flags {
+  DRM_PANTHOR_BO_NO_MMAP = (1 << 0),
+};
+struct drm_panthor_bo_create {
+  __u64 size;
+  __u32 flags;
+  __u32 exclusive_vm_id;
+  __u32 handle;
+  __u32 pad;
+};
+struct drm_panthor_bo_mmap_offset {
+  __u32 handle;
+  __u32 pad;
+  __u64 offset;
+};
+struct drm_panthor_queue_create {
+  __u8 priority;
+  __u8 pad[3];
+  __u32 ringbuf_size;
+};
+enum drm_panthor_group_priority {
+  PANTHOR_GROUP_PRIORITY_LOW = 0,
+  PANTHOR_GROUP_PRIORITY_MEDIUM,
+  PANTHOR_GROUP_PRIORITY_HIGH,
+};
+struct drm_panthor_group_create {
+  struct drm_panthor_obj_array queues;
+  __u8 max_compute_cores;
+  __u8 max_fragment_cores;
+  __u8 max_tiler_cores;
+  __u8 priority;
+  __u32 pad;
+  __u64 compute_core_mask;
+  __u64 fragment_core_mask;
+  __u64 tiler_core_mask;
+  __u32 vm_id;
+  __u32 group_handle;
+};
+struct drm_panthor_group_destroy {
+  __u32 group_handle;
+  __u32 pad;
+};
+struct drm_panthor_queue_submit {
+  __u32 queue_index;
+  __u32 stream_size;
+  __u64 stream_addr;
+  __u32 latest_flush;
+  __u32 pad;
+  struct drm_panthor_obj_array syncs;
+};
+struct drm_panthor_group_submit {
+  __u32 group_handle;
+  __u32 pad;
+  struct drm_panthor_obj_array queue_submits;
+};
+enum drm_panthor_group_state_flags {
+  DRM_PANTHOR_GROUP_STATE_TIMEDOUT = 1 << 0,
+  DRM_PANTHOR_GROUP_STATE_FATAL_FAULT = 1 << 1,
+};
+struct drm_panthor_group_get_state {
+  __u32 group_handle;
+  __u32 state;
+  __u32 fatal_queues;
+  __u32 pad;
+};
+struct drm_panthor_tiler_heap_create {
+  __u32 vm_id;
+  __u32 initial_chunk_count;
+  __u32 chunk_size;
+  __u32 max_chunks;
+  __u32 target_in_flight;
+  __u32 handle;
+  __u64 tiler_heap_ctx_gpu_va;
+  __u64 first_heap_chunk_gpu_va;
+};
+struct drm_panthor_tiler_heap_destroy {
+  __u32 handle;
+  __u32 pad;
+};
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/libc/kernel/uapi/drm/v3d_drm.h b/libc/kernel/uapi/drm/v3d_drm.h
index 4000fd3..b7aca21 100644
--- a/libc/kernel/uapi/drm/v3d_drm.h
+++ b/libc/kernel/uapi/drm/v3d_drm.h
@@ -22,6 +22,7 @@
 #define DRM_V3D_PERFMON_DESTROY 0x09
 #define DRM_V3D_PERFMON_GET_VALUES 0x0a
 #define DRM_V3D_SUBMIT_CPU 0x0b
+#define DRM_V3D_PERFMON_GET_COUNTER 0x0c
 #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)
@@ -34,6 +35,7 @@
 #define DRM_IOCTL_V3D_PERFMON_DESTROY DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_PERFMON_DESTROY, struct drm_v3d_perfmon_destroy)
 #define DRM_IOCTL_V3D_PERFMON_GET_VALUES DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_PERFMON_GET_VALUES, struct drm_v3d_perfmon_get_values)
 #define DRM_IOCTL_V3D_SUBMIT_CPU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CPU, struct drm_v3d_submit_cpu)
+#define DRM_IOCTL_V3D_PERFMON_GET_COUNTER DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_PERFMON_GET_COUNTER, struct drm_v3d_perfmon_get_counter)
 #define DRM_V3D_SUBMIT_CL_FLUSH_CACHE 0x01
 #define DRM_V3D_SUBMIT_EXTENSION 0x02
 struct drm_v3d_extension {
@@ -119,6 +121,7 @@
   DRM_V3D_PARAM_SUPPORTS_PERFMON,
   DRM_V3D_PARAM_SUPPORTS_MULTISYNC_EXT,
   DRM_V3D_PARAM_SUPPORTS_CPU_QUEUE,
+  DRM_V3D_PARAM_MAX_PERF_COUNTERS,
 };
 struct drm_v3d_get_param {
   __u32 param;
@@ -324,6 +327,16 @@
   __u32 pad;
   __u64 values_ptr;
 };
+#define DRM_V3D_PERFCNT_MAX_NAME 64
+#define DRM_V3D_PERFCNT_MAX_CATEGORY 32
+#define DRM_V3D_PERFCNT_MAX_DESCRIPTION 256
+struct drm_v3d_perfmon_get_counter {
+  __u8 counter;
+  __u8 name[DRM_V3D_PERFCNT_MAX_NAME];
+  __u8 category[DRM_V3D_PERFCNT_MAX_CATEGORY];
+  __u8 description[DRM_V3D_PERFCNT_MAX_DESCRIPTION];
+  __u8 reserved[7];
+};
 #ifdef __cplusplus
 }
 #endif
diff --git a/libc/kernel/uapi/drm/xe_drm.h b/libc/kernel/uapi/drm/xe_drm.h
index dd0da6f..a034b29 100644
--- a/libc/kernel/uapi/drm/xe_drm.h
+++ b/libc/kernel/uapi/drm/xe_drm.h
@@ -21,6 +21,7 @@
 #define DRM_XE_EXEC_QUEUE_GET_PROPERTY 0x08
 #define DRM_XE_EXEC 0x09
 #define DRM_XE_WAIT_USER_FENCE 0x0a
+#define DRM_XE_OBSERVATION 0x0b
 #define DRM_IOCTL_XE_DEVICE_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_DEVICE_QUERY, struct drm_xe_device_query)
 #define DRM_IOCTL_XE_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_GEM_CREATE, struct drm_xe_gem_create)
 #define DRM_IOCTL_XE_GEM_MMAP_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_GEM_MMAP_OFFSET, struct drm_xe_gem_mmap_offset)
@@ -32,6 +33,7 @@
 #define DRM_IOCTL_XE_EXEC_QUEUE_GET_PROPERTY DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_EXEC_QUEUE_GET_PROPERTY, struct drm_xe_exec_queue_get_property)
 #define DRM_IOCTL_XE_EXEC DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC, struct drm_xe_exec)
 #define DRM_IOCTL_XE_WAIT_USER_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE, struct drm_xe_wait_user_fence)
+#define DRM_IOCTL_XE_OBSERVATION DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION, struct drm_xe_observation_param)
 struct drm_xe_user_extension {
   __u64 next_extension;
   __u32 name;
@@ -105,7 +107,11 @@
   __u32 reference_clock;
   __u64 near_mem_regions;
   __u64 far_mem_regions;
-  __u64 reserved[8];
+  __u16 ip_ver_major;
+  __u16 ip_ver_minor;
+  __u16 ip_ver_rev;
+  __u16 pad2;
+  __u64 reserved[7];
 };
 struct drm_xe_query_gt_list {
   __u32 num_gt;
@@ -114,9 +120,10 @@
 };
 struct drm_xe_query_topology_mask {
   __u16 gt_id;
-#define DRM_XE_TOPO_DSS_GEOMETRY (1 << 0)
-#define DRM_XE_TOPO_DSS_COMPUTE (1 << 1)
-#define DRM_XE_TOPO_EU_PER_DSS (1 << 2)
+#define DRM_XE_TOPO_DSS_GEOMETRY 1
+#define DRM_XE_TOPO_DSS_COMPUTE 2
+#define DRM_XE_TOPO_L3_BANK 3
+#define DRM_XE_TOPO_EU_PER_DSS 4
   __u16 type;
   __u32 num_bytes;
   __u8 mask[];
@@ -131,6 +138,7 @@
 };
 struct drm_xe_query_uc_fw_version {
 #define XE_QUERY_UC_TYPE_GUC_SUBMISSION 0
+#define XE_QUERY_UC_TYPE_HUC 1
   __u16 uc_type;
   __u16 pad;
   __u32 branch_ver;
@@ -150,6 +158,7 @@
 #define DRM_XE_DEVICE_QUERY_GT_TOPOLOGY 5
 #define DRM_XE_DEVICE_QUERY_ENGINE_CYCLES 6
 #define DRM_XE_DEVICE_QUERY_UC_FW_VERSION 7
+#define DRM_XE_DEVICE_QUERY_OA_UNITS 8
   __u32 query;
   __u32 size;
   __u64 data;
@@ -209,6 +218,8 @@
 #define DRM_XE_VM_BIND_OP_UNMAP_ALL 0x3
 #define DRM_XE_VM_BIND_OP_PREFETCH 0x4
   __u32 op;
+#define DRM_XE_VM_BIND_FLAG_READONLY (1 << 0)
+#define DRM_XE_VM_BIND_FLAG_IMMEDIATE (1 << 1)
 #define DRM_XE_VM_BIND_FLAG_NULL (1 << 2)
 #define DRM_XE_VM_BIND_FLAG_DUMPABLE (1 << 3)
   __u32 flags;
@@ -302,6 +313,92 @@
   __u32 pad2;
   __u64 reserved[2];
 };
+enum drm_xe_observation_type {
+  DRM_XE_OBSERVATION_TYPE_OA,
+};
+enum drm_xe_observation_op {
+  DRM_XE_OBSERVATION_OP_STREAM_OPEN,
+  DRM_XE_OBSERVATION_OP_ADD_CONFIG,
+  DRM_XE_OBSERVATION_OP_REMOVE_CONFIG,
+};
+struct drm_xe_observation_param {
+  __u64 extensions;
+  __u64 observation_type;
+  __u64 observation_op;
+  __u64 param;
+};
+enum drm_xe_observation_ioctls {
+  DRM_XE_OBSERVATION_IOCTL_ENABLE = _IO('i', 0x0),
+  DRM_XE_OBSERVATION_IOCTL_DISABLE = _IO('i', 0x1),
+  DRM_XE_OBSERVATION_IOCTL_CONFIG = _IO('i', 0x2),
+  DRM_XE_OBSERVATION_IOCTL_STATUS = _IO('i', 0x3),
+  DRM_XE_OBSERVATION_IOCTL_INFO = _IO('i', 0x4),
+};
+enum drm_xe_oa_unit_type {
+  DRM_XE_OA_UNIT_TYPE_OAG,
+  DRM_XE_OA_UNIT_TYPE_OAM,
+};
+struct drm_xe_oa_unit {
+  __u64 extensions;
+  __u32 oa_unit_id;
+  __u32 oa_unit_type;
+  __u64 capabilities;
+#define DRM_XE_OA_CAPS_BASE (1 << 0)
+  __u64 oa_timestamp_freq;
+  __u64 reserved[4];
+  __u64 num_engines;
+  struct drm_xe_engine_class_instance eci[];
+};
+struct drm_xe_query_oa_units {
+  __u64 extensions;
+  __u32 num_oa_units;
+  __u32 pad;
+  __u64 oa_units[];
+};
+enum drm_xe_oa_format_type {
+  DRM_XE_OA_FMT_TYPE_OAG,
+  DRM_XE_OA_FMT_TYPE_OAR,
+  DRM_XE_OA_FMT_TYPE_OAM,
+  DRM_XE_OA_FMT_TYPE_OAC,
+  DRM_XE_OA_FMT_TYPE_OAM_MPEC,
+  DRM_XE_OA_FMT_TYPE_PEC,
+};
+enum drm_xe_oa_property_id {
+#define DRM_XE_OA_EXTENSION_SET_PROPERTY 0
+  DRM_XE_OA_PROPERTY_OA_UNIT_ID = 1,
+  DRM_XE_OA_PROPERTY_SAMPLE_OA,
+  DRM_XE_OA_PROPERTY_OA_METRIC_SET,
+  DRM_XE_OA_PROPERTY_OA_FORMAT,
+#define DRM_XE_OA_FORMAT_MASK_FMT_TYPE (0xffu << 0)
+#define DRM_XE_OA_FORMAT_MASK_COUNTER_SEL (0xffu << 8)
+#define DRM_XE_OA_FORMAT_MASK_COUNTER_SIZE (0xffu << 16)
+#define DRM_XE_OA_FORMAT_MASK_BC_REPORT (0xffu << 24)
+  DRM_XE_OA_PROPERTY_OA_PERIOD_EXPONENT,
+  DRM_XE_OA_PROPERTY_OA_DISABLED,
+  DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID,
+  DRM_XE_OA_PROPERTY_OA_ENGINE_INSTANCE,
+  DRM_XE_OA_PROPERTY_NO_PREEMPT,
+};
+struct drm_xe_oa_config {
+  __u64 extensions;
+  char uuid[36];
+  __u32 n_regs;
+  __u64 regs_ptr;
+};
+struct drm_xe_oa_stream_status {
+  __u64 extensions;
+  __u64 oa_status;
+#define DRM_XE_OASTATUS_MMIO_TRG_Q_FULL (1 << 3)
+#define DRM_XE_OASTATUS_COUNTER_OVERFLOW (1 << 2)
+#define DRM_XE_OASTATUS_BUFFER_OVERFLOW (1 << 1)
+#define DRM_XE_OASTATUS_REPORT_LOST (1 << 0)
+  __u64 reserved[3];
+};
+struct drm_xe_oa_stream_info {
+  __u64 extensions;
+  __u64 oa_buf_size;
+  __u64 reserved[3];
+};
 #ifdef __cplusplus
 }
 #endif
diff --git a/libc/kernel/uapi/linux/bpf.h b/libc/kernel/uapi/linux/bpf.h
index 0e9e883..8d64816 100644
--- a/libc/kernel/uapi/linux/bpf.h
+++ b/libc/kernel/uapi/linux/bpf.h
@@ -272,6 +272,7 @@
   BPF_CGROUP_UNIX_GETSOCKNAME,
   BPF_NETKIT_PRIMARY,
   BPF_NETKIT_PEER,
+  BPF_TRACE_KPROBE_SESSION,
   __MAX_BPF_ATTACH_TYPE
 };
 #define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
@@ -290,6 +291,7 @@
   BPF_LINK_TYPE_TCX = 11,
   BPF_LINK_TYPE_UPROBE_MULTI = 12,
   BPF_LINK_TYPE_NETKIT = 13,
+  BPF_LINK_TYPE_SOCKMAP = 14,
   __MAX_BPF_LINK_TYPE,
 };
 #define MAX_BPF_LINK_TYPE __MAX_BPF_LINK_TYPE
@@ -365,6 +367,7 @@
 #define BPF_F_QUERY_EFFECTIVE (1U << 0)
 #define BPF_F_TEST_RUN_ON_CPU (1U << 0)
 #define BPF_F_TEST_XDP_LIVE_FRAMES (1U << 1)
+#define BPF_F_TEST_SKB_CHECKSUM_COMPLETE (1U << 2)
 enum bpf_stats_type {
   BPF_STATS_RUN_TIME = 0,
 };
@@ -529,6 +532,8 @@
   struct {
     __u64 name;
     __u32 prog_fd;
+    __u32 : 32;
+    __aligned_u64 cookie;
   } raw_tracepoint;
   struct {
     __aligned_u64 btf;
@@ -769,8 +774,11 @@
 #define __bpf_md_ptr(type,name) union { type name; __u64 : 64; \
 } __attribute__((aligned(8)))
 enum {
-  BPF_SKB_TSTAMP_UNSPEC,
-  BPF_SKB_TSTAMP_DELIVERY_MONO,
+  BPF_SKB_TSTAMP_UNSPEC = 0,
+  BPF_SKB_TSTAMP_DELIVERY_MONO = 1,
+  BPF_SKB_CLOCK_REALTIME = 0,
+  BPF_SKB_CLOCK_MONOTONIC = 1,
+  BPF_SKB_CLOCK_TAI = 2,
 };
 struct __sk_buff {
   __u32 len;
@@ -1150,6 +1158,10 @@
       __u32 ifindex;
       __u32 attach_type;
     } netkit;
+    struct {
+      __u32 map_id;
+      __u32 attach_type;
+    } sockmap;
   };
 } __attribute__((aligned(8)));
 struct bpf_sock_addr {
@@ -1299,6 +1311,7 @@
   BPF_FIB_LOOKUP_SKIP_NEIGH = (1U << 2),
   BPF_FIB_LOOKUP_TBID = (1U << 3),
   BPF_FIB_LOOKUP_SRC = (1U << 4),
+  BPF_FIB_LOOKUP_MARK = (1U << 5),
 };
 enum {
   BPF_FIB_LKUP_RET_SUCCESS,
@@ -1320,7 +1333,7 @@
   union {
     __u16 tot_len;
     __u16 mtu_result;
-  };
+  } __attribute__((packed, aligned(2)));
   __u32 ifindex;
   union {
     __u8 tos;
@@ -1342,8 +1355,15 @@
     };
     __u32 tbid;
   };
-  __u8 smac[6];
-  __u8 dmac[6];
+  union {
+    struct {
+      __u32 mark;
+    };
+    struct {
+      __u8 smac[6];
+      __u8 dmac[6];
+    };
+  };
 };
 struct bpf_redir_neigh {
   __u32 nh_family;
@@ -1415,6 +1435,9 @@
 struct bpf_timer {
   __u64 __opaque[2];
 } __attribute__((aligned(8)));
+struct bpf_wq {
+  __u64 __opaque[2];
+} __attribute__((aligned(8)));
 struct bpf_dynptr {
   __u64 __opaque[2];
 } __attribute__((aligned(8)));
diff --git a/libc/kernel/uapi/linux/btrfs_tree.h b/libc/kernel/uapi/linux/btrfs_tree.h
index ea33eee..88f44d9 100644
--- a/libc/kernel/uapi/linux/btrfs_tree.h
+++ b/libc/kernel/uapi/linux/btrfs_tree.h
@@ -279,18 +279,8 @@
   __le64 devid;
   __le64 physical;
 } __attribute__((__packed__));
-#define BTRFS_STRIPE_RAID0 1
-#define BTRFS_STRIPE_RAID1 2
-#define BTRFS_STRIPE_DUP 3
-#define BTRFS_STRIPE_RAID10 4
-#define BTRFS_STRIPE_RAID5 5
-#define BTRFS_STRIPE_RAID6 6
-#define BTRFS_STRIPE_RAID1C3 7
-#define BTRFS_STRIPE_RAID1C4 8
 struct btrfs_stripe_extent {
-  __u8 encoding;
-  __u8 reserved[7];
-  struct btrfs_raid_stride strides[];
+  __DECLARE_FLEX_ARRAY(struct btrfs_raid_stride, strides);
 } __attribute__((__packed__));
 #define BTRFS_HEADER_FLAG_WRITTEN (1ULL << 0)
 #define BTRFS_HEADER_FLAG_RELOC (1ULL << 1)
@@ -300,6 +290,9 @@
 #define BTRFS_SUPER_FLAG_METADUMP_V2 (1ULL << 34)
 #define BTRFS_SUPER_FLAG_CHANGING_FSID (1ULL << 35)
 #define BTRFS_SUPER_FLAG_CHANGING_FSID_V2 (1ULL << 36)
+#define BTRFS_SUPER_FLAG_CHANGING_BG_TREE (1ULL << 38)
+#define BTRFS_SUPER_FLAG_CHANGING_DATA_CSUM (1ULL << 39)
+#define BTRFS_SUPER_FLAG_CHANGING_META_CSUM (1ULL << 40)
 struct btrfs_extent_item {
   __le64 refs;
   __le64 generation;
diff --git a/libc/kernel/uapi/linux/cxl_mem.h b/libc/kernel/uapi/linux/cxl_mem.h
index 942e817..abe6573 100644
--- a/libc/kernel/uapi/linux/cxl_mem.h
+++ b/libc/kernel/uapi/linux/cxl_mem.h
@@ -9,7 +9,7 @@
 #include <linux/types.h>
 #define CXL_MEM_QUERY_COMMANDS _IOR(0xCE, 1, struct cxl_mem_query_commands)
 #define CXL_MEM_SEND_COMMAND _IOWR(0xCE, 2, struct cxl_send_command)
-#define CXL_CMDS ___C(INVALID, "Invalid Command"), ___C(IDENTIFY, "Identify Command"), ___C(RAW, "Raw device command"), ___C(GET_SUPPORTED_LOGS, "Get Supported Logs"), ___C(GET_FW_INFO, "Get FW Info"), ___C(GET_PARTITION_INFO, "Get Partition Information"), ___C(GET_LSA, "Get Label Storage Area"), ___C(GET_HEALTH_INFO, "Get Health Info"), ___C(GET_LOG, "Get Log"), ___C(SET_PARTITION_INFO, "Set Partition Information"), ___C(SET_LSA, "Set Label Storage Area"), ___C(GET_ALERT_CONFIG, "Get Alert Configuration"), ___C(SET_ALERT_CONFIG, "Set Alert Configuration"), ___C(GET_SHUTDOWN_STATE, "Get Shutdown State"), ___C(SET_SHUTDOWN_STATE, "Set Shutdown State"), ___DEPRECATED(GET_POISON, "Get Poison List"), ___DEPRECATED(INJECT_POISON, "Inject Poison"), ___DEPRECATED(CLEAR_POISON, "Clear Poison"), ___C(GET_SCAN_MEDIA_CAPS, "Get Scan Media Capabilities"), ___DEPRECATED(SCAN_MEDIA, "Scan Media"), ___DEPRECATED(GET_SCAN_MEDIA, "Get Scan Media Results"), ___C(GET_TIMESTAMP, "Get Timestamp"), ___C(MAX, "invalid / last command")
+#define CXL_CMDS ___C(INVALID, "Invalid Command"), ___C(IDENTIFY, "Identify Command"), ___C(RAW, "Raw device command"), ___C(GET_SUPPORTED_LOGS, "Get Supported Logs"), ___C(GET_FW_INFO, "Get FW Info"), ___C(GET_PARTITION_INFO, "Get Partition Information"), ___C(GET_LSA, "Get Label Storage Area"), ___C(GET_HEALTH_INFO, "Get Health Info"), ___C(GET_LOG, "Get Log"), ___C(SET_PARTITION_INFO, "Set Partition Information"), ___C(SET_LSA, "Set Label Storage Area"), ___C(GET_ALERT_CONFIG, "Get Alert Configuration"), ___C(SET_ALERT_CONFIG, "Set Alert Configuration"), ___C(GET_SHUTDOWN_STATE, "Get Shutdown State"), ___C(SET_SHUTDOWN_STATE, "Set Shutdown State"), ___DEPRECATED(GET_POISON, "Get Poison List"), ___DEPRECATED(INJECT_POISON, "Inject Poison"), ___DEPRECATED(CLEAR_POISON, "Clear Poison"), ___C(GET_SCAN_MEDIA_CAPS, "Get Scan Media Capabilities"), ___DEPRECATED(SCAN_MEDIA, "Scan Media"), ___DEPRECATED(GET_SCAN_MEDIA, "Get Scan Media Results"), ___C(GET_TIMESTAMP, "Get Timestamp"), ___C(GET_LOG_CAPS, "Get Log Capabilities"), ___C(CLEAR_LOG, "Clear Log"), ___C(GET_SUP_LOG_SUBLIST, "Get Supported Logs Sub-List"), ___C(MAX, "invalid / last command")
 #define ___C(a,b) CXL_MEM_COMMAND_ID_ ##a
 #define ___DEPRECATED(a,b) CXL_MEM_DEPRECATED_ID_ ##a
 enum {
diff --git a/libc/kernel/uapi/linux/devlink.h b/libc/kernel/uapi/linux/devlink.h
index 968d6be..d87c189 100644
--- a/libc/kernel/uapi/linux/devlink.h
+++ b/libc/kernel/uapi/linux/devlink.h
@@ -466,6 +466,7 @@
   DEVLINK_PORT_FN_ATTR_OPSTATE,
   DEVLINK_PORT_FN_ATTR_CAPS,
   DEVLINK_PORT_FN_ATTR_DEVLINK,
+  DEVLINK_PORT_FN_ATTR_MAX_IO_EQS,
   __DEVLINK_PORT_FUNCTION_ATTR_MAX,
   DEVLINK_PORT_FUNCTION_ATTR_MAX = __DEVLINK_PORT_FUNCTION_ATTR_MAX - 1
 };
diff --git a/libc/kernel/uapi/linux/dlm.h b/libc/kernel/uapi/linux/dlm.h
index 3c73908..1344f9b 100644
--- a/libc/kernel/uapi/linux/dlm.h
+++ b/libc/kernel/uapi/linux/dlm.h
@@ -20,4 +20,5 @@
 };
 #define DLM_LSFL_TIMEWARN 0x00000002
 #define DLM_LSFL_NEWEXCL 0x00000008
+#define __DLM_LSFL_RESERVED0 0x00000010
 #endif
diff --git a/libc/kernel/uapi/linux/dma-heap.h b/libc/kernel/uapi/linux/dma-heap.h
index 467e336..ac86b59 100644
--- a/libc/kernel/uapi/linux/dma-heap.h
+++ b/libc/kernel/uapi/linux/dma-heap.h
@@ -9,7 +9,7 @@
 #include <linux/ioctl.h>
 #include <linux/types.h>
 #define DMA_HEAP_VALID_FD_FLAGS (O_CLOEXEC | O_ACCMODE)
-#define DMA_HEAP_VALID_HEAP_FLAGS (0)
+#define DMA_HEAP_VALID_HEAP_FLAGS (0ULL)
 struct dma_heap_allocation_data {
   __u64 len;
   __u32 fd;
diff --git a/libc/kernel/uapi/linux/dvb/frontend.h b/libc/kernel/uapi/linux/dvb/frontend.h
index 64e2cae..9428cc0 100644
--- a/libc/kernel/uapi/linux/dvb/frontend.h
+++ b/libc/kernel/uapi/linux/dvb/frontend.h
@@ -341,7 +341,7 @@
   union {
     __u64 uvalue;
     __s64 svalue;
-  };
+  } __attribute__((packed));
 } __attribute__((packed));
 #define MAX_DTV_STATS 4
 struct dtv_fe_stats {
diff --git a/libc/kernel/uapi/linux/ethtool.h b/libc/kernel/uapi/linux/ethtool.h
index 48b4544..e213ba1 100644
--- a/libc/kernel/uapi/linux/ethtool.h
+++ b/libc/kernel/uapi/linux/ethtool.h
@@ -270,6 +270,75 @@
   ETHTOOL_MODULE_POWER_MODE_LOW = 1,
   ETHTOOL_MODULE_POWER_MODE_HIGH,
 };
+enum ethtool_c33_pse_ext_state {
+  ETHTOOL_C33_PSE_EXT_STATE_ERROR_CONDITION = 1,
+  ETHTOOL_C33_PSE_EXT_STATE_MR_MPS_VALID,
+  ETHTOOL_C33_PSE_EXT_STATE_MR_PSE_ENABLE,
+  ETHTOOL_C33_PSE_EXT_STATE_OPTION_DETECT_TED,
+  ETHTOOL_C33_PSE_EXT_STATE_OPTION_VPORT_LIM,
+  ETHTOOL_C33_PSE_EXT_STATE_OVLD_DETECTED,
+  ETHTOOL_C33_PSE_EXT_STATE_PD_DLL_POWER_TYPE,
+  ETHTOOL_C33_PSE_EXT_STATE_POWER_NOT_AVAILABLE,
+  ETHTOOL_C33_PSE_EXT_STATE_SHORT_DETECTED,
+};
+enum ethtool_c33_pse_ext_substate_mr_mps_valid {
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_MPS_VALID_DETECTED_UNDERLOAD = 1,
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_MPS_VALID_CONNECTION_OPEN,
+};
+enum ethtool_c33_pse_ext_substate_error_condition {
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_NON_EXISTING_PORT = 1,
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNDEFINED_PORT,
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_INTERNAL_HW_FAULT,
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_COMM_ERROR_AFTER_FORCE_ON,
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_UNKNOWN_PORT_STATUS,
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_HOST_CRASH_TURN_OFF,
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_HOST_CRASH_FORCE_SHUTDOWN,
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_CONFIG_CHANGE,
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_ERROR_CONDITION_DETECTED_OVER_TEMP,
+};
+enum ethtool_c33_pse_ext_substate_mr_pse_enable {
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_MR_PSE_ENABLE_DISABLE_PIN_ACTIVE = 1,
+};
+enum ethtool_c33_pse_ext_substate_option_detect_ted {
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_DETECT_TED_DET_IN_PROCESS = 1,
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_DETECT_TED_CONNECTION_CHECK_ERROR,
+};
+enum ethtool_c33_pse_ext_substate_option_vport_lim {
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_HIGH_VOLTAGE = 1,
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_LOW_VOLTAGE,
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_OPTION_VPORT_LIM_VOLTAGE_INJECTION,
+};
+enum ethtool_c33_pse_ext_substate_ovld_detected {
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_OVLD_DETECTED_OVERLOAD = 1,
+};
+enum ethtool_c33_pse_ext_substate_power_not_available {
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_BUDGET_EXCEEDED = 1,
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_PORT_PW_LIMIT_EXCEEDS_CONTROLLER_BUDGET,
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_PD_REQUEST_EXCEEDS_PORT_LIMIT,
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_POWER_NOT_AVAILABLE_HW_PW_LIMIT,
+};
+enum ethtool_c33_pse_ext_substate_short_detected {
+  ETHTOOL_C33_PSE_EXT_SUBSTATE_SHORT_DETECTED_SHORT_CONDITION = 1,
+};
+enum ethtool_pse_types {
+  ETHTOOL_PSE_UNKNOWN = 1 << 0,
+  ETHTOOL_PSE_PODL = 1 << 1,
+  ETHTOOL_PSE_C33 = 1 << 2,
+};
+enum ethtool_c33_pse_admin_state {
+  ETHTOOL_C33_PSE_ADMIN_STATE_UNKNOWN = 1,
+  ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED,
+  ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED,
+};
+enum ethtool_c33_pse_pw_d_status {
+  ETHTOOL_C33_PSE_PW_D_STATUS_UNKNOWN = 1,
+  ETHTOOL_C33_PSE_PW_D_STATUS_DISABLED,
+  ETHTOOL_C33_PSE_PW_D_STATUS_SEARCHING,
+  ETHTOOL_C33_PSE_PW_D_STATUS_DELIVERING,
+  ETHTOOL_C33_PSE_PW_D_STATUS_TEST,
+  ETHTOOL_C33_PSE_PW_D_STATUS_FAULT,
+  ETHTOOL_C33_PSE_PW_D_STATUS_OTHERFAULT,
+};
 enum ethtool_podl_pse_admin_state {
   ETHTOOL_PODL_PSE_ADMIN_STATE_UNKNOWN = 1,
   ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED,
@@ -292,6 +361,12 @@
   ETHTOOL_MM_VERIFY_STATUS_FAILED,
   ETHTOOL_MM_VERIFY_STATUS_DISABLED,
 };
+enum ethtool_module_fw_flash_status {
+  ETHTOOL_MODULE_FW_FLASH_STATUS_STARTED = 1,
+  ETHTOOL_MODULE_FW_FLASH_STATUS_IN_PROGRESS,
+  ETHTOOL_MODULE_FW_FLASH_STATUS_COMPLETED,
+  ETHTOOL_MODULE_FW_FLASH_STATUS_ERROR,
+};
 struct ethtool_gstrings {
   __u32 cmd;
   __u32 string_set;
@@ -730,6 +805,7 @@
   ETHTOOL_LINK_MODE_10baseT1S_Full_BIT = 99,
   ETHTOOL_LINK_MODE_10baseT1S_Half_BIT = 100,
   ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT = 101,
+  ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT = 102,
   __ETHTOOL_LINK_MODE_MASK_NBITS
 };
 #define __ETHTOOL_LINK_MODE_LEGACY_MASK(base_name) (1UL << (ETHTOOL_LINK_MODE_ ##base_name ##_BIT))
diff --git a/libc/kernel/uapi/linux/ethtool_netlink.h b/libc/kernel/uapi/linux/ethtool_netlink.h
index e4fc40e..ac6391a 100644
--- a/libc/kernel/uapi/linux/ethtool_netlink.h
+++ b/libc/kernel/uapi/linux/ethtool_netlink.h
@@ -52,6 +52,7 @@
   ETHTOOL_MSG_PLCA_GET_STATUS,
   ETHTOOL_MSG_MM_GET,
   ETHTOOL_MSG_MM_SET,
+  ETHTOOL_MSG_MODULE_FW_FLASH_ACT,
   __ETHTOOL_MSG_USER_CNT,
   ETHTOOL_MSG_USER_MAX = __ETHTOOL_MSG_USER_CNT - 1
 };
@@ -100,12 +101,15 @@
   ETHTOOL_MSG_PLCA_NTF,
   ETHTOOL_MSG_MM_GET_REPLY,
   ETHTOOL_MSG_MM_NTF,
+  ETHTOOL_MSG_MODULE_FW_FLASH_NTF,
   __ETHTOOL_MSG_KERNEL_CNT,
   ETHTOOL_MSG_KERNEL_MAX = __ETHTOOL_MSG_KERNEL_CNT - 1
 };
-#define ETHTOOL_FLAG_COMPACT_BITSETS (1 << 0)
-#define ETHTOOL_FLAG_OMIT_REPLY (1 << 1)
-#define ETHTOOL_FLAG_STATS (1 << 2)
+enum ethtool_header_flags {
+  ETHTOOL_FLAG_COMPACT_BITSETS = 1 << 0,
+  ETHTOOL_FLAG_OMIT_REPLY = 1 << 1,
+  ETHTOOL_FLAG_STATS = 1 << 2,
+};
 #define ETHTOOL_FLAG_ALL (ETHTOOL_FLAG_COMPACT_BITSETS | ETHTOOL_FLAG_OMIT_REPLY | ETHTOOL_FLAG_STATS)
 enum {
   ETHTOOL_A_HEADER_UNSPEC,
@@ -314,10 +318,26 @@
   ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES,
   ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES,
   ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS,
+  ETHTOOL_A_COALESCE_RX_PROFILE,
+  ETHTOOL_A_COALESCE_TX_PROFILE,
   __ETHTOOL_A_COALESCE_CNT,
   ETHTOOL_A_COALESCE_MAX = (__ETHTOOL_A_COALESCE_CNT - 1)
 };
 enum {
+  ETHTOOL_A_PROFILE_UNSPEC,
+  ETHTOOL_A_PROFILE_IRQ_MODERATION,
+  __ETHTOOL_A_PROFILE_CNT,
+  ETHTOOL_A_PROFILE_MAX = (__ETHTOOL_A_PROFILE_CNT - 1)
+};
+enum {
+  ETHTOOL_A_IRQ_MODERATION_UNSPEC,
+  ETHTOOL_A_IRQ_MODERATION_USEC,
+  ETHTOOL_A_IRQ_MODERATION_PKTS,
+  ETHTOOL_A_IRQ_MODERATION_COMPS,
+  __ETHTOOL_A_IRQ_MODERATION_CNT,
+  ETHTOOL_A_IRQ_MODERATION_MAX = (__ETHTOOL_A_IRQ_MODERATION_CNT - 1)
+};
+enum {
   ETHTOOL_A_PAUSE_UNSPEC,
   ETHTOOL_A_PAUSE_HEADER,
   ETHTOOL_A_PAUSE_AUTONEG,
@@ -355,10 +375,19 @@
   ETHTOOL_A_TSINFO_TX_TYPES,
   ETHTOOL_A_TSINFO_RX_FILTERS,
   ETHTOOL_A_TSINFO_PHC_INDEX,
+  ETHTOOL_A_TSINFO_STATS,
   __ETHTOOL_A_TSINFO_CNT,
   ETHTOOL_A_TSINFO_MAX = (__ETHTOOL_A_TSINFO_CNT - 1)
 };
 enum {
+  ETHTOOL_A_TS_STAT_UNSPEC,
+  ETHTOOL_A_TS_STAT_TX_PKTS,
+  ETHTOOL_A_TS_STAT_TX_LOST,
+  ETHTOOL_A_TS_STAT_TX_ERR,
+  __ETHTOOL_A_TS_STAT_CNT,
+  ETHTOOL_A_TS_STAT_MAX = (__ETHTOOL_A_TS_STAT_CNT - 1)
+};
+enum {
   ETHTOOL_A_PHC_VCLOCKS_UNSPEC,
   ETHTOOL_A_PHC_VCLOCKS_HEADER,
   ETHTOOL_A_PHC_VCLOCKS_NUM,
@@ -378,6 +407,7 @@
   ETHTOOL_A_CABLE_RESULT_CODE_OPEN,
   ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT,
   ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT,
+  ETHTOOL_A_CABLE_RESULT_CODE_IMPEDANCE_MISMATCH,
 };
 enum {
   ETHTOOL_A_CABLE_PAIR_A,
@@ -623,11 +653,25 @@
   ETHTOOL_A_MODULE_MAX = (__ETHTOOL_A_MODULE_CNT - 1)
 };
 enum {
+  ETHTOOL_A_C33_PSE_PW_LIMIT_UNSPEC,
+  ETHTOOL_A_C33_PSE_PW_LIMIT_MIN,
+  ETHTOOL_A_C33_PSE_PW_LIMIT_MAX,
+};
+enum {
   ETHTOOL_A_PSE_UNSPEC,
   ETHTOOL_A_PSE_HEADER,
   ETHTOOL_A_PODL_PSE_ADMIN_STATE,
   ETHTOOL_A_PODL_PSE_ADMIN_CONTROL,
   ETHTOOL_A_PODL_PSE_PW_D_STATUS,
+  ETHTOOL_A_C33_PSE_ADMIN_STATE,
+  ETHTOOL_A_C33_PSE_ADMIN_CONTROL,
+  ETHTOOL_A_C33_PSE_PW_D_STATUS,
+  ETHTOOL_A_C33_PSE_PW_CLASS,
+  ETHTOOL_A_C33_PSE_ACTUAL_PW,
+  ETHTOOL_A_C33_PSE_EXT_STATE,
+  ETHTOOL_A_C33_PSE_EXT_SUBSTATE,
+  ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT,
+  ETHTOOL_A_C33_PSE_PW_LIMIT_RANGES,
   __ETHTOOL_A_PSE_CNT,
   ETHTOOL_A_PSE_MAX = (__ETHTOOL_A_PSE_CNT - 1)
 };
@@ -684,6 +728,18 @@
   __ETHTOOL_A_MM_CNT,
   ETHTOOL_A_MM_MAX = (__ETHTOOL_A_MM_CNT - 1)
 };
+enum {
+  ETHTOOL_A_MODULE_FW_FLASH_UNSPEC,
+  ETHTOOL_A_MODULE_FW_FLASH_HEADER,
+  ETHTOOL_A_MODULE_FW_FLASH_FILE_NAME,
+  ETHTOOL_A_MODULE_FW_FLASH_PASSWORD,
+  ETHTOOL_A_MODULE_FW_FLASH_STATUS,
+  ETHTOOL_A_MODULE_FW_FLASH_STATUS_MSG,
+  ETHTOOL_A_MODULE_FW_FLASH_DONE,
+  ETHTOOL_A_MODULE_FW_FLASH_TOTAL,
+  __ETHTOOL_A_MODULE_FW_FLASH_CNT,
+  ETHTOOL_A_MODULE_FW_FLASH_MAX = (__ETHTOOL_A_MODULE_FW_FLASH_CNT - 1)
+};
 #define ETHTOOL_GENL_NAME "ethtool"
 #define ETHTOOL_GENL_VERSION 1
 #define ETHTOOL_MCGRP_MONITOR_NAME "monitor"
diff --git a/libc/kernel/uapi/linux/fcntl.h b/libc/kernel/uapi/linux/fcntl.h
index 0e5c84d..9f32f9f 100644
--- a/libc/kernel/uapi/linux/fcntl.h
+++ b/libc/kernel/uapi/linux/fcntl.h
@@ -10,9 +10,10 @@
 #include <linux/openat2.h>
 #define F_SETLEASE (F_LINUX_SPECIFIC_BASE + 0)
 #define F_GETLEASE (F_LINUX_SPECIFIC_BASE + 1)
+#define F_NOTIFY (F_LINUX_SPECIFIC_BASE + 2)
+#define F_DUPFD_QUERY (F_LINUX_SPECIFIC_BASE + 3)
 #define F_CANCELLK (F_LINUX_SPECIFIC_BASE + 5)
 #define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
-#define F_NOTIFY (F_LINUX_SPECIFIC_BASE + 2)
 #define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
 #define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8)
 #define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
diff --git a/libc/kernel/uapi/linux/fs.h b/libc/kernel/uapi/linux/fs.h
index 38a2d9e..adab56f 100644
--- a/libc/kernel/uapi/linux/fs.h
+++ b/libc/kernel/uapi/linux/fs.h
@@ -194,8 +194,10 @@
 #define RWF_NOWAIT (( __kernel_rwf_t) 0x00000008)
 #define RWF_APPEND (( __kernel_rwf_t) 0x00000010)
 #define RWF_NOAPPEND (( __kernel_rwf_t) 0x00000020)
-#define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT | RWF_APPEND | RWF_NOAPPEND)
-#define PAGEMAP_SCAN _IOWR('f', 16, struct pm_scan_arg)
+#define RWF_ATOMIC (( __kernel_rwf_t) 0x00000040)
+#define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT | RWF_APPEND | RWF_NOAPPEND | RWF_ATOMIC)
+#define PROCFS_IOCTL_MAGIC 'f'
+#define PAGEMAP_SCAN _IOWR(PROCFS_IOCTL_MAGIC, 16, struct pm_scan_arg)
 #define PAGE_IS_WPALLOWED (1 << 0)
 #define PAGE_IS_WRITTEN (1 << 1)
 #define PAGE_IS_FILE (1 << 2)
@@ -225,4 +227,30 @@
   __u64 category_anyof_mask;
   __u64 return_mask;
 };
+#define PROCMAP_QUERY _IOWR(PROCFS_IOCTL_MAGIC, 17, struct procmap_query)
+enum procmap_query_flags {
+  PROCMAP_QUERY_VMA_READABLE = 0x01,
+  PROCMAP_QUERY_VMA_WRITABLE = 0x02,
+  PROCMAP_QUERY_VMA_EXECUTABLE = 0x04,
+  PROCMAP_QUERY_VMA_SHARED = 0x08,
+  PROCMAP_QUERY_COVERING_OR_NEXT_VMA = 0x10,
+  PROCMAP_QUERY_FILE_BACKED_VMA = 0x20,
+};
+struct procmap_query {
+  __u64 size;
+  __u64 query_flags;
+  __u64 query_addr;
+  __u64 vma_start;
+  __u64 vma_end;
+  __u64 vma_flags;
+  __u64 vma_page_size;
+  __u64 vma_offset;
+  __u64 inode;
+  __u32 dev_major;
+  __u32 dev_minor;
+  __u32 vma_name_size;
+  __u32 build_id_size;
+  __u64 vma_name_addr;
+  __u64 build_id_addr;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/gtp.h b/libc/kernel/uapi/linux/gtp.h
index c828470..5a8cdde 100644
--- a/libc/kernel/uapi/linux/gtp.h
+++ b/libc/kernel/uapi/linux/gtp.h
@@ -31,6 +31,9 @@
   GTPA_I_TEI,
   GTPA_O_TEI,
   GTPA_PAD,
+  GTPA_PEER_ADDR6,
+  GTPA_MS_ADDR6,
+  GTPA_FAMILY,
   __GTPA_MAX,
 };
 #define GTPA_MAX (__GTPA_MAX - 1)
diff --git a/libc/kernel/uapi/linux/icmpv6.h b/libc/kernel/uapi/linux/icmpv6.h
index 9df18ad..a2ca922 100644
--- a/libc/kernel/uapi/linux/icmpv6.h
+++ b/libc/kernel/uapi/linux/icmpv6.h
@@ -81,6 +81,7 @@
 #define ICMPV6_MOBILE_PREFIX_SOL 146
 #define ICMPV6_MOBILE_PREFIX_ADV 147
 #define ICMPV6_MRDISC_ADV 151
+#define ICMPV6_MRDISC_SOL 152
 #define ICMPV6_MSG_MAX 255
 #define ICMPV6_NOROUTE 0
 #define ICMPV6_ADM_PROHIBITED 1
diff --git a/libc/kernel/uapi/linux/if_link.h b/libc/kernel/uapi/linux/if_link.h
index 397adfe..c2483a2 100644
--- a/libc/kernel/uapi/linux/if_link.h
+++ b/libc/kernel/uapi/linux/if_link.h
@@ -610,6 +610,8 @@
   IFLA_GTP_ROLE,
   IFLA_GTP_CREATE_SOCKETS,
   IFLA_GTP_RESTART_COUNT,
+  IFLA_GTP_LOCAL,
+  IFLA_GTP_LOCAL6,
   __IFLA_GTP_MAX,
 };
 #define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1)
@@ -845,6 +847,7 @@
   IFLA_HSR_SEQ_NR,
   IFLA_HSR_VERSION,
   IFLA_HSR_PROTOCOL,
+  IFLA_HSR_INTERLINK,
   __IFLA_HSR_MAX,
 };
 #define IFLA_HSR_MAX (__IFLA_HSR_MAX - 1)
diff --git a/libc/kernel/uapi/linux/if_team.h b/libc/kernel/uapi/linux/if_team.h
index b22be7e..9985f63 100644
--- a/libc/kernel/uapi/linux/if_team.h
+++ b/libc/kernel/uapi/linux/if_team.h
@@ -4,30 +4,25 @@
  * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
  * for more information.
  */
-#ifndef _UAPI_LINUX_IF_TEAM_H_
-#define _UAPI_LINUX_IF_TEAM_H_
+#ifndef _UAPI_LINUX_IF_TEAM_H
+#define _UAPI_LINUX_IF_TEAM_H
+#define TEAM_GENL_NAME "team"
+#define TEAM_GENL_VERSION 1
 #define TEAM_STRING_MAX_LEN 32
-enum {
-  TEAM_CMD_NOOP,
-  TEAM_CMD_OPTIONS_SET,
-  TEAM_CMD_OPTIONS_GET,
-  TEAM_CMD_PORT_LIST_GET,
-  __TEAM_CMD_MAX,
-  TEAM_CMD_MAX = (__TEAM_CMD_MAX - 1),
-};
+#define TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME "change_event"
 enum {
   TEAM_ATTR_UNSPEC,
   TEAM_ATTR_TEAM_IFINDEX,
   TEAM_ATTR_LIST_OPTION,
   TEAM_ATTR_LIST_PORT,
   __TEAM_ATTR_MAX,
-  TEAM_ATTR_MAX = __TEAM_ATTR_MAX - 1,
+  TEAM_ATTR_MAX = (__TEAM_ATTR_MAX - 1)
 };
 enum {
   TEAM_ATTR_ITEM_OPTION_UNSPEC,
   TEAM_ATTR_ITEM_OPTION,
   __TEAM_ATTR_ITEM_OPTION_MAX,
-  TEAM_ATTR_ITEM_OPTION_MAX = __TEAM_ATTR_ITEM_OPTION_MAX - 1,
+  TEAM_ATTR_ITEM_OPTION_MAX = (__TEAM_ATTR_ITEM_OPTION_MAX - 1)
 };
 enum {
   TEAM_ATTR_OPTION_UNSPEC,
@@ -39,13 +34,13 @@
   TEAM_ATTR_OPTION_PORT_IFINDEX,
   TEAM_ATTR_OPTION_ARRAY_INDEX,
   __TEAM_ATTR_OPTION_MAX,
-  TEAM_ATTR_OPTION_MAX = __TEAM_ATTR_OPTION_MAX - 1,
+  TEAM_ATTR_OPTION_MAX = (__TEAM_ATTR_OPTION_MAX - 1)
 };
 enum {
   TEAM_ATTR_ITEM_PORT_UNSPEC,
   TEAM_ATTR_ITEM_PORT,
   __TEAM_ATTR_ITEM_PORT_MAX,
-  TEAM_ATTR_ITEM_PORT_MAX = __TEAM_ATTR_ITEM_PORT_MAX - 1,
+  TEAM_ATTR_ITEM_PORT_MAX = (__TEAM_ATTR_ITEM_PORT_MAX - 1)
 };
 enum {
   TEAM_ATTR_PORT_UNSPEC,
@@ -56,9 +51,14 @@
   TEAM_ATTR_PORT_DUPLEX,
   TEAM_ATTR_PORT_REMOVED,
   __TEAM_ATTR_PORT_MAX,
-  TEAM_ATTR_PORT_MAX = __TEAM_ATTR_PORT_MAX - 1,
+  TEAM_ATTR_PORT_MAX = (__TEAM_ATTR_PORT_MAX - 1)
 };
-#define TEAM_GENL_NAME "team"
-#define TEAM_GENL_VERSION 0x1
-#define TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME "change_event"
+enum {
+  TEAM_CMD_NOOP,
+  TEAM_CMD_OPTIONS_SET,
+  TEAM_CMD_OPTIONS_GET,
+  TEAM_CMD_PORT_LIST_GET,
+  __TEAM_CMD_MAX,
+  TEAM_CMD_MAX = (__TEAM_CMD_MAX - 1)
+};
 #endif
diff --git a/libc/kernel/uapi/linux/if_tunnel.h b/libc/kernel/uapi/linux/if_tunnel.h
index e87daf2..fa6825a 100644
--- a/libc/kernel/uapi/linux/if_tunnel.h
+++ b/libc/kernel/uapi/linux/if_tunnel.h
@@ -159,4 +159,26 @@
 #define TUNNEL_ERSPAN_OPT __cpu_to_be16(0x4000)
 #define TUNNEL_GTP_OPT __cpu_to_be16(0x8000)
 #define TUNNEL_OPTIONS_PRESENT (TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT | TUNNEL_ERSPAN_OPT | TUNNEL_GTP_OPT)
+enum {
+  IP_TUNNEL_CSUM_BIT = 0U,
+  IP_TUNNEL_ROUTING_BIT,
+  IP_TUNNEL_KEY_BIT,
+  IP_TUNNEL_SEQ_BIT,
+  IP_TUNNEL_STRICT_BIT,
+  IP_TUNNEL_REC_BIT,
+  IP_TUNNEL_VERSION_BIT,
+  IP_TUNNEL_NO_KEY_BIT,
+  IP_TUNNEL_DONT_FRAGMENT_BIT,
+  IP_TUNNEL_OAM_BIT,
+  IP_TUNNEL_CRIT_OPT_BIT,
+  IP_TUNNEL_GENEVE_OPT_BIT,
+  IP_TUNNEL_VXLAN_OPT_BIT,
+  IP_TUNNEL_NOCACHE_BIT,
+  IP_TUNNEL_ERSPAN_OPT_BIT,
+  IP_TUNNEL_GTP_OPT_BIT,
+  IP_TUNNEL_VTI_BIT,
+  IP_TUNNEL_SIT_ISATAP_BIT = IP_TUNNEL_VTI_BIT,
+  IP_TUNNEL_PFCP_OPT_BIT,
+  __IP_TUNNEL_FLAG_NUM,
+};
 #endif
diff --git a/libc/kernel/uapi/linux/if_xdp.h b/libc/kernel/uapi/linux/if_xdp.h
index b7eec87..7201e06 100644
--- a/libc/kernel/uapi/linux/if_xdp.h
+++ b/libc/kernel/uapi/linux/if_xdp.h
@@ -14,6 +14,7 @@
 #define XDP_USE_SG (1 << 4)
 #define XDP_UMEM_UNALIGNED_CHUNK_FLAG (1 << 0)
 #define XDP_UMEM_TX_SW_CSUM (1 << 1)
+#define XDP_UMEM_TX_METADATA_LEN (1 << 2)
 struct sockaddr_xdp {
   __u16 sxdp_family;
   __u16 sxdp_flags;
diff --git a/libc/kernel/uapi/linux/iio/buffer.h b/libc/kernel/uapi/linux/iio/buffer.h
index 45c6f65..7e03a8c 100644
--- a/libc/kernel/uapi/linux/iio/buffer.h
+++ b/libc/kernel/uapi/linux/iio/buffer.h
@@ -6,5 +6,16 @@
  */
 #ifndef _UAPI_IIO_BUFFER_H_
 #define _UAPI_IIO_BUFFER_H_
+#include <linux/types.h>
+#define IIO_BUFFER_DMABUF_CYCLIC (1 << 0)
+#define IIO_BUFFER_DMABUF_SUPPORTED_FLAGS 0x00000001
+struct iio_dmabuf {
+  __u32 fd;
+  __u32 flags;
+  __u64 bytes_used;
+};
 #define IIO_BUFFER_GET_FD_IOCTL _IOWR('i', 0x91, int)
+#define IIO_BUFFER_DMABUF_ATTACH_IOCTL _IOW('i', 0x92, int)
+#define IIO_BUFFER_DMABUF_DETACH_IOCTL _IOW('i', 0x93, int)
+#define IIO_BUFFER_DMABUF_ENQUEUE_IOCTL _IOW('i', 0x94, struct iio_dmabuf)
 #endif
diff --git a/libc/kernel/uapi/linux/in.h b/libc/kernel/uapi/linux/in.h
index 44efdd8..97bf493 100644
--- a/libc/kernel/uapi/linux/in.h
+++ b/libc/kernel/uapi/linux/in.h
@@ -69,6 +69,8 @@
 #define IPPROTO_ETHERNET IPPROTO_ETHERNET
   IPPROTO_RAW = 255,
 #define IPPROTO_RAW IPPROTO_RAW
+  IPPROTO_SMC = 256,
+#define IPPROTO_SMC IPPROTO_SMC
   IPPROTO_MPTCP = 262,
 #define IPPROTO_MPTCP IPPROTO_MPTCP
   IPPROTO_MAX
diff --git a/libc/kernel/uapi/linux/input-event-codes.h b/libc/kernel/uapi/linux/input-event-codes.h
index 0fe5a14..4f93d5e 100644
--- a/libc/kernel/uapi/linux/input-event-codes.h
+++ b/libc/kernel/uapi/linux/input-event-codes.h
@@ -543,6 +543,8 @@
 #define KEY_CAMERA_ACCESS_ENABLE 0x24b
 #define KEY_CAMERA_ACCESS_DISABLE 0x24c
 #define KEY_CAMERA_ACCESS_TOGGLE 0x24d
+#define KEY_ACCESSIBILITY 0x24e
+#define KEY_DO_NOT_DISTURB 0x24f
 #define KEY_BRIGHTNESS_MIN 0x250
 #define KEY_BRIGHTNESS_MAX 0x251
 #define KEY_KBDINPUTASSIST_PREV 0x260
diff --git a/libc/kernel/uapi/linux/io_uring.h b/libc/kernel/uapi/linux/io_uring.h
index 10936f2..6b4f2ea 100644
--- a/libc/kernel/uapi/linux/io_uring.h
+++ b/libc/kernel/uapi/linux/io_uring.h
@@ -59,6 +59,7 @@
     __u32 waitid_flags;
     __u32 futex_flags;
     __u32 install_fd_flags;
+    __u32 nop_flags;
   };
   __u64 user_data;
   union {
@@ -85,7 +86,7 @@
   };
 };
 #define IORING_FILE_INDEX_ALLOC (~0U)
-enum {
+enum io_uring_sqe_flags_bit {
   IOSQE_FIXED_FILE_BIT,
   IOSQE_IO_DRAIN_BIT,
   IOSQE_IO_LINK_BIT,
@@ -175,6 +176,8 @@
   IORING_OP_FUTEX_WAITV,
   IORING_OP_FIXED_FD_INSTALL,
   IORING_OP_FTRUNCATE,
+  IORING_OP_BIND,
+  IORING_OP_LISTEN,
   IORING_OP_LAST,
 };
 #define IORING_URING_CMD_FIXED (1U << 0)
@@ -204,15 +207,19 @@
 #define IORING_RECV_MULTISHOT (1U << 1)
 #define IORING_RECVSEND_FIXED_BUF (1U << 2)
 #define IORING_SEND_ZC_REPORT_USAGE (1U << 3)
+#define IORING_RECVSEND_BUNDLE (1U << 4)
 #define IORING_NOTIF_USAGE_ZC_COPIED (1U << 31)
 #define IORING_ACCEPT_MULTISHOT (1U << 0)
-enum {
+#define IORING_ACCEPT_DONTWAIT (1U << 1)
+#define IORING_ACCEPT_POLL_FIRST (1U << 2)
+enum io_uring_msg_ring_flags {
   IORING_MSG_DATA,
   IORING_MSG_SEND_FD,
 };
 #define IORING_MSG_RING_CQE_SKIP (1U << 0)
 #define IORING_MSG_RING_FLAGS_PASS (1U << 1)
 #define IORING_FIXED_FD_NO_CLOEXEC (1U << 0)
+#define IORING_NOP_INJECT_RESULT (1U << 0)
 struct io_uring_cqe {
   __u64 user_data;
   __s32 res;
@@ -223,9 +230,7 @@
 #define IORING_CQE_F_MORE (1U << 1)
 #define IORING_CQE_F_SOCK_NONEMPTY (1U << 2)
 #define IORING_CQE_F_NOTIF (1U << 3)
-enum {
-  IORING_CQE_BUFFER_SHIFT = 16,
-};
+#define IORING_CQE_BUFFER_SHIFT 16
 #define IORING_OFF_SQ_RING 0ULL
 #define IORING_OFF_CQ_RING 0x8000000ULL
 #define IORING_OFF_SQES 0x10000000ULL
@@ -289,7 +294,8 @@
 #define IORING_FEAT_CQE_SKIP (1U << 11)
 #define IORING_FEAT_LINKED_FILE (1U << 12)
 #define IORING_FEAT_REG_REG_RING (1U << 13)
-enum {
+#define IORING_FEAT_RECVSEND_BUNDLE (1U << 14)
+enum io_uring_register_op {
   IORING_REGISTER_BUFFERS = 0,
   IORING_UNREGISTER_BUFFERS = 1,
   IORING_REGISTER_FILES = 2,
@@ -322,7 +328,7 @@
   IORING_REGISTER_LAST,
   IORING_REGISTER_USE_REGISTERED_RING = 1U << 31
 };
-enum {
+enum io_wq_type {
   IO_WQ_BOUND,
   IO_WQ_UNBOUND,
 };
@@ -394,7 +400,7 @@
     __DECLARE_FLEX_ARRAY(struct io_uring_buf, bufs);
   };
 };
-enum {
+enum io_uring_register_pbuf_ring_flags {
   IOU_PBUF_RING_MMAP = 1,
 };
 struct io_uring_buf_reg {
@@ -415,7 +421,7 @@
   __u8 pad[3];
   __u64 resv;
 };
-enum {
+enum io_uring_register_restriction_op {
   IORING_RESTRICTION_REGISTER_OP = 0,
   IORING_RESTRICTION_SQE_OP = 1,
   IORING_RESTRICTION_SQE_FLAGS_ALLOWED = 2,
@@ -448,7 +454,7 @@
   __u32 payloadlen;
   __u32 flags;
 };
-enum {
+enum io_uring_socket_op {
   SOCKET_URING_OP_SIOCINQ = 0,
   SOCKET_URING_OP_SIOCOUTQ,
   SOCKET_URING_OP_GETSOCKOPT,
diff --git a/libc/kernel/uapi/linux/iommu.h b/libc/kernel/uapi/linux/iommu.h
deleted file mode 100644
index 3a7bf82..0000000
--- a/libc/kernel/uapi/linux/iommu.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * This file is auto-generated. Modifications will be lost.
- *
- * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
- * for more information.
- */
-#ifndef _UAPI_IOMMU_H
-#define _UAPI_IOMMU_H
-#include <linux/types.h>
-#define IOMMU_FAULT_PERM_READ (1 << 0)
-#define IOMMU_FAULT_PERM_WRITE (1 << 1)
-#define IOMMU_FAULT_PERM_EXEC (1 << 2)
-#define IOMMU_FAULT_PERM_PRIV (1 << 3)
-enum iommu_fault_type {
-  IOMMU_FAULT_DMA_UNRECOV = 1,
-  IOMMU_FAULT_PAGE_REQ,
-};
-enum iommu_fault_reason {
-  IOMMU_FAULT_REASON_UNKNOWN = 0,
-  IOMMU_FAULT_REASON_PASID_FETCH,
-  IOMMU_FAULT_REASON_BAD_PASID_ENTRY,
-  IOMMU_FAULT_REASON_PASID_INVALID,
-  IOMMU_FAULT_REASON_WALK_EABT,
-  IOMMU_FAULT_REASON_PTE_FETCH,
-  IOMMU_FAULT_REASON_PERMISSION,
-  IOMMU_FAULT_REASON_ACCESS,
-  IOMMU_FAULT_REASON_OOR_ADDRESS,
-};
-struct iommu_fault_unrecoverable {
-  __u32 reason;
-#define IOMMU_FAULT_UNRECOV_PASID_VALID (1 << 0)
-#define IOMMU_FAULT_UNRECOV_ADDR_VALID (1 << 1)
-#define IOMMU_FAULT_UNRECOV_FETCH_ADDR_VALID (1 << 2)
-  __u32 flags;
-  __u32 pasid;
-  __u32 perm;
-  __u64 addr;
-  __u64 fetch_addr;
-};
-struct iommu_fault_page_request {
-#define IOMMU_FAULT_PAGE_REQUEST_PASID_VALID (1 << 0)
-#define IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE (1 << 1)
-#define IOMMU_FAULT_PAGE_REQUEST_PRIV_DATA (1 << 2)
-#define IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID (1 << 3)
-  __u32 flags;
-  __u32 pasid;
-  __u32 grpid;
-  __u32 perm;
-  __u64 addr;
-  __u64 private_data[2];
-};
-struct iommu_fault {
-  __u32 type;
-  __u32 padding;
-  union {
-    struct iommu_fault_unrecoverable event;
-    struct iommu_fault_page_request prm;
-    __u8 padding2[56];
-  };
-};
-enum iommu_page_response_code {
-  IOMMU_PAGE_RESP_SUCCESS = 0,
-  IOMMU_PAGE_RESP_INVALID,
-  IOMMU_PAGE_RESP_FAILURE,
-};
-struct iommu_page_response {
-  __u32 argsz;
-#define IOMMU_PAGE_RESP_VERSION_1 1
-  __u32 version;
-#define IOMMU_PAGE_RESP_PASID_VALID (1 << 0)
-  __u32 flags;
-  __u32 pasid;
-  __u32 grpid;
-  __u32 code;
-};
-#endif
diff --git a/libc/kernel/uapi/linux/iommufd.h b/libc/kernel/uapi/linux/iommufd.h
index 2570628..6f663b4 100644
--- a/libc/kernel/uapi/linux/iommufd.h
+++ b/libc/kernel/uapi/linux/iommufd.h
@@ -12,19 +12,20 @@
 enum {
   IOMMUFD_CMD_BASE = 0x80,
   IOMMUFD_CMD_DESTROY = IOMMUFD_CMD_BASE,
-  IOMMUFD_CMD_IOAS_ALLOC,
-  IOMMUFD_CMD_IOAS_ALLOW_IOVAS,
-  IOMMUFD_CMD_IOAS_COPY,
-  IOMMUFD_CMD_IOAS_IOVA_RANGES,
-  IOMMUFD_CMD_IOAS_MAP,
-  IOMMUFD_CMD_IOAS_UNMAP,
-  IOMMUFD_CMD_OPTION,
-  IOMMUFD_CMD_VFIO_IOAS,
-  IOMMUFD_CMD_HWPT_ALLOC,
-  IOMMUFD_CMD_GET_HW_INFO,
-  IOMMUFD_CMD_HWPT_SET_DIRTY_TRACKING,
-  IOMMUFD_CMD_HWPT_GET_DIRTY_BITMAP,
-  IOMMUFD_CMD_HWPT_INVALIDATE,
+  IOMMUFD_CMD_IOAS_ALLOC = 0x81,
+  IOMMUFD_CMD_IOAS_ALLOW_IOVAS = 0x82,
+  IOMMUFD_CMD_IOAS_COPY = 0x83,
+  IOMMUFD_CMD_IOAS_IOVA_RANGES = 0x84,
+  IOMMUFD_CMD_IOAS_MAP = 0x85,
+  IOMMUFD_CMD_IOAS_UNMAP = 0x86,
+  IOMMUFD_CMD_OPTION = 0x87,
+  IOMMUFD_CMD_VFIO_IOAS = 0x88,
+  IOMMUFD_CMD_HWPT_ALLOC = 0x89,
+  IOMMUFD_CMD_GET_HW_INFO = 0x8a,
+  IOMMUFD_CMD_HWPT_SET_DIRTY_TRACKING = 0x8b,
+  IOMMUFD_CMD_HWPT_GET_DIRTY_BITMAP = 0x8c,
+  IOMMUFD_CMD_HWPT_INVALIDATE = 0x8d,
+  IOMMUFD_CMD_FAULT_QUEUE_ALLOC = 0x8e,
 };
 struct iommu_destroy {
   __u32 size;
@@ -122,6 +123,7 @@
 enum iommufd_hwpt_alloc_flags {
   IOMMU_HWPT_ALLOC_NEST_PARENT = 1 << 0,
   IOMMU_HWPT_ALLOC_DIRTY_TRACKING = 1 << 1,
+  IOMMU_HWPT_FAULT_ID_VALID = 1 << 2,
 };
 enum iommu_hwpt_vtd_s1_flags {
   IOMMU_VTD_S1_SRE = 1 << 0,
@@ -135,8 +137,8 @@
   __u32 __reserved;
 };
 enum iommu_hwpt_data_type {
-  IOMMU_HWPT_DATA_NONE,
-  IOMMU_HWPT_DATA_VTD_S1,
+  IOMMU_HWPT_DATA_NONE = 0,
+  IOMMU_HWPT_DATA_VTD_S1 = 1,
 };
 struct iommu_hwpt_alloc {
   __u32 size;
@@ -148,6 +150,8 @@
   __u32 data_type;
   __u32 data_len;
   __aligned_u64 data_uptr;
+  __u32 fault_id;
+  __u32 __reserved2;
 };
 #define IOMMU_HWPT_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_ALLOC)
 enum iommu_hw_info_vtd_flags {
@@ -160,8 +164,8 @@
   __aligned_u64 ecap_reg;
 };
 enum iommu_hw_info_type {
-  IOMMU_HW_INFO_TYPE_NONE,
-  IOMMU_HW_INFO_TYPE_INTEL_VTD,
+  IOMMU_HW_INFO_TYPE_NONE = 0,
+  IOMMU_HW_INFO_TYPE_INTEL_VTD = 1,
 };
 enum iommufd_hw_capabilities {
   IOMMU_HW_CAP_DIRTY_TRACKING = 1 << 0,
@@ -202,7 +206,7 @@
 };
 #define IOMMU_HWPT_GET_DIRTY_BITMAP _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_GET_DIRTY_BITMAP)
 enum iommu_hwpt_invalidate_data_type {
-  IOMMU_HWPT_INVALIDATE_DATA_VTD_S1,
+  IOMMU_HWPT_INVALIDATE_DATA_VTD_S1 = 0,
 };
 enum iommu_hwpt_vtd_s1_invalidate_flags {
   IOMMU_VTD_INV_FLAGS_LEAF = 1 << 0,
@@ -223,4 +227,39 @@
   __u32 __reserved;
 };
 #define IOMMU_HWPT_INVALIDATE _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_INVALIDATE)
+enum iommu_hwpt_pgfault_flags {
+  IOMMU_PGFAULT_FLAGS_PASID_VALID = (1 << 0),
+  IOMMU_PGFAULT_FLAGS_LAST_PAGE = (1 << 1),
+};
+enum iommu_hwpt_pgfault_perm {
+  IOMMU_PGFAULT_PERM_READ = (1 << 0),
+  IOMMU_PGFAULT_PERM_WRITE = (1 << 1),
+  IOMMU_PGFAULT_PERM_EXEC = (1 << 2),
+  IOMMU_PGFAULT_PERM_PRIV = (1 << 3),
+};
+struct iommu_hwpt_pgfault {
+  __u32 flags;
+  __u32 dev_id;
+  __u32 pasid;
+  __u32 grpid;
+  __u32 perm;
+  __u64 addr;
+  __u32 length;
+  __u32 cookie;
+};
+enum iommufd_page_response_code {
+  IOMMUFD_PAGE_RESP_SUCCESS = 0,
+  IOMMUFD_PAGE_RESP_INVALID = 1,
+};
+struct iommu_hwpt_page_response {
+  __u32 cookie;
+  __u32 code;
+};
+struct iommu_fault_alloc {
+  __u32 size;
+  __u32 flags;
+  __u32 out_fault_id;
+  __u32 out_fault_fd;
+};
+#define IOMMU_FAULT_QUEUE_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_FAULT_QUEUE_ALLOC)
 #endif
diff --git a/libc/kernel/uapi/linux/kexec.h b/libc/kernel/uapi/linux/kexec.h
index c5c8623..d34f065 100644
--- a/libc/kernel/uapi/linux/kexec.h
+++ b/libc/kernel/uapi/linux/kexec.h
@@ -10,6 +10,7 @@
 #define KEXEC_ON_CRASH 0x00000001
 #define KEXEC_PRESERVE_CONTEXT 0x00000002
 #define KEXEC_UPDATE_ELFCOREHDR 0x00000004
+#define KEXEC_CRASH_HOTPLUG_SUPPORT 0x00000008
 #define KEXEC_ARCH_MASK 0xffff0000
 #define KEXEC_FILE_UNLOAD 0x00000001
 #define KEXEC_FILE_ON_CRASH 0x00000002
diff --git a/libc/kernel/uapi/linux/kfd_ioctl.h b/libc/kernel/uapi/linux/kfd_ioctl.h
index 62c9872..193dd8e 100644
--- a/libc/kernel/uapi/linux/kfd_ioctl.h
+++ b/libc/kernel/uapi/linux/kfd_ioctl.h
@@ -9,7 +9,7 @@
 #include <drm/drm.h>
 #include <linux/ioctl.h>
 #define KFD_IOCTL_MAJOR_VERSION 1
-#define KFD_IOCTL_MINOR_VERSION 15
+#define KFD_IOCTL_MINOR_VERSION 16
 struct kfd_ioctl_get_version_args {
   __u32 major_version;
   __u32 minor_version;
@@ -269,6 +269,7 @@
 #define KFD_IOC_ALLOC_MEM_FLAGS_COHERENT (1 << 26)
 #define KFD_IOC_ALLOC_MEM_FLAGS_UNCACHED (1 << 25)
 #define KFD_IOC_ALLOC_MEM_FLAGS_EXT_COHERENT (1 << 24)
+#define KFD_IOC_ALLOC_MEM_FLAGS_CONTIGUOUS (1 << 23)
 struct kfd_ioctl_alloc_memory_of_gpu_args {
   __u64 va_addr;
   __u64 size;
@@ -465,6 +466,7 @@
 };
 enum kfd_dbg_trap_flags {
   KFD_DBG_TRAP_FLAG_SINGLE_MEM_OP = 1,
+  KFD_DBG_TRAP_FLAG_SINGLE_ALU_OP = 2,
 };
 enum kfd_dbg_trap_exception_code {
   EC_NONE = 0,
diff --git a/libc/kernel/uapi/linux/kfd_sysfs.h b/libc/kernel/uapi/linux/kfd_sysfs.h
index e538cf2..7771582 100644
--- a/libc/kernel/uapi/linux/kfd_sysfs.h
+++ b/libc/kernel/uapi/linux/kfd_sysfs.h
@@ -35,7 +35,8 @@
 #define HSA_CAP_SVMAPI_SUPPORTED 0x08000000
 #define HSA_CAP_FLAGS_COHERENTHOSTACCESS 0x10000000
 #define HSA_CAP_TRAP_DEBUG_FIRMWARE_SUPPORTED 0x20000000
-#define HSA_CAP_RESERVED 0xe00f8000
+#define HSA_CAP_TRAP_DEBUG_PRECISE_ALU_OPERATIONS_SUPPORTED 0x40000000
+#define HSA_CAP_RESERVED 0x800f8000
 #define HSA_DBG_WATCH_ADDR_MASK_LO_BIT_MASK 0x0000000f
 #define HSA_DBG_WATCH_ADDR_MASK_LO_BIT_SHIFT 0
 #define HSA_DBG_WATCH_ADDR_MASK_HI_BIT_MASK 0x000003f0
diff --git a/libc/kernel/uapi/linux/kvm.h b/libc/kernel/uapi/linux/kvm.h
index ffaf5e6..297a09d 100644
--- a/libc/kernel/uapi/linux/kvm.h
+++ b/libc/kernel/uapi/linux/kvm.h
@@ -149,9 +149,10 @@
 #define KVM_INTERNAL_ERROR_DELIVERY_EV 3
 #define KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON 4
 #define KVM_INTERNAL_ERROR_EMULATION_FLAG_INSTRUCTION_BYTES (1ULL << 0)
+#define HINT_UNSAFE_IN_KVM(_symbol) _symbol
 struct kvm_run {
   __u8 request_interrupt_window;
-  __u8 immediate_exit;
+  __u8 HINT_UNSAFE_IN_KVM(immediate_exit);
   __u8 padding1[6];
   __u32 exit_reason;
   __u8 ready_for_interrupt_injection;
@@ -719,6 +720,9 @@
 #define KVM_CAP_MEMORY_ATTRIBUTES 233
 #define KVM_CAP_GUEST_MEMFD 234
 #define KVM_CAP_VM_TYPES 235
+#define KVM_CAP_PRE_FAULT_MEMORY 236
+#define KVM_CAP_X86_APIC_BUS_CYCLES_NS 237
+#define KVM_CAP_X86_GUEST_MODE 238
 struct kvm_irq_routing_irqchip {
   __u32 irqchip;
   __u32 pin;
@@ -1109,4 +1113,11 @@
   __u64 flags;
   __u64 reserved[6];
 };
+#define KVM_PRE_FAULT_MEMORY _IOWR(KVMIO, 0xd5, struct kvm_pre_fault_memory)
+struct kvm_pre_fault_memory {
+  __u64 gpa;
+  __u64 size;
+  __u64 flags;
+  __u64 padding[5];
+};
 #endif
diff --git a/libc/kernel/uapi/linux/landlock.h b/libc/kernel/uapi/linux/landlock.h
index 75d3037..f903ae6 100644
--- a/libc/kernel/uapi/linux/landlock.h
+++ b/libc/kernel/uapi/linux/landlock.h
@@ -39,6 +39,7 @@
 #define LANDLOCK_ACCESS_FS_MAKE_SYM (1ULL << 12)
 #define LANDLOCK_ACCESS_FS_REFER (1ULL << 13)
 #define LANDLOCK_ACCESS_FS_TRUNCATE (1ULL << 14)
+#define LANDLOCK_ACCESS_FS_IOCTL_DEV (1ULL << 15)
 #define LANDLOCK_ACCESS_NET_BIND_TCP (1ULL << 0)
 #define LANDLOCK_ACCESS_NET_CONNECT_TCP (1ULL << 1)
 #endif
diff --git a/libc/kernel/uapi/linux/magic.h b/libc/kernel/uapi/linux/magic.h
index 4d24726..5f2a2a2 100644
--- a/libc/kernel/uapi/linux/magic.h
+++ b/libc/kernel/uapi/linux/magic.h
@@ -41,6 +41,7 @@
 #define HOSTFS_SUPER_MAGIC 0x00c0ffee
 #define OVERLAYFS_SUPER_MAGIC 0x794c7630
 #define FUSE_SUPER_MAGIC 0x65735546
+#define BCACHEFS_SUPER_MAGIC 0xca451a4e
 #define MINIX_SUPER_MAGIC 0x137F
 #define MINIX_SUPER_MAGIC2 0x138F
 #define MINIX2_SUPER_MAGIC 0x2468
diff --git a/libc/kernel/uapi/linux/media-bus-format.h b/libc/kernel/uapi/linux/media-bus-format.h
index 230bfbb..cb36554 100644
--- a/libc/kernel/uapi/linux/media-bus-format.h
+++ b/libc/kernel/uapi/linux/media-bus-format.h
@@ -126,4 +126,11 @@
 #define MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8 0x5001
 #define MEDIA_BUS_FMT_AHSV8888_1X32 0x6001
 #define MEDIA_BUS_FMT_METADATA_FIXED 0x7001
+#define MEDIA_BUS_FMT_META_8 0x8001
+#define MEDIA_BUS_FMT_META_10 0x8002
+#define MEDIA_BUS_FMT_META_12 0x8003
+#define MEDIA_BUS_FMT_META_14 0x8004
+#define MEDIA_BUS_FMT_META_16 0x8005
+#define MEDIA_BUS_FMT_META_20 0x8006
+#define MEDIA_BUS_FMT_META_24 0x8007
 #endif
diff --git a/libc/kernel/uapi/linux/media/raspberrypi/pisp_be_config.h b/libc/kernel/uapi/linux/media/raspberrypi/pisp_be_config.h
new file mode 100644
index 0000000..2e981ad
--- /dev/null
+++ b/libc/kernel/uapi/linux/media/raspberrypi/pisp_be_config.h
@@ -0,0 +1,418 @@
+/*
+ * This file is auto-generated. Modifications will be lost.
+ *
+ * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
+ * for more information.
+ */
+#ifndef _UAPI_PISP_BE_CONFIG_H_
+#define _UAPI_PISP_BE_CONFIG_H_
+#include <linux/types.h>
+#include "pisp_common.h"
+#define PISP_BACK_END_INPUT_ALIGN 4u
+#define PISP_BACK_END_COMPRESSED_ALIGN 8u
+#define PISP_BACK_END_OUTPUT_MIN_ALIGN 16u
+#define PISP_BACK_END_OUTPUT_MAX_ALIGN 64u
+#define PISP_BACK_END_MIN_TILE_WIDTH 16u
+#define PISP_BACK_END_MIN_TILE_HEIGHT 16u
+#define PISP_BACK_END_NUM_OUTPUTS 2
+#define PISP_BACK_END_HOG_OUTPUT 1
+#define PISP_BACK_END_NUM_TILES 64
+enum pisp_be_bayer_enable {
+  PISP_BE_BAYER_ENABLE_INPUT = 0x000001,
+  PISP_BE_BAYER_ENABLE_DECOMPRESS = 0x000002,
+  PISP_BE_BAYER_ENABLE_DPC = 0x000004,
+  PISP_BE_BAYER_ENABLE_GEQ = 0x000008,
+  PISP_BE_BAYER_ENABLE_TDN_INPUT = 0x000010,
+  PISP_BE_BAYER_ENABLE_TDN_DECOMPRESS = 0x000020,
+  PISP_BE_BAYER_ENABLE_TDN = 0x000040,
+  PISP_BE_BAYER_ENABLE_TDN_COMPRESS = 0x000080,
+  PISP_BE_BAYER_ENABLE_TDN_OUTPUT = 0x000100,
+  PISP_BE_BAYER_ENABLE_SDN = 0x000200,
+  PISP_BE_BAYER_ENABLE_BLC = 0x000400,
+  PISP_BE_BAYER_ENABLE_STITCH_INPUT = 0x000800,
+  PISP_BE_BAYER_ENABLE_STITCH_DECOMPRESS = 0x001000,
+  PISP_BE_BAYER_ENABLE_STITCH = 0x002000,
+  PISP_BE_BAYER_ENABLE_STITCH_COMPRESS = 0x004000,
+  PISP_BE_BAYER_ENABLE_STITCH_OUTPUT = 0x008000,
+  PISP_BE_BAYER_ENABLE_WBG = 0x010000,
+  PISP_BE_BAYER_ENABLE_CDN = 0x020000,
+  PISP_BE_BAYER_ENABLE_LSC = 0x040000,
+  PISP_BE_BAYER_ENABLE_TONEMAP = 0x080000,
+  PISP_BE_BAYER_ENABLE_CAC = 0x100000,
+  PISP_BE_BAYER_ENABLE_DEBIN = 0x200000,
+  PISP_BE_BAYER_ENABLE_DEMOSAIC = 0x400000,
+};
+enum pisp_be_rgb_enable {
+  PISP_BE_RGB_ENABLE_INPUT = 0x000001,
+  PISP_BE_RGB_ENABLE_CCM = 0x000002,
+  PISP_BE_RGB_ENABLE_SAT_CONTROL = 0x000004,
+  PISP_BE_RGB_ENABLE_YCBCR = 0x000008,
+  PISP_BE_RGB_ENABLE_FALSE_COLOUR = 0x000010,
+  PISP_BE_RGB_ENABLE_SHARPEN = 0x000020,
+  PISP_BE_RGB_ENABLE_YCBCR_INVERSE = 0x000080,
+  PISP_BE_RGB_ENABLE_GAMMA = 0x000100,
+  PISP_BE_RGB_ENABLE_CSC0 = 0x000200,
+  PISP_BE_RGB_ENABLE_CSC1 = 0x000400,
+  PISP_BE_RGB_ENABLE_DOWNSCALE0 = 0x001000,
+  PISP_BE_RGB_ENABLE_DOWNSCALE1 = 0x002000,
+  PISP_BE_RGB_ENABLE_RESAMPLE0 = 0x008000,
+  PISP_BE_RGB_ENABLE_RESAMPLE1 = 0x010000,
+  PISP_BE_RGB_ENABLE_OUTPUT0 = 0x040000,
+  PISP_BE_RGB_ENABLE_OUTPUT1 = 0x080000,
+  PISP_BE_RGB_ENABLE_HOG = 0x200000
+};
+#define PISP_BE_RGB_ENABLE_CSC(i) (PISP_BE_RGB_ENABLE_CSC0 << (i))
+#define PISP_BE_RGB_ENABLE_DOWNSCALE(i) (PISP_BE_RGB_ENABLE_DOWNSCALE0 << (i))
+#define PISP_BE_RGB_ENABLE_RESAMPLE(i) (PISP_BE_RGB_ENABLE_RESAMPLE0 << (i))
+#define PISP_BE_RGB_ENABLE_OUTPUT(i) (PISP_BE_RGB_ENABLE_OUTPUT0 << (i))
+enum pisp_be_dirty {
+  PISP_BE_DIRTY_GLOBAL = 0x0001,
+  PISP_BE_DIRTY_SH_FC_COMBINE = 0x0002,
+  PISP_BE_DIRTY_CROP = 0x0004
+};
+struct pisp_be_global_config {
+  __u32 bayer_enables;
+  __u32 rgb_enables;
+  __u8 bayer_order;
+  __u8 pad[3];
+} __attribute__((packed));
+struct pisp_be_input_buffer_config {
+  __u32 addr[3][2];
+} __attribute__((packed));
+struct pisp_be_dpc_config {
+  __u8 coeff_level;
+  __u8 coeff_range;
+  __u8 pad;
+#define PISP_BE_DPC_FLAG_FOLDBACK 1
+  __u8 flags;
+} __attribute__((packed));
+struct pisp_be_geq_config {
+  __u16 offset;
+#define PISP_BE_GEQ_SHARPER (1U << 15)
+#define PISP_BE_GEQ_SLOPE ((1 << 10) - 1)
+  __u16 slope_sharper;
+  __u16 min;
+  __u16 max;
+} __attribute__((packed));
+struct pisp_be_tdn_input_buffer_config {
+  __u32 addr[2];
+} __attribute__((packed));
+struct pisp_be_tdn_config {
+  __u16 black_level;
+  __u16 ratio;
+  __u16 noise_constant;
+  __u16 noise_slope;
+  __u16 threshold;
+  __u8 reset;
+  __u8 pad;
+} __attribute__((packed));
+struct pisp_be_tdn_output_buffer_config {
+  __u32 addr[2];
+} __attribute__((packed));
+struct pisp_be_sdn_config {
+  __u16 black_level;
+  __u8 leakage;
+  __u8 pad;
+  __u16 noise_constant;
+  __u16 noise_slope;
+  __u16 noise_constant2;
+  __u16 noise_slope2;
+} __attribute__((packed));
+struct pisp_be_stitch_input_buffer_config {
+  __u32 addr[2];
+} __attribute__((packed));
+#define PISP_BE_STITCH_STREAMING_LONG 0x8000
+#define PISP_BE_STITCH_EXPOSURE_RATIO_MASK 0x7fff
+struct pisp_be_stitch_config {
+  __u16 threshold_lo;
+  __u8 threshold_diff_power;
+  __u8 pad;
+  __u16 exposure_ratio;
+  __u8 motion_threshold_256;
+  __u8 motion_threshold_recip;
+} __attribute__((packed));
+struct pisp_be_stitch_output_buffer_config {
+  __u32 addr[2];
+} __attribute__((packed));
+struct pisp_be_cdn_config {
+  __u16 thresh;
+  __u8 iir_strength;
+  __u8 g_adjust;
+} __attribute__((packed));
+#define PISP_BE_LSC_LOG_GRID_SIZE 5
+#define PISP_BE_LSC_GRID_SIZE (1 << PISP_BE_LSC_LOG_GRID_SIZE)
+#define PISP_BE_LSC_STEP_PRECISION 18
+struct pisp_be_lsc_config {
+  __u16 grid_step_x;
+  __u16 grid_step_y;
+#define PISP_BE_LSC_LUT_SIZE (PISP_BE_LSC_GRID_SIZE + 1)
+  __u32 lut_packed[PISP_BE_LSC_LUT_SIZE][PISP_BE_LSC_LUT_SIZE];
+} __attribute__((packed));
+struct pisp_be_lsc_extra {
+  __u16 offset_x;
+  __u16 offset_y;
+} __attribute__((packed));
+#define PISP_BE_CAC_LOG_GRID_SIZE 3
+#define PISP_BE_CAC_GRID_SIZE (1 << PISP_BE_CAC_LOG_GRID_SIZE)
+#define PISP_BE_CAC_STEP_PRECISION 20
+struct pisp_be_cac_config {
+  __u16 grid_step_x;
+  __u16 grid_step_y;
+#define PISP_BE_CAC_LUT_SIZE (PISP_BE_CAC_GRID_SIZE + 1)
+  __s8 lut[PISP_BE_CAC_LUT_SIZE][PISP_BE_CAC_LUT_SIZE][2][2];
+} __attribute__((packed));
+struct pisp_be_cac_extra {
+  __u16 offset_x;
+  __u16 offset_y;
+} __attribute__((packed));
+#define PISP_BE_DEBIN_NUM_COEFFS 4
+struct pisp_be_debin_config {
+  __s8 coeffs[PISP_BE_DEBIN_NUM_COEFFS];
+  __s8 h_enable;
+  __s8 v_enable;
+  __s8 pad[2];
+} __attribute__((packed));
+#define PISP_BE_TONEMAP_LUT_SIZE 64
+struct pisp_be_tonemap_config {
+  __u16 detail_constant;
+  __u16 detail_slope;
+  __u16 iir_strength;
+  __u16 strength;
+  __u32 lut[PISP_BE_TONEMAP_LUT_SIZE];
+} __attribute__((packed));
+struct pisp_be_demosaic_config {
+  __u8 sharper;
+  __u8 fc_mode;
+  __u8 pad[2];
+} __attribute__((packed));
+struct pisp_be_ccm_config {
+  __s16 coeffs[9];
+  __u8 pad[2];
+  __s32 offsets[3];
+} __attribute__((packed));
+struct pisp_be_sat_control_config {
+  __u8 shift_r;
+  __u8 shift_g;
+  __u8 shift_b;
+  __u8 pad;
+} __attribute__((packed));
+struct pisp_be_false_colour_config {
+  __u8 distance;
+  __u8 pad[3];
+} __attribute__((packed));
+#define PISP_BE_SHARPEN_SIZE 5
+#define PISP_BE_SHARPEN_FUNC_NUM_POINTS 9
+struct pisp_be_sharpen_config {
+  __s8 kernel0[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE];
+  __s8 pad0[3];
+  __s8 kernel1[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE];
+  __s8 pad1[3];
+  __s8 kernel2[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE];
+  __s8 pad2[3];
+  __s8 kernel3[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE];
+  __s8 pad3[3];
+  __s8 kernel4[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE];
+  __s8 pad4[3];
+  __u16 threshold_offset0;
+  __u16 threshold_slope0;
+  __u16 scale0;
+  __u16 pad5;
+  __u16 threshold_offset1;
+  __u16 threshold_slope1;
+  __u16 scale1;
+  __u16 pad6;
+  __u16 threshold_offset2;
+  __u16 threshold_slope2;
+  __u16 scale2;
+  __u16 pad7;
+  __u16 threshold_offset3;
+  __u16 threshold_slope3;
+  __u16 scale3;
+  __u16 pad8;
+  __u16 threshold_offset4;
+  __u16 threshold_slope4;
+  __u16 scale4;
+  __u16 pad9;
+  __u16 positive_strength;
+  __u16 positive_pre_limit;
+  __u16 positive_func[PISP_BE_SHARPEN_FUNC_NUM_POINTS];
+  __u16 positive_limit;
+  __u16 negative_strength;
+  __u16 negative_pre_limit;
+  __u16 negative_func[PISP_BE_SHARPEN_FUNC_NUM_POINTS];
+  __u16 negative_limit;
+  __u8 enables;
+  __u8 white;
+  __u8 black;
+  __u8 grey;
+} __attribute__((packed));
+struct pisp_be_sh_fc_combine_config {
+  __u8 y_factor;
+  __u8 c1_factor;
+  __u8 c2_factor;
+  __u8 pad;
+} __attribute__((packed));
+#define PISP_BE_GAMMA_LUT_SIZE 64
+struct pisp_be_gamma_config {
+  __u32 lut[PISP_BE_GAMMA_LUT_SIZE];
+} __attribute__((packed));
+struct pisp_be_crop_config {
+  __u16 offset_x, offset_y;
+  __u16 width, height;
+} __attribute__((packed));
+#define PISP_BE_RESAMPLE_FILTER_SIZE 96
+struct pisp_be_resample_config {
+  __u16 scale_factor_h, scale_factor_v;
+  __s16 coef[PISP_BE_RESAMPLE_FILTER_SIZE];
+} __attribute__((packed));
+struct pisp_be_resample_extra {
+  __u16 scaled_width;
+  __u16 scaled_height;
+  __s16 initial_phase_h[3];
+  __s16 initial_phase_v[3];
+} __attribute__((packed));
+struct pisp_be_downscale_config {
+  __u16 scale_factor_h;
+  __u16 scale_factor_v;
+  __u16 scale_recip_h;
+  __u16 scale_recip_v;
+} __attribute__((packed));
+struct pisp_be_downscale_extra {
+  __u16 scaled_width;
+  __u16 scaled_height;
+} __attribute__((packed));
+struct pisp_be_hog_config {
+  __u8 compute_signed;
+  __u8 channel_mix[3];
+  __u32 stride;
+} __attribute__((packed));
+struct pisp_be_axi_config {
+  __u8 r_qos;
+  __u8 r_cache_prot;
+  __u8 w_qos;
+  __u8 w_cache_prot;
+} __attribute__((packed));
+enum pisp_be_transform {
+  PISP_BE_TRANSFORM_NONE = 0x0,
+  PISP_BE_TRANSFORM_HFLIP = 0x1,
+  PISP_BE_TRANSFORM_VFLIP = 0x2,
+  PISP_BE_TRANSFORM_ROT180 = (PISP_BE_TRANSFORM_HFLIP | PISP_BE_TRANSFORM_VFLIP)
+};
+struct pisp_be_output_format_config {
+  struct pisp_image_format_config image;
+  __u8 transform;
+  __u8 pad[3];
+  __u16 lo;
+  __u16 hi;
+  __u16 lo2;
+  __u16 hi2;
+} __attribute__((packed));
+struct pisp_be_output_buffer_config {
+  __u32 addr[3][2];
+} __attribute__((packed));
+struct pisp_be_hog_buffer_config {
+  __u32 addr[2];
+} __attribute__((packed));
+struct pisp_be_config {
+  struct pisp_be_input_buffer_config input_buffer;
+  struct pisp_be_tdn_input_buffer_config tdn_input_buffer;
+  struct pisp_be_stitch_input_buffer_config stitch_input_buffer;
+  struct pisp_be_tdn_output_buffer_config tdn_output_buffer;
+  struct pisp_be_stitch_output_buffer_config stitch_output_buffer;
+  struct pisp_be_output_buffer_config output_buffer[PISP_BACK_END_NUM_OUTPUTS];
+  struct pisp_be_hog_buffer_config hog_buffer;
+  struct pisp_be_global_config global;
+  struct pisp_image_format_config input_format;
+  struct pisp_decompress_config decompress;
+  struct pisp_be_dpc_config dpc;
+  struct pisp_be_geq_config geq;
+  struct pisp_image_format_config tdn_input_format;
+  struct pisp_decompress_config tdn_decompress;
+  struct pisp_be_tdn_config tdn;
+  struct pisp_compress_config tdn_compress;
+  struct pisp_image_format_config tdn_output_format;
+  struct pisp_be_sdn_config sdn;
+  struct pisp_bla_config blc;
+  struct pisp_compress_config stitch_compress;
+  struct pisp_image_format_config stitch_output_format;
+  struct pisp_image_format_config stitch_input_format;
+  struct pisp_decompress_config stitch_decompress;
+  struct pisp_be_stitch_config stitch;
+  struct pisp_be_lsc_config lsc;
+  struct pisp_wbg_config wbg;
+  struct pisp_be_cdn_config cdn;
+  struct pisp_be_cac_config cac;
+  struct pisp_be_debin_config debin;
+  struct pisp_be_tonemap_config tonemap;
+  struct pisp_be_demosaic_config demosaic;
+  struct pisp_be_ccm_config ccm;
+  struct pisp_be_sat_control_config sat_control;
+  struct pisp_be_ccm_config ycbcr;
+  struct pisp_be_sharpen_config sharpen;
+  struct pisp_be_false_colour_config false_colour;
+  struct pisp_be_sh_fc_combine_config sh_fc_combine;
+  struct pisp_be_ccm_config ycbcr_inverse;
+  struct pisp_be_gamma_config gamma;
+  struct pisp_be_ccm_config csc[PISP_BACK_END_NUM_OUTPUTS];
+  struct pisp_be_downscale_config downscale[PISP_BACK_END_NUM_OUTPUTS];
+  struct pisp_be_resample_config resample[PISP_BACK_END_NUM_OUTPUTS];
+  struct pisp_be_output_format_config output_format[PISP_BACK_END_NUM_OUTPUTS];
+  struct pisp_be_hog_config hog;
+  struct pisp_be_axi_config axi;
+  struct pisp_be_lsc_extra lsc_extra;
+  struct pisp_be_cac_extra cac_extra;
+  struct pisp_be_downscale_extra downscale_extra[PISP_BACK_END_NUM_OUTPUTS];
+  struct pisp_be_resample_extra resample_extra[PISP_BACK_END_NUM_OUTPUTS];
+  struct pisp_be_crop_config crop;
+  struct pisp_image_format_config hog_format;
+  __u32 dirty_flags_bayer;
+  __u32 dirty_flags_rgb;
+  __u32 dirty_flags_extra;
+} __attribute__((packed));
+enum pisp_tile_edge {
+  PISP_LEFT_EDGE = (1 << 0),
+  PISP_RIGHT_EDGE = (1 << 1),
+  PISP_TOP_EDGE = (1 << 2),
+  PISP_BOTTOM_EDGE = (1 << 3)
+};
+struct pisp_tile {
+  __u8 edge;
+  __u8 pad0[3];
+  __u32 input_addr_offset;
+  __u32 input_addr_offset2;
+  __u16 input_offset_x;
+  __u16 input_offset_y;
+  __u16 input_width;
+  __u16 input_height;
+  __u32 tdn_input_addr_offset;
+  __u32 tdn_output_addr_offset;
+  __u32 stitch_input_addr_offset;
+  __u32 stitch_output_addr_offset;
+  __u32 lsc_grid_offset_x;
+  __u32 lsc_grid_offset_y;
+  __u32 cac_grid_offset_x;
+  __u32 cac_grid_offset_y;
+  __u16 crop_x_start[PISP_BACK_END_NUM_OUTPUTS];
+  __u16 crop_x_end[PISP_BACK_END_NUM_OUTPUTS];
+  __u16 crop_y_start[PISP_BACK_END_NUM_OUTPUTS];
+  __u16 crop_y_end[PISP_BACK_END_NUM_OUTPUTS];
+  __u16 downscale_phase_x[3 * PISP_BACK_END_NUM_OUTPUTS];
+  __u16 downscale_phase_y[3 * PISP_BACK_END_NUM_OUTPUTS];
+  __u16 resample_in_width[PISP_BACK_END_NUM_OUTPUTS];
+  __u16 resample_in_height[PISP_BACK_END_NUM_OUTPUTS];
+  __u16 resample_phase_x[3 * PISP_BACK_END_NUM_OUTPUTS];
+  __u16 resample_phase_y[3 * PISP_BACK_END_NUM_OUTPUTS];
+  __u16 output_offset_x[PISP_BACK_END_NUM_OUTPUTS];
+  __u16 output_offset_y[PISP_BACK_END_NUM_OUTPUTS];
+  __u16 output_width[PISP_BACK_END_NUM_OUTPUTS];
+  __u16 output_height[PISP_BACK_END_NUM_OUTPUTS];
+  __u32 output_addr_offset[PISP_BACK_END_NUM_OUTPUTS];
+  __u32 output_addr_offset2[PISP_BACK_END_NUM_OUTPUTS];
+  __u32 output_hog_addr_offset;
+} __attribute__((packed));
+struct pisp_be_tiles_config {
+  struct pisp_be_config config;
+  struct pisp_tile tiles[PISP_BACK_END_NUM_TILES];
+  __u32 num_tiles;
+} __attribute__((packed));
+#endif
diff --git a/libc/kernel/uapi/linux/media/raspberrypi/pisp_common.h b/libc/kernel/uapi/linux/media/raspberrypi/pisp_common.h
new file mode 100644
index 0000000..0e0b23f
--- /dev/null
+++ b/libc/kernel/uapi/linux/media/raspberrypi/pisp_common.h
@@ -0,0 +1,119 @@
+/*
+ * This file is auto-generated. Modifications will be lost.
+ *
+ * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
+ * for more information.
+ */
+#ifndef _UAPI_PISP_COMMON_H_
+#define _UAPI_PISP_COMMON_H_
+#include <linux/types.h>
+struct pisp_image_format_config {
+  __u16 width;
+  __u16 height;
+  __u32 format;
+  __s32 stride;
+  __s32 stride2;
+} __attribute__((packed));
+enum pisp_bayer_order {
+  PISP_BAYER_ORDER_RGGB = 0,
+  PISP_BAYER_ORDER_GBRG = 1,
+  PISP_BAYER_ORDER_BGGR = 2,
+  PISP_BAYER_ORDER_GRBG = 3,
+  PISP_BAYER_ORDER_GREYSCALE = 128
+};
+enum pisp_image_format {
+  PISP_IMAGE_FORMAT_BPS_8 = 0x00000000,
+  PISP_IMAGE_FORMAT_BPS_10 = 0x00000001,
+  PISP_IMAGE_FORMAT_BPS_12 = 0x00000002,
+  PISP_IMAGE_FORMAT_BPS_16 = 0x00000003,
+  PISP_IMAGE_FORMAT_BPS_MASK = 0x00000003,
+  PISP_IMAGE_FORMAT_PLANARITY_INTERLEAVED = 0x00000000,
+  PISP_IMAGE_FORMAT_PLANARITY_SEMI_PLANAR = 0x00000010,
+  PISP_IMAGE_FORMAT_PLANARITY_PLANAR = 0x00000020,
+  PISP_IMAGE_FORMAT_PLANARITY_MASK = 0x00000030,
+  PISP_IMAGE_FORMAT_SAMPLING_444 = 0x00000000,
+  PISP_IMAGE_FORMAT_SAMPLING_422 = 0x00000100,
+  PISP_IMAGE_FORMAT_SAMPLING_420 = 0x00000200,
+  PISP_IMAGE_FORMAT_SAMPLING_MASK = 0x00000300,
+  PISP_IMAGE_FORMAT_ORDER_NORMAL = 0x00000000,
+  PISP_IMAGE_FORMAT_ORDER_SWAPPED = 0x00001000,
+  PISP_IMAGE_FORMAT_SHIFT_0 = 0x00000000,
+  PISP_IMAGE_FORMAT_SHIFT_1 = 0x00010000,
+  PISP_IMAGE_FORMAT_SHIFT_2 = 0x00020000,
+  PISP_IMAGE_FORMAT_SHIFT_3 = 0x00030000,
+  PISP_IMAGE_FORMAT_SHIFT_4 = 0x00040000,
+  PISP_IMAGE_FORMAT_SHIFT_5 = 0x00050000,
+  PISP_IMAGE_FORMAT_SHIFT_6 = 0x00060000,
+  PISP_IMAGE_FORMAT_SHIFT_7 = 0x00070000,
+  PISP_IMAGE_FORMAT_SHIFT_8 = 0x00080000,
+  PISP_IMAGE_FORMAT_SHIFT_MASK = 0x000f0000,
+  PISP_IMAGE_FORMAT_BPP_32 = 0x00100000,
+  PISP_IMAGE_FORMAT_UNCOMPRESSED = 0x00000000,
+  PISP_IMAGE_FORMAT_COMPRESSION_MODE_1 = 0x01000000,
+  PISP_IMAGE_FORMAT_COMPRESSION_MODE_2 = 0x02000000,
+  PISP_IMAGE_FORMAT_COMPRESSION_MODE_3 = 0x03000000,
+  PISP_IMAGE_FORMAT_COMPRESSION_MASK = 0x03000000,
+  PISP_IMAGE_FORMAT_HOG_SIGNED = 0x04000000,
+  PISP_IMAGE_FORMAT_HOG_UNSIGNED = 0x08000000,
+  PISP_IMAGE_FORMAT_INTEGRAL_IMAGE = 0x10000000,
+  PISP_IMAGE_FORMAT_WALLPAPER_ROLL = 0x20000000,
+  PISP_IMAGE_FORMAT_THREE_CHANNEL = 0x40000000,
+  PISP_IMAGE_FORMAT_SINGLE_16 = PISP_IMAGE_FORMAT_BPS_16,
+  PISP_IMAGE_FORMAT_THREE_16 = PISP_IMAGE_FORMAT_BPS_16 | PISP_IMAGE_FORMAT_THREE_CHANNEL
+};
+#define PISP_IMAGE_FORMAT_BPS_8(fmt) (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_8)
+#define PISP_IMAGE_FORMAT_BPS_10(fmt) (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_10)
+#define PISP_IMAGE_FORMAT_BPS_12(fmt) (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_12)
+#define PISP_IMAGE_FORMAT_BPS_16(fmt) (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_16)
+#define PISP_IMAGE_FORMAT_BPS(fmt) (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) ? 8 + (2 << (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) - 1)) : 8)
+#define PISP_IMAGE_FORMAT_SHIFT(fmt) (((fmt) & PISP_IMAGE_FORMAT_SHIFT_MASK) / PISP_IMAGE_FORMAT_SHIFT_1)
+#define PISP_IMAGE_FORMAT_THREE_CHANNEL(fmt) ((fmt) & PISP_IMAGE_FORMAT_THREE_CHANNEL)
+#define PISP_IMAGE_FORMAT_SINGLE_CHANNEL(fmt) (! ((fmt) & PISP_IMAGE_FORMAT_THREE_CHANNEL))
+#define PISP_IMAGE_FORMAT_COMPRESSED(fmt) (((fmt) & PISP_IMAGE_FORMAT_COMPRESSION_MASK) != PISP_IMAGE_FORMAT_UNCOMPRESSED)
+#define PISP_IMAGE_FORMAT_SAMPLING_444(fmt) (((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == PISP_IMAGE_FORMAT_SAMPLING_444)
+#define PISP_IMAGE_FORMAT_SAMPLING_422(fmt) (((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == PISP_IMAGE_FORMAT_SAMPLING_422)
+#define PISP_IMAGE_FORMAT_SAMPLING_420(fmt) (((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == PISP_IMAGE_FORMAT_SAMPLING_420)
+#define PISP_IMAGE_FORMAT_ORDER_NORMAL(fmt) (! ((fmt) & PISP_IMAGE_FORMAT_ORDER_SWAPPED))
+#define PISP_IMAGE_FORMAT_ORDER_SWAPPED(fmt) ((fmt) & PISP_IMAGE_FORMAT_ORDER_SWAPPED)
+#define PISP_IMAGE_FORMAT_INTERLEAVED(fmt) (((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == PISP_IMAGE_FORMAT_PLANARITY_INTERLEAVED)
+#define PISP_IMAGE_FORMAT_SEMIPLANAR(fmt) (((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == PISP_IMAGE_FORMAT_PLANARITY_SEMI_PLANAR)
+#define PISP_IMAGE_FORMAT_PLANAR(fmt) (((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == PISP_IMAGE_FORMAT_PLANARITY_PLANAR)
+#define PISP_IMAGE_FORMAT_WALLPAPER(fmt) ((fmt) & PISP_IMAGE_FORMAT_WALLPAPER_ROLL)
+#define PISP_IMAGE_FORMAT_BPP_32(fmt) ((fmt) & PISP_IMAGE_FORMAT_BPP_32)
+#define PISP_IMAGE_FORMAT_HOG(fmt) ((fmt) & (PISP_IMAGE_FORMAT_HOG_SIGNED | PISP_IMAGE_FORMAT_HOG_UNSIGNED))
+#define PISP_WALLPAPER_WIDTH 128
+struct pisp_bla_config {
+  __u16 black_level_r;
+  __u16 black_level_gr;
+  __u16 black_level_gb;
+  __u16 black_level_b;
+  __u16 output_black_level;
+  __u8 pad[2];
+} __attribute__((packed));
+struct pisp_wbg_config {
+  __u16 gain_r;
+  __u16 gain_g;
+  __u16 gain_b;
+  __u8 pad[2];
+} __attribute__((packed));
+struct pisp_compress_config {
+  __u16 offset;
+  __u8 pad;
+  __u8 mode;
+} __attribute__((packed));
+struct pisp_decompress_config {
+  __u16 offset;
+  __u8 pad;
+  __u8 mode;
+} __attribute__((packed));
+enum pisp_axi_flags {
+  PISP_AXI_FLAG_ALIGN = 128,
+  PISP_AXI_FLAG_PAD = 64,
+  PISP_AXI_FLAG_PANIC = 32,
+};
+struct pisp_axi_config {
+  __u8 maxlen_flags;
+  __u8 cache_prot;
+  __u16 qos;
+} __attribute__((packed));
+#endif
diff --git a/libc/kernel/uapi/linux/mman.h b/libc/kernel/uapi/linux/mman.h
index cf1e978..f50b51c 100644
--- a/libc/kernel/uapi/linux/mman.h
+++ b/libc/kernel/uapi/linux/mman.h
@@ -18,6 +18,7 @@
 #define MAP_SHARED 0x01
 #define MAP_PRIVATE 0x02
 #define MAP_SHARED_VALIDATE 0x03
+#define MAP_DROPPABLE 0x08
 #define MAP_HUGE_SHIFT HUGETLB_FLAG_ENCODE_SHIFT
 #define MAP_HUGE_MASK HUGETLB_FLAG_ENCODE_MASK
 #define MAP_HUGE_16KB HUGETLB_FLAG_ENCODE_16KB
diff --git a/libc/kernel/uapi/linux/mount.h b/libc/kernel/uapi/linux/mount.h
index 1166a7a..c4278b5 100644
--- a/libc/kernel/uapi/linux/mount.h
+++ b/libc/kernel/uapi/linux/mount.h
@@ -90,7 +90,7 @@
 #define MOUNT_ATTR_SIZE_VER0 32
 struct statmount {
   __u32 size;
-  __u32 __spare1;
+  __u32 mnt_opts;
   __u64 mask;
   __u32 sb_dev_major;
   __u32 sb_dev_minor;
@@ -108,7 +108,8 @@
   __u64 propagate_from;
   __u32 mnt_root;
   __u32 mnt_point;
-  __u64 __spare2[50];
+  __u64 mnt_ns_id;
+  __u64 __spare2[49];
   char str[];
 };
 struct mnt_id_req {
@@ -116,13 +117,18 @@
   __u32 spare;
   __u64 mnt_id;
   __u64 param;
+  __u64 mnt_ns_id;
 };
 #define MNT_ID_REQ_SIZE_VER0 24
+#define MNT_ID_REQ_SIZE_VER1 32
 #define STATMOUNT_SB_BASIC 0x00000001U
 #define STATMOUNT_MNT_BASIC 0x00000002U
 #define STATMOUNT_PROPAGATE_FROM 0x00000004U
 #define STATMOUNT_MNT_ROOT 0x00000008U
 #define STATMOUNT_MNT_POINT 0x00000010U
 #define STATMOUNT_FS_TYPE 0x00000020U
+#define STATMOUNT_MNT_NS_ID 0x00000040U
+#define STATMOUNT_MNT_OPTS 0x00000080U
 #define LSMT_ROOT 0xffffffffffffffff
+#define LISTMOUNT_REVERSE (1 << 0)
 #endif
diff --git a/libc/kernel/uapi/linux/mptcp.h b/libc/kernel/uapi/linux/mptcp.h
index 3c9ba5e..03d3691 100644
--- a/libc/kernel/uapi/linux/mptcp.h
+++ b/libc/kernel/uapi/linux/mptcp.h
@@ -53,6 +53,10 @@
   __u64 mptcpi_bytes_received;
   __u64 mptcpi_bytes_acked;
   __u8 mptcpi_subflows_total;
+  __u8 reserved[3];
+  __u32 mptcpi_last_data_sent;
+  __u32 mptcpi_last_data_recv;
+  __u32 mptcpi_last_ack_recv;
 };
 #define MPTCP_RST_EUNSPEC 0
 #define MPTCP_RST_EMPTCP 1
diff --git a/libc/kernel/uapi/linux/netdev.h b/libc/kernel/uapi/linux/netdev.h
index cbfe26a..b084297 100644
--- a/libc/kernel/uapi/linux/netdev.h
+++ b/libc/kernel/uapi/linux/netdev.h
@@ -96,6 +96,28 @@
   NETDEV_A_QSTATS_TX_PACKETS,
   NETDEV_A_QSTATS_TX_BYTES,
   NETDEV_A_QSTATS_RX_ALLOC_FAIL,
+  NETDEV_A_QSTATS_RX_HW_DROPS,
+  NETDEV_A_QSTATS_RX_HW_DROP_OVERRUNS,
+  NETDEV_A_QSTATS_RX_CSUM_COMPLETE,
+  NETDEV_A_QSTATS_RX_CSUM_UNNECESSARY,
+  NETDEV_A_QSTATS_RX_CSUM_NONE,
+  NETDEV_A_QSTATS_RX_CSUM_BAD,
+  NETDEV_A_QSTATS_RX_HW_GRO_PACKETS,
+  NETDEV_A_QSTATS_RX_HW_GRO_BYTES,
+  NETDEV_A_QSTATS_RX_HW_GRO_WIRE_PACKETS,
+  NETDEV_A_QSTATS_RX_HW_GRO_WIRE_BYTES,
+  NETDEV_A_QSTATS_RX_HW_DROP_RATELIMITS,
+  NETDEV_A_QSTATS_TX_HW_DROPS,
+  NETDEV_A_QSTATS_TX_HW_DROP_ERRORS,
+  NETDEV_A_QSTATS_TX_CSUM_NONE,
+  NETDEV_A_QSTATS_TX_NEEDS_CSUM,
+  NETDEV_A_QSTATS_TX_HW_GSO_PACKETS,
+  NETDEV_A_QSTATS_TX_HW_GSO_BYTES,
+  NETDEV_A_QSTATS_TX_HW_GSO_WIRE_PACKETS,
+  NETDEV_A_QSTATS_TX_HW_GSO_WIRE_BYTES,
+  NETDEV_A_QSTATS_TX_HW_DROP_RATELIMITS,
+  NETDEV_A_QSTATS_TX_STOP,
+  NETDEV_A_QSTATS_TX_WAKE,
   __NETDEV_A_QSTATS_MAX,
   NETDEV_A_QSTATS_MAX = (__NETDEV_A_QSTATS_MAX - 1)
 };
diff --git a/libc/kernel/uapi/linux/netfilter/nf_tables.h b/libc/kernel/uapi/linux/netfilter/nf_tables.h
index 7922147..bfc6e25 100644
--- a/libc/kernel/uapi/linux/netfilter/nf_tables.h
+++ b/libc/kernel/uapi/linux/netfilter/nf_tables.h
@@ -695,7 +695,7 @@
   __NFTA_SECMARK_MAX,
 };
 #define NFTA_SECMARK_MAX (__NFTA_SECMARK_MAX - 1)
-#define NFT_SECMARK_CTX_MAXLEN 256
+#define NFT_SECMARK_CTX_MAXLEN 4096
 enum nft_reject_types {
   NFT_REJECT_ICMP_UNREACH,
   NFT_REJECT_TCP_RST,
diff --git a/libc/kernel/uapi/linux/nfs.h b/libc/kernel/uapi/linux/nfs.h
index 710e8ca..7b18f1f 100644
--- a/libc/kernel/uapi/linux/nfs.h
+++ b/libc/kernel/uapi/linux/nfs.h
@@ -47,7 +47,6 @@
   NFSERR_NOSPC = 28,
   NFSERR_ROFS = 30,
   NFSERR_MLINK = 31,
-  NFSERR_OPNOTSUPP = 45,
   NFSERR_NAMETOOLONG = 63,
   NFSERR_NOTEMPTY = 66,
   NFSERR_DQUOT = 69,
diff --git a/libc/kernel/uapi/linux/nfs4.h b/libc/kernel/uapi/linux/nfs4.h
index 21f1103..6512901 100644
--- a/libc/kernel/uapi/linux/nfs4.h
+++ b/libc/kernel/uapi/linux/nfs4.h
@@ -34,6 +34,7 @@
 #define NFS4_OPEN_RESULT_CONFIRM 0x0002
 #define NFS4_OPEN_RESULT_LOCKTYPE_POSIX 0x0004
 #define NFS4_OPEN_RESULT_PRESERVE_UNLINKED 0x0008
+#define NFS4_OPEN_RESULT_NO_OPEN_STATEID 0x0010
 #define NFS4_OPEN_RESULT_MAY_NOTIFY_LOCK 0x0020
 #define NFS4_SHARE_ACCESS_MASK 0x000F
 #define NFS4_SHARE_ACCESS_READ 0x0001
@@ -52,6 +53,8 @@
 #define NFS4_SHARE_WHEN_MASK 0xF0000
 #define NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL 0x10000
 #define NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED 0x20000
+#define NFS4_SHARE_WANT_DELEG_TIMESTAMPS 0x100000
+#define NFS4_SHARE_WANT_OPEN_XOR_DELEGATION 0x200000
 #define NFS4_CDFC4_FORE 0x1
 #define NFS4_CDFC4_BACK 0x2
 #define NFS4_CDFC4_BOTH 0x3
diff --git a/libc/kernel/uapi/linux/nfsd_netlink.h b/libc/kernel/uapi/linux/nfsd_netlink.h
index dd3d570..bd3f02c 100644
--- a/libc/kernel/uapi/linux/nfsd_netlink.h
+++ b/libc/kernel/uapi/linux/nfsd_netlink.h
@@ -27,7 +27,52 @@
   NFSD_A_RPC_STATUS_MAX = (__NFSD_A_RPC_STATUS_MAX - 1)
 };
 enum {
+  NFSD_A_SERVER_THREADS = 1,
+  NFSD_A_SERVER_GRACETIME,
+  NFSD_A_SERVER_LEASETIME,
+  NFSD_A_SERVER_SCOPE,
+  __NFSD_A_SERVER_MAX,
+  NFSD_A_SERVER_MAX = (__NFSD_A_SERVER_MAX - 1)
+};
+enum {
+  NFSD_A_VERSION_MAJOR = 1,
+  NFSD_A_VERSION_MINOR,
+  NFSD_A_VERSION_ENABLED,
+  __NFSD_A_VERSION_MAX,
+  NFSD_A_VERSION_MAX = (__NFSD_A_VERSION_MAX - 1)
+};
+enum {
+  NFSD_A_SERVER_PROTO_VERSION = 1,
+  __NFSD_A_SERVER_PROTO_MAX,
+  NFSD_A_SERVER_PROTO_MAX = (__NFSD_A_SERVER_PROTO_MAX - 1)
+};
+enum {
+  NFSD_A_SOCK_ADDR = 1,
+  NFSD_A_SOCK_TRANSPORT_NAME,
+  __NFSD_A_SOCK_MAX,
+  NFSD_A_SOCK_MAX = (__NFSD_A_SOCK_MAX - 1)
+};
+enum {
+  NFSD_A_SERVER_SOCK_ADDR = 1,
+  __NFSD_A_SERVER_SOCK_MAX,
+  NFSD_A_SERVER_SOCK_MAX = (__NFSD_A_SERVER_SOCK_MAX - 1)
+};
+enum {
+  NFSD_A_POOL_MODE_MODE = 1,
+  NFSD_A_POOL_MODE_NPOOLS,
+  __NFSD_A_POOL_MODE_MAX,
+  NFSD_A_POOL_MODE_MAX = (__NFSD_A_POOL_MODE_MAX - 1)
+};
+enum {
   NFSD_CMD_RPC_STATUS_GET = 1,
+  NFSD_CMD_THREADS_SET,
+  NFSD_CMD_THREADS_GET,
+  NFSD_CMD_VERSION_SET,
+  NFSD_CMD_VERSION_GET,
+  NFSD_CMD_LISTENER_SET,
+  NFSD_CMD_LISTENER_GET,
+  NFSD_CMD_POOL_MODE_SET,
+  NFSD_CMD_POOL_MODE_GET,
   __NFSD_CMD_MAX,
   NFSD_CMD_MAX = (__NFSD_CMD_MAX - 1)
 };
diff --git a/libc/kernel/uapi/linux/nl80211.h b/libc/kernel/uapi/linux/nl80211.h
index ddf2b3b..1bad2f2 100644
--- a/libc/kernel/uapi/linux/nl80211.h
+++ b/libc/kernel/uapi/linux/nl80211.h
@@ -528,6 +528,8 @@
   NL80211_ATTR_MLO_TTLM_DLINK,
   NL80211_ATTR_MLO_TTLM_ULINK,
   NL80211_ATTR_ASSOC_SPP_AMSDU,
+  NL80211_ATTR_WIPHY_RADIOS,
+  NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS,
   __NL80211_ATTR_AFTER_LAST,
   NUM_NL80211_ATTR = __NL80211_ATTR_AFTER_LAST,
   NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
@@ -878,6 +880,7 @@
   NL80211_FREQUENCY_ATTR_NO_6GHZ_VLP_CLIENT,
   NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT,
   NL80211_FREQUENCY_ATTR_CAN_MONITOR,
+  NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP,
   __NL80211_FREQUENCY_ATTR_AFTER_LAST,
   NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1
 };
@@ -955,6 +958,7 @@
   NL80211_RRF_DFS_CONCURRENT = 1 << 21,
   NL80211_RRF_NO_6GHZ_VLP_CLIENT = 1 << 22,
   NL80211_RRF_NO_6GHZ_AFC_CLIENT = 1 << 23,
+  NL80211_RRF_ALLOW_6GHZ_VLP_AP = 1 << 24,
 };
 #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
 #define NL80211_RRF_NO_IBSS NL80211_RRF_NO_IR
@@ -1423,7 +1427,7 @@
   NUM_NL80211_PLINK_STATES,
   MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1
 };
-enum plink_actions {
+enum nl80211_plink_action {
   NL80211_PLINK_ACTION_NO_ACTION,
   NL80211_PLINK_ACTION_OPEN,
   NL80211_PLINK_ACTION_BLOCK,
@@ -1973,4 +1977,19 @@
   NL80211_AP_SETTINGS_EXTERNAL_AUTH_SUPPORT = 1 << 0,
   NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT = 1 << 1,
 };
+enum nl80211_wiphy_radio_attrs {
+  __NL80211_WIPHY_RADIO_ATTR_INVALID,
+  NL80211_WIPHY_RADIO_ATTR_INDEX,
+  NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE,
+  NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION,
+  __NL80211_WIPHY_RADIO_ATTR_LAST,
+  NL80211_WIPHY_RADIO_ATTR_MAX = __NL80211_WIPHY_RADIO_ATTR_LAST - 1,
+};
+enum nl80211_wiphy_radio_freq_range {
+  __NL80211_WIPHY_RADIO_FREQ_ATTR_INVALID,
+  NL80211_WIPHY_RADIO_FREQ_ATTR_START,
+  NL80211_WIPHY_RADIO_FREQ_ATTR_END,
+  __NL80211_WIPHY_RADIO_FREQ_ATTR_LAST,
+  NL80211_WIPHY_RADIO_FREQ_ATTR_MAX = __NL80211_WIPHY_RADIO_FREQ_ATTR_LAST - 1,
+};
 #endif
diff --git a/libc/kernel/uapi/linux/nsfs.h b/libc/kernel/uapi/linux/nsfs.h
index 61a5797..c8f2208 100644
--- a/libc/kernel/uapi/linux/nsfs.h
+++ b/libc/kernel/uapi/linux/nsfs.h
@@ -7,9 +7,15 @@
 #ifndef __LINUX_NSFS_H
 #define __LINUX_NSFS_H
 #include <linux/ioctl.h>
+#include <linux/types.h>
 #define NSIO 0xb7
 #define NS_GET_USERNS _IO(NSIO, 0x1)
 #define NS_GET_PARENT _IO(NSIO, 0x2)
 #define NS_GET_NSTYPE _IO(NSIO, 0x3)
 #define NS_GET_OWNER_UID _IO(NSIO, 0x4)
+#define NS_GET_MNTNS_ID _IOR(NSIO, 0x5, __u64)
+#define NS_GET_PID_FROM_PIDNS _IOR(NSIO, 0x6, int)
+#define NS_GET_TGID_FROM_PIDNS _IOR(NSIO, 0x7, int)
+#define NS_GET_PID_IN_PIDNS _IOR(NSIO, 0x8, int)
+#define NS_GET_TGID_IN_PIDNS _IOR(NSIO, 0x9, int)
 #endif
diff --git a/libc/kernel/uapi/linux/ntsync.h b/libc/kernel/uapi/linux/ntsync.h
new file mode 100644
index 0000000..857b31b
--- /dev/null
+++ b/libc/kernel/uapi/linux/ntsync.h
@@ -0,0 +1,17 @@
+/*
+ * This file is auto-generated. Modifications will be lost.
+ *
+ * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
+ * for more information.
+ */
+#ifndef __LINUX_NTSYNC_H
+#define __LINUX_NTSYNC_H
+#include <linux/types.h>
+struct ntsync_sem_args {
+  __u32 sem;
+  __u32 count;
+  __u32 max;
+};
+#define NTSYNC_IOC_CREATE_SEM _IOWR('N', 0x80, struct ntsync_sem_args)
+#define NTSYNC_IOC_SEM_POST _IOWR('N', 0x81, __u32)
+#endif
diff --git a/libc/kernel/uapi/linux/openvswitch.h b/libc/kernel/uapi/linux/openvswitch.h
index d45f4fa..98c8037 100644
--- a/libc/kernel/uapi/linux/openvswitch.h
+++ b/libc/kernel/uapi/linux/openvswitch.h
@@ -429,6 +429,13 @@
   __OVS_CHECK_PKT_LEN_ATTR_MAX,
 };
 #define OVS_CHECK_PKT_LEN_ATTR_MAX (__OVS_CHECK_PKT_LEN_ATTR_MAX - 1)
+#define OVS_PSAMPLE_COOKIE_MAX_SIZE 16
+enum ovs_psample_attr {
+  OVS_PSAMPLE_ATTR_GROUP = 1,
+  OVS_PSAMPLE_ATTR_COOKIE,
+  __OVS_PSAMPLE_ATTR_MAX
+};
+#define OVS_PSAMPLE_ATTR_MAX (__OVS_PSAMPLE_ATTR_MAX - 1)
 enum ovs_action_attr {
   OVS_ACTION_ATTR_UNSPEC,
   OVS_ACTION_ATTR_OUTPUT,
@@ -455,6 +462,7 @@
   OVS_ACTION_ATTR_ADD_MPLS,
   OVS_ACTION_ATTR_DEC_TTL,
   OVS_ACTION_ATTR_DROP,
+  OVS_ACTION_ATTR_PSAMPLE,
   __OVS_ACTION_ATTR_MAX,
 };
 #define OVS_ACTION_ATTR_MAX (__OVS_ACTION_ATTR_MAX - 1)
diff --git a/libc/kernel/uapi/linux/papr_pdsm.h b/libc/kernel/uapi/linux/papr_pdsm.h
new file mode 100644
index 0000000..f466caa
--- /dev/null
+++ b/libc/kernel/uapi/linux/papr_pdsm.h
@@ -0,0 +1,64 @@
+/*
+ * This file is auto-generated. Modifications will be lost.
+ *
+ * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
+ * for more information.
+ */
+#ifndef _UAPI_ASM_POWERPC_PAPR_PDSM_H_
+#define _UAPI_ASM_POWERPC_PAPR_PDSM_H_
+#include <linux/types.h>
+#include <linux/ndctl.h>
+#define ND_PDSM_PAYLOAD_MAX_SIZE 184
+#define ND_PDSM_HDR_SIZE (sizeof(struct nd_pkg_pdsm) - ND_PDSM_PAYLOAD_MAX_SIZE)
+#define PAPR_PDSM_DIMM_HEALTHY 0
+#define PAPR_PDSM_DIMM_UNHEALTHY 1
+#define PAPR_PDSM_DIMM_CRITICAL 2
+#define PAPR_PDSM_DIMM_FATAL 3
+#define PDSM_DIMM_HEALTH_RUN_GAUGE_VALID 1
+#define PDSM_DIMM_DSC_VALID 2
+struct nd_papr_pdsm_health {
+  union {
+    struct {
+      __u32 extension_flags;
+      __u8 dimm_unarmed;
+      __u8 dimm_bad_shutdown;
+      __u8 dimm_bad_restore;
+      __u8 dimm_scrubbed;
+      __u8 dimm_locked;
+      __u8 dimm_encrypted;
+      __u16 dimm_health;
+      __u16 dimm_fuel_gauge;
+      __u64 dimm_dsc;
+    };
+    __u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE];
+  };
+};
+#define PDSM_SMART_INJECT_HEALTH_FATAL (1 << 0)
+#define PDSM_SMART_INJECT_BAD_SHUTDOWN (1 << 1)
+struct nd_papr_pdsm_smart_inject {
+  union {
+    struct {
+      __u32 flags;
+      __u8 fatal_enable;
+      __u8 unsafe_shutdown_enable;
+    };
+    __u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE];
+  };
+};
+enum papr_pdsm {
+  PAPR_PDSM_MIN = 0x0,
+  PAPR_PDSM_HEALTH,
+  PAPR_PDSM_SMART_INJECT,
+  PAPR_PDSM_MAX,
+};
+union nd_pdsm_payload {
+  struct nd_papr_pdsm_health health;
+  struct nd_papr_pdsm_smart_inject smart_inject;
+  __u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE];
+} __attribute__((__packed__));
+struct nd_pkg_pdsm {
+  __s32 cmd_status;
+  __u16 reserved[2];
+  union nd_pdsm_payload payload;
+} __attribute__((__packed__));
+#endif
diff --git a/libc/kernel/uapi/linux/pci_regs.h b/libc/kernel/uapi/linux/pci_regs.h
index e26392b..703d398 100644
--- a/libc/kernel/uapi/linux/pci_regs.h
+++ b/libc/kernel/uapi/linux/pci_regs.h
@@ -963,7 +963,11 @@
 #define PCI_DOE_DATA_OBJECT_HEADER_1_TYPE 0x00ff0000
 #define PCI_DOE_DATA_OBJECT_HEADER_2_LENGTH 0x0003ffff
 #define PCI_DOE_DATA_OBJECT_DISC_REQ_3_INDEX 0x000000ff
+#define PCI_DOE_DATA_OBJECT_DISC_REQ_3_VER 0x0000ff00
 #define PCI_DOE_DATA_OBJECT_DISC_RSP_3_VID 0x0000ffff
 #define PCI_DOE_DATA_OBJECT_DISC_RSP_3_PROTOCOL 0x00ff0000
 #define PCI_DOE_DATA_OBJECT_DISC_RSP_3_NEXT_INDEX 0xff000000
+#define PCI_DVSEC_CXL_PORT 3
+#define PCI_DVSEC_CXL_PORT_CTL 0x0c
+#define PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR 0x00000001
 #endif
diff --git a/libc/kernel/uapi/linux/perf_event.h b/libc/kernel/uapi/linux/perf_event.h
index 16a1a2e..ec9b856 100644
--- a/libc/kernel/uapi/linux/perf_event.h
+++ b/libc/kernel/uapi/linux/perf_event.h
@@ -460,6 +460,8 @@
 #define PERF_MEM_LVLNUM_L2 0x02
 #define PERF_MEM_LVLNUM_L3 0x03
 #define PERF_MEM_LVLNUM_L4 0x04
+#define PERF_MEM_LVLNUM_L2_MHB 0x05
+#define PERF_MEM_LVLNUM_MSC 0x06
 #define PERF_MEM_LVLNUM_UNC 0x08
 #define PERF_MEM_LVLNUM_CXL 0x09
 #define PERF_MEM_LVLNUM_IO 0x0a
diff --git a/libc/kernel/uapi/linux/pidfd.h b/libc/kernel/uapi/linux/pidfd.h
index 082b4a0..9068727 100644
--- a/libc/kernel/uapi/linux/pidfd.h
+++ b/libc/kernel/uapi/linux/pidfd.h
@@ -8,9 +8,21 @@
 #define _UAPI_LINUX_PIDFD_H
 #include <linux/types.h>
 #include <linux/fcntl.h>
+#include <linux/ioctl.h>
 #define PIDFD_NONBLOCK O_NONBLOCK
 #define PIDFD_THREAD O_EXCL
 #define PIDFD_SIGNAL_THREAD (1UL << 0)
 #define PIDFD_SIGNAL_THREAD_GROUP (1UL << 1)
 #define PIDFD_SIGNAL_PROCESS_GROUP (1UL << 2)
+#define PIDFS_IOCTL_MAGIC 0xFF
+#define PIDFD_GET_CGROUP_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 1)
+#define PIDFD_GET_IPC_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 2)
+#define PIDFD_GET_MNT_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 3)
+#define PIDFD_GET_NET_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 4)
+#define PIDFD_GET_PID_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 5)
+#define PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 6)
+#define PIDFD_GET_TIME_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 7)
+#define PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 8)
+#define PIDFD_GET_USER_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 9)
+#define PIDFD_GET_UTS_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 10)
 #endif
diff --git a/libc/kernel/uapi/linux/pkt_cls.h b/libc/kernel/uapi/linux/pkt_cls.h
index b402fa6..bdca553 100644
--- a/libc/kernel/uapi/linux/pkt_cls.h
+++ b/libc/kernel/uapi/linux/pkt_cls.h
@@ -419,6 +419,8 @@
   TCA_FLOWER_KEY_CFM,
   TCA_FLOWER_KEY_SPI,
   TCA_FLOWER_KEY_SPI_MASK,
+  TCA_FLOWER_KEY_ENC_FLAGS,
+  TCA_FLOWER_KEY_ENC_FLAGS_MASK,
   __TCA_FLOWER_MAX,
 };
 #define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
@@ -437,6 +439,7 @@
   TCA_FLOWER_KEY_ENC_OPTS_VXLAN,
   TCA_FLOWER_KEY_ENC_OPTS_ERSPAN,
   TCA_FLOWER_KEY_ENC_OPTS_GTP,
+  TCA_FLOWER_KEY_ENC_OPTS_PFCP,
   __TCA_FLOWER_KEY_ENC_OPTS_MAX,
 };
 #define TCA_FLOWER_KEY_ENC_OPTS_MAX (__TCA_FLOWER_KEY_ENC_OPTS_MAX - 1)
@@ -471,6 +474,13 @@
 };
 #define TCA_FLOWER_KEY_ENC_OPT_GTP_MAX (__TCA_FLOWER_KEY_ENC_OPT_GTP_MAX - 1)
 enum {
+  TCA_FLOWER_KEY_ENC_OPT_PFCP_UNSPEC,
+  TCA_FLOWER_KEY_ENC_OPT_PFCP_TYPE,
+  TCA_FLOWER_KEY_ENC_OPT_PFCP_SEID,
+  __TCA_FLOWER_KEY_ENC_OPT_PFCP_MAX,
+};
+#define TCA_FLOWER_KEY_ENC_OPT_PFCP_MAX (__TCA_FLOWER_KEY_ENC_OPT_PFCP_MAX - 1)
+enum {
   TCA_FLOWER_KEY_MPLS_OPTS_UNSPEC,
   TCA_FLOWER_KEY_MPLS_OPTS_LSE,
   __TCA_FLOWER_KEY_MPLS_OPTS_MAX,
@@ -489,7 +499,13 @@
 enum {
   TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0),
   TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1),
+  TCA_FLOWER_KEY_FLAGS_TUNNEL_CSUM = (1 << 2),
+  TCA_FLOWER_KEY_FLAGS_TUNNEL_DONT_FRAGMENT = (1 << 3),
+  TCA_FLOWER_KEY_FLAGS_TUNNEL_OAM = (1 << 4),
+  TCA_FLOWER_KEY_FLAGS_TUNNEL_CRIT_OPT = (1 << 5),
+  __TCA_FLOWER_KEY_FLAGS_MAX,
 };
+#define TCA_FLOWER_KEY_FLAGS_MAX (__TCA_FLOWER_KEY_FLAGS_MAX - 1)
 enum {
   TCA_FLOWER_KEY_CFM_OPT_UNSPEC,
   TCA_FLOWER_KEY_CFM_MD_LEVEL,
diff --git a/libc/kernel/uapi/linux/prctl.h b/libc/kernel/uapi/linux/prctl.h
index 48e100b..136a10f 100644
--- a/libc/kernel/uapi/linux/prctl.h
+++ b/libc/kernel/uapi/linux/prctl.h
@@ -190,4 +190,21 @@
 #define PR_RISCV_V_VSTATE_CTRL_CUR_MASK 0x3
 #define PR_RISCV_V_VSTATE_CTRL_NEXT_MASK 0xc
 #define PR_RISCV_V_VSTATE_CTRL_MASK 0x1f
+#define PR_RISCV_SET_ICACHE_FLUSH_CTX 71
+#define PR_RISCV_CTX_SW_FENCEI_ON 0
+#define PR_RISCV_CTX_SW_FENCEI_OFF 1
+#define PR_RISCV_SCOPE_PER_PROCESS 0
+#define PR_RISCV_SCOPE_PER_THREAD 1
+#define PR_PPC_GET_DEXCR 72
+#define PR_PPC_SET_DEXCR 73
+#define PR_PPC_DEXCR_SBHE 0
+#define PR_PPC_DEXCR_IBRTPD 1
+#define PR_PPC_DEXCR_SRAPD 2
+#define PR_PPC_DEXCR_NPHIE 3
+#define PR_PPC_DEXCR_CTRL_EDITABLE 0x1
+#define PR_PPC_DEXCR_CTRL_SET 0x2
+#define PR_PPC_DEXCR_CTRL_CLEAR 0x4
+#define PR_PPC_DEXCR_CTRL_SET_ONEXEC 0x8
+#define PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC 0x10
+#define PR_PPC_DEXCR_CTRL_MASK 0x1f
 #endif
diff --git a/libc/kernel/uapi/linux/psample.h b/libc/kernel/uapi/linux/psample.h
index c82e76e..f9f979c 100644
--- a/libc/kernel/uapi/linux/psample.h
+++ b/libc/kernel/uapi/linux/psample.h
@@ -22,6 +22,8 @@
   PSAMPLE_ATTR_LATENCY,
   PSAMPLE_ATTR_TIMESTAMP,
   PSAMPLE_ATTR_PROTO,
+  PSAMPLE_ATTR_USER_COOKIE,
+  PSAMPLE_ATTR_SAMPLE_PROBABILITY,
   __PSAMPLE_ATTR_MAX
 };
 enum psample_command {
diff --git a/libc/kernel/uapi/linux/psp-sev.h b/libc/kernel/uapi/linux/psp-sev.h
index 82fcbf1..7274081 100644
--- a/libc/kernel/uapi/linux/psp-sev.h
+++ b/libc/kernel/uapi/linux/psp-sev.h
@@ -20,6 +20,7 @@
   SNP_PLATFORM_STATUS,
   SNP_COMMIT,
   SNP_SET_CONFIG,
+  SNP_VLEK_LOAD,
   SEV_MAX,
 };
 typedef enum {
@@ -28,6 +29,7 @@
   SEV_RET_INVALID_PLATFORM_STATE,
   SEV_RET_INVALID_GUEST_STATE,
   SEV_RET_INAVLID_CONFIG,
+  SEV_RET_INVALID_CONFIG = SEV_RET_INAVLID_CONFIG,
   SEV_RET_INVALID_LEN,
   SEV_RET_ALREADY_OWNED,
   SEV_RET_INVALID_CERTIFICATE,
@@ -113,6 +115,15 @@
   __u32 rsvd : 30;
   __u8 rsvd1[52];
 } __attribute__((__packed__));
+struct sev_user_data_snp_vlek_load {
+  __u32 len;
+  __u8 vlek_wrapped_version;
+  __u8 rsvd[3];
+  __u64 vlek_wrapped_address;
+} __attribute__((__packed__));
+struct sev_user_data_snp_wrapped_vlek_hashstick {
+  __u8 data[432];
+} __attribute__((__packed__));
 struct sev_issue_cmd {
   __u32 cmd;
   __u64 data;
diff --git a/libc/kernel/uapi/linux/random.h b/libc/kernel/uapi/linux/random.h
index d1fd998..64f62d9 100644
--- a/libc/kernel/uapi/linux/random.h
+++ b/libc/kernel/uapi/linux/random.h
@@ -24,4 +24,10 @@
 #define GRND_NONBLOCK 0x0001
 #define GRND_RANDOM 0x0002
 #define GRND_INSECURE 0x0004
+struct vgetrandom_opaque_params {
+  __u32 size_of_opaque_state;
+  __u32 mmap_prot;
+  __u32 mmap_flags;
+  __u32 reserved[13];
+};
 #endif
diff --git a/libc/kernel/uapi/linux/sev-guest.h b/libc/kernel/uapi/linux/sev-guest.h
index a822bed..a722641 100644
--- a/libc/kernel/uapi/linux/sev-guest.h
+++ b/libc/kernel/uapi/linux/sev-guest.h
@@ -51,6 +51,8 @@
 #define SNP_GUEST_FW_ERR_MASK GENMASK_ULL(31, 0)
 #define SNP_GUEST_VMM_ERR_SHIFT 32
 #define SNP_GUEST_VMM_ERR(x) (((u64) x) << SNP_GUEST_VMM_ERR_SHIFT)
+#define SNP_GUEST_FW_ERR(x) ((x) & SNP_GUEST_FW_ERR_MASK)
+#define SNP_GUEST_ERR(vmm_err,fw_err) (SNP_GUEST_VMM_ERR(vmm_err) | SNP_GUEST_FW_ERR(fw_err))
 #define SNP_GUEST_VMM_ERR_INVALID_LEN 1
 #define SNP_GUEST_VMM_ERR_BUSY 2
 #endif
diff --git a/libc/kernel/uapi/linux/snmp.h b/libc/kernel/uapi/linux/snmp.h
index 2f4c65c..0f72302 100644
--- a/libc/kernel/uapi/linux/snmp.h
+++ b/libc/kernel/uapi/linux/snmp.h
@@ -289,6 +289,8 @@
   LINUX_MIB_XFRMFWDHDRERROR,
   LINUX_MIB_XFRMOUTSTATEINVALID,
   LINUX_MIB_XFRMACQUIREERROR,
+  LINUX_MIB_XFRMOUTSTATEDIRERROR,
+  LINUX_MIB_XFRMINSTATEDIRERROR,
   __LINUX_MIB_XFRMMAX
 };
 enum {
diff --git a/libc/kernel/uapi/linux/stat.h b/libc/kernel/uapi/linux/stat.h
index 9974f3e..aae9ed4 100644
--- a/libc/kernel/uapi/linux/stat.h
+++ b/libc/kernel/uapi/linux/stat.h
@@ -68,7 +68,12 @@
   __u64 stx_mnt_id;
   __u32 stx_dio_mem_align;
   __u32 stx_dio_offset_align;
-  __u64 __spare3[12];
+  __u64 stx_subvol;
+  __u32 stx_atomic_write_unit_min;
+  __u32 stx_atomic_write_unit_max;
+  __u32 stx_atomic_write_segments_max;
+  __u32 __spare1[1];
+  __u64 __spare3[9];
 };
 #define STATX_TYPE 0x00000001U
 #define STATX_MODE 0x00000002U
@@ -86,6 +91,8 @@
 #define STATX_MNT_ID 0x00001000U
 #define STATX_DIOALIGN 0x00002000U
 #define STATX_MNT_ID_UNIQUE 0x00004000U
+#define STATX_SUBVOL 0x00008000U
+#define STATX_WRITE_ATOMIC 0x00010000U
 #define STATX__RESERVED 0x80000000U
 #define STATX_ALL 0x00000fffU
 #define STATX_ATTR_COMPRESSED 0x00000004
@@ -97,4 +104,5 @@
 #define STATX_ATTR_MOUNT_ROOT 0x00002000
 #define STATX_ATTR_VERITY 0x00100000
 #define STATX_ATTR_DAX 0x00200000
+#define STATX_ATTR_WRITE_ATOMIC 0x00400000
 #endif
diff --git a/libc/kernel/uapi/linux/stddef.h b/libc/kernel/uapi/linux/stddef.h
index aa3a694..dc37c6f 100644
--- a/libc/kernel/uapi/linux/stddef.h
+++ b/libc/kernel/uapi/linux/stddef.h
@@ -19,4 +19,10 @@
 #ifndef __counted_by
 #define __counted_by(m)
 #endif
+#ifndef __counted_by_le
+#define __counted_by_le(m)
+#endif
+#ifndef __counted_by_be
+#define __counted_by_be(m)
+#endif
 #endif
diff --git a/libc/kernel/uapi/linux/swab.h b/libc/kernel/uapi/linux/swab.h
index 6225a76..5d240e1 100644
--- a/libc/kernel/uapi/linux/swab.h
+++ b/libc/kernel/uapi/linux/swab.h
@@ -15,29 +15,14 @@
 #define ___constant_swab64(x) ((__u64) ((((__u64) (x) & (__u64) 0x00000000000000ffULL) << 56) | (((__u64) (x) & (__u64) 0x000000000000ff00ULL) << 40) | (((__u64) (x) & (__u64) 0x0000000000ff0000ULL) << 24) | (((__u64) (x) & (__u64) 0x00000000ff000000ULL) << 8) | (((__u64) (x) & (__u64) 0x000000ff00000000ULL) >> 8) | (((__u64) (x) & (__u64) 0x0000ff0000000000ULL) >> 24) | (((__u64) (x) & (__u64) 0x00ff000000000000ULL) >> 40) | (((__u64) (x) & (__u64) 0xff00000000000000ULL) >> 56)))
 #define ___constant_swahw32(x) ((__u32) ((((__u32) (x) & (__u32) 0x0000ffffUL) << 16) | (((__u32) (x) & (__u32) 0xffff0000UL) >> 16)))
 #define ___constant_swahb32(x) ((__u32) ((((__u32) (x) & (__u32) 0x00ff00ffUL) << 8) | (((__u32) (x) & (__u32) 0xff00ff00UL) >> 8)))
-#ifdef __arch_swab16
-#else
-#endif
-#ifdef __arch_swab32
-#else
-#endif
-#ifdef __arch_swab64
-#elif defined(__SWAB_64_THRU_32__)
+#ifdef __SWAB_64_THRU_32__
 #else
 #endif
 static inline __attribute__((__const__)) __u32 __fswahw32(__u32 val) {
-#ifdef __arch_swahw32
-  return __arch_swahw32(val);
-#else
   return ___constant_swahw32(val);
-#endif
 }
 static inline __attribute__((__const__)) __u32 __fswahb32(__u32 val) {
-#ifdef __arch_swahb32
-  return __arch_swahb32(val);
-#else
   return ___constant_swahb32(val);
-#endif
 }
 #define __swab16(x) (__u16) __builtin_bswap16((__u16) (x))
 #define __swab32(x) (__u32) __builtin_bswap32((__u32) (x))
@@ -48,73 +33,33 @@
 #define __swahw32(x) (__builtin_constant_p((__u32) (x)) ? ___constant_swahw32(x) : __fswahw32(x))
 #define __swahb32(x) (__builtin_constant_p((__u32) (x)) ? ___constant_swahb32(x) : __fswahb32(x))
 static __always_inline __u16 __swab16p(const __u16 * p) {
-#ifdef __arch_swab16p
-  return __arch_swab16p(p);
-#else
   return __swab16(* p);
-#endif
 }
 static __always_inline __u32 __swab32p(const __u32 * p) {
-#ifdef __arch_swab32p
-  return __arch_swab32p(p);
-#else
   return __swab32(* p);
-#endif
 }
 static __always_inline __u64 __swab64p(const __u64 * p) {
-#ifdef __arch_swab64p
-  return __arch_swab64p(p);
-#else
   return __swab64(* p);
-#endif
 }
 static inline __u32 __swahw32p(const __u32 * p) {
-#ifdef __arch_swahw32p
-  return __arch_swahw32p(p);
-#else
   return __swahw32(* p);
-#endif
 }
 static inline __u32 __swahb32p(const __u32 * p) {
-#ifdef __arch_swahb32p
-  return __arch_swahb32p(p);
-#else
   return __swahb32(* p);
-#endif
 }
 static inline void __swab16s(__u16 * p) {
-#ifdef __arch_swab16s
-  __arch_swab16s(p);
-#else
   * p = __swab16p(p);
-#endif
 }
 static __always_inline void __swab32s(__u32 * p) {
-#ifdef __arch_swab32s
-  __arch_swab32s(p);
-#else
   * p = __swab32p(p);
-#endif
 }
 static __always_inline void __swab64s(__u64 * p) {
-#ifdef __arch_swab64s
-  __arch_swab64s(p);
-#else
   * p = __swab64p(p);
-#endif
 }
 static inline void __swahw32s(__u32 * p) {
-#ifdef __arch_swahw32s
-  __arch_swahw32s(p);
-#else
   * p = __swahw32p(p);
-#endif
 }
 static inline void __swahb32s(__u32 * p) {
-#ifdef __arch_swahb32s
-  __arch_swahb32s(p);
-#else
   * p = __swahb32p(p);
-#endif
 }
 #endif
diff --git a/libc/kernel/uapi/linux/tcp.h b/libc/kernel/uapi/linux/tcp.h
index cb26f97..c71715c 100644
--- a/libc/kernel/uapi/linux/tcp.h
+++ b/libc/kernel/uapi/linux/tcp.h
@@ -71,6 +71,7 @@
 #define TCP_AO_INFO 40
 #define TCP_AO_GET_KEYS 41
 #define TCP_AO_REPAIR 42
+#define TCP_IS_MPTCP 43
 #define TCP_REPAIR_ON 1
 #define TCP_REPAIR_OFF 0
 #define TCP_REPAIR_OFF_NO_WP - 1
diff --git a/libc/kernel/uapi/linux/tcp_metrics.h b/libc/kernel/uapi/linux/tcp_metrics.h
index 931f50c..46ca141 100644
--- a/libc/kernel/uapi/linux/tcp_metrics.h
+++ b/libc/kernel/uapi/linux/tcp_metrics.h
@@ -4,8 +4,8 @@
  * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
  * for more information.
  */
-#ifndef _LINUX_TCP_METRICS_H
-#define _LINUX_TCP_METRICS_H
+#ifndef _UAPI_LINUX_TCP_METRICS_H
+#define _UAPI_LINUX_TCP_METRICS_H
 #include <linux/types.h>
 #define TCP_METRICS_GENL_NAME "tcp_metrics"
 #define TCP_METRICS_GENL_VERSION 0x1
@@ -21,6 +21,17 @@
 };
 #define TCP_METRIC_MAX (__TCP_METRIC_MAX - 1)
 enum {
+  TCP_METRICS_A_METRICS_RTT = 1,
+  TCP_METRICS_A_METRICS_RTTVAR,
+  TCP_METRICS_A_METRICS_SSTHRESH,
+  TCP_METRICS_A_METRICS_CWND,
+  TCP_METRICS_A_METRICS_REODERING,
+  TCP_METRICS_A_METRICS_RTT_US,
+  TCP_METRICS_A_METRICS_RTTVAR_US,
+  __TCP_METRICS_A_METRICS_MAX
+};
+#define TCP_METRICS_A_METRICS_MAX (__TCP_METRICS_A_METRICS_MAX - 1)
+enum {
   TCP_METRICS_ATTR_UNSPEC,
   TCP_METRICS_ATTR_ADDR_IPV4,
   TCP_METRICS_ATTR_ADDR_IPV6,
diff --git a/libc/kernel/uapi/linux/tee.h b/libc/kernel/uapi/linux/tee.h
index d4772ee..6e4cff3 100644
--- a/libc/kernel/uapi/linux/tee.h
+++ b/libc/kernel/uapi/linux/tee.h
@@ -18,6 +18,7 @@
 #define TEE_MEMREF_NULL (__u64) (- 1)
 #define TEE_IMPL_ID_OPTEE 1
 #define TEE_IMPL_ID_AMDTEE 2
+#define TEE_IMPL_ID_TSTEE 3
 #define TEE_OPTEE_CAP_TZ (1 << 0)
 struct tee_ioctl_version_data {
   __u32 impl_id;
diff --git a/libc/kernel/uapi/linux/trace_mmap.h b/libc/kernel/uapi/linux/trace_mmap.h
new file mode 100644
index 0000000..e891a7e
--- /dev/null
+++ b/libc/kernel/uapi/linux/trace_mmap.h
@@ -0,0 +1,28 @@
+/*
+ * This file is auto-generated. Modifications will be lost.
+ *
+ * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
+ * for more information.
+ */
+#ifndef _TRACE_MMAP_H_
+#define _TRACE_MMAP_H_
+#include <linux/types.h>
+struct trace_buffer_meta {
+  __u32 meta_page_size;
+  __u32 meta_struct_len;
+  __u32 subbuf_size;
+  __u32 nr_subbufs;
+  struct {
+    __u64 lost_events;
+    __u32 id;
+    __u32 read;
+  } reader;
+  __u64 flags;
+  __u64 entries;
+  __u64 overrun;
+  __u64 read;
+  __u64 Reserved1;
+  __u64 Reserved2;
+};
+#define TRACE_MMAP_IOCTL_GET_READER _IO('R', 0x20)
+#endif
diff --git a/libc/kernel/uapi/linux/um_timetravel.h b/libc/kernel/uapi/linux/um_timetravel.h
index 8706017..49eeb28 100644
--- a/libc/kernel/uapi/linux/um_timetravel.h
+++ b/libc/kernel/uapi/linux/um_timetravel.h
@@ -12,6 +12,15 @@
   __u32 seq;
   __u64 time;
 };
+#define UM_TIMETRAVEL_MAX_FDS 2
+enum um_timetravel_shared_mem_fds {
+  UM_TIMETRAVEL_SHARED_MEMFD,
+  UM_TIMETRAVEL_SHARED_LOGFD,
+  UM_TIMETRAVEL_SHARED_MAX_FDS,
+};
+enum um_timetravel_start_ack {
+  UM_TIMETRAVEL_START_ACK_ID = 0xffff,
+};
 enum um_timetravel_ops {
   UM_TIMETRAVEL_ACK = 0,
   UM_TIMETRAVEL_START = 1,
@@ -22,5 +31,36 @@
   UM_TIMETRAVEL_RUN = 6,
   UM_TIMETRAVEL_FREE_UNTIL = 7,
   UM_TIMETRAVEL_GET_TOD = 8,
+  UM_TIMETRAVEL_BROADCAST = 9,
+};
+#define UM_TIMETRAVEL_SCHEDSHM_VERSION 2
+enum um_timetravel_schedshm_cap {
+  UM_TIMETRAVEL_SCHEDSHM_CAP_TIME_SHARE = 0x1,
+};
+enum um_timetravel_schedshm_flags {
+  UM_TIMETRAVEL_SCHEDSHM_FLAGS_REQ_RUN = 0x1,
+};
+union um_timetravel_schedshm_client {
+  struct {
+    __u32 capa;
+    __u32 flags;
+    __u64 req_time;
+    __u64 name;
+  };
+  char reserve[128];
+};
+struct um_timetravel_schedshm {
+  union {
+    struct {
+      __u32 version;
+      __u32 len;
+      __u64 free_until;
+      __u64 current_time;
+      __u16 running_id;
+      __u16 max_clients;
+    };
+    char hdr[4096];
+  };
+  union um_timetravel_schedshm_client clients[];
 };
 #endif
diff --git a/libc/kernel/uapi/linux/v4l2-controls.h b/libc/kernel/uapi/linux/v4l2-controls.h
index 23158dc..f6ef26c 100644
--- a/libc/kernel/uapi/linux/v4l2-controls.h
+++ b/libc/kernel/uapi/linux/v4l2-controls.h
@@ -714,6 +714,7 @@
   V4L2_MPEG_VIDEO_AV1_LEVEL_7_2 = 22,
   V4L2_MPEG_VIDEO_AV1_LEVEL_7_3 = 23
 };
+#define V4L2_CID_MPEG_VIDEO_AVERAGE_QP (V4L2_CID_CODEC_BASE + 657)
 #define V4L2_CID_CODEC_CX2341X_BASE (V4L2_CTRL_CLASS_CODEC | 0x1000)
 #define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE (V4L2_CID_CODEC_CX2341X_BASE + 0)
 enum v4l2_mpeg_cx2341x_video_spatial_filter_mode {
diff --git a/libc/kernel/uapi/linux/v4l2-subdev.h b/libc/kernel/uapi/linux/v4l2-subdev.h
index 9caaa47..b5a0c87 100644
--- a/libc/kernel/uapi/linux/v4l2-subdev.h
+++ b/libc/kernel/uapi/linux/v4l2-subdev.h
@@ -100,9 +100,10 @@
 };
 struct v4l2_subdev_routing {
   __u32 which;
-  __u32 num_routes;
+  __u32 len_routes;
   __u64 routes;
-  __u32 reserved[6];
+  __u32 num_routes;
+  __u32 reserved[11];
 };
 #define V4L2_SUBDEV_CLIENT_CAP_STREAMS (1ULL << 0)
 #define V4L2_SUBDEV_CLIENT_CAP_INTERVAL_USES_WHICH (1ULL << 1)
diff --git a/libc/kernel/uapi/linux/version.h b/libc/kernel/uapi/linux/version.h
index 1563f47..0cc45cf 100644
--- a/libc/kernel/uapi/linux/version.h
+++ b/libc/kernel/uapi/linux/version.h
@@ -4,8 +4,8 @@
  * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
  * for more information.
  */
-#define LINUX_VERSION_CODE 395520
+#define LINUX_VERSION_CODE 396032
 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
 #define LINUX_VERSION_MAJOR 6
-#define LINUX_VERSION_PATCHLEVEL 9
+#define LINUX_VERSION_PATCHLEVEL 11
 #define LINUX_VERSION_SUBLEVEL 0
diff --git a/libc/kernel/uapi/linux/videodev2.h b/libc/kernel/uapi/linux/videodev2.h
index ed91484..fb69a8a 100644
--- a/libc/kernel/uapi/linux/videodev2.h
+++ b/libc/kernel/uapi/linux/videodev2.h
@@ -236,6 +236,8 @@
 #define V4L2_PIX_FMT_RGBA1010102 v4l2_fourcc('R', 'A', '3', '0')
 #define V4L2_PIX_FMT_ARGB2101010 v4l2_fourcc('A', 'R', '3', '0')
 #define V4L2_PIX_FMT_BGR48_12 v4l2_fourcc('B', '3', '1', '2')
+#define V4L2_PIX_FMT_BGR48 v4l2_fourcc('B', 'G', 'R', '6')
+#define V4L2_PIX_FMT_RGB48 v4l2_fourcc('R', 'G', 'B', '6')
 #define V4L2_PIX_FMT_ABGR64_12 v4l2_fourcc('B', '4', '1', '2')
 #define V4L2_PIX_FMT_GREY v4l2_fourcc('G', 'R', 'E', 'Y')
 #define V4L2_PIX_FMT_Y4 v4l2_fourcc('Y', '0', '4', ' ')
@@ -249,6 +251,8 @@
 #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_IPU3_Y10 v4l2_fourcc('i', 'p', '3', 'y')
+#define V4L2_PIX_FMT_Y12P v4l2_fourcc('Y', '1', '2', 'P')
+#define V4L2_PIX_FMT_Y14P v4l2_fourcc('Y', '1', '4', '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')
@@ -423,6 +427,16 @@
 #define V4L2_PIX_FMT_IPU3_SGBRG10 v4l2_fourcc('i', 'p', '3', 'g')
 #define V4L2_PIX_FMT_IPU3_SGRBG10 v4l2_fourcc('i', 'p', '3', 'G')
 #define V4L2_PIX_FMT_IPU3_SRGGB10 v4l2_fourcc('i', 'p', '3', 'r')
+#define V4L2_PIX_FMT_PISP_COMP1_RGGB v4l2_fourcc('P', 'C', '1', 'R')
+#define V4L2_PIX_FMT_PISP_COMP1_GRBG v4l2_fourcc('P', 'C', '1', 'G')
+#define V4L2_PIX_FMT_PISP_COMP1_GBRG v4l2_fourcc('P', 'C', '1', 'g')
+#define V4L2_PIX_FMT_PISP_COMP1_BGGR v4l2_fourcc('P', 'C', '1', 'B')
+#define V4L2_PIX_FMT_PISP_COMP1_MONO v4l2_fourcc('P', 'C', '1', 'M')
+#define V4L2_PIX_FMT_PISP_COMP2_RGGB v4l2_fourcc('P', 'C', '2', 'R')
+#define V4L2_PIX_FMT_PISP_COMP2_GRBG v4l2_fourcc('P', 'C', '2', 'G')
+#define V4L2_PIX_FMT_PISP_COMP2_GBRG v4l2_fourcc('P', 'C', '2', 'g')
+#define V4L2_PIX_FMT_PISP_COMP2_BGGR v4l2_fourcc('P', 'C', '2', 'B')
+#define V4L2_PIX_FMT_PISP_COMP2_MONO v4l2_fourcc('P', 'C', '2', 'M')
 #define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8')
 #define V4L2_SDR_FMT_CU16LE v4l2_fourcc('C', 'U', '1', '6')
 #define V4L2_SDR_FMT_CS8 v4l2_fourcc('C', 'S', '0', '8')
@@ -442,6 +456,7 @@
 #define V4L2_META_FMT_VIVID v4l2_fourcc('V', 'I', 'V', 'D')
 #define V4L2_META_FMT_RK_ISP1_PARAMS v4l2_fourcc('R', 'K', '1', 'P')
 #define V4L2_META_FMT_RK_ISP1_STAT_3A v4l2_fourcc('R', 'K', '1', 'S')
+#define V4L2_META_FMT_RPI_BE_CFG v4l2_fourcc('R', 'P', 'B', 'C')
 #define V4L2_PIX_FMT_PRIV_MAGIC 0xfeedcafe
 #define V4L2_PIX_FMT_FLAG_PREMUL_ALPHA 0x00000001
 #define V4L2_PIX_FMT_FLAG_SET_CSC 0x00000002
@@ -464,6 +479,7 @@
 #define V4L2_FMT_FLAG_CSC_YCBCR_ENC 0x0080
 #define V4L2_FMT_FLAG_CSC_HSV_ENC V4L2_FMT_FLAG_CSC_YCBCR_ENC
 #define V4L2_FMT_FLAG_CSC_QUANTIZATION 0x0100
+#define V4L2_FMT_FLAG_META_LINE_BASED 0x0200
 enum v4l2_frmsizetypes {
   V4L2_FRMSIZE_TYPE_DISCRETE = 1,
   V4L2_FRMSIZE_TYPE_CONTINUOUS = 2,
@@ -563,6 +579,7 @@
 #define V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF (1 << 5)
 #define V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS (1 << 6)
 #define V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS (1 << 7)
+#define V4L2_BUF_CAP_SUPPORTS_REMOVE_BUFS (1 << 8)
 struct v4l2_plane {
   __u32 bytesused;
   __u32 length;
@@ -936,7 +953,7 @@
     struct v4l2_ctrl_hdr10_cll_info  * p_hdr10_cll_info;
     struct v4l2_ctrl_hdr10_mastering_display  * p_hdr10_mastering_display;
     void  * ptr;
-  };
+  } __attribute__((packed));
 } __attribute__((packed));
 struct v4l2_ext_controls {
   union {
@@ -1311,6 +1328,9 @@
 struct v4l2_meta_format {
   __u32 dataformat;
   __u32 buffersize;
+  __u32 width;
+  __u32 height;
+  __u32 bytesperline;
 } __attribute__((packed));
 struct v4l2_format {
   __u32 type;
@@ -1435,6 +1455,12 @@
   __u32 max_num_buffers;
   __u32 reserved[5];
 };
+struct v4l2_remove_buffers {
+  __u32 index;
+  __u32 count;
+  __u32 type;
+  __u32 reserved[13];
+};
 #define VIDIOC_QUERYCAP _IOR('V', 0, struct v4l2_capability)
 #define VIDIOC_ENUM_FMT _IOWR('V', 2, struct v4l2_fmtdesc)
 #define VIDIOC_G_FMT _IOWR('V', 4, struct v4l2_format)
@@ -1517,6 +1543,7 @@
 #define VIDIOC_ENUM_FREQ_BANDS _IOWR('V', 101, struct v4l2_frequency_band)
 #define VIDIOC_DBG_G_CHIP_INFO _IOWR('V', 102, struct v4l2_dbg_chip_info)
 #define VIDIOC_QUERY_EXT_CTRL _IOWR('V', 103, struct v4l2_query_ext_ctrl)
+#define VIDIOC_REMOVE_BUFS _IOWR('V', 104, struct v4l2_remove_buffers)
 #define BASE_VIDIOC_PRIVATE 192
 #define V4L2_PIX_FMT_HM12 V4L2_PIX_FMT_NV12_16L16
 #define V4L2_PIX_FMT_SUNXI_TILED_NV12 V4L2_PIX_FMT_NV12_32L32
diff --git a/libc/kernel/uapi/linux/virtio_bt.h b/libc/kernel/uapi/linux/virtio_bt.h
index 2b790ea..8799b66 100644
--- a/libc/kernel/uapi/linux/virtio_bt.h
+++ b/libc/kernel/uapi/linux/virtio_bt.h
@@ -13,7 +13,6 @@
 #define VIRTIO_BT_F_CONFIG_V2 3
 enum virtio_bt_config_type {
   VIRTIO_BT_CONFIG_TYPE_PRIMARY = 0,
-  VIRTIO_BT_CONFIG_TYPE_AMP = 1,
 };
 enum virtio_bt_config_vendor {
   VIRTIO_BT_CONFIG_VENDOR_NONE = 0,
diff --git a/libc/kernel/uapi/linux/virtio_mem.h b/libc/kernel/uapi/linux/virtio_mem.h
index e90853e..770623a 100644
--- a/libc/kernel/uapi/linux/virtio_mem.h
+++ b/libc/kernel/uapi/linux/virtio_mem.h
@@ -12,6 +12,7 @@
 #include <linux/virtio_config.h>
 #define VIRTIO_MEM_F_ACPI_PXM 0
 #define VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE 1
+#define VIRTIO_MEM_F_PERSISTENT_SUSPEND 2
 #define VIRTIO_MEM_REQ_PLUG 0
 #define VIRTIO_MEM_REQ_UNPLUG 1
 #define VIRTIO_MEM_REQ_UNPLUG_ALL 2
diff --git a/libc/kernel/uapi/linux/virtio_net.h b/libc/kernel/uapi/linux/virtio_net.h
index 7573209..26ff301 100644
--- a/libc/kernel/uapi/linux/virtio_net.h
+++ b/libc/kernel/uapi/linux/virtio_net.h
@@ -33,6 +33,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_DEVICE_STATS 50
 #define VIRTIO_NET_F_VQ_NOTF_COAL 52
 #define VIRTIO_NET_F_NOTF_COAL 53
 #define VIRTIO_NET_F_GUEST_USO4 54
@@ -203,4 +204,103 @@
   __le16 reserved;
   struct virtio_net_ctrl_coal coal;
 };
+#define VIRTIO_NET_CTRL_STATS 8
+#define VIRTIO_NET_CTRL_STATS_QUERY 0
+#define VIRTIO_NET_CTRL_STATS_GET 1
+struct virtio_net_stats_capabilities {
+#define VIRTIO_NET_STATS_TYPE_CVQ (1ULL << 32)
+#define VIRTIO_NET_STATS_TYPE_RX_BASIC (1ULL << 0)
+#define VIRTIO_NET_STATS_TYPE_RX_CSUM (1ULL << 1)
+#define VIRTIO_NET_STATS_TYPE_RX_GSO (1ULL << 2)
+#define VIRTIO_NET_STATS_TYPE_RX_SPEED (1ULL << 3)
+#define VIRTIO_NET_STATS_TYPE_TX_BASIC (1ULL << 16)
+#define VIRTIO_NET_STATS_TYPE_TX_CSUM (1ULL << 17)
+#define VIRTIO_NET_STATS_TYPE_TX_GSO (1ULL << 18)
+#define VIRTIO_NET_STATS_TYPE_TX_SPEED (1ULL << 19)
+  __le64 supported_stats_types[1];
+};
+struct virtio_net_ctrl_queue_stats {
+  struct {
+    __le16 vq_index;
+    __le16 reserved[3];
+    __le64 types_bitmap[1];
+  } stats[1];
+};
+struct virtio_net_stats_reply_hdr {
+#define VIRTIO_NET_STATS_TYPE_REPLY_CVQ 32
+#define VIRTIO_NET_STATS_TYPE_REPLY_RX_BASIC 0
+#define VIRTIO_NET_STATS_TYPE_REPLY_RX_CSUM 1
+#define VIRTIO_NET_STATS_TYPE_REPLY_RX_GSO 2
+#define VIRTIO_NET_STATS_TYPE_REPLY_RX_SPEED 3
+#define VIRTIO_NET_STATS_TYPE_REPLY_TX_BASIC 16
+#define VIRTIO_NET_STATS_TYPE_REPLY_TX_CSUM 17
+#define VIRTIO_NET_STATS_TYPE_REPLY_TX_GSO 18
+#define VIRTIO_NET_STATS_TYPE_REPLY_TX_SPEED 19
+  __u8 type;
+  __u8 reserved;
+  __le16 vq_index;
+  __le16 reserved1;
+  __le16 size;
+};
+struct virtio_net_stats_cvq {
+  struct virtio_net_stats_reply_hdr hdr;
+  __le64 command_num;
+  __le64 ok_num;
+};
+struct virtio_net_stats_rx_basic {
+  struct virtio_net_stats_reply_hdr hdr;
+  __le64 rx_notifications;
+  __le64 rx_packets;
+  __le64 rx_bytes;
+  __le64 rx_interrupts;
+  __le64 rx_drops;
+  __le64 rx_drop_overruns;
+};
+struct virtio_net_stats_tx_basic {
+  struct virtio_net_stats_reply_hdr hdr;
+  __le64 tx_notifications;
+  __le64 tx_packets;
+  __le64 tx_bytes;
+  __le64 tx_interrupts;
+  __le64 tx_drops;
+  __le64 tx_drop_malformed;
+};
+struct virtio_net_stats_rx_csum {
+  struct virtio_net_stats_reply_hdr hdr;
+  __le64 rx_csum_valid;
+  __le64 rx_needs_csum;
+  __le64 rx_csum_none;
+  __le64 rx_csum_bad;
+};
+struct virtio_net_stats_tx_csum {
+  struct virtio_net_stats_reply_hdr hdr;
+  __le64 tx_csum_none;
+  __le64 tx_needs_csum;
+};
+struct virtio_net_stats_rx_gso {
+  struct virtio_net_stats_reply_hdr hdr;
+  __le64 rx_gso_packets;
+  __le64 rx_gso_bytes;
+  __le64 rx_gso_packets_coalesced;
+  __le64 rx_gso_bytes_coalesced;
+};
+struct virtio_net_stats_tx_gso {
+  struct virtio_net_stats_reply_hdr hdr;
+  __le64 tx_gso_packets;
+  __le64 tx_gso_bytes;
+  __le64 tx_gso_segments;
+  __le64 tx_gso_segments_bytes;
+  __le64 tx_gso_packets_noseg;
+  __le64 tx_gso_bytes_noseg;
+};
+struct virtio_net_stats_rx_speed {
+  struct virtio_net_stats_reply_hdr hdr;
+  __le64 rx_ratelimit_packets;
+  __le64 rx_ratelimit_bytes;
+};
+struct virtio_net_stats_tx_speed {
+  struct virtio_net_stats_reply_hdr hdr;
+  __le64 tx_ratelimit_packets;
+  __le64 tx_ratelimit_bytes;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/xfrm.h b/libc/kernel/uapi/linux/xfrm.h
index e2f168d..9509efe 100644
--- a/libc/kernel/uapi/linux/xfrm.h
+++ b/libc/kernel/uapi/linux/xfrm.h
@@ -111,6 +111,10 @@
   XFRM_POLICY_MASK = 3,
   XFRM_POLICY_MAX = 3
 };
+enum xfrm_sa_dir {
+  XFRM_SA_DIR_IN = 1,
+  XFRM_SA_DIR_OUT = 2
+};
 enum {
   XFRM_SHARE_ANY,
   XFRM_SHARE_SESSION,
@@ -255,6 +259,8 @@
   XFRMA_SET_MARK_MASK,
   XFRMA_IF_ID,
   XFRMA_MTIMER_THRESH,
+  XFRMA_SA_DIR,
+  XFRMA_NAT_KEEPALIVE_INTERVAL,
   __XFRMA_MAX
 #define XFRMA_OUTPUT_MARK XFRMA_SET_MARK
 #define XFRMA_MAX (__XFRMA_MAX - 1)
diff --git a/libc/kernel/uapi/linux/zorro_ids.h b/libc/kernel/uapi/linux/zorro_ids.h
index f47c899..05239cd 100644
--- a/libc/kernel/uapi/linux/zorro_ids.h
+++ b/libc/kernel/uapi/linux/zorro_ids.h
@@ -354,6 +354,8 @@
 #define ZORRO_MANUF_VMC 0x1389
 #define ZORRO_PROD_VMC_ISDN_BLASTER_Z2 ZORRO_ID(VMC, 0x01, 0)
 #define ZORRO_PROD_VMC_HYPERCOM_4 ZORRO_ID(VMC, 0x02, 0)
+#define ZORRO_MANUF_CSLAB 0x1400
+#define ZORRO_PROD_CSLAB_WARP_1260 ZORRO_ID(CSLAB, 0x65, 0)
 #define ZORRO_MANUF_INFORMATION 0x157C
 #define ZORRO_PROD_INFORMATION_ISDN_ENGINE_I ZORRO_ID(INFORMATION, 0x64, 0)
 #define ZORRO_MANUF_VORTEX 0x2017
diff --git a/libc/kernel/uapi/misc/mrvl_cn10k_dpi.h b/libc/kernel/uapi/misc/mrvl_cn10k_dpi.h
new file mode 100644
index 0000000..7d8671f
--- /dev/null
+++ b/libc/kernel/uapi/misc/mrvl_cn10k_dpi.h
@@ -0,0 +1,26 @@
+/*
+ * This file is auto-generated. Modifications will be lost.
+ *
+ * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
+ * for more information.
+ */
+#ifndef __MRVL_CN10K_DPI_H__
+#define __MRVL_CN10K_DPI_H__
+#include <linux/types.h>
+#define DPI_MAX_ENGINES 6
+struct dpi_mps_mrrs_cfg {
+  __u16 max_read_req_sz;
+  __u16 max_payload_sz;
+  __u16 port;
+  __u16 reserved;
+};
+struct dpi_engine_cfg {
+  __u64 fifo_mask;
+  __u16 molr[DPI_MAX_ENGINES];
+  __u16 update_molr;
+  __u16 reserved;
+};
+#define DPI_MAGIC_NUM 0xB8
+#define DPI_MPS_MRRS_CFG _IOW(DPI_MAGIC_NUM, 1, struct dpi_mps_mrrs_cfg)
+#define DPI_ENGINE_CFG _IOW(DPI_MAGIC_NUM, 2, struct dpi_engine_cfg)
+#endif
diff --git a/libc/kernel/uapi/misc/pvpanic.h b/libc/kernel/uapi/misc/pvpanic.h
index bc421ae..8e1be62 100644
--- a/libc/kernel/uapi/misc/pvpanic.h
+++ b/libc/kernel/uapi/misc/pvpanic.h
@@ -6,6 +6,8 @@
  */
 #ifndef __PVPANIC_H__
 #define __PVPANIC_H__
-#define PVPANIC_PANICKED (1 << 0)
-#define PVPANIC_CRASH_LOADED (1 << 1)
+#include <linux/const.h>
+#define PVPANIC_PANICKED _BITUL(0)
+#define PVPANIC_CRASH_LOADED _BITUL(1)
+#define PVPANIC_SHUTDOWN _BITUL(2)
 #endif
diff --git a/libc/kernel/uapi/rdma/bnxt_re-abi.h b/libc/kernel/uapi/rdma/bnxt_re-abi.h
index 3dceafd..50f8b8a 100644
--- a/libc/kernel/uapi/rdma/bnxt_re-abi.h
+++ b/libc/kernel/uapi/rdma/bnxt_re-abi.h
@@ -18,7 +18,7 @@
   BNXT_RE_UCNTX_CMASK_WC_DPI_ENABLED = 0x04ULL,
   BNXT_RE_UCNTX_CMASK_DBR_PACING_ENABLED = 0x08ULL,
   BNXT_RE_UCNTX_CMASK_POW2_DISABLED = 0x10ULL,
-  BNXT_RE_COMP_MASK_UCNTX_HW_RETX_ENABLED = 0x40,
+  BNXT_RE_UCNTX_CMASK_MSN_TABLE_ENABLED = 0x40,
 };
 enum bnxt_re_wqe_mode {
   BNXT_QPLIB_WQE_MODE_STATIC = 0x00,
diff --git a/libc/kernel/uapi/rdma/efa-abi.h b/libc/kernel/uapi/rdma/efa-abi.h
index 2b30941..d4a9089 100644
--- a/libc/kernel/uapi/rdma/efa-abi.h
+++ b/libc/kernel/uapi/rdma/efa-abi.h
@@ -63,11 +63,16 @@
 enum {
   EFA_QP_DRIVER_TYPE_SRD = 0,
 };
+enum {
+  EFA_CREATE_QP_WITH_UNSOLICITED_WRITE_RECV = 1 << 0,
+};
 struct efa_ibv_create_qp {
   __u32 comp_mask;
   __u32 rq_ring_size;
   __u32 sq_ring_size;
   __u32 driver_qp_type;
+  __u16 flags;
+  __u8 reserved_90[6];
 };
 struct efa_ibv_create_qp_resp {
   __u32 comp_mask;
@@ -95,6 +100,7 @@
   EFA_QUERY_DEVICE_CAPS_CQ_WITH_SGID = 1 << 3,
   EFA_QUERY_DEVICE_CAPS_DATA_POLLING_128 = 1 << 4,
   EFA_QUERY_DEVICE_CAPS_RDMA_WRITE = 1 << 5,
+  EFA_QUERY_DEVICE_CAPS_UNSOLICITED_WRITE_RECV = 1 << 6,
 };
 struct efa_ibv_ex_query_device_resp {
   __u32 comp_mask;
diff --git a/libc/kernel/uapi/rdma/hns-abi.h b/libc/kernel/uapi/rdma/hns-abi.h
index 5b0f700..b76e45c 100644
--- a/libc/kernel/uapi/rdma/hns-abi.h
+++ b/libc/kernel/uapi/rdma/hns-abi.h
@@ -68,6 +68,11 @@
   __aligned_u64 cap_flags;
   __aligned_u64 dwqe_mmap_key;
 };
+struct hns_roce_ib_modify_qp_resp {
+  __u8 tc_mode;
+  __u8 priority;
+  __u8 reserved[6];
+};
 enum {
   HNS_ROCE_EXSGE_FLAGS = 1 << 0,
   HNS_ROCE_RQ_INLINE_FLAGS = 1 << 1,
@@ -97,6 +102,7 @@
 };
 struct hns_roce_ib_create_ah_resp {
   __u8 dmac[6];
-  __u8 reserved[2];
+  __u8 priority;
+  __u8 tc_mode;
 };
 #endif
diff --git a/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h b/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h
index d774fba..5f5c426 100644
--- a/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h
+++ b/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h
@@ -8,8 +8,6 @@
 #define IB_USER_IOCTL_CMDS_H
 #define UVERBS_ID_NS_MASK 0xF000
 #define UVERBS_ID_NS_SHIFT 12
-#define UVERBS_UDATA_DRIVER_DATA_NS 1
-#define UVERBS_UDATA_DRIVER_DATA_FLAG (1UL << UVERBS_ID_NS_SHIFT)
 enum uverbs_default_objects {
   UVERBS_OBJECT_DEVICE,
   UVERBS_OBJECT_PD,
@@ -30,8 +28,10 @@
   UVERBS_OBJECT_ASYNC_EVENT,
 };
 enum {
-  UVERBS_ATTR_UHW_IN = UVERBS_UDATA_DRIVER_DATA_FLAG,
+  UVERBS_ID_DRIVER_NS = 1UL << UVERBS_ID_NS_SHIFT,
+  UVERBS_ATTR_UHW_IN = UVERBS_ID_DRIVER_NS,
   UVERBS_ATTR_UHW_OUT,
+  UVERBS_ID_DRIVER_NS_WITH_UHW,
 };
 enum uverbs_methods_device {
   UVERBS_METHOD_INVOKE_WRITE,
diff --git a/libc/kernel/uapi/rdma/mana-abi.h b/libc/kernel/uapi/rdma/mana-abi.h
index 73967b4..02bb061 100644
--- a/libc/kernel/uapi/rdma/mana-abi.h
+++ b/libc/kernel/uapi/rdma/mana-abi.h
@@ -9,8 +9,18 @@
 #include <linux/types.h>
 #include <rdma/ib_user_ioctl_verbs.h>
 #define MANA_IB_UVERBS_ABI_VERSION 1
+enum mana_ib_create_cq_flags {
+  MANA_IB_CREATE_RNIC_CQ = 1 << 0,
+};
 struct mana_ib_create_cq {
   __aligned_u64 buf_addr;
+  __u16 flags;
+  __u16 reserved0;
+  __u32 reserved1;
+};
+struct mana_ib_create_cq_resp {
+  __u32 cqid;
+  __u32 reserved;
 };
 struct mana_ib_create_qp {
   __aligned_u64 sq_buf_addr;
@@ -23,6 +33,13 @@
   __u32 tx_vp_offset;
   __u32 reserved;
 };
+struct mana_ib_create_rc_qp {
+  __aligned_u64 queue_buf[4];
+  __u32 queue_size[4];
+};
+struct mana_ib_create_rc_qp_resp {
+  __u32 queue_id[4];
+};
 struct mana_ib_create_wq {
   __aligned_u64 wq_buf_addr;
   __u32 wq_buf_size;
diff --git a/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h b/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h
index 69d5250..ebafb00 100644
--- a/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h
+++ b/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h
@@ -201,6 +201,9 @@
 enum mlx5_ib_device_query_context_attrs {
   MLX5_IB_ATTR_QUERY_CONTEXT_RESP_UCTX = (1U << UVERBS_ID_NS_SHIFT),
 };
+enum mlx5_ib_create_cq_attrs {
+  MLX5_IB_ATTR_CREATE_CQ_UAR_INDEX = UVERBS_ID_DRIVER_NS_WITH_UHW,
+};
 #define MLX5_IB_DW_MATCH_PARAM 0xA0
 struct mlx5_ib_match_params {
   __u32 match_params[MLX5_IB_DW_MATCH_PARAM];
diff --git a/libc/kernel/uapi/rdma/rdma_netlink.h b/libc/kernel/uapi/rdma/rdma_netlink.h
index 2fe8c30..ac027ac 100644
--- a/libc/kernel/uapi/rdma/rdma_netlink.h
+++ b/libc/kernel/uapi/rdma/rdma_netlink.h
@@ -199,6 +199,8 @@
   RDMA_NLDEV_CMD_RES_SRQ_GET,
   RDMA_NLDEV_CMD_STAT_GET_STATUS,
   RDMA_NLDEV_CMD_RES_SRQ_GET_RAW,
+  RDMA_NLDEV_CMD_NEWDEV,
+  RDMA_NLDEV_CMD_DELDEV,
   RDMA_NLDEV_NUM_OPS
 };
 enum rdma_nldev_print_type {
@@ -304,6 +306,11 @@
   RDMA_NLDEV_ATTR_STAT_HWCOUNTER_INDEX,
   RDMA_NLDEV_ATTR_STAT_HWCOUNTER_DYNAMIC,
   RDMA_NLDEV_SYS_ATTR_PRIVILEGED_QKEY_MODE,
+  RDMA_NLDEV_ATTR_DRIVER_DETAILS,
+  RDMA_NLDEV_ATTR_RES_SUBTYPE,
+  RDMA_NLDEV_ATTR_DEV_TYPE,
+  RDMA_NLDEV_ATTR_PARENT_NAME,
+  RDMA_NLDEV_ATTR_NAME_ASSIGN_TYPE,
   RDMA_NLDEV_ATTR_MAX
 };
 enum rdma_nl_counter_mode {
@@ -316,4 +323,11 @@
   RDMA_COUNTER_MASK_QP_TYPE = 1,
   RDMA_COUNTER_MASK_PID = 1 << 1,
 };
+enum rdma_nl_dev_type {
+  RDMA_DEVICE_TYPE_SMI = 1,
+};
+enum rdma_nl_name_assign_type {
+  RDMA_NAME_ASSIGN_TYPE_UNKNOWN = 0,
+  RDMA_NAME_ASSIGN_TYPE_USER = 1,
+};
 #endif
diff --git a/libc/kernel/uapi/scsi/scsi_bsg_mpi3mr.h b/libc/kernel/uapi/scsi/scsi_bsg_mpi3mr.h
index d98e8fa..fe3094e 100644
--- a/libc/kernel/uapi/scsi/scsi_bsg_mpi3mr.h
+++ b/libc/kernel/uapi/scsi/scsi_bsg_mpi3mr.h
@@ -144,7 +144,7 @@
 };
 struct mpi3mr_bsg_in_hdb_status {
   __u8 num_hdb_types;
-  __u8 rsvd1;
+  __u8 element_trigger_format;
   __u16 rsvd2;
   __u32 rsvd3;
   struct mpi3mr_hdb_entry entry[1];
diff --git a/libc/kernel/uapi/sound/asequencer.h b/libc/kernel/uapi/sound/asequencer.h
index 7918528..a3826a5 100644
--- a/libc/kernel/uapi/sound/asequencer.h
+++ b/libc/kernel/uapi/sound/asequencer.h
@@ -7,7 +7,7 @@
 #ifndef _UAPI__SOUND_ASEQUENCER_H
 #define _UAPI__SOUND_ASEQUENCER_H
 #include <sound/asound.h>
-#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 3)
+#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 4)
 #define SNDRV_SEQ_EVENT_SYSTEM 0
 #define SNDRV_SEQ_EVENT_RESULT 1
 #define SNDRV_SEQ_EVENT_NOTE 5
@@ -343,7 +343,8 @@
   int ppq;
   unsigned int skew_value;
   unsigned int skew_base;
-  char reserved[24];
+  unsigned short tempo_base;
+  char reserved[22];
 };
 #define SNDRV_SEQ_TIMER_ALSA 0
 #define SNDRV_SEQ_TIMER_MIDI_CLOCK 1
diff --git a/libc/kernel/uapi/sound/asoc.h b/libc/kernel/uapi/sound/asoc.h
index 8718b46..f7992cb 100644
--- a/libc/kernel/uapi/sound/asoc.h
+++ b/libc/kernel/uapi/sound/asoc.h
@@ -336,48 +336,4 @@
   __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;
-} __attribute__((__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;
-} __attribute__((__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];
-} __attribute__((__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;
-} __attribute__((__packed__));
 #endif
diff --git a/libc/kernel/uapi/sound/asound.h b/libc/kernel/uapi/sound/asound.h
index b608ed5..cfe9f66 100644
--- a/libc/kernel/uapi/sound/asound.h
+++ b/libc/kernel/uapi/sound/asound.h
@@ -92,7 +92,7 @@
 #define SNDRV_HWDEP_IOCTL_INFO _IOR('H', 0x01, struct snd_hwdep_info)
 #define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status)
 #define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image)
-#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 17)
+#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 18)
 typedef unsigned long snd_pcm_uframes_t;
 typedef signed long snd_pcm_sframes_t;
 enum {
@@ -263,7 +263,7 @@
   unsigned char id[16];
   unsigned short id16[8];
   unsigned int id32[4];
-};
+} __attribute__((deprecated));
 struct snd_pcm_info {
   unsigned int device;
   unsigned int subdevice;
@@ -276,7 +276,7 @@
   int dev_subclass;
   unsigned int subdevices_count;
   unsigned int subdevices_avail;
-  union snd_pcm_sync_id sync;
+  unsigned char pad1[16];
   unsigned char reserved[64];
 };
 typedef int snd_pcm_hw_param_t;
@@ -324,7 +324,8 @@
   unsigned int rate_num;
   unsigned int rate_den;
   snd_pcm_uframes_t fifo_size;
-  unsigned char reserved[64];
+  unsigned char sync[16];
+  unsigned char reserved[48];
 };
 enum {
   SNDRV_PCM_TSTAMP_NONE = 0,
diff --git a/libc/kernel/uapi/sound/skl-tplg-interface.h b/libc/kernel/uapi/sound/skl-tplg-interface.h
index c620295..d613c7f 100644
--- a/libc/kernel/uapi/sound/skl-tplg-interface.h
+++ b/libc/kernel/uapi/sound/skl-tplg-interface.h
@@ -109,66 +109,4 @@
   SKL_TYPE_TUPLE,
   SKL_TYPE_DATA
 };
-struct skl_dfw_v4_module_pin {
-  __u16 module_id;
-  __u16 instance_id;
-} __attribute__((__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;
-} __attribute__((__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];
-} __attribute__((__packed__));
-struct skl_dfw_v4_pipe {
-  __u8 pipe_id;
-  __u8 pipe_priority;
-  __u16 conn_type : 4;
-  __u16 rsvd : 4;
-  __u16 memory_pages : 8;
-} __attribute__((__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;
-} __attribute__((__packed__));
 #endif
diff --git a/libc/kernel/uapi/sound/sof/abi.h b/libc/kernel/uapi/sound/sof/abi.h
index fe1fe47..ed66131 100644
--- a/libc/kernel/uapi/sound/sof/abi.h
+++ b/libc/kernel/uapi/sound/sof/abi.h
@@ -9,7 +9,7 @@
 #include <linux/types.h>
 #define SOF_ABI_MAJOR 3
 #define SOF_ABI_MINOR 23
-#define SOF_ABI_PATCH 0
+#define SOF_ABI_PATCH 1
 #define SOF_ABI_MAJOR_SHIFT 24
 #define SOF_ABI_MAJOR_MASK 0xff
 #define SOF_ABI_MINOR_SHIFT 12
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index f56a791..86dcc39 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -8,29 +8,29 @@
     __atomic_swap; # arm
     __b64_ntop;
     __b64_pton;
-    __cmsg_nxthdr; # introduced=21
-    __connect; # arm x86 introduced=21
-    __ctype_get_mb_cur_max; # introduced=21
+    __cmsg_nxthdr;
+    __connect; # arm x86
+    __ctype_get_mb_cur_max;
     __cxa_atexit;
     __cxa_finalize;
     __cxa_thread_atexit_impl; # introduced=23
     __dn_comp;
     __dn_count_labels;
     __dn_skipname;
-    __epoll_pwait; # arm x86 introduced=21
+    __epoll_pwait; # arm x86
     __errno;
-    __exit; # arm x86 introduced=21
-    __fadvise64; # x86 introduced=21
+    __exit; # arm x86
+    __fadvise64; # x86
     __fbufsize; # introduced=23
     __fcntl64; # arm x86
-    __FD_CLR_chk; # introduced=21
-    __FD_ISSET_chk; # introduced=21
-    __FD_SET_chk; # introduced=21
-    __fgets_chk; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
+    __FD_CLR_chk;
+    __FD_ISSET_chk;
+    __FD_SET_chk;
+    __fgets_chk;
     __flbf; # introduced=23
     __fp_nquery;
     __fp_query;
-    __fpclassify; # introduced=21
+    __fpclassify;
     __fpclassifyd;
     __fpclassifyf;
     __fpclassifyl;
@@ -41,9 +41,9 @@
     __fstatfs64; # arm x86
     __fwritable; # introduced=23
     __get_h_errno;
-    __getcpu; # arm x86 introduced-arm=12 introduced-x86=12
+    __getcpu; # arm x86
     __getcwd; # arm x86
-    __getpid; # arm x86 introduced=21
+    __getpid; # arm x86
     __getpriority; # arm x86
     __gnu_basename; # introduced=23
     __gnu_strerror_r; # introduced=23
@@ -55,24 +55,24 @@
     __isinf;
     __isinff;
     __isinfl;
-    __isnan; # introduced=21
-    __isnanf; # introduced=21
+    __isnan;
+    __isnanf;
     __isnanl;
     __isnormal;
     __isnormalf;
     __isnormall;
     __isthreaded; # arm x86 var
-    __libc_current_sigrtmax; # introduced=21
-    __libc_current_sigrtmin; # introduced=21
+    __libc_current_sigrtmax;
+    __libc_current_sigrtmin;
     __libc_init;
     __llseek; # arm x86
     __loc_aton;
     __loc_ntoa;
     __memchr_chk; # introduced=23
-    __memcpy_chk; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
-    __memmove_chk; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
+    __memcpy_chk;
+    __memmove_chk;
     __memrchr_chk; # introduced=23
-    __memset_chk; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
+    __memset_chk;
     __mmap2; # arm x86
     __ns_format_ttl; # arm x86 introduced=22
     __ns_get16; # arm x86 introduced=22
@@ -96,9 +96,9 @@
     __ns_skiprr; # arm x86 introduced=22
     __ns_sprintrr; # arm x86 introduced=22
     __ns_sprintrrf; # arm x86 introduced=22
-    __open_2; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
+    __open_2;
     __openat; # arm x86
-    __openat_2; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
+    __openat_2;
     __p_cdname;
     __p_cdnname;
     __p_class;
@@ -113,23 +113,23 @@
     __p_type;
     __p_type_syms; # var
     __poll_chk; # introduced=23
-    __ppoll; # arm x86 introduced=21
+    __ppoll; # arm x86
     __ppoll_chk; # introduced=23
     __ppoll64_chk; # introduced=28
     __pread64_chk; # introduced=23
     __pread_chk; # introduced=23
     __progname; # var
-    __pselect6; # arm x86 introduced=21
+    __pselect6; # arm x86
     __pthread_cleanup_pop;
     __pthread_cleanup_push;
     __ptrace; # arm x86
     __putlong;
     __putshort;
-    __read_chk; # introduced=21
+    __read_chk;
     __readlink_chk; # introduced=23
     __readlinkat_chk; # introduced=23
     __reboot; # arm x86
-    __recvfrom_chk; # introduced=21
+    __recvfrom_chk;
     __register_atfork; # introduced=23
     __res_close;
     __res_dnok;
@@ -152,83 +152,83 @@
     __res_send_setqhook;
     __res_send_setrhook;
     __rt_sigaction; # arm x86
-    __rt_sigpending; # arm x86 introduced=21
+    __rt_sigpending; # arm x86
     __rt_sigprocmask; # arm x86
-    __rt_sigsuspend; # arm x86 introduced=21
+    __rt_sigsuspend; # arm x86
     __rt_sigtimedwait; # arm x86
-    __sched_cpualloc; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
-    __sched_cpucount; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
-    __sched_cpufree; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
-    __sched_getaffinity; # arm x86 introduced=12
+    __sched_cpualloc;
+    __sched_cpucount;
+    __sched_cpufree;
+    __sched_getaffinity; # arm x86
     __set_thread_area; # x86
-    __set_tid_address; # arm x86 introduced=21
+    __set_tid_address; # arm x86
     __set_tls; # arm
     __sF; # var
-    __sigaction; # arm x86 introduced=21
-    __snprintf_chk; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
-    __socket; # arm x86 introduced=21
-    __sprintf_chk; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
+    __sigaction; # arm x86
+    __snprintf_chk;
+    __socket; # arm x86
+    __sprintf_chk;
     __stack_chk_fail;
     __stack_chk_guard; # var
     __statfs64; # arm x86
-    __stpcpy_chk; # introduced=21
-    __stpncpy_chk; # introduced=21
-    __stpncpy_chk2; # introduced=21
-    __strcat_chk; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
-    __strchr_chk; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
-    __strcpy_chk; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
-    __strlcat_chk; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
-    __strlcpy_chk; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
-    __strlen_chk; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
-    __strncat_chk; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
-    __strncpy_chk; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
-    __strncpy_chk2; # introduced=21
-    __strrchr_chk; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
+    __stpcpy_chk;
+    __stpncpy_chk;
+    __stpncpy_chk2;
+    __strcat_chk;
+    __strchr_chk;
+    __strcpy_chk;
+    __strlcat_chk;
+    __strlcpy_chk;
+    __strlen_chk;
+    __strncat_chk;
+    __strncpy_chk;
+    __strncpy_chk2;
+    __strrchr_chk;
     __sym_ntop;
     __sym_ntos;
     __sym_ston;
     __system_property_area_serial; # introduced=23
     __system_property_find;
     __system_property_find_nth;
-    __system_property_foreach; # introduced-arm=19 introduced-arm64=21 introduced-x86=19 introduced-x86_64=21
+    __system_property_foreach;
     __system_property_get;
     __system_property_read;
-    __system_property_serial; # introduced-arm=19 introduced-arm64=21 introduced-x86=19 introduced-x86_64=21
-    __system_property_set; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
+    __system_property_serial;
+    __system_property_set;
     __timer_create; # arm x86
     __timer_delete; # arm x86
     __timer_getoverrun; # arm x86
     __timer_gettime; # arm x86
     __timer_settime; # arm x86
-    __umask_chk; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
-    __vsnprintf_chk; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
-    __vsprintf_chk; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
+    __umask_chk;
+    __vsnprintf_chk;
+    __vsprintf_chk;
     __waitid; # arm x86
     _ctype_; # var
-    _Exit; # introduced=21
+    _Exit;
     _exit;
     _flushlbf; # introduced=23
     _getlong;
     _getshort;
     _longjmp;
-    _resolv_delete_cache_for_net; # introduced=21
-    _resolv_flush_cache_for_net; # introduced=21
-    _resolv_set_nameservers_for_net; # introduced=21
+    _resolv_delete_cache_for_net;
+    _resolv_flush_cache_for_net;
+    _resolv_set_nameservers_for_net;
     _setjmp;
-    _tolower; # introduced=21
+    _tolower;
     _tolower_tab_; # arm x86 var
-    _toupper; # introduced=21
+    _toupper;
     _toupper_tab_; # arm x86 var
     abort;
-    abs; # introduced-arm=19 introduced-arm64=21 introduced-x86=19 introduced-x86_64=21
+    abs;
     accept;
-    accept4; # introduced=21
+    accept4;
     access;
     acct;
     alarm;
     alphasort;
-    alphasort64; # introduced=21
-    android_set_abort_message; # introduced=21
+    alphasort64;
+    android_set_abort_message;
     arc4random;
     arc4random_buf;
     arc4random_uniform;
@@ -237,8 +237,8 @@
     asctime64_r; # arm x86
     asctime_r;
     asprintf;
-    at_quick_exit; # introduced=21
-    atof; # introduced=21
+    at_quick_exit;
+    atof;
     atoi;
     atol;
     atoll;
@@ -249,18 +249,18 @@
     brk;
     bsearch;
     btowc;
-    c16rtomb; # introduced=21
-    c32rtomb; # introduced=21
+    c16rtomb;
+    c32rtomb;
     cacheflush; # arm
     calloc;
     capget;
     capset;
-    cfgetispeed; # introduced=21
-    cfgetospeed; # introduced=21
-    cfmakeraw; # introduced=21
-    cfsetispeed; # introduced=21
-    cfsetospeed; # introduced=21
-    cfsetspeed; # introduced=21
+    cfgetispeed;
+    cfgetospeed;
+    cfmakeraw;
+    cfsetispeed;
+    cfsetospeed;
+    cfsetspeed;
     chdir;
     chmod;
     chown;
@@ -274,13 +274,13 @@
     clock_gettime;
     clock_nanosleep;
     clock_settime;
-    clone; # introduced-arm=9 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
+    clone;
     close;
     closedir;
     closelog;
     connect;
     creat;
-    creat64; # introduced=21
+    creat64;
     ctime;
     ctime64; # arm x86
     ctime64_r; # arm x86
@@ -294,20 +294,20 @@
     dirname_r; # arm x86
     div;
     dn_expand;
-    dprintf; # introduced=21
+    dprintf;
     drand48;
     dup;
     dup2;
-    dup3; # introduced=21
-    duplocale; # introduced=21
-    endmntent; # introduced=21
+    dup3;
+    duplocale;
+    endmntent;
     endservent;
     endutent;
     environ; # var
     epoll_create;
-    epoll_create1; # introduced=21
+    epoll_create1;
     epoll_ctl;
-    epoll_pwait; # introduced=21
+    epoll_pwait;
     epoll_wait;
     erand48;
     err;
@@ -317,10 +317,10 @@
     error_one_per_line; # var introduced=23
     error_print_progname; # var introduced=23
     errx;
-    ether_aton; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
-    ether_aton_r; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
-    ether_ntoa; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
-    ether_ntoa_r; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
+    ether_aton;
+    ether_aton_r;
+    ether_ntoa;
+    ether_ntoa_r;
     eventfd;
     eventfd_read;
     eventfd_write;
@@ -330,11 +330,11 @@
     execv;
     execve;
     execvp;
-    execvpe; # introduced=21
+    execvpe;
     exit;
     faccessat;
-    fallocate; # introduced=21
-    fallocate64; # introduced=21
+    fallocate;
+    fallocate64;
     fchdir;
     fchmod;
     fchmodat;
@@ -351,7 +351,7 @@
     ferror;
     ferror_unlocked; # introduced=23
     fflush;
-    ffs; # introduced-arm=9 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
+    ffs;
     fgetc;
     fgetln;
     fgetpos;
@@ -378,7 +378,7 @@
     fread;
     free;
     freeaddrinfo;
-    freelocale; # introduced=21
+    freelocale;
     fremovexattr;
     freopen;
     fscanf;
@@ -387,30 +387,30 @@
     fsetpos;
     fsetxattr;
     fstat;
-    fstat64; # introduced=21
+    fstat64;
     fstatat;
-    fstatat64; # introduced=21
+    fstatat64;
     fstatfs;
-    fstatfs64; # introduced=21
-    fstatvfs; # introduced-arm=19 introduced-arm64=21 introduced-x86=19 introduced-x86_64=21
-    fstatvfs64; # introduced=21
+    fstatfs64;
+    fstatvfs;
+    fstatvfs64;
     fsync;
     ftell;
     ftello;
     ftok;
     ftruncate;
-    ftruncate64; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
+    ftruncate64;
     ftrylockfile;
-    fts_children; # introduced=21
-    fts_close; # introduced=21
-    fts_open; # introduced=21
-    fts_read; # introduced=21
-    fts_set; # introduced=21
-    ftw; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
-    ftw64; # introduced=21
+    fts_children;
+    fts_close;
+    fts_open;
+    fts_read;
+    fts_set;
+    ftw;
+    ftw64;
     funlockfile;
     funopen;
-    futimens; # introduced-arm=19 introduced-arm64=21 introduced-x86=19 introduced-x86_64=21
+    futimens;
     fwide;
     fwprintf;
     fwrite;
@@ -421,13 +421,13 @@
     get_nprocs_conf; # introduced=23
     get_phys_pages; # introduced=23
     getaddrinfo;
-    getauxval; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
+    getauxval;
     getc;
     getc_unlocked;
     getchar;
     getchar_unlocked;
     getcwd;
-    getdelim; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
+    getdelim;
     getegid;
     getenv;
     geteuid;
@@ -445,41 +445,41 @@
     gethostent;
     gethostname;
     getitimer;
-    getline; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
+    getline;
     getlogin;
     getmntent;
-    getmntent_r; # introduced=21
+    getmntent_r;
     getnameinfo;
     getnetbyaddr;
     getnetbyname;
     getopt;
     getopt_long;
     getopt_long_only;
-    getpagesize; # introduced=21
+    getpagesize;
     getpeername;
     getpgid;
     getpgrp;
     getpid;
     getppid;
     getpriority;
-    getprogname; # introduced=21
+    getprogname;
     getprotobyname;
     getprotobynumber;
     getpt;
     getpwnam;
-    getpwnam_r; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
+    getpwnam_r;
     getpwuid;
-    getpwuid_r; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
+    getpwuid_r;
     getresgid;
     getresuid;
     getrlimit;
-    getrlimit64; # introduced=21
+    getrlimit64;
     getrusage;
     gets;
     getservbyname;
     getservbyport;
     getservent;
-    getsid; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
+    getsid;
     getsockname;
     getsockopt;
     gettid;
@@ -493,21 +493,21 @@
     gmtime64; # arm x86
     gmtime64_r; # arm x86
     gmtime_r;
-    grantpt; # introduced=21
+    grantpt;
     herror;
     hstrerror;
-    htonl; # introduced=21
-    htons; # introduced=21
+    htonl;
+    htons;
     if_indextoname;
     if_nametoindex;
-    imaxabs; # introduced-arm=19 introduced-arm64=21 introduced-x86=19 introduced-x86_64=21
-    imaxdiv; # introduced-arm=19 introduced-arm64=21 introduced-x86=19 introduced-x86_64=21
+    imaxabs;
+    imaxdiv;
     inet_addr;
     inet_aton;
-    inet_lnaof; # introduced=21
-    inet_makeaddr; # introduced=21
-    inet_netof; # introduced=21
-    inet_network; # introduced=21
+    inet_lnaof;
+    inet_makeaddr;
+    inet_netof;
+    inet_network;
     inet_nsap_addr;
     inet_nsap_ntoa;
     inet_ntoa;
@@ -515,96 +515,96 @@
     inet_pton;
     init_module;
     initgroups;
-    initstate; # introduced=21
+    initstate;
     inotify_add_watch;
     inotify_init;
-    inotify_init1; # introduced=21
+    inotify_init1;
     inotify_rm_watch;
-    insque; # introduced=21
+    insque;
     ioctl;
     isalnum;
-    isalnum_l; # introduced=21
+    isalnum_l;
     isalpha;
-    isalpha_l; # introduced=21
+    isalpha_l;
     isascii;
     isatty;
     isblank;
-    isblank_l; # introduced=21
+    isblank_l;
     iscntrl;
-    iscntrl_l; # introduced=21
+    iscntrl_l;
     isdigit;
-    isdigit_l; # introduced=21
-    isfinite; # introduced=21
-    isfinitef; # introduced=21
-    isfinitel; # introduced=21
+    isdigit_l;
+    isfinite;
+    isfinitef;
+    isfinitel;
     isgraph;
-    isgraph_l; # introduced=21
-    isinf; # introduced=21
-    isinff; # introduced=21
-    isinfl; # introduced=21
+    isgraph_l;
+    isinf;
+    isinff;
+    isinfl;
     islower;
-    islower_l; # introduced=21
+    islower_l;
     isnan;
     isnanf;
-    isnanl; # introduced=21
-    isnormal; # introduced=21
-    isnormalf; # introduced=21
-    isnormall; # introduced=21
+    isnanl;
+    isnormal;
+    isnormalf;
+    isnormall;
     isprint;
-    isprint_l; # introduced=21
+    isprint_l;
     ispunct;
-    ispunct_l; # introduced=21
+    ispunct_l;
     isspace;
-    isspace_l; # introduced=21
+    isspace_l;
     isupper;
-    isupper_l; # introduced=21
+    isupper_l;
     iswalnum;
-    iswalnum_l; # introduced=21
+    iswalnum_l;
     iswalpha;
-    iswalpha_l; # introduced=21
-    iswblank; # introduced=21
-    iswblank_l; # introduced=21
+    iswalpha_l;
+    iswblank;
+    iswblank_l;
     iswcntrl;
-    iswcntrl_l; # introduced=21
+    iswcntrl_l;
     iswctype;
-    iswctype_l; # introduced=21
+    iswctype_l;
     iswdigit;
-    iswdigit_l; # introduced=21
+    iswdigit_l;
     iswgraph;
-    iswgraph_l; # introduced=21
+    iswgraph_l;
     iswlower;
-    iswlower_l; # introduced=21
+    iswlower_l;
     iswprint;
-    iswprint_l; # introduced=21
+    iswprint_l;
     iswpunct;
-    iswpunct_l; # introduced=21
+    iswpunct_l;
     iswspace;
-    iswspace_l; # introduced=21
+    iswspace_l;
     iswupper;
-    iswupper_l; # introduced=21
+    iswupper_l;
     iswxdigit;
-    iswxdigit_l; # introduced=21
+    iswxdigit_l;
     isxdigit;
-    isxdigit_l; # introduced=21
+    isxdigit_l;
     jrand48;
     kill;
     killpg;
     klogctl;
-    labs; # introduced-arm=19 introduced-arm64=21 introduced-x86=19 introduced-x86_64=21
+    labs;
     lchown;
     lcong48; # introduced=23
     ldexp;
     ldiv;
-    lfind; # introduced=21
+    lfind;
     lgetxattr;
     link;
-    linkat; # introduced=21
+    linkat;
     listen;
     listxattr;
-    llabs; # introduced-arm=19 introduced-arm64=21 introduced-x86=19 introduced-x86_64=21
+    llabs;
     lldiv;
     llistxattr;
-    localeconv; # introduced=21
+    localeconv;
     localtime;
     localtime64; # arm x86
     localtime64_r; # arm x86
@@ -613,26 +613,26 @@
     longjmp;
     lrand48;
     lremovexattr;
-    lsearch; # introduced=21
+    lsearch;
     lseek;
     lseek64;
     lsetxattr;
     lstat;
-    lstat64; # introduced=21
+    lstat64;
     madvise;
     mallinfo;
     malloc;
     malloc_info; # introduced=23
-    malloc_usable_size; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
+    malloc_usable_size;
     mbrlen;
-    mbrtoc16; # introduced=21
-    mbrtoc32; # introduced=21
+    mbrtoc16;
+    mbrtoc32;
     mbrtowc;
     mbsinit;
-    mbsnrtowcs; # introduced=21
+    mbsnrtowcs;
     mbsrtowcs;
-    mbstowcs; # introduced=21
-    mbtowc; # introduced=21
+    mbstowcs;
+    mbtowc;
     memalign;
     memccpy;
     memchr;
@@ -647,37 +647,37 @@
     mkdir;
     mkdirat;
     mkdtemp;
-    mkfifo; # introduced=21
+    mkfifo;
     mkfifoat; # introduced=23
     mknod;
-    mknodat; # introduced=21
+    mknodat;
     mkostemp; # introduced=23
     mkostemp64; # introduced=23
     mkostemps; # introduced=23
     mkostemps64; # introduced=23
     mkstemp;
-    mkstemp64; # introduced=21
+    mkstemp64;
     mkstemps;
     mkstemps64; # introduced=23
     mktemp;
     mktime;
     mktime64; # arm x86
     mlock;
-    mlockall; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
+    mlockall;
     mmap;
-    mmap64; # introduced=21
+    mmap64;
     mount;
     mprotect;
     mrand48;
     mremap;
     msync;
     munlock;
-    munlockall; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
+    munlockall;
     munmap;
     nanosleep;
-    newlocale; # introduced=21
-    nftw; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
-    nftw64; # introduced=21
+    newlocale;
+    nftw;
+    nftw64;
     nice;
     nrand48;
     ns_format_ttl; # arm64 x86_64 riscv64 introduced=22
@@ -703,14 +703,14 @@
     ns_sprintrr; # arm64 x86_64 riscv64 introduced=22
     ns_sprintrrf; # arm64 x86_64 riscv64 introduced=22
     nsdispatch;
-    ntohl; # introduced=21
-    ntohs; # introduced=21
+    ntohl;
+    ntohs;
     open;
-    open64; # introduced=21
+    open64;
     open_memstream; # introduced=23
     open_wmemstream; # introduced=23
     openat;
-    openat64; # introduced=21
+    openat64;
     opendir;
     openlog;
     openpty; # introduced=23
@@ -728,26 +728,26 @@
     pipe2;
     poll;
     popen;
-    posix_fadvise; # introduced=21
-    posix_fadvise64; # introduced=21
-    posix_fallocate; # introduced=21
-    posix_fallocate64; # introduced=21
+    posix_fadvise;
+    posix_fadvise64;
+    posix_fallocate;
+    posix_fallocate64;
     posix_madvise; # introduced=23
-    posix_memalign; # introduced=17
-    posix_openpt; # introduced=21
-    ppoll; # introduced=21
+    posix_memalign;
+    posix_openpt;
+    ppoll;
     prctl;
     pread;
-    pread64; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
+    pread64;
     printf;
     prlimit; # arm64 x86_64 riscv64
-    prlimit64; # introduced=21
+    prlimit64;
     process_vm_readv; # introduced=23
     process_vm_writev; # introduced=23
     pselect;
-    psiginfo; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
-    psignal; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
-    pthread_atfork; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
+    psiginfo;
+    psignal;
+    pthread_atfork;
     pthread_attr_destroy;
     pthread_attr_getdetachstate;
     pthread_attr_getguardsize;
@@ -770,15 +770,15 @@
     pthread_cond_signal;
     pthread_cond_timedwait;
     pthread_cond_timedwait_monotonic; # arm x86
-    pthread_cond_timedwait_monotonic_np; # introduced-arm=9 introduced-x86=9 introduced-arm64=28 introduced-x64_64=28
+    pthread_cond_timedwait_monotonic_np; # introduced-arm=9 introduced-x86=9 introduced-arm64=28 introduced-x64_64=28 introduced-riscv64=28
     pthread_cond_timedwait_relative_np; # arm x86
     pthread_cond_timeout_np; # arm x86
     pthread_cond_wait;
     pthread_condattr_destroy;
-    pthread_condattr_getclock; # introduced=21
+    pthread_condattr_getclock;
     pthread_condattr_getpshared;
     pthread_condattr_init;
-    pthread_condattr_setclock; # introduced=21
+    pthread_condattr_setclock;
     pthread_condattr_setpshared;
     pthread_create;
     pthread_detach;
@@ -788,7 +788,7 @@
     pthread_getcpuclockid;
     pthread_getschedparam;
     pthread_getspecific;
-    pthread_gettid_np; # introduced=21
+    pthread_gettid_np;
     pthread_join;
     pthread_key_create;
     pthread_key_delete;
@@ -797,7 +797,7 @@
     pthread_mutex_init;
     pthread_mutex_lock;
     pthread_mutex_lock_timeout_np; # arm x86
-    pthread_mutex_timedlock; # introduced=21
+    pthread_mutex_timedlock;
     pthread_mutex_trylock;
     pthread_mutex_unlock;
     pthread_mutexattr_destroy;
@@ -840,30 +840,30 @@
     putw; # arm x86
     putwc;
     putwchar;
-    pvalloc; # arm x86 introduced=17
+    pvalloc; # arm x86
     pwrite;
-    pwrite64; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
+    pwrite64;
     qsort;
-    quick_exit; # introduced=21
+    quick_exit;
     raise;
-    rand; # introduced=21
-    rand_r; # introduced=21
-    random; # introduced=21
+    rand;
+    rand_r;
+    random;
     read;
     readahead;
     readdir;
-    readdir64; # introduced=21
-    readdir64_r; # introduced=21
+    readdir64;
+    readdir64_r;
     readdir_r;
     readlink;
-    readlinkat; # introduced=21
+    readlinkat;
     readv;
     realloc;
     realpath;
     reboot;
     recv;
     recvfrom;
-    recvmmsg; # introduced=21
+    recvmmsg;
     recvmsg;
     regcomp;
     regerror;
@@ -871,7 +871,7 @@
     regfree;
     remove;
     removexattr;
-    remque; # introduced=21
+    remque;
     rename;
     renameat;
     res_init;
@@ -883,16 +883,16 @@
     rmdir;
     sbrk;
     scandir;
-    scandir64; # introduced=21
+    scandir64;
     scanf;
     sched_get_priority_max;
     sched_get_priority_min;
-    sched_getaffinity; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
-    sched_getcpu; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
+    sched_getaffinity;
+    sched_getcpu;
     sched_getparam;
     sched_getscheduler;
     sched_rr_get_interval;
-    sched_setaffinity; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
+    sched_setaffinity;
     sched_setparam;
     sched_setscheduler;
     sched_yield;
@@ -911,8 +911,8 @@
     sem_wait;
     send;
     sendfile;
-    sendfile64; # introduced=21
-    sendmmsg; # introduced=21
+    sendfile64;
+    sendmmsg;
     sendmsg;
     sendto;
     setbuf;
@@ -920,8 +920,8 @@
     setegid;
     setenv;
     seteuid;
-    setfsgid; # introduced=21
-    setfsuid; # introduced=21
+    setfsgid;
+    setfsuid;
     setgid;
     setgroups;
     sethostname; # introduced=23
@@ -930,22 +930,22 @@
     setlinebuf;
     setlocale;
     setlogmask;
-    setmntent; # introduced=21
-    setns; # introduced=21
+    setmntent;
+    setns;
     setpgid;
     setpgrp;
     setpriority;
-    setprogname; # introduced=21
+    setprogname;
     setregid;
     setresgid;
     setresuid;
     setreuid;
     setrlimit;
-    setrlimit64; # introduced=21
+    setrlimit64;
     setservent;
     setsid;
     setsockopt;
-    setstate; # introduced=21
+    setstate;
     settimeofday;
     setuid;
     setutent;
@@ -953,22 +953,22 @@
     setxattr;
     shutdown;
     sigaction;
-    sigaddset; # introduced=21
+    sigaddset;
     sigaltstack;
-    sigblock; # arm x86 arm64 x86_64
-    sigdelset; # introduced=21
-    sigemptyset; # introduced=21
-    sigfillset; # introduced=21
+    sigblock;
+    sigdelset;
+    sigemptyset;
+    sigfillset;
     siginterrupt;
-    sigismember; # introduced=21
-    siglongjmp; # introduced-arm=9 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
-    signal; # introduced=21
-    signalfd; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
+    sigismember;
+    siglongjmp;
+    signal;
+    signalfd;
     sigpending;
     sigprocmask;
     sigqueue; # introduced=23
-    sigsetjmp; # introduced-arm=9 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
-    sigsetmask; # arm x86 arm64 x86_64
+    sigsetjmp;
+    sigsetmask;
     sigsuspend;
     sigtimedwait; # introduced=23
     sigwait;
@@ -977,23 +977,23 @@
     snprintf;
     socket;
     socketpair;
-    splice; # introduced=21
+    splice;
     sprintf;
-    srand; # introduced=21
+    srand;
     srand48;
-    srandom; # introduced=21
+    srandom;
     sscanf;
     stat;
-    stat64; # introduced=21
+    stat64;
     statfs;
-    statfs64; # introduced=21
-    statvfs; # introduced-arm=19 introduced-arm64=21 introduced-x86=19 introduced-x86_64=21
-    statvfs64; # introduced=21
+    statfs64;
+    statvfs;
+    statvfs64;
     stderr; # var introduced=23
     stdin; # var introduced=23
     stdout; # var introduced=23
-    stpcpy; # introduced=21
-    stpncpy; # introduced=21
+    stpcpy;
+    stpncpy;
     strcasecmp;
     strcasecmp_l; # introduced=23
     strcasestr;
@@ -1001,7 +1001,7 @@
     strchr;
     strcmp;
     strcoll;
-    strcoll_l; # introduced=21
+    strcoll_l;
     strcpy;
     strcspn;
     strdup;
@@ -1009,7 +1009,7 @@
     strerror_l; # introduced=23
     strerror_r;
     strftime;
-    strftime_l; # introduced=21
+    strftime_l;
     strlcat;
     strlcpy;
     strlen;
@@ -1028,27 +1028,27 @@
     strspn;
     strstr;
     strtod;
-    strtof; # introduced=21
+    strtof;
     strtoimax;
     strtok;
     strtok_r;
     strtol;
-    strtold; # introduced=21
-    strtold_l; # introduced=21
+    strtold;
+    strtold_l;
     strtoll;
-    strtoll_l; # introduced=21
+    strtoll_l;
     strtoul;
     strtoull;
-    strtoull_l; # introduced=21
+    strtoull_l;
     strtoumax;
     strxfrm;
-    strxfrm_l; # introduced=21
-    swapoff; # introduced-arm=19 introduced-arm64=21 introduced-x86=19 introduced-x86_64=21
-    swapon; # introduced-arm=19 introduced-arm64=21 introduced-x86=19 introduced-x86_64=21
+    strxfrm_l;
+    swapoff;
+    swapon;
     swprintf;
     swscanf;
     symlink;
-    symlinkat; # introduced=21
+    symlinkat;
     sync;
     sys_siglist; # var
     sys_signame; # var
@@ -1057,54 +1057,54 @@
     sysinfo;
     syslog;
     system;
-    tcdrain; # introduced=21
-    tcflow; # introduced=21
-    tcflush; # introduced=21
-    tcgetattr; # introduced=21
+    tcdrain;
+    tcflow;
+    tcflush;
+    tcgetattr;
     tcgetpgrp;
-    tcgetsid; # introduced=21
-    tcsendbreak; # introduced=21
-    tcsetattr; # introduced=21
+    tcgetsid;
+    tcsendbreak;
+    tcsetattr;
     tcsetpgrp;
     tdelete;
     tdestroy;
-    tee; # introduced=21
+    tee;
     telldir; # introduced=23
     tempnam;
     tfind;
     tgkill;
     time;
-    timegm; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
+    timegm;
     timegm64; # arm x86
-    timelocal; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
+    timelocal;
     timelocal64; # arm x86
     timer_create;
     timer_delete;
     timer_getoverrun;
     timer_gettime;
     timer_settime;
-    timerfd_create; # introduced-arm=19 introduced-arm64=21 introduced-x86=19 introduced-x86_64=21
-    timerfd_gettime; # introduced-arm=19 introduced-arm64=21 introduced-x86=19 introduced-x86_64=21
-    timerfd_settime; # introduced-arm=19 introduced-arm64=21 introduced-x86=19 introduced-x86_64=21
+    timerfd_create;
+    timerfd_gettime;
+    timerfd_settime;
     times;
     timezone; # var
     tmpfile;
     tmpnam;
     toascii;
     tolower;
-    tolower_l; # introduced=21
+    tolower_l;
     toupper;
-    toupper_l; # introduced=21
+    toupper_l;
     towlower;
-    towlower_l; # introduced=21
+    towlower_l;
     towupper;
-    towupper_l; # introduced=21
+    towupper_l;
     truncate;
-    truncate64; # introduced=21
+    truncate64;
     tsearch;
     ttyname;
     ttyname_r;
-    twalk; # introduced=21
+    twalk;
     tzname; # var
     tzset;
     umask;
@@ -1117,16 +1117,16 @@
     unlinkat;
     unlockpt;
     unsetenv;
-    unshare; # introduced-arm=17 introduced-arm64=21 introduced-x86=17 introduced-x86_64=21
-    uselocale; # introduced=21
+    unshare;
+    uselocale;
     usleep;
     utime;
-    utimensat; # introduced-arm=12 introduced-arm64=21 introduced-x86=12 introduced-x86_64=21
+    utimensat;
     utimes;
     utmpname;
     valloc; # arm x86
     vasprintf;
-    vdprintf; # introduced=21
+    vdprintf;
     verr;
     verrx;
     vfdprintf; # arm x86 versioned=28
@@ -1134,22 +1134,22 @@
     vfprintf;
     vfscanf;
     vfwprintf;
-    vfwscanf; # introduced=21
-    vmsplice; # introduced=21
+    vfwscanf;
+    vmsplice;
     vprintf;
     vscanf;
     vsnprintf;
     vsprintf;
     vsscanf;
     vswprintf;
-    vswscanf; # introduced=21
+    vswscanf;
     vsyslog;
     vwarn;
     vwarnx;
     vwprintf;
-    vwscanf; # introduced=21
+    vwscanf;
     wait;
-    wait4; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
+    wait4;
     waitid;
     waitpid;
     warn;
@@ -1163,7 +1163,7 @@
     wcschr;
     wcscmp;
     wcscoll;
-    wcscoll_l; # introduced=21
+    wcscoll_l;
     wcscpy;
     wcscspn;
     wcsdup;
@@ -1177,33 +1177,33 @@
     wcsncmp;
     wcsncpy;
     wcsnlen;
-    wcsnrtombs; # introduced=21
+    wcsnrtombs;
     wcspbrk;
     wcsrchr;
     wcsrtombs;
     wcsspn;
     wcsstr;
     wcstod;
-    wcstof; # introduced=21
-    wcstoimax; # introduced=21
+    wcstof;
+    wcstoimax;
     wcstok;
     wcstol;
-    wcstold; # introduced=21
-    wcstold_l; # introduced=21
-    wcstoll; # introduced=21
-    wcstoll_l; # introduced=21
-    wcstombs; # introduced=21
+    wcstold;
+    wcstold_l;
+    wcstoll;
+    wcstoll_l;
+    wcstombs;
     wcstoul;
-    wcstoull; # introduced=21
-    wcstoull_l; # introduced=21
-    wcstoumax; # introduced=21
+    wcstoull;
+    wcstoull_l;
+    wcstoumax;
     wcswidth;
     wcsxfrm;
-    wcsxfrm_l; # introduced=21
+    wcsxfrm_l;
     wctob;
-    wctomb; # introduced=21
+    wctomb;
     wctype;
-    wctype_l; # introduced=21
+    wctype_l;
     wcwidth;
     wmemchr;
     wmemcmp;
@@ -1608,6 +1608,17 @@
     __system_properties_zygote_reload; # apex
 } LIBC_U;
 
+LIBC_36 { # introduced=36
+  global:
+    lchmod;
+    mseal;
+    pthread_getaffinity_np;
+    pthread_setaffinity_np;
+    qsort_r;
+    sig2str;
+    str2sig;
+} LIBC_V;
+
 LIBC_PRIVATE {
   global:
     __accept4; # arm x86
diff --git a/libc/malloc_debug/Android.bp b/libc/malloc_debug/Android.bp
index 3828c28..5d61801 100644
--- a/libc/malloc_debug/Android.bp
+++ b/libc/malloc_debug/Android.bp
@@ -79,6 +79,10 @@
         "libmemunreachable",
     ],
 
+    whole_static_libs: [
+        "libmemory_trace",
+    ],
+
     shared_libs: [
         "libunwindstack",
     ],
diff --git a/libc/bionic/time_l.cpp b/libc/malloc_debug/Nanotime.h
similarity index 82%
copy from libc/bionic/time_l.cpp
copy to libc/malloc_debug/Nanotime.h
index e5fa9a5..d7c3f60 100644
--- a/libc/bionic/time_l.cpp
+++ b/libc/malloc_debug/Nanotime.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2012 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,9 +26,13 @@
  * SUCH DAMAGE.
  */
 
-#include <time.h>
-//#include <xlocale.h>
+#pragma once
 
-char* strptime_l(const char* buf, const char* fmt, struct tm* tm, locale_t) {
-  return strptime(buf, fmt, tm);
+#include <stdint.h>
+#include <time.h>
+
+static inline __always_inline uint64_t Nanotime() {
+  struct timespec t = {};
+  clock_gettime(CLOCK_MONOTONIC, &t);
+  return static_cast<uint64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
 }
diff --git a/libc/malloc_debug/RecordData.cpp b/libc/malloc_debug/RecordData.cpp
index 79e051b..1641732 100644
--- a/libc/malloc_debug/RecordData.cpp
+++ b/libc/malloc_debug/RecordData.cpp
@@ -39,72 +39,19 @@
 #include <mutex>
 
 #include <android-base/stringprintf.h>
+#include <memory_trace/MemoryTrace.h>
 
 #include "Config.h"
 #include "DebugData.h"
+#include "Nanotime.h"
 #include "RecordData.h"
 #include "debug_disable.h"
 #include "debug_log.h"
 
-RecordEntry::RecordEntry() : tid_(gettid()) {
-}
-
-bool ThreadCompleteEntry::Write(int fd) const {
-  return dprintf(fd, "%d: thread_done 0x0\n", tid_) > 0;
-}
-
-AllocEntry::AllocEntry(void* pointer, uint64_t start_ns, uint64_t end_ns)
-    : pointer_(pointer), start_ns_(start_ns), end_ns_(end_ns) {}
-
-MallocEntry::MallocEntry(void* pointer, size_t size, uint64_t start_ns, uint64_t end_ns)
-    : AllocEntry(pointer, start_ns, end_ns), size_(size) {}
-
-bool MallocEntry::Write(int fd) const {
-  return dprintf(fd, "%d: malloc %p %zu %" PRIu64 " %" PRIu64 "\n", tid_, pointer_, size_,
-                 start_ns_, end_ns_) > 0;
-}
-
-FreeEntry::FreeEntry(void* pointer, uint64_t start_ns, uint64_t end_ns)
-    : AllocEntry(pointer, start_ns, end_ns) {}
-
-bool FreeEntry::Write(int fd) const {
-  return dprintf(fd, "%d: free %p %" PRIu64 " %" PRIu64 "\n", tid_, pointer_, start_ns_, end_ns_) >
-         0;
-}
-
-CallocEntry::CallocEntry(void* pointer, size_t nmemb, size_t size, uint64_t start_ns,
-                         uint64_t end_ns)
-    : MallocEntry(pointer, size, start_ns, end_ns), nmemb_(nmemb) {}
-
-bool CallocEntry::Write(int fd) const {
-  return dprintf(fd, "%d: calloc %p %zu %zu %" PRIu64 " %" PRIu64 "\n", tid_, pointer_, nmemb_,
-                 size_, start_ns_, end_ns_) > 0;
-}
-
-ReallocEntry::ReallocEntry(void* pointer, size_t size, void* old_pointer, uint64_t start_ns,
-                           uint64_t end_ns)
-    : MallocEntry(pointer, size, start_ns, end_ns), old_pointer_(old_pointer) {}
-
-bool ReallocEntry::Write(int fd) const {
-  return dprintf(fd, "%d: realloc %p %p %zu %" PRIu64 " %" PRIu64 "\n", tid_, pointer_,
-                 old_pointer_, size_, start_ns_, end_ns_) > 0;
-}
-
-// aligned_alloc, posix_memalign, memalign, pvalloc, valloc all recorded with this class.
-MemalignEntry::MemalignEntry(void* pointer, size_t size, size_t alignment, uint64_t start_ns,
-                             uint64_t end_ns)
-    : MallocEntry(pointer, size, start_ns, end_ns), alignment_(alignment) {}
-
-bool MemalignEntry::Write(int fd) const {
-  return dprintf(fd, "%d: memalign %p %zu %zu %" PRIu64 " %" PRIu64 "\n", tid_, pointer_,
-                 alignment_, size_, start_ns_, end_ns_) > 0;
-}
-
 struct ThreadData {
-  ThreadData(RecordData* record_data, ThreadCompleteEntry* entry)
-      : record_data(record_data), entry(entry) {}
-  RecordData* record_data;
-  ThreadCompleteEntry* entry;
+  ThreadData(RecordData* record_data) : record_data(record_data) {}
+
+  RecordData* record_data = nullptr;
   size_t count = 0;
 };
 
@@ -117,7 +64,8 @@
   if (thread_data->count == 4) {
     ScopedDisableDebugCalls disable;
 
-    thread_data->record_data->AddEntryOnly(thread_data->entry);
+    thread_data->record_data->AddEntryOnly(memory_trace::Entry{
+        .tid = gettid(), .type = memory_trace::THREAD_DONE, .end_ns = Nanotime()});
     delete thread_data;
   } else {
     pthread_setspecific(thread_data->record_data->key(), data);
@@ -159,7 +107,7 @@
   }
 
   for (size_t i = 0; i < cur_index_; i++) {
-    if (!entries_[i]->Write(dump_fd)) {
+    if (!memory_trace::WriteEntryToFd(dump_fd, entries_[i])) {
       error_log("Failed to write record alloc information: %s", strerror(errno));
       break;
     }
@@ -201,23 +149,23 @@
   pthread_key_delete(key_);
 }
 
-void RecordData::AddEntryOnly(const RecordEntry* entry) {
+void RecordData::AddEntryOnly(const memory_trace::Entry& entry) {
   std::lock_guard<std::mutex> entries_lock(entries_lock_);
   if (cur_index_ == entries_.size()) {
     // Maxed out, throw the entry away.
     return;
   }
 
-  entries_[cur_index_++].reset(entry);
+  entries_[cur_index_++] = entry;
   if (cur_index_ == entries_.size()) {
     info_log("Maximum number of records added, all new operations will be dropped.");
   }
 }
 
-void RecordData::AddEntry(const RecordEntry* entry) {
+void RecordData::AddEntry(const memory_trace::Entry& entry) {
   void* data = pthread_getspecific(key_);
   if (data == nullptr) {
-    ThreadData* thread_data = new ThreadData(this, new ThreadCompleteEntry());
+    ThreadData* thread_data = new ThreadData(this);
     pthread_setspecific(key_, thread_data);
   }
 
diff --git a/libc/malloc_debug/RecordData.h b/libc/malloc_debug/RecordData.h
index 7efa1f7..f4b0d82 100644
--- a/libc/malloc_debug/RecordData.h
+++ b/libc/malloc_debug/RecordData.h
@@ -39,117 +39,9 @@
 #include <string>
 #include <vector>
 
+#include <memory_trace/MemoryTrace.h>
 #include <platform/bionic/macros.h>
 
-class RecordEntry {
- public:
-  RecordEntry();
-  virtual ~RecordEntry() = default;
-
-  virtual bool Write(int fd) const = 0;
-
- protected:
-  pid_t tid_;
-
- private:
-  BIONIC_DISALLOW_COPY_AND_ASSIGN(RecordEntry);
-};
-
-class ThreadCompleteEntry : public RecordEntry {
- public:
-  ThreadCompleteEntry() = default;
-  virtual ~ThreadCompleteEntry() = default;
-
-  bool Write(int fd) const override;
-
- private:
-  BIONIC_DISALLOW_COPY_AND_ASSIGN(ThreadCompleteEntry);
-};
-
-class AllocEntry : public RecordEntry {
- public:
-  explicit AllocEntry(void* pointer, uint64_t st, uint64_t et);
-  virtual ~AllocEntry() = default;
-
- protected:
-  void* pointer_;
-
-  // The start/end time of this operation.
-  uint64_t start_ns_;
-  uint64_t end_ns_;
-
- private:
-  BIONIC_DISALLOW_COPY_AND_ASSIGN(AllocEntry);
-};
-
-class MallocEntry : public AllocEntry {
- public:
-  MallocEntry(void* pointer, size_t size, uint64_t st, uint64_t et);
-  virtual ~MallocEntry() = default;
-
-  bool Write(int fd) const override;
-
- protected:
-  size_t size_;
-
- private:
-  BIONIC_DISALLOW_COPY_AND_ASSIGN(MallocEntry);
-};
-
-class FreeEntry : public AllocEntry {
- public:
-  explicit FreeEntry(void* pointer, uint64_t st, uint64_t et);
-  virtual ~FreeEntry() = default;
-
-  bool Write(int fd) const override;
-
- private:
-  BIONIC_DISALLOW_COPY_AND_ASSIGN(FreeEntry);
-};
-
-class CallocEntry : public MallocEntry {
- public:
-  CallocEntry(void* pointer, size_t nmemb, size_t size, uint64_t st, uint64_t et);
-  virtual ~CallocEntry() = default;
-
-  bool Write(int fd) const override;
-
- protected:
-  size_t nmemb_;
-
- private:
-  BIONIC_DISALLOW_COPY_AND_ASSIGN(CallocEntry);
-};
-
-class ReallocEntry : public MallocEntry {
- public:
-  ReallocEntry(void* pointer, size_t size, void* old_pointer, uint64_t st, uint64_t et);
-  virtual ~ReallocEntry() = default;
-
-  bool Write(int fd) const override;
-
- protected:
-  void* old_pointer_;
-
- private:
-  BIONIC_DISALLOW_COPY_AND_ASSIGN(ReallocEntry);
-};
-
-// aligned_alloc, posix_memalign, memalign, pvalloc, valloc all recorded with this class.
-class MemalignEntry : public MallocEntry {
- public:
-  MemalignEntry(void* pointer, size_t size, size_t alignment, uint64_t st, uint64_t et);
-  virtual ~MemalignEntry() = default;
-
-  bool Write(int fd) const override;
-
- protected:
-  size_t alignment_;
-
- private:
-  BIONIC_DISALLOW_COPY_AND_ASSIGN(MemalignEntry);
-};
-
 class Config;
 
 class RecordData {
@@ -159,8 +51,8 @@
 
   bool Initialize(const Config& config);
 
-  void AddEntry(const RecordEntry* entry);
-  void AddEntryOnly(const RecordEntry* entry);
+  void AddEntry(const memory_trace::Entry& entry);
+  void AddEntryOnly(const memory_trace::Entry& entry);
 
   const std::string& file() { return file_; }
   pthread_key_t key() { return key_; }
@@ -176,7 +68,7 @@
 
   std::mutex entries_lock_;
   pthread_key_t key_;
-  std::vector<std::unique_ptr<const RecordEntry>> entries_;
+  std::vector<memory_trace::Entry> entries_;
   size_t cur_index_;
   std::string file_;
 
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 3743852..c183897 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -54,6 +54,7 @@
 #include "Config.h"
 #include "DebugData.h"
 #include "LogAllocatorStats.h"
+#include "Nanotime.h"
 #include "Unreachable.h"
 #include "UnwindBacktrace.h"
 #include "backtrace.h"
@@ -70,12 +71,6 @@
 
 const MallocDispatch* g_dispatch;
 
-static inline __always_inline uint64_t Nanotime() {
-  struct timespec t = {};
-  clock_gettime(CLOCK_MONOTONIC, &t);
-  return static_cast<uint64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
-}
-
 namespace {
 // A TimedResult contains the result of from malloc end_ns al. functions and the
 // start/end timestamps.
@@ -598,8 +593,13 @@
   TimedResult result = InternalMalloc(size);
 
   if (g_debug->config().options() & RECORD_ALLOCS) {
-    g_debug->record->AddEntry(new MallocEntry(result.getValue<void*>(), size,
-                                              result.GetStartTimeNS(), result.GetEndTimeNS()));
+    g_debug->record->AddEntry(
+        memory_trace::Entry{.tid = gettid(),
+                            .type = memory_trace::MALLOC,
+                            .ptr = reinterpret_cast<uint64_t>(result.getValue<void*>()),
+                            .size = size,
+                            .start_ns = result.GetStartTimeNS(),
+                            .end_ns = result.GetEndTimeNS()});
   }
 
   return result.getValue<void*>();
@@ -687,8 +687,11 @@
   TimedResult result = InternalFree(pointer);
 
   if (g_debug->config().options() & RECORD_ALLOCS) {
-    g_debug->record->AddEntry(
-        new FreeEntry(pointer, result.GetStartTimeNS(), result.GetEndTimeNS()));
+    g_debug->record->AddEntry(memory_trace::Entry{.tid = gettid(),
+                                                  .type = memory_trace::FREE,
+                                                  .ptr = reinterpret_cast<uint64_t>(pointer),
+                                                  .start_ns = result.GetStartTimeNS(),
+                                                  .end_ns = result.GetEndTimeNS()});
   }
 }
 
@@ -771,8 +774,13 @@
     }
 
     if (g_debug->config().options() & RECORD_ALLOCS) {
-      g_debug->record->AddEntry(new MemalignEntry(pointer, bytes, alignment,
-                                                  result.GetStartTimeNS(), result.GetEndTimeNS()));
+      g_debug->record->AddEntry(memory_trace::Entry{.tid = gettid(),
+                                                    .type = memory_trace::MEMALIGN,
+                                                    .ptr = reinterpret_cast<uint64_t>(pointer),
+                                                    .size = bytes,
+                                                    .u.align = alignment,
+                                                    .start_ns = result.GetStartTimeNS(),
+                                                    .end_ns = result.GetEndTimeNS()});
     }
   }
 
@@ -791,11 +799,16 @@
 
   if (pointer == nullptr) {
     TimedResult result = InternalMalloc(bytes);
-    if (g_debug->config().options() & RECORD_ALLOCS) {
-      g_debug->record->AddEntry(new ReallocEntry(result.getValue<void*>(), bytes, nullptr,
-                                                 result.GetStartTimeNS(), result.GetEndTimeNS()));
-    }
     pointer = result.getValue<void*>();
+    if (g_debug->config().options() & RECORD_ALLOCS) {
+      g_debug->record->AddEntry(memory_trace::Entry{.tid = gettid(),
+                                                    .type = memory_trace::REALLOC,
+                                                    .ptr = reinterpret_cast<uint64_t>(pointer),
+                                                    .size = bytes,
+                                                    .u.old_ptr = 0,
+                                                    .start_ns = result.GetStartTimeNS(),
+                                                    .end_ns = result.GetEndTimeNS()});
+    }
     return pointer;
   }
 
@@ -807,8 +820,14 @@
     TimedResult result = InternalFree(pointer);
 
     if (g_debug->config().options() & RECORD_ALLOCS) {
-      g_debug->record->AddEntry(new ReallocEntry(nullptr, bytes, pointer, result.GetStartTimeNS(),
-                                                 result.GetEndTimeNS()));
+      g_debug->record->AddEntry(
+          memory_trace::Entry{.tid = gettid(),
+                              .type = memory_trace::REALLOC,
+                              .ptr = 0,
+                              .size = 0,
+                              .u.old_ptr = reinterpret_cast<uint64_t>(pointer),
+                              .start_ns = result.GetStartTimeNS(),
+                              .end_ns = result.GetEndTimeNS()});
     }
 
     return nullptr;
@@ -905,8 +924,13 @@
   }
 
   if (g_debug->config().options() & RECORD_ALLOCS) {
-    g_debug->record->AddEntry(new ReallocEntry(new_pointer, bytes, pointer, result.GetStartTimeNS(),
-                                               result.GetEndTimeNS()));
+    g_debug->record->AddEntry(memory_trace::Entry{.tid = gettid(),
+                                                  .type = memory_trace::REALLOC,
+                                                  .ptr = reinterpret_cast<uint64_t>(new_pointer),
+                                                  .size = bytes,
+                                                  .u.old_ptr = reinterpret_cast<uint64_t>(pointer),
+                                                  .start_ns = result.GetStartTimeNS(),
+                                                  .end_ns = result.GetEndTimeNS()});
   }
 
   return new_pointer;
@@ -962,8 +986,13 @@
   }
 
   if (g_debug->config().options() & RECORD_ALLOCS) {
-    g_debug->record->AddEntry(
-        new CallocEntry(pointer, nmemb, bytes, result.GetStartTimeNS(), result.GetEndTimeNS()));
+    g_debug->record->AddEntry(memory_trace::Entry{.tid = gettid(),
+                                                  .type = memory_trace::CALLOC,
+                                                  .ptr = reinterpret_cast<uint64_t>(pointer),
+                                                  .size = bytes,
+                                                  .u.n_elements = nmemb,
+                                                  .start_ns = result.GetStartTimeNS(),
+                                                  .end_ns = result.GetEndTimeNS()});
   }
 
   if (pointer != nullptr && g_debug->TrackPointers()) {
diff --git a/libc/platform/bionic/macros.h b/libc/platform/bionic/macros.h
index 93268c1..b2d6f96 100644
--- a/libc/platform/bionic/macros.h
+++ b/libc/platform/bionic/macros.h
@@ -97,3 +97,26 @@
 static inline T* _Nonnull untag_address(T* _Nonnull p) {
   return reinterpret_cast<T*>(untag_address(reinterpret_cast<uintptr_t>(p)));
 }
+
+// MTE globals protects internal and external global variables. One of the main
+// things that MTE globals does is force all global variable accesses to go
+// through the GOT. In the linker though, some global variables are accessed (or
+// address-taken) prior to relocations being processed. Because relocations
+// haven't run yet, the GOT entry hasn't been populated, and this leads to
+// crashes. Thus, any globals used by the linker prior to relocation should be
+// annotated with this attribute, which suppresses tagging of this global
+// variable, restoring the pc-relative address computation.
+//
+// A way to find global variables that need this attribute is to build the
+// linker/libc with `SANITIZE_TARGET=memtag_globals`, push them onto a device
+// (it doesn't have to be MTE capable), and then run an executable using
+// LD_LIBRARY_PATH and using the linker in interpreter mode (e.g.
+// `LD_LIBRARY_PATH=/data/tmp/ /data/tmp/linker64 /data/tmp/my_binary`). A
+// good heuristic is that the global variable is in a file that should be
+// compiled with `-ffreestanding` (but there are global variables there that
+// don't need this attribute).
+#if __has_feature(memtag_globals)
+#define BIONIC_USED_BEFORE_LINKER_RELOCATES __attribute__((no_sanitize("memtag")))
+#else  // __has_feature(memtag_globals)
+#define BIONIC_USED_BEFORE_LINKER_RELOCATES
+#endif  // __has_feature(memtag_globals)
diff --git a/libc/platform/bionic/mte.h b/libc/platform/bionic/mte.h
index 98b3d27..610cb45 100644
--- a/libc/platform/bionic/mte.h
+++ b/libc/platform/bionic/mte.h
@@ -28,6 +28,7 @@
 
 #pragma once
 
+#include <stddef.h>
 #include <sys/auxv.h>
 #include <sys/mman.h>
 #include <sys/prctl.h>
@@ -49,6 +50,36 @@
   return supported;
 }
 
+inline void* get_tagged_address(const void* ptr) {
+#if defined(__aarch64__)
+  if (mte_supported()) {
+    __asm__ __volatile__(".arch_extension mte; ldg %0, [%0]" : "+r"(ptr));
+  }
+#endif  // aarch64
+  return const_cast<void*>(ptr);
+}
+
+// Inserts a random tag tag to `ptr`, using any of the set lower 16 bits in
+// `mask` to exclude the corresponding tag from being generated. Note: This does
+// not tag memory. This generates a pointer to be used with set_memory_tag.
+inline void* insert_random_tag(const void* ptr, __attribute__((unused)) uint64_t mask = 0) {
+#if defined(__aarch64__)
+  if (mte_supported() && ptr) {
+    __asm__ __volatile__(".arch_extension mte; irg %0, %0, %1" : "+r"(ptr) : "r"(mask));
+  }
+#endif  // aarch64
+  return const_cast<void*>(ptr);
+}
+
+// Stores the address tag in `ptr` to memory, at `ptr`.
+inline void set_memory_tag(__attribute__((unused)) void* ptr) {
+#if defined(__aarch64__)
+  if (mte_supported()) {
+    __asm__ __volatile__(".arch_extension mte; stg %0, [%0]" : "+r"(ptr));
+  }
+#endif  // aarch64
+}
+
 #ifdef __aarch64__
 class ScopedDisableMTE {
   size_t prev_tco_;
@@ -86,6 +117,12 @@
   return ptr | ((1ULL << size_cls) << 56ULL);
 }
 
+inline void stack_mte_free_ringbuffer(uintptr_t stack_mte_tls) {
+  size_t size = stack_mte_ringbuffer_size_from_pointer(stack_mte_tls);
+  void* ptr = reinterpret_cast<void*>(stack_mte_tls & ((1ULL << 56ULL) - 1ULL));
+  munmap(ptr, size);
+}
+
 inline void* stack_mte_ringbuffer_allocate(size_t n, const char* name) {
   if (n > 7) return nullptr;
   // Allocation needs to be aligned to 2*size to make the fancy code-gen work.
diff --git a/libc/platform/bionic/reserved_signals.h b/libc/platform/bionic/reserved_signals.h
index dab58af..eb423f6 100644
--- a/libc/platform/bionic/reserved_signals.h
+++ b/libc/platform/bionic/reserved_signals.h
@@ -44,6 +44,7 @@
 //   38 (__SIGRTMIN + 6)        heapprofd ART managed heap dumps
 //   39 (__SIGRTMIN + 7)        fdtrack
 //   40 (__SIGRTMIN + 8)        android_run_on_all_threads (bionic/pthread_internal.cpp)
+//   41 (__SIGRTMIN + 9)        re-enable MTE on thread
 
 #define BIONIC_SIGNAL_POSIX_TIMERS (__SIGRTMIN + 0)
 #define BIONIC_SIGNAL_BACKTRACE (__SIGRTMIN + 1)
@@ -52,8 +53,9 @@
 #define BIONIC_SIGNAL_ART_PROFILER (__SIGRTMIN + 6)
 #define BIONIC_SIGNAL_FDTRACK (__SIGRTMIN + 7)
 #define BIONIC_SIGNAL_RUN_ON_ALL_THREADS (__SIGRTMIN + 8)
+#define BIONIC_ENABLE_MTE (__SIGRTMIN + 9)
 
-#define __SIGRT_RESERVED 9
+#define __SIGRT_RESERVED 10
 static inline __always_inline sigset64_t filter_reserved_signals(sigset64_t sigset, int how) {
   int (*block)(sigset64_t*, int);
   int (*unblock)(sigset64_t*, int);
@@ -83,5 +85,6 @@
   unblock(&sigset, __SIGRTMIN + 6);
   unblock(&sigset, __SIGRTMIN + 7);
   unblock(&sigset, __SIGRTMIN + 8);
+  unblock(&sigset, __SIGRTMIN + 9);
   return sigset;
 }
diff --git a/libc/private/CachedProperty.h b/libc/private/CachedProperty.h
index bd67d74..7accdb3 100644
--- a/libc/private/CachedProperty.h
+++ b/libc/private/CachedProperty.h
@@ -29,9 +29,7 @@
 #pragma once
 
 #include <string.h>
-
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
+#include <sys/system_properties.h>
 
 // Cached system property lookup. For code that needs to read the same property multiple times,
 // this class helps optimize those lookups.
diff --git a/libc/private/KernelArgumentBlock.h b/libc/private/KernelArgumentBlock.h
index ee28d69..e1f655a 100644
--- a/libc/private/KernelArgumentBlock.h
+++ b/libc/private/KernelArgumentBlock.h
@@ -29,7 +29,7 @@
 // constituents for easy access.
 class KernelArgumentBlock {
  public:
-  explicit KernelArgumentBlock(void* raw_args) {
+  __attribute__((no_sanitize("hwaddress"))) explicit KernelArgumentBlock(void* raw_args) {
     uintptr_t* args = reinterpret_cast<uintptr_t*>(raw_args);
     argc = static_cast<int>(*args);
     argv = reinterpret_cast<char**>(args + 1);
@@ -48,7 +48,7 @@
 
   // Similar to ::getauxval but doesn't require the libc global variables to be set up,
   // so it's safe to call this really early on.
-  unsigned long getauxval(unsigned long type) {
+  __attribute__((no_sanitize("hwaddress"))) unsigned long getauxval(unsigned long type) {
     for (ElfW(auxv_t)* v = auxv; v->a_type != AT_NULL; ++v) {
       if (v->a_type == type) {
         return v->a_un.a_val;
diff --git a/libc/private/bionic_asm_arm.h b/libc/private/bionic_asm_arm.h
index d8381d3..9ca5f38 100644
--- a/libc/private/bionic_asm_arm.h
+++ b/libc/private/bionic_asm_arm.h
@@ -37,7 +37,7 @@
 
 #pragma once
 
-#define __bionic_asm_align 0
+#define __bionic_asm_align 64
 
 #undef __bionic_asm_custom_entry
 #undef __bionic_asm_custom_end
diff --git a/libc/private/bionic_asm_arm64.h b/libc/private/bionic_asm_arm64.h
index ffc7181..1e907a1 100644
--- a/libc/private/bionic_asm_arm64.h
+++ b/libc/private/bionic_asm_arm64.h
@@ -37,7 +37,7 @@
 
 #pragma once
 
-#define __bionic_asm_align 16
+#define __bionic_asm_align 64
 
 #undef __bionic_asm_function_type
 #define __bionic_asm_function_type %function
diff --git a/libc/private/bionic_constants.h b/libc/private/bionic_constants.h
index 6274fe2..ce484d8 100644
--- a/libc/private/bionic_constants.h
+++ b/libc/private/bionic_constants.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#define US_PER_S 1'000'000LL
 #define NS_PER_S 1'000'000'000LL
 
 // Size of the shadow call stack. This can be small because these stacks only
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
index a1bebda..cd6dca9 100644
--- a/libc/private/bionic_globals.h
+++ b/libc/private/bionic_globals.h
@@ -157,6 +157,10 @@
 };
 
 __LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals();
+__LIBC_HIDDEN__ bool __libc_mte_enabled();
+__LIBC_HIDDEN__ void __libc_init_mte(const memtag_dynamic_entries_t*, const void*, size_t,
+                                     uintptr_t);
+__LIBC_HIDDEN__ void __libc_init_mte_stack(void*);
 __LIBC_HIDDEN__ void __libc_init_fdsan();
 __LIBC_HIDDEN__ void __libc_init_fdtrack();
 __LIBC_HIDDEN__ void __libc_init_profiling_handlers();
diff --git a/libc/private/bionic_ifuncs.h b/libc/private/bionic_ifuncs.h
index e6b349a..b31c903 100644
--- a/libc/private/bionic_ifuncs.h
+++ b/libc/private/bionic_ifuncs.h
@@ -31,6 +31,8 @@
 #include <stdint.h>
 #include <sys/ifunc.h>
 
+#include <private/bionic_call_ifunc_resolver.h>
+
 #if defined(__aarch64__)
 #define IFUNC_ARGS (uint64_t hwcap __attribute__((unused)), \
                     __ifunc_arg_t* arg __attribute__((unused)))
@@ -40,14 +42,6 @@
 #define IFUNC_ARGS ()
 #endif
 
-// We can't have HWASAN enabled in resolvers because they may be called before HWASAN is
-// initialized.
-#define DEFINE_IFUNC_FOR(name) \
-    name##_func name __attribute__((ifunc(#name "_resolver"))); \
-    __attribute__((visibility("hidden"))) \
-    __attribute__((no_sanitize("hwaddress"))) \
-    name##_func* name##_resolver IFUNC_ARGS
-
 #define DECLARE_FUNC(type, name) \
     __attribute__((visibility("hidden"))) \
     type name
@@ -56,3 +50,137 @@
         DECLARE_FUNC(type, name); \
         return name; \
     }
+
+#if defined(BIONIC_DYNAMIC_DISPATCH)
+
+// We can't have HWASAN enabled in resolvers because they may be called before
+// HWASAN is initialized.
+#define DEFINE_IFUNC_FOR(name)                                  \
+  name##_func_t name __attribute__((ifunc(#name "_resolver"))); \
+  __attribute__((visibility("hidden")))                         \
+  __attribute__((no_sanitize("hwaddress"))) name##_func_t* name##_resolver IFUNC_ARGS
+
+#define DEFINE_STATIC_SHIM(x)
+
+#elif defined(BIONIC_STATIC_DISPATCH)
+
+#define DEFINE_IFUNC_FOR(name)               \
+  name##_func_t* name##_resolver IFUNC_ARGS; \
+  __attribute__((visibility("hidden")))      \
+  __attribute__((no_sanitize("hwaddress"))) name##_func_t* name##_resolver IFUNC_ARGS
+
+#define DEFINE_STATIC_SHIM(x) x
+
+#define FORWARD(name)                                                               \
+  static name##_func_t* fn = reinterpret_cast<name##_func_t*>(                      \
+      __bionic_call_ifunc_resolver(reinterpret_cast<ElfW(Addr)>(name##_resolver))); \
+  return fn
+
+#else
+#error neither dynamic nor static dispatch?!
+#endif
+
+typedef void* memchr_func_t(const void*, int, size_t);
+#define MEMCHR_SHIM()                                                  \
+  DEFINE_STATIC_SHIM(void* memchr(const void* src, int ch, size_t n) { \
+    FORWARD(memchr)(src, ch, n);                                       \
+  })
+
+typedef int memcmp_func_t(const void*, const void*, size_t);
+#define MEMCMP_SHIM()                                                         \
+  DEFINE_STATIC_SHIM(int memcmp(const void* lhs, const void* rhs, size_t n) { \
+    FORWARD(memcmp)(lhs, rhs, n);                                             \
+  })
+
+typedef void* memcpy_func_t(void*, const void*, size_t);
+#define MEMCPY_SHIM()                                                     \
+  DEFINE_STATIC_SHIM(void* memcpy(void* dst, const void* src, size_t n) { \
+    FORWARD(memcpy)(dst, src, n);                                         \
+  })
+
+typedef void* memmove_func_t(void*, const void*, size_t);
+#define MEMMOVE_SHIM()                                                     \
+  DEFINE_STATIC_SHIM(void* memmove(void* dst, const void* src, size_t n) { \
+    FORWARD(memmove)(dst, src, n);                                         \
+  })
+
+typedef int memrchr_func_t(const void*, int, size_t);
+#define MEMRCHR_SHIM()                                                \
+  DEFINE_STATIC_SHIM(int memrchr(const void* src, int ch, size_t n) { \
+    FORWARD(memrchr)(src, ch, n);                                     \
+  })
+
+typedef void* memset_func_t(void*, int, size_t);
+#define MEMSET_SHIM() \
+  DEFINE_STATIC_SHIM(void* memset(void* dst, int ch, size_t n) { FORWARD(memset)(dst, ch, n); })
+
+typedef void* __memset_chk_func_t(void*, int, size_t, size_t);
+#define __MEMSET_CHK_SHIM()                                                       \
+  DEFINE_STATIC_SHIM(void* __memset_chk(void* dst, int ch, size_t n, size_t n2) { \
+    FORWARD(__memset_chk)(dst, ch, n, n2);                                        \
+  })
+
+typedef char* stpcpy_func_t(char*, const char*);
+#define STPCPY_SHIM() \
+  DEFINE_STATIC_SHIM(char* stpcpy(char* dst, const char* src) { FORWARD(stpcpy)(dst, src); })
+
+typedef char* strcat_func_t(char*, const char*);
+#define STRCAT_SHIM() \
+  DEFINE_STATIC_SHIM(char* strcat(char* dst, const char* src) { FORWARD(strcat)(dst, src); })
+
+typedef char* __strcat_chk_func_t(char*, const char*, size_t);
+#define __STRCAT_CHK_SHIM()                                                                \
+  DEFINE_STATIC_SHIM(char* __strcat_chk(char* dst, const char* src, size_t dst_buf_size) { \
+    FORWARD(__strcat_chk)(dst, src, dst_buf_size);                                         \
+  })
+
+typedef char* strchr_func_t(const char*, int);
+#define STRCHR_SHIM() \
+  DEFINE_STATIC_SHIM(char* strchr(const char* src, int ch) { FORWARD(strchr)(src, ch); })
+
+typedef char* strchrnul_func_t(const char*, int);
+#define STRCHRNUL_SHIM() \
+  DEFINE_STATIC_SHIM(char* strchrnul(const char* src, int ch) { FORWARD(strchrnul)(src, ch); })
+
+typedef int strcmp_func_t(const char*, const char*);
+#define STRCMP_SHIM() \
+  DEFINE_STATIC_SHIM(int strcmp(char* lhs, const char* rhs) { FORWARD(strcmp)(lhs, rhs); })
+
+typedef char* strcpy_func_t(char*, const char*);
+#define STRCPY_SHIM() \
+  DEFINE_STATIC_SHIM(char* strcpy(char* dst, const char* src) { FORWARD(strcpy)(dst, src); })
+
+typedef char* __strcpy_chk_func_t(char*, const char*, size_t);
+#define __STRCPY_CHK_SHIM()                                                           \
+  DEFINE_STATIC_SHIM(char* __strcpy_chk(char* dst, const char* src, size_t dst_len) { \
+    FORWARD(__strcpy_chk)(dst, src, dst_len);                                         \
+  })
+
+typedef size_t strlen_func_t(const char*);
+#define STRLEN_SHIM() DEFINE_STATIC_SHIM(size_t strlen(const char* s) { FORWARD(strlen)(s); })
+
+typedef char* strncat_func_t(char*, const char*, size_t);
+#define STRNCAT_SHIM()                                                     \
+  DEFINE_STATIC_SHIM(char* strncat(char* dst, const char* src, size_t n) { \
+    FORWARD(strncat)(dst, src, n);                                         \
+  })
+
+typedef int strncmp_func_t(const char*, const char*, size_t);
+#define STRNCMP_SHIM()                                                         \
+  DEFINE_STATIC_SHIM(int strncmp(const char* lhs, const char* rhs, size_t n) { \
+    FORWARD(strncmp)(lhs, rhs, n);                                             \
+  })
+
+typedef char* strncpy_func_t(char*, const char*, size_t);
+#define STRNCPY_SHIM()                                                     \
+  DEFINE_STATIC_SHIM(char* strncpy(char* dst, const char* src, size_t n) { \
+    FORWARD(strncpy)(dst, src, n);                                         \
+  })
+
+typedef size_t strnlen_func_t(const char*, size_t);
+#define STRNLEN_SHIM() \
+  DEFINE_STATIC_SHIM(size_t strnlen(const char* s, size_t n) { FORWARD(strnlen)(s, n); })
+
+typedef char* strrchr_func_t(const char*, int);
+#define STRRCHR_SHIM() \
+  DEFINE_STATIC_SHIM(char* strrchr(const char* src, int ch) { FORWARD(strrchr)(src, ch); })
diff --git a/libc/private/bionic_lock.h b/libc/private/bionic_lock.h
index 8ed4939..d0c6d5e 100644
--- a/libc/private/bionic_lock.h
+++ b/libc/private/bionic_lock.h
@@ -46,7 +46,7 @@
 
  public:
   void init(bool process_shared) {
-    atomic_init(&state, Unlocked);
+    atomic_store_explicit(&state, Unlocked, memory_order_relaxed);
     this->process_shared = process_shared;
   }
 
diff --git a/libc/private/bionic_mbstate.h b/libc/private/bionic_mbstate.h
index 0e5f861..fb85775 100644
--- a/libc/private/bionic_mbstate.h
+++ b/libc/private/bionic_mbstate.h
@@ -38,11 +38,11 @@
   (rv == BIONIC_MULTIBYTE_RESULT_ILLEGAL_SEQUENCE || \
    rv == BIONIC_MULTIBYTE_RESULT_INCOMPLETE_SEQUENCE)
 
-static inline __wur bool mbstate_is_initial(const mbstate_t* ps) {
+static inline __nodiscard bool mbstate_is_initial(const mbstate_t* ps) {
   return *(reinterpret_cast<const uint32_t*>(ps->__seq)) == 0;
 }
 
-static inline __wur size_t mbstate_bytes_so_far(const mbstate_t* ps) {
+static inline __nodiscard size_t mbstate_bytes_so_far(const mbstate_t* ps) {
   return
       (ps->__seq[2] != 0) ? 3 :
       (ps->__seq[1] != 0) ? 2 :
@@ -53,7 +53,7 @@
   ps->__seq[i] = static_cast<uint8_t>(byte);
 }
 
-static inline __wur uint8_t mbstate_get_byte(const mbstate_t* ps, int n) {
+static inline __nodiscard uint8_t mbstate_get_byte(const mbstate_t* ps, int n) {
   return ps->__seq[n];
 }
 
@@ -61,13 +61,13 @@
   *(reinterpret_cast<uint32_t*>(ps->__seq)) = 0;
 }
 
-static inline __wur size_t mbstate_reset_and_return_illegal(int _errno, mbstate_t* ps) {
+static inline __nodiscard size_t mbstate_reset_and_return_illegal(int _errno, mbstate_t* ps) {
   errno = _errno;
   mbstate_reset(ps);
   return BIONIC_MULTIBYTE_RESULT_ILLEGAL_SEQUENCE;
 }
 
-static inline __wur size_t mbstate_reset_and_return(size_t _return, mbstate_t* ps) {
+static inline __nodiscard size_t mbstate_reset_and_return(size_t _return, mbstate_t* ps) {
   mbstate_reset(ps);
   return _return;
 }
diff --git a/libc/private/bionic_time_conversions.h b/libc/private/bionic_time_conversions.h
index c6b3c78..ce7de0d 100644
--- a/libc/private/bionic_time_conversions.h
+++ b/libc/private/bionic_time_conversions.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _BIONIC_TIME_CONVERSIONS_H
-#define _BIONIC_TIME_CONVERSIONS_H
+#pragma once
 
 #include <errno.h>
 #include <time.h>
@@ -35,20 +34,21 @@
 
 #include "private/bionic_constants.h"
 
-__BEGIN_DECLS
+bool timespec_from_timeval(timespec& ts, const timeval& tv);
+void timespec_from_ms(timespec& ts, const int ms);
 
-__LIBC_HIDDEN__ bool timespec_from_timeval(timespec& ts, const timeval& tv);
-__LIBC_HIDDEN__ void timespec_from_ms(timespec& ts, const int ms);
+void timeval_from_timespec(timeval& tv, const timespec& ts);
 
-__LIBC_HIDDEN__ void timeval_from_timespec(timeval& tv, const timespec& ts);
+void monotonic_time_from_realtime_time(timespec& monotonic_time, const timespec& realtime_time);
+void realtime_time_from_monotonic_time(timespec& realtime_time, const timespec& monotonic_time);
 
-__LIBC_HIDDEN__ void monotonic_time_from_realtime_time(timespec& monotonic_time,
-                                                       const timespec& realtime_time);
+static inline int64_t to_ns(const timespec& ts) {
+  return ts.tv_sec * NS_PER_S + ts.tv_nsec;
+}
 
-__LIBC_HIDDEN__ void realtime_time_from_monotonic_time(timespec& realtime_time,
-                                                       const timespec& monotonic_time);
-
-__END_DECLS
+static inline int64_t to_us(const timeval& tv) {
+  return tv.tv_sec * US_PER_S + tv.tv_usec;
+}
 
 static inline int check_timespec(const timespec* ts, bool null_allowed) {
   if (null_allowed && ts == nullptr) {
@@ -76,5 +76,3 @@
   }
 }
 #endif
-
-#endif
diff --git a/libc/private/bsd_sys_param.h b/libc/private/bsd_sys_param.h
deleted file mode 100644
index ab54aa0..0000000
--- a/libc/private/bsd_sys_param.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <inttypes.h>
-
-/* OpenBSD has these in <sys/param.h>, but "ALIGN" isn't something we want to reserve. */
-#define ALIGNBYTES (sizeof(uintptr_t) - 1)
-#define ALIGN(p) ((__BIONIC_CAST(reinterpret_cast, uintptr_t, p) + ALIGNBYTES) & ~ALIGNBYTES)
diff --git a/libc/private/icu.h b/libc/private/icu.h
index a671e98..8e4aa80 100644
--- a/libc/private/icu.h
+++ b/libc/private/icu.h
@@ -80,7 +80,8 @@
 
 int8_t __icu_charType(wint_t wc);
 int32_t __icu_getIntPropertyValue(wint_t wc, UProperty property);
-bool __icu_hasBinaryProperty(wint_t wc, UProperty property, int (*fallback)(int));
+
+typedef UBool (*u_hasBinaryProperty_t)(UChar32, UProperty);
 
 void* __find_icu_symbol(const char* symbol_name);
 
diff --git a/libc/stdio/fmemopen.cpp b/libc/stdio/fmemopen.cpp
index 6e333ba..f069da4 100644
--- a/libc/stdio/fmemopen.cpp
+++ b/libc/stdio/fmemopen.cpp
@@ -33,8 +33,8 @@
 
 #include "local.h"
 
-// See http://pubs.opengroup.org/onlinepubs/9699919799/functions/fmemopen.html
-// and http://man7.org/linux/man-pages/man3/fmemopen.3.html for documentation.
+// See https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/fmemopen.html
+// and https://man7.org/linux/man-pages/man3/fmemopen.3.html for documentation.
 
 struct fmemopen_cookie {
   char* buf;
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
index 62efea1..a60468e 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -51,11 +51,7 @@
 
 struct __sbuf {
   unsigned char* _base;
-#if defined(__LP64__)
   size_t _size;
-#else
-  int _size;
-#endif
 };
 
 struct __sFILE {
diff --git a/libc/stdio/printf_common.h b/libc/stdio/printf_common.h
index 702f8d3..653bba2 100644
--- a/libc/stdio/printf_common.h
+++ b/libc/stdio/printf_common.h
@@ -85,6 +85,10 @@
 // Helper function for `fprintf to unbuffered unix file': creates a
 // temporary buffer.  We only work on write-only files; this avoids
 // worries about ungetc buffers and so forth.
+//
+// We prevent inlining because this massively increases the printf()
+// family's stack usage to support a rare case.
+__attribute__((__noinline__))
 static int __sbprintf(FILE* fp, const CHAR_TYPE* fmt, va_list ap) {
   FILE fake;
   struct __sfileext fakeext;
diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp
index f18cd81..a5f2f81 100644
--- a/libc/stdio/stdio.cpp
+++ b/libc/stdio/stdio.cpp
@@ -58,8 +58,6 @@
 #include "private/bionic_fortify.h"
 #include "private/thread_private.h"
 
-#include "private/bsd_sys_param.h" // For ALIGN/ALIGNBYTES.
-
 #define	NDYNAMIC 10		/* add ten more whenever necessary */
 
 #define PRINTF_IMPL(expr) \
@@ -135,12 +133,14 @@
 };
 
 static glue* moreglue(int n) {
-  char* data = new char[sizeof(glue) + ALIGNBYTES + n * sizeof(FILE) + n * sizeof(__sfileext)];
+  char* data = new char[sizeof(glue) +
+                        alignof(FILE) + n * sizeof(FILE) +
+                        alignof(__sfileext) + n * sizeof(__sfileext)];
   if (data == nullptr) return nullptr;
 
   glue* g = reinterpret_cast<glue*>(data);
-  FILE* p = reinterpret_cast<FILE*>(ALIGN(data + sizeof(*g)));
-  __sfileext* pext = reinterpret_cast<__sfileext*>(ALIGN(data + sizeof(*g)) + n * sizeof(FILE));
+  FILE* p = reinterpret_cast<FILE*>(__builtin_align_up(g + 1, alignof(FILE)));
+  __sfileext* pext = reinterpret_cast<__sfileext*>(__builtin_align_up(p + n, alignof(__sfileext)));
   g->next = nullptr;
   g->niobs = n;
   g->iobs = p;
@@ -1079,6 +1079,26 @@
   return __sflush(fp);
 }
 
+int fpurge(FILE* fp) {
+  CHECK_FP(fp);
+
+  ScopedFileLock sfl(fp);
+
+  if (fp->_flags == 0) {
+    // Already freed!
+    errno = EBADF;
+    return EOF;
+  }
+
+  if (HASUB(fp)) FREEUB(fp);
+  WCIO_FREE(fp);
+  fp->_p = fp->_bf._base;
+  fp->_r = 0;
+  fp->_w = fp->_flags & (__SLBF | __SNBF) ? 0 : fp->_bf._size;
+  return 0;
+}
+__strong_alias(__fpurge, fpurge);
+
 size_t fread(void* buf, size_t size, size_t count, FILE* fp) {
   CHECK_FP(fp);
   ScopedFileLock sfl(fp);
diff --git a/libc/stdio/stdio_ext.cpp b/libc/stdio/stdio_ext.cpp
index 99a8af7..3eb2f33 100644
--- a/libc/stdio/stdio_ext.cpp
+++ b/libc/stdio/stdio_ext.cpp
@@ -59,10 +59,6 @@
   return (fp->_flags & __SLBF) != 0;
 }
 
-void __fpurge(FILE* fp) {
-  fpurge(fp);
-}
-
 size_t __fpending(FILE* fp) {
   return fp->_p - fp->_bf._base;
 }
diff --git a/libc/stdio/vfprintf.cpp b/libc/stdio/vfprintf.cpp
index e0509aa..354317c 100644
--- a/libc/stdio/vfprintf.cpp
+++ b/libc/stdio/vfprintf.cpp
@@ -43,7 +43,7 @@
 
 #define PRINT(ptr, len)                          \
   do {                                           \
-    iovp->iov_base = (ptr);                      \
+    iovp->iov_base = (void*)(ptr);               \
     iovp->iov_len = (len);                       \
     uio.uio_resid += (len);                      \
     iovp++;                                      \
@@ -125,10 +125,10 @@
    * below longer.
    */
 #define PADSIZE 16 /* pad chunk size */
-  static CHAR_TYPE blanks[PADSIZE] = {
+  static const CHAR_TYPE blanks[PADSIZE] = {
     ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
   };
-  static CHAR_TYPE zeroes[PADSIZE] = {
+  static const CHAR_TYPE zeroes[PADSIZE] = {
     '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'
   };
 
diff --git a/libc/stdio/vfwprintf.cpp b/libc/stdio/vfwprintf.cpp
index 72f973c..89e889e 100644
--- a/libc/stdio/vfwprintf.cpp
+++ b/libc/stdio/vfwprintf.cpp
@@ -128,10 +128,10 @@
    * below longer.
    */
 #define PADSIZE 16 /* pad chunk size */
-  static CHAR_TYPE blanks[PADSIZE] = {
+  static const CHAR_TYPE blanks[PADSIZE] = {
     ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
   };
-  static CHAR_TYPE zeroes[PADSIZE] = {
+  static const CHAR_TYPE zeroes[PADSIZE] = {
     '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'
   };
 
diff --git a/libc/system_properties/Android.bp b/libc/system_properties/Android.bp
index 16ea73f..e2fce34 100644
--- a/libc/system_properties/Android.bp
+++ b/libc/system_properties/Android.bp
@@ -58,27 +58,10 @@
     ],
 }
 
-soong_config_module_type {
-    name: "large_system_property_node_cc_defaults",
-    module_type: "cc_defaults",
-    config_namespace: "bionic",
-    bool_variables: [
-        "large_system_property_node",
-    ],
-    properties: [
-        "cflags",
-    ],
-}
-
-soong_config_bool_variable {
-    name: "large_system_property_node",
-}
-
-large_system_property_node_cc_defaults {
+cc_defaults {
     name: "large_system_property_node_defaults",
-    soong_config_variables: {
-        large_system_property_node: {
-            cflags: ["-DLARGE_SYSTEM_PROPERTY_NODE=1"]
-        }
-    }
+    cflags: select(release_flag("RELEASE_LARGE_SYSTEM_PROPERTY_NODE"), {
+        true: ["-DLARGE_SYSTEM_PROPERTY_NODE=1"],
+        default: [],
+    }),
 }
diff --git a/libc/system_properties/include/system_properties/prop_area.h b/libc/system_properties/include/system_properties/prop_area.h
index 187ff75..089cf52 100644
--- a/libc/system_properties/include/system_properties/prop_area.h
+++ b/libc/system_properties/include/system_properties/prop_area.h
@@ -102,7 +102,7 @@
   }
 
   prop_area(const uint32_t magic, const uint32_t version) : magic_(magic), version_(version) {
-    atomic_init(&serial_, 0u);
+    atomic_store_explicit(&serial_, 0u, memory_order_relaxed);
     memset(reserved_, 0, sizeof(reserved_));
     // Allocate enough space for the root node.
     bytes_used_ = sizeof(prop_trie_node);
diff --git a/libc/system_properties/include/system_properties/properties_filename.h b/libc/system_properties/include/system_properties/properties_filename.h
index d686f20..743d291 100644
--- a/libc/system_properties/include/system_properties/properties_filename.h
+++ b/libc/system_properties/include/system_properties/properties_filename.h
@@ -46,6 +46,8 @@
   const char* c_str() { return filename_; }
 
  private:
-  // Typically something like "/dev/__properties__/properties_serial".
-  char filename_[128];
+  // Typically something like "/dev/__properties__/properties_serial", but can be as long as
+  // "/data/local/tmp/TemporaryDir-fntJb8/appcompat_override/u:object_r:PROPERTY_NAME_prop:s0"
+  // when running CTS.
+  char filename_[256];
 };
diff --git a/libc/system_properties/prop_info.cpp b/libc/system_properties/prop_info.cpp
index c3bf177..499b36a 100644
--- a/libc/system_properties/prop_info.cpp
+++ b/libc/system_properties/prop_info.cpp
@@ -38,7 +38,7 @@
 prop_info::prop_info(const char* name, uint32_t namelen, const char* value, uint32_t valuelen) {
   memcpy(this->name, name, namelen);
   this->name[namelen] = '\0';
-  atomic_init(&this->serial, valuelen << 24);
+  atomic_store_explicit(&this->serial, valuelen << 24, memory_order_relaxed);
   memcpy(this->value, value, valuelen);
   this->value[valuelen] = '\0';
 }
@@ -48,7 +48,7 @@
   this->name[namelen] = '\0';
 
   auto error_value_len = sizeof(kLongLegacyError) - 1;
-  atomic_init(&this->serial, error_value_len << 24 | kLongFlag);
+  atomic_store_explicit(&this->serial, error_value_len << 24 | kLongFlag, memory_order_relaxed);
   memcpy(this->long_property.error_message, kLongLegacyError, sizeof(kLongLegacyError));
 
   this->long_property.offset = long_offset;
diff --git a/libc/tzcode/strptime.c b/libc/tzcode/strptime.c
index ae7881e..20160c9 100644
--- a/libc/tzcode/strptime.c
+++ b/libc/tzcode/strptime.c
@@ -68,8 +68,8 @@
 #define FIELD_TM_YDAY	(1 << 3)
 #define FIELD_TM_YEAR	(1 << 4)
 
-static char gmt[] = { "GMT" };
-static char utc[] = { "UTC" };
+static const char gmt[] = { "GMT" };
+static const char utc[] = { "UTC" };
 /* RFC-822/RFC-2822 */
 static const char * const nast[5] = {
        "EST",    "CST",    "MST",    "PST",    "\0\0\0"
@@ -97,6 +97,7 @@
 	return(_strptime(buf, fmt, tm, 1));
 }
 DEF_WEAK(strptime);
+__strong_alias(strptime_l, strptime);
 
 static char *
 _strptime(const char *buf, const char *fmt, struct tm *tm, int initialize)
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/qsort_r.c b/libc/upstream-freebsd/lib/libc/stdlib/qsort_r.c
new file mode 100644
index 0000000..b382b40
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/stdlib/qsort_r.c
@@ -0,0 +1,6 @@
+/*
+ * This file is in the public domain.  Originally written by Garrett
+ * A. Wollman.
+ */
+#define I_AM_QSORT_R
+#include "qsort.c"
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/bsearch.c b/libc/upstream-netbsd/lib/libc/stdlib/bsearch.c
deleted file mode 100644
index e48fe85..0000000
--- a/libc/upstream-netbsd/lib/libc/stdlib/bsearch.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*	$NetBSD: bsearch.c,v 1.16 2022/05/31 08:43:14 andvar Exp $	*/
-
-/*
- * Copyright (c) 1990, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)bsearch.c	8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: bsearch.c,v 1.16 2022/05/31 08:43:14 andvar Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
-#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/*
- * Perform a binary search.
- *
- * The code below is a bit sneaky.  After a comparison fails, we
- * divide the work in half by moving either left or right. If lim
- * is odd, moving left simply involves halving lim: e.g., when lim
- * is 5 we look at item 2, so we change lim to 2 so that we will
- * look at items 0 & 1.  If lim is even, the same applies.  If lim
- * is odd, moving right again involves halving lim, this time moving
- * the base up one item past p: e.g., when lim is 5 we change base
- * to item 3 and make lim 2 so that we will look at items 3 and 4.
- * If lim is even, however, we have to shrink it by one before
- * halving: e.g., when lim is 4, we still looked at item 2, so we
- * have to make lim 3, then halve, obtaining 1, so that we will only
- * look at item 3.
- */
-void *
-bsearch(const void *key, const void *base0, size_t nmemb, size_t size,
-    int (*compar)(const void *, const void *))
-{
-	const char *base = base0;
-	size_t lim;
-	int cmp;
-	const void *p;
-
-	_DIAGASSERT(key != NULL);
-	_DIAGASSERT(base0 != NULL || nmemb == 0);
-	_DIAGASSERT(compar != NULL);
-
-	for (lim = nmemb; lim != 0; lim >>= 1) {
-		p = base + (lim >> 1) * size;
-		cmp = (*compar)(key, p);
-		if (cmp == 0)
-			return __UNCONST(p);
-		if (cmp > 0) {	/* key > p: move right */
-			base = (const char *)p + size;
-			lim--;
-		}		/* else move left */
-	}
-	return (NULL);
-}
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index cbc52b5..ac6840a 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -25,8 +25,6 @@
 
 #include <sys/random.h> // For getentropy.
 
-#include "private/bsd_sys_param.h"
-
 #define __BEGIN_HIDDEN_DECLS _Pragma("GCC visibility push(hidden)")
 #define __END_HIDDEN_DECLS _Pragma("GCC visibility pop")
 
diff --git a/libc/upstream-openbsd/lib/libc/gen/fnmatch.c b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
index ff6b26e..3ec0222 100644
--- a/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
+++ b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
@@ -46,11 +46,11 @@
  *
  * Derived from The Open Group Base Specifications Issue 7, IEEE Std 1003.1-2008
  * as described in;
- *   http://pubs.opengroup.org/onlinepubs/9699919799/functions/fnmatch.html
+ *   https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/fnmatch.html
  *
  * Filename pattern matches defined in section 2.13, "Pattern Matching Notation"
  * from chapter 2. "Shell Command Language"
- *   http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13
+ *   https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/utilities/V3_chap02.html#tag_18_13
  * where; 1. A bracket expression starting with an unquoted <circumflex> '^'
  * character CONTINUES to specify a non-matching list; 2. an explicit <period> '.'
  * in a bracket expression matching list, e.g. "[.abc]" does NOT match a leading
@@ -61,7 +61,7 @@
  *
  * Bracket expansion defined in section 9.3.5, "RE Bracket Expression",
  * from chapter 9, "Regular Expressions"
- *   http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_05
+ *   https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/basedefs/V1_chap09.html#tag_09_03_05
  * with no support for collating symbols, equivalence class expressions or
  * character class expressions.  A partial range expression with a leading
  * hyphen following a valid range expression will match only the ordinary
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fpurge.c b/libc/upstream-openbsd/lib/libc/stdio/fpurge.c
deleted file mode 100644
index 8dd8a91..0000000
--- a/libc/upstream-openbsd/lib/libc/stdio/fpurge.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*	$OpenBSD: fpurge.c,v 1.10 2015/08/31 02:53:57 guenther Exp $ */
-/*-
- * Copyright (c) 1990, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "local.h"
-
-/*
- * fpurge: like fflush, but without writing anything: leave the
- * given FILE's buffer empty.
- */
-int
-fpurge(FILE *fp)
-{
-	FLOCKFILE(fp);
-	if (!fp->_flags) {
-		FUNLOCKFILE(fp);
-		errno = EBADF;
-		return(EOF);
-	}
-
-	if (HASUB(fp))
-		FREEUB(fp);
-	WCIO_FREE(fp);
-	fp->_p = fp->_bf._base;
-	fp->_r = 0;
-	fp->_w = fp->_flags & (__SLBF|__SNBF) ? 0 : fp->_bf._size;
-	FUNLOCKFILE(fp);
-	return (0);
-}
-DEF_WEAK(fpurge);
diff --git a/libc/upstream-openbsd/lib/libc/string/memrchr.c b/libc/upstream-openbsd/lib/libc/string/memrchr.c
deleted file mode 100644
index e123bc1..0000000
--- a/libc/upstream-openbsd/lib/libc/string/memrchr.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*	$OpenBSD: memrchr.c,v 1.4 2019/01/25 00:19:25 millert Exp $	*/
-
-/*
- * Copyright (c) 2007 Todd C. Miller <millert@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <string.h>
-
-/*
- * Reverse memchr()
- * Find the last occurrence of 'c' in the buffer 's' of size 'n'.
- */
-void *
-memrchr(const void *s, int c, size_t n)
-{
-	const unsigned char *cp;
-
-	if (n != 0) {
-		cp = (unsigned char *)s + n;
-		do {
-			if (*(--cp) == (unsigned char)c)
-				return((void *)cp);
-		} while (--n != 0);
-	}
-	return(NULL);
-}
-DEF_WEAK(memrchr);
diff --git a/libc/upstream-openbsd/lib/libc/string/strlcat.c b/libc/upstream-openbsd/lib/libc/string/strlcat.c
deleted file mode 100644
index aa3db7ab..0000000
--- a/libc/upstream-openbsd/lib/libc/string/strlcat.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*	$OpenBSD: strlcat.c,v 1.19 2019/01/25 00:19:25 millert Exp $	*/
-
-/*
- * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <string.h>
-
-/*
- * Appends src to string dst of size dsize (unlike strncat, dsize is the
- * full size of dst, not space left).  At most dsize-1 characters
- * will be copied.  Always NUL terminates (unless dsize <= strlen(dst)).
- * Returns strlen(src) + MIN(dsize, strlen(initial dst)).
- * If retval >= dsize, truncation occurred.
- */
-size_t
-strlcat(char *dst, const char *src, size_t dsize)
-{
-	const char *odst = dst;
-	const char *osrc = src;
-	size_t n = dsize;
-	size_t dlen;
-
-	/* Find the end of dst and adjust bytes left but don't go past end. */
-	while (n-- != 0 && *dst != '\0')
-		dst++;
-	dlen = dst - odst;
-	n = dsize - dlen;
-
-	if (n-- == 0)
-		return(dlen + strlen(src));
-	while (*src != '\0') {
-		if (n != 0) {
-			*dst++ = *src;
-			n--;
-		}
-		src++;
-	}
-	*dst = '\0';
-
-	return(dlen + (src - osrc));	/* count does not include NUL */
-}
-DEF_WEAK(strlcat);
diff --git a/libc/upstream-openbsd/lib/libc/string/strlcpy.c b/libc/upstream-openbsd/lib/libc/string/strlcpy.c
deleted file mode 100644
index 7e3b9ae..0000000
--- a/libc/upstream-openbsd/lib/libc/string/strlcpy.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*	$OpenBSD: strlcpy.c,v 1.16 2019/01/25 00:19:25 millert Exp $	*/
-
-/*
- * Copyright (c) 1998, 2015 Todd C. Miller <millert@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <string.h>
-
-/*
- * Copy string src to buffer dst of size dsize.  At most dsize-1
- * chars will be copied.  Always NUL terminates (unless dsize == 0).
- * Returns strlen(src); if retval >= dsize, truncation occurred.
- */
-size_t
-strlcpy(char *dst, const char *src, size_t dsize)
-{
-	const char *osrc = src;
-	size_t nleft = dsize;
-
-	/* Copy as many bytes as will fit. */
-	if (nleft != 0) {
-		while (--nleft != 0) {
-			if ((*dst++ = *src++) == '\0')
-				break;
-		}
-	}
-
-	/* Not enough room in dst, add NUL and traverse rest of src. */
-	if (nleft == 0) {
-		if (dsize != 0)
-			*dst = '\0';		/* NUL-terminate dst */
-		while (*src++)
-			;
-	}
-
-	return(src - osrc - 1);	/* count does not include NUL */
-}
-DEF_WEAK(strlcpy);
diff --git a/libc/versioner-dependencies/arm/kernel_uapi_asm-arm b/libc/versioner-dependencies/arm/kernel_uapi_asm-arm
deleted file mode 120000
index 3c7584d..0000000
--- a/libc/versioner-dependencies/arm/kernel_uapi_asm-arm
+++ /dev/null
@@ -1 +0,0 @@
-../../kernel/uapi/asm-arm
\ No newline at end of file
diff --git a/libc/versioner-dependencies/arm64/kernel_uapi_asm-arm64 b/libc/versioner-dependencies/arm64/kernel_uapi_asm-arm64
deleted file mode 120000
index 7ee6fd2..0000000
--- a/libc/versioner-dependencies/arm64/kernel_uapi_asm-arm64
+++ /dev/null
@@ -1 +0,0 @@
-../../kernel/uapi/asm-arm64
\ No newline at end of file
diff --git a/libc/versioner-dependencies/common/clang-builtins b/libc/versioner-dependencies/common/clang-builtins
deleted file mode 120000
index 148dd2b..0000000
--- a/libc/versioner-dependencies/common/clang-builtins
+++ /dev/null
@@ -1 +0,0 @@
-../../../../prebuilts/clang-tools/linux-x86/clang-headers
\ No newline at end of file
diff --git a/libc/versioner-dependencies/common/kernel_android_uapi b/libc/versioner-dependencies/common/kernel_android_uapi
deleted file mode 120000
index fd78315..0000000
--- a/libc/versioner-dependencies/common/kernel_android_uapi
+++ /dev/null
@@ -1 +0,0 @@
-../../kernel/android/uapi/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/common/kernel_uapi b/libc/versioner-dependencies/common/kernel_uapi
deleted file mode 120000
index d5cb8ee..0000000
--- a/libc/versioner-dependencies/common/kernel_uapi
+++ /dev/null
@@ -1 +0,0 @@
-../../kernel/uapi/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/riscv64/kernel_uapi_asm-riscv64 b/libc/versioner-dependencies/riscv64/kernel_uapi_asm-riscv64
deleted file mode 120000
index 61353cb..0000000
--- a/libc/versioner-dependencies/riscv64/kernel_uapi_asm-riscv64
+++ /dev/null
@@ -1 +0,0 @@
-../../kernel/uapi/asm-riscv/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/x86/kernel_uapi_asm-x86 b/libc/versioner-dependencies/x86/kernel_uapi_asm-x86
deleted file mode 120000
index 1b7a73d..0000000
--- a/libc/versioner-dependencies/x86/kernel_uapi_asm-x86
+++ /dev/null
@@ -1 +0,0 @@
-../../kernel/uapi/asm-x86/
\ No newline at end of file
diff --git a/libc/versioner-dependencies/x86_64/kernel_uapi_asm-x86 b/libc/versioner-dependencies/x86_64/kernel_uapi_asm-x86
deleted file mode 120000
index 1b7a73d..0000000
--- a/libc/versioner-dependencies/x86_64/kernel_uapi_asm-x86
+++ /dev/null
@@ -1 +0,0 @@
-../../kernel/uapi/asm-x86/
\ No newline at end of file
diff --git a/libdl/Android.bp b/libdl/Android.bp
index 1bbd902..87db4b1 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -123,7 +123,6 @@
     },
 
     apex_available: [
-        "//apex_available:platform",
         "com.android.runtime",
     ],
 }
@@ -170,7 +169,6 @@
     },
 
     apex_available: [
-        "//apex_available:platform",
         "com.android.runtime",
     ],
 }
diff --git a/libdl/libdl_android.cpp b/libdl/libdl_android.cpp
index 47a164a..f0959eb 100644
--- a/libdl/libdl_android.cpp
+++ b/libdl/libdl_android.cpp
@@ -59,6 +59,9 @@
 __attribute__((__weak__, visibility("default")))
 struct android_namespace_t* __loader_android_get_exported_namespace(const char* name);
 
+__attribute__((__weak__, visibility("default"))) void __loader_android_set_16kb_appcompat_mode(
+    bool enable_app_compat);
+
 // Proxy calls to bionic loader
 __attribute__((__weak__))
 void android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
@@ -115,4 +118,8 @@
   return __loader_android_get_exported_namespace(name);
 }
 
+__attribute__((__weak__)) void android_set_16kb_appcompat_mode(bool enable_app_compat) {
+  __loader_android_set_16kb_appcompat_mode(enable_app_compat);
+}
+
 } // extern "C"
diff --git a/libdl/libdl_android.map.txt b/libdl/libdl_android.map.txt
index 7afcd9c..efbc841 100644
--- a/libdl/libdl_android.map.txt
+++ b/libdl/libdl_android.map.txt
@@ -24,6 +24,7 @@
     android_init_anonymous_namespace; # apex
     android_link_namespaces; # apex
     android_set_application_target_sdk_version; # apex
+    android_set_16kb_appcompat_mode; #apex
   local:
     *;
 };
diff --git a/libm/Android.bp b/libm/Android.bp
index 9fd79f8..ee86959 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -435,7 +435,6 @@
     },
 
     apex_available: [
-        "//apex_available:platform",
         "com.android.runtime",
     ],
 
diff --git a/libm/libm.map.txt b/libm/libm.map.txt
index f1732f8..b9a0db2 100644
--- a/libm/libm.map.txt
+++ b/libm/libm.map.txt
@@ -8,23 +8,23 @@
     acosf;
     acosh;
     acoshf;
-    acoshl; # introduced=21
-    acosl; # introduced=21
+    acoshl;
+    acosl;
     asin;
     asinf;
     asinh;
     asinhf;
-    asinhl; # introduced=21
-    asinl; # introduced=21
+    asinhl;
+    asinl;
     atan;
     atan2;
     atan2f;
-    atan2l; # introduced=21
+    atan2l;
     atanf;
     atanh;
     atanhf;
-    atanhl; # introduced=21
-    atanl; # introduced=21
+    atanhl;
+    atanl;
     cabs; # introduced=23
     cabsf; # introduced=23
     cabsl; # introduced-arm=21 introduced-arm64=23 introduced-x86=21 introduced-x86_64=23
@@ -45,7 +45,7 @@
     catanhf; # introduced=23
     cbrt;
     cbrtf;
-    cbrtl; # introduced=21
+    cbrtl;
     ccos; # introduced=23
     ccosf; # introduced=23
     ccosh; # introduced=23
@@ -68,8 +68,8 @@
     cosf;
     cosh;
     coshf;
-    coshl; # introduced=21
-    cosl; # introduced=21
+    coshl;
+    cosl;
     cproj; # introduced=23
     cprojf; # introduced=23
     cprojl; # introduced-arm=21 introduced-arm64=23 introduced-x86=21 introduced-x86_64=23
@@ -92,38 +92,38 @@
     erf;
     erfc;
     erfcf;
-    erfcl; # introduced=21
+    erfcl;
     erff;
-    erfl; # introduced=21
+    erfl;
     exp;
     exp2;
     exp2f;
-    exp2l; # introduced=21
+    exp2l;
     expf;
-    expl; # introduced=21
+    expl;
     expm1;
     expm1f;
-    expm1l; # introduced=21
+    expm1l;
     fabs;
     fabsf;
     fabsl;
     fdim;
     fdimf;
     fdiml;
-    feclearexcept; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
-    fedisableexcept; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
-    feenableexcept; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
-    fegetenv; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
-    fegetexcept; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
-    fegetexceptflag; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
-    fegetround; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
-    feholdexcept; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
-    feraiseexcept; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
-    fesetenv; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
-    fesetexceptflag; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
-    fesetround; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
-    fetestexcept; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
-    feupdateenv; # introduced-arm=21 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
+    feclearexcept;
+    fedisableexcept;
+    feenableexcept;
+    fegetenv;
+    fegetexcept;
+    fegetexceptflag;
+    fegetround;
+    feholdexcept;
+    feraiseexcept;
+    fesetenv;
+    fesetexceptflag;
+    fesetround;
+    fetestexcept;
+    feupdateenv;
     finite;
     finitef;
     floor;
@@ -131,7 +131,7 @@
     floorl;
     fma;
     fmaf;
-    fmal; # introduced=21
+    fmal;
     fmax;
     fmaxf;
     fmaxl;
@@ -140,17 +140,17 @@
     fminl;
     fmod;
     fmodf;
-    fmodl; # introduced=21
+    fmodl;
     frexp;
     frexpf;
-    frexpl; # introduced=21
+    frexpl;
     gamma;
     gamma_r;
     gammaf;
     gammaf_r;
     hypot;
     hypotf;
-    hypotl; # introduced=21
+    hypotl;
     ilogb;
     ilogbf;
     ilogbl;
@@ -166,77 +166,77 @@
     lgamma_r;
     lgammaf;
     lgammaf_r;
-    lgammal; # introduced=21
+    lgammal;
     lgammal_r; # introduced=23
     llrint;
     llrintf;
-    llrintl; # introduced=21
+    llrintl;
     llround;
     llroundf;
     llroundl;
     log;
     log10;
     log10f;
-    log10l; # introduced=21
+    log10l;
     log1p;
     log1pf;
-    log1pl; # introduced=21
-    log2; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
-    log2f; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
-    log2l; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
+    log1pl;
+    log2;
+    log2f;
+    log2l;
     logb;
     logbf;
-    logbl; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
+    logbl;
     logf;
-    logl; # introduced=21
+    logl;
     lrint;
     lrintf;
-    lrintl; # introduced=21
+    lrintl;
     lround;
     lroundf;
     lroundl;
     modf;
     modff;
-    modfl; # introduced=21
-    nan; # introduced-arm=13 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
-    nanf; # introduced-arm=13 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
-    nanl; # introduced-arm=13 introduced-arm64=21 introduced-x86=13 introduced-x86_64=21
+    modfl;
+    nan;
+    nanf;
+    nanl;
     nearbyint;
     nearbyintf;
-    nearbyintl; # introduced=21
+    nearbyintl;
     nextafter;
     nextafterf;
-    nextafterl; # introduced=21
-    nexttoward; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
+    nextafterl;
+    nexttoward;
     nexttowardf;
-    nexttowardl; # introduced-arm=18 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
+    nexttowardl;
     pow;
     powf;
-    powl; # introduced=21
+    powl;
     remainder;
     remainderf;
-    remainderl; # introduced=21
+    remainderl;
     remquo;
     remquof;
-    remquol; # introduced=21
+    remquol;
     rint;
     rintf;
-    rintl; # introduced=21
+    rintl;
     round;
     roundf;
     roundl;
     scalb;
     scalbf;
-    scalbln; # introduced-arm=9 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
-    scalblnf; # introduced-arm=9 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
-    scalblnl; # introduced-arm=9 introduced-arm64=21 introduced-x86=18 introduced-x86_64=21
+    scalbln;
+    scalblnf;
+    scalblnl;
     scalbn;
     scalbnf;
     scalbnl;
     signgam; # var
     significand;
     significandf;
-    significandl; # introduced=21
+    significandl;
     sin;
     sincos;
     sincosf;
@@ -244,20 +244,20 @@
     sinf;
     sinh;
     sinhf;
-    sinhl; # introduced=21
-    sinl; # introduced=21
+    sinhl;
+    sinl;
     sqrt;
     sqrtf;
-    sqrtl; # introduced=21
+    sqrtl;
     tan;
     tanf;
     tanh;
     tanhf;
-    tanhl; # introduced=21
-    tanl; # introduced=21
+    tanhl;
+    tanl;
     tgamma;
-    tgammaf; # introduced-arm=13 introduced-arm64=21 introduced-x86=9 introduced-x86_64=21
-    tgammal; # introduced=21
+    tgammaf;
+    tgammal;
     trunc;
     truncf;
     truncl;
diff --git a/libm/upstream-freebsd/lib/msun/src/e_acosf.c b/libm/upstream-freebsd/lib/msun/src/e_acosf.c
index 42ba126..ede552e 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_acosf.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_acosf.c
@@ -22,11 +22,17 @@
 pio2_hi =  1.5707962513e+00; /* 0x3fc90fda */
 static volatile float
 pio2_lo =  7.5497894159e-08; /* 0x33a22168 */
+
+/*
+ * The coefficients for the rational approximation were generated over
+ *  0x1p-12f <= x <= 0.5f.  The maximum error satisfies log2(e) < -30.084.
+ */
 static const float
-pS0 =  1.6666586697e-01,
-pS1 = -4.2743422091e-02,
-pS2 = -8.6563630030e-03,
-qS1 = -7.0662963390e-01;
+pS0 =  1.66666672e-01f, /* 0x3e2aaaab */
+pS1 = -1.19510300e-01f, /* 0xbdf4c1d1 */
+pS2 =  5.47002675e-03f, /* 0x3bb33de9 */
+qS1 = -1.16706085e+00f, /* 0xbf956240 */
+qS2 =  2.90115148e-01f; /* 0x3e9489f9 */
 
 float
 acosf(float x)
@@ -46,13 +52,13 @@
 	    if(ix<=0x32800000) return pio2_hi+pio2_lo;/*if|x|<2**-26*/
 	    z = x*x;
 	    p = z*(pS0+z*(pS1+z*pS2));
-	    q = one+z*qS1;
+	    q = one+z*(qS1+z*qS2);
 	    r = p/q;
 	    return pio2_hi - (x - (pio2_lo-x*r));
 	} else  if (hx<0) {		/* x < -0.5 */
 	    z = (one+x)*(float)0.5;
 	    p = z*(pS0+z*(pS1+z*pS2));
-	    q = one+z*qS1;
+	    q = one+z*(qS1+z*qS2);
 	    s = sqrtf(z);
 	    r = p/q;
 	    w = r*s-pio2_lo;
@@ -66,7 +72,7 @@
 	    SET_FLOAT_WORD(df,idf&0xfffff000);
 	    c  = (z-df*df)/(s+df);
 	    p = z*(pS0+z*(pS1+z*pS2));
-	    q = one+z*qS1;
+	    q = one+z*(qS1+z*qS2);
 	    r = p/q;
 	    w = r*s+c;
 	    return (float)2.0*(df+w);
diff --git a/libm/upstream-freebsd/lib/msun/src/e_asinf.c b/libm/upstream-freebsd/lib/msun/src/e_asinf.c
index a2ee1a1..8d1aca2 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_asinf.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_asinf.c
@@ -18,12 +18,18 @@
 
 static const float
 one =  1.0000000000e+00, /* 0x3F800000 */
-huge =  1.000e+30,
-	/* coefficient for R(x^2) */
-pS0 =  1.6666586697e-01,
-pS1 = -4.2743422091e-02,
-pS2 = -8.6563630030e-03,
-qS1 = -7.0662963390e-01;
+huge =  1.000e+30;
+
+/*
+ * The coefficients for the rational approximation were generated over
+ *  0x1p-12f <= x <= 0.5f.  The maximum error satisfies log2(e) < -30.084.
+ */
+static const float
+pS0 =  1.66666672e-01f, /* 0x3e2aaaab */
+pS1 = -1.19510300e-01f, /* 0xbdf4c1d1 */
+pS2 =  5.47002675e-03f, /* 0x3bb33de9 */
+qS1 = -1.16706085e+00f, /* 0xbf956240 */
+qS2 =  2.90115148e-01f; /* 0x3e9489f9 */
 
 static const double
 pio2 =  1.570796326794896558e+00;
@@ -46,7 +52,7 @@
 	    }
 	    t = x*x;
 	    p = t*(pS0+t*(pS1+t*pS2));
-	    q = one+t*qS1;
+	    q = one+t*(qS1+t*qS2);
 	    w = p/q;
 	    return x+x*w;
 	}
@@ -54,7 +60,7 @@
 	w = one-fabsf(x);
 	t = w*(float)0.5;
 	p = t*(pS0+t*(pS1+t*pS2));
-	q = one+t*qS1;
+	q = one+t*(qS1+t*qS2);
 	s = sqrt(t);
 	w = p/q;
 	t = pio2-2.0*(s+s*w);
diff --git a/libm/upstream-freebsd/lib/msun/src/math_private.h b/libm/upstream-freebsd/lib/msun/src/math_private.h
index f3f7985..1595f90 100644
--- a/libm/upstream-freebsd/lib/msun/src/math_private.h
+++ b/libm/upstream-freebsd/lib/msun/src/math_private.h
@@ -405,7 +405,7 @@
  * any extra precision into the type of 'a' -- 'a' should have type float_t,
  * double_t or long double.  b's type should be no larger than 'a's type.
  * Callers should use these types with scopes as large as possible, to
- * reduce their own extra-precision and efficiciency problems.  In
+ * reduce their own extra-precision and efficiency problems.  In
  * particular, they shouldn't convert back and forth just to call here.
  */
 #ifdef DEBUG
diff --git a/libm/upstream-freebsd/lib/msun/src/s_fma.c b/libm/upstream-freebsd/lib/msun/src/s_fma.c
index 6c889a6..23a8449 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_fma.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_fma.c
@@ -260,14 +260,14 @@
 
 	spread = ex + ey;
 
-	if (r.hi == 0.0) {
+	if (r.hi == 0.0 && xy.lo == 0) {
 		/*
 		 * When the addends cancel to 0, ensure that the result has
 		 * the correct sign.
 		 */
 		fesetround(oround);
 		volatile double vzs = zs; /* XXX gcc CSE bug workaround */
-		return (xy.hi + vzs + ldexp(xy.lo, spread));
+		return (xy.hi + vzs);
 	}
 
 	if (oround != FE_TONEAREST) {
diff --git a/libm/upstream-freebsd/lib/msun/src/s_fmal.c b/libm/upstream-freebsd/lib/msun/src/s_fmal.c
index 80c835d..2fca206 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_fmal.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_fmal.c
@@ -241,14 +241,14 @@
 
 	spread = ex + ey;
 
-	if (r.hi == 0.0) {
+	if (r.hi == 0.0 && xy.lo == 0) {
 		/*
 		 * When the addends cancel to 0, ensure that the result has
 		 * the correct sign.
 		 */
 		fesetround(oround);
 		volatile long double vzs = zs; /* XXX gcc CSE bug workaround */
-		return (xy.hi + vzs + ldexpl(xy.lo, spread));
+		return (xy.hi + vzs);
 	}
 
 	if (oround != FE_TONEAREST) {
diff --git a/linker/Android.bp b/linker/Android.bp
index 563cf3d..4863b92 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -108,6 +108,12 @@
 
     // We need to access Bionic private headers in the linker.
     include_dirs: ["bionic/libc"],
+
+    sanitize: {
+        // Supporting memtag_globals in the linker would be tricky,
+        // because it relocates itself very early.
+        memtag_globals: false,
+    },
 }
 
 // ========================================================
@@ -184,6 +190,7 @@
         "linker_mapped_file_fragment.cpp",
         "linker_note_gnu_property.cpp",
         "linker_phdr.cpp",
+        "linker_phdr_16kib_compat.cpp",
         "linker_relocate.cpp",
         "linker_sdk_versions.cpp",
         "linker_soinfo.cpp",
@@ -493,6 +500,7 @@
         "linker_mapped_file_fragment.cpp",
         "linker_sdk_versions.cpp",
         "linker_dlwarning.cpp",
+        "linker_phdr_16kib_compat.cpp"
     ],
 
     static_libs: [
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index fee19f4..f811d6d 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -89,6 +89,7 @@
                       const void* caller_addr) __LINKER_PUBLIC__;
 void __loader_add_thread_local_dtor(void* dso_handle) __LINKER_PUBLIC__;
 void __loader_remove_thread_local_dtor(void* dso_handle) __LINKER_PUBLIC__;
+void __loader_android_set_16kb_appcompat_mode(bool enable_app_compat) __LINKER_PUBLIC__;
 libc_shared_globals* __loader_shared_globals() __LINKER_PUBLIC__;
 #if defined(__arm__)
 _Unwind_Ptr __loader_dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) __LINKER_PUBLIC__;
@@ -301,6 +302,11 @@
   decrement_dso_handle_reference_counter(dso_handle);
 }
 
+void __loader_android_set_16kb_appcompat_mode(bool enable_app_compat) {
+  ScopedPthreadMutexLocker locker(&g_dl_mutex);
+  set_16kb_appcompat_mode(enable_app_compat);
+}
+
 libc_shared_globals* __loader_shared_globals() {
   return __libc_shared_globals();
 }
@@ -331,6 +337,7 @@
     __libdl_info->gnu_bloom_filter_ = linker_si.gnu_bloom_filter_;
     __libdl_info->gnu_bucket_ = linker_si.gnu_bucket_;
     __libdl_info->gnu_chain_ = linker_si.gnu_chain_;
+    __libdl_info->memtag_dynamic_entries_ = linker_si.memtag_dynamic_entries_;
 
     __libdl_info->ref_count_ = 1;
     __libdl_info->strtab_size_ = linker_si.strtab_size_;
diff --git a/linker/ld_android.cpp b/linker/ld_android.cpp
index 1c03106..c938a16 100644
--- a/linker/ld_android.cpp
+++ b/linker/ld_android.cpp
@@ -55,6 +55,7 @@
 __strong_alias(__loader_add_thread_local_dtor, __internal_linker_error);
 __strong_alias(__loader_remove_thread_local_dtor, __internal_linker_error);
 __strong_alias(__loader_shared_globals, __internal_linker_error);
+__strong_alias(__loader_android_set_16kb_appcompat_mode, __internal_linker_error);
 #if defined(__arm__)
 __strong_alias(__loader_dl_unwind_find_exidx, __internal_linker_error);
 #endif
diff --git a/linker/linker.arm.map b/linker/linker.arm.map
index b805cd6..edfa249 100644
--- a/linker/linker.arm.map
+++ b/linker/linker.arm.map
@@ -25,6 +25,7 @@
     __loader_shared_globals;
     rtld_db_dlactivity;
     __loader_android_handle_signal;
+    __loader_android_set_16kb_appcompat_mode;
   local:
     *;
 };
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 4365ea5..8f78915 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -51,6 +51,7 @@
 #include <android-base/scopeguard.h>
 #include <async_safe/log.h>
 #include <bionic/pthread_internal.h>
+#include <platform/bionic/mte.h>
 
 // Private C library headers.
 
@@ -316,7 +317,7 @@
     async_safe_fatal("library name \"%s\" too long", name);
   }
 
-  TRACE("name %s: allocating soinfo for ns=%p", name, ns);
+  LD_DEBUG(any, "name %s: allocating soinfo for ns=%p", name, ns);
 
   soinfo* si = new (g_soinfo_allocator.alloc()) soinfo(ns, name, file_stat,
                                                        file_offset, rtld_flags);
@@ -326,7 +327,7 @@
   si->generate_handle();
   ns->add_soinfo(si);
 
-  TRACE("name %s: allocated soinfo @ %p", name, si);
+  LD_DEBUG(any, "name %s: allocated soinfo @ %p", name, si);
   return si;
 }
 
@@ -349,7 +350,7 @@
     munmap(reinterpret_cast<void*>(si->get_gap_start()), si->get_gap_size());
   }
 
-  TRACE("name %s: freeing soinfo @ %p", si->get_realpath(), si);
+  LD_DEBUG(any, "name %s: freeing soinfo @ %p", si->get_realpath(), si);
 
   if (!solist_remove_soinfo(si)) {
     async_safe_fatal("soinfo=%p is not in soinfo_list (double unload?)", si);
@@ -387,7 +388,7 @@
   auto length = readlink(proc_self_fd, buf, sizeof(buf));
   if (length == -1) {
     if (!is_first_stage_init()) {
-      PRINT("readlink(\"%s\" [fd=%d]) failed: %m", proc_self_fd, fd);
+      DL_WARN("readlink(\"%s\" [fd=%d]) failed: %m", proc_self_fd, fd);
     }
     return false;
   }
@@ -640,6 +641,11 @@
     si_->set_gap_start(elf_reader.gap_start());
     si_->set_gap_size(elf_reader.gap_size());
     si_->set_should_pad_segments(elf_reader.should_pad_segments());
+    si_->set_should_use_16kib_app_compat(elf_reader.should_use_16kib_app_compat());
+    if (si_->should_use_16kib_app_compat()) {
+      si_->set_compat_relro_start(elf_reader.compat_relro_start());
+      si_->set_compat_relro_size(elf_reader.compat_relro_size());
+    }
 
     return true;
   }
@@ -818,8 +824,8 @@
   }
 
   if (s != nullptr) {
-    TRACE_TYPE(LOOKUP, "%s s->st_value = %p, found->base = %p",
-               name, reinterpret_cast<void*>(s->st_value), reinterpret_cast<void*>((*found)->base));
+    LD_DEBUG(lookup, "%s s->st_value = %p, found->base = %p",
+             name, reinterpret_cast<void*>(s->st_value), reinterpret_cast<void*>((*found)->base));
   }
 
   return s;
@@ -923,7 +929,7 @@
   }
 
   const char* const path = normalized_path.c_str();
-  TRACE("Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path);
+  LD_DEBUG(any, "Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path);
 
   // Treat an '!/' separator inside a path as the separator between the name
   // of the zip file on disk and the subdirectory to search within it.
@@ -936,7 +942,7 @@
 
   char buf[512];
   if (strlcpy(buf, path, sizeof(buf)) >= sizeof(buf)) {
-    PRINT("Warning: ignoring very long library path: %s", path);
+    DL_WARN("ignoring very long library path: %s", path);
     return -1;
   }
 
@@ -976,8 +982,8 @@
     *realpath += separator;
   } else {
     if (!is_first_stage_init()) {
-      PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.",
-            normalized_path.c_str());
+      DL_WARN("unable to get realpath for the library \"%s\". Will use given path.",
+              normalized_path.c_str());
     }
     *realpath = normalized_path;
   }
@@ -988,7 +994,7 @@
 static bool format_path(char* buf, size_t buf_size, const char* path, const char* name) {
   int n = async_safe_format_buffer(buf, buf_size, "%s/%s", path, name);
   if (n < 0 || n >= static_cast<int>(buf_size)) {
-    PRINT("Warning: ignoring very long library path: %s/%s", path, name);
+    DL_WARN("ignoring very long library path: %s/%s", path, name);
     return false;
   }
 
@@ -1009,8 +1015,7 @@
       *file_offset = 0;
       if (!realpath_fd(fd, realpath)) {
         if (!is_first_stage_init()) {
-          PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.",
-                path);
+          DL_WARN("unable to get realpath for the library \"%s\". Will use given path.", path);
         }
         *realpath = path;
       }
@@ -1043,7 +1048,7 @@
                         ZipArchiveCache* zip_archive_cache,
                         const char* name, soinfo *needed_by,
                         off64_t* file_offset, std::string* realpath) {
-  TRACE("[ opening %s from namespace %s ]", name, ns->get_name());
+  LD_DEBUG(any, "[ opening %s from namespace %s ]", name, ns->get_name());
 
   // If the name contains a slash, we should attempt to open it directly and not search the paths.
   if (strchr(name, '/') != nullptr) {
@@ -1249,15 +1254,15 @@
 
       // do not print this if a library is in the list of shared libraries for linked namespaces
       if (!maybe_accessible_via_namespace_links(ns, name)) {
-        PRINT("library \"%s\" (\"%s\") needed or dlopened by \"%s\" is not accessible for the"
-              " namespace: [name=\"%s\", ld_library_paths=\"%s\", default_library_paths=\"%s\","
-              " permitted_paths=\"%s\"]",
-              name, realpath.c_str(),
-              needed_or_dlopened_by,
-              ns->get_name(),
-              android::base::Join(ns->get_ld_library_paths(), ':').c_str(),
-              android::base::Join(ns->get_default_library_paths(), ':').c_str(),
-              android::base::Join(ns->get_permitted_paths(), ':').c_str());
+        DL_WARN("library \"%s\" (\"%s\") needed or dlopened by \"%s\" is not accessible for the"
+                " namespace: [name=\"%s\", ld_library_paths=\"%s\", default_library_paths=\"%s\","
+                " permitted_paths=\"%s\"]",
+                name, realpath.c_str(),
+                needed_or_dlopened_by,
+                ns->get_name(),
+                android::base::Join(ns->get_ld_library_paths(), ':').c_str(),
+                android::base::Join(ns->get_default_library_paths(), ':').c_str(),
+                android::base::Join(ns->get_permitted_paths(), ':').c_str());
       }
       return false;
     }
@@ -1330,10 +1335,9 @@
     std::string realpath;
     if (!realpath_fd(extinfo->library_fd, &realpath)) {
       if (!is_first_stage_init()) {
-        PRINT(
-            "warning: unable to get realpath for the library \"%s\" by extinfo->library_fd. "
-            "Will use given name.",
-            name);
+        DL_WARN("unable to get realpath for the library \"%s\" by extinfo->library_fd. "
+                "Will use given name.",
+                name);
       }
       realpath = name;
     }
@@ -1474,8 +1478,8 @@
 
   // Library might still be loaded, the accurate detection
   // of this fact is done by load_library.
-  TRACE("[ \"%s\" find_loaded_library_by_soname failed (*candidate=%s@%p). Trying harder... ]",
-        task->get_name(), candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
+  LD_DEBUG(any, "[ \"%s\" find_loaded_library_by_soname failed (*candidate=%s@%p). Trying harder... ]",
+           task->get_name(), candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
 
   if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags,
                    true /* search_linked_namespaces */)) {
@@ -1694,16 +1698,24 @@
     }
   }
 
+  // The WebView loader uses RELRO sharing in order to promote page sharing of the large RELRO
+  // segment, as it's full of C++ vtables. Because MTE globals, by default, applies random tags to
+  // each global variable, the RELRO segment is polluted and unique for each process. In order to
+  // allow sharing, but still provide some protection, we use deterministic global tagging schemes
+  // for DSOs that are loaded through android_dlopen_ext, such as those loaded by WebView.
+  bool dlext_use_relro =
+      extinfo && extinfo->flags & (ANDROID_DLEXT_WRITE_RELRO | ANDROID_DLEXT_USE_RELRO);
+
   // Step 3: pre-link all DT_NEEDED libraries in breadth first order.
   bool any_memtag_stack = false;
   for (auto&& task : load_tasks) {
     soinfo* si = task->get_soinfo();
-    if (!si->is_linked() && !si->prelink_image()) {
+    if (!si->is_linked() && !si->prelink_image(dlext_use_relro)) {
       return false;
     }
     // si->memtag_stack() needs to be called after si->prelink_image() which populates
     // the dynamic section.
-    if (si->has_min_version(7) && si->memtag_stack()) {
+    if (si->memtag_stack()) {
       any_memtag_stack = true;
       LD_LOG(kLogDlopen,
              "... load_library requesting stack MTE for: realpath=\"%s\", soname=\"%s\"",
@@ -1717,7 +1729,7 @@
     } else {
       // find_library is used by the initial linking step, so we communicate that we
       // want memtag_stack enabled to __libc_init_mte.
-      __libc_shared_globals()->initial_memtag_stack = true;
+      __libc_shared_globals()->initial_memtag_stack_abi = true;
     }
   }
 
@@ -1906,8 +1918,8 @@
     if (si->has_min_version(0)) {
       soinfo* child = nullptr;
       while ((child = si->get_children().pop_front()) != nullptr) {
-        TRACE("%s@%p needs to unload %s@%p", si->get_realpath(), si,
-            child->get_realpath(), child);
+        LD_DEBUG(any, "%s@%p needs to unload %s@%p", si->get_realpath(), si,
+                 child->get_realpath(), child);
 
         child->get_parents().remove(si);
 
@@ -2197,10 +2209,10 @@
       if (file_exists(translated_name_holder.c_str())) {
         soinfo* si = nullptr;
         if (find_loaded_library_by_realpath(ns, original_path, true, &si)) {
-          PRINT("linker_asan dlopen NOT translating \"%s\" -> \"%s\": library already loaded", name,
-                translated_name_holder.c_str());
+          DL_WARN("linker_asan dlopen NOT translating \"%s\" -> \"%s\": library already loaded", name,
+                  translated_name_holder.c_str());
         } else {
-          PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
+          DL_WARN("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
           translated_name = translated_name_holder.c_str();
         }
       }
@@ -2217,10 +2229,10 @@
       if (!translated_name_holder.empty() && file_exists(translated_name_holder.c_str())) {
         soinfo* si = nullptr;
         if (find_loaded_library_by_realpath(ns, original_path, true, &si)) {
-          PRINT("linker_hwasan dlopen NOT translating \"%s\" -> \"%s\": library already loaded", name,
-                translated_name_holder.c_str());
+          DL_WARN("linker_hwasan dlopen NOT translating \"%s\" -> \"%s\": library already loaded",
+                  name, translated_name_holder.c_str());
         } else {
-          PRINT("linker_hwasan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
+          DL_WARN("linker_hwasan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
           translated_name = translated_name_holder.c_str();
         }
       }
@@ -2358,7 +2370,7 @@
         void* tls_block = get_tls_block_for_this_thread(tls_module, /*should_alloc=*/true);
         *symbol = static_cast<char*>(tls_block) + sym->st_value;
       } else {
-        *symbol = reinterpret_cast<void*>(found->resolve_symbol_address(sym));
+        *symbol = get_tagged_address(reinterpret_cast<void*>(found->resolve_symbol_address(sym)));
       }
       failure_guard.Disable();
       LD_LOG(kLogDlsym,
@@ -2589,8 +2601,8 @@
   if (g_is_ldd) return 0;
 
   ElfW(Addr) ifunc_addr = __bionic_call_ifunc_resolver(resolver_addr);
-  TRACE_TYPE(RELO, "Called ifunc_resolver@%p. The result is %p",
-      reinterpret_cast<void *>(resolver_addr), reinterpret_cast<void*>(ifunc_addr));
+  LD_DEBUG(calls, "ifunc_resolver@%p returned %p",
+           reinterpret_cast<void *>(resolver_addr), reinterpret_cast<void*>(ifunc_addr));
 
   return ifunc_addr;
 }
@@ -2788,15 +2800,25 @@
   return true;
 }
 
-static void apply_relr_reloc(ElfW(Addr) offset, ElfW(Addr) load_bias) {
-  ElfW(Addr) address = offset + load_bias;
-  *reinterpret_cast<ElfW(Addr)*>(address) += load_bias;
+static void apply_relr_reloc(ElfW(Addr) offset, ElfW(Addr) load_bias, bool has_memtag_globals) {
+  ElfW(Addr) destination = offset + load_bias;
+  if (!has_memtag_globals) {
+    *reinterpret_cast<ElfW(Addr)*>(destination) += load_bias;
+    return;
+  }
+
+  ElfW(Addr)* tagged_destination =
+      reinterpret_cast<ElfW(Addr)*>(get_tagged_address(reinterpret_cast<void*>(destination)));
+  ElfW(Addr) tagged_value = reinterpret_cast<ElfW(Addr)>(
+      get_tagged_address(reinterpret_cast<void*>(*tagged_destination + load_bias)));
+  *tagged_destination = tagged_value;
 }
 
 // Process relocations in SHT_RELR section (experimental).
 // Details of the encoding are described in this post:
 //   https://groups.google.com/d/msg/generic-abi/bX460iggiKg/Pi9aSwwABgAJ
-bool relocate_relr(const ElfW(Relr)* begin, const ElfW(Relr)* end, ElfW(Addr) load_bias) {
+bool relocate_relr(const ElfW(Relr) * begin, const ElfW(Relr) * end, ElfW(Addr) load_bias,
+                   bool has_memtag_globals) {
   constexpr size_t wordsize = sizeof(ElfW(Addr));
 
   ElfW(Addr) base = 0;
@@ -2807,7 +2829,7 @@
     if ((entry&1) == 0) {
       // Even entry: encodes the offset for next relocation.
       offset = static_cast<ElfW(Addr)>(entry);
-      apply_relr_reloc(offset, load_bias);
+      apply_relr_reloc(offset, load_bias, has_memtag_globals);
       // Set base offset for subsequent bitmap entries.
       base = offset + wordsize;
       continue;
@@ -2818,7 +2840,7 @@
     while (entry != 0) {
       entry >>= 1;
       if ((entry&1) != 0) {
-        apply_relr_reloc(offset, load_bias);
+        apply_relr_reloc(offset, load_bias, has_memtag_globals);
       }
       offset += wordsize;
     }
@@ -2833,7 +2855,7 @@
 // An empty list of soinfos
 static soinfo_list_t g_empty_list;
 
-bool soinfo::prelink_image() {
+bool soinfo::prelink_image(bool dlext_use_relro) {
   if (flags_ & FLAG_PRELINKED) return true;
   /* Extract dynamic section */
   ElfW(Word) dynamic_flags = 0;
@@ -2842,8 +2864,8 @@
   /* We can't log anything until the linker is relocated */
   bool relocating_linker = (flags_ & FLAG_LINKER) != 0;
   if (!relocating_linker) {
-    INFO("[ Linking \"%s\" ]", get_realpath());
-    DEBUG("si->base = %p si->flags = 0x%08x", reinterpret_cast<void*>(base), flags_);
+    LD_DEBUG(any, "[ Linking \"%s\" ]", get_realpath());
+    LD_DEBUG(any, "si->base = %p si->flags = 0x%08x", reinterpret_cast<void*>(base), flags_);
   }
 
   if (dynamic == nullptr) {
@@ -2853,7 +2875,7 @@
     return false;
   } else {
     if (!relocating_linker) {
-      DEBUG("dynamic = %p", dynamic);
+      LD_DEBUG(dynamic, "dynamic section @%p", dynamic);
     }
   }
 
@@ -2883,8 +2905,8 @@
   // source: http://www.sco.com/developers/gabi/1998-04-29/ch5.dynamic.html
   uint32_t needed_count = 0;
   for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
-    DEBUG("d = %p, d[0](tag) = %p d[1](val) = %p",
-          d, reinterpret_cast<void*>(d->d_tag), reinterpret_cast<void*>(d->d_un.d_val));
+    LD_DEBUG(dynamic, "dynamic entry @%p: d_tag=%p, d_val=%p",
+             d, reinterpret_cast<void*>(d->d_tag), reinterpret_cast<void*>(d->d_un.d_val));
     switch (d->d_tag) {
       case DT_SONAME:
         // this is parsed after we have strtab initialized (see below).
@@ -3098,17 +3120,17 @@
 
       case DT_INIT:
         init_func_ = reinterpret_cast<linker_ctor_function_t>(load_bias + d->d_un.d_ptr);
-        DEBUG("%s constructors (DT_INIT) found at %p", get_realpath(), init_func_);
+        LD_DEBUG(dynamic, "%s constructors (DT_INIT) found at %p", get_realpath(), init_func_);
         break;
 
       case DT_FINI:
         fini_func_ = reinterpret_cast<linker_dtor_function_t>(load_bias + d->d_un.d_ptr);
-        DEBUG("%s destructors (DT_FINI) found at %p", get_realpath(), fini_func_);
+        LD_DEBUG(dynamic, "%s destructors (DT_FINI) found at %p", get_realpath(), fini_func_);
         break;
 
       case DT_INIT_ARRAY:
         init_array_ = reinterpret_cast<linker_ctor_function_t*>(load_bias + d->d_un.d_ptr);
-        DEBUG("%s constructors (DT_INIT_ARRAY) found at %p", get_realpath(), init_array_);
+        LD_DEBUG(dynamic, "%s constructors (DT_INIT_ARRAY) found at %p", get_realpath(), init_array_);
         break;
 
       case DT_INIT_ARRAYSZ:
@@ -3117,7 +3139,7 @@
 
       case DT_FINI_ARRAY:
         fini_array_ = reinterpret_cast<linker_dtor_function_t*>(load_bias + d->d_un.d_ptr);
-        DEBUG("%s destructors (DT_FINI_ARRAY) found at %p", get_realpath(), fini_array_);
+        LD_DEBUG(dynamic, "%s destructors (DT_FINI_ARRAY) found at %p", get_realpath(), fini_array_);
         break;
 
       case DT_FINI_ARRAYSZ:
@@ -3126,7 +3148,7 @@
 
       case DT_PREINIT_ARRAY:
         preinit_array_ = reinterpret_cast<linker_ctor_function_t*>(load_bias + d->d_un.d_ptr);
-        DEBUG("%s constructors (DT_PREINIT_ARRAY) found at %p", get_realpath(), preinit_array_);
+        LD_DEBUG(dynamic, "%s constructors (DT_PREINIT_ARRAY) found at %p", get_realpath(), preinit_array_);
         break;
 
       case DT_PREINIT_ARRAYSZ:
@@ -3266,8 +3288,8 @@
     }
   }
 
-  DEBUG("si->base = %p, si->strtab = %p, si->symtab = %p",
-        reinterpret_cast<void*>(base), strtab_, symtab_);
+  LD_DEBUG(dynamic, "si->base = %p, si->strtab = %p, si->symtab = %p",
+           reinterpret_cast<void*>(base), strtab_, symtab_);
 
   // Validity checks.
   if (relocating_linker && needed_count != 0) {
@@ -3322,6 +3344,18 @@
   // it each time we look up a symbol with a version.
   if (!validate_verdef_section(this)) return false;
 
+  // MTE globals requires remapping data segments with PROT_MTE as anonymous mappings, because file
+  // based mappings may not be backed by tag-capable memory (see "MAP_ANONYMOUS" on
+  // https://www.kernel.org/doc/html/latest/arch/arm64/memory-tagging-extension.html). This is only
+  // done if the binary has MTE globals (evidenced by the dynamic table entries), as it destroys
+  // page sharing. It's also only done on devices that support MTE, because the act of remapping
+  // pages is unnecessary on non-MTE devices (where we might still run MTE-globals enabled code).
+  if (should_tag_memtag_globals() &&
+      remap_memtag_globals_segments(phdr, phnum, base) == 0) {
+    tag_globals(dlext_use_relro);
+    protect_memtag_globals_ro_segments(phdr, phnum, base);
+  }
+
   flags_ |= FLAG_PRELINKED;
   return true;
 }
@@ -3363,7 +3397,8 @@
                               "\"%s\" has text relocations",
                               get_realpath());
     add_dlwarning(get_realpath(), "text relocations");
-    if (phdr_table_unprotect_segments(phdr, phnum, load_bias, should_pad_segments_) < 0) {
+    if (phdr_table_unprotect_segments(phdr, phnum, load_bias, should_pad_segments_,
+                                      should_use_16kib_app_compat_) < 0) {
       DL_ERR("can't unprotect loadable segments for \"%s\": %m", get_realpath());
       return false;
     }
@@ -3374,12 +3409,13 @@
     return false;
   }
 
-  DEBUG("[ finished linking %s ]", get_realpath());
+  LD_DEBUG(any, "[ finished linking %s ]", get_realpath());
 
 #if !defined(__LP64__)
   if (has_text_relocations) {
     // All relocations are done, we can protect our segments back to read-only.
-    if (phdr_table_protect_segments(phdr, phnum, load_bias, should_pad_segments_) < 0) {
+    if (phdr_table_protect_segments(phdr, phnum, load_bias, should_pad_segments_,
+                                    should_use_16kib_app_compat_) < 0) {
       DL_ERR("can't protect segments for \"%s\": %m", get_realpath());
       return false;
     }
@@ -3392,6 +3428,13 @@
     return false;
   }
 
+  if (should_tag_memtag_globals()) {
+    std::list<std::string>* vma_names_ptr = vma_names();
+    // should_tag_memtag_globals -> __aarch64__ -> vma_names() != nullptr
+    CHECK(vma_names_ptr);
+    name_memtag_globals_segments(phdr, phnum, base, get_realpath(), vma_names_ptr);
+  }
+
   /* Handle serializing/sharing the RELRO segment */
   if (extinfo && (extinfo->flags & ANDROID_DLEXT_WRITE_RELRO)) {
     if (phdr_table_serialize_gnu_relro(phdr, phnum, load_bias,
@@ -3414,13 +3457,70 @@
 }
 
 bool soinfo::protect_relro() {
-  if (phdr_table_protect_gnu_relro(phdr, phnum, load_bias, should_pad_segments_) < 0) {
-    DL_ERR("can't enable GNU RELRO protection for \"%s\": %m", get_realpath());
-    return false;
+  if (should_use_16kib_app_compat_) {
+    if (phdr_table_protect_gnu_relro_16kib_compat(compat_relro_start_, compat_relro_size_) < 0) {
+      DL_ERR("can't enable COMPAT GNU RELRO protection for \"%s\": %s", get_realpath(),
+             strerror(errno));
+      return false;
+    }
+  } else {
+    if (phdr_table_protect_gnu_relro(phdr, phnum, load_bias, should_pad_segments_,
+                                     should_use_16kib_app_compat_) < 0) {
+      DL_ERR("can't enable GNU RELRO protection for \"%s\": %m", get_realpath());
+      return false;
+    }
   }
   return true;
 }
 
+// https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#global-variable-tagging
+void soinfo::tag_globals(bool dlext_use_relro) {
+  if (is_linked()) return;
+  if (flags_ & FLAG_GLOBALS_TAGGED) return;
+  flags_ |= FLAG_GLOBALS_TAGGED;
+
+  constexpr size_t kTagGranuleSize = 16;
+  const uint8_t* descriptor_stream = reinterpret_cast<const uint8_t*>(memtag_globals());
+
+  if (memtag_globalssz() == 0) {
+    DL_ERR("Invalid memtag descriptor pool size: %zu", memtag_globalssz());
+  }
+
+  uint64_t addr = load_bias;
+  uleb128_decoder decoder(descriptor_stream, memtag_globalssz());
+  // Don't ever generate tag zero, to easily distinguish between tagged and
+  // untagged globals in register/tag dumps.
+  uint64_t last_tag_mask = 1;
+  uint64_t last_tag = 1;
+  constexpr uint64_t kDistanceReservedBits = 3;
+
+  while (decoder.has_bytes()) {
+    uint64_t value = decoder.pop_front();
+    uint64_t distance = (value >> kDistanceReservedBits) * kTagGranuleSize;
+    uint64_t ngranules = value & ((1 << kDistanceReservedBits) - 1);
+    if (ngranules == 0) {
+      ngranules = decoder.pop_front() + 1;
+    }
+
+    addr += distance;
+    void* tagged_addr;
+    if (dlext_use_relro) {
+      tagged_addr = reinterpret_cast<void*>(addr | (last_tag++ << 56));
+      if (last_tag > (1 << kTagGranuleSize)) last_tag = 1;
+    } else {
+      tagged_addr = insert_random_tag(reinterpret_cast<void*>(addr), last_tag_mask);
+      uint64_t tag = (reinterpret_cast<uint64_t>(tagged_addr) >> 56) & 0x0f;
+      last_tag_mask = 1 | (1 << tag);
+    }
+
+    for (size_t k = 0; k < ngranules; k++) {
+      auto* granule = static_cast<uint8_t*>(tagged_addr) + k * kTagGranuleSize;
+      set_memory_tag(static_cast<void*>(granule));
+    }
+    addr += ngranules * kTagGranuleSize;
+  }
+}
+
 static std::vector<android_namespace_t*> init_default_namespace_no_config(bool is_asan, bool is_hwasan) {
   g_default_namespace.set_isolated(false);
   auto default_ld_paths = is_asan ? kAsanDefaultLdPaths : (
@@ -3556,7 +3656,7 @@
 
   {
     std::string ld_config_file_path = get_ld_config_file_path(executable_path);
-    INFO("[ Reading linker config \"%s\" ]", ld_config_file_path.c_str());
+    LD_DEBUG(any, "[ Reading linker config \"%s\" ]", ld_config_file_path.c_str());
     ScopedTrace trace(("linker config " + ld_config_file_path).c_str());
     std::string error_msg;
     if (!Config::read_binary_config(ld_config_file_path.c_str(), executable_path, g_is_asan, g_is_hwasan,
diff --git a/linker/linker.generic.map b/linker/linker.generic.map
index 4d7f236..2beae65 100644
--- a/linker/linker.generic.map
+++ b/linker/linker.generic.map
@@ -24,6 +24,7 @@
     __loader_shared_globals;
     rtld_db_dlactivity;
     __loader_android_handle_signal;
+    __loader_android_set_16kb_appcompat_mode;
   local:
     *;
 };
diff --git a/linker/linker.h b/linker/linker.h
index ac2222d..7afa0d7 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -108,6 +108,9 @@
 
 bool get_transparent_hugepages_supported();
 
+void set_16kb_appcompat_mode(bool enable_app_compat);
+bool get_16kb_appcompat_mode();
+
 enum {
   /* A regular namespace is the namespace with a custom search path that does
    * not impose any restrictions on the location of native libraries.
@@ -179,7 +182,8 @@
 int get_application_target_sdk_version();
 ElfW(Versym) find_verdef_version_index(const soinfo* si, const version_info* vi);
 bool validate_verdef_section(const soinfo* si);
-bool relocate_relr(const ElfW(Relr)* begin, const ElfW(Relr)* end, ElfW(Addr) load_bias);
+bool relocate_relr(const ElfW(Relr) * begin, const ElfW(Relr) * end, ElfW(Addr) load_bias,
+                   bool has_memtag_globals);
 
 struct platform_properties {
 #if defined(__aarch64__)
diff --git a/linker/linker_auxv.cpp b/linker/linker_auxv.cpp
index 95413a0..23025f7 100644
--- a/linker/linker_auxv.cpp
+++ b/linker/linker_auxv.cpp
@@ -61,10 +61,14 @@
   case AT_HWCAP2: return "AT_HWCAP2";
   case AT_RSEQ_FEATURE_SIZE: return "AT_RSEQ_FEATURE_SIZE";
   case AT_RSEQ_ALIGN: return "AT_RSEQ_ALIGN";
+  case AT_HWCAP3: return "AT_HWCAP3";
+  case AT_HWCAP4: return "AT_HWCAP4";
   case AT_EXECFN: return "AT_EXECFN";
   case AT_SYSINFO_EHDR: return "AT_SYSINFO_EHDR";
-#if defined(AT_MINSIGSTKSZ)
   case AT_MINSIGSTKSZ: return "AT_MINSIGSTKSZ";
+#if defined(AT_VECTOR_SIZE_ARCH)
+  // AT_VECTOR_SIZE_ARCH isn't a value: it's the number of architecture-specific
+  // values that exist for the current architecture, so not relevant here.
 #endif
 #if defined(AT_SYSINFO)
   case AT_SYSINFO: return "AT_SYSINFO";
@@ -114,6 +118,8 @@
     case AT_FLAGS:
     case AT_HWCAP:
     case AT_HWCAP2:
+    case AT_HWCAP3:
+    case AT_HWCAP4:
       async_safe_format_fd(STDOUT_FILENO, "%-20s %#lb\n", name, value);
       break;
     case AT_EXECFN:
diff --git a/linker/linker_cfi.cpp b/linker/linker_cfi.cpp
index 247a25d..92ec53e 100644
--- a/linker/linker_cfi.cpp
+++ b/linker/linker_cfi.cpp
@@ -166,13 +166,13 @@
   }
   uintptr_t cfi_check = soinfo_find_cfi_check(si);
   if (cfi_check == 0) {
-    INFO("[ CFI add 0x%zx + 0x%zx %s ]", static_cast<uintptr_t>(si->base),
+    LD_DEBUG(cfi, "[ CFI add 0x%zx + 0x%zx %s ]", static_cast<uintptr_t>(si->base),
          static_cast<uintptr_t>(si->size), si->get_soname());
     AddUnchecked(si->base, si->base + si->size);
     return true;
   }
 
-  INFO("[ CFI add 0x%zx + 0x%zx %s: 0x%zx ]", static_cast<uintptr_t>(si->base),
+  LD_DEBUG(cfi, "[ CFI add 0x%zx + 0x%zx %s: 0x%zx ]", static_cast<uintptr_t>(si->base),
        static_cast<uintptr_t>(si->size), si->get_soname(), cfi_check);
 #ifdef __arm__
   // Require Thumb encoding.
@@ -263,8 +263,8 @@
 void CFIShadowWriter::BeforeUnload(soinfo* si) {
   if (shadow_start == nullptr) return;
   if (si->base == 0 || si->size == 0) return;
-  INFO("[ CFI remove 0x%zx + 0x%zx: %s ]", static_cast<uintptr_t>(si->base),
-       static_cast<uintptr_t>(si->size), si->get_soname());
+  LD_DEBUG(cfi, "[ CFI remove 0x%zx + 0x%zx: %s ]", static_cast<uintptr_t>(si->base),
+           static_cast<uintptr_t>(si->size), si->get_soname());
   AddInvalid(si->base, si->base + si->size);
   FixupVmaName();
 }
diff --git a/linker/linker_config.cpp b/linker/linker_config.cpp
index 613c781..35a93fc 100644
--- a/linker/linker_config.cpp
+++ b/linker/linker_config.cpp
@@ -46,9 +46,6 @@
 #include <string>
 #include <unordered_map>
 
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
-
 class ConfigParser {
  public:
   enum {
@@ -254,10 +251,8 @@
         // the failure with INFO rather than DL_WARN. e.g. A binary in
         // /data/local/tmp may attempt to stat /postinstall. See
         // http://b/120996057.
-        INFO("%s:%zd: warning: path \"%s\" couldn't be resolved: %m",
-             ld_config_file_path,
-             cp.lineno(),
-             value.c_str());
+        LD_DEBUG(any, "%s:%zd: warning: path \"%s\" couldn't be resolved: %m",
+                 ld_config_file_path, cp.lineno(), value.c_str());
         resolved_path = value;
       }
 
@@ -268,7 +263,7 @@
     }
   }
 
-  INFO("[ Using config section \"%s\" ]", section_name.c_str());
+  LD_DEBUG(any, "[ Using config section \"%s\" ]", section_name.c_str());
 
   // skip everything until we meet a correct section
   while (true) {
diff --git a/linker/linker_debug.cpp b/linker/linker_debug.cpp
index e6211f7..430a151 100644
--- a/linker/linker_debug.cpp
+++ b/linker/linker_debug.cpp
@@ -30,19 +30,76 @@
 
 #include <unistd.h>
 
-void linker_log_va_list(int prio, const char* fmt, va_list ap) {
+#include <android-base/strings.h>
+
+LinkerDebugConfig g_linker_debug_config;
+
+void init_LD_DEBUG(const std::string& value) {
+  if (value.empty()) return;
+  std::vector<std::string> options = android::base::Split(value, ",");
+  for (const auto& o : options) {
+    if (o == "calls") g_linker_debug_config.calls = true;
+    else if (o == "cfi") g_linker_debug_config.cfi = true;
+    else if (o == "dynamic") g_linker_debug_config.dynamic = true;
+    else if (o == "lookup") g_linker_debug_config.lookup = true;
+    else if (o == "props") g_linker_debug_config.props = true;
+    else if (o == "reloc") g_linker_debug_config.reloc = true;
+    else if (o == "statistics") g_linker_debug_config.statistics = true;
+    else if (o == "timing") g_linker_debug_config.timing = true;
+    else if (o == "all") {
+      g_linker_debug_config.calls = true;
+      g_linker_debug_config.cfi = true;
+      g_linker_debug_config.dynamic = true;
+      g_linker_debug_config.lookup = true;
+      g_linker_debug_config.props = true;
+      g_linker_debug_config.reloc = true;
+      g_linker_debug_config.statistics = true;
+      g_linker_debug_config.timing = true;
+    } else {
+      __linker_error("$LD_DEBUG is a comma-separated list of:\n"
+                     "\n"
+                     "  calls       ctors/dtors/ifuncs\n"
+                     "  cfi         control flow integrity messages\n"
+                     "  dynamic     dynamic section processing\n"
+                     "  lookup      symbol lookup\n"
+                     "  props       ELF property processing\n"
+                     "  reloc       relocation resolution\n"
+                     "  statistics  relocation statistics\n"
+                     "  timing      timing information\n"
+                     "\n"
+                     "or 'all' for all of the above.\n");
+    }
+  }
+  if (g_linker_debug_config.calls || g_linker_debug_config.cfi ||
+      g_linker_debug_config.dynamic || g_linker_debug_config.lookup ||
+      g_linker_debug_config.props || g_linker_debug_config.reloc ||
+      g_linker_debug_config.statistics || g_linker_debug_config.timing) {
+    g_linker_debug_config.any = true;
+  }
+}
+
+static void linker_log_va_list(int prio, const char* fmt, va_list ap) {
   va_list ap2;
   va_copy(ap2, ap);
-  async_safe_format_log_va_list(5 - prio, "linker", fmt, ap2);
+  async_safe_format_log_va_list(prio, "linker", fmt, ap2);
   va_end(ap2);
 
   async_safe_format_fd_va_list(STDERR_FILENO, fmt, ap);
   write(STDERR_FILENO, "\n", 1);
 }
 
-void linker_log(int prio, const char* fmt, ...) {
+void __linker_log(int prio, const char* fmt, ...) {
   va_list ap;
   va_start(ap, fmt);
   linker_log_va_list(prio, fmt, ap);
   va_end(ap);
 }
+
+void __linker_error(const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  linker_log_va_list(ANDROID_LOG_FATAL, fmt, ap);
+  va_end(ap);
+
+  _exit(EXIT_FAILURE);
+}
diff --git a/linker/linker_debug.h b/linker/linker_debug.h
index 3aab185..e5f17c4 100644
--- a/linker/linker_debug.h
+++ b/linker/linker_debug.h
@@ -28,54 +28,45 @@
 
 #pragma once
 
-// You can increase the verbosity of debug traces by defining the LD_DEBUG
-// environment variable to a numeric value from 0 to 2 (corresponding to
-// INFO, TRACE, and DEBUG calls in the source). This will only
-// affect new processes being launched.
-
-#define TRACE_DEBUG          1
-#define DO_TRACE_LOOKUP      1
-#define DO_TRACE_RELO        1
-#define DO_TRACE_IFUNC       1
-#define TIMING               0
-#define STATS                0
-
-/*********************************************************************
- * You shouldn't need to modify anything below unless you are adding
- * more debugging information.
- *
- * To enable/disable specific debug options, change the defines above
- *********************************************************************/
-
 #include <stdarg.h>
 #include <unistd.h>
 
+#include <string>
+
 #include <async_safe/log.h>
 #include <async_safe/CHECK.h>
 
-#define LINKER_VERBOSITY_PRINT (-1)
-#define LINKER_VERBOSITY_INFO   0
-#define LINKER_VERBOSITY_TRACE  1
-#define LINKER_VERBOSITY_DEBUG  2
+struct LinkerDebugConfig {
+  // Set automatically if any of the more specific options are set.
+  bool any;
 
-__LIBC_HIDDEN__ extern int g_ld_debug_verbosity;
+  // Messages relating to calling ctors/dtors/ifuncs.
+  bool calls;
+  // Messages relating to CFI.
+  bool cfi;
+  // Messages relating to the dynamic section.
+  bool dynamic;
+  // Messages relating to symbol lookup.
+  bool lookup;
+  // Messages relating to relocation processing.
+  bool reloc;
+  // Messages relating to ELF properties.
+  bool props;
+  // TODO: "config" and "zip" seem likely to want to be separate?
 
-__LIBC_HIDDEN__ void linker_log_va_list(int prio, const char* fmt, va_list ap);
-__LIBC_HIDDEN__ void linker_log(int prio, const char* fmt, ...) __printflike(2, 3);
+  bool timing;
+  bool statistics;
+};
 
-#define _PRINTVF(v, x...) \
-    do { \
-      if (g_ld_debug_verbosity > (v)) linker_log((v), x); \
-    } while (0)
+extern LinkerDebugConfig g_linker_debug_config;
 
-#define PRINT(x...)          _PRINTVF(LINKER_VERBOSITY_PRINT, x)
-#define INFO(x...)           _PRINTVF(LINKER_VERBOSITY_INFO, x)
-#define TRACE(x...)          _PRINTVF(LINKER_VERBOSITY_TRACE, x)
+__LIBC_HIDDEN__ void init_LD_DEBUG(const std::string& value);
+__LIBC_HIDDEN__ void __linker_log(int prio, const char* fmt, ...) __printflike(2, 3);
+__LIBC_HIDDEN__ void __linker_error(const char* fmt, ...) __printflike(1, 2);
 
-#if TRACE_DEBUG
-#define DEBUG(x...)          _PRINTVF(LINKER_VERBOSITY_DEBUG, "DEBUG: " x)
-#else /* !TRACE_DEBUG */
-#define DEBUG(x...)          do {} while (0)
-#endif /* TRACE_DEBUG */
-
-#define TRACE_TYPE(t, x...)   do { if (DO_TRACE_##t) { TRACE(x); } } while (0)
+#define LD_DEBUG(what, x...) \
+  do { \
+    if (g_linker_debug_config.what) { \
+      __linker_log(ANDROID_LOG_INFO, x); \
+    } \
+  } while (false)
diff --git a/linker/linker_globals.h b/linker/linker_globals.h
index 0cb7ca9..2bfdccd 100644
--- a/linker/linker_globals.h
+++ b/linker/linker_globals.h
@@ -54,7 +54,7 @@
 #define DL_ERR_AND_LOG(fmt, x...) \
   do { \
     DL_ERR(fmt, ##x); \
-    PRINT(fmt, ##x); \
+    __linker_log(ANDROID_LOG_ERROR, fmt, ##x); \
   } while (false)
 
 #define DL_OPEN_ERR(fmt, x...) \
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 0e5fb96..f65f82d 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -46,6 +46,7 @@
 #include "linker_tls.h"
 #include "linker_utils.h"
 
+#include "platform/bionic/macros.h"
 #include "private/KernelArgumentBlock.h"
 #include "private/bionic_call_ifunc_resolver.h"
 #include "private/bionic_globals.h"
@@ -71,22 +72,9 @@
 static void set_bss_vma_name(soinfo* si);
 
 void __libc_init_mte(const memtag_dynamic_entries_t* memtag_dynamic_entries, const void* phdr_start,
-                     size_t phdr_count, uintptr_t load_bias, void* stack_top);
+                     size_t phdr_count, uintptr_t load_bias);
 
-__printflike(1, 2) static void __linker_error(const char* fmt, ...) {
-  va_list ap;
-
-  va_start(ap, fmt);
-  async_safe_format_fd_va_list(STDERR_FILENO, fmt, ap);
-  write(STDERR_FILENO, "\n", 1);
-  va_end(ap);
-
-  va_start(ap, fmt);
-  async_safe_format_log_va_list(ANDROID_LOG_FATAL, "linker", fmt, ap);
-  va_end(ap);
-
-  _exit(EXIT_FAILURE);
-}
+void __libc_init_mte_stack(void* stack_top);
 
 static void __linker_cannot_link(const char* argv0) {
   __linker_error("CANNOT LINK EXECUTABLE \"%s\": %s", argv0, linker_get_error_buffer());
@@ -119,7 +107,7 @@
 
   if (trav == nullptr) {
     // si was not in solist
-    PRINT("name \"%s\"@%p is not in solist!", si->get_realpath(), si);
+    DL_WARN("name \"%s\"@%p is not in solist!", si->get_realpath(), si);
     return false;
   }
 
@@ -147,7 +135,6 @@
 }
 
 bool g_is_ldd;
-int g_ld_debug_verbosity;
 
 static std::vector<std::string> g_ld_preload_names;
 
@@ -250,12 +237,6 @@
   return result;
 }
 
-#if defined(__LP64__)
-static char kFallbackLinkerPath[] = "/system/bin/linker64";
-#else
-static char kFallbackLinkerPath[] = "/system/bin/linker";
-#endif
-
 // Load an executable. Normally the kernel has already loaded the executable when the linker
 // starts. The linker can be invoked directly on an executable, though, and then the linker must
 // load it. This function doesn't load dependencies or resolve relocations.
@@ -302,10 +283,8 @@
 static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load) {
   ProtectedDataGuard guard;
 
-#if TIMING
-  struct timeval t0, t1;
-  gettimeofday(&t0, 0);
-#endif
+  timeval t0, t1;
+  gettimeofday(&t0, nullptr);
 
   // Sanitize the environment.
   __libc_init_AT_SECURE(args.envp);
@@ -323,13 +302,11 @@
 
   // Enable debugging logs?
   const char* LD_DEBUG = getenv("LD_DEBUG");
-  if (LD_DEBUG != nullptr) {
-    g_ld_debug_verbosity = atoi(LD_DEBUG);
-  }
+  if (LD_DEBUG != nullptr) init_LD_DEBUG(LD_DEBUG);
 
   if (getenv("LD_SHOW_AUXV") != nullptr) ld_show_auxv(args.auxv);
 
-  INFO("[ Android dynamic linker (" ABI_STRING ") ]");
+  LD_DEBUG(any, "[ Android dynamic linker (" ABI_STRING ") ]");
 
   // These should have been sanitized by __libc_init_AT_SECURE, but the test
   // doesn't cost us anything.
@@ -338,18 +315,18 @@
   if (!getauxval(AT_SECURE)) {
     ldpath_env = getenv("LD_LIBRARY_PATH");
     if (ldpath_env != nullptr) {
-      INFO("[ LD_LIBRARY_PATH set to \"%s\" ]", ldpath_env);
+      LD_DEBUG(any, "[ LD_LIBRARY_PATH set to \"%s\" ]", ldpath_env);
     }
     ldpreload_env = getenv("LD_PRELOAD");
     if (ldpreload_env != nullptr) {
-      INFO("[ LD_PRELOAD set to \"%s\" ]", ldpreload_env);
+      LD_DEBUG(any, "[ LD_PRELOAD set to \"%s\" ]", ldpreload_env);
     }
   }
 
   const ExecutableInfo exe_info = exe_to_load ? load_executable(exe_to_load) :
                                                 get_executable_info(args.argv[0]);
 
-  INFO("[ Linking executable \"%s\" ]", exe_info.path.c_str());
+  LD_DEBUG(any, "[ Linking executable \"%s\" ]", exe_info.path.c_str());
 
   // Initialize the main exe's soinfo.
   soinfo* si = soinfo_alloc(&g_default_namespace,
@@ -380,19 +357,27 @@
   if (interp == nullptr) {
     // This case can happen if the linker attempts to execute itself
     // (e.g. "linker64 /system/bin/linker64").
-    interp = kFallbackLinkerPath;
+#if defined(__LP64__)
+#define DEFAULT_INTERP "/system/bin/linker64"
+#else
+#define DEFAULT_INTERP "/system/bin/linker"
+#endif
+    interp = DEFAULT_INTERP;
   }
   solinker->set_realpath(interp);
   init_link_map_head(*solinker);
 
 #if defined(__aarch64__)
+  __libc_init_mte(somain->memtag_dynamic_entries(), somain->phdr, somain->phnum, somain->load_bias);
+
   if (exe_to_load == nullptr) {
     // Kernel does not add PROT_BTI to executable pages of the loaded ELF.
     // Apply appropriate protections here if it is needed.
     auto note_gnu_property = GnuPropertySection(somain);
     if (note_gnu_property.IsBTICompatible() &&
-        (phdr_table_protect_segments(somain->phdr, somain->phnum, somain->load_bias,
-                                     somain->should_pad_segments(), &note_gnu_property) < 0)) {
+        (phdr_table_protect_segments(
+             somain->phdr, somain->phnum, somain->load_bias, somain->should_pad_segments(),
+             somain->should_use_16kib_app_compat(), &note_gnu_property) < 0)) {
       __linker_error("error: can't protect segments for \"%s\": %m", exe_info.path.c_str());
     }
   }
@@ -485,8 +470,7 @@
 #if defined(__aarch64__)
   // This has to happen after the find_libraries, which will have collected any possible
   // libraries that request memtag_stack in the dynamic section.
-  __libc_init_mte(somain->memtag_dynamic_entries(), somain->phdr, somain->phnum, somain->load_bias,
-                  args.argv);
+  __libc_init_mte_stack(args.argv);
 #endif
 
   linker_finalize_static_tls();
@@ -497,27 +481,22 @@
   si->call_pre_init_constructors();
   si->call_constructors();
 
-#if TIMING
-  gettimeofday(&t1, nullptr);
-  PRINT("LINKER TIME: %s: %d microseconds", g_argv[0],
-        static_cast<int>(((static_cast<long long>(t1.tv_sec) * 1000000LL) +
-                          static_cast<long long>(t1.tv_usec)) -
-                         ((static_cast<long long>(t0.tv_sec) * 1000000LL) +
-                          static_cast<long long>(t0.tv_usec))));
-#endif
-#if STATS
-  print_linker_stats();
-#endif
-#if TIMING || STATS
-  fflush(stdout);
-#endif
+  if (g_linker_debug_config.timing) {
+    gettimeofday(&t1, nullptr);
+    long long t0_us = (t0.tv_sec * 1000000LL) + t0.tv_usec;
+    long long t1_us = (t1.tv_sec * 1000000LL) + t1.tv_usec;
+    LD_DEBUG(timing, "LINKER TIME: %s: %lld microseconds", g_argv[0], t1_us - t0_us);
+  }
+  if (g_linker_debug_config.statistics) {
+    print_linker_stats();
+  }
 
   // We are about to hand control over to the executable loaded.  We don't want
   // to leave dirty pages behind unnecessarily.
   purge_unused_memory();
 
   ElfW(Addr) entry = exe_info.entry_point;
-  TRACE("[ Ready to execute \"%s\" @ %p ]", si->get_realpath(), reinterpret_cast<void*>(entry));
+  LD_DEBUG(any, "[ Ready to execute \"%s\" @ %p ]", si->get_realpath(), reinterpret_cast<void*>(entry));
   return entry;
 }
 
@@ -650,8 +629,13 @@
     // Apply RELR relocations first so that the GOT is initialized for ifunc
     // resolvers.
     if (relr && relrsz) {
+      // Nothing has tagged the memtag globals here, so it is pointless either
+      // way to handle them, the tags will be zero anyway.
+      // That is moot though, because the linker does not use memtag_globals
+      // in the first place.
       relocate_relr(reinterpret_cast<ElfW(Relr*)>(ehdr + relr),
-                    reinterpret_cast<ElfW(Relr*)>(ehdr + relr + relrsz), ehdr);
+                    reinterpret_cast<ElfW(Relr*)>(ehdr + relr + relrsz), ehdr,
+                    /*has_memtag_globals=*/ false);
     }
     if (pltrel && pltrelsz) {
       call_ifunc_resolvers_for_section(reinterpret_cast<RelType*>(ehdr + pltrel),
@@ -671,6 +655,16 @@
   }
 }
 
+// Remapping MTE globals segments happens before the linker relocates itself, and so can't use
+// memcpy() from string.h. This function is compiled with -ffreestanding.
+void linker_memcpy(void* dst, const void* src, size_t n) {
+  char* dst_bytes = reinterpret_cast<char*>(dst);
+  const char* src_bytes = reinterpret_cast<const char*>(src);
+  for (size_t i = 0; i < n; ++i) {
+    dst_bytes[i] = src_bytes[i];
+  }
+}
+
 // Detect an attempt to run the linker on itself. e.g.:
 //   /system/bin/linker64 /system/bin/linker64
 // Use priority-1 to run this constructor before other constructors.
@@ -748,6 +742,8 @@
   tmp_linker_so.set_linker_flag();
 
   if (!tmp_linker_so.prelink_image()) __linker_cannot_link(args.argv[0]);
+  // There is special logic in soinfo::relocate to avoid duplicating the
+  // relocations we did in relocate_linker().
   if (!tmp_linker_so.link_image(SymbolLookupList(&tmp_linker_so), &tmp_linker_so, nullptr, nullptr)) __linker_cannot_link(args.argv[0]);
 
   return __linker_init_post_relocation(args, tmp_linker_so);
@@ -834,7 +830,7 @@
 
   ElfW(Addr) start_address = linker_main(args, exe_to_load);
 
-  INFO("[ Jumping to _start (%p)... ]", reinterpret_cast<void*>(start_address));
+  LD_DEBUG(any, "[ Jumping to _start (%p)... ]", reinterpret_cast<void*>(start_address));
 
   // Return the address that the calling assembly stub should jump to.
   return start_address;
diff --git a/linker/linker_main.h b/linker/linker_main.h
index 724f43c..ffbcf0f 100644
--- a/linker/linker_main.h
+++ b/linker/linker_main.h
@@ -70,3 +70,5 @@
 soinfo* solist_get_head();
 soinfo* solist_get_somain();
 soinfo* solist_get_vdso();
+
+void linker_memcpy(void* dst, const void* src, size_t n);
diff --git a/linker/linker_note_gnu_property.cpp b/linker/linker_note_gnu_property.cpp
index be1aebc..082a604 100644
--- a/linker/linker_note_gnu_property.cpp
+++ b/linker/linker_note_gnu_property.cpp
@@ -62,7 +62,7 @@
         continue;
       }
 
-      TRACE("\"%s\" PT_GNU_PROPERTY: found at segment index %zu", name, i);
+      LD_DEBUG(props, "\"%s\" PT_GNU_PROPERTY: found at segment index %zu", name, i);
 
       // Check segment size.
       if (phdr[i].p_memsz < sizeof(ElfW(NhdrGNUProperty))) {
@@ -90,7 +90,7 @@
     }
   }
 
-  TRACE("\"%s\" PT_GNU_PROPERTY: not found", name);
+  LD_DEBUG(props, "\"%s\" PT_GNU_PROPERTY: not found", name);
   return nullptr;
 }
 
@@ -122,7 +122,7 @@
   // The total length of the program property array is in _bytes_.
   ElfW(Word) offset = 0;
   while (offset < note_nhdr->nhdr.n_descsz) {
-    DEBUG("\"%s\" .note.gnu.property: processing at offset 0x%x", name, offset);
+    LD_DEBUG(props, "\"%s\" .note.gnu.property: processing at offset 0x%x", name, offset);
 
     // At least the "header" part must fit.
     // The ABI doesn't say that pr_datasz can't be 0.
@@ -161,14 +161,14 @@
         const ElfW(Word) flags = *reinterpret_cast<const ElfW(Word)*>(&property->pr_data[0]);
         properties_.bti_compatible = (flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) != 0;
         if (properties_.bti_compatible) {
-          INFO("[ BTI compatible: \"%s\" ]", name);
+          LD_DEBUG(props, "[ BTI compatible: \"%s\" ]", name);
         }
         break;
       }
 #endif
       default:
-        DEBUG("\"%s\" .note.gnu.property: found property pr_type %u pr_datasz 0x%x", name,
-              property->pr_type, property->pr_datasz);
+        LD_DEBUG(props, "\"%s\" .note.gnu.property: found property pr_type %u pr_datasz 0x%x",
+                 name, property->pr_type, property->pr_datasz);
         break;
     }
 
diff --git a/linker/linker_note_gnu_property_test.cpp b/linker/linker_note_gnu_property_test.cpp
index 41fc47b..960118c 100644
--- a/linker/linker_note_gnu_property_test.cpp
+++ b/linker/linker_note_gnu_property_test.cpp
@@ -137,18 +137,18 @@
     dump_member("entries ", entries);
     if (entries > 0) {
       std::cout << "    raw data:";
-      const uintptr_t offset = note->nhdr.n_descsz + 16;
-      for (uintptr_t offs = 16; offs < offset; ++offs) {
+      const uintptr_t end = note->nhdr.n_descsz + 16;
+      for (uintptr_t offset = 16; offset < end; ++offset) {
         std::cout << std::hex;
-        if ((offs % 8) == 0) {
+        if ((offset % 8) == 0) {
           std::cout << "\n   ";
         }
-        auto value = static_cast<unsigned>(section[offs]);
+        auto value = static_cast<unsigned>(section[offset]);
         std::cout << " ";
         if (value < 0x10) {
           std::cout << "0";
         }
-        std::cout << static_cast<unsigned>(section[offs]);
+        std::cout << static_cast<unsigned>(section[offset]);
       }
       std::cout << std::dec << "\n";
     }
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 1b51fcd..14bf208 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -37,9 +37,12 @@
 #include <unistd.h>
 
 #include "linker.h"
+#include "linker_debug.h"
 #include "linker_dlwarning.h"
 #include "linker_globals.h"
-#include "linker_debug.h"
+#include "linker_logger.h"
+#include "linker_main.h"
+#include "linker_soinfo.h"
 #include "linker_utils.h"
 
 #include "private/bionic_asm_note.h"
@@ -47,6 +50,7 @@
 #include "private/elf_note.h"
 
 #include <android-base/file.h>
+#include <android-base/properties.h>
 
 static int GetTargetElfMachine() {
 #if defined(__arm__)
@@ -139,11 +143,6 @@
 
  **/
 
-#define MAYBE_MAP_FLAG(x, from, to)  (((x) & (from)) ? (to) : 0)
-#define PFLAGS_TO_PROT(x)            (MAYBE_MAP_FLAG((x), PF_X, PROT_EXEC) | \
-                                      MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \
-                                      MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE))
-
 static const size_t kPageSize = page_size();
 
 /*
@@ -182,6 +181,15 @@
     did_read_ = true;
   }
 
+  if (kPageSize == 0x4000 && phdr_table_get_minimum_alignment(phdr_table_, phdr_num_) == 0x1000) {
+    // This prop needs to be read on 16KiB devices for each ELF where min_palign is 4KiB.
+    // It cannot be cached since the developer may toggle app compat on/off.
+    // This check will be removed once app compat is made the default on 16KiB devices.
+    should_use_16kib_app_compat_ =
+        ::android::base::GetBoolProperty("bionic.linker.16kb.app_compat.enabled", false) ||
+        get_16kb_appcompat_mode();
+  }
+
   return did_read_;
 }
 
@@ -197,8 +205,9 @@
 #if defined(__aarch64__)
     // For Armv8.5-A loaded executable segments may require PROT_BTI.
     if (note_gnu_property_.IsBTICompatible()) {
-      did_load_ = (phdr_table_protect_segments(phdr_table_, phdr_num_, load_bias_,
-                                               should_pad_segments_, &note_gnu_property_) == 0);
+      did_load_ =
+          (phdr_table_protect_segments(phdr_table_, phdr_num_, load_bias_, should_pad_segments_,
+                                       should_use_16kib_app_compat_, &note_gnu_property_) == 0);
     }
 #endif
   }
@@ -221,24 +230,17 @@
 }
 
 bool ElfReader::ReadElfHeader() {
-  size_t map_size = file_size_ - file_offset_;
-  if (map_size < sizeof(header_)) {
+  ssize_t rc = TEMP_FAILURE_RETRY(pread64(fd_, &header_, sizeof(header_), file_offset_));
+  if (rc < 0) {
+    DL_ERR("can't read file \"%s\": %s", name_.c_str(), strerror(errno));
+    return false;
+  }
+
+  if (rc != sizeof(header_)) {
     DL_ERR("\"%s\" is too small to be an ELF executable: only found %zd bytes", name_.c_str(),
-           map_size);
+           static_cast<size_t>(rc));
     return false;
   }
-
-#if !defined(__LP64__)
-  // Map at most 1MiB which should cover most cases
-  map_size = std::min(map_size, static_cast<size_t>(1 * 1024 * 1024));
-#endif
-
-  if (!file_fragment_.Map(fd_, file_offset_, 0, map_size)) {
-    DL_ERR("\"%s\" header mmap failed: %m", name_.c_str());
-    return false;
-  }
-
-  header_ = *static_cast<ElfW(Ehdr)*>(file_fragment_.data());
   return true;
 }
 
@@ -347,24 +349,6 @@
          ((offset % alignment) == 0);
 }
 
-void* ElfReader::MapData(MappedFileFragment* fragment, off64_t offs, off64_t size) {
-  off64_t end;
-  CHECK(safe_add(&end, offs, size));
-
-  // If the data is already mapped just return it
-  if (static_cast<off64_t>(file_fragment_.size()) >= end) {
-    return static_cast<char*>(file_fragment_.data()) + offs;
-  }
-  // Use the passed-in fragment if area is not mapped. We can't remap the original fragment
-  // because that invalidates all previous pointers if the file is remapped to a different
-  // virtual address. A local variable can't be used in place of the passed-in fragment because
-  // the area would be unmapped as soon as the local object goes out of scope.
-  if (fragment->Map(fd_, file_offset_, offs, size)) {
-    return fragment->data();
-  }
-  return nullptr;
-}
-
 // Loads the program header table from an ELF file into a read-only private
 // anonymous mmap-ed block.
 bool ElfReader::ReadProgramHeaders() {
@@ -387,13 +371,12 @@
     return false;
   }
 
-  void* phdr_data = MapData(&phdr_fragment_, header_.e_phoff, size);
-  if (phdr_data == nullptr) {
+  if (!phdr_fragment_.Map(fd_, file_offset_, header_.e_phoff, size)) {
     DL_ERR("\"%s\" phdr mmap failed: %m", name_.c_str());
     return false;
   }
 
-  phdr_table_ = static_cast<ElfW(Phdr)*>(phdr_data);
+  phdr_table_ = static_cast<ElfW(Phdr)*>(phdr_fragment_.data());
   return true;
 }
 
@@ -414,13 +397,12 @@
     return false;
   }
 
-  void* shdr_data = MapData(&shdr_fragment_, header_.e_shoff, size);
-  if (shdr_data == nullptr) {
+  if (!shdr_fragment_.Map(fd_, file_offset_, header_.e_shoff, size)) {
     DL_ERR("\"%s\" shdr mmap failed: %m", name_.c_str());
     return false;
   }
 
-  shdr_table_ = static_cast<const ElfW(Shdr)*>(shdr_data);
+  shdr_table_ = static_cast<const ElfW(Shdr)*>(shdr_fragment_.data());
   return true;
 }
 
@@ -508,13 +490,12 @@
     return false;
   }
 
-  void* dynamic_data = MapData(&dynamic_fragment_, dynamic_shdr->sh_offset, dynamic_shdr->sh_size);
-  if (dynamic_data == nullptr) {
+  if (!dynamic_fragment_.Map(fd_, file_offset_, dynamic_shdr->sh_offset, dynamic_shdr->sh_size)) {
     DL_ERR("\"%s\" dynamic section mmap failed: %m", name_.c_str());
     return false;
   }
 
-  dynamic_ = static_cast<const ElfW(Dyn)*>(dynamic_data);
+  dynamic_ = static_cast<const ElfW(Dyn)*>(dynamic_fragment_.data());
 
   if (!CheckFileRange(strtab_shdr->sh_offset, strtab_shdr->sh_size, alignof(const char))) {
     DL_ERR_AND_LOG("\"%s\" has invalid offset/size of the .strtab section linked from .dynamic section",
@@ -522,14 +503,13 @@
     return false;
   }
 
-  void* strtab_data = MapData(&strtab_fragment_, strtab_shdr->sh_offset, strtab_shdr->sh_size);
-  if (strtab_data == nullptr) {
+  if (!strtab_fragment_.Map(fd_, file_offset_, strtab_shdr->sh_offset, strtab_shdr->sh_size)) {
     DL_ERR("\"%s\" strtab section mmap failed: %m", name_.c_str());
     return false;
   }
 
-  strtab_ = static_cast<const char*>(strtab_data);
-  strtab_size_ = strtab_shdr->sh_size;
+  strtab_ = static_cast<const char*>(strtab_fragment_.data());
+  strtab_size_ = strtab_fragment_.size();
   return true;
 }
 
@@ -596,9 +576,7 @@
       continue;
     }
 
-    if (phdr->p_align > maximum_alignment) {
-      maximum_alignment = phdr->p_align;
-    }
+    maximum_alignment = std::max(maximum_alignment, static_cast<size_t>(phdr->p_align));
   }
 
 #if defined(__LP64__)
@@ -608,6 +586,30 @@
 #endif
 }
 
+// Returns the minimum p_align associated with a loadable segment in the ELF
+// program header table. Used to determine if the program alignment is compatible
+// with the page size of this system.
+size_t phdr_table_get_minimum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count) {
+  size_t minimum_alignment = page_size();
+
+  for (size_t i = 0; i < phdr_count; ++i) {
+    const ElfW(Phdr)* phdr = &phdr_table[i];
+
+    // p_align must be 0, 1, or a positive, integral power of two.
+    if (phdr->p_type != PT_LOAD || ((phdr->p_align & (phdr->p_align - 1)) != 0)) {
+      continue;
+    }
+
+    if (phdr->p_align <= 1) {
+      continue;
+    }
+
+    minimum_alignment = std::min(minimum_alignment, static_cast<size_t>(phdr->p_align));
+  }
+
+  return minimum_alignment;
+}
+
 // 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* ReserveWithAlignmentPadding(size_t size, size_t mapping_align, size_t start_align,
@@ -697,6 +699,13 @@
     return false;
   }
 
+  if (should_use_16kib_app_compat_) {
+    // Reserve additional space for aligning the permission boundary in compat loading
+    // Up to kPageSize-kCompatPageSize additional space is needed, but reservation
+    // is done with mmap which gives kPageSize multiple-sized reservations.
+    load_size_ += kPageSize;
+  }
+
   uint8_t* addr = reinterpret_cast<uint8_t*>(min_vaddr);
   void* start;
 
@@ -732,6 +741,13 @@
 
   load_start_ = start;
   load_bias_ = reinterpret_cast<uint8_t*>(start) - addr;
+
+  if (should_use_16kib_app_compat_) {
+    // In compat mode make the initial mapping RW since the ELF contents will be read
+    // into it; instead of mapped over it.
+    mprotect(reinterpret_cast<void*>(start), load_size_, PROT_READ | PROT_WRITE);
+  }
+
   return true;
 }
 
@@ -785,8 +801,7 @@
     // note_fragment is scoped to within the loop so that there is
     // at most 1 PT_NOTE mapped at anytime during this search.
     MappedFileFragment note_fragment;
-    void* note_data = MapData(&note_fragment, phdr->p_offset, phdr->p_memsz);
-    if (note_data == nullptr) {
+    if (!note_fragment.Map(fd_, file_offset_, phdr->p_offset, phdr->p_memsz)) {
       DL_ERR("\"%s\": PT_NOTE mmap(nullptr, %p, PROT_READ, MAP_PRIVATE, %d, %p) failed: %m",
              name_.c_str(), reinterpret_cast<void*>(phdr->p_memsz), fd_,
              reinterpret_cast<void*>(page_start(file_offset_ + phdr->p_offset)));
@@ -796,7 +811,7 @@
     const ElfW(Nhdr)* note_hdr = nullptr;
     const char* note_desc = nullptr;
     if (!__get_elf_note(NT_ANDROID_TYPE_PAD_SEGMENT, "Android",
-                        reinterpret_cast<ElfW(Addr)>(note_data),
+                        reinterpret_cast<ElfW(Addr)>(note_fragment.data()),
                         phdr, &note_hdr, &note_desc)) {
       continue;
     }
@@ -816,8 +831,15 @@
 }
 
 static inline void _extend_load_segment_vma(const ElfW(Phdr)* phdr_table, size_t phdr_count,
-                                             size_t phdr_idx, ElfW(Addr)* p_memsz,
-                                             ElfW(Addr)* p_filesz, bool should_pad_segments) {
+                                            size_t phdr_idx, ElfW(Addr)* p_memsz,
+                                            ElfW(Addr)* p_filesz, bool should_pad_segments,
+                                            bool should_use_16kib_app_compat) {
+  // NOTE: Segment extension is only applicable where the ELF's max-page-size > runtime page size;
+  // to save kernel VMA slab memory. 16KiB compat mode is the exact opposite scenario.
+  if (should_use_16kib_app_compat) {
+    return;
+  }
+
   const ElfW(Phdr)* phdr = &phdr_table[phdr_idx];
   const ElfW(Phdr)* next = nullptr;
   size_t next_idx = phdr_idx + 1;
@@ -859,7 +881,147 @@
   *p_filesz += extend;
 }
 
+bool ElfReader::MapSegment(size_t seg_idx, size_t len) {
+  const ElfW(Phdr)* phdr = &phdr_table_[seg_idx];
+
+  void* start = reinterpret_cast<void*>(page_start(phdr->p_vaddr + load_bias_));
+
+  // The ELF could be being loaded directly from a zipped APK,
+  // the zip offset must be added to find the segment offset.
+  const ElfW(Addr) offset = file_offset_ + page_start(phdr->p_offset);
+
+  int prot = PFLAGS_TO_PROT(phdr->p_flags);
+
+  void* seg_addr = mmap64(start, len, prot, MAP_FIXED | MAP_PRIVATE, fd_, offset);
+
+  if (seg_addr == MAP_FAILED) {
+    DL_ERR("couldn't map \"%s\" segment %zd: %m", name_.c_str(), seg_idx);
+    return false;
+  }
+
+  // Mark segments as huge page eligible if they meet the requirements
+  if ((phdr->p_flags & PF_X) && phdr->p_align == kPmdSize &&
+      get_transparent_hugepages_supported()) {
+    madvise(seg_addr, len, MADV_HUGEPAGE);
+  }
+
+  return true;
+}
+
+void ElfReader::ZeroFillSegment(const ElfW(Phdr)* phdr) {
+  // NOTE: In 16KiB app compat mode, the ELF mapping is anonymous, meaning that
+  // RW segments are COW-ed from the kernel's zero page. So there is no need to
+  // explicitly zero-fill until the last page's limit.
+  if (should_use_16kib_app_compat_) {
+    return;
+  }
+
+  ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_;
+  uint64_t unextended_seg_file_end = seg_start + phdr->p_filesz;
+
+  // If the segment is writable, and does not end on a page boundary,
+  // zero-fill it until the page limit.
+  //
+  // Do not attempt to zero the extended region past the first partial page,
+  // since doing so may:
+  //   1) Result in a SIGBUS, as the region is not backed by the underlying
+  //      file.
+  //   2) Break the COW backing, faulting in new anon pages for a region
+  //      that will not be used.
+  if ((phdr->p_flags & PF_W) != 0 && page_offset(unextended_seg_file_end) > 0) {
+    memset(reinterpret_cast<void*>(unextended_seg_file_end), 0,
+           kPageSize - page_offset(unextended_seg_file_end));
+  }
+}
+
+void ElfReader::DropPaddingPages(const ElfW(Phdr)* phdr, uint64_t seg_file_end) {
+  // NOTE: Padding pages are only applicable where the ELF's max-page-size > runtime page size;
+  // 16KiB compat mode is the exact opposite scenario.
+  if (should_use_16kib_app_compat_) {
+    return;
+  }
+
+  ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_;
+  uint64_t unextended_seg_file_end = seg_start + phdr->p_filesz;
+
+  uint64_t pad_start = page_end(unextended_seg_file_end);
+  uint64_t pad_end = page_end(seg_file_end);
+  CHECK(pad_start <= pad_end);
+
+  uint64_t pad_len = pad_end - pad_start;
+  if (pad_len == 0 || !page_size_migration_supported()) {
+    return;
+  }
+
+  // Pages may be brought in due to readahead.
+  // Drop the padding (zero) pages, to avoid reclaim work later.
+  //
+  // NOTE: The madvise() here is special, as it also serves to hint to the
+  // kernel the portion of the LOAD segment that is padding.
+  //
+  // See: [1] https://android-review.googlesource.com/c/kernel/common/+/3032411
+  //      [2] https://android-review.googlesource.com/c/kernel/common/+/3048835
+  if (madvise(reinterpret_cast<void*>(pad_start), pad_len, MADV_DONTNEED)) {
+    DL_WARN("\"%s\": madvise(0x%" PRIx64 ", 0x%" PRIx64 ", MADV_DONTNEED) failed: %m",
+            name_.c_str(), pad_start, pad_len);
+  }
+}
+
+bool ElfReader::MapBssSection(const ElfW(Phdr)* phdr, ElfW(Addr) seg_page_end,
+                              ElfW(Addr) seg_file_end) {
+  // NOTE: We do not need to handle .bss in 16KiB compat mode since the mapping
+  // reservation is anonymous and RW to begin with.
+  if (should_use_16kib_app_compat_) {
+    return true;
+  }
+
+  // seg_file_end is now the first page address after the file content.
+  seg_file_end = page_end(seg_file_end);
+
+  if (seg_page_end <= seg_file_end) {
+    return true;
+  }
+
+  // If seg_page_end is larger than seg_file_end, we need to zero
+  // anything between them. This is done by using a private anonymous
+  // map for all extra pages
+  size_t zeromap_size = seg_page_end - seg_file_end;
+  void* zeromap =
+      mmap(reinterpret_cast<void*>(seg_file_end), zeromap_size, PFLAGS_TO_PROT(phdr->p_flags),
+           MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+  if (zeromap == MAP_FAILED) {
+    DL_ERR("couldn't map .bss section for \"%s\": %m", name_.c_str());
+    return false;
+  }
+
+  // Set the VMA name using prctl
+  prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, zeromap, zeromap_size, ".bss");
+
+  return true;
+}
+
 bool ElfReader::LoadSegments() {
+  // NOTE: The compat(legacy) page size (4096) must be used when aligning
+  // the 4KiB segments for loading in compat mode. The larger 16KiB page size
+  // will lead to overwriting adjacent segments since the ELF's segment(s)
+  // are not 16KiB aligned.
+  size_t seg_align = should_use_16kib_app_compat_ ? kCompatPageSize : kPageSize;
+
+  size_t min_palign = phdr_table_get_minimum_alignment(phdr_table_, phdr_num_);
+  // Only enforce this on 16 KB systems with app compat disabled.
+  // Apps may rely on undefined behavior here on 4 KB systems,
+  // which is the norm before this change is introduced
+  if (kPageSize >= 16384 && min_palign < kPageSize && !should_use_16kib_app_compat_) {
+    DL_ERR("\"%s\" program alignment (%zu) cannot be smaller than system page size (%zu)",
+           name_.c_str(), min_palign, kPageSize);
+    return false;
+  }
+
+  if (!Setup16KiBAppCompat()) {
+    DL_ERR("\"%s\" failed to setup 16KiB App Compat", name_.c_str());
+    return false;
+  }
+
   for (size_t i = 0; i < phdr_num_; ++i) {
     const ElfW(Phdr)* phdr = &phdr_table_[i];
 
@@ -869,14 +1031,14 @@
 
     ElfW(Addr) p_memsz = phdr->p_memsz;
     ElfW(Addr) p_filesz = phdr->p_filesz;
-    _extend_load_segment_vma(phdr_table_, phdr_num_, i, &p_memsz, &p_filesz, should_pad_segments_);
+    _extend_load_segment_vma(phdr_table_, phdr_num_, i, &p_memsz, &p_filesz, should_pad_segments_,
+                             should_use_16kib_app_compat_);
 
     // Segment addresses in memory.
     ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_;
     ElfW(Addr) seg_end = seg_start + p_memsz;
 
-    ElfW(Addr) seg_page_start = page_start(seg_start);
-    ElfW(Addr) seg_page_end = page_end(seg_end);
+    ElfW(Addr) seg_page_end = align_up(seg_end, seg_align);
 
     ElfW(Addr) seg_file_end = seg_start + p_filesz;
 
@@ -884,7 +1046,7 @@
     ElfW(Addr) file_start = phdr->p_offset;
     ElfW(Addr) file_end = file_start + p_filesz;
 
-    ElfW(Addr) file_page_start = page_start(file_start);
+    ElfW(Addr) file_page_start = align_down(file_start, seg_align);
     ElfW(Addr) file_length = file_end - file_page_start;
 
     if (file_size_ <= 0) {
@@ -916,79 +1078,24 @@
         add_dlwarning(name_.c_str(), "W+E load segments");
       }
 
-      void* seg_addr = mmap64(reinterpret_cast<void*>(seg_page_start),
-                            file_length,
-                            prot,
-                            MAP_FIXED|MAP_PRIVATE,
-                            fd_,
-                            file_offset_ + file_page_start);
-      if (seg_addr == MAP_FAILED) {
-        DL_ERR("couldn't map \"%s\" segment %zd: %m", name_.c_str(), i);
-        return false;
-      }
-
-      // Mark segments as huge page eligible if they meet the requirements
-      // (executable and PMD aligned).
-      if ((phdr->p_flags & PF_X) && phdr->p_align == kPmdSize &&
-          get_transparent_hugepages_supported()) {
-        madvise(seg_addr, file_length, MADV_HUGEPAGE);
+      // Pass the file_length, since it may have been extended by _extend_load_segment_vma().
+      if (should_use_16kib_app_compat_) {
+        if (!CompatMapSegment(i, file_length)) {
+          return false;
+        }
+      } else {
+        if (!MapSegment(i, file_length)) {
+          return false;
+        }
       }
     }
 
-    // if the segment is writable, and does not end on a page boundary,
-    // zero-fill it until the page limit.
-    //
-    // Do not attempt to zero the extended region past the first partial page,
-    // since doing so may:
-    //   1) Result in a SIGBUS, as the region is not backed by the underlying
-    //      file.
-    //   2) Break the COW backing, faulting in new anon pages for a region
-    //      that will not be used.
+    ZeroFillSegment(phdr);
 
-    uint64_t unextended_seg_file_end = seg_start + phdr->p_filesz;
-    if ((phdr->p_flags & PF_W) != 0 && page_offset(unextended_seg_file_end) > 0) {
-      memset(reinterpret_cast<void*>(unextended_seg_file_end), 0,
-             kPageSize - page_offset(unextended_seg_file_end));
-    }
+    DropPaddingPages(phdr, seg_file_end);
 
-    // Pages may be brought in due to readahead.
-    // Drop the padding (zero) pages, to avoid reclaim work later.
-    //
-    // NOTE: The madvise() here is special, as it also serves to hint to the
-    // kernel the portion of the LOAD segment that is padding.
-    //
-    // See: [1] https://android-review.googlesource.com/c/kernel/common/+/3032411
-    //      [2] https://android-review.googlesource.com/c/kernel/common/+/3048835
-    uint64_t pad_start = page_end(unextended_seg_file_end);
-    uint64_t pad_end = page_end(seg_file_end);
-    CHECK(pad_start <= pad_end);
-    uint64_t pad_len = pad_end - pad_start;
-    if (page_size_migration_supported() && pad_len > 0 &&
-        madvise(reinterpret_cast<void*>(pad_start), pad_len, MADV_DONTNEED)) {
-      DL_WARN("\"%s\": madvise(0x%" PRIx64 ", 0x%" PRIx64 ", MADV_DONTNEED) failed: %m",
-              name_.c_str(), pad_start, pad_len);
-    }
-
-    seg_file_end = page_end(seg_file_end);
-
-    // seg_file_end is now the first page address after the file
-    // content. If seg_end is larger, we need to zero anything
-    // between them. This is done by using a private anonymous
-    // map for all extra pages.
-    if (seg_page_end > seg_file_end) {
-      size_t zeromap_size = seg_page_end - seg_file_end;
-      void* zeromap = mmap(reinterpret_cast<void*>(seg_file_end),
-                           zeromap_size,
-                           PFLAGS_TO_PROT(phdr->p_flags),
-                           MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE,
-                           -1,
-                           0);
-      if (zeromap == MAP_FAILED) {
-        DL_ERR("couldn't zero fill \"%s\" gap: %m", name_.c_str());
-        return false;
-      }
-
-      prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, zeromap, zeromap_size, ".bss");
+    if (!MapBssSection(phdr, seg_page_end, seg_file_end)) {
+      return false;
     }
   }
   return true;
@@ -1000,7 +1107,7 @@
  */
 static int _phdr_table_set_load_prot(const ElfW(Phdr)* phdr_table, size_t phdr_count,
                                      ElfW(Addr) load_bias, int extra_prot_flags,
-                                     bool should_pad_segments) {
+                                     bool should_pad_segments, bool should_use_16kib_app_compat) {
   for (size_t i = 0; i < phdr_count; ++i) {
     const ElfW(Phdr)* phdr = &phdr_table[i];
 
@@ -1010,7 +1117,8 @@
 
     ElfW(Addr) p_memsz = phdr->p_memsz;
     ElfW(Addr) p_filesz = phdr->p_filesz;
-    _extend_load_segment_vma(phdr_table, phdr_count, i, &p_memsz, &p_filesz, should_pad_segments);
+    _extend_load_segment_vma(phdr_table, phdr_count, i, &p_memsz, &p_filesz, should_pad_segments,
+                             should_use_16kib_app_compat);
 
     ElfW(Addr) seg_page_start = page_start(phdr->p_vaddr + load_bias);
     ElfW(Addr) seg_page_end = page_end(phdr->p_vaddr + p_memsz + load_bias);
@@ -1049,12 +1157,14 @@
  *   phdr_count  -> number of entries in tables
  *   load_bias   -> load bias
  *   should_pad_segments -> Are segments extended to avoid gaps in the memory map
+ *   should_use_16kib_app_compat -> Is the ELF being loaded in 16KiB app compat mode.
  *   prop        -> GnuPropertySection or nullptr
  * Return:
  *   0 on success, -1 on failure (error code in errno).
  */
 int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count,
                                 ElfW(Addr) load_bias, bool should_pad_segments,
+                                bool should_use_16kib_app_compat,
                                 const GnuPropertySection* prop __unused) {
   int prot = 0;
 #if defined(__aarch64__)
@@ -1062,7 +1172,127 @@
     prot |= PROT_BTI;
   }
 #endif
-  return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, prot, should_pad_segments);
+  return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, prot, should_pad_segments,
+                                   should_use_16kib_app_compat);
+}
+
+static bool segment_needs_memtag_globals_remapping(const ElfW(Phdr) * phdr) {
+  // For now, MTE globals is only supported on writeable data segments.
+  return phdr->p_type == PT_LOAD && !(phdr->p_flags & PF_X) && (phdr->p_flags & PF_W);
+}
+
+/* When MTE globals are requested by the binary, and when the hardware supports
+ * it, remap the executable's PT_LOAD data pages to have PROT_MTE.
+ *
+ * Returns 0 on success, -1 on failure (error code in errno).
+ */
+int remap_memtag_globals_segments(const ElfW(Phdr) * phdr_table __unused,
+                                  size_t phdr_count __unused, ElfW(Addr) load_bias __unused) {
+#if defined(__aarch64__)
+  for (const ElfW(Phdr)* phdr = phdr_table; phdr < phdr_table + phdr_count; phdr++) {
+    if (!segment_needs_memtag_globals_remapping(phdr)) {
+      continue;
+    }
+
+    uintptr_t seg_page_start = page_start(phdr->p_vaddr) + load_bias;
+    uintptr_t seg_page_end = page_end(phdr->p_vaddr + phdr->p_memsz) + load_bias;
+    size_t seg_page_aligned_size = seg_page_end - seg_page_start;
+
+    int prot = PFLAGS_TO_PROT(phdr->p_flags);
+    // For anonymous private mappings, it may be possible to simply mprotect()
+    // the PROT_MTE flag over the top. For file-based mappings, this will fail,
+    // and we'll need to fall back. We also allow PROT_WRITE here to allow
+    // writing memory tags (in `soinfo::tag_globals()`), and set these sections
+    // back to read-only after tags are applied (similar to RELRO).
+    prot |= PROT_MTE;
+    if (mprotect(reinterpret_cast<void*>(seg_page_start), seg_page_aligned_size,
+                 prot | PROT_WRITE) == 0) {
+      continue;
+    }
+
+    void* mapping_copy = mmap(nullptr, seg_page_aligned_size, PROT_READ | PROT_WRITE,
+                              MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+    linker_memcpy(mapping_copy, reinterpret_cast<void*>(seg_page_start), seg_page_aligned_size);
+
+    void* seg_addr = mmap(reinterpret_cast<void*>(seg_page_start), seg_page_aligned_size,
+                          prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+    if (seg_addr == MAP_FAILED) return -1;
+
+    linker_memcpy(seg_addr, mapping_copy, seg_page_aligned_size);
+    munmap(mapping_copy, seg_page_aligned_size);
+  }
+#endif  // defined(__aarch64__)
+  return 0;
+}
+
+void protect_memtag_globals_ro_segments(const ElfW(Phdr) * phdr_table __unused,
+                                        size_t phdr_count __unused, ElfW(Addr) load_bias __unused) {
+#if defined(__aarch64__)
+  for (const ElfW(Phdr)* phdr = phdr_table; phdr < phdr_table + phdr_count; phdr++) {
+    int prot = PFLAGS_TO_PROT(phdr->p_flags);
+    if (!segment_needs_memtag_globals_remapping(phdr) || (prot & PROT_WRITE)) {
+      continue;
+    }
+
+    prot |= PROT_MTE;
+
+    uintptr_t seg_page_start = page_start(phdr->p_vaddr) + load_bias;
+    uintptr_t seg_page_end = page_end(phdr->p_vaddr + phdr->p_memsz) + load_bias;
+    size_t seg_page_aligned_size = seg_page_end - seg_page_start;
+    mprotect(reinterpret_cast<void*>(seg_page_start), seg_page_aligned_size, prot);
+  }
+#endif  // defined(__aarch64__)
+}
+
+void name_memtag_globals_segments(const ElfW(Phdr) * phdr_table, size_t phdr_count,
+                                  ElfW(Addr) load_bias, const char* soname,
+                                  std::list<std::string>* vma_names) {
+  for (const ElfW(Phdr)* phdr = phdr_table; phdr < phdr_table + phdr_count; phdr++) {
+    if (!segment_needs_memtag_globals_remapping(phdr)) {
+      continue;
+    }
+
+    uintptr_t seg_page_start = page_start(phdr->p_vaddr) + load_bias;
+    uintptr_t seg_page_end = page_end(phdr->p_vaddr + phdr->p_memsz) + load_bias;
+    size_t seg_page_aligned_size = seg_page_end - seg_page_start;
+
+    // For file-based mappings that we're now forcing to be anonymous mappings, set the VMA name to
+    // make debugging easier.
+    // Once we are targeting only devices that run kernel 5.10 or newer (and thus include
+    // https://android-review.git.corp.google.com/c/kernel/common/+/1934723 which causes the
+    // VMA_ANON_NAME to be copied into the kernel), we can get rid of the storage here.
+    // For now, that is not the case:
+    // https://source.android.com/docs/core/architecture/kernel/android-common#compatibility-matrix
+    constexpr int kVmaNameLimit = 80;
+    std::string& vma_name = vma_names->emplace_back(kVmaNameLimit, '\0');
+    int full_vma_length =
+        async_safe_format_buffer(vma_name.data(), kVmaNameLimit, "mt:%s+%" PRIxPTR, soname,
+                                 page_start(phdr->p_vaddr)) +
+        /* include the null terminator */ 1;
+    // There's an upper limit of 80 characters, including the null terminator, in the anonymous VMA
+    // name. If we run over that limit, we end up truncating the segment offset and parts of the
+    // DSO's name, starting on the right hand side of the basename. Because the basename is the most
+    // important thing, chop off the soname from the left hand side first.
+    //
+    // Example (with '#' as the null terminator):
+    //   - "mt:/data/nativetest64/bionic-unit-tests/bionic-loader-test-libs/libdlext_test.so+e000#"
+    //     is a `full_vma_length` == 86.
+    //
+    // We need to left-truncate (86 - 80) 6 characters from the soname, plus the
+    // `vma_truncation_prefix`, so 9 characters total.
+    if (full_vma_length > kVmaNameLimit) {
+      const char vma_truncation_prefix[] = "...";
+      int soname_truncated_bytes =
+          full_vma_length - kVmaNameLimit + sizeof(vma_truncation_prefix) - 1;
+      async_safe_format_buffer(vma_name.data(), kVmaNameLimit, "mt:%s%s+%" PRIxPTR,
+                               vma_truncation_prefix, soname + soname_truncated_bytes,
+                               page_start(phdr->p_vaddr));
+    }
+    if (prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, reinterpret_cast<void*>(seg_page_start),
+              seg_page_aligned_size, vma_name.data()) != 0) {
+      DL_WARN("Failed to rename memtag global segment: %m");
+    }
+  }
 }
 
 /* Change the protection of all loaded segments in memory to writable.
@@ -1079,20 +1309,22 @@
  *   phdr_count  -> number of entries in tables
  *   load_bias   -> load bias
  *   should_pad_segments -> Are segments extended to avoid gaps in the memory map
+ *   should_use_16kib_app_compat -> Is the ELF being loaded in 16KiB app compat mode.
  * Return:
  *   0 on success, -1 on failure (error code in errno).
  */
-int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table,
-                                  size_t phdr_count, ElfW(Addr) load_bias,
-                                  bool should_pad_segments) {
+int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+                                  ElfW(Addr) load_bias, bool should_pad_segments,
+                                  bool should_use_16kib_app_compat) {
   return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, PROT_WRITE,
-                                   should_pad_segments);
+                                   should_pad_segments, should_use_16kib_app_compat);
 }
 
 static inline void _extend_gnu_relro_prot_end(const ElfW(Phdr)* relro_phdr,
                                               const ElfW(Phdr)* phdr_table, size_t phdr_count,
                                               ElfW(Addr) load_bias, ElfW(Addr)* seg_page_end,
-                                              bool should_pad_segments) {
+                                              bool should_pad_segments,
+                                              bool should_use_16kib_app_compat) {
   // Find the index and phdr of the LOAD containing the GNU_RELRO segment
   for (size_t index = 0; index < phdr_count; ++index) {
     const ElfW(Phdr)* phdr = &phdr_table[index];
@@ -1140,7 +1372,7 @@
       // mprotect will only RO protect a part of the extended RW LOAD segment, which
       // will leave an extra split RW VMA (the gap).
       _extend_load_segment_vma(phdr_table, phdr_count, index, &p_memsz, &p_filesz,
-                               should_pad_segments);
+                               should_pad_segments, should_use_16kib_app_compat);
 
       *seg_page_end = page_end(phdr->p_vaddr + p_memsz + load_bias);
       return;
@@ -1153,7 +1385,8 @@
  */
 static int _phdr_table_set_gnu_relro_prot(const ElfW(Phdr)* phdr_table, size_t phdr_count,
                                           ElfW(Addr) load_bias, int prot_flags,
-                                          bool should_pad_segments) {
+                                          bool should_pad_segments,
+                                          bool should_use_16kib_app_compat) {
   const ElfW(Phdr)* phdr = phdr_table;
   const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
 
@@ -1181,7 +1414,7 @@
     ElfW(Addr) seg_page_start = page_start(phdr->p_vaddr) + load_bias;
     ElfW(Addr) seg_page_end = page_end(phdr->p_vaddr + phdr->p_memsz) + load_bias;
     _extend_gnu_relro_prot_end(phdr, phdr_table, phdr_count, load_bias, &seg_page_end,
-                               should_pad_segments);
+                               should_pad_segments, should_use_16kib_app_compat);
 
     int ret = mprotect(reinterpret_cast<void*>(seg_page_start),
                        seg_page_end - seg_page_start,
@@ -1207,13 +1440,29 @@
  *   phdr_count  -> number of entries in tables
  *   load_bias   -> load bias
  *   should_pad_segments -> Were segments extended to avoid gaps in the memory map
+ *   should_use_16kib_app_compat -> Is the ELF being loaded in 16KiB app compat mode.
  * Return:
  *   0 on success, -1 on failure (error code in errno).
  */
 int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count,
-                                 ElfW(Addr) load_bias, bool should_pad_segments) {
+                                 ElfW(Addr) load_bias, bool should_pad_segments,
+                                 bool should_use_16kib_app_compat) {
   return _phdr_table_set_gnu_relro_prot(phdr_table, phdr_count, load_bias, PROT_READ,
-                                        should_pad_segments);
+                                        should_pad_segments, should_use_16kib_app_compat);
+}
+
+/*
+ * Apply RX protection to the compat relro region of the ELF being loaded in
+ * 16KiB compat mode.
+ *
+ * Input:
+ *   start  -> start address of the compat relro region.
+ *   size   -> size of the compat relro region in bytes.
+ * Return:
+ *   0 on success, -1 on failure (error code in errno).
+ */
+int phdr_table_protect_gnu_relro_16kib_compat(ElfW(Addr) start, ElfW(Addr) size) {
+  return mprotect(reinterpret_cast<void*>(start), size, PROT_READ | PROT_EXEC);
 }
 
 /* Serialize the GNU relro segments to the given file descriptor. This can be
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index dc1ca99..e15ece4 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -39,6 +39,15 @@
 #include "linker_mapped_file_fragment.h"
 #include "linker_note_gnu_property.h"
 
+#include <list>
+
+#define MAYBE_MAP_FLAG(x, from, to)  (((x) & (from)) ? (to) : 0)
+#define PFLAGS_TO_PROT(x)            (MAYBE_MAP_FLAG((x), PF_X, PROT_EXEC) | \
+                                      MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \
+                                      MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE))
+
+static constexpr size_t kCompatPageSize = 0x1000;
+
 class ElfReader {
  public:
   ElfReader();
@@ -59,6 +68,9 @@
   bool is_mapped_by_caller() const { return mapped_by_caller_; }
   ElfW(Addr) entry_point() const { return header_.e_entry + load_bias_; }
   bool should_pad_segments() const { return should_pad_segments_; }
+  bool should_use_16kib_app_compat() const { return should_use_16kib_app_compat_; }
+  ElfW(Addr) compat_relro_start() const { return compat_relro_start_; }
+  ElfW(Addr) compat_relro_size() const { return compat_relro_size_; }
 
  private:
   [[nodiscard]] bool ReadElfHeader();
@@ -68,12 +80,20 @@
   [[nodiscard]] bool ReadDynamicSection();
   [[nodiscard]] bool ReadPadSegmentNote();
   [[nodiscard]] bool ReserveAddressSpace(address_space_params* address_space);
+  [[nodiscard]] bool MapSegment(size_t seg_idx, size_t len);
+  [[nodiscard]] bool CompatMapSegment(size_t seg_idx, size_t len);
+  void ZeroFillSegment(const ElfW(Phdr)* phdr);
+  void DropPaddingPages(const ElfW(Phdr)* phdr, uint64_t seg_file_end);
+  [[nodiscard]] bool MapBssSection(const ElfW(Phdr)* phdr, ElfW(Addr) seg_page_end,
+                                   ElfW(Addr) seg_file_end);
+  [[nodiscard]] bool IsEligibleFor16KiBAppCompat(ElfW(Addr)* vaddr);
+  [[nodiscard]] bool HasAtMostOneRelroSegment(const ElfW(Phdr)** relro_phdr);
+  [[nodiscard]] bool Setup16KiBAppCompat();
   [[nodiscard]] bool LoadSegments();
   [[nodiscard]] bool FindPhdr();
   [[nodiscard]] bool FindGnuPropertySection();
   [[nodiscard]] bool CheckPhdr(ElfW(Addr));
   [[nodiscard]] bool CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment);
-  [[nodiscard]] void* MapData(MappedFileFragment* fragment, off64_t offs, off64_t size);
 
   bool did_read_;
   bool did_load_;
@@ -82,8 +102,6 @@
   off64_t file_offset_;
   off64_t file_size_;
 
-  MappedFileFragment file_fragment_;
-
   ElfW(Ehdr) header_;
   size_t phdr_num_;
 
@@ -121,6 +139,13 @@
   // Pad gaps between segments when memory mapping?
   bool should_pad_segments_ = false;
 
+  // Use app compat mode when loading 4KiB max-page-size ELFs on 16KiB page-size devices?
+  bool should_use_16kib_app_compat_ = false;
+
+  // RELRO region for 16KiB compat loading
+  ElfW(Addr) compat_relro_start_ = 0;
+  ElfW(Addr) compat_relro_size_ = 0;
+
   // Only used by AArch64 at the moment.
   GnuPropertySection note_gnu_property_ __unused;
 };
@@ -129,16 +154,22 @@
                                 ElfW(Addr)* min_vaddr = nullptr, ElfW(Addr)* max_vaddr = nullptr);
 
 size_t phdr_table_get_maximum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count);
+size_t phdr_table_get_minimum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count);
 
 int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count,
                                 ElfW(Addr) load_bias, bool should_pad_segments,
+                                bool should_use_16kib_app_compat,
                                 const GnuPropertySection* prop = nullptr);
 
 int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count,
-                                  ElfW(Addr) load_bias, bool should_pad_segments);
+                                  ElfW(Addr) load_bias, bool should_pad_segments,
+                                  bool should_use_16kib_app_compat);
 
 int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count,
-                                 ElfW(Addr) load_bias, bool should_pad_segments);
+                                 ElfW(Addr) load_bias, bool should_pad_segments,
+                                 bool should_use_16kib_app_compat);
+
+int phdr_table_protect_gnu_relro_16kib_compat(ElfW(Addr) start, ElfW(Addr) size);
 
 int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count,
                                    ElfW(Addr) load_bias, int fd, size_t* file_offset);
@@ -159,3 +190,13 @@
                                             ElfW(Addr) load_bias);
 
 bool page_size_migration_supported();
+
+int remap_memtag_globals_segments(const ElfW(Phdr) * phdr_table, size_t phdr_count,
+                                  ElfW(Addr) load_bias);
+
+void protect_memtag_globals_ro_segments(const ElfW(Phdr) * phdr_table, size_t phdr_count,
+                                        ElfW(Addr) load_bias);
+
+void name_memtag_globals_segments(const ElfW(Phdr) * phdr_table, size_t phdr_count,
+                                  ElfW(Addr) load_bias, const char* soname,
+                                  std::list<std::string>* vma_names);
diff --git a/linker/linker_phdr_16kib_compat.cpp b/linker/linker_phdr_16kib_compat.cpp
new file mode 100644
index 0000000..bad20ba
--- /dev/null
+++ b/linker/linker_phdr_16kib_compat.cpp
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "linker_phdr.h"
+
+#include <linux/prctl.h>
+#include <sys/mman.h>
+#include <sys/prctl.h>
+#include <unistd.h>
+
+#include "linker_debug.h"
+#include "linker_dlwarning.h"
+#include "linker_globals.h"
+
+#include "platform/bionic/macros.h"
+#include "platform/bionic/page.h"
+
+#include <string>
+
+static bool g_enable_16kb_app_compat;
+
+static inline bool segment_contains_prefix(const ElfW(Phdr)* segment, const ElfW(Phdr)* prefix) {
+  return segment && prefix && segment->p_vaddr == prefix->p_vaddr;
+}
+
+void set_16kb_appcompat_mode(bool enable_app_compat) {
+  g_enable_16kb_app_compat = enable_app_compat;
+}
+
+bool get_16kb_appcompat_mode() {
+  return g_enable_16kb_app_compat;
+}
+
+/*
+ * Returns true if the ELF contains at most 1 RELRO segment; and populates @relro_phdr
+ * with the relro phdr or nullptr if none.
+ *
+ * Returns false if more than 1 RELRO segments are found.
+ */
+bool ElfReader::HasAtMostOneRelroSegment(const ElfW(Phdr)** relro_phdr) {
+  const ElfW(Phdr)* relro = nullptr;
+  for (size_t i = 0; i < phdr_num_; ++i) {
+    const ElfW(Phdr)* phdr = &phdr_table_[i];
+
+    if (phdr->p_type != PT_GNU_RELRO) {
+      continue;
+    }
+
+    if (relro == nullptr) {
+      relro = phdr;
+    } else {
+      return false;
+    }
+  }
+
+  *relro_phdr = relro;
+
+  return true;
+}
+
+/*
+ * In 16KiB compatibility mode ELFs with the following segment layout
+ * can be loaded successfully:
+ *
+ *         ┌────────────┬─────────────────────────┬────────────┐
+ *         │            │                         │            │
+ *         │  (RO|RX)*  │   (RW - RELRO prefix)?  │    (RW)*   │
+ *         │            │                         │            │
+ *         └────────────┴─────────────────────────┴────────────┘
+ *
+ * In other words, compatible layouts have:
+ *         - zero or more RO or RX segments;
+ *         - followed by zero or one RELRO prefix;
+ *         - followed by zero or more RW segments (this can include the RW
+ *           suffix from the segment containing the RELRO prefix, if any)
+ *
+ * In 16KiB compat mode, after relocation, the ELF is layout in virtual
+ * memory is as shown below:
+ *         ┌──────────────────────────────────────┬────────────┐
+ *         │                                      │            │
+ *         │                (RX)?                 │    (RW)?   │
+ *         │                                      │            │
+ *         └──────────────────────────────────────┴────────────┘
+ *
+ * In compat mode:
+ *         - the RO and RX segments along with the RELRO prefix are protected
+ *           as RX;
+ *         - and the RW segments along with RW suffix from the relro segment,
+ *           if any; are RW protected.
+ *
+ * This allows for the single RX|RW permission boundary to be aligned with
+ * a 16KiB page boundary; since a single page cannot share multiple
+ * permissions.
+ *
+ * IsEligibleFor16KiBAppCompat() identifies compatible ELFs and populates @vaddr
+ * with the boundary between RX|RW portions.
+ *
+ * Returns true if the ELF can be loaded in compat mode, else false.
+ */
+bool ElfReader::IsEligibleFor16KiBAppCompat(ElfW(Addr)* vaddr) {
+  const ElfW(Phdr)* relro_phdr = nullptr;
+  if (!HasAtMostOneRelroSegment(&relro_phdr)) {
+    DL_WARN("\"%s\": Compat loading failed: Multiple RELRO segments found", name_.c_str());
+    return false;
+  }
+
+  const ElfW(Phdr)* last_rw = nullptr;
+  const ElfW(Phdr)* first_rw = nullptr;
+
+  for (size_t i = 0; i < phdr_num_; ++i) {
+    const ElfW(Phdr)* curr = &phdr_table_[i];
+    const ElfW(Phdr)* prev = (i > 0) ? &phdr_table_[i - 1] : nullptr;
+
+    if (curr->p_type != PT_LOAD) {
+      continue;
+    }
+
+    int prot = PFLAGS_TO_PROT(curr->p_flags);
+
+    if ((prot & PROT_WRITE) && (prot & PROT_READ)) {
+      if (!first_rw) {
+        first_rw = curr;
+      }
+
+      if (last_rw && last_rw != prev) {
+        DL_WARN("\"%s\": Compat loading failed: ELF contains multiple non-adjacent RW segments",
+                name_.c_str());
+        return false;
+      }
+
+      last_rw = curr;
+    }
+  }
+
+  if (!relro_phdr) {
+    *vaddr = align_down(first_rw->p_vaddr, kCompatPageSize);
+    return true;
+  }
+
+  // The RELRO segment is present, it must be the prefix of the first RW segment.
+  if (!segment_contains_prefix(first_rw, relro_phdr)) {
+    DL_WARN("\"%s\": Compat loading failed: RELRO is not in the first RW segment",
+            name_.c_str());
+    return false;
+  }
+
+  uint64_t end;
+  if (__builtin_add_overflow(relro_phdr->p_vaddr, relro_phdr->p_memsz, &end)) {
+    DL_WARN("\"%s\": Compat loading failed: relro vaddr + memsz overflowed", name_.c_str());
+    return false;
+  }
+
+  *vaddr = align_up(end, kCompatPageSize);
+  return true;
+}
+
+/*
+ * Returns the offset/shift needed to align @vaddr to a page boundary.
+ */
+static inline ElfW(Addr) perm_boundary_offset(const ElfW(Addr) addr) {
+  ElfW(Addr) offset = page_offset(addr);
+
+  return offset ? page_size() - offset : 0;
+}
+
+bool ElfReader::Setup16KiBAppCompat() {
+  if (!should_use_16kib_app_compat_) {
+    return true;
+  }
+
+  ElfW(Addr) rx_rw_boundary;  // Permission bounadry for compat mode
+  if (!IsEligibleFor16KiBAppCompat(&rx_rw_boundary)) {
+    return false;
+  }
+
+  // Adjust the load_bias to position the RX|RW boundary on a page boundary
+  load_bias_ += perm_boundary_offset(rx_rw_boundary);
+
+  // RW region (.data, .bss ...)
+  ElfW(Addr) rw_start = load_bias_ + rx_rw_boundary;
+  ElfW(Addr) rw_size = load_size_ - (rw_start - reinterpret_cast<ElfW(Addr)>(load_start_));
+
+  CHECK(rw_start % getpagesize() == 0);
+  CHECK(rw_size % getpagesize() == 0);
+
+  // Compat RELRO (RX) region (.text, .data.relro, ...)
+  compat_relro_start_ = reinterpret_cast<ElfW(Addr)>(load_start_);
+  compat_relro_size_ = load_size_ - rw_size;
+
+  // Label the ELF VMA, since compat mode uses anonymous mappings.
+  std::string compat_name = name_ + " (compat loaded)";
+  prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, load_start_, load_size_, compat_name.c_str());
+
+  return true;
+}
+
+bool ElfReader::CompatMapSegment(size_t seg_idx, size_t len) {
+  const ElfW(Phdr)* phdr = &phdr_table_[seg_idx];
+
+  // NOTE: The compat(legacy) page size (4096) must be used when aligning
+  // the 4KiB segments for loading (reading). The larger 16KiB page size
+  // will lead to overwriting adjacent segments since the ELF's segment(s)
+  // are not 16KiB aligned.
+
+  void* start = reinterpret_cast<void*>(align_down(phdr->p_vaddr + load_bias_, kCompatPageSize));
+
+  // The ELF could be being loaded directly from a zipped APK,
+  // the zip offset must be added to find the segment offset.
+  const ElfW(Addr) offset = file_offset_ + align_down(phdr->p_offset, kCompatPageSize);
+
+  CHECK(should_use_16kib_app_compat_);
+
+  // Since the 4KiB max-page-size ELF is not properly aligned, loading it by
+  // directly mmapping the ELF file is not feasible.
+  // Instead, read the ELF contents into the anonymous RW mapping.
+  if (TEMP_FAILURE_RETRY(pread64(fd_, start, len, offset)) == -1) {
+    DL_ERR("Compat loading: \"%s\" failed to read LOAD segment %zu: %m", name_.c_str(), seg_idx);
+    return false;
+  }
+
+  return true;
+}
diff --git a/linker/linker_relocate.cpp b/linker/linker_relocate.cpp
index 8f85871..bbf8359 100644
--- a/linker/linker_relocate.cpp
+++ b/linker/linker_relocate.cpp
@@ -44,6 +44,8 @@
 #include "linker_soinfo.h"
 #include "private/bionic_globals.h"
 
+#include <platform/bionic/mte.h>
+
 static bool is_tls_reloc(ElfW(Word) type) {
   switch (type) {
     case R_GENERIC_TLS_DTPMOD:
@@ -147,12 +149,13 @@
 }
 
 void print_linker_stats() {
-  PRINT("RELO STATS: %s: %d abs, %d rel, %d symbol (%d cached)",
-         g_argv[0],
-         linker_stats.count[kRelocAbsolute],
-         linker_stats.count[kRelocRelative],
-         linker_stats.count[kRelocSymbol],
-         linker_stats.count[kRelocSymbolCached]);
+  LD_DEBUG(statistics,
+           "RELO STATS: %s: %d abs, %d rel, %d symbol (%d cached)",
+           g_argv[0],
+           linker_stats.count[kRelocAbsolute],
+           linker_stats.count[kRelocRelative],
+           linker_stats.count[kRelocSymbol],
+           linker_stats.count[kRelocSymbolCached]);
 }
 
 static bool process_relocation_general(Relocator& relocator, const rel_t& reloc);
@@ -162,7 +165,8 @@
 static bool process_relocation_impl(Relocator& relocator, const rel_t& reloc) {
   constexpr bool IsGeneral = Mode == RelocMode::General;
 
-  void* const rel_target = reinterpret_cast<void*>(reloc.r_offset + relocator.si->load_bias);
+  void* const rel_target = reinterpret_cast<void*>(
+      relocator.si->apply_memtag_if_mte_globals(reloc.r_offset + relocator.si->load_bias));
   const uint32_t r_type = ELFW(R_TYPE)(reloc.r_info);
   const uint32_t r_sym = ELFW(R_SYM)(reloc.r_info);
 
@@ -187,8 +191,8 @@
   auto protect_segments = [&]() {
     // Make .text executable.
     if (phdr_table_protect_segments(relocator.si->phdr, relocator.si->phnum,
-                                    relocator.si->load_bias,
-                                    relocator.si->should_pad_segments()) < 0) {
+                                    relocator.si->load_bias, relocator.si->should_pad_segments(),
+                                    relocator.si->should_use_16kib_app_compat()) < 0) {
       DL_ERR("can't protect segments for \"%s\": %m", relocator.si->get_realpath());
       return false;
     }
@@ -197,8 +201,8 @@
   auto unprotect_segments = [&]() {
     // Make .text writable.
     if (phdr_table_unprotect_segments(relocator.si->phdr, relocator.si->phnum,
-                                      relocator.si->load_bias,
-                                      relocator.si->should_pad_segments()) < 0) {
+                                      relocator.si->load_bias, relocator.si->should_pad_segments(),
+                                      relocator.si->should_use_16kib_app_compat()) < 0) {
       DL_ERR("can't unprotect loadable segments for \"%s\": %m",
              relocator.si->get_realpath());
       return false;
@@ -207,20 +211,9 @@
   };
 #endif
 
-  auto trace_reloc = [](const char* fmt, ...) __printflike(2, 3) {
-    if (IsGeneral &&
-        g_ld_debug_verbosity > LINKER_VERBOSITY_TRACE &&
-        DO_TRACE_RELO) {
-      va_list ap;
-      va_start(ap, fmt);
-      linker_log_va_list(LINKER_VERBOSITY_TRACE, fmt, ap);
-      va_end(ap);
-    }
-  };
-
   // Skip symbol lookup for R_GENERIC_NONE relocations.
   if (__predict_false(r_type == R_GENERIC_NONE)) {
-    trace_reloc("RELO NONE");
+    LD_DEBUG(reloc && IsGeneral, "RELO NONE");
     return true;
   }
 
@@ -313,8 +306,8 @@
     if (r_type == R_GENERIC_JUMP_SLOT) {
       count_relocation_if<IsGeneral>(kRelocAbsolute);
       const ElfW(Addr) result = sym_addr + get_addend_norel();
-      trace_reloc("RELO JMP_SLOT %16p <- %16p %s",
-                  rel_target, reinterpret_cast<void*>(result), sym_name);
+      LD_DEBUG(reloc && IsGeneral, "RELO JMP_SLOT %16p <- %16p %s",
+               rel_target, reinterpret_cast<void*>(result), sym_name);
       *static_cast<ElfW(Addr)*>(rel_target) = result;
       return true;
     }
@@ -326,9 +319,10 @@
     // common in non-platform binaries.
     if (r_type == R_GENERIC_ABSOLUTE) {
       count_relocation_if<IsGeneral>(kRelocAbsolute);
+      if (found_in) sym_addr = found_in->apply_memtag_if_mte_globals(sym_addr);
       const ElfW(Addr) result = sym_addr + get_addend_rel();
-      trace_reloc("RELO ABSOLUTE %16p <- %16p %s",
-                  rel_target, reinterpret_cast<void*>(result), sym_name);
+      LD_DEBUG(reloc && IsGeneral, "RELO ABSOLUTE %16p <- %16p %s",
+               rel_target, reinterpret_cast<void*>(result), sym_name);
       *static_cast<ElfW(Addr)*>(rel_target) = result;
       return true;
     } else if (r_type == R_GENERIC_GLOB_DAT) {
@@ -336,18 +330,30 @@
       // document (IHI0044F) specifies that R_ARM_GLOB_DAT has an addend, but Bionic isn't adding
       // it.
       count_relocation_if<IsGeneral>(kRelocAbsolute);
+      if (found_in) sym_addr = found_in->apply_memtag_if_mte_globals(sym_addr);
       const ElfW(Addr) result = sym_addr + get_addend_norel();
-      trace_reloc("RELO GLOB_DAT %16p <- %16p %s",
-                  rel_target, reinterpret_cast<void*>(result), sym_name);
+      LD_DEBUG(reloc && IsGeneral, "RELO GLOB_DAT %16p <- %16p %s",
+               rel_target, reinterpret_cast<void*>(result), sym_name);
       *static_cast<ElfW(Addr)*>(rel_target) = result;
       return true;
     } else if (r_type == R_GENERIC_RELATIVE) {
       // In practice, r_sym is always zero, but if it weren't, the linker would still look up the
       // referenced symbol (and abort if the symbol isn't found), even though it isn't used.
       count_relocation_if<IsGeneral>(kRelocRelative);
-      const ElfW(Addr) result = relocator.si->load_bias + get_addend_rel();
-      trace_reloc("RELO RELATIVE %16p <- %16p",
-                  rel_target, reinterpret_cast<void*>(result));
+      ElfW(Addr) result = relocator.si->load_bias + get_addend_rel();
+      // MTE globals reuses the place bits for additional tag-derivation metadata for
+      // R_AARCH64_RELATIVE relocations, which makes it incompatible with
+      // `-Wl,--apply-dynamic-relocs`. This is enforced by lld, however there's nothing stopping
+      // Android binaries (particularly prebuilts) from building with this linker flag if they're
+      // not built with MTE globals. Thus, don't use the new relocation semantics if this DSO
+      // doesn't have MTE globals.
+      if (relocator.si->should_tag_memtag_globals()) {
+        int64_t* place = static_cast<int64_t*>(rel_target);
+        int64_t offset = *place;
+        result = relocator.si->apply_memtag_if_mte_globals(result + offset) - offset;
+      }
+      LD_DEBUG(reloc && IsGeneral, "RELO RELATIVE %16p <- %16p",
+               rel_target, reinterpret_cast<void*>(result));
       *static_cast<ElfW(Addr)*>(rel_target) = result;
       return true;
     }
@@ -368,8 +374,8 @@
       if (!relocator.si->is_linker()) {
         count_relocation_if<IsGeneral>(kRelocRelative);
         const ElfW(Addr) ifunc_addr = relocator.si->load_bias + get_addend_rel();
-        trace_reloc("RELO IRELATIVE %16p <- %16p",
-                    rel_target, reinterpret_cast<void*>(ifunc_addr));
+        LD_DEBUG(reloc && IsGeneral, "RELO IRELATIVE %16p <- %16p",
+                 rel_target, reinterpret_cast<void*>(ifunc_addr));
         if (handle_text_relocs && !protect_segments()) return false;
         const ElfW(Addr) result = call_ifunc_resolver(ifunc_addr);
         if (handle_text_relocs && !unprotect_segments()) return false;
@@ -406,8 +412,8 @@
           }
         }
         tpoff += sym_addr + get_addend_rel();
-        trace_reloc("RELO TLS_TPREL %16p <- %16p %s",
-                    rel_target, reinterpret_cast<void*>(tpoff), sym_name);
+        LD_DEBUG(reloc && IsGeneral, "RELO TLS_TPREL %16p <- %16p %s",
+                 rel_target, reinterpret_cast<void*>(tpoff), sym_name);
         *static_cast<ElfW(Addr)*>(rel_target) = tpoff;
       }
       break;
@@ -422,8 +428,8 @@
           module_id = found_in->get_tls()->module_id;
           CHECK(module_id != kTlsUninitializedModuleId);
         }
-        trace_reloc("RELO TLS_DTPMOD %16p <- %zu %s",
-                    rel_target, module_id, sym_name);
+        LD_DEBUG(reloc && IsGeneral, "RELO TLS_DTPMOD %16p <- %zu %s",
+                 rel_target, module_id, sym_name);
         *static_cast<ElfW(Addr)*>(rel_target) = module_id;
       }
       break;
@@ -431,8 +437,8 @@
       count_relocation_if<IsGeneral>(kRelocRelative);
       {
         const ElfW(Addr) result = sym_addr + get_addend_rel() - TLS_DTV_OFFSET;
-        trace_reloc("RELO TLS_DTPREL %16p <- %16p %s",
-                    rel_target, reinterpret_cast<void*>(result), sym_name);
+        LD_DEBUG(reloc && IsGeneral, "RELO TLS_DTPREL %16p <- %16p %s",
+                 rel_target, reinterpret_cast<void*>(result), sym_name);
         *static_cast<ElfW(Addr)*>(rel_target) = result;
       }
       break;
@@ -449,8 +455,8 @@
           // Unresolved weak relocation.
           desc->func = tlsdesc_resolver_unresolved_weak;
           desc->arg = addend;
-          trace_reloc("RELO TLSDESC %16p <- unresolved weak, addend 0x%zx %s",
-                      rel_target, static_cast<size_t>(addend), sym_name);
+          LD_DEBUG(reloc && IsGeneral, "RELO TLSDESC %16p <- unresolved weak, addend 0x%zx %s",
+                   rel_target, static_cast<size_t>(addend), sym_name);
         } else {
           CHECK(found_in->get_tls() != nullptr); // We rejected a missing TLS segment above.
           size_t module_id = found_in->get_tls()->module_id;
@@ -458,10 +464,10 @@
           if (mod.static_offset != SIZE_MAX) {
             desc->func = tlsdesc_resolver_static;
             desc->arg = mod.static_offset - relocator.tls_tp_base + sym_addr + addend;
-            trace_reloc("RELO TLSDESC %16p <- static (0x%zx - 0x%zx + 0x%zx + 0x%zx) %s",
-                        rel_target, mod.static_offset, relocator.tls_tp_base,
-                        static_cast<size_t>(sym_addr), static_cast<size_t>(addend),
-                        sym_name);
+            LD_DEBUG(reloc && IsGeneral, "RELO TLSDESC %16p <- static (0x%zx - 0x%zx + 0x%zx + 0x%zx) %s",
+                     rel_target, mod.static_offset, relocator.tls_tp_base,
+                     static_cast<size_t>(sym_addr), static_cast<size_t>(addend),
+                     sym_name);
           } else {
             relocator.tlsdesc_args->push_back({
               .generation = mod.first_generation,
@@ -474,9 +480,9 @@
               desc, relocator.tlsdesc_args->size() - 1
             });
             const TlsDynamicResolverArg& desc_arg = relocator.tlsdesc_args->back();
-            trace_reloc("RELO TLSDESC %16p <- dynamic (gen %zu, mod %zu, off %zu) %s",
-                        rel_target, desc_arg.generation, desc_arg.index.module_id,
-                        desc_arg.index.offset, sym_name);
+            LD_DEBUG(reloc && IsGeneral, "RELO TLSDESC %16p <- dynamic (gen %zu, mod %zu, off %zu) %s",
+                     rel_target, desc_arg.generation, desc_arg.index.module_id,
+                     desc_arg.index.offset, sym_name);
           }
         }
       }
@@ -488,8 +494,8 @@
       count_relocation_if<IsGeneral>(kRelocAbsolute);
       {
         const Elf32_Addr result = sym_addr + reloc.r_addend;
-        trace_reloc("RELO R_X86_64_32 %16p <- 0x%08x %s",
-                    rel_target, result, sym_name);
+        LD_DEBUG(reloc && IsGeneral, "RELO R_X86_64_32 %16p <- 0x%08x %s",
+                 rel_target, result, sym_name);
         *static_cast<Elf32_Addr*>(rel_target) = result;
       }
       break;
@@ -499,9 +505,9 @@
         const ElfW(Addr) target = sym_addr + reloc.r_addend;
         const ElfW(Addr) base = reinterpret_cast<ElfW(Addr)>(rel_target);
         const Elf32_Addr result = target - base;
-        trace_reloc("RELO R_X86_64_PC32 %16p <- 0x%08x (%16p - %16p) %s",
-                    rel_target, result, reinterpret_cast<void*>(target),
-                    reinterpret_cast<void*>(base), sym_name);
+        LD_DEBUG(reloc && IsGeneral, "RELO R_X86_64_PC32 %16p <- 0x%08x (%16p - %16p) %s",
+                 rel_target, result, reinterpret_cast<void*>(target),
+                 reinterpret_cast<void*>(base), sym_name);
         *static_cast<Elf32_Addr*>(rel_target) = result;
       }
       break;
@@ -512,9 +518,9 @@
         const ElfW(Addr) target = sym_addr + get_addend_rel();
         const ElfW(Addr) base = reinterpret_cast<ElfW(Addr)>(rel_target);
         const ElfW(Addr) result = target - base;
-        trace_reloc("RELO R_386_PC32 %16p <- 0x%08x (%16p - %16p) %s",
-                    rel_target, result, reinterpret_cast<void*>(target),
-                    reinterpret_cast<void*>(base), sym_name);
+        LD_DEBUG(reloc && IsGeneral, "RELO R_386_PC32 %16p <- 0x%08x (%16p - %16p) %s",
+                 rel_target, result, reinterpret_cast<void*>(target),
+                 reinterpret_cast<void*>(base), sym_name);
         *static_cast<ElfW(Addr)*>(rel_target) = result;
       }
       break;
@@ -559,15 +565,11 @@
 }
 
 static bool needs_slow_relocate_loop(const Relocator& relocator __unused) {
-#if STATS
-  // TODO: This could become a run-time flag.
-  return true;
-#endif
 #if !defined(__LP64__)
   if (relocator.si->has_text_relocations) return true;
 #endif
-  if (g_ld_debug_verbosity > LINKER_VERBOSITY_TRACE) {
-    // If linker TRACE() is enabled, then each relocation is logged.
+  // Both LD_DEBUG relocation logging and statistics need the slow path.
+  if (g_linker_debug_config.any || g_linker_debug_config.statistics) {
     return true;
   }
   return false;
@@ -611,10 +613,10 @@
   // The linker already applied its RELR relocations in an earlier pass, so
   // skip the RELR relocations for the linker.
   if (relr_ != nullptr && !is_linker()) {
-    DEBUG("[ relocating %s relr ]", get_realpath());
+    LD_DEBUG(reloc, "[ relocating %s relr ]", get_realpath());
     const ElfW(Relr)* begin = relr_;
     const ElfW(Relr)* end = relr_ + relr_count_;
-    if (!relocate_relr(begin, end, load_bias)) {
+    if (!relocate_relr(begin, end, load_bias, should_tag_memtag_globals())) {
       return false;
     }
   }
@@ -626,7 +628,7 @@
         android_relocs_[1] == 'P' &&
         android_relocs_[2] == 'S' &&
         android_relocs_[3] == '2') {
-      DEBUG("[ relocating %s android rel/rela ]", get_realpath());
+      LD_DEBUG(reloc, "[ relocating %s android rel/rela ]", get_realpath());
 
       const uint8_t* packed_relocs = android_relocs_ + 4;
       const size_t packed_relocs_size = android_relocs_size_ - 4;
@@ -642,27 +644,27 @@
 
 #if defined(USE_RELA)
   if (rela_ != nullptr) {
-    DEBUG("[ relocating %s rela ]", get_realpath());
+    LD_DEBUG(reloc, "[ relocating %s rela ]", get_realpath());
 
     if (!plain_relocate<RelocMode::Typical>(relocator, rela_, rela_count_)) {
       return false;
     }
   }
   if (plt_rela_ != nullptr) {
-    DEBUG("[ relocating %s plt rela ]", get_realpath());
+    LD_DEBUG(reloc, "[ relocating %s plt rela ]", get_realpath());
     if (!plain_relocate<RelocMode::JumpTable>(relocator, plt_rela_, plt_rela_count_)) {
       return false;
     }
   }
 #else
   if (rel_ != nullptr) {
-    DEBUG("[ relocating %s rel ]", get_realpath());
+    LD_DEBUG(reloc, "[ relocating %s rel ]", get_realpath());
     if (!plain_relocate<RelocMode::Typical>(relocator, rel_, rel_count_)) {
       return false;
     }
   }
   if (plt_rel_ != nullptr) {
-    DEBUG("[ relocating %s plt rel ]", get_realpath());
+   LD_DEBUG(reloc, "[ relocating %s plt rel ]", get_realpath());
     if (!plain_relocate<RelocMode::JumpTable>(relocator, plt_rel_, plt_rel_count_)) {
       return false;
     }
diff --git a/linker/linker_sleb128.h b/linker/linker_sleb128.h
index 6bb3199..f48fda8 100644
--- a/linker/linker_sleb128.h
+++ b/linker/linker_sleb128.h
@@ -69,3 +69,32 @@
   const uint8_t* current_;
   const uint8_t* const end_;
 };
+
+class uleb128_decoder {
+ public:
+  uleb128_decoder(const uint8_t* buffer, size_t count) : current_(buffer), end_(buffer + count) {}
+
+  uint64_t pop_front() {
+    uint64_t value = 0;
+
+    size_t shift = 0;
+    uint8_t byte;
+
+    do {
+      if (current_ >= end_) {
+        async_safe_fatal("uleb128_decoder ran out of bounds");
+      }
+      byte = *current_++;
+      value |= (static_cast<size_t>(byte & 127) << shift);
+      shift += 7;
+    } while (byte & 128);
+
+    return value;
+  }
+
+  bool has_bytes() { return current_ < end_; }
+
+ private:
+  const uint8_t* current_;
+  const uint8_t* const end_;
+};
diff --git a/linker/linker_soinfo.cpp b/linker/linker_soinfo.cpp
index b2170d8..176c133 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -44,21 +44,18 @@
 #include "linker_logger.h"
 #include "linker_relocate.h"
 #include "linker_utils.h"
-
-// Enable the slow lookup path if symbol lookups should be logged.
-static bool is_lookup_tracing_enabled() {
-  return g_ld_debug_verbosity > LINKER_VERBOSITY_TRACE && DO_TRACE_LOOKUP;
-}
+#include "platform/bionic/mte.h"
+#include "private/bionic_globals.h"
 
 SymbolLookupList::SymbolLookupList(soinfo* si)
     : sole_lib_(si->get_lookup_lib()), begin_(&sole_lib_), end_(&sole_lib_ + 1) {
   CHECK(si != nullptr);
-  slow_path_count_ += is_lookup_tracing_enabled();
+  slow_path_count_ += !!g_linker_debug_config.lookup;
   slow_path_count_ += sole_lib_.needs_sysv_lookup();
 }
 
 SymbolLookupList::SymbolLookupList(const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
-  slow_path_count_ += is_lookup_tracing_enabled();
+  slow_path_count_ += !!g_linker_debug_config.lookup;
   libs_.reserve(1 + global_group.size() + local_group.size());
 
   // Reserve a space in front for DT_SYMBOLIC lookup.
@@ -144,8 +141,8 @@
       }
 
       if (IsGeneral) {
-        TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p (gnu)",
-                   name, lib->si_->get_realpath(), reinterpret_cast<void*>(lib->si_->base));
+        LD_DEBUG(lookup, "SEARCH %s in %s@%p (gnu)",
+                 name, lib->si_->get_realpath(), reinterpret_cast<void*>(lib->si_->base));
       }
 
       const uint32_t word_num = (hash / kBloomMaskBits) & lib->gnu_maskwords_;
@@ -309,6 +306,12 @@
   return is_gnu_hash() ? gnu_lookup(symbol_name, vi) : elf_lookup(symbol_name, vi);
 }
 
+ElfW(Addr) soinfo::apply_memtag_if_mte_globals(ElfW(Addr) sym_addr) const {
+  if (!should_tag_memtag_globals()) return sym_addr;
+  if (sym_addr == 0) return sym_addr;  // Handle undefined weak symbols.
+  return reinterpret_cast<ElfW(Addr)>(get_tagged_address(reinterpret_cast<void*>(sym_addr)));
+}
+
 const ElfW(Sym)* soinfo::gnu_lookup(SymbolName& symbol_name, const version_info* vi) const {
   const uint32_t hash = symbol_name.gnu_hash();
 
@@ -318,8 +321,8 @@
   const uint32_t h1 = hash % kBloomMaskBits;
   const uint32_t h2 = (hash >> gnu_shift2_) % kBloomMaskBits;
 
-  TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p (gnu)",
-      symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
+  LD_DEBUG(lookup, "SEARCH %s in %s@%p (gnu)",
+           symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
 
   // test against bloom filter
   if ((1 & (bloom_word >> h1) & (bloom_word >> h2)) == 0) {
@@ -352,9 +355,9 @@
 const ElfW(Sym)* soinfo::elf_lookup(SymbolName& symbol_name, const version_info* vi) const {
   uint32_t hash = symbol_name.elf_hash();
 
-  TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p h=%x(elf) %zd",
-             symbol_name.get_name(), get_realpath(),
-             reinterpret_cast<void*>(base), hash, hash % nbucket_);
+  LD_DEBUG(lookup, "SEARCH %s in %s@%p h=%x(elf) %zd",
+           symbol_name.get_name(), get_realpath(),
+           reinterpret_cast<void*>(base), hash, hash % nbucket_);
 
   const ElfW(Versym) verneed = find_verdef_version_index(this, vi);
   const ElfW(Versym)* versym = get_versym_table();
@@ -429,9 +432,9 @@
     return;
   }
 
-  TRACE("[ Calling c-tor %s @ %p for '%s' ]", function_name, function, realpath);
+  LD_DEBUG(calls, "[ Calling c-tor %s @ %p for '%s' ]", function_name, function, realpath);
   function(g_argc, g_argv, g_envp);
-  TRACE("[ Done calling c-tor %s @ %p for '%s' ]", function_name, function, realpath);
+  LD_DEBUG(calls, "[ Done calling c-tor %s @ %p for '%s' ]", function_name, function, realpath);
 }
 
 static void call_function(const char* function_name __unused,
@@ -441,9 +444,9 @@
     return;
   }
 
-  TRACE("[ Calling d-tor %s @ %p for '%s' ]", function_name, function, realpath);
+  LD_DEBUG(calls, "[ Calling d-tor %s @ %p for '%s' ]", function_name, function, realpath);
   function();
-  TRACE("[ Done calling d-tor %s @ %p for '%s' ]", function_name, function, realpath);
+  LD_DEBUG(calls, "[ Done calling d-tor %s @ %p for '%s' ]", function_name, function, realpath);
 }
 
 template <typename F>
@@ -453,18 +456,18 @@
     return;
   }
 
-  TRACE("[ Calling %s (size %zd) @ %p for '%s' ]", array_name, count, functions, realpath);
+  LD_DEBUG(calls, "[ Calling %s (size %zd) @ %p for '%s' ]", array_name, count, functions, realpath);
 
   int begin = reverse ? (count - 1) : 0;
   int end = reverse ? -1 : count;
   int step = reverse ? -1 : 1;
 
   for (int i = begin; i != end; i += step) {
-    TRACE("[ %s[%d] == %p ]", array_name, i, functions[i]);
+    LD_DEBUG(calls, "[ %s[%d] == %p ]", array_name, i, functions[i]);
     call_function("function", functions[i], realpath);
   }
 
-  TRACE("[ Done calling %s for '%s' ]", array_name, realpath);
+  LD_DEBUG(calls, "[ Done calling %s for '%s' ]", array_name, realpath);
 }
 
 void soinfo::call_pre_init_constructors() {
@@ -492,7 +495,7 @@
 
   if (!is_main_executable() && preinit_array_ != nullptr) {
     // The GNU dynamic linker silently ignores these, but we warn the developer.
-    PRINT("\"%s\": ignoring DT_PREINIT_ARRAY in shared library!", get_realpath());
+    DL_WARN("\"%s\": ignoring DT_PREINIT_ARRAY in shared library!", get_realpath());
   }
 
   get_children().for_each([] (soinfo* si) {
diff --git a/linker/linker_soinfo.h b/linker/linker_soinfo.h
index 9a13af2..4d02676 100644
--- a/linker/linker_soinfo.h
+++ b/linker/linker_soinfo.h
@@ -30,6 +30,7 @@
 
 #include <link.h>
 
+#include <list>
 #include <memory>
 #include <string>
 #include <vector>
@@ -66,6 +67,7 @@
                                          // soinfo is executed and this flag is
                                          // unset.
 #define FLAG_PRELINKED        0x00000400 // prelink_image has successfully processed this soinfo
+#define FLAG_GLOBALS_TAGGED   0x00000800 // globals have been tagged by MTE.
 #define FLAG_NEW_SOINFO       0x40000000 // new soinfo format
 
 #define SOINFO_VERSION 6
@@ -252,11 +254,14 @@
   void call_constructors();
   void call_destructors();
   void call_pre_init_constructors();
-  bool prelink_image();
+  bool prelink_image(bool deterministic_memtag_globals = false);
   bool link_image(const SymbolLookupList& lookup_list, soinfo* local_group_root,
                   const android_dlextinfo* extinfo, size_t* relro_fd_offset);
   bool protect_relro();
 
+  void tag_globals(bool deterministic_memtag_globals);
+  ElfW(Addr) apply_memtag_if_mte_globals(ElfW(Addr) sym_addr) const;
+
   void add_child(soinfo* child);
   void remove_all_links();
 
@@ -293,6 +298,9 @@
 #if defined(__work_around_b_24465209__)
     return (flags_ & FLAG_NEW_SOINFO) != 0 && version_ >= min_version;
 #else
+    // If you make this return non-true in the case where
+    // __work_around_b_24465209__ is not defined, you will have to change
+    // memtag_dynamic_entries() and vma_names().
     return true;
 #endif
   }
@@ -354,20 +362,66 @@
   size_t get_gap_size() const;
 
   const memtag_dynamic_entries_t* memtag_dynamic_entries() const {
-    CHECK(has_min_version(7));
+#ifdef __aarch64__
+#ifdef __work_around_b_24465209__
+#error "Assuming aarch64 does not use versioned soinfo."
+#endif
     return &memtag_dynamic_entries_;
+#endif
+    return nullptr;
   }
-  void* memtag_globals() const { return memtag_dynamic_entries()->memtag_globals; }
-  size_t memtag_globalssz() const { return memtag_dynamic_entries()->memtag_globalssz; }
-  bool has_memtag_mode() const { return memtag_dynamic_entries()->has_memtag_mode; }
-  unsigned memtag_mode() const { return memtag_dynamic_entries()->memtag_mode; }
-  bool memtag_heap() const { return memtag_dynamic_entries()->memtag_heap; }
-  bool memtag_stack() const { return memtag_dynamic_entries()->memtag_stack; }
+  void* memtag_globals() const {
+    const memtag_dynamic_entries_t* entries = memtag_dynamic_entries();
+    return entries ? entries->memtag_globals : nullptr;
+  }
+  size_t memtag_globalssz() const {
+    const memtag_dynamic_entries_t* entries = memtag_dynamic_entries();
+    return entries ? entries->memtag_globalssz : 0U;
+  }
+  bool has_memtag_mode() const {
+    const memtag_dynamic_entries_t* entries = memtag_dynamic_entries();
+    return entries ? entries->has_memtag_mode : false;
+  }
+  unsigned memtag_mode() const {
+    const memtag_dynamic_entries_t* entries = memtag_dynamic_entries();
+    return entries ? entries->memtag_mode : 0U;
+  }
+  bool memtag_heap() const {
+    const memtag_dynamic_entries_t* entries = memtag_dynamic_entries();
+    return entries ? entries->memtag_heap : false;
+  }
+  bool memtag_stack() const {
+    const memtag_dynamic_entries_t* entries = memtag_dynamic_entries();
+    return entries ? entries->memtag_stack : false;
+  }
 
   void set_should_pad_segments(bool should_pad_segments) {
    should_pad_segments_ = should_pad_segments;
   }
   bool should_pad_segments() const { return should_pad_segments_; }
+  bool should_tag_memtag_globals() const {
+    return !is_linker() && memtag_globals() && memtag_globalssz() > 0 && __libc_mte_enabled();
+  }
+  std::list<std::string>* vma_names() {
+#ifdef __aarch64__
+#ifdef __work_around_b_24465209__
+#error "Assuming aarch64 does not use versioned soinfo."
+#endif
+    return &vma_names_;
+#endif
+    return nullptr;
+};
+
+  void set_should_use_16kib_app_compat(bool should_use_16kib_app_compat) {
+    should_use_16kib_app_compat_ = should_use_16kib_app_compat;
+  }
+  bool should_use_16kib_app_compat() const { return should_use_16kib_app_compat_; }
+
+  void set_compat_relro_start(ElfW(Addr) start) { compat_relro_start_ = start; }
+  ElfW(Addr) compat_relro_start() const { return compat_relro_start_; }
+
+  void set_compat_relro_size(ElfW(Addr) size) { compat_relro_size_ = size; }
+  ElfW(Addr) compat_relro_size() const { return compat_relro_start_; }
 
  private:
   bool is_image_linked() const;
@@ -450,11 +504,19 @@
   ElfW(Addr) gap_start_;
   size_t gap_size_;
 
-  // version >= 7
+  // __aarch64__ only, which does not use versioning.
   memtag_dynamic_entries_t memtag_dynamic_entries_;
+  std::list<std::string> vma_names_;
 
   // Pad gaps between segments when memory mapping?
   bool should_pad_segments_ = false;
+
+  // Use app compat mode when loading 4KiB max-page-size ELFs on 16KiB page-size devices?
+  bool should_use_16kib_app_compat_ = false;
+
+  // RELRO region for 16KiB compat loading
+  ElfW(Addr) compat_relro_start_ = 0;
+  ElfW(Addr) compat_relro_size_ = 0;
 };
 
 // This function is used by dlvsym() to calculate hash of sym_ver
diff --git a/linker/linker_test_globals.cpp b/linker/linker_test_globals.cpp
index 4b41eed..27ec6f7 100644
--- a/linker/linker_test_globals.cpp
+++ b/linker/linker_test_globals.cpp
@@ -26,9 +26,6 @@
  * SUCH DAMAGE.
  */
 
-// To enable logging
-int g_ld_debug_verbosity = 0;
-
 // Stub some symbols to avoid linking issues
 void DL_WARN_documented_change(int api_level [[maybe_unused]],
                                const char* doc_link [[maybe_unused]],
diff --git a/linker/linker_translate_path.cpp b/linker/linker_translate_path.cpp
index 4f3fdfb..b41669e 100644
--- a/linker/linker_translate_path.cpp
+++ b/linker/linker_translate_path.cpp
@@ -42,13 +42,13 @@
 // Workaround for dlopen(/system/lib(64)/<soname>) when .so is in /apex. http://b/121248172
 /**
  * Translate /system path to /apex path if needed
- * The workaround should work only when targetSdkVersion < Q.
+ * The workaround should work only when targetSdkVersion < 29.
  *
  * param out_name_to_apex pointing to /apex path
  * return true if translation is needed
  */
 bool translateSystemPathToApexPath(const char* name, std::string* out_name_to_apex) {
-  static constexpr const char* kPathTranslationQ[][2] = {
+  static constexpr const char* kPathTranslation[][2] = {
       APEX_LIB("com.android.i18n", "libicui18n.so"),
       APEX_LIB("com.android.i18n", "libicuuc.so")
   };
@@ -59,10 +59,10 @@
 
   auto comparator = [name](auto p) { return strcmp(name, p[0]) == 0; };
 
-  if (get_application_target_sdk_version() < __ANDROID_API_Q__) {
+  if (get_application_target_sdk_version() < 29) {
     if (auto it =
-            std::find_if(std::begin(kPathTranslationQ), std::end(kPathTranslationQ), comparator);
-        it != std::end(kPathTranslationQ)) {
+            std::find_if(std::begin(kPathTranslation), std::end(kPathTranslation), comparator);
+        it != std::end(kPathTranslation)) {
       *out_name_to_apex = (*it)[1];
       return true;
     }
diff --git a/linker/linker_utils.cpp b/linker/linker_utils.cpp
index 9abe542..f72716e 100644
--- a/linker/linker_utils.cpp
+++ b/linker/linker_utils.cpp
@@ -75,7 +75,7 @@
 bool normalize_path(const char* path, std::string* normalized_path) {
   // Input should be an absolute path
   if (path[0] != '/') {
-    PRINT("normalize_path - invalid input: \"%s\", the input path should be absolute", path);
+    DL_WARN("normalize_path - invalid input: \"%s\", the input path should be absolute", path);
     return false;
   }
 
@@ -144,7 +144,7 @@
   }
 
   const char* const path = normalized_path.c_str();
-  TRACE("Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path);
+  LD_DEBUG(any, "Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path);
 
   // Treat an '!/' separator inside a path as the separator between the name
   // of the zip file on disk and the subdirectory to search within it.
@@ -157,7 +157,7 @@
 
   char buf[512];
   if (strlcpy(buf, path, sizeof(buf)) >= sizeof(buf)) {
-    PRINT("Warning: ignoring very long library path: %s", path);
+    DL_WARN("ignoring very long library path: %s", path);
     return false;
   }
 
diff --git a/tests/Android.bp b/tests/Android.bp
index d2a3110..22fa542 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -389,6 +389,7 @@
         "bug_26110743_test.cpp",
         "byteswap_test.cpp",
         "complex_test.cpp",
+        "cpu_target_features_test.cpp",
         "ctype_test.cpp",
         "dirent_test.cpp",
         "elf_test.cpp",
@@ -427,6 +428,7 @@
         "malloc_test.cpp",
         "math_test.cpp",
         "membarrier_test.cpp",
+        "memtag_globals_test.cpp",
         "memtag_stack_test.cpp",
         "mntent_test.cpp",
         "mte_test.cpp",
@@ -566,12 +568,6 @@
     },
 
     generated_headers: ["generated_android_ids"],
-
-    // Bug: http://b/218788252 IR verifier too strict for ifunc resolver that
-    // accept parameters.
-    lto: {
-        never: true,
-    },
 }
 
 cc_test_library {
@@ -719,11 +715,6 @@
     ],
     srcs: ["clang_fortify_tests.cpp"],
     tidy: false,
-    target: {
-        host: {
-            cflags: ["-D__clang__"],
-        },
-    },
 }
 
 cc_test_library {
@@ -756,6 +747,40 @@
     },
 }
 
+cc_defaults {
+    name: "bionic_fortify_c_tests_defaults",
+    defaults: [
+        "bionic_clang_fortify_tests_w_flags",
+        "bionic_tests_defaults",
+    ],
+    cflags: [
+        "-U_FORTIFY_SOURCE",
+        // -fbuiltin is required here to counteract -fno-builtin from
+        // `bionic_tests_defaults`. With `-fno-builtin`, Clang won't
+        // const-evaluate calls to `strlen`, which is tested for here.
+        "-fbuiltin",
+    ],
+    srcs: [
+        "clang_fortify_c_only_tests.c",
+    ],
+    tidy: false,
+    shared: {
+        enabled: false,
+    },
+}
+
+cc_test_library {
+    name: "libfortify1-c-tests-clang",
+    defaults: ["bionic_fortify_c_tests_defaults"],
+    cflags: ["-D_FORTIFY_SOURCE=1"],
+}
+
+cc_test_library {
+    name: "libfortify2-c-tests-clang",
+    defaults: ["bionic_fortify_c_tests_defaults"],
+    cflags: ["-D_FORTIFY_SOURCE=2"],
+}
+
 // -----------------------------------------------------------------------------
 // Library of all tests (excluding the dynamic linker tests).
 // -----------------------------------------------------------------------------
@@ -767,8 +792,10 @@
         "libBionicStandardTests",
         "libBionicElfTlsTests",
         "libBionicFramePointerTests",
+        "libfortify1-c-tests-clang",
         "libfortify1-tests-clang",
         "libfortify1-new-tests-clang",
+        "libfortify2-c-tests-clang",
         "libfortify2-tests-clang",
         "libfortify2-new-tests-clang",
     ],
@@ -789,6 +816,7 @@
         "dlfcn_test.cpp",
         "execinfo_test.cpp",
         "link_test.cpp",
+        "page_size_16kib_compat_test.cpp",
         "pthread_dlfcn_test.cpp",
     ],
     static_libs: [
@@ -797,6 +825,7 @@
     ],
     include_dirs: [
         "bionic/libc",
+        "bionic/tests/libs",
     ],
     shared: {
         enabled: false,
@@ -863,6 +892,11 @@
         "ld_preload_test_helper",
         "ld_preload_test_helper_lib1",
         "ld_preload_test_helper_lib2",
+        "memtag_globals_binary",
+        "memtag_globals_binary_static",
+        "memtag_globals_dso",
+        "mte_globals_relr_regression_test_b_314038442",
+        "mte_globals_relr_regression_test_b_314038442_mte",
         "ns_hidden_child_helper",
         "preinit_getauxval_test_helper",
         "preinit_syscall_test_helper",
@@ -944,6 +978,7 @@
         "libtest_dt_runpath_d",
         "libtest_dt_runpath_x",
         "libtest_dt_runpath_y",
+        "libtest_elf_max_page_size_4kib",
         "libtest_elftls_dynamic",
         "libtest_elftls_dynamic_filler_1",
         "libtest_elftls_dynamic_filler_2",
@@ -1094,8 +1129,8 @@
     ],
 }
 
-cc_test {
-    name: "hwasan_test",
+cc_defaults {
+    name: "hwasan_test_defaults",
     enabled: false,
     // This does not use bionic_tests_defaults because it is not supported on
     // host.
@@ -1110,9 +1145,6 @@
     srcs: [
         "hwasan_test.cpp",
     ],
-    shared_libs: [
-        "libbase",
-    ],
     data_libs: [
         "libtest_simple_hwasan",
         "libtest_simple_hwasan_nohwasan",
@@ -1122,6 +1154,24 @@
 }
 
 cc_test {
+    name: "hwasan_test",
+    defaults: ["hwasan_test_defaults"],
+    shared_libs: [
+        "libbase",
+    ],
+}
+
+cc_test {
+    name: "hwasan_test_static",
+    defaults: ["hwasan_test_defaults"],
+    static_libs: [
+        "libbase",
+    ],
+    static_executable: true,
+    cflags: ["-DHWASAN_TEST_STATIC"],
+}
+
+cc_test {
     name: "memtag_stack_dlopen_test",
     enabled: false,
     // This does not use bionic_tests_defaults because it is not supported on
@@ -1155,6 +1205,35 @@
 }
 
 cc_test {
+    name: "memtag_stack_abi_test",
+    enabled: false,
+    // This does not use bionic_tests_defaults because it is not supported on
+    // host.
+    arch: {
+        arm64: {
+            enabled: true,
+        },
+    },
+    // We don't use `sanitize:` so we generate the appropriate ELF note, but
+    // still support non-MTE devices.
+    // TODO(fmayer): also add a test that enables stack MTE for MTE devices,
+    // which would test for more bugs.
+    ldflags: ["-fsanitize=memtag-stack"],
+    // Turn off all other sanitizers from SANITIZE_TARGET.
+    sanitize: {
+        never: true,
+    },
+    shared_libs: [
+        "libbase",
+    ],
+    srcs: [
+        "memtag_stack_abi_test.cpp",
+    ],
+    header_libs: ["bionic_libc_platform_headers"],
+    test_suites: ["device-tests"],
+}
+
+cc_test {
     name: "bionic-stress-tests",
     defaults: [
         "bionic_tests_defaults",
@@ -1173,6 +1252,7 @@
 
     shared_libs: [
         "libbase",
+        "liblog",
     ],
 
     target: {
@@ -1242,6 +1322,11 @@
         "heap_tagging_static_disabled_helper",
         "heap_tagging_static_sync_helper",
         "heap_tagging_sync_helper",
+        "memtag_globals_binary",
+        "memtag_globals_binary_static",
+        "memtag_globals_dso",
+        "mte_globals_relr_regression_test_b_314038442",
+        "mte_globals_relr_regression_test_b_314038442_mte",
         "stack_tagging_helper",
         "stack_tagging_static_helper",
     ],
diff --git a/tools/versioner/src/Preprocessor.h b/tests/DoNotOptimize.h
similarity index 63%
rename from tools/versioner/src/Preprocessor.h
rename to tests/DoNotOptimize.h
index 2a17534..711d339 100644
--- a/tools/versioner/src/Preprocessor.h
+++ b/tests/DoNotOptimize.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2012 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,9 +16,12 @@
 
 #pragma once
 
-#include <string>
-
-class HeaderDatabase;
-
-bool preprocessHeaders(const std::string& preprocessor_output_path, const std::string& source_dir,
-                       HeaderDatabase* database);
+// From <benchmark/benchmark.h>.
+template <class Tp>
+static inline void DoNotOptimize(Tp const& value) {
+  asm volatile("" : : "r,m"(value) : "memory");
+}
+template <class Tp>
+static inline void DoNotOptimize(Tp& value) {
+  asm volatile("" : "+r,m"(value) : : "memory");
+}
diff --git a/libc/arch-x86/generic/string/wcscat.c b/tests/clang_fortify_c_only_tests.c
similarity index 78%
rename from libc/arch-x86/generic/string/wcscat.c
rename to tests/clang_fortify_c_only_tests.c
index a102551..3bec848 100644
--- a/libc/arch-x86/generic/string/wcscat.c
+++ b/tests/clang_fortify_c_only_tests.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,5 +26,13 @@
  * SUCH DAMAGE.
  */
 
-#define wcscat wcscat_freebsd
-#include <upstream-freebsd/lib/libc/string/wcscat.c>
+#include <string.h>
+
+// This is a test specifically of bionic's FORTIFY machinery. Other stdlibs need not apply.
+#ifdef __BIONIC__
+
+// Ensure that strlen can be evaluated at compile-time. Clang doesn't support
+// this in C++, but does in C.
+_Static_assert(strlen("foo") == 3, "");
+
+#endif  // __BIONIC__
diff --git a/tests/clang_fortify_tests.cpp b/tests/clang_fortify_tests.cpp
index f4ef4ac..da7926d 100644
--- a/tests/clang_fortify_tests.cpp
+++ b/tests/clang_fortify_tests.cpp
@@ -14,10 +14,6 @@
  * limitations under the License.
  */
 
-#ifndef __clang__
-#error "Non-clang isn't supported"
-#endif
-
 //
 // Clang compile-time and run-time tests for Bionic's FORTIFY.
 //
@@ -93,6 +89,10 @@
 #include <unistd.h>
 #include <wchar.h>
 
+#include <array>
+
+#include "DoNotOptimize.h"
+
 #ifndef COMPILATION_TESTS
 #include <android-base/silent_death_test.h>
 #include <gtest/gtest.h>
@@ -137,6 +137,24 @@
 
 const static int kBogusFD = -1;
 
+FORTIFY_TEST(strlen) {
+  auto run_strlen_with_contents = [&](std::array<char, 3> contents) {
+    // A lot of cruft is necessary to make this test DTRT. LLVM and Clang love to fold/optimize
+    // strlen calls, and that's the opposite of what we want to happen.
+
+    // Loop to convince LLVM that `contents` can never be known (since `xor volatile_value` can flip
+    // any bit in each elem of `contents`).
+    volatile char always_zero = 0;
+    for (char& c : contents) {
+      c ^= always_zero;
+    }
+    DoNotOptimize(strlen(&contents.front()));
+  };
+
+  EXPECT_NO_DEATH(run_strlen_with_contents({'f', 'o', '\0'}));
+  EXPECT_FORTIFY_DEATH(run_strlen_with_contents({'f', 'o', 'o'}));
+}
+
 FORTIFY_TEST(string) {
   char small_buffer[8] = {};
 
diff --git a/tests/complex_test.cpp b/tests/complex_test.cpp
index 8fdb2b2..ed0109a 100644
--- a/tests/complex_test.cpp
+++ b/tests/complex_test.cpp
@@ -20,6 +20,9 @@
 #if !defined(__INTRODUCED_IN)
 #define __INTRODUCED_IN(x)
 #endif
+#if !defined(__BIONIC_AVAILABILITY_GUARD)
+#define __BIONIC_AVAILABILITY_GUARD(x) 1
+#endif
 
 // libc++ actively gets in the way of including <complex.h> from C++, so we
 // have to be naughty.
diff --git a/tests/cpu_target_features_test.cpp b/tests/cpu_target_features_test.cpp
new file mode 100644
index 0000000..d773772
--- /dev/null
+++ b/tests/cpu_target_features_test.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <gtest/gtest.h>
+#include <stdlib.h>
+
+#include "utils.h"
+
+TEST(cpu_target_features, has_expected_x86_compiler_values) {
+#if defined(__x86_64__) || defined(__i386__)
+  ExecTestHelper eth;
+  char* const argv[] = {nullptr};
+  const auto invocation = [&] { execvp("cpu-target-features", argv); };
+  eth.Run(invocation, 0, "(^|\n)__AES__=1($|\n)");
+  eth.Run(invocation, 0, "(^|\n)__CRC32__=1($|\n)");
+#else
+  GTEST_SKIP() << "Not targeting an x86 architecture.";
+#endif
+}
+
+TEST(cpu_target_features, has_expected_aarch64_compiler_values) {
+#if defined(__aarch64__)
+  ExecTestHelper eth;
+  char* const argv[] = {nullptr};
+  const auto invocation = [&] { execvp("cpu-target-features", argv); };
+  eth.Run(invocation, 0, "(^|\n)__ARM_FEATURE_AES=1($|\n)");
+  eth.Run(invocation, 0, "(^|\n)__ARM_FEATURE_CRC32=1($|\n)");
+#else
+  GTEST_SKIP() << "Not targeting an aarch64 architecture.";
+#endif
+}
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 570da2a..8b26cb0 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -21,6 +21,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
+#include <link.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
@@ -40,11 +41,13 @@
 #include <procinfo/process_map.h>
 #include <ziparchive/zip_archive.h>
 
+#include "bionic/mte.h"
+#include "bionic/page.h"
 #include "core_shared_libs.h"
-#include "gtest_globals.h"
-#include "utils.h"
 #include "dlext_private.h"
 #include "dlfcn_symlink_support.h"
+#include "gtest_globals.h"
+#include "utils.h"
 
 #define ASSERT_DL_NOTNULL(ptr) \
     ASSERT_TRUE((ptr) != nullptr) << "dlerror: " << dlerror()
@@ -1958,6 +1961,14 @@
   dlclose(ns_a_handle3);
 }
 
+static inline int MapPflagsToProtFlags(uint32_t flags) {
+  int prot_flags = 0;
+  if (PF_X & flags) prot_flags |= PROT_EXEC;
+  if (PF_W & flags) prot_flags |= PROT_WRITE;
+  if (PF_R & flags) prot_flags |= PROT_READ;
+  return prot_flags;
+}
+
 TEST(dlext, ns_anonymous) {
   static const char* root_lib = "libnstest_root.so";
   std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
@@ -1999,30 +2010,45 @@
   typedef const char* (*fn_t)();
   fn_t ns_get_dlopened_string_private = reinterpret_cast<fn_t>(ns_get_dlopened_string_addr);
 
-  std::vector<map_record> maps;
-  Maps::parse_maps(&maps);
-
+  Dl_info private_library_info;
+  ASSERT_NE(dladdr(reinterpret_cast<void*>(ns_get_dlopened_string_addr), &private_library_info), 0)
+      << dlerror();
+  std::vector<map_record> maps_to_copy;
+  bool has_executable_segment = false;
   uintptr_t addr_start = 0;
   uintptr_t addr_end = 0;
-  bool has_executable_segment = false;
-  std::vector<map_record> maps_to_copy;
+  std::tuple dl_iterate_arg = {&private_library_info, &maps_to_copy, &has_executable_segment,
+                               &addr_start, &addr_end};
+  ASSERT_EQ(
+      1, dl_iterate_phdr(
+             [](dl_phdr_info* info, size_t /*size*/, void* data) -> int {
+               auto [private_library_info, maps_to_copy, has_executable_segment, addr_start,
+                     addr_end] = *reinterpret_cast<decltype(dl_iterate_arg)*>(data);
+               if (info->dlpi_addr != reinterpret_cast<ElfW(Addr)>(private_library_info->dli_fbase))
+                 return 0;
 
-  for (const auto& rec : maps) {
-    if (rec.pathname == private_library_absolute_path) {
-      if (addr_start == 0) {
-        addr_start = rec.addr_start;
-      }
-      addr_end = rec.addr_end;
-      has_executable_segment = has_executable_segment || (rec.perms & PROT_EXEC) != 0;
-
-      maps_to_copy.push_back(rec);
-    }
-  }
+               for (size_t i = 0; i < info->dlpi_phnum; ++i) {
+                 const ElfW(Phdr)* phdr = info->dlpi_phdr + i;
+                 if (phdr->p_type != PT_LOAD) continue;
+                 *has_executable_segment |= phdr->p_flags & PF_X;
+                 uintptr_t mapping_start = page_start(info->dlpi_addr + phdr->p_vaddr);
+                 uintptr_t mapping_end = page_end(info->dlpi_addr + phdr->p_vaddr + phdr->p_memsz);
+                 if (*addr_start == 0 || mapping_start < *addr_start) *addr_start = mapping_start;
+                 if (*addr_end == 0 || mapping_end > *addr_end) *addr_end = mapping_end;
+                 maps_to_copy->push_back({
+                     .addr_start = mapping_start,
+                     .addr_end = mapping_end,
+                     .perms = MapPflagsToProtFlags(phdr->p_flags),
+                 });
+               }
+               return 1;
+             },
+             &dl_iterate_arg));
 
   // Some validity checks.
+  ASSERT_NE(maps_to_copy.size(), 0u);
   ASSERT_TRUE(addr_start > 0);
   ASSERT_TRUE(addr_end > 0);
-  ASSERT_TRUE(maps_to_copy.size() > 0);
   ASSERT_TRUE(ns_get_dlopened_string_addr > addr_start);
   ASSERT_TRUE(ns_get_dlopened_string_addr < addr_end);
 
@@ -2052,19 +2078,26 @@
   ASSERT_EQ(ret, 0) << "Failed to stat library";
   size_t file_size = file_stat.st_size;
 
-  for (const auto& rec : maps_to_copy) {
-    uintptr_t offset = rec.addr_start - addr_start;
-    size_t size = rec.addr_end - rec.addr_start;
-    void* addr = reinterpret_cast<void*>(reserved_addr + offset);
-    void* map = mmap(addr, size, PROT_READ | PROT_WRITE,
-                     MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
-    ASSERT_TRUE(map != MAP_FAILED);
-    // Attempting the below memcpy from a portion of the map that is off the end of
-    // the backing file will cause the kernel to throw a SIGBUS
-    size_t _size = ::android::procinfo::MappedFileSize(rec.addr_start, rec.addr_end,
-                                                       rec.offset, file_size);
-    memcpy(map, reinterpret_cast<void*>(rec.addr_start), _size);
-    mprotect(map, size, rec.perms);
+  {
+    // Disable MTE while copying the PROT_MTE-protected global variables from
+    // the existing mappings. We don't really care about turning on PROT_MTE for
+    // the new copy of the mappings, as this isn't the behaviour under test and
+    // tags will be ignored. This only applies for MTE-enabled devices.
+    ScopedDisableMTE disable_mte_for_copying_global_variables;
+    for (const auto& rec : maps_to_copy) {
+      uintptr_t offset = rec.addr_start - addr_start;
+      size_t size = rec.addr_end - rec.addr_start;
+      void* addr = reinterpret_cast<void*>(reserved_addr + offset);
+      void* map =
+          mmap(addr, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
+      ASSERT_TRUE(map != MAP_FAILED);
+      // Attempting the below memcpy from a portion of the map that is off the end of
+      // the backing file will cause the kernel to throw a SIGBUS
+      size_t _size =
+          ::android::procinfo::MappedFileSize(rec.addr_start, rec.addr_end, rec.offset, file_size);
+      memcpy(map, reinterpret_cast<void*>(rec.addr_start), _size);
+      mprotect(map, size, rec.perms);
+    }
   }
 
   // call the function copy
diff --git a/tests/fenv_test.cpp b/tests/fenv_test.cpp
index 9cf9d98..bbf339f 100644
--- a/tests/fenv_test.cpp
+++ b/tests/fenv_test.cpp
@@ -16,6 +16,7 @@
 
 #include <gtest/gtest.h>
 
+#include "DoNotOptimize.h"
 #include "utils.h"
 
 #include <fenv.h>
diff --git a/tests/grp_pwd_test.cpp b/tests/grp_pwd_test.cpp
index ddc0fc1..3f93c8a 100644
--- a/tests/grp_pwd_test.cpp
+++ b/tests/grp_pwd_test.cpp
@@ -444,10 +444,9 @@
     return result;
   };
 
-  // AID_UPROBESTATS (1093) was added in V, but "trunk stable" means
-  // that the 2024Q builds don't have branches like the QPR builds used
-  // to, and are tested with the _previous_ release's CTS.
-  if (android::base::GetIntProperty("ro.build.version.sdk", 0) == __ANDROID_API_U__) {
+  // AID_UPROBESTATS (1093) was added in API level 35, but "trunk stable" means
+  // that the 2024Q* builds are tested with the _previous_ release's CTS.
+  if (android::base::GetIntProperty("ro.build.version.sdk", 0) == 34) {
 #if !defined(AID_UPROBESTATS)
 #define AID_UPROBESTATS 1093
 #endif
@@ -457,10 +456,9 @@
       EXPECT_STREQ(getpwuid(AID_UPROBESTATS)->pw_name, "uprobestats");
     }
   }
-  // AID_VIRTUALMACHINE (3013) was added in V, but "trunk stable" means
-  // that the 2024Q builds don't have branches like the QPR builds used
-  // to, and are tested with the _previous_ release's CTS.
-  if (android::base::GetIntProperty("ro.build.version.sdk", 0) == __ANDROID_API_U__) {
+  // AID_VIRTUALMACHINE (3013) was added in API level 35, but "trunk stable" means
+  // that the 2024Q* builds are tested with the _previous_ release's CTS.
+  if (android::base::GetIntProperty("ro.build.version.sdk", 0) == 34) {
 #if !defined(AID_VIRTUALMACHINE)
 #define AID_VIRTUALMACHINE 3013
 #endif
@@ -470,6 +468,30 @@
       EXPECT_STREQ(getpwuid(AID_VIRTUALMACHINE)->pw_name, "virtualmachine");
     }
   }
+  // AID_CROS_EC (1094) was added in API level 36, but "trunk stable" means
+  // that the 2024Q* builds are tested with the _previous_ release's CTS.
+  if (android::base::GetIntProperty("ro.build.version.sdk", 0) == 35) {
+#if !defined(AID_CROS_EC)
+#define AID_CROS_EC 1094
+#endif
+    ids.erase(AID_CROS_EC);
+    expected_ids.erase(AID_CROS_EC);
+    if (getpwuid(AID_CROS_EC)) {
+      EXPECT_STREQ(getpwuid(AID_CROS_EC)->pw_name, "cros_ec");
+    }
+  }
+  // AID_MMD (1095) was added in API level 36, but "trunk stable" means
+  // that the 2024Q* builds are tested with the _previous_ release's CTS.
+  if (android::base::GetIntProperty("ro.build.version.sdk", 0) == 35) {
+#if !defined(AID_MMD)
+#define AID_MMD 1095
+#endif
+    ids.erase(AID_MMD);
+    expected_ids.erase(AID_MMD);
+    if (getpwuid(AID_MMD)) {
+      EXPECT_STREQ(getpwuid(AID_MMD)->pw_name, "mmd");
+    }
+  }
 
   EXPECT_EQ(expected_ids, ids) << return_differences();
 }
diff --git a/tests/headers/posix/signal_h.c b/tests/headers/posix/signal_h.c
index c2e544e..82751f4 100644
--- a/tests/headers/posix/signal_h.c
+++ b/tests/headers/posix/signal_h.c
@@ -63,6 +63,10 @@
   MACRO(SIGEV_SIGNAL);
   MACRO(SIGEV_THREAD);
 
+#if !defined(__GLIBC__)  // Our glibc is too old.
+  MACRO(SIG2STR_MAX);
+#endif
+
   TYPE(union sigval);
   STRUCT_MEMBER(union sigval, int, sival_int);
   STRUCT_MEMBER(union sigval, void*, sival_ptr);
@@ -205,6 +209,9 @@
   FUNCTION(pthread_kill, int (*f)(pthread_t, int));
   FUNCTION(pthread_sigmask, int (*f)(int, const sigset_t*, sigset_t*));
   FUNCTION(raise, int (*f)(int));
+#if !defined(__GLIBC__)  // Our glibc is too old.
+  FUNCTION(sig2str, int (*f)(int, char*));
+#endif
   FUNCTION(sigaction, int (*f)(int, const struct sigaction*, struct sigaction*));
   FUNCTION(sigaddset, int (*f)(sigset_t*, int));
   FUNCTION(sigaltstack, int (*f)(const stack_t*, stack_t*));
@@ -226,4 +233,7 @@
   FUNCTION(sigtimedwait, int (*f)(const sigset_t*, siginfo_t*, const struct timespec*));
   FUNCTION(sigwait, int (*f)(const sigset_t*, int*));
   FUNCTION(sigwaitinfo, int (*f)(const sigset_t*, siginfo_t*));
+#if !defined(__GLIBC__)  // Our glibc is too old.
+  FUNCTION(str2sig, int (*f)(const char*, int*));
+#endif
 }
diff --git a/tests/headers/posix/stdatomic_h.c b/tests/headers/posix/stdatomic_h.c
new file mode 100644
index 0000000..05be859
--- /dev/null
+++ b/tests/headers/posix/stdatomic_h.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2024 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 <stdatomic.h>
+
+#include "header_checks.h"
+
+static void stdatomic_h() {
+  TYPE(atomic_flag);
+  TYPE(atomic_bool);
+  TYPE(atomic_char);
+  TYPE(atomic_schar);
+  TYPE(atomic_uchar);
+  TYPE(atomic_short);
+  TYPE(atomic_ushort);
+  TYPE(atomic_int);
+  TYPE(atomic_uint);
+  TYPE(atomic_long);
+  TYPE(atomic_ulong);
+  TYPE(atomic_llong);
+  TYPE(atomic_ullong);
+#if !defined(__GLIBC__)
+  TYPE(atomic_char16_t);
+  TYPE(atomic_char32_t);
+#endif
+  TYPE(atomic_wchar_t);
+  TYPE(atomic_int_least8_t);
+  TYPE(atomic_uint_least8_t);
+  TYPE(atomic_int_least16_t);
+  TYPE(atomic_uint_least16_t);
+  TYPE(atomic_int_least32_t);
+  TYPE(atomic_uint_least32_t);
+  TYPE(atomic_int_least64_t);
+  TYPE(atomic_uint_least64_t);
+  TYPE(atomic_int_fast8_t);
+  TYPE(atomic_uint_fast8_t);
+  TYPE(atomic_int_fast16_t);
+  TYPE(atomic_uint_fast16_t);
+  TYPE(atomic_int_fast32_t);
+  TYPE(atomic_uint_fast32_t);
+  TYPE(atomic_int_fast64_t);
+  TYPE(atomic_uint_fast64_t);
+  TYPE(atomic_intptr_t);
+  TYPE(atomic_uintptr_t);
+  TYPE(atomic_size_t);
+  TYPE(atomic_ptrdiff_t);
+  TYPE(atomic_intmax_t);
+  TYPE(atomic_uintmax_t);
+
+  memory_order m1 = memory_order_relaxed;
+  memory_order m2 = memory_order_consume;
+  memory_order m3 = memory_order_acquire;
+  memory_order m4 = memory_order_release;
+  memory_order m5 = memory_order_acq_rel;
+  memory_order m6 = memory_order_seq_cst;
+
+  MACRO(ATOMIC_BOOL_LOCK_FREE);
+  MACRO(ATOMIC_CHAR_LOCK_FREE);
+  MACRO(ATOMIC_CHAR16_T_LOCK_FREE);
+  MACRO(ATOMIC_CHAR32_T_LOCK_FREE);
+  MACRO(ATOMIC_WCHAR_T_LOCK_FREE);
+  MACRO(ATOMIC_SHORT_LOCK_FREE);
+  MACRO(ATOMIC_INT_LOCK_FREE);
+  MACRO(ATOMIC_LONG_LOCK_FREE);
+  MACRO(ATOMIC_LLONG_LOCK_FREE);
+  MACRO(ATOMIC_POINTER_LOCK_FREE);
+
+  atomic_flag f = ATOMIC_FLAG_INIT;
+  atomic_int i = ATOMIC_VAR_INIT(123);
+
+  // TODO: remove this #if after the next toolchain update (http://b/374104004).
+#if !defined(__GLIBC__)
+  i = kill_dependency(i);
+#endif
+
+#if !defined(atomic_compare_exchange_strong)
+#error atomic_compare_exchange_strong
+#endif
+#if !defined(atomic_compare_exchange_strong_explicit)
+#error atomic_compare_exchange_strong_explicit
+#endif
+#if !defined(atomic_compare_exchange_weak)
+#error atomic_compare_exchange_weak
+#endif
+#if !defined(atomic_compare_exchange_weak_explicit)
+#error atomic_compare_exchange_weak_explicit
+#endif
+#if !defined(atomic_exchange)
+#error atomic_exchange
+#endif
+#if !defined(atomic_exchange_explicit)
+#error atomic_exchange_explicit
+#endif
+#if !defined(atomic_fetch_add)
+#error atomic_fetch_add
+#endif
+#if !defined(atomic_fetch_add_explicit)
+#error atomic_fetch_add_explicit
+#endif
+#if !defined(atomic_fetch_and)
+#error atomic_fetch_and
+#endif
+#if !defined(atomic_fetch_and_explicit)
+#error atomic_fetch_and_explicit
+#endif
+#if !defined(atomic_fetch_or)
+#error atomic_fetch_or
+#endif
+#if !defined(atomic_fetch_or_explicit)
+#error atomic_fetch_or_explicit
+#endif
+#if !defined(atomic_fetch_sub)
+#error atomic_fetch_sub
+#endif
+#if !defined(atomic_fetch_sub_explicit)
+#error atomic_fetch_sub_explicit
+#endif
+#if !defined(atomic_fetch_xor)
+#error atomic_fetch_xor
+#endif
+#if !defined(atomic_fetch_xor_explicit)
+#error atomic_fetch_xor_explicit
+#endif
+#if !defined(atomic_init)
+#error atomic_init
+#endif
+#if !defined(atomic_is_lock_free)
+#error atomic_is_lock_free
+#endif
+#if !defined(atomic_load)
+#error atomic_load
+#endif
+#if !defined(atomic_load_explicit)
+#error atomic_load_explicit
+#endif
+#if !defined(atomic_store)
+#error atomic_store
+#endif
+#if !defined(atomic_store_explicit)
+#error atomic_store_explicit
+#endif
+
+  FUNCTION(atomic_flag_clear, void (*f)(volatile atomic_flag*));
+  FUNCTION(atomic_flag_clear_explicit, void (*f)(volatile atomic_flag*, memory_order));
+  FUNCTION(atomic_flag_test_and_set, bool (*f)(volatile atomic_flag*));
+  FUNCTION(atomic_flag_test_and_set_explicit, bool (*f)(volatile atomic_flag*, memory_order));
+
+  FUNCTION(atomic_signal_fence, void (*f)(memory_order));
+  FUNCTION(atomic_thread_fence, void (*f)(memory_order));
+}
diff --git a/tests/headers/posix/stdbool_h.c b/tests/headers/posix/stdbool_h.c
index f891a73..830c33c 100644
--- a/tests/headers/posix/stdbool_h.c
+++ b/tests/headers/posix/stdbool_h.c
@@ -31,10 +31,8 @@
 #include "header_checks.h"
 
 static void stdbool_h() {
-#if !defined(bool)
-#error bool
-#endif
-  MACRO_VALUE(true, 1);
-  MACRO_VALUE(false, 0);
+  TYPE(bool);
+  bool t = true;
+  bool f = false;
   MACRO_VALUE(__bool_true_false_are_defined, 1);
 }
diff --git a/tests/headers/posix/stdlib_h.c b/tests/headers/posix/stdlib_h.c
index 52580cf..95769b4 100644
--- a/tests/headers/posix/stdlib_h.c
+++ b/tests/headers/posix/stdlib_h.c
@@ -112,6 +112,9 @@
   FUNCTION(ptsname, char* (*f)(int));
   FUNCTION(putenv, int (*f)(char*));
   FUNCTION(qsort, void (*f)(void*, size_t, size_t, int (*)(const void*, const void*)));
+#if !defined(__GLIBC__) // Our glibc is too old.
+  FUNCTION(qsort_r, void (*f)(void*, size_t, size_t, int (*)(const void*, const void*, void*), void*));
+#endif
   FUNCTION(rand, int (*f)(void));
   FUNCTION(rand_r, int (*f)(unsigned*));
   FUNCTION(random, long (*f)(void));
diff --git a/tests/headers/posix/unistd_h.c b/tests/headers/posix/unistd_h.c
index 0b2cee5..f66609d 100644
--- a/tests/headers/posix/unistd_h.c
+++ b/tests/headers/posix/unistd_h.c
@@ -331,6 +331,9 @@
   FUNCTION(fdatasync, int (*f)(int));
   FUNCTION(fexecve, int (*f)(int, char* const[], char* const[]));
   FUNCTION(fork, pid_t (*f)(void));
+#if !defined(__GLIBC__) // Our glibc is too old.
+  FUNCTION(_Fork, pid_t (*f)(void));
+#endif
   FUNCTION(fpathconf, long (*f)(int, int));
   FUNCTION(fsync, int (*f)(int));
   FUNCTION(ftruncate, int (*f)(int, off_t));
diff --git a/tests/hwasan_test.cpp b/tests/hwasan_test.cpp
index e32534e..ddf84cb 100644
--- a/tests/hwasan_test.cpp
+++ b/tests/hwasan_test.cpp
@@ -36,7 +36,18 @@
 
 using HwasanDeathTest = SilentDeathTest;
 
-TEST_F(HwasanDeathTest, UseAfterFree) {
+
+#ifdef HWASAN_TEST_STATIC
+#define MAYBE_DlopenAbsolutePath DISABLED_DlopenAbsolutePath
+// TODO(fmayer): figure out why uaf is misclassified as out of bounds for
+// static executables.
+#define MAYBE_UseAfterFree DISABLED_UseAfterFree
+#else
+#define MAYBE_DlopenAbsolutePath DlopenAbsolutePath
+#define MAYBE_UseAfterFree UseAfterFree
+#endif
+
+TEST_F(HwasanDeathTest, MAYBE_UseAfterFree) {
   EXPECT_DEATH(
       {
         void* m = malloc(1);
@@ -59,7 +70,7 @@
 }
 
 // Check whether dlopen of /foo/bar.so checks /foo/hwasan/bar.so first.
-TEST(HwasanTest, DlopenAbsolutePath) {
+TEST(HwasanTest, MAYBE_DlopenAbsolutePath) {
   std::string path = android::base::GetExecutableDirectory() + "/libtest_simple_hwasan.so";
   ASSERT_EQ(0, access(path.c_str(), F_OK));  // Verify test setup.
   std::string hwasan_path =
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index fc7fd40..5b86e78 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -48,6 +48,16 @@
 }
 
 // -----------------------------------------------------------------------------
+// Test library ELFs for linker page size related tests
+// -----------------------------------------------------------------------------
+cc_test_library {
+    name: "libtest_elf_max_page_size_4kib",
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["elf_max_page_size.c"],
+    ldflags: ["-z max-page-size=0x1000"],
+}
+
+// -----------------------------------------------------------------------------
 // Libraries and helper binaries for ELF TLS
 // -----------------------------------------------------------------------------
 cc_test_library {
@@ -1852,7 +1862,7 @@
         " cp $(in) $(genDir)/zipdir/libdir/ &&" +
         " touch $(genDir)/zipdir/empty_file.txt &&" +
         " $(location soong_zip) -o $(out).unaligned -L 0 -C $(genDir)/zipdir -D $(genDir)/zipdir &&" +
-        " $(location bionic_tests_zipalign) 4096 $(out).unaligned $(out)",
+        " $(location bionic_tests_zipalign) 16384 $(out).unaligned $(out)",
 
 }
 
@@ -1891,5 +1901,91 @@
         " cp $(location :libtest_dt_runpath_y) $(genDir)/zipdir/libdir/dt_runpath_y/$$PRIVATE_LIB_OR_LIB64 &&" +
         " touch $(genDir)/zipdir/empty_file.txt &&" +
         " $(location soong_zip) -o $(out).unaligned -L 0 -C $(genDir)/zipdir -D $(genDir)/zipdir &&" +
-        " $(location bionic_tests_zipalign) 4096 $(out).unaligned $(out)",
+        " $(location bionic_tests_zipalign) 16384 $(out).unaligned $(out)",
+}
+
+cc_defaults {
+    name: "memtag_globals_defaults",
+    defaults: [
+        "bionic_testlib_defaults",
+        "bionic_targets_only"
+    ],
+    cflags: [
+        "-Wno-array-bounds",
+        "-Wno-unused-variable",
+    ],
+    header_libs: ["bionic_libc_platform_headers"],
+    sanitize: {
+        hwaddress: false,
+        memtag_heap: true,
+        memtag_globals: true,
+        diag: {
+            memtag_heap: true,
+        }
+    },
+}
+
+cc_test_library {
+    name: "memtag_globals_dso",
+    defaults: [ "memtag_globals_defaults" ],
+    srcs: ["memtag_globals_dso.cpp"],
+}
+
+cc_test {
+    name: "memtag_globals_binary",
+    defaults: [ "memtag_globals_defaults" ],
+    srcs: ["memtag_globals_binary.cpp"],
+    shared_libs: [ "memtag_globals_dso" ],
+    // This binary is used in the bionic-unit-tests as a data dependency, and is
+    // in the same folder as memtag_globals_dso. But, the default cc_test rules
+    // make this binary (when just explicitly built and shoved in
+    // /data/nativetest64/) end up in a subfolder called
+    // 'memtag_globals_binary'. When this happens, the explicit build fails to
+    // find the DSO because the default rpath is just ${ORIGIN}, and because we
+    // want this to be usable both from bionic-unit-tests and explicit builds,
+    // let's just not put it in a subdirectory.
+    no_named_install_directory: true,
+}
+
+cc_test {
+    name: "memtag_globals_binary_static",
+    defaults: [ "memtag_globals_defaults" ],
+    srcs: ["memtag_globals_binary.cpp"],
+    static_libs: [ "memtag_globals_dso" ],
+    no_named_install_directory: true,
+    static_executable: true,
+}
+
+// This is a regression test for b/314038442, where binaries built *without* MTE
+// globals would have out-of-bounds RELR relocations, which where then `ldg`'d,
+// which resulted in linker crashes.
+cc_test {
+  name: "mte_globals_relr_regression_test_b_314038442",
+  defaults: [
+        "bionic_testlib_defaults",
+        "bionic_targets_only"
+    ],
+    cflags: [ "-Wno-array-bounds" ],
+    ldflags: [ "-Wl,--pack-dyn-relocs=relr" ],
+    srcs: ["mte_globals_relr_regression_test_b_314038442.cpp"],
+    no_named_install_directory: true,
+    sanitize: {
+        memtag_globals: false,
+    },
+}
+
+// Same test as above, but also for MTE globals, just for the sake of it.
+cc_test {
+  name: "mte_globals_relr_regression_test_b_314038442_mte",
+  defaults: [
+        "bionic_testlib_defaults",
+        "bionic_targets_only"
+    ],
+    cflags: [ "-Wno-array-bounds" ],
+    ldflags: [ "-Wl,--pack-dyn-relocs=relr" ],
+    srcs: ["mte_globals_relr_regression_test_b_314038442.cpp"],
+    no_named_install_directory: true,
+    sanitize: {
+      memtag_globals: true,
+    },
 }
diff --git a/libc/bionic/time_l.cpp b/tests/libs/elf_max_page_size.c
similarity index 74%
copy from libc/bionic/time_l.cpp
copy to tests/libs/elf_max_page_size.c
index e5fa9a5..24c7e89 100644
--- a/libc/bionic/time_l.cpp
+++ b/tests/libs/elf_max_page_size.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,9 +26,25 @@
  * SUCH DAMAGE.
  */
 
-#include <time.h>
-//#include <xlocale.h>
+#include "elf_max_page_size.h"
 
-char* strptime_l(const char* buf, const char* fmt, struct tm* tm, locale_t) {
-  return strptime(buf, fmt, tm);
+const int ro0 = RO0;
+const int ro1 = RO1;
+int rw0 = RW0;
+
+/* Force some padding alignment */
+int rw1 __attribute__((aligned(0x10000))) = RW1;
+
+int bss0, bss1;
+
+int* const prw0 = &rw0;
+
+int loader_test_func(void) {
+  rw0 += RW0_INCREMENT;
+  rw1 += RW1_INCREMENT;
+
+  bss0 += BSS0_INCREMENT;
+  bss1 += BSS1_INCREMENT;
+
+  return ro0 + ro1 + rw0 + rw1 + bss0 + bss1 + *prw0;
 }
diff --git a/libc/arch-x86/generic/string/wcscat.c b/tests/libs/elf_max_page_size.h
similarity index 72%
copy from libc/arch-x86/generic/string/wcscat.c
copy to tests/libs/elf_max_page_size.h
index a102551..846a8b6 100644
--- a/libc/arch-x86/generic/string/wcscat.c
+++ b/tests/libs/elf_max_page_size.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,5 +26,20 @@
  * SUCH DAMAGE.
  */
 
-#define wcscat wcscat_freebsd
-#include <upstream-freebsd/lib/libc/string/wcscat.c>
+#define RO0 23
+#define RO1 234
+#define RW0 2345
+#define RW1 23456
+#define BSS0 0
+#define BSS1 0
+
+#define RW0_INCREMENT 12
+#define RW1_INCREMENT 123
+#define BSS0_INCREMENT 1234
+#define BSS1_INCREMENT 12345
+
+#define TEST_RESULT_BASE (RO0 + RO1 + RW0 + RW1 + BSS0 + BSS1 + RW0)
+#define TEST_RESULT_INCREMENT \
+  (RW0_INCREMENT + RW1_INCREMENT + BSS0_INCREMENT + BSS1_INCREMENT + RW0_INCREMENT)
+
+typedef int (*loader_test_func_t)(void);
diff --git a/libc/arch-x86/generic/string/wcscat.c b/tests/libs/memtag_globals.h
similarity index 67%
copy from libc/arch-x86/generic/string/wcscat.c
copy to tests/libs/memtag_globals.h
index a102551..a03abae 100644
--- a/libc/arch-x86/generic/string/wcscat.c
+++ b/tests/libs/memtag_globals.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,5 +26,18 @@
  * SUCH DAMAGE.
  */
 
-#define wcscat wcscat_freebsd
-#include <upstream-freebsd/lib/libc/string/wcscat.c>
+#include <utility>
+#include <vector>
+
+void check_tagged(const void* a);
+void check_untagged(const void* a);
+void check_matching_tags(const void* a, const void* b);
+void check_eq(const void* a, const void* b);
+
+void dso_check_assertions(bool enforce_tagged);
+void dso_print_variables();
+
+void print_variable_address(const char* name, const void* ptr);
+void print_variables(const char* header,
+                     const std::vector<std::pair<const char*, const void*>>& tagged_variables,
+                     const std::vector<std::pair<const char*, const void*>>& untagged_variables);
diff --git a/tests/libs/memtag_globals_binary.cpp b/tests/libs/memtag_globals_binary.cpp
new file mode 100644
index 0000000..9248728
--- /dev/null
+++ b/tests/libs/memtag_globals_binary.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <string>
+#include <vector>
+
+#include "memtag_globals.h"
+
+// Adapted from the LLD test suite: lld/test/ELF/Inputs/aarch64-memtag-globals.s
+
+/// Global variables defined here, of various semantics.
+char global[30] = {};
+__attribute__((no_sanitize("memtag"))) int global_untagged = 0;
+const int const_global = 0;
+static const int hidden_const_global = 0;
+static char hidden_global[12] = {};
+__attribute__((visibility("hidden"))) int hidden_attr_global = 0;
+__attribute__((visibility("hidden"))) const int hidden_attr_const_global = 0;
+
+/// Should be untagged.
+__thread int tls_global;
+__thread static int hidden_tls_global;
+
+/// Tagged, from the other file.
+extern int global_extern;
+/// Untagged, from the other file.
+extern __attribute__((no_sanitize("memtag"))) int global_extern_untagged;
+/// Tagged here, but untagged in the definition found in the sister objfile
+/// (explicitly).
+extern int global_extern_untagged_definition_but_tagged_import;
+
+/// ABS64 relocations. Also, forces symtab entries for local and external
+/// globals.
+char* pointer_to_global = &global[0];
+char* pointer_inside_global = &global[17];
+char* pointer_to_global_end = &global[30];
+char* pointer_past_global_end = &global[48];
+int* pointer_to_global_untagged = &global_untagged;
+const int* pointer_to_const_global = &const_global;
+/// RELATIVE relocations.
+const int* pointer_to_hidden_const_global = &hidden_const_global;
+char* pointer_to_hidden_global = &hidden_global[0];
+int* pointer_to_hidden_attr_global = &hidden_attr_global;
+const int* pointer_to_hidden_attr_const_global = &hidden_attr_const_global;
+/// RELATIVE relocations with special AArch64 MemtagABI semantics, with the
+/// offset ('12' or '16') encoded in the place.
+char* pointer_to_hidden_global_end = &hidden_global[12];
+char* pointer_past_hidden_global_end = &hidden_global[16];
+/// ABS64 relocations.
+int* pointer_to_global_extern = &global_extern;
+int* pointer_to_global_extern_untagged = &global_extern_untagged;
+int* pointer_to_global_extern_untagged_definition_but_tagged_import =
+    &global_extern_untagged_definition_but_tagged_import;
+
+// Force materialization of these globals into the symtab.
+int* get_address_to_tls_global() {
+  return &tls_global;
+}
+int* get_address_to_hidden_tls_global() {
+  return &hidden_tls_global;
+}
+
+static const std::vector<std::pair<const char*, const void*>>& get_expected_tagged_vars() {
+  static std::vector<std::pair<const char*, const void*>> expected_tagged_vars = {
+      {"global", &global},
+      {"pointer_inside_global", pointer_inside_global},
+      {"pointer_to_global_end", pointer_to_global_end},
+      {"pointer_past_global_end", pointer_past_global_end},
+      {"hidden_global", &hidden_global},
+      {"hidden_attr_global", &hidden_attr_global},
+      {"global_extern", &global_extern},
+  };
+  return expected_tagged_vars;
+}
+
+static const std::vector<std::pair<const char*, const void*>>& get_expected_untagged_vars() {
+  static std::vector<std::pair<const char*, const void*>> expected_untagged_vars = {
+      {"global_extern_untagged", &global_extern_untagged},
+      {"global_extern_untagged_definition_but_tagged_import",
+       &global_extern_untagged_definition_but_tagged_import},
+      {"global_untagged", &global_untagged},
+      {"const_global", &const_global},
+      {"hidden_const_global", &hidden_const_global},
+      {"hidden_attr_const_global", &hidden_attr_const_global},
+      {"tls_global", &tls_global},
+      {"hidden_tls_global", &hidden_tls_global},
+  };
+  return expected_untagged_vars;
+}
+
+void exe_print_variables() {
+  print_variables("  Variables accessible from the binary:\n", get_expected_tagged_vars(),
+                  get_expected_untagged_vars());
+}
+
+// Dump the addresses of the global variables to stderr
+void dso_print();
+void dso_print_others();
+
+void exe_check_assertions(bool check_pointers_are_tagged) {
+  // Check that non-const variables are writeable.
+  *pointer_to_global = 0;
+  *pointer_inside_global = 0;
+  *(pointer_to_global_end - 1) = 0;
+  *pointer_to_global_untagged = 0;
+  *pointer_to_hidden_global = 0;
+  *pointer_to_hidden_attr_global = 0;
+  *(pointer_to_hidden_global_end - 1) = 0;
+  *pointer_to_global_extern = 0;
+  *pointer_to_global_extern_untagged = 0;
+  *pointer_to_global_extern_untagged_definition_but_tagged_import = 0;
+
+  if (check_pointers_are_tagged) {
+    for (const auto& [_, pointer] : get_expected_tagged_vars()) {
+      check_tagged(pointer);
+    }
+  }
+
+  for (const auto& [_, pointer] : get_expected_untagged_vars()) {
+    check_untagged(pointer);
+  }
+
+  check_matching_tags(pointer_to_global, pointer_inside_global);
+  check_matching_tags(pointer_to_global, pointer_to_global_end);
+  check_matching_tags(pointer_to_global, pointer_past_global_end);
+  check_eq(pointer_inside_global, pointer_to_global + 17);
+  check_eq(pointer_to_global_end, pointer_to_global + 30);
+  check_eq(pointer_past_global_end, pointer_to_global + 48);
+
+  check_matching_tags(pointer_to_hidden_global, pointer_to_hidden_global_end);
+  check_matching_tags(pointer_to_hidden_global, pointer_past_hidden_global_end);
+  check_eq(pointer_to_hidden_global_end, pointer_to_hidden_global + 12);
+  check_eq(pointer_past_hidden_global_end, pointer_to_hidden_global + 16);
+}
+
+void crash() {
+  *pointer_past_global_end = 0;
+}
+
+int main(int argc, char** argv) {
+  bool check_pointers_are_tagged = false;
+  // For an MTE-capable device, provide argv[1] == '1' to enable the assertions
+  // that pointers should be tagged.
+  if (argc >= 2 && argv[1][0] == '1') {
+    check_pointers_are_tagged = true;
+  }
+
+  char* heap_ptr = static_cast<char*>(malloc(1));
+  print_variable_address("heap address", heap_ptr);
+  *heap_ptr = 0;
+  if (check_pointers_are_tagged) check_tagged(heap_ptr);
+  free(heap_ptr);
+
+  exe_print_variables();
+  dso_print_variables();
+
+  exe_check_assertions(check_pointers_are_tagged);
+  dso_check_assertions(check_pointers_are_tagged);
+
+  printf("Assertions were passed. Now doing a global-buffer-overflow.\n");
+  fflush(stdout);
+  crash();
+  printf("global-buffer-overflow went uncaught.\n");
+  return 0;
+}
diff --git a/tests/libs/memtag_globals_dso.cpp b/tests/libs/memtag_globals_dso.cpp
new file mode 100644
index 0000000..9ed264e
--- /dev/null
+++ b/tests/libs/memtag_globals_dso.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <vector>
+
+#include "memtag_globals.h"
+
+// Adapted from the LLD test suite: lld/test/ELF/Inputs/aarch64-memtag-globals.s
+
+int global_extern;
+static int global_extern_hidden;
+__attribute__((no_sanitize("memtag"))) int global_extern_untagged;
+__attribute__((no_sanitize("memtag"))) int global_extern_untagged_definition_but_tagged_import;
+
+void assertion_failure() {
+  exit(1);
+}
+
+void check_tagged(const void* a) {
+  uintptr_t a_uptr = reinterpret_cast<uintptr_t>(a);
+#if defined(__aarch64__)
+  if ((a_uptr >> 56) == 0) {
+    fprintf(stderr, "**********************************\n");
+    fprintf(stderr, "Failed assertion:\n");
+    fprintf(stderr, "  tag(0x%zx) != 0\n", a_uptr);
+    fprintf(stderr, "**********************************\n");
+
+    assertion_failure();
+  }
+#endif  // defined(__aarch64__)
+}
+
+void check_untagged(const void* a) {
+  uintptr_t a_uptr = reinterpret_cast<uintptr_t>(a);
+#if defined(__aarch64__)
+  if ((a_uptr >> 56) != 0) {
+    fprintf(stderr, "**********************************\n");
+    fprintf(stderr, "Failed assertion:\n");
+    fprintf(stderr, "  tag(0x%zx) == 0\n", a_uptr);
+    fprintf(stderr, "**********************************\n");
+
+    assertion_failure();
+  }
+#endif  // defined(__aarch64__)
+}
+
+void check_matching_tags(const void* a, const void* b) {
+  uintptr_t a_uptr = reinterpret_cast<uintptr_t>(a);
+  uintptr_t b_uptr = reinterpret_cast<uintptr_t>(b);
+#if defined(__aarch64__)
+  if (a_uptr >> 56 != b_uptr >> 56) {
+    fprintf(stderr, "**********************************\n");
+    fprintf(stderr, "Failed assertion:\n");
+    fprintf(stderr, "  tag(0x%zx) != tag(0x%zx)\n", a_uptr, b_uptr);
+    fprintf(stderr, "**********************************\n");
+
+    assertion_failure();
+  }
+#endif  // defined(__aarch64__)
+}
+
+void check_eq(const void* a, const void* b) {
+  if (a != b) {
+    fprintf(stderr, "**********************************\n");
+    fprintf(stderr, "Failed assertion:\n");
+    fprintf(stderr, "  %p != %p\n", a, b);
+    fprintf(stderr, "**********************************\n");
+
+    assertion_failure();
+  }
+}
+
+#define LONGEST_VARIABLE_NAME "51"
+void print_variable_address(const char* name, const void* ptr) {
+  printf("%" LONGEST_VARIABLE_NAME "s: %16p\n", name, ptr);
+}
+
+static const std::vector<std::pair<const char*, const void*>>& get_expected_tagged_vars() {
+  static std::vector<std::pair<const char*, const void*>> expected_tagged_vars = {
+      {"global_extern", &global_extern},
+      {"global_extern_hidden", &global_extern_hidden},
+  };
+  return expected_tagged_vars;
+}
+
+static const std::vector<std::pair<const char*, const void*>>& get_expected_untagged_vars() {
+  static std::vector<std::pair<const char*, const void*>> expected_untagged_vars = {
+      {"global_extern_untagged", &global_extern_untagged},
+      {"global_extern_untagged_definition_but_tagged_import",
+       &global_extern_untagged_definition_but_tagged_import},
+  };
+  return expected_untagged_vars;
+}
+
+void dso_print_variables() {
+  print_variables("  Variables declared in the DSO:\n", get_expected_tagged_vars(),
+                  get_expected_untagged_vars());
+}
+
+void print_variables(const char* header,
+                     const std::vector<std::pair<const char*, const void*>>& tagged_variables,
+                     const std::vector<std::pair<const char*, const void*>>& untagged_variables) {
+  printf("==========================================================\n");
+  printf("%s", header);
+  printf("==========================================================\n");
+  printf(" Variables expected to be tagged:\n");
+  printf("----------------------------------------------------------\n");
+  for (const auto& [name, pointer] : tagged_variables) {
+    print_variable_address(name, pointer);
+  }
+
+  printf("\n----------------------------------------------------------\n");
+  printf(" Variables expected to be untagged:\n");
+  printf("----------------------------------------------------------\n");
+  for (const auto& [name, pointer] : untagged_variables) {
+    print_variable_address(name, pointer);
+  }
+  printf("\n");
+}
+
+void dso_check_assertions(bool check_pointers_are_tagged) {
+  // Check that non-const variables are writeable.
+  global_extern = 0;
+  global_extern_hidden = 0;
+  global_extern_untagged = 0;
+  global_extern_untagged_definition_but_tagged_import = 0;
+
+  if (check_pointers_are_tagged) {
+    for (const auto& [_, pointer] : get_expected_tagged_vars()) {
+      check_tagged(pointer);
+    }
+  }
+
+  for (const auto& [_, pointer] : get_expected_untagged_vars()) {
+    check_untagged(pointer);
+  }
+}
diff --git a/libc/arch-arm/static_function_dispatch.S b/tests/libs/mte_globals_relr_regression_test_b_314038442.cpp
similarity index 63%
rename from libc/arch-arm/static_function_dispatch.S
rename to tests/libs/mte_globals_relr_regression_test_b_314038442.cpp
index a8235c2..20bbba9 100644
--- a/libc/arch-arm/static_function_dispatch.S
+++ b/tests/libs/mte_globals_relr_regression_test_b_314038442.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,21 +26,30 @@
  * SUCH DAMAGE.
  */
 
-#include <private/bionic_asm.h>
+#include <stdint.h>
+#include <stdio.h>
 
-#define FUNCTION_DELEGATE(name, impl) \
-ENTRY(name); \
-    b impl; \
-END(name)
+static volatile char array[0x10000];
+volatile char* volatile oob_ptr = &array[0x111111111];
 
-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(__strcpy_chk, __strcpy_chk_generic)
-FUNCTION_DELEGATE(stpcpy, stpcpy_generic)
-FUNCTION_DELEGATE(strcat, strcat_generic)
-FUNCTION_DELEGATE(__strcat_chk, __strcat_chk_generic)
-FUNCTION_DELEGATE(strcmp, strcmp_generic)
-FUNCTION_DELEGATE(strlen, strlen_generic)
+unsigned char get_tag(__attribute__((unused)) volatile void* ptr) {
+#if defined(__aarch64__)
+  return static_cast<unsigned char>(reinterpret_cast<uintptr_t>(ptr) >> 56) & 0xf;
+#else   // !defined(__aarch64__)
+  return 0;
+#endif  // defined(__aarch64__)
+}
+
+int main() {
+  printf("Program loaded successfully. %p %p. ", array, oob_ptr);
+  if (get_tag(array) != get_tag(oob_ptr)) {
+    printf("Tags are mismatched!\n");
+    return 1;
+  }
+  if (get_tag(array) == 0) {
+    printf("Tags are zero!\n");
+  } else {
+    printf("Tags are non-zero\n");
+  }
+  return 0;
+}
diff --git a/tests/libs/segment_gap_outer.cpp b/tests/libs/segment_gap_outer.cpp
index 3ba90d0..0328a99 100644
--- a/tests/libs/segment_gap_outer.cpp
+++ b/tests/libs/segment_gap_outer.cpp
@@ -1,6 +1,7 @@
 #include <android/dlext.h>
 #include <dlfcn.h>
 #include <stdlib.h>
+#include <unistd.h>
 
 extern "C" void __attribute__((section(".custom_text"))) text_before_start_of_gap() {}
 char __attribute__((section(".custom_bss"))) end_of_gap[0x1000];
@@ -10,8 +11,9 @@
   info.flags = ANDROID_DLEXT_RESERVED_ADDRESS;
 
   char* start_of_gap =
-      reinterpret_cast<char*>(reinterpret_cast<uintptr_t>(text_before_start_of_gap) & ~0xfffull) +
-      0x1000;
+      reinterpret_cast<char*>(
+          (reinterpret_cast<uintptr_t>(text_before_start_of_gap) &
+           ~(sysconf(_SC_PAGESIZE) - 1)) + sysconf(_SC_PAGESIZE));
   info.reserved_addr = start_of_gap;
   info.reserved_size = end_of_gap - start_of_gap;
 
diff --git a/tests/libs/segment_gap_outer.lds b/tests/libs/segment_gap_outer.lds
index 527f29e..758b6bc 100644
--- a/tests/libs/segment_gap_outer.lds
+++ b/tests/libs/segment_gap_outer.lds
@@ -3,17 +3,17 @@
   # appropriate alignment between them.
   . = SIZEOF_HEADERS;
   .rodata : {*(.rodata .rodata.*)}
-  . = ALIGN(0x1000);
+  . = ALIGN(CONSTANT (MAXPAGESIZE));
   .text : {*(.text .text.*)}
-  . = ALIGN(0x1000);
+  . = ALIGN(CONSTANT (MAXPAGESIZE));
   .dynamic : {*(.dynamic)}
-  . = ALIGN(0x1000);
+  . = ALIGN(CONSTANT (MAXPAGESIZE));
   .data : {*(.data .data.*)}
   .bss : {*(.bss .bss.*)}
 
   # Now create the gap. We need a text segment first to prevent the linker from
   # merging .bss with .custom_bss.
-  . = ALIGN(0x1000);
+  . = ALIGN(CONSTANT (MAXPAGESIZE));
   .custom_text : {
     *(.custom_text);
   }
diff --git a/tests/malloc_stress_test.cpp b/tests/malloc_stress_test.cpp
index b5b06ab..00f5919 100644
--- a/tests/malloc_stress_test.cpp
+++ b/tests/malloc_stress_test.cpp
@@ -27,10 +27,58 @@
 #include <thread>
 #include <vector>
 
-#include <android-base/strings.h>
 #if defined(__BIONIC__)
 #include <meminfo/procmeminfo.h>
 #include <procinfo/process_map.h>
+
+#include <log/log.h>
+#include <log/log_read.h>
+#endif
+
+#if defined(__BIONIC__)
+static void PrintLogStats(uint64_t& last_time) {
+  logger_list* logger =
+      android_logger_list_open(android_name_to_log_id("main"), ANDROID_LOG_NONBLOCK, 0, getpid());
+  if (logger == nullptr) {
+    printf("Failed to open log for main\n");
+    return;
+  }
+
+  uint64_t last_message_time = last_time;
+  while (true) {
+    log_msg entry;
+    ssize_t retval = android_logger_list_read(logger, &entry);
+    if (retval == 0) {
+      break;
+    }
+    if (retval < 0) {
+      if (retval == -EINTR) {
+        continue;
+      }
+      // EAGAIN means there is nothing left to read when ANDROID_LOG_NONBLOCK is set.
+      if (retval != -EAGAIN) {
+        printf("Failed to read log entry: %s\n", strerrordesc_np(retval));
+      }
+      break;
+    }
+    if (entry.msg() == nullptr) {
+      continue;
+    }
+    // Only print allocator tagged log entries.
+    std::string_view tag(entry.msg() + 1);
+    if (tag != "scudo" && tag != "jemalloc") {
+      continue;
+    }
+    if (entry.nsec() > last_time) {
+      printf("  %s\n", &tag.back() + 2);
+      // Only update the last time outside this loop just in case two or more
+      // messages have the same timestamp.
+      last_message_time = entry.nsec();
+    }
+  }
+  android_logger_list_close(logger);
+  last_time = last_message_time;
+}
 #endif
 
 TEST(malloc_stress, multiple_threads_forever) {
@@ -45,6 +93,8 @@
 #endif
   uint64_t mallinfo_min = UINT64_MAX;
   uint64_t mallinfo_max = 0;
+
+  uint64_t last_message_time = 0;
   for (size_t i = 0; ; i++) {
     printf("Pass %zu\n", i);
 
@@ -74,8 +124,8 @@
     uint64_t rss_bytes = 0;
     uint64_t vss_bytes = 0;
     for (auto& vma : maps) {
-      if (vma.name == "[anon:libc_malloc]" || android::base::StartsWith(vma.name, "[anon:scudo:") ||
-          android::base::StartsWith(vma.name, "[anon:GWP-ASan")) {
+      if (vma.name == "[anon:libc_malloc]" || vma.name.starts_with("[anon:scudo:") ||
+          vma.name.starts_with("[anon:GWP-ASan")) {
         android::meminfo::Vma update_vma(vma);
         ASSERT_TRUE(proc_mem.FillInVmaStats(update_vma));
         rss_bytes += update_vma.usage.rss;
@@ -112,5 +162,15 @@
     printf("Allocated memory %zu %0.2fMB\n", mallinfo_bytes, mallinfo_bytes / (1024.0 * 1024.0));
     printf("  Min %" PRIu64 " %0.2fMB\n", mallinfo_min, mallinfo_min / (1024.0 * 1024.0));
     printf("  Max %" PRIu64 " %0.2fMB\n", mallinfo_max, mallinfo_max / (1024.0 * 1024.0));
+
+#if defined(__BIONIC__)
+    if (((i + 1) % 100) == 0) {
+      // Send native allocator stats to the log
+      mallopt(M_LOG_STATS, 0);
+
+      printf("Log stats:\n");
+      PrintLogStats(last_message_time);
+    }
+#endif
   }
 }
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index a5916d3..3f1ba79 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -47,6 +47,7 @@
 #include <android-base/file.h>
 #include <android-base/test_utils.h>
 
+#include "DoNotOptimize.h"
 #include "utils.h"
 
 #if defined(__BIONIC__)
@@ -1627,6 +1628,7 @@
 #if !defined(__BIONIC__)
   GTEST_SKIP() << "Only valid on bionic";
 #endif
+  SKIP_WITH_HWASAN << "Only test system allocator, not hwasan allocator.";
 
   if (IsLowRamDevice()) {
     GTEST_SKIP() << "Skipped on low memory devices.";
@@ -1657,6 +1659,7 @@
 #if !defined(__BIONIC__)
   GTEST_SKIP() << "Only valid on bionic";
 #endif
+  SKIP_WITH_HWASAN << "Only test system allocator, not hwasan allocator.";
 
   if (IsLowRamDevice()) {
     GTEST_SKIP() << "Skipped on low memory devices.";
@@ -1687,6 +1690,7 @@
 #if !defined(__BIONIC__)
   GTEST_SKIP() << "Only valid on bionic";
 #endif
+  SKIP_WITH_HWASAN << "Only test system allocator, not hwasan allocator.";
 
   if (IsLowRamDevice()) {
     GTEST_SKIP() << "Skipped on low memory devices.";
diff --git a/tests/memtag_globals_test.cpp b/tests/memtag_globals_test.cpp
new file mode 100644
index 0000000..ff93e7b
--- /dev/null
+++ b/tests/memtag_globals_test.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <gtest/gtest.h>
+
+#if defined(__BIONIC__)
+#include "gtest_globals.h"
+#include "utils.h"
+#endif  // defined(__BIONIC__)
+
+#include <android-base/test_utils.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string>
+#include <tuple>
+
+#include "platform/bionic/mte.h"
+
+class MemtagGlobalsTest : public testing::TestWithParam<bool> {};
+
+TEST_P(MemtagGlobalsTest, test) {
+  SKIP_WITH_HWASAN << "MTE globals tests are incompatible with HWASan";
+#if defined(__BIONIC__) && defined(__aarch64__)
+  std::string binary = GetTestLibRoot() + "/memtag_globals_binary";
+  bool is_static = MemtagGlobalsTest::GetParam();
+  if (is_static) {
+    binary += "_static";
+  }
+
+  chmod(binary.c_str(), 0755);
+  ExecTestHelper eth;
+  eth.SetArgs({binary.c_str(), nullptr});
+  eth.Run(
+      [&]() {
+        execve(binary.c_str(), eth.GetArgs(), eth.GetEnv());
+        GTEST_FAIL() << "Failed to execve: " << strerror(errno) << " " << binary.c_str();
+      },
+      // We catch the global-buffer-overflow and crash only when MTE globals is
+      // supported. Note that MTE globals is unsupported for fully static
+      // executables, but we should still make sure the binary passes its
+      // assertions, just that global variables won't be tagged.
+      (mte_supported() && !is_static) ? -SIGSEGV : 0, "Assertions were passed");
+#else
+  GTEST_SKIP() << "bionic/arm64 only";
+#endif
+}
+
+INSTANTIATE_TEST_SUITE_P(MemtagGlobalsTest, MemtagGlobalsTest, testing::Bool(),
+                         [](const ::testing::TestParamInfo<MemtagGlobalsTest::ParamType>& info) {
+                           if (info.param) return "MemtagGlobalsTest_static";
+                           return "MemtagGlobalsTest";
+                         });
+
+TEST(MemtagGlobalsTest, RelrRegressionTestForb314038442) {
+  SKIP_WITH_HWASAN << "MTE globals tests are incompatible with HWASan";
+#if defined(__BIONIC__) && defined(__aarch64__)
+  std::string binary = GetTestLibRoot() + "/mte_globals_relr_regression_test_b_314038442";
+  chmod(binary.c_str(), 0755);
+  ExecTestHelper eth;
+  eth.SetArgs({binary.c_str(), nullptr});
+  eth.Run(
+      [&]() {
+        execve(binary.c_str(), eth.GetArgs(), eth.GetEnv());
+        GTEST_FAIL() << "Failed to execve: " << strerror(errno) << " " << binary.c_str();
+      },
+      /* exit code */ 0, "Program loaded successfully.*Tags are zero!");
+#else
+  GTEST_SKIP() << "bionic/arm64 only";
+#endif
+}
+
+TEST(MemtagGlobalsTest, RelrRegressionTestForb314038442WithMteGlobals) {
+  if (!mte_supported()) GTEST_SKIP() << "Must have MTE support.";
+#if defined(__BIONIC__) && defined(__aarch64__)
+  std::string binary = GetTestLibRoot() + "/mte_globals_relr_regression_test_b_314038442_mte";
+  chmod(binary.c_str(), 0755);
+  ExecTestHelper eth;
+  eth.SetArgs({binary.c_str(), nullptr});
+  eth.Run(
+      [&]() {
+        execve(binary.c_str(), eth.GetArgs(), eth.GetEnv());
+        GTEST_FAIL() << "Failed to execve: " << strerror(errno) << " " << binary.c_str();
+      },
+      /* exit code */ 0, "Program loaded successfully.*Tags are non-zero");
+#else
+  GTEST_SKIP() << "bionic/arm64 only";
+#endif
+}
diff --git a/tests/memtag_stack_abi_test.cpp b/tests/memtag_stack_abi_test.cpp
new file mode 100644
index 0000000..4725c8d
--- /dev/null
+++ b/tests/memtag_stack_abi_test.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2024 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 <filesystem>
+#include <fstream>
+#include <iterator>
+#include <string>
+#include <thread>
+
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#include <android-base/logging.h>
+#include <gtest/gtest.h>
+
+static size_t NumberBuffers() {
+  size_t bufs = 0;
+  std::ifstream file("/proc/self/maps");
+  CHECK(file.is_open());
+  std::string line;
+  while (std::getline(file, line)) {
+    if (line.find("stack_mte_ring") != std::string::npos) {
+      ++bufs;
+    }
+  }
+  return bufs;
+}
+
+static size_t NumberThreads() {
+  std::filesystem::directory_iterator di("/proc/self/task");
+  return std::distance(begin(di), end(di));
+}
+
+TEST(MemtagStackAbiTest, MainThread) {
+#if defined(__BIONIC__) && defined(__aarch64__)
+  ASSERT_EQ(NumberBuffers(), 1U);
+  ASSERT_EQ(NumberBuffers(), NumberThreads());
+#else
+  GTEST_SKIP() << "requires bionic arm64";
+#endif
+}
+
+TEST(MemtagStackAbiTest, JoinableThread) {
+#if defined(__BIONIC__) && defined(__aarch64__)
+  ASSERT_EQ(NumberBuffers(), 1U);
+  ASSERT_EQ(NumberBuffers(), NumberThreads());
+  std::thread th([] {
+    ASSERT_EQ(NumberBuffers(), 2U);
+    ASSERT_EQ(NumberBuffers(), NumberThreads());
+  });
+  th.join();
+  ASSERT_EQ(NumberBuffers(), 1U);
+  ASSERT_EQ(NumberBuffers(), NumberThreads());
+#else
+  GTEST_SKIP() << "requires bionic arm64";
+#endif
+}
+
+TEST(MemtagStackAbiTest, DetachedThread) {
+#if defined(__BIONIC__) && defined(__aarch64__)
+  ASSERT_EQ(NumberBuffers(), 1U);
+  ASSERT_EQ(NumberBuffers(), NumberThreads());
+  std::thread th([] {
+    ASSERT_EQ(NumberBuffers(), 2U);
+    ASSERT_EQ(NumberBuffers(), NumberThreads());
+  });
+  th.detach();
+  // Leave the thread some time to exit.
+  for (int i = 0; NumberBuffers() != 1 && i < 3; ++i) {
+    sleep(1);
+  }
+  ASSERT_EQ(NumberBuffers(), 1U);
+  ASSERT_EQ(NumberBuffers(), NumberThreads());
+#else
+  GTEST_SKIP() << "requires bionic arm64";
+#endif
+}
diff --git a/tests/mntent_test.cpp b/tests/mntent_test.cpp
index 4b8fc9a..fd69ae1 100644
--- a/tests/mntent_test.cpp
+++ b/tests/mntent_test.cpp
@@ -59,9 +59,7 @@
   // indices                  1  1
   // of keys:      0    5   9 1  4
   char mnt_opts[]{"aa=b,a=b,b,bb,c=d"};
-  struct mntent ent;
-  memset(&ent, 0, sizeof(ent));
-  ent.mnt_opts = mnt_opts;
+  struct mntent ent = {.mnt_opts = mnt_opts};
 
   EXPECT_EQ(mnt_opts, hasmntopt(&ent, "aa"));
   EXPECT_EQ(mnt_opts + 5, hasmntopt(&ent, "a"));
@@ -71,3 +69,9 @@
   EXPECT_EQ(nullptr, hasmntopt(&ent, "d"));
   EXPECT_EQ(nullptr, hasmntopt(&ent, "e"));
 }
+
+TEST(mntent, hasmntopt_no_suffix_match) {
+  char mnt_opts[]{"noatime"};
+  struct mntent ent = {.mnt_opts = mnt_opts};
+  EXPECT_EQ(nullptr, hasmntopt(&ent, "atime"));
+}
diff --git a/tests/page_size_16kib_compat_test.cpp b/tests/page_size_16kib_compat_test.cpp
new file mode 100644
index 0000000..a5d91b8
--- /dev/null
+++ b/tests/page_size_16kib_compat_test.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2024 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 "page_size_compat_helpers.h"
+
+#include <android-base/properties.h>
+
+extern "C" void android_set_16kb_appcompat_mode(bool enable_app_compat);
+
+TEST(PageSize16KiBCompatTest, ElfAlignment4KiB_LoadElf) {
+  if (getpagesize() != 0x4000) {
+    GTEST_SKIP() << "This test is only applicable to 16kB page-size devices";
+  }
+
+  bool app_compat_enabled =
+      android::base::GetBoolProperty("bionic.linker.16kb.app_compat.enabled", false);
+  std::string lib = GetTestLibRoot() + "/libtest_elf_max_page_size_4kib.so";
+  void* handle = nullptr;
+
+  OpenTestLibrary(lib, !app_compat_enabled, &handle);
+
+  if (app_compat_enabled) CallTestFunction(handle);
+}
+
+TEST(PageSize16KiBCompatTest, ElfAlignment4KiB_LoadElf_perAppOption) {
+  if (getpagesize() != 0x4000) {
+    GTEST_SKIP() << "This test is only applicable to 16kB page-size devices";
+  }
+
+  android_set_16kb_appcompat_mode(true);
+  std::string lib = GetTestLibRoot() + "/libtest_elf_max_page_size_4kib.so";
+  void* handle = nullptr;
+
+  OpenTestLibrary(lib, false /*should_fail*/, &handle);
+  CallTestFunction(handle);
+  android_set_16kb_appcompat_mode(false);
+}
diff --git a/tests/page_size_compat_helpers.h b/tests/page_size_compat_helpers.h
new file mode 100644
index 0000000..2f0f1d0
--- /dev/null
+++ b/tests/page_size_compat_helpers.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "elf_max_page_size.h"
+#include "gtest_globals.h"
+
+#include <android-base/stringprintf.h>
+
+#include <string>
+
+#include <dlfcn.h>
+#include <gtest/gtest.h>
+#include <unistd.h>
+
+static inline void OpenTestLibrary(std::string lib, bool expect_fail, void** handle) {
+  void* _handle = dlopen(lib.c_str(), RTLD_NODELETE);
+  const char* dlopen_error = dlerror();
+
+  if (expect_fail) {
+    ASSERT_EQ(_handle, nullptr);
+
+    const std::string expected_error = android::base::StringPrintf(
+        "dlopen failed: \"%s\" program alignment (%d) cannot be smaller than system page size (%d)",
+        lib.c_str(), 4096, getpagesize());
+
+    ASSERT_EQ(expected_error, dlopen_error);
+  } else {
+    ASSERT_NE(_handle, nullptr) << "Failed to dlopen shared library \"" << lib
+                                << "\": " << dlopen_error;
+  }
+
+  *handle = _handle;
+}
+
+static inline void CallTestFunction(void* handle) {
+  loader_test_func_t loader_test_func = (loader_test_func_t)dlsym(handle, "loader_test_func");
+  const char* dlsym_error = dlerror();
+
+  ASSERT_EQ(dlsym_error, nullptr) << "Failed to locate symbol \"loader_test_func\": "
+                                  << dlsym_error;
+
+  int res = loader_test_func();
+  ASSERT_EQ(res, TEST_RESULT_BASE + TEST_RESULT_INCREMENT);
+
+  // Call loader_test_func() twice to ensure we can modify writeable data and bss data
+  res = loader_test_func();
+  ASSERT_EQ(res, TEST_RESULT_BASE + (2 * TEST_RESULT_INCREMENT));
+}
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-empty_shdr_table.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-empty_shdr_table.so
index c8b5430..21a8f26 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-empty_shdr_table.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-empty_shdr_table.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-local-tls.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-local-tls.so
index 20c5765..c902bbe 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-local-tls.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-local-tls.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-rw_load_segment.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-rw_load_segment.so
index 6463c6b..46af37f 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-rw_load_segment.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-rw_load_segment.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-textrels.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-textrels.so
index f83bbe4..c60b0d6 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-textrels.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-textrels.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-textrels2.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-textrels2.so
index fbf62c5..eb33692 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-textrels2.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-textrels2.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-unaligned_shdr_offset.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-unaligned_shdr_offset.so
index 6e5a6e3..fb86bca 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-unaligned_shdr_offset.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-unaligned_shdr_offset.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_content.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_content.so
index 14b80b5..0416db2 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_content.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_content.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_offset.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_offset.so
index 0aaca72..90892a6 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_offset.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_offset.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shentsize.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shentsize.so
index 4ffc7e8..c186b1d 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shentsize.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shentsize.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shstrndx.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shstrndx.so
index 9098310..857f702 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shstrndx.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shstrndx.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/gen-libtest_invalid-local-tls.sh b/tests/prebuilt-elf-files/gen-libtest_invalid-local-tls.sh
index 0f3e736..98a2b00 100755
--- a/tests/prebuilt-elf-files/gen-libtest_invalid-local-tls.sh
+++ b/tests/prebuilt-elf-files/gen-libtest_invalid-local-tls.sh
@@ -19,12 +19,18 @@
 build() {
   arch=$1
   target=$2
+
+  if [[ "$arch" == "arm64" || "$arch" == "x86_64" ]]; then
+    alignment="-Wl,-z,max-page-size=16384"
+  fi
+
   $NDK21E/toolchains/llvm/prebuilt/linux-x86_64/bin/clang -O2 --target=$target \
       -fpic -shared -o $arch/libtest_invalid-local-tls.so -fno-emulated-tls \
-      -fuse-ld=gold test.c test2.c
+      $alignment -fuse-ld=gold test.c test2.c
 }
 
 build arm armv7a-linux-androideabi29
 build arm64 aarch64-linux-android29
 build x86 i686-linux-android29
 build x86_64 x86_64-linux-android29
+
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-empty_shdr_table.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-empty_shdr_table.so
index af1538d..00fefd4 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-empty_shdr_table.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-empty_shdr_table.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-local-tls.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-local-tls.so
index 5b689ba..31d2b37 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-local-tls.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-local-tls.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-rw_load_segment.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-rw_load_segment.so
index 113e455..9d2c5f1 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-rw_load_segment.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-rw_load_segment.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-textrels.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-textrels.so
index 719fb5a..f231d11 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-textrels.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-textrels.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-textrels2.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-textrels2.so
index 9d0741e..97fb5c4 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-textrels2.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-textrels2.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-unaligned_shdr_offset.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-unaligned_shdr_offset.so
index 87631af..f9c310f 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-unaligned_shdr_offset.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-unaligned_shdr_offset.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_content.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_content.so
index 27d1138..3d1f5d3 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_content.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_content.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_offset.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_offset.so
index 3e2c1d1..aeea1d2 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_offset.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_offset.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shentsize.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shentsize.so
index 78fed79..8146676 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shentsize.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shentsize.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shstrndx.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shstrndx.so
index 0953633..4ac70f7 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shstrndx.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shstrndx.so
Binary files differ
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 2bf755b..5ce7d4d 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -45,6 +45,7 @@
 #include <android-base/test_utils.h>
 
 #include "private/bionic_constants.h"
+#include "private/bionic_time_conversions.h"
 #include "SignalUtils.h"
 #include "utils.h"
 
@@ -2437,23 +2438,25 @@
   ts.tv_sec = -1;
   ASSERT_EQ(ETIMEDOUT, lock_function(&m, &ts));
 
-  // check we wait long enough for the lock.
+  // Check we wait long enough for the lock before timing out...
+
+  // What time is it before we start?
   ASSERT_EQ(0, clock_gettime(clock, &ts));
-  const int64_t start_ns = ts.tv_sec * NS_PER_S + ts.tv_nsec;
-
-  // add a second to get deadline.
+  const int64_t start_ns = to_ns(ts);
+  // Add a second to get deadline, and wait until we time out.
   ts.tv_sec += 1;
-
   ASSERT_EQ(ETIMEDOUT, lock_function(&m, &ts));
 
+  // What time is it now we've timed out?
+  timespec ts2;
+  clock_gettime(clock, &ts2);
+  const int64_t end_ns = to_ns(ts2);
+
   // The timedlock must have waited at least 1 second before returning.
-  clock_gettime(clock, &ts);
-  const int64_t end_ns = ts.tv_sec * NS_PER_S + ts.tv_nsec;
-  ASSERT_GT(end_ns - start_ns, NS_PER_S);
+  ASSERT_GE(end_ns - start_ns, NS_PER_S);
 
   // If the mutex is unlocked, pthread_mutex_timedlock should succeed.
   ASSERT_EQ(0, pthread_mutex_unlock(&m));
-
   ASSERT_EQ(0, clock_gettime(clock, &ts));
   ts.tv_sec += 1;
   ASSERT_EQ(0, lock_function(&m, &ts));
@@ -2474,12 +2477,19 @@
 #endif  // __BIONIC__
 }
 
-TEST(pthread, pthread_mutex_clocklock) {
+TEST(pthread, pthread_mutex_clocklock_MONOTONIC) {
 #if defined(__BIONIC__)
   pthread_mutex_timedlock_helper(
       CLOCK_MONOTONIC, [](pthread_mutex_t* __mutex, const timespec* __timeout) {
         return pthread_mutex_clocklock(__mutex, CLOCK_MONOTONIC, __timeout);
       });
+#else   // __BIONIC__
+  GTEST_SKIP() << "pthread_mutex_clocklock not available";
+#endif  // __BIONIC__
+}
+
+TEST(pthread, pthread_mutex_clocklock_REALTIME) {
+#if defined(__BIONIC__)
   pthread_mutex_timedlock_helper(
       CLOCK_REALTIME, [](pthread_mutex_t* __mutex, const timespec* __timeout) {
         return pthread_mutex_clocklock(__mutex, CLOCK_REALTIME, __timeout);
@@ -3127,3 +3137,39 @@
   GTEST_SKIP() << "bionic-only test";
 #endif
 }
+
+TEST(pthread, pthread_getaffinity_np_failure) {
+  // Trivial test of the errno-preserving/returning behavior.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnonnull"
+  errno = 0;
+  ASSERT_EQ(EINVAL, pthread_getaffinity_np(pthread_self(), 0, nullptr));
+  ASSERT_ERRNO(0);
+#pragma clang diagnostic pop
+}
+
+TEST(pthread, pthread_getaffinity) {
+  cpu_set_t set;
+  CPU_ZERO(&set);
+  ASSERT_EQ(0, pthread_getaffinity_np(pthread_self(), sizeof(set), &set));
+  ASSERT_GT(CPU_COUNT(&set), 0);
+}
+
+TEST(pthread, pthread_setaffinity_np_failure) {
+  // Trivial test of the errno-preserving/returning behavior.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnonnull"
+  errno = 0;
+  ASSERT_EQ(EINVAL, pthread_setaffinity_np(pthread_self(), 0, nullptr));
+  ASSERT_ERRNO(0);
+#pragma clang diagnostic pop
+}
+
+TEST(pthread, pthread_setaffinity) {
+  cpu_set_t set;
+  CPU_ZERO(&set);
+  ASSERT_EQ(0, pthread_getaffinity_np(pthread_self(), sizeof(set), &set));
+  // It's hard to make any more general claim than this,
+  // but it ought to be safe to ask for the same affinity you already have.
+  ASSERT_EQ(0, pthread_setaffinity_np(pthread_self(), sizeof(set), &set));
+}
diff --git a/tests/sched_test.cpp b/tests/sched_test.cpp
index 0231de4..448fae9 100644
--- a/tests/sched_test.cpp
+++ b/tests/sched_test.cpp
@@ -305,8 +305,35 @@
 }
 
 TEST(sched, sched_getaffinity_failure) {
+  // Trivial test of the errno-preserving/returning behavior.
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wnonnull"
   ASSERT_EQ(-1, sched_getaffinity(getpid(), 0, nullptr));
+  ASSERT_ERRNO(EINVAL);
 #pragma clang diagnostic pop
 }
+
+TEST(pthread, sched_getaffinity) {
+  cpu_set_t set;
+  CPU_ZERO(&set);
+  ASSERT_EQ(0, sched_getaffinity(getpid(), sizeof(set), &set));
+  ASSERT_GT(CPU_COUNT(&set), 0);
+}
+
+TEST(sched, sched_setaffinity_failure) {
+  // Trivial test of the errno-preserving/returning behavior.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnonnull"
+  ASSERT_EQ(-1, sched_setaffinity(getpid(), 0, nullptr));
+  ASSERT_ERRNO(EINVAL);
+#pragma clang diagnostic pop
+}
+
+TEST(pthread, sched_setaffinity) {
+  cpu_set_t set;
+  CPU_ZERO(&set);
+  ASSERT_EQ(0, sched_getaffinity(getpid(), sizeof(set), &set));
+  // It's hard to make any more general claim than this,
+  // but it ought to be safe to ask for the same affinity you already have.
+  ASSERT_EQ(0, sched_setaffinity(getpid(), sizeof(set), &set));
+}
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index de126da..c1719dc 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -982,3 +982,94 @@
   ASSERT_EQ(-1, killpg(-1, SIGKILL));
   ASSERT_ERRNO(EINVAL);
 }
+
+TEST(signal, sig2str) {
+#if defined(__BIONIC__)
+  char str[SIG2STR_MAX];
+
+  // A regular signal.
+  ASSERT_EQ(0, sig2str(SIGHUP, str));
+  ASSERT_STREQ("HUP", str);
+
+  // A real-time signal.
+  ASSERT_EQ(0, sig2str(SIGRTMIN + 4, str));
+  ASSERT_STREQ("RTMIN+4", str);
+  ASSERT_EQ(0, sig2str(SIGRTMAX - 4, str));
+  ASSERT_STREQ("RTMAX-4", str);
+  // Special cases.
+  ASSERT_EQ(0, sig2str(SIGRTMAX, str));
+  ASSERT_STREQ("RTMAX", str);
+  ASSERT_EQ(0, sig2str(SIGRTMIN, str));
+  ASSERT_STREQ("RTMIN", str);
+  // One of the signals the C library keeps to itself.
+  ASSERT_EQ(-1, sig2str(32, str));  // __SIGRTMIN
+
+  // Errors.
+  ASSERT_EQ(-1, sig2str(-1, str));    // Too small.
+  ASSERT_EQ(-1, sig2str(0, str));     // Still too small.
+  ASSERT_EQ(-1, sig2str(1234, str));  // Too large.
+#else
+  GTEST_SKIP() << "our old glibc doesn't have sig2str";
+#endif
+}
+
+TEST(signal, str2sig) {
+#if defined(__BIONIC__)
+  int sig;
+
+  // A regular signal, by number.
+  sig = -1;
+  ASSERT_EQ(0, str2sig("9", &sig));
+  ASSERT_EQ(SIGKILL, sig);
+
+  // A regular signal, by name.
+  sig = -1;
+  ASSERT_EQ(0, str2sig("HUP", &sig));
+  ASSERT_EQ(SIGHUP, sig);
+
+  // A real-time signal, by number.
+  sig = -1;
+  ASSERT_EQ(0, str2sig("64", &sig));
+  ASSERT_EQ(SIGRTMAX, sig);
+
+  // A real-time signal, by name and offset.
+  sig = -1;
+  ASSERT_EQ(0, str2sig("RTMAX-4", &sig));
+  ASSERT_EQ(SIGRTMAX - 4, sig);
+  sig = -1;
+  ASSERT_EQ(0, str2sig("RTMIN+4", &sig));
+  ASSERT_EQ(SIGRTMIN + 4, sig);
+  // Unspecified by POSIX, but we try to be reasonable.
+  sig = -1;
+  ASSERT_EQ(0, str2sig("RTMAX-0", &sig));
+  ASSERT_EQ(SIGRTMAX, sig);
+  sig = -1;
+  ASSERT_EQ(0, str2sig("RTMIN+0", &sig));
+  ASSERT_EQ(SIGRTMIN, sig);
+  // One of the signals the C library keeps to itself, numerically.
+  ASSERT_EQ(-1, str2sig("32", &sig));  // __SIGRTMIN
+
+  // Special cases.
+  sig = -1;
+  ASSERT_EQ(0, str2sig("RTMAX", &sig));
+  ASSERT_EQ(SIGRTMAX, sig);
+  sig = -1;
+  ASSERT_EQ(0, str2sig("RTMIN", &sig));
+  ASSERT_EQ(SIGRTMIN, sig);
+
+  // Errors.
+  ASSERT_EQ(-1, str2sig("SIGHUP", &sig));     // No "SIG" prefix allowed.
+  ASSERT_EQ(-1, str2sig("-1", &sig));         // Too small.
+  ASSERT_EQ(-1, str2sig("0", &sig));          // Still too small.
+  ASSERT_EQ(-1, str2sig("1234", &sig));       // Too large.
+  ASSERT_EQ(-1, str2sig("RTMAX-666", &sig));  // Offset too small.
+  ASSERT_EQ(-1, str2sig("RTMIN+666", &sig));  // Offset too large.
+  ASSERT_EQ(-1, str2sig("RTMAX-+1", &sig));   // Silly.
+  ASSERT_EQ(-1, str2sig("RTMIN+-1", &sig));   // Silly.
+  ASSERT_EQ(-1, str2sig("HUPs", &sig));       // Trailing junk.
+  ASSERT_EQ(-1, str2sig("2b", &sig));         // Trailing junk.
+  ASSERT_EQ(-1, str2sig("RTMIN+2b", &sig));   // Trailing junk.
+#else
+  GTEST_SKIP() << "our old glibc doesn't have str2sig";
+#endif
+}
diff --git a/tests/static_tls_layout_test.cpp b/tests/static_tls_layout_test.cpp
index bf508e8..ada29a5 100644
--- a/tests/static_tls_layout_test.cpp
+++ b/tests/static_tls_layout_test.cpp
@@ -35,6 +35,8 @@
 
 #include <gtest/gtest.h>
 
+#include <android-base/silent_death_test.h>
+
 #include "private/bionic_tls.h"
 
 using namespace std::string_literals;
@@ -138,7 +140,9 @@
   return i * sizeof(void*);
 }
 
-TEST(static_tls_layout, arm) {
+using static_tls_layout_DeathTest = SilentDeathTest;
+
+TEST_F(static_tls_layout_DeathTest, arm) {
 #if !defined(__arm__) && !defined(__aarch64__)
   GTEST_SKIP() << "test only applies to arm32/arm64 targets";
 #endif
diff --git a/tests/stdatomic_test.cpp b/tests/stdatomic_test.cpp
index f5c6bb1..8a54080 100644
--- a/tests/stdatomic_test.cpp
+++ b/tests/stdatomic_test.cpp
@@ -37,10 +37,10 @@
 }
 
 TEST(stdatomic, init) {
-  atomic_int v = ATOMIC_VAR_INIT(123);
+  atomic_int v = 123;
   ASSERT_EQ(123, atomic_load(&v));
 
-  atomic_init(&v, 456);
+  atomic_store_explicit(&v, 456, memory_order_relaxed);
   ASSERT_EQ(456, atomic_load(&v));
 
   atomic_flag f = ATOMIC_FLAG_INIT;
@@ -145,35 +145,35 @@
 }
 
 TEST(stdatomic, atomic_fetch_add) {
-  atomic_int i = ATOMIC_VAR_INIT(123);
+  atomic_int i = 123;
   ASSERT_EQ(123, atomic_fetch_add(&i, 1));
   ASSERT_EQ(124, atomic_fetch_add_explicit(&i, 1, memory_order_relaxed));
   ASSERT_EQ(125, atomic_load(&i));
 }
 
 TEST(stdatomic, atomic_fetch_sub) {
-  atomic_int i = ATOMIC_VAR_INIT(123);
+  atomic_int i = 123;
   ASSERT_EQ(123, atomic_fetch_sub(&i, 1));
   ASSERT_EQ(122, atomic_fetch_sub_explicit(&i, 1, memory_order_relaxed));
   ASSERT_EQ(121, atomic_load(&i));
 }
 
 TEST(stdatomic, atomic_fetch_or) {
-  atomic_int i = ATOMIC_VAR_INIT(0x100);
+  atomic_int i = 0x100;
   ASSERT_EQ(0x100, atomic_fetch_or(&i, 0x020));
   ASSERT_EQ(0x120, atomic_fetch_or_explicit(&i, 0x003, memory_order_relaxed));
   ASSERT_EQ(0x123, atomic_load(&i));
 }
 
 TEST(stdatomic, atomic_fetch_xor) {
-  atomic_int i = ATOMIC_VAR_INIT(0x100);
+  atomic_int i = 0x100;
   ASSERT_EQ(0x100, atomic_fetch_xor(&i, 0x120));
   ASSERT_EQ(0x020, atomic_fetch_xor_explicit(&i, 0x103, memory_order_relaxed));
   ASSERT_EQ(0x123, atomic_load(&i));
 }
 
 TEST(stdatomic, atomic_fetch_and) {
-  atomic_int i = ATOMIC_VAR_INIT(0x123);
+  atomic_int i = 0x123;
   ASSERT_EQ(0x123, atomic_fetch_and(&i, 0x00f));
   ASSERT_EQ(0x003, atomic_fetch_and_explicit(&i, 0x2, memory_order_relaxed));
   ASSERT_EQ(0x002, atomic_load(&i));
@@ -258,9 +258,9 @@
   // Run a memory ordering smoke test.
   void* result;
   three_atomics a;
-  atomic_init(&a.x, 0ul);
-  atomic_init(&a.y, 0ul);
-  atomic_init(&a.z, 0ul);
+  atomic_store_explicit(&a.x, 0ul, memory_order_relaxed);
+  atomic_store_explicit(&a.y, 0ul, memory_order_relaxed);
+  atomic_store_explicit(&a.z, 0ul, memory_order_relaxed);
   pthread_t t1,t2;
   ASSERT_EQ(0, pthread_create(&t1, nullptr, reader, &a));
   ASSERT_EQ(0, pthread_create(&t2, nullptr, writer, &a));
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index f5e57a5..fac9b9b 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -431,6 +431,31 @@
   ASSERT_STREQ("charlie", entries[2].name);
 }
 
+TEST(stdlib, qsort_r) {
+  struct s {
+    char name[16];
+    static int comparator(const void* lhs, const void* rhs, void* context) {
+      int* count_p = reinterpret_cast<int*>(context);
+      *count_p += 1;
+      return strcmp(reinterpret_cast<const s*>(lhs)->name, reinterpret_cast<const s*>(rhs)->name);
+    }
+  };
+  s entries[3];
+  strcpy(entries[0].name, "charlie");
+  strcpy(entries[1].name, "bravo");
+  strcpy(entries[2].name, "alpha");
+
+  int count;
+  void* context = &count;
+
+  count = 0;
+  qsort_r(entries, 3, sizeof(s), s::comparator, context);
+  ASSERT_STREQ("alpha", entries[0].name);
+  ASSERT_STREQ("bravo", entries[1].name);
+  ASSERT_STREQ("charlie", entries[2].name);
+  ASSERT_EQ(count, 3);
+}
+
 static void* TestBug57421_child(void* arg) {
   pthread_t main_thread = reinterpret_cast<pthread_t>(arg);
   pthread_join(main_thread, nullptr);
@@ -494,7 +519,7 @@
 
 TEST(stdlib, system_NULL) {
   // "The system() function shall always return non-zero when command is NULL."
-  // http://pubs.opengroup.org/onlinepubs/9699919799/functions/system.html
+  // https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/system.html
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wnonnull"
   ASSERT_NE(0, system(nullptr));
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index 6e1fcfc..502405f 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -740,15 +740,11 @@
     // Set the second half of ptr to the expected pattern in ptr2.
     memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN);
     memcpy(state.ptr + state.MAX_LEN, state.ptr1, copy_len);
-    size_t expected_end;
     if (copy_len > ptr1_len) {
       memset(state.ptr + state.MAX_LEN + ptr1_len, '\0', copy_len - ptr1_len);
-      expected_end = ptr1_len;
-    } else {
-      expected_end = copy_len;
     }
 
-    ASSERT_EQ(state.ptr2 + expected_end, stpncpy(state.ptr2, state.ptr1, copy_len));
+    ASSERT_EQ(state.ptr2, strncpy(state.ptr2, state.ptr1, copy_len));
 
     // Verify ptr1 was not modified.
     ASSERT_EQ(0, memcmp(state.ptr1, state.ptr, state.MAX_LEN));
diff --git a/tests/struct_layout_test.cpp b/tests/struct_layout_test.cpp
index 1f04344..b9fd315 100644
--- a/tests/struct_layout_test.cpp
+++ b/tests/struct_layout_test.cpp
@@ -30,7 +30,7 @@
 #define CHECK_OFFSET(name, field, offset) \
     check_offset(#name, #field, offsetof(name, field), offset);
 #ifdef __LP64__
-  CHECK_SIZE(pthread_internal_t, 816);
+  CHECK_SIZE(pthread_internal_t, 824);
   CHECK_OFFSET(pthread_internal_t, next, 0);
   CHECK_OFFSET(pthread_internal_t, prev, 8);
   CHECK_OFFSET(pthread_internal_t, tid, 16);
@@ -57,6 +57,7 @@
   CHECK_OFFSET(pthread_internal_t, errno_value, 768);
   CHECK_OFFSET(pthread_internal_t, bionic_tcb, 776);
   CHECK_OFFSET(pthread_internal_t, stack_mte_ringbuffer_vma_name_buffer, 784);
+  CHECK_OFFSET(pthread_internal_t, should_allocate_stack_mte_ringbuffer, 816);
   CHECK_SIZE(bionic_tls, 12200);
   CHECK_OFFSET(bionic_tls, key_data, 0);
   CHECK_OFFSET(bionic_tls, locale, 2080);
@@ -74,7 +75,7 @@
   CHECK_OFFSET(bionic_tls, bionic_systrace_disabled, 12193);
   CHECK_OFFSET(bionic_tls, padding, 12194);
 #else
-  CHECK_SIZE(pthread_internal_t, 704);
+  CHECK_SIZE(pthread_internal_t, 708);
   CHECK_OFFSET(pthread_internal_t, next, 0);
   CHECK_OFFSET(pthread_internal_t, prev, 4);
   CHECK_OFFSET(pthread_internal_t, tid, 8);
@@ -101,6 +102,7 @@
   CHECK_OFFSET(pthread_internal_t, errno_value, 664);
   CHECK_OFFSET(pthread_internal_t, bionic_tcb, 668);
   CHECK_OFFSET(pthread_internal_t, stack_mte_ringbuffer_vma_name_buffer, 672);
+  CHECK_OFFSET(pthread_internal_t, should_allocate_stack_mte_ringbuffer, 704);
   CHECK_SIZE(bionic_tls, 11080);
   CHECK_OFFSET(bionic_tls, key_data, 0);
   CHECK_OFFSET(bionic_tls, locale, 1040);
diff --git a/tests/sys_mman_test.cpp b/tests/sys_mman_test.cpp
index 40c85f2..54a0b64 100644
--- a/tests/sys_mman_test.cpp
+++ b/tests/sys_mman_test.cpp
@@ -320,3 +320,30 @@
   close(fd);
 #endif
 }
+
+TEST(sys_mseal, mseal) {
+#if defined(__GLIBC__)
+  GTEST_SKIP() << "needs glibc 2.40";
+#else
+  void* map = mmap(nullptr, kPageSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  ASSERT_NE(MAP_FAILED, map);
+
+#if defined(__LP64__)
+  int rc = mseal(map, kPageSize, 0);
+  if (rc == -1) {
+    ASSERT_ERRNO(ENOSYS);
+    GTEST_SKIP() << "needs kernel with mseal(2)";
+  }
+  ASSERT_EQ(-1, mprotect(map, kPageSize, PROT_READ));
+  ASSERT_ERRNO(EPERM);
+#else
+  // No mseal() for ILP32.
+  errno = 0;
+  ASSERT_EQ(-1, mseal(map, kPageSize, 0));
+  ASSERT_ERRNO(ENOSYS);
+  GTEST_SKIP() << "mseal(2) is LP64-only";
+#endif
+
+  // We can't munmap() our test mapping if mseal() actually succeeded :-)
+#endif
+}
diff --git a/tests/sys_ptrace_test.cpp b/tests/sys_ptrace_test.cpp
index 93daac3..499adbb 100644
--- a/tests/sys_ptrace_test.cpp
+++ b/tests/sys_ptrace_test.cpp
@@ -41,11 +41,6 @@
 
 using android::base::unique_fd;
 
-// Host libc does not define this.
-#ifndef TRAP_HWBKPT
-#define TRAP_HWBKPT 4
-#endif
-
 class ChildGuard {
  public:
   explicit ChildGuard(pid_t pid) : pid(pid) {}
diff --git a/tests/sys_stat_test.cpp b/tests/sys_stat_test.cpp
index 126f469..50c50df 100644
--- a/tests/sys_stat_test.cpp
+++ b/tests/sys_stat_test.cpp
@@ -151,12 +151,12 @@
   ASSERT_ERRNO(EINVAL);
 }
 
-TEST(sys_stat, fchmodat_nonexistant_file) {
+TEST(sys_stat, fchmodat_nonexistent_file) {
   ASSERT_EQ(-1, fchmodat(AT_FDCWD, "/blah", 0751, 0));
   ASSERT_ERRNO(ENOENT);
 }
 
-TEST(sys_stat, fchmodat_AT_SYMLINK_NOFOLLOW_nonexistant_file) {
+TEST(sys_stat, fchmodat_AT_SYMLINK_NOFOLLOW_nonexistent_file) {
   ASSERT_EQ(-1, fchmodat(AT_FDCWD, "/blah", 0751, AT_SYMLINK_NOFOLLOW));
 #if defined(__BIONIC__)
   ASSERT_ERRNO(ENOENT);
@@ -305,7 +305,7 @@
   ASSERT_EQ(0, faccessat(AT_FDCWD, "/dev/null", R_OK|W_OK, 0));
 }
 
-TEST(sys_stat, faccessat_nonexistant) {
+TEST(sys_stat, faccessat_nonexistent) {
   ASSERT_EQ(-1, faccessat(AT_FDCWD, "/blah", F_OK, AT_SYMLINK_NOFOLLOW));
 #if defined(__BIONIC__)
   // Android doesn't support AT_SYMLINK_NOFOLLOW
@@ -314,3 +314,26 @@
   ASSERT_ERRNO(ENOENT);
 #endif
 }
+
+TEST(sys_stat, lchmod) {
+  TemporaryFile tf;
+  struct stat tf_sb;
+  ASSERT_EQ(0, stat(tf.path, &tf_sb));
+
+  char linkname[255];
+  snprintf(linkname, sizeof(linkname), "%s.link", tf.path);
+
+  ASSERT_EQ(0, symlink(tf.path, linkname));
+  int result = lchmod(linkname, 0751);
+  // Whether or not chmod is allowed on a symlink depends on the kernel.
+  if (result == 0) {
+    AssertSymlinkModeEquals(0751, linkname);
+  } else {
+    ASSERT_EQ(-1, result);
+    ASSERT_ERRNO(ENOTSUP);
+  }
+
+  // The target file mode shouldn't be modified.
+  AssertFileModeEquals(tf_sb.st_mode, tf.path);
+  unlink(linkname);
+}
diff --git a/tests/sys_statvfs_test.cpp b/tests/sys_statvfs_test.cpp
index 5dd7b93..25256ff 100644
--- a/tests/sys_statvfs_test.cpp
+++ b/tests/sys_statvfs_test.cpp
@@ -25,7 +25,15 @@
 #include <string>
 
 template <typename StatVfsT> void Check(StatVfsT& sb) {
+#if defined(__x86_64__)
+  // On x86_64 based 16kb page size targets, the page size in userspace is simulated to 16kb but
+  // the underlying filesystem block size would remain unchanged, i.e., 4kb.
+  // For more info:
+  // https://source.android.com/docs/core/architecture/16kb-page-size/getting-started-cf-x86-64-pgagnostic
+  EXPECT_EQ(4096, static_cast<int>(sb.f_bsize));
+#else
   EXPECT_EQ(getpagesize(), static_cast<int>(sb.f_bsize));
+#endif
   EXPECT_EQ(0U, sb.f_bfree);
   EXPECT_EQ(0U, sb.f_ffree);
   EXPECT_EQ(255U, sb.f_namemax);
diff --git a/tests/sys_time_test.cpp b/tests/sys_time_test.cpp
index ff9271f..b0e52aa 100644
--- a/tests/sys_time_test.cpp
+++ b/tests/sys_time_test.cpp
@@ -23,6 +23,7 @@
 
 #include <android-base/file.h>
 
+#include "private/bionic_time_conversions.h"
 #include "utils.h"
 
 // http://b/11383777
@@ -147,14 +148,6 @@
   ASSERT_EQ(0, syscall(__NR_gettimeofday, &tv2, nullptr));
 
   // What's the difference between the two?
-  tv2.tv_sec -= tv1.tv_sec;
-  tv2.tv_usec -= tv1.tv_usec;
-  if (tv2.tv_usec < 0) {
-    --tv2.tv_sec;
-    tv2.tv_usec += 1000000;
-  }
-
   // To try to avoid flakiness we'll accept answers within 10,000us (0.01s).
-  ASSERT_EQ(0, tv2.tv_sec);
-  ASSERT_LT(tv2.tv_usec, 10'000);
+  ASSERT_LT(to_us(tv2) - to_us(tv1), 10'000);
 }
diff --git a/tests/sys_vfs_test.cpp b/tests/sys_vfs_test.cpp
index e783190..90b6da9 100644
--- a/tests/sys_vfs_test.cpp
+++ b/tests/sys_vfs_test.cpp
@@ -27,7 +27,15 @@
 #include "utils.h"
 
 template <typename StatFsT> void Check(StatFsT& sb) {
+#if defined(__x86_64__)
+  // On x86_64 based 16kb page size targets, the page size in userspace is simulated to 16kb but
+  // the underlying filesystem block size would remain unchanged, i.e., 4kb.
+  // For more info:
+  // https://source.android.com/docs/core/architecture/16kb-page-size/getting-started-cf-x86-64-pgagnostic
+  EXPECT_EQ(4096, static_cast<int>(sb.f_bsize));
+#else
   EXPECT_EQ(getpagesize(), static_cast<int>(sb.f_bsize));
+#endif
   EXPECT_EQ(0U, sb.f_bfree);
   EXPECT_EQ(0U, sb.f_ffree);
   EXPECT_EQ(255, static_cast<int>(sb.f_namelen));
diff --git a/tests/system_properties_test.cpp b/tests/system_properties_test.cpp
index f11f509..5b5e009 100644
--- a/tests/system_properties_test.cpp
+++ b/tests/system_properties_test.cpp
@@ -33,10 +33,9 @@
 
 #if defined(__BIONIC__)
 
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 #include <stdlib.h>
-#include <sys/_system_properties.h>
 #include <sys/mount.h>
+#include <sys/system_properties.h>
 
 #include <system_properties/system_properties.h>
 
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 78b55c1..9ad3b6d 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -16,6 +16,7 @@
 
 #include <gtest/gtest.h>
 
+#include "DoNotOptimize.h"
 #include "SignalUtils.h"
 #include "utils.h"
 
diff --git a/tests/utils.h b/tests/utils.h
index 3c83b73..4740e59 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -295,16 +295,6 @@
   size_t start_count_ = CountOpenFds();
 };
 
-// From <benchmark/benchmark.h>.
-template <class Tp>
-static inline void DoNotOptimize(Tp const& value) {
-  asm volatile("" : : "r,m"(value) : "memory");
-}
-template <class Tp>
-static inline void DoNotOptimize(Tp& value) {
-  asm volatile("" : "+r,m"(value) : : "memory");
-}
-
 static inline bool running_with_mte() {
 #ifdef __aarch64__
   int level = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index 387d23b..a811fd8 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -556,7 +556,7 @@
   } else {
     // If the subject sequence begins with a <hyphen-minus>, the value resulting
     // from the conversion shall be negated.
-    // http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtoul.html
+    // https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/strtoul.html
     ASSERT_EQ(std::numeric_limits<T>::max(), fn(min_str, nullptr, 0)) << min_str;
   }
   ASSERT_EQ(std::numeric_limits<T>::max(), fn(max_str, nullptr, 0)) << max_str;
diff --git a/tools/NOTICE b/tools/NOTICE
index a4ec954..e69de29 100644
--- a/tools/NOTICE
+++ b/tools/NOTICE
@@ -1,32 +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.
-
--------------------------------------------------------------------
-
-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.
-
--------------------------------------------------------------------
-
diff --git a/tools/versioner/Android.bp b/tools/versioner/Android.bp
deleted file mode 100644
index cc4dbfa..0000000
--- a/tools/versioner/Android.bp
+++ /dev/null
@@ -1,7 +0,0 @@
-package {
-    default_applicable_licenses: ["bionic_tools_license"],
-}
-
-subdirs = [
-    "src",
-]
diff --git a/tools/versioner/README.md b/tools/versioner/README.md
deleted file mode 100644
index edb32be..0000000
--- a/tools/versioner/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-## versioner
-Use clang to verify the correctness of bionic's availability attributes against the NDK platform definitions.
-
-#### Build
-Build with `LLVM_BUILD_HOST_TOOLS=true mma -j48`
-
-#### Use
-`versioner -p platforms current dependencies`
diff --git a/tools/versioner/current b/tools/versioner/current
deleted file mode 120000
index 234dfe7..0000000
--- a/tools/versioner/current
+++ /dev/null
@@ -1 +0,0 @@
-../../libc/include
\ No newline at end of file
diff --git a/tools/versioner/dependencies b/tools/versioner/dependencies
deleted file mode 120000
index 4ec3391..0000000
--- a/tools/versioner/dependencies
+++ /dev/null
@@ -1 +0,0 @@
-../../libc/versioner-dependencies
\ No newline at end of file
diff --git a/tools/versioner/platforms/crtbegin.map.txt b/tools/versioner/platforms/crtbegin.map.txt
deleted file mode 100644
index b844c1e..0000000
--- a/tools/versioner/platforms/crtbegin.map.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file lists the libc functions are included in `crtbegin.o` and not
-# exported by `libc.so`.
-
-CRTBEGIN {
-  global:
-    atexit;  # arm64 x86 x86_64
-};
diff --git a/tools/versioner/platforms/libc.map.txt b/tools/versioner/platforms/libc.map.txt
deleted file mode 120000
index 8527b2e..0000000
--- a/tools/versioner/platforms/libc.map.txt
+++ /dev/null
@@ -1 +0,0 @@
-../../../libc/libc.map.txt
\ No newline at end of file
diff --git a/tools/versioner/run_tests.py b/tools/versioner/run_tests.py
deleted file mode 100755
index 396f895..0000000
--- a/tools/versioner/run_tests.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python3
-
-import os
-import subprocess
-import sys
-
-red = '\033[91m'
-green = '\033[92m'
-bold = '\033[1m'
-reset = '\033[0m'
-prefix_pass = bold + "[" + green + "PASS" + reset + bold + "]" + reset
-prefix_fail = bold + "[" + red + "FAIL" + reset + bold + "]" + reset
-
-
-def indent(text, spaces=4):
-    text = text.decode("utf-8")
-    prefix = "    "
-    return "\n".join([prefix + line for line in text.split("\n")])
-
-
-def run_test(test_name, path):
-    os.chdir(path)
-    process = subprocess.Popen(
-        ["/bin/sh", "run.sh"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-    (output, _) = process.communicate()
-
-    if os.path.exists("expected_fail"):
-        with open("expected_fail", "rb") as f:
-            expected_output = f.read()
-            if process.returncode == 0:
-                print("{} {}: unexpected success:".format(prefix_fail, test_name))
-                print("")
-                print("  Expected:")
-                print(indent(expected_output))
-                print("  Actual:")
-                print(indent(output))
-                return False
-            elif not output.endswith(expected_output):
-                print("{} {}: expected output mismatch".format(
-                    prefix_fail, test_name))
-                print("")
-                print("  Expected:")
-                print(indent(expected_output))
-                print("  Actual:")
-                print(indent(output))
-                return False
-    elif process.returncode != 0:
-        print("{} {}: unexpected failure:".format(prefix_fail, test_name))
-        print("")
-        print(indent(output))
-        return False
-
-    print("{} {}".format(prefix_pass, test_name))
-    return True
-
-
-def usage():
-    print("Usage: run_tests.py [-f]")
-    print("    -f\t\tdon't run slow tests")
-    sys.exit(0)
-
-
-root_dir = os.path.dirname(os.path.realpath(__file__))
-test_dir = os.path.join(root_dir, "tests")
-tests = os.listdir(test_dir)
-run_slow = True
-
-if len(sys.argv) > 2:
-    usage()
-elif len(sys.argv) == 2:
-    if sys.argv[1] != "-f":
-        usage()
-    run_slow = False
-
-success = True
-for test in sorted(tests):
-    if test.startswith("slow") and not run_slow:
-        continue
-    path = os.path.join(test_dir, test)
-    if not os.path.isdir(path):
-        continue
-    if not run_test(test, path):
-        success = False
-
-sys.exit(0 if success else 1)
diff --git a/tools/versioner/src/Android.bp b/tools/versioner/src/Android.bp
deleted file mode 100644
index 6551e77..0000000
--- a/tools/versioner/src/Android.bp
+++ /dev/null
@@ -1,46 +0,0 @@
-package {
-    default_applicable_licenses: ["bionic_tools_license"],
-}
-
-cc_binary_host {
-    name: "versioner",
-
-    defaults: ["llvm-build-host-tools-defaults"],
-
-    srcs: [
-        "versioner.cpp",
-        "Arch.cpp",
-        "CompilationType.cpp",
-        "DeclarationDatabase.cpp",
-        "Driver.cpp",
-        "Preprocessor.cpp",
-        "SymbolDatabase.cpp",
-        "SymbolFileParser.cpp",
-        "Utils.cpp",
-        "VFS.cpp",
-    ],
-
-    shared_libs: [
-        "libclang-cpp_host",
-        "libbase",
-    ],
-
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-Wno-unused-parameter",
-        "-fno-omit-frame-pointer",
-    ],
-
-    target: {
-        host: {
-            cppflags: [
-                "-fno-rtti",
-            ],
-        },
-        windows: {
-            enabled: false,
-        },
-    },
-}
diff --git a/tools/versioner/src/Arch.cpp b/tools/versioner/src/Arch.cpp
deleted file mode 100644
index d4d0208..0000000
--- a/tools/versioner/src/Arch.cpp
+++ /dev/null
@@ -1,58 +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.
- */
-
-#include "Arch.h"
-
-#include <err.h>
-
-#include <string>
-
-std::string to_string(const Arch& arch) {
-  switch (arch) {
-    case Arch::arm:
-      return "arm";
-
-    case Arch::arm64:
-      return "arm64";
-
-    case Arch::riscv64:
-      return "riscv64";
-
-    case Arch::x86:
-      return "x86";
-
-    case Arch::x86_64:
-      return "x86_64";
-  }
-
-  errx(1, "unknown arch '%zu'", size_t(arch));
-}
-
-static const std::unordered_map<std::string, Arch> arch_name_map{
-  {"arm", Arch::arm},
-  {"arm64", Arch::arm64},
-  {"riscv64", Arch::riscv64},
-  {"x86", Arch::x86},
-  {"x86_64", Arch::x86_64},
-};
-
-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
deleted file mode 100644
index fd98abc..0000000
--- a/tools/versioner/src/Arch.h
+++ /dev/null
@@ -1,170 +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.
- */
-
-#pragma once
-
-#include <stdlib.h>
-
-#include <array>
-#include <initializer_list>
-#include <optional>
-#include <set>
-#include <string>
-#include <unordered_map>
-
-enum class Arch : size_t {
-  arm = 0,
-  arm64,
-  riscv64,
-  x86,
-  x86_64,
-};
-
-std::string to_string(const Arch& arch);
-std::optional<Arch> arch_from_string(const std::string& name);
-
-template <typename T>
-class ArchMapIterator;
-
-template <typename T>
-class ArchMap {
- public:
-  ArchMap() {
-  }
-
-  ArchMap(std::initializer_list<std::pair<Arch, T>> initializer) {
-    for (auto& pair : initializer) {
-      this->operator[](pair.first) = pair.second;
-    }
-  }
-
-  T& operator[](Arch arch) {
-    return data_[size_t(arch)];
-  }
-
-  const T& operator[](Arch arch) const {
-    return data_[size_t(arch)];
-  }
-
-  bool operator==(const ArchMap& other) const {
-    for (size_t i = 0; i < data_.size(); ++i) {
-      if (data_[i] != other.data_[i]) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  ArchMapIterator<T> begin() const {
-    return ArchMapIterator<T>(*this, Arch::arm);
-  }
-
-  ArchMapIterator<T> end() const {
-    return ArchMapIterator<T>(*this, Arch(size_t(Arch::x86_64) + 1));
-  }
-
- private:
-  std::array<T, size_t(Arch::x86_64) + 1> data_ = {};
-};
-
-template <typename T>
-class ArchMapIterator {
-  const ArchMap<T>& map_;
-  Arch arch_ = Arch::arm;
-
- public:
-  ArchMapIterator() = delete;
-
-  ArchMapIterator(const ArchMap<T>& map, Arch arch) : map_(map), arch_(arch) {
-  }
-
-  bool operator==(const ArchMapIterator<T>& rhs) const {
-    return map_ == rhs.map_ && arch_ == rhs.arch_;
-  }
-
-  bool operator!=(const ArchMapIterator<T>& rhs) const {
-    return !(*this == rhs);
-  }
-
-  ArchMapIterator& operator++() {
-    arch_ = Arch(size_t(arch_) + 1);
-    return *this;
-  }
-
-  ArchMapIterator operator++(int) {
-    ArchMapIterator result = *this;
-    ++*this;
-    return result;
-  }
-
-  std::pair<const Arch&, const T&> operator*() const {
-    return std::tie(arch_, map_[arch_]);
-  }
-
-  std::pair<const Arch&, const T&> operator->() const {
-    return std::tie(arch_, map_[arch_]);
-  }
-};
-
-static const std::set<Arch> supported_archs = {
-  Arch::arm,
-  Arch::arm64,
-  Arch::riscv64,
-  Arch::x86,
-  Arch::x86_64,
-};
-
-static ArchMap<std::string> arch_targets = {
-  { Arch::arm, "arm-linux-androideabi" },
-  { Arch::arm64, "aarch64-linux-android" },
-  { Arch::riscv64, "riscv64-linux-android" },
-  { Arch::x86, "i686-linux-android" },
-  { 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, 28, 29, 30, 31, 33, 34,
-};
-
-static const ArchMap<int> arch_min_api = {
-  { Arch::arm, 9 },
-  { Arch::arm64, 21 },
-  { Arch::riscv64, 10000 },
-  { Arch::x86, 9 },
-  { Arch::x86_64, 21 },
-};
-
-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", 29},
-  {"R", 30},
-  {"S", 31},
-  {"T", 33},
-  {"U", 34},
-};
diff --git a/tools/versioner/src/CompilationType.cpp b/tools/versioner/src/CompilationType.cpp
deleted file mode 100644
index 7e7bb5d..0000000
--- a/tools/versioner/src/CompilationType.cpp
+++ /dev/null
@@ -1,27 +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.
- */
-
-#include "CompilationType.h"
-
-#include <sstream>
-#include <string>
-
-std::string to_string(const CompilationType& type) {
-  std::stringstream ss;
-  ss << to_string(type.arch) << "-" << type.api_level << " [" << (type.cpp ? "c++" : "c")
-     << ", fob = " << type.file_offset_bits << "]";
-  return ss.str();
-}
diff --git a/tools/versioner/src/CompilationType.h b/tools/versioner/src/CompilationType.h
deleted file mode 100644
index 2f4cf5c..0000000
--- a/tools/versioner/src/CompilationType.h
+++ /dev/null
@@ -1,70 +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.
- */
-
-#pragma once
-
-#include <stdint.h>
-
-#include <functional>
-#include <utility>
-
-#include "Arch.h"
-
-struct CompilationType {
-  Arch arch;
-  bool cpp;
-  int api_level;
-  int file_offset_bits;
-
- private:
-  auto tie() const {
-    return std::tie(arch, cpp, api_level, file_offset_bits);
-  }
-
- public:
-  bool operator<(const CompilationType& other) const {
-    return tie() < other.tie();
-  }
-
-  bool operator==(const CompilationType& other) const {
-    return tie() == other.tie();
-  }
-};
-
-namespace std {
-template <>
-struct hash<CompilationType> {
-  size_t operator()(CompilationType type) const {
-    struct {
-      int32_t arch : 3;
-      int32_t cpp : 1;
-      int32_t api_level : 6;
-      int32_t file_offset_bits : 1;
-      int32_t padding : 21;
-    } packed;
-    packed.arch = static_cast<int32_t>(type.arch);
-    packed.cpp = type.cpp;
-    packed.api_level = type.api_level;
-    packed.file_offset_bits = (type.file_offset_bits == 64);
-    packed.padding = 0;
-    int32_t value;
-    memcpy(&value, &packed, sizeof(value));
-    return std::hash<int32_t>()(value);
-  }
-};
-}
-
-std::string to_string(const CompilationType& type);
diff --git a/tools/versioner/src/DeclarationDatabase.cpp b/tools/versioner/src/DeclarationDatabase.cpp
deleted file mode 100644
index 9794286..0000000
--- a/tools/versioner/src/DeclarationDatabase.cpp
+++ /dev/null
@@ -1,403 +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.
- */
-
-#include "DeclarationDatabase.h"
-
-#include <err.h>
-
-#include <iostream>
-#include <map>
-#include <mutex>
-#include <set>
-#include <sstream>
-#include <string>
-#include <utility>
-
-#include <clang/AST/AST.h>
-#include <clang/AST/Attr.h>
-#include <clang/AST/Mangle.h>
-#include <clang/AST/RecursiveASTVisitor.h>
-#include <clang/Frontend/ASTUnit.h>
-#include <llvm/Support/raw_ostream.h>
-
-using namespace clang;
-
-static bool shouldMangle(MangleContext* mangler, NamedDecl* decl) {
-  // Passing a decl with static linkage to the mangler gives incorrect results.
-  // Check some things ourselves before handing it off to the mangler.
-  if (auto FD = dyn_cast<FunctionDecl>(decl)) {
-    if (FD->isExternC()) {
-      return false;
-    }
-
-    if (FD->isInExternCContext()) {
-      return false;
-    }
-  }
-
-  return mangler->shouldMangleDeclName(decl);
-}
-
-class Visitor : public RecursiveASTVisitor<Visitor> {
-  HeaderDatabase& database;
-  CompilationType type;
-  SourceManager& src_manager;
-  std::unique_ptr<MangleContext> mangler;
-
- public:
-  Visitor(HeaderDatabase& database, CompilationType type, ASTContext& ctx)
-      : database(database), type(type), src_manager(ctx.getSourceManager()) {
-    mangler.reset(ItaniumMangleContext::create(ctx, ctx.getDiagnostics()));
-  }
-
-  std::string getDeclName(NamedDecl* decl) {
-    if (auto var_decl = dyn_cast<VarDecl>(decl)) {
-      if (!var_decl->isFileVarDecl()) {
-        return "<local var>";
-      }
-    }
-
-    // <math.h> maps fool onto foo on 32-bit, since long double is the same as double.
-    if (auto asm_attr = decl->getAttr<AsmLabelAttr>()) {
-      return asm_attr->getLabel().str();
-    }
-
-    // The decl might not have a name (e.g. bitfields).
-    if (auto identifier = decl->getIdentifier()) {
-      if (shouldMangle(mangler.get(), decl)) {
-        std::string mangled;
-        llvm::raw_string_ostream ss(mangled);
-        mangler->mangleName(decl, ss);
-        return mangled;
-      }
-
-      return identifier->getName().str();
-    }
-
-    return "<unnamed>";
-  }
-
-  bool VisitDeclaratorDecl(DeclaratorDecl* decl, SourceRange range) {
-    // Skip declarations inside of functions (function arguments, variable declarations inside of
-    // inline functions, etc).
-    if (decl->getParentFunctionOrMethod()) {
-      return true;
-    }
-
-    auto named_decl = dyn_cast<NamedDecl>(decl);
-    if (!named_decl) {
-      return true;
-    }
-
-    std::string declaration_name = getDeclName(named_decl);
-    bool is_extern = named_decl->getFormalLinkage() == Linkage::External;
-    bool is_definition = false;
-    bool no_guard = false;
-    bool fortify_inline = false;
-
-    if (auto function_decl = dyn_cast<FunctionDecl>(decl)) {
-      is_definition = function_decl->isThisDeclarationADefinition();
-    } else if (auto var_decl = dyn_cast<VarDecl>(decl)) {
-      if (!var_decl->isFileVarDecl()) {
-        return true;
-      }
-
-      switch (var_decl->isThisDeclarationADefinition()) {
-        case VarDecl::DeclarationOnly:
-          is_definition = false;
-          break;
-
-        case VarDecl::Definition:
-          is_definition = true;
-          break;
-
-        case VarDecl::TentativeDefinition:
-          // Forbid tentative definitions in headers.
-          fprintf(stderr, "ERROR: declaration '%s' is a tentative definition\n",
-                  declaration_name.c_str());
-          decl->dump();
-          abort();
-      }
-    } else {
-      // We only care about function and variable declarations.
-      return true;
-    }
-
-    if (decl->hasAttr<UnavailableAttr>()) {
-      // Skip declarations that exist only for compile-time diagnostics.
-      return true;
-    }
-
-    DeclarationAvailability availability;
-
-    // Find and parse __ANDROID_AVAILABILITY_DUMP__ annotations.
-    for (const AnnotateAttr* attr : decl->specific_attrs<AnnotateAttr>()) {
-      llvm::StringRef annotation = attr->getAnnotation();
-      if (annotation == "versioner_no_guard") {
-        no_guard = true;
-      } else if (annotation == "versioner_fortify_inline") {
-        fortify_inline = true;
-      } else {
-        llvm::SmallVector<llvm::StringRef, 2> fragments;
-        annotation.split(fragments, "=");
-        if (fragments.size() != 2) {
-          continue;
-        }
-
-        auto& global_availability = availability.global_availability;
-        auto& arch_availability = availability.arch_availability;
-        std::map<std::string, std::vector<int*>> prefix_map = {
-          { "introduced_in", { &global_availability.introduced } },
-          { "deprecated_in", { &global_availability.deprecated } },
-          { "obsoleted_in", { &global_availability.obsoleted } },
-          { "introduced_in_arm", { &arch_availability[Arch::arm].introduced } },
-          { "introduced_in_x86", { &arch_availability[Arch::x86].introduced } },
-          { "introduced_in_32",
-            { &arch_availability[Arch::arm].introduced,
-              &arch_availability[Arch::x86].introduced } },
-          { "introduced_in_64",
-            { &arch_availability[Arch::arm64].introduced,
-              &arch_availability[Arch::riscv64].introduced,
-              &arch_availability[Arch::x86_64].introduced } },
-        };
-
-        if (auto it = prefix_map.find(fragments[0].str()); it != prefix_map.end()) {
-          int value;
-          if (fragments[1].getAsInteger(10, value)) {
-            errx(1, "invalid __ANDROID_AVAILABILITY_DUMP__ annotation: '%s'",
-                 annotation.str().c_str());
-          }
-
-          for (int* ptr : it->second) {
-            *ptr = value;
-          }
-        }
-      }
-    }
-
-    auto symbol_it = database.symbols.find(declaration_name);
-    if (symbol_it == database.symbols.end()) {
-      Symbol symbol = {.name = declaration_name };
-      bool unused;
-      std::tie(symbol_it, unused) = database.symbols.insert({declaration_name, symbol});
-    }
-
-    auto expansion_range = src_manager.getExpansionRange(range);
-    auto filename = src_manager.getFilename(expansion_range.getBegin());
-    if (filename != src_manager.getFilename(expansion_range.getEnd())) {
-      errx(1, "expansion range filenames don't match");
-    }
-
-    Location location = {
-      .filename = filename.str(),
-      .start = {
-        .line = src_manager.getExpansionLineNumber(expansion_range.getBegin()),
-        .column = src_manager.getExpansionColumnNumber(expansion_range.getBegin()),
-      },
-      .end = {
-        .line = src_manager.getExpansionLineNumber(expansion_range.getEnd()),
-        .column = src_manager.getExpansionColumnNumber(expansion_range.getEnd()),
-      }
-    };
-
-    // Find or insert an entry for the declaration.
-    if (auto declaration_it = symbol_it->second.declarations.find(location);
-        declaration_it != symbol_it->second.declarations.end()) {
-      if (declaration_it->second.is_extern != is_extern ||
-          declaration_it->second.is_definition != is_definition ||
-          declaration_it->second.no_guard != no_guard ||
-          declaration_it->second.fortify_inline != fortify_inline) {
-        errx(1, "varying declaration of '%s' at %s:%u:%u", declaration_name.c_str(),
-             location.filename.c_str(), location.start.line, location.start.column);
-      }
-      declaration_it->second.availability.insert(std::make_pair(type, availability));
-    } else {
-      Declaration declaration;
-      declaration.name = declaration_name;
-      declaration.location = location;
-      declaration.is_extern = is_extern;
-      declaration.is_definition = is_definition;
-      declaration.no_guard = no_guard;
-      declaration.fortify_inline = fortify_inline;
-      declaration.availability.insert(std::make_pair(type, availability));
-      symbol_it->second.declarations.insert(std::make_pair(location, declaration));
-    }
-
-    return true;
-  }
-
-  bool VisitDeclaratorDecl(DeclaratorDecl* decl) {
-    return VisitDeclaratorDecl(decl, decl->getSourceRange());
-  }
-
-  bool TraverseLinkageSpecDecl(LinkageSpecDecl* decl) {
-    // Make sure that we correctly calculate the SourceRange of a declaration that has a non-braced
-    // extern "C"/"C++".
-    if (!decl->hasBraces()) {
-      DeclaratorDecl* child = nullptr;
-      for (auto child_decl : decl->decls()) {
-        if (child != nullptr) {
-          errx(1, "LinkageSpecDecl has multiple children");
-        }
-
-        if (DeclaratorDecl* declarator_decl = dyn_cast<DeclaratorDecl>(child_decl)) {
-          child = declarator_decl;
-        } else {
-          errx(1, "child of LinkageSpecDecl is not a DeclaratorDecl");
-        }
-      }
-
-      return VisitDeclaratorDecl(child, decl->getSourceRange());
-    }
-
-    for (auto child : decl->decls()) {
-      if (!TraverseDecl(child)) {
-        return false;
-      }
-    }
-    return true;
-  }
-};
-
-bool DeclarationAvailability::merge(const DeclarationAvailability& other) {
-#define check_avail(expr) error |= (!this->expr.empty() && this->expr != other.expr);
-  bool error = false;
-
-  if (!other.global_availability.empty()) {
-    check_avail(global_availability);
-    this->global_availability = other.global_availability;
-  }
-
-  for (Arch arch : supported_archs) {
-    if (!other.arch_availability[arch].empty()) {
-      check_avail(arch_availability[arch]);
-      this->arch_availability[arch] = other.arch_availability[arch];
-    }
-  }
-#undef check_avail
-
-  return !error;
-}
-
-bool Declaration::calculateAvailability(DeclarationAvailability* output) const {
-  DeclarationAvailability avail;
-  for (const auto& it : this->availability) {
-    if (!avail.merge(it.second)) {
-      return false;
-    }
-  }
-  *output = avail;
-  return true;
-}
-
-bool Symbol::calculateAvailability(DeclarationAvailability* output) const {
-  DeclarationAvailability avail;
-  for (const auto& it : this->declarations) {
-    // Don't merge availability for inline functions (because they shouldn't have any).
-    if (it.second.is_definition) {
-      continue;
-    }
-
-    DeclarationAvailability decl_availability;
-    if (!it.second.calculateAvailability(&decl_availability)) {
-      return false;
-      abort();
-    }
-
-    if (!avail.merge(decl_availability)) {
-      return false;
-    }
-  }
-  *output = avail;
-  return true;
-}
-
-bool Symbol::hasDeclaration(const CompilationType& type) const {
-  for (const auto& decl_it : this->declarations) {
-    for (const auto& compilation_it : decl_it.second.availability) {
-      if (compilation_it.first == type) {
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-void HeaderDatabase::parseAST(CompilationType type, ASTContext& ctx) {
-  std::unique_lock<std::mutex> lock(this->mutex);
-  Visitor visitor(*this, type, ctx);
-  visitor.TraverseDecl(ctx.getTranslationUnitDecl());
-}
-
-std::string to_string(const AvailabilityValues& av) {
-  std::stringstream ss;
-
-  if (av.introduced != 0) {
-    ss << "introduced = " << av.introduced << ", ";
-  }
-
-  if (av.deprecated != 0) {
-    ss << "deprecated = " << av.deprecated << ", ";
-  }
-
-  if (av.obsoleted != 0) {
-    ss << "obsoleted = " << av.obsoleted << ", ";
-  }
-
-  std::string result = ss.str();
-  if (!result.empty()) {
-    result = result.substr(0, result.length() - 2);
-  }
-  return result;
-}
-
-std::string to_string(const DeclarationType& type) {
-  switch (type) {
-    case DeclarationType::function:
-      return "function";
-    case DeclarationType::variable:
-      return "variable";
-    case DeclarationType::inconsistent:
-      return "inconsistent";
-  }
-  abort();
-}
-
-std::string to_string(const DeclarationAvailability& decl_av) {
-  std::stringstream ss;
-  if (!decl_av.global_availability.empty()) {
-    ss << to_string(decl_av.global_availability) << ", ";
-  }
-
-  for (const auto& it : decl_av.arch_availability) {
-    if (!it.second.empty()) {
-      ss << to_string(it.first) << ": " << to_string(it.second) << ", ";
-    }
-  }
-
-  std::string result = ss.str();
-  if (result.size() == 0) {
-    return "no availability";
-  }
-
-  return result.substr(0, result.length() - 2);
-}
-
-std::string to_string(const Location& loc) {
-  std::stringstream ss;
-  ss << loc.filename << ":" << loc.start.line << ":" << loc.start.column;
-  return ss.str();
-}
diff --git a/tools/versioner/src/DeclarationDatabase.h b/tools/versioner/src/DeclarationDatabase.h
deleted file mode 100644
index 9a45227..0000000
--- a/tools/versioner/src/DeclarationDatabase.h
+++ /dev/null
@@ -1,212 +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.
- */
-
-#pragma once
-
-#include <stdio.h>
-
-#include <map>
-#include <mutex>
-#include <set>
-#include <string>
-#include <vector>
-
-#include <llvm/ADT/StringRef.h>
-
-#include "Arch.h"
-#include "CompilationType.h"
-#include "Utils.h"
-
-namespace clang {
-class ASTContext;
-class Decl;
-}
-
-enum class DeclarationType {
-  function,
-  variable,
-  inconsistent,
-};
-
-struct AvailabilityValues {
-  int introduced = 0;
-  int deprecated = 0;
-  int obsoleted = 0;
-
-  bool empty() const {
-    return !(introduced || deprecated || obsoleted);
-  }
-
-  bool operator==(const AvailabilityValues& rhs) const {
-    return std::tie(introduced, deprecated, obsoleted) ==
-           std::tie(rhs.introduced, rhs.deprecated, rhs.obsoleted);
-  }
-
-  bool operator!=(const AvailabilityValues& rhs) const {
-    return !(*this == rhs);
-  }
-};
-
-std::string to_string(const AvailabilityValues& av);
-
-struct DeclarationAvailability {
-  AvailabilityValues global_availability;
-  ArchMap<AvailabilityValues> arch_availability;
-
-  bool empty() const {
-    if (!global_availability.empty()) {
-      return false;
-    }
-
-    for (const auto& it : arch_availability) {
-      if (!it.second.empty()) {
-        return false;
-      }
-    }
-
-    return true;
-  }
-
-  bool operator==(const DeclarationAvailability& rhs) const {
-    return std::tie(global_availability, arch_availability) ==
-           std::tie(rhs.global_availability, rhs.arch_availability);
-  }
-
-  bool operator!=(const DeclarationAvailability& rhs) const {
-    return !(*this == rhs);
-  }
-
-  // Returns false if the availability declarations conflict.
-  bool merge(const DeclarationAvailability& other);
-};
-
-std::string to_string(const DeclarationAvailability& decl_av);
-
-struct FileLocation {
-  unsigned line;
-  unsigned column;
-
-  bool operator<(const FileLocation& rhs) const {
-    return std::tie(line, column) < std::tie(rhs.line, rhs.column);
-  }
-
-  bool operator==(const FileLocation& rhs) const {
-    return std::tie(line, column) == std::tie(rhs.line, rhs.column);
-  }
-};
-
-struct Location {
-  std::string filename;
-  FileLocation start;
-  FileLocation end;
-
-  bool operator<(const Location& rhs) const {
-    return std::tie(filename, start, end) < std::tie(rhs.filename, rhs.start, rhs.end);
-  }
-};
-
-std::string to_string(const Location& loc);
-
-struct Declaration {
-  std::string name;
-  Location location;
-
-  bool is_extern;
-  bool is_definition;
-  bool no_guard;
-  bool fortify_inline;
-  std::map<CompilationType, DeclarationAvailability> availability;
-
-  bool calculateAvailability(DeclarationAvailability* output) const;
-  bool operator<(const Declaration& rhs) const {
-    return location < rhs.location;
-  }
-
-  void dump(const std::string& base_path = "", FILE* out = stdout, unsigned indent = 0) const {
-    std::string indent_str(indent, ' ');
-    fprintf(out, "%s", indent_str.c_str());
-
-    fprintf(out, "%s ", is_extern ? "extern" : "static");
-    fprintf(out, "%s ", is_definition ? "definition" : "declaration");
-    if (no_guard) {
-      fprintf(out, "no_guard ");
-    }
-    if (fortify_inline) {
-      fprintf(out, "fortify_inline ");
-    }
-    fprintf(out, "@ %s:%u:%u", StripPrefix(location.filename, base_path).str().c_str(),
-            location.start.line, location.start.column);
-
-    if (!availability.empty()) {
-      DeclarationAvailability avail;
-
-      fprintf(out, "\n%s  ", indent_str.c_str());
-      if (!calculateAvailability(&avail)) {
-        fprintf(out, "invalid availability\n");
-      } else {
-        fprintf(out, "%s\n", to_string(avail).c_str());
-      }
-    }
-  }
-};
-
-struct Symbol {
-  std::string name;
-  std::map<Location, Declaration> declarations;
-
-  bool calculateAvailability(DeclarationAvailability* output) const;
-  bool hasDeclaration(const CompilationType& type) const;
-
-  bool operator<(const Symbol& rhs) const {
-    return name < rhs.name;
-  }
-
-  bool operator==(const Symbol& rhs) const {
-    return name == rhs.name;
-  }
-
-  void dump(const std::string& base_path = "", FILE* out = stdout) const {
-    DeclarationAvailability availability;
-    bool valid_availability = calculateAvailability(&availability);
-    fprintf(out, "  %s: ", name.c_str());
-
-    if (valid_availability) {
-      fprintf(out, "%s\n", to_string(availability).c_str());
-    } else {
-      fprintf(out, "invalid\n");
-    }
-
-    for (auto& it : declarations) {
-      it.second.dump(base_path, out, 4);
-    }
-  }
-};
-
-class HeaderDatabase {
-  std::mutex mutex;
-
- public:
-  std::map<std::string, Symbol> symbols;
-
-  void parseAST(CompilationType type, clang::ASTContext& ast);
-
-  void dump(const std::string& base_path = "", FILE* out = stdout) const {
-    fprintf(out, "HeaderDatabase contains %zu symbols:\n", symbols.size());
-    for (const auto& pair : symbols) {
-      pair.second.dump(base_path, out);
-    }
-  }
-};
diff --git a/tools/versioner/src/Driver.cpp b/tools/versioner/src/Driver.cpp
deleted file mode 100644
index 79672ac..0000000
--- a/tools/versioner/src/Driver.cpp
+++ /dev/null
@@ -1,265 +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.
- */
-
-#include "Driver.h"
-
-#include <err.h>
-#include <string.h>
-
-#include <chrono>
-#include <mutex>
-#include <string>
-#include <thread>
-#include <unordered_map>
-#include <vector>
-
-#include <clang/AST/ASTConsumer.h>
-#include <clang/Basic/Diagnostic.h>
-#include <clang/Basic/TargetInfo.h>
-#include <clang/Driver/Compilation.h>
-#include <clang/Driver/Driver.h>
-#include <clang/Frontend/CompilerInstance.h>
-#include <clang/Frontend/CompilerInvocation.h>
-#include <clang/Frontend/FrontendAction.h>
-#include <clang/Frontend/FrontendActions.h>
-#include <clang/Frontend/TextDiagnosticPrinter.h>
-#include <clang/Frontend/Utils.h>
-#include <clang/FrontendTool/Utils.h>
-#include <llvm/ADT/IntrusiveRefCntPtr.h>
-#include <llvm/ADT/SmallVector.h>
-#include <llvm/ADT/StringRef.h>
-#include <llvm/Option/Option.h>
-#include <llvm/TargetParser/Host.h>
-#include <llvm/Support/VirtualFileSystem.h>
-
-#include "Arch.h"
-#include "DeclarationDatabase.h"
-#include "versioner.h"
-
-using namespace std::chrono_literals;
-using namespace std::string_literals;
-
-using namespace clang;
-
-class VersionerASTConsumer : public clang::ASTConsumer {
- public:
-  HeaderDatabase* header_database;
-  CompilationType type;
-
-  VersionerASTConsumer(HeaderDatabase* header_database, CompilationType type)
-      : header_database(header_database), type(type) {
-  }
-
-  void HandleTranslationUnit(ASTContext& ctx) override {
-    header_database->parseAST(type, ctx);
-  }
-};
-
-class VersionerASTAction : public clang::ASTFrontendAction {
- public:
-  HeaderDatabase* header_database;
-  CompilationType type;
-
-  VersionerASTAction(HeaderDatabase* header_database, CompilationType type)
-      : header_database(header_database), type(type) {
-  }
-
-  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance&, llvm::StringRef) override {
-    return std::make_unique<VersionerASTConsumer>(header_database, type);
-  }
-};
-
-static IntrusiveRefCntPtr<DiagnosticsEngine> constructDiags() {
-  IntrusiveRefCntPtr<DiagnosticOptions> diag_opts(new DiagnosticOptions());
-  auto diag_printer = std::make_unique<TextDiagnosticPrinter>(llvm::errs(), diag_opts.get());
-  IntrusiveRefCntPtr<DiagnosticIDs> diag_ids(new DiagnosticIDs());
-  IntrusiveRefCntPtr<DiagnosticsEngine> diags(
-      new DiagnosticsEngine(diag_ids.get(), diag_opts.get(), diag_printer.release()));
-  return diags;
-}
-
-// clang's driver is slow compared to the work it performs to compile our headers.
-// 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<llvm::vfs::FileSystem> vfs,
-                                   CompilationType type,
-                                   const std::vector<std::string>& include_dirs) {
-  std::vector<std::string> cmd = { "versioner" };
-  if (type.cpp) {
-    cmd.push_back("-std=gnu++11");
-    cmd.push_back("-x");
-    cmd.push_back("c++");
-  } else {
-    cmd.push_back("-std=gnu11");
-    cmd.push_back("-x");
-    cmd.push_back("c");
-  }
-
-  cmd.push_back("-fsyntax-only");
-
-  cmd.push_back("-Wall");
-  cmd.push_back("-Wextra");
-  cmd.push_back("-Weverything");
-  cmd.push_back("-Werror");
-  cmd.push_back("-Wundef");
-  cmd.push_back("-Wno-unused-macros");
-  cmd.push_back("-Wno-unused-function");
-  cmd.push_back("-Wno-unused-variable");
-  cmd.push_back("-Wno-unknown-attributes");
-  cmd.push_back("-Wno-pragma-once-outside-header");
-
-  cmd.push_back("-target");
-  cmd.push_back(arch_targets[type.arch]);
-
-  cmd.push_back("-DANDROID");
-  cmd.push_back("-D__BIONIC_VERSIONER=1");
-  cmd.push_back("-D__ANDROID_API__="s + std::to_string(type.api_level));
-  cmd.push_back("-D_FORTIFY_SOURCE=2");
-  cmd.push_back("-D_GNU_SOURCE");
-  cmd.push_back("-D_FILE_OFFSET_BITS="s + std::to_string(type.file_offset_bits));
-
-  cmd.push_back("-nostdinc");
-
-  if (add_include) {
-    cmd.push_back("-include");
-    cmd.push_back("android/versioning.h");
-  }
-
-  for (const auto& dir : include_dirs) {
-    cmd.push_back("-isystem");
-    cmd.push_back(dir);
-  }
-
-  cmd.push_back("-include");
-  cmd.push_back(filename_placeholder);
-  cmd.push_back("-");
-
-  auto diags = constructDiags();
-  driver::Driver driver("versioner", llvm::sys::getDefaultTargetTriple(), *diags, "versioner", vfs);
-  driver.setCheckInputsExist(false);
-
-  llvm::SmallVector<const char*, 32> driver_args;
-  for (const std::string& str : cmd) {
-    driver_args.push_back(str.c_str());
-  }
-
-  std::unique_ptr<driver::Compilation> Compilation(driver.BuildCompilation(driver_args));
-  const driver::JobList& jobs = Compilation->getJobs();
-  if (jobs.size() != 1) {
-    errx(1, "driver returned %zu jobs for %s", jobs.size(), to_string(type).c_str());
-  }
-
-  const driver::Command& driver_cmd = llvm::cast<driver::Command>(*jobs.begin());
-  const llvm::opt::ArgStringList& cc_args = driver_cmd.getArguments();
-
-  if (cc_args.size() == 0) {
-    errx(1, "driver returned empty command for %s", to_string(type).c_str());
-  }
-
-  std::vector<std::string> result(cc_args.begin(), cc_args.end());
-
-  {
-    static std::mutex cc1_init_mutex;
-    std::unique_lock<std::mutex> lock(cc1_init_mutex);
-    if (cc1_flags.count(type) > 0) {
-      errx(1, "attemped to generate cc1 flags for existing CompilationType %s",
-           to_string(type).c_str());
-    }
-
-    cc1_flags.emplace(std::make_pair(type, std::move(result)));
-  }
-}
-
-static std::vector<const char*> getCC1Command(CompilationType type, const std::string& filename) {
-  const auto& target_flag_it = cc1_flags.find(type);
-  if (target_flag_it == cc1_flags.end()) {
-    errx(1, "failed to find target flags for CompilationType %s", to_string(type).c_str());
-  }
-
-  std::vector<const char*> result;
-  for (const std::string& flag : target_flag_it->second) {
-    if (flag == "-disable-free") {
-      continue;
-    } else if (flag == filename_placeholder) {
-      result.push_back(filename.c_str());
-    } else {
-      result.push_back(flag.c_str());
-    }
-  }
-  return result;
-}
-
-void initializeTargetCC1FlagCache(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
-                                  const std::set<CompilationType>& types,
-                                  const std::unordered_map<Arch, CompilationRequirements>& reqs) {
-  if (!cc1_flags.empty()) {
-    errx(1, "reinitializing target CC1 flag cache?");
-  }
-
-  auto start = std::chrono::high_resolution_clock::now();
-  std::vector<std::thread> threads;
-  for (const CompilationType type : types) {
-    threads.emplace_back([type, &vfs, &reqs]() {
-      const auto& arch_req_it = reqs.find(type.arch);
-      if (arch_req_it == reqs.end()) {
-        errx(1, "CompilationRequirement map missing entry for CompilationType %s",
-             to_string(type).c_str());
-      }
-
-      generateTargetCC1Flags(vfs, type, arch_req_it->second.dependencies);
-    });
-  }
-  for (auto& thread : threads) {
-    thread.join();
-  }
-  auto end = std::chrono::high_resolution_clock::now();
-
-  if (verbose) {
-    auto diff = (end - start) / 1.0ms;
-    printf("Generated compiler flags for %zu targets in %0.2Lfms\n", types.size(), diff);
-  }
-
-  if (cc1_flags.empty()) {
-    errx(1, "failed to initialize target CC1 flag cache");
-  }
-}
-
-void compileHeader(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
-                   HeaderDatabase* header_database, CompilationType type,
-                   const std::string& filename) {
-  auto diags = constructDiags();
-  std::vector<const char*> cc1_flags = getCC1Command(type, filename);
-  auto invocation = std::make_unique<CompilerInvocation>();
-  if (!CompilerInvocation::CreateFromArgs(*invocation.get(), cc1_flags, *diags)) {
-    errx(1, "failed to create CompilerInvocation");
-  }
-
-  clang::CompilerInstance Compiler;
-
-  Compiler.setInvocation(std::move(invocation));
-  Compiler.setDiagnostics(diags.get());
-  Compiler.createFileManager(vfs);
-
-  VersionerASTAction versioner_action(header_database, type);
-  if (!Compiler.ExecuteAction(versioner_action)) {
-    errx(1, "compilation generated warnings or errors");
-  }
-
-  if (diags->getNumWarnings() || diags->hasErrorOccurred()) {
-    errx(1, "compilation generated warnings or errors");
-  }
-}
diff --git a/tools/versioner/src/Driver.h b/tools/versioner/src/Driver.h
deleted file mode 100644
index 99e57ae..0000000
--- a/tools/versioner/src/Driver.h
+++ /dev/null
@@ -1,40 +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.
- */
-
-#pragma once
-
-#include <set>
-#include <string>
-#include <unordered_map>
-
-#include <llvm/ADT/IntrusiveRefCntPtr.h>
-
-#include "Arch.h"
-#include "DeclarationDatabase.h"
-#include "VFS.h"
-
-struct CompilationRequirements {
-  std::vector<std::string> headers;
-  std::vector<std::string> dependencies;
-};
-
-void initializeTargetCC1FlagCache(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
-                                  const std::set<CompilationType>& types,
-                                  const std::unordered_map<Arch, CompilationRequirements>& reqs);
-
-void compileHeader(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
-                   HeaderDatabase* header_database, CompilationType type,
-                   const std::string& filename);
diff --git a/tools/versioner/src/Preprocessor.cpp b/tools/versioner/src/Preprocessor.cpp
deleted file mode 100644
index 74d5ba0..0000000
--- a/tools/versioner/src/Preprocessor.cpp
+++ /dev/null
@@ -1,504 +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.
- */
-
-#include "Preprocessor.h"
-
-#include <err.h>
-#include <fcntl.h>
-#include <fts.h>
-#include <libgen.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <deque>
-#include <fstream>
-#include <string>
-#include <unordered_map>
-
-#include <llvm/ADT/StringRef.h>
-#include <llvm/ADT/Twine.h>
-#include <llvm/Support/FileSystem.h>
-#include <llvm/Support/Path.h>
-
-#include "Arch.h"
-#include "DeclarationDatabase.h"
-#include "versioner.h"
-
-using namespace std::string_literals;
-
-static DeclarationAvailability calculateRequiredGuard(const Declaration& declaration) {
-  // To avoid redundant macro guards, the availability calculated by this function is the set
-  // difference of 'targets marked-available' from 'targets the declaration is visible in'.
-  // For example, a declaration that is visible always and introduced in 9 would return introduced
-  // in 9, but the same declaration, except only visible in 9+ would return an empty
-  // DeclarationAvailability.
-
-  // This currently only handles __INTRODUCED_IN.
-  // TODO: Do the same for __REMOVED_IN.
-  int global_min_api_visible = 0;
-  ArchMap<int> arch_visibility;
-
-  for (const auto& it : declaration.availability) {
-    const CompilationType& type = it.first;
-
-    if (global_min_api_visible == 0 || global_min_api_visible > type.api_level) {
-      global_min_api_visible = type.api_level;
-    }
-
-    if (arch_visibility[type.arch] == 0 || arch_visibility[type.arch] > type.api_level) {
-      arch_visibility[type.arch] = type.api_level;
-    }
-  }
-
-  DeclarationAvailability decl_av;
-  if (!declaration.calculateAvailability(&decl_av)) {
-    fprintf(stderr, "versioner: failed to calculate availability while preprocessing:\n");
-    declaration.dump("", stderr, 2);
-    exit(1);
-  }
-
-  D("Calculating required guard for %s:\n", declaration.name.c_str());
-  D("  Declaration availability: %s\n", to_string(decl_av).c_str());
-
-  if (verbose) {
-    std::string arch_visibility_str;
-    for (Arch arch : supported_archs) {
-      if (arch_visibility[arch] != 0) {
-        arch_visibility_str += to_string(arch);
-        arch_visibility_str += ": ";
-        arch_visibility_str += std::to_string(arch_visibility[arch]);
-        arch_visibility_str += ", ";
-      }
-    }
-    if (!arch_visibility_str.empty()) {
-      arch_visibility_str.resize(arch_visibility_str.size() - 2);
-    }
-    D("  Declaration visibility: global = %d, arch = %s\n", global_min_api_visible,
-      arch_visibility_str.c_str());
-  }
-
-  DeclarationAvailability result = decl_av;
-  if (result.global_availability.introduced <= global_min_api_visible) {
-    result.global_availability.introduced = 0;
-  }
-
-  for (Arch arch : supported_archs) {
-    if (result.arch_availability[arch].introduced <= arch_visibility[arch] ||
-        result.arch_availability[arch].introduced <= arch_min_api[arch]) {
-      result.arch_availability[arch].introduced = 0;
-    }
-  }
-
-  D("  Calculated result: %s\n", to_string(result).c_str());
-  D("\n");
-
-  return result;
-}
-
-static std::deque<std::string> readFileLines(const std::string& path) {
-  std::ifstream is(path.c_str());
-  std::deque<std::string> result;
-  std::string line;
-
-  while (std::getline(is, line)) {
-    result.push_back(std::move(line));
-  }
-
-  return result;
-}
-
-static void writeFileLines(const std::string& path, const std::deque<std::string>& lines) {
-  if (!mkdirs(dirname(path))) {
-    err(1, "failed to create directory '%s'", dirname(path).c_str());
-  }
-
-  std::ofstream os(path.c_str(), std::ios_base::out | std::ios_base::trunc);
-
-  for (const std::string& line : lines) {
-    os << line << "\n";
-  }
-}
-
-using GuardMap = std::map<Location, DeclarationAvailability>;
-
-static std::string generateGuardCondition(const DeclarationAvailability& avail) {
-  // Logically orred expressions that constitute the macro guard.
-  std::vector<std::string> expressions;
-  static const std::vector<std::pair<std::string, std::set<Arch>>> arch_sets = {
-      {"!defined(__LP64__)", {Arch::arm, Arch::x86}},
-      {"defined(__LP64__)", {Arch::arm64, Arch::riscv64, Arch::x86_64}},
-  };
-  std::map<Arch, std::string> individual_archs = {
-    { Arch::arm, "defined(__arm__)" },
-    { Arch::arm64, "defined(__aarch64__)" },
-    { Arch::riscv64, "defined(__riscv)" },
-    { Arch::x86, "defined(__i386__)" },
-    { Arch::x86_64, "defined(__x86_64__)" },
-  };
-
-  auto generate_guard = [](const std::string& arch_expr, int min_version) {
-    if (min_version == 0) {
-      return arch_expr;
-    }
-    return arch_expr + " && __ANDROID_API__ >= " + std::to_string(min_version);
-  };
-
-  D("Generating guard for availability: %s\n", to_string(avail).c_str());
-  if (!avail.global_availability.empty()) {
-    for (Arch arch : supported_archs) {
-      if (!avail.arch_availability[arch].empty()) {
-        errx(1, "attempted to generate guard with global and per-arch values: %s",
-             to_string(avail).c_str());
-      }
-    }
-
-    if (avail.global_availability.introduced == 0) {
-      // We currently get here for the "__sF" symbol because it's marked __REMOVED_IN(23). This
-      // symbol is the only use of __REMOVED_IN, and it's already guarded manually, so there's no
-      // need to do anything.
-      fprintf(stderr, "warning: attempted to generate guard with empty availability: %s\n",
-              to_string(avail).c_str());
-      return "";
-    }
-
-    if (avail.global_availability.introduced <= 9) {
-      return "";
-    }
-
-    return "__ANDROID_API__ >= "s + std::to_string(avail.global_availability.introduced);
-  }
-
-  for (const auto& it : arch_sets) {
-    const std::string& arch_expr = it.first;
-    const std::set<Arch>& archs = it.second;
-
-    D("  Checking arch set '%s'\n", arch_expr.c_str());
-
-    int version = 0;
-
-    // Find the architectures that need to check __ANDROID_API__ and verify that they check against
-    // the same API level.
-    for (Arch arch : archs) {
-      const int arch_version = avail.arch_availability[arch].introduced;
-      if (arch_version == 0) {
-        continue;
-      } else if (version == 0) {
-        version = arch_version;
-      } else if (version != arch_version) {
-        D("    Skipping arch set, availability for %s doesn't match %s\n",
-          to_string(*it.second.begin()).c_str(), to_string(arch).c_str());
-        goto skip;
-      }
-    }
-
-    // Verify that a non-zero version is acceptable to reuse for other archs with a higher minimum
-    // API, like riscv64. (e.g. It's OK to reuse an (__ANDROID_API__ >= 24) check if the arch's
-    // minimum API is 35.)
-    if (version != 0) {
-      for (Arch arch : archs) {
-        const int arch_version = avail.arch_availability[arch].introduced;
-        if (arch_version == 0 && version > arch_min_api[arch]) {
-          D("    Skipping arch set, availability for %s doesn't match %s\n",
-            to_string(*it.second.begin()).c_str(), to_string(arch).c_str());
-          goto skip;
-        }
-      }
-    }
-
-    expressions.emplace_back(generate_guard(arch_expr, version));
-
-    D("    Generated expression '%s'\n", expressions.rbegin()->c_str());
-
-    for (Arch arch : archs) {
-      individual_archs.erase(arch);
-    }
-
-  skip:
-    continue;
-  }
-
-  for (const auto& it : individual_archs) {
-    const std::string& arch_expr = it.second;
-    int introduced = avail.arch_availability[it.first].introduced;
-    expressions.emplace_back(generate_guard(arch_expr, introduced));
-  }
-
-  if (expressions.size() == 0) {
-    errx(1, "generated empty guard for availability %s", to_string(avail).c_str());
-  } else if (expressions.size() == 1) {
-    return expressions[0];
-  }
-
-  return "("s + Join(expressions, ") || (") + ")";
-}
-
-// Assumes that nothing weird is happening (e.g. having the semicolon be in a macro).
-static FileLocation findNextSemicolon(const std::deque<std::string>& lines, FileLocation start) {
-  unsigned current_line = start.line;
-  unsigned current_column = start.column;
-  while (current_line <= lines.size()) {
-    size_t result = lines[current_line - 1].find_first_of(';', current_column - 1);
-
-    if (result != std::string::npos) {
-      FileLocation loc = {
-        .line = current_line,
-        .column = unsigned(result) + 1,
-      };
-
-      return loc;
-    }
-
-    ++current_line;
-    current_column = 0;
-  }
-
-  errx(1, "failed to find semicolon starting from %u:%u", start.line, start.column);
-}
-
-// Merge adjacent blocks with identical guards.
-static void mergeGuards(std::deque<std::string>& file_lines, GuardMap& guard_map) {
-  if (guard_map.size() < 2) {
-    return;
-  }
-
-  auto current = guard_map.begin();
-  auto next = current;
-  ++next;
-
-  while (next != guard_map.end()) {
-    if (current->second != next->second) {
-      ++current;
-      ++next;
-      continue;
-    }
-
-    // Scan from the end of current to the beginning of next.
-    bool in_block_comment = false;
-    bool valid = true;
-
-    FileLocation current_location = current->first.end;
-    FileLocation end_location = next->first.start;
-
-    auto nextLine = [&current_location]() {
-      ++current_location.line;
-      current_location.column = 1;
-    };
-
-    auto nextCol = [&file_lines, &current_location, &nextLine]() {
-      if (current_location.column == file_lines[current_location.line - 1].length()) {
-        nextLine();
-      } else {
-        ++current_location.column;
-      }
-    };
-
-    // The end location will point to the semicolon, which we don't want to read, so skip it.
-    nextCol();
-
-    while (current_location < end_location) {
-      const std::string& line = file_lines[current_location.line - 1];
-      size_t line_index = current_location.column - 1;
-
-      if (in_block_comment) {
-        size_t pos = line.find("*/", line_index);
-        if (pos == std::string::npos) {
-          D("Didn't find block comment terminator, skipping line\n");
-          nextLine();
-          continue;
-        } else {
-          D("Found block comment terminator\n");
-          in_block_comment = false;
-          current_location.column = pos + 2;
-          nextCol();
-          continue;
-        }
-      } else {
-        size_t pos = line.find_first_not_of(" \t", line_index);
-        if (pos == std::string::npos) {
-          nextLine();
-          continue;
-        }
-
-        current_location.column = pos + 1;
-        if (line[pos] != '/') {
-          valid = false;
-          break;
-        }
-
-        nextCol();
-        if (line.length() <= pos + 1) {
-          // Trailing slash at the end of a line?
-          D("Trailing slash at end of line\n");
-          valid = false;
-          break;
-        }
-
-        if (line[pos + 1] == '/') {
-          // C++ style comment
-          nextLine();
-        } else if (line[pos + 1] == '*') {
-          // Block comment
-          nextCol();
-          in_block_comment = true;
-          D("In a block comment\n");
-        } else {
-          // Garbage?
-          D("Unexpected output after /: %s\n", line.substr(pos).c_str());
-          valid = false;
-          break;
-        }
-      }
-    }
-
-    if (!valid) {
-      D("Not merging blocks %s and %s\n", to_string(current->first).c_str(),
-        to_string(next->first).c_str());
-      ++current;
-      ++next;
-      continue;
-    }
-
-    D("Merging blocks %s and %s\n", to_string(current->first).c_str(),
-      to_string(next->first).c_str());
-
-    Location merged = current->first;
-    merged.end = next->first.end;
-
-    DeclarationAvailability avail = current->second;
-
-    guard_map.erase(current);
-    guard_map.erase(next);
-    bool unused;
-    std::tie(current, unused) = guard_map.insert(std::make_pair(merged, avail));
-    next = current;
-    ++next;
-  }
-}
-
-static void rewriteFile(const std::string& output_path, std::deque<std::string>& file_lines,
-                        const GuardMap& guard_map) {
-  for (auto it = guard_map.rbegin(); it != guard_map.rend(); ++it) {
-    const Location& loc = it->first;
-    const DeclarationAvailability& avail = it->second;
-
-    std::string condition = generateGuardCondition(avail);
-    if (condition.empty()) {
-      continue;
-    }
-
-    std::string prologue = "\n#if "s + condition + "\n";
-    std::string epilogue = "\n#endif /* " + condition + " */\n";
-
-    file_lines[loc.end.line - 1].insert(loc.end.column, epilogue);
-    file_lines[loc.start.line - 1].insert(loc.start.column - 1, prologue);
-  }
-
-  if (verbose) {
-    printf("Preprocessing %s...\n", output_path.c_str());
-  }
-  writeFileLines(output_path, file_lines);
-}
-
-bool preprocessHeaders(const std::string& dst_dir, const std::string& src_dir,
-                       HeaderDatabase* database) {
-  std::unordered_map<std::string, GuardMap> guards;
-  std::unordered_map<std::string, std::deque<std::string>> file_lines;
-
-  for (const auto& symbol_it : database->symbols) {
-    const Symbol& symbol = symbol_it.second;
-
-    for (const auto& decl_it : symbol.declarations) {
-      const Location& location = decl_it.first;
-      const Declaration& decl = decl_it.second;
-
-      if (decl.no_guard) {
-        // No guard required.
-        continue;
-      }
-
-      DeclarationAvailability macro_guard = calculateRequiredGuard(decl);
-      if (!macro_guard.empty()) {
-        guards[location.filename][location] = macro_guard;
-      }
-    }
-  }
-
-  // Copy over the original headers before preprocessing.
-  char* fts_paths[2] = { const_cast<char*>(src_dir.c_str()), nullptr };
-  std::unique_ptr<FTS, decltype(&fts_close)> fts(fts_open(fts_paths, FTS_LOGICAL, nullptr),
-                                                 fts_close);
-  if (!fts) {
-    err(1, "failed to open directory %s", src_dir.c_str());
-  }
-
-  while (FTSENT* ent = fts_read(fts.get())) {
-    llvm::StringRef path = ent->fts_path;
-    if (!path.starts_with(src_dir)) {
-      err(1, "path '%s' doesn't start with source dir '%s'", ent->fts_path, src_dir.c_str());
-    }
-
-    if (ent->fts_info != FTS_F) {
-      continue;
-    }
-
-    std::string rel_path = path.substr(src_dir.length() + 1).str();
-    std::string dst_path = dst_dir + "/" + rel_path;
-    llvm::StringRef parent_path = llvm::sys::path::parent_path(dst_path);
-    if (llvm::sys::fs::create_directories(parent_path)) {
-      errx(1, "failed to ensure existence of directory '%s'", parent_path.str().c_str());
-    }
-    if (llvm::sys::fs::copy_file(path, dst_path)) {
-      errx(1, "failed to copy '%s/%s' to '%s'", src_dir.c_str(), path.str().c_str(),
-           dst_path.c_str());
-    }
-  }
-
-  for (const auto& file_it : guards) {
-    file_lines[file_it.first] = readFileLines(file_it.first);
-  }
-
-  for (auto& file_it : guards) {
-    llvm::StringRef file_path = file_it.first;
-    GuardMap& orig_guard_map = file_it.second;
-
-    // The end positions given to us are the end of the declaration, which is some point before the
-    // semicolon. Fix up the end positions by scanning for the next semicolon.
-    GuardMap guard_map;
-    for (const auto& it : orig_guard_map) {
-      Location loc = it.first;
-      loc.end = findNextSemicolon(file_lines[file_path.str()], loc.end);
-      guard_map[loc] = it.second;
-    }
-
-    // TODO: Make sure that the Locations don't overlap.
-    // TODO: Merge adjacent non-identical guards.
-    mergeGuards(file_lines[file_path.str()], guard_map);
-
-    if (!file_path.starts_with(src_dir)) {
-      errx(1, "input file %s is not in %s\n", file_path.str().c_str(), src_dir.c_str());
-    }
-
-    // rel_path has a leading slash.
-    llvm::StringRef rel_path = file_path.substr(src_dir.size(), file_path.size() - src_dir.size());
-    std::string output_path = (llvm::Twine(dst_dir) + rel_path).str();
-
-    rewriteFile(output_path, file_lines[file_path.str()], guard_map);
-  }
-
-  return true;
-}
diff --git a/tools/versioner/src/SymbolDatabase.cpp b/tools/versioner/src/SymbolDatabase.cpp
deleted file mode 100644
index c483c0f..0000000
--- a/tools/versioner/src/SymbolDatabase.cpp
+++ /dev/null
@@ -1,115 +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.
- */
-
-#include "SymbolDatabase.h"
-
-#include "SymbolFileParser.h"
-
-#include <err.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <fstream>
-#include <streambuf>
-#include <string>
-#include <unordered_set>
-
-#include <llvm/ADT/SmallVector.h>
-#include <llvm/ADT/StringRef.h>
-#include <llvm/Object/Binary.h>
-#include <llvm/Object/ELFObjectFile.h>
-
-#include "versioner.h"
-
-using namespace llvm;
-using namespace llvm::object;
-
-std::unordered_set<std::string> getSymbols(const std::string& filename) {
-  std::unordered_set<std::string> result;
-  auto binaryOrError = createBinary(filename);
-  if (!binaryOrError) {
-    errx(1, "failed to open library at %s: %s\n", filename.c_str(),
-         llvm::toString(binaryOrError.takeError()).c_str());
-  }
-
-  ELFObjectFileBase* elf = dyn_cast_or_null<ELFObjectFileBase>(binaryOrError.get().getBinary());
-  if (!elf) {
-    errx(1, "failed to parse %s as ELF", filename.c_str());
-  }
-
-  for (const ELFSymbolRef symbol : elf->getDynamicSymbolIterators()) {
-    Expected<StringRef> symbolNameOrError = symbol.getName();
-
-    if (!symbolNameOrError) {
-      errx(1, "failed to get symbol name for symbol in %s: %s", filename.c_str(),
-           llvm::toString(symbolNameOrError.takeError()).c_str());
-    }
-
-    result.insert(symbolNameOrError.get().str());
-  }
-
-  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
deleted file mode 100644
index dbbba4f..0000000
--- a/tools/versioner/src/SymbolDatabase.h
+++ /dev/null
@@ -1,37 +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.
- */
-
-#pragma once
-
-#include <map>
-#include <optional>
-#include <set>
-#include <string>
-#include <unordered_set>
-
-#include "DeclarationDatabase.h"
-
-using LibrarySymbolDatabase = std::unordered_set<std::string>;
-std::unordered_set<std::string> getSymbols(const std::string& filename);
-
-enum class NdkSymbolType {
-  function,
-  variable,
-};
-
-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
deleted file mode 100644
index 1b4adae..0000000
--- a/tools/versioner/src/SymbolFileParser.cpp
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * 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 (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 == parseApiLevelValue(api_level);
-    }
-
-    return compilation_type.api_level >= parseApiLevelValue(intro);
-  }
-
-  // Parse the integer API level from api-level or introduced tags.
-  int parseApiLevelValue(const std::string& tag) const {
-    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;
-    }
-    if (api_level.find_first_not_of("0123456789") != std::string::npos) {
-      errx(1, "%s:%zu: error: unknown API level codename specified: \"%s\"",
-           file_path.c_str(), curr_line_num, tag.c_str());
-    }
-    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
deleted file mode 100644
index 5cdbf2f..0000000
--- a/tools/versioner/src/SymbolFileParser.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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/Utils.cpp b/tools/versioner/src/Utils.cpp
deleted file mode 100644
index d2bb1a8..0000000
--- a/tools/versioner/src/Utils.cpp
+++ /dev/null
@@ -1,90 +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.
- */
-
-#include "Utils.h"
-
-#include <err.h>
-#include <fts.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include <android-base/strings.h>
-
-#include "DeclarationDatabase.h"
-
-std::string getWorkingDir() {
-  char buf[PATH_MAX];
-  if (!getcwd(buf, sizeof(buf))) {
-    err(1, "getcwd failed");
-  }
-  return buf;
-}
-
-std::vector<std::string> collectHeaders(const std::string& directory,
-                                        const std::unordered_set<std::string>& ignored_directories) {
-  std::vector<std::string> headers;
-
-  char* dir_argv[2] = { const_cast<char*>(directory.c_str()), nullptr };
-  std::unique_ptr<FTS, decltype(&fts_close)> fts(
-      fts_open(dir_argv, FTS_LOGICAL | FTS_NOCHDIR, nullptr), fts_close);
-
-  if (!fts) {
-    err(1, "failed to open directory '%s'", directory.c_str());
-  }
-
-  FTSENT* skipping = nullptr;
-  while (FTSENT* ent = fts_read(fts.get())) {
-    if (ent->fts_info & FTS_DP) {
-      if (ent == skipping) {
-        skipping = nullptr;
-      }
-      continue;
-    }
-
-    if (skipping != nullptr) {
-      continue;
-    }
-
-    if (ent->fts_info & FTS_D) {
-      if (ignored_directories.count(ent->fts_path) != 0) {
-        // fts_read guarantees that `ent` is valid and okay to hold on to until
-        // after it's returned with FTS_DP set.
-        skipping = ent;
-      }
-      continue;
-    }
-
-    std::string path = ent->fts_path;
-    if (!android::base::EndsWith(path, ".h")) {
-      continue;
-    }
-
-    headers.push_back(std::move(path));
-  }
-
-  return headers;
-}
-
-llvm::StringRef StripPrefix(llvm::StringRef string, llvm::StringRef prefix) {
-  if (string.starts_with(prefix)) {
-    return string.drop_front(prefix.size());
-  }
-  return string;
-}
diff --git a/tools/versioner/src/Utils.h b/tools/versioner/src/Utils.h
deleted file mode 100644
index 9b45dcd..0000000
--- a/tools/versioner/src/Utils.h
+++ /dev/null
@@ -1,93 +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.
- */
-
-#pragma once
-
-#include <errno.h>
-#include <libgen.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <string>
-#include <unordered_set>
-#include <vector>
-
-#include <llvm/ADT/StringRef.h>
-
-std::string getWorkingDir();
-std::vector<std::string> collectHeaders(const std::string& directory,
-                                        const std::unordered_set<std::string>& ignored_directories);
-
-static inline std::string dirname(const std::string& path) {
-  std::unique_ptr<char, decltype(&free)> path_copy(strdup(path.c_str()), free);
-  return dirname(path_copy.get());
-}
-
-static inline bool is_directory(const std::string& path) {
-  struct stat st;
-  if (stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode)) {
-    return true;
-  }
-  return false;
-}
-
-static inline bool mkdirs(const std::string& path) {
-  if (is_directory(path)) {
-    return true;
-  }
-
-  std::string parent = dirname(path);
-  if (parent == path) {
-    return false;
-  }
-
-  if (!mkdirs(parent)) {
-    return false;
-  }
-
-  if (mkdir(path.c_str(), 0700) != 0) {
-    if (errno != EEXIST) {
-      return false;
-    }
-    return is_directory(path);
-  }
-
-  return true;
-}
-
-static inline std::string to_string(const char* c) {
-  return c;
-}
-
-static inline const std::string& to_string(const std::string& str) {
-  return str;
-}
-
-template <typename Collection>
-static inline std::string Join(Collection c, const std::string& delimiter = ", ") {
-  std::string result;
-  for (const auto& item : c) {
-    using namespace std;
-    result.append(to_string(item));
-    result.append(delimiter);
-  }
-  if (!result.empty()) {
-    result.resize(result.length() - delimiter.length());
-  }
-  return result;
-}
-
-llvm::StringRef StripPrefix(llvm::StringRef string, llvm::StringRef prefix);
diff --git a/tools/versioner/src/VFS.cpp b/tools/versioner/src/VFS.cpp
deleted file mode 100644
index d797f82..0000000
--- a/tools/versioner/src/VFS.cpp
+++ /dev/null
@@ -1,92 +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.
- */
-
-#include <err.h>
-#include <fcntl.h>
-#include <fts.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <memory>
-#include <string>
-
-#include <android-base/unique_fd.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 llvm::vfs;
-
-static void addDirectoryToVFS(InMemoryFileSystem* vfs, const std::string& path) {
-  char* paths[] = { const_cast<char*>(path.c_str()), nullptr };
-  std::unique_ptr<FTS, decltype(&fts_close)> fts(
-      fts_open(paths, FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR, nullptr), fts_close);
-
-  if (!fts) {
-    err(1, "failed to open directory %s", path.c_str());
-  }
-
-  while (FTSENT* ent = fts_read(fts.get())) {
-    if ((ent->fts_info & FTS_F) == 0) {
-      continue;
-    }
-
-    const char* file_path = ent->fts_accpath;
-    unique_fd fd(open(file_path, O_RDONLY | O_CLOEXEC));
-    if (fd == -1) {
-      err(1, "failed to open header '%s'", file_path);
-    }
-
-    auto buffer_opt = llvm::MemoryBuffer::getOpenFile(fd, file_path, -1, false, false);
-    if (!buffer_opt) {
-      errx(1, "failed to map header '%s'", file_path);
-    }
-
-    if (!vfs->addFile(file_path, ent->fts_statp->st_mtime, std::move(buffer_opt.get()))) {
-      errx(1, "failed to add file '%s'", file_path);
-    }
-  }
-}
-
-llvm::IntrusiveRefCntPtr<FileSystem> createCommonVFS(const std::string& header_dir,
-                                                     const std::string& dependency_dir,
-                                                     bool add_versioning_header) {
-  auto vfs = std::make_unique<InMemoryFileSystem>();
-  addDirectoryToVFS(vfs.get(), header_dir);
-  if (!dependency_dir.empty()) {
-    addDirectoryToVFS(vfs.get(), dependency_dir);
-  }
-
-  if (add_versioning_header) {
-    const char* top = getenv("ANDROID_BUILD_TOP");
-    if (!top) {
-      errx(1, "-i passed, but ANDROID_BUILD_TOP is unset");
-    }
-
-    std::string header_path = std::string(top) + "/bionic/libc/include/android/versioning.h";
-    auto buffer_opt = llvm::MemoryBuffer::getFile(header_path);
-    if (!buffer_opt) {
-      err(1, "failed to open %s", header_path.c_str());
-    }
-    vfs->addFile("android/versioning.h", 0, std::move(buffer_opt.get()));
-  }
-
-  return llvm::IntrusiveRefCntPtr<FileSystem>(vfs.release());
-}
diff --git a/tools/versioner/src/VFS.h b/tools/versioner/src/VFS.h
deleted file mode 100644
index e4aac75..0000000
--- a/tools/versioner/src/VFS.h
+++ /dev/null
@@ -1,27 +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.
- */
-
-#pragma once
-
-#include <memory>
-#include <string>
-
-#include <llvm/ADT/IntrusiveRefCntPtr.h>
-#include <llvm/Support/VirtualFileSystem.h>
-
-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
deleted file mode 100644
index 37c8bac..0000000
--- a/tools/versioner/src/versioner.cpp
+++ /dev/null
@@ -1,697 +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.
- */
-
-#include <dirent.h>
-#include <err.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#if defined(__linux__)
-#include <sched.h>
-#endif
-
-#include <atomic>
-#include <chrono>
-#include <functional>
-#include <iostream>
-#include <map>
-#include <memory>
-#include <set>
-#include <sstream>
-#include <string>
-#include <string_view>
-#include <thread>
-#include <unordered_map>
-#include <vector>
-
-#include <llvm/ADT/StringRef.h>
-
-#include <android-base/file.h>
-#include <android-base/macros.h>
-#include <android-base/parseint.h>
-#include <android-base/strings.h>
-
-#include "Arch.h"
-#include "DeclarationDatabase.h"
-#include "Driver.h"
-#include "Preprocessor.h"
-#include "SymbolDatabase.h"
-#include "Utils.h"
-#include "VFS.h"
-
-#include "versioner.h"
-
-using namespace std::chrono_literals;
-using namespace std::string_literals;
-
-bool strict;
-bool verbose;
-bool add_include;
-
-static int getCpuCount();
-static int max_thread_count = getCpuCount();
-
-static int getCpuCount() {
-#if defined(__linux__)
-  cpu_set_t cpu_set;
-  int rc = sched_getaffinity(getpid(), sizeof(cpu_set), &cpu_set);
-  if (rc != 0) {
-    err(1, "sched_getaffinity failed");
-  }
-  return CPU_COUNT(&cpu_set);
-#else
-  return 1;
-#endif
-}
-
-namespace {
-struct HeaderLocationInformation {
-  std::string header_path;
-  std::string dependency_dir;
-  // Absolute paths to ignore all children -- including subdirectories -- of.
-  std::unordered_set<std::string> ignored_directories;
-};
-}
-
-static bool is_dir(const std::string& path) {
-  struct stat st;
-  return stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode);
-}
-
-static CompilationRequirements collectRequirements(const Arch& arch,
-                                                   const HeaderLocationInformation& location) {
-  std::vector<std::string> headers =
-      collectHeaders(location.header_path, location.ignored_directories);
-  std::vector<std::string> dependencies;
-
-  if (is_dir(location.header_path)) {
-    dependencies.emplace_back(location.header_path);
-  }
-
-  if (!location.dependency_dir.empty()) {
-    auto collect_children = [&dependencies](const std::string& dir_path) {
-      DIR* dir = opendir(dir_path.c_str());
-      if (!dir) {
-        err(1, "failed to open dependency directory '%s'", dir_path.c_str());
-      }
-
-      struct dirent* dent;
-      while ((dent = readdir(dir))) {
-        if (dent->d_name[0] == '.') {
-          continue;
-        }
-
-        // TODO: Resolve symlinks.
-        std::string dependency = dir_path + "/" + dent->d_name;
-
-        struct stat st;
-        if (stat(dependency.c_str(), &st) != 0) {
-          err(1, "failed to stat dependency '%s'", dependency.c_str());
-        }
-
-        if (!S_ISDIR(st.st_mode)) {
-          errx(1, "'%s' is not a directory", dependency.c_str());
-        }
-
-        dependencies.push_back(dependency);
-      }
-
-      closedir(dir);
-    };
-
-    collect_children(location.dependency_dir + "/common");
-    collect_children(location.dependency_dir + "/" + to_string(arch));
-  }
-
-  auto new_end = std::remove_if(headers.begin(), headers.end(), [&arch](llvm::StringRef header) {
-    for (const auto& it : ignored_headers) {
-      if (!it.second.contains(arch)) {
-        continue;
-      }
-
-      if (header.ends_with("/" + it.first)) {
-        return true;
-      }
-    }
-    return false;
-  });
-
-  headers.erase(new_end, headers.end());
-
-  CompilationRequirements result = { .headers = headers, .dependencies = dependencies };
-  return result;
-}
-
-static std::set<CompilationType> generateCompilationTypes(const std::set<Arch> selected_architectures,
-                                                          const std::set<int>& selected_levels) {
-  std::set<CompilationType> result;
-  for (const auto& arch : selected_architectures) {
-    int min_api = arch_min_api[arch];
-    for (int api_level : selected_levels) {
-      if (api_level < min_api) {
-        continue;
-      }
-
-      for (int file_offset_bits : { 32, 64 }) {
-        for (bool cpp : { true, false }) {
-          CompilationType type = {
-            .arch = arch, .cpp = cpp, .api_level = api_level, .file_offset_bits = file_offset_bits
-          };
-          result.insert(type);
-        }
-      }
-    }
-  }
-  return result;
-}
-
-static std::unique_ptr<HeaderDatabase> compileHeaders(const std::set<CompilationType>& types,
-                                                      const HeaderLocationInformation& location) {
-  if (types.empty()) {
-    errx(1, "compileHeaders received no CompilationTypes");
-  }
-
-  auto vfs = createCommonVFS(location.header_path, location.dependency_dir, add_include);
-
-  size_t thread_count = max_thread_count;
-  std::vector<std::thread> threads;
-
-  std::map<CompilationType, HeaderDatabase> header_databases;
-  std::unordered_map<Arch, CompilationRequirements> requirements;
-
-  auto result = std::make_unique<HeaderDatabase>();
-  for (const auto& type : types) {
-    if (requirements.count(type.arch) == 0) {
-      requirements[type.arch] = collectRequirements(type.arch, location);
-    }
-  }
-
-  initializeTargetCC1FlagCache(vfs, types, requirements);
-
-  std::vector<std::pair<CompilationType, const std::string&>> jobs;
-  std::atomic<size_t> job_index(0);
-  for (CompilationType type : types) {
-    CompilationRequirements& req = requirements[type.arch];
-    for (const std::string& header : req.headers) {
-      jobs.emplace_back(type, header);
-    }
-  }
-
-  // Dup an empty file to stdin, so that we can use `clang -include a.h -` instead of `clang a.h`,
-  // since some warnings don't get generated in files that are compiled directly.
-  FILE* empty_file = tmpfile();
-  if (!empty_file) {
-    err(1, "failed to create temporary file");
-  }
-
-  int empty_file_fd = fileno(empty_file);
-  if (empty_file_fd == -1) {
-    errx(1, "fileno failed on tmpfile");
-  }
-
-  dup2(empty_file_fd, STDIN_FILENO);
-  fclose(empty_file);
-
-  thread_count = std::min(thread_count, jobs.size());
-
-  if (thread_count == 1) {
-    for (const auto& job : jobs) {
-      compileHeader(vfs, result.get(), job.first, job.second);
-    }
-  } else {
-    // Spawn threads.
-    for (size_t i = 0; i < thread_count; ++i) {
-      threads.emplace_back([&jobs, &job_index, &result, vfs]() {
-        while (true) {
-          size_t idx = job_index++;
-          if (idx >= jobs.size()) {
-            return;
-          }
-
-          const auto& job = jobs[idx];
-          compileHeader(vfs, result.get(), job.first, job.second);
-        }
-      });
-    }
-
-    // Reap them.
-    for (auto& thread : threads) {
-      thread.join();
-    }
-    threads.clear();
-  }
-
-  return result;
-}
-
-static std::set<CompilationType> getCompilationTypes(const Declaration* decl) {
-  std::set<CompilationType> result;
-  for (const auto& it : decl->availability) {
-    result.insert(it.first);
-  }
-  return result;
-}
-
-template<typename T>
-static std::vector<T> Intersection(const std::set<T>& a, const std::set<T>& b) {
-  std::vector<T> intersection;
-  std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(intersection));
-  return intersection;
-}
-
-// Perform a validity check on a symbol's declarations, enforcing the following invariants:
-//   1. At most one inline definition of the function exists (overloaded inline functions for
-//      _FORTIFY_SOURCE do not count because they are usually introduced to intercept the original
-//      functions or usually have enable_if attributes).
-//   2. All of the availability declarations for a symbol are compatible.
-//      If a function is declared as an inline before a certain version, the inline definition
-//      should have no version tag.
-//   3. Each availability type must only be present globally or on a per-arch basis.
-//      (e.g. __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(22) __DEPRECATED_IN(23) is fine,
-//      but not __INTRODUCED_IN(9) __INTRODUCED_IN_32(10))
-static bool checkSymbol(const Symbol& symbol) {
-  std::string cwd = getWorkingDir() + "/";
-
-  std::unordered_map<const Declaration*, std::set<CompilationType>> inline_definitions;
-  for (const auto& decl_it : symbol.declarations) {
-    const Declaration* decl = &decl_it.second;
-    if (decl->is_definition && !decl->fortify_inline) {
-      std::set<CompilationType> compilation_types = getCompilationTypes(decl);
-      for (const auto& inline_def_it : inline_definitions) {
-        auto intersection = Intersection(compilation_types, inline_def_it.second);
-        if (!intersection.empty()) {
-          fprintf(stderr, "versioner: conflicting inline definitions for symbol %s:\n",
-                  symbol.name.c_str());
-          fprintf(stderr, "  declarations visible in: %s\n", Join(intersection, ", ").c_str());
-          decl->dump(cwd, stderr, 4);
-          inline_def_it.first->dump(cwd, stderr, 4);
-          return false;
-        }
-      }
-
-      inline_definitions[decl] = std::move(compilation_types);
-    }
-
-    DeclarationAvailability availability;
-    if (!decl->calculateAvailability(&availability)) {
-      fprintf(stderr, "versioner: failed to calculate availability for declaration:\n");
-      decl->dump(cwd, stderr, 2);
-      return false;
-    }
-
-    if (decl->is_definition && !availability.empty()) {
-      fprintf(stderr, "versioner: inline definition has non-empty versioning information:\n");
-      decl->dump(cwd, stderr, 2);
-      return false;
-    }
-  }
-
-  DeclarationAvailability availability;
-  if (!symbol.calculateAvailability(&availability)) {
-    fprintf(stderr, "versioner: inconsistent availability for symbol '%s'\n", symbol.name.c_str());
-    symbol.dump(cwd);
-    return false;
-  }
-
-  // TODO: Check invariant #3.
-  return true;
-}
-
-static bool validityCheck(const HeaderDatabase* database) {
-  bool error = false;
-  std::string cwd = getWorkingDir() + "/";
-
-  for (const auto& symbol_it : database->symbols) {
-    if (!checkSymbol(symbol_it.second)) {
-      error = true;
-    }
-  }
-  return !error;
-}
-
-// Check that our symbol availability declarations match the actual NDK
-// platform symbol availability.
-static bool checkVersions(const std::set<CompilationType>& types,
-                          const HeaderDatabase* header_database,
-                          const NdkSymbolDatabase& symbol_database) {
-  std::string cwd = getWorkingDir() + "/";
-  bool failed = false;
-
-  std::map<Arch, std::set<CompilationType>> arch_types;
-  for (const CompilationType& type : types) {
-    arch_types[type.arch].insert(type);
-  }
-
-  std::set<std::string> completely_unavailable;
-  std::map<std::string, std::set<CompilationType>> missing_availability;
-  std::map<std::string, std::set<CompilationType>> extra_availability;
-
-  for (const auto& symbol_it : header_database->symbols) {
-    const auto& symbol_name = symbol_it.first;
-    DeclarationAvailability symbol_availability;
-
-    if (!symbol_it.second.calculateAvailability(&symbol_availability)) {
-      errx(1, "failed to calculate symbol availability");
-    }
-
-    const auto platform_availability_it = symbol_database.find(symbol_name);
-    if (platform_availability_it == symbol_database.end()) {
-      completely_unavailable.insert(symbol_name);
-      continue;
-    }
-
-    const auto& platform_availability = platform_availability_it->second;
-
-    for (const CompilationType& type : types) {
-      bool should_be_available = true;
-      const auto& global_availability = symbol_availability.global_availability;
-      const auto& arch_availability = symbol_availability.arch_availability[type.arch];
-      if (global_availability.introduced != 0 && global_availability.introduced > type.api_level) {
-        should_be_available = false;
-      }
-
-      if (arch_availability.introduced != 0 && arch_availability.introduced > type.api_level) {
-        should_be_available = false;
-      }
-
-      if (global_availability.obsoleted != 0 && global_availability.obsoleted <= type.api_level) {
-        should_be_available = false;
-      }
-
-      if (arch_availability.obsoleted != 0 && arch_availability.obsoleted <= type.api_level) {
-        should_be_available = false;
-      }
-
-      // The function declaration might be (validly) missing for the given CompilationType.
-      if (!symbol_it.second.hasDeclaration(type)) {
-        should_be_available = false;
-      }
-
-      bool is_available = platform_availability.count(type);
-
-      if (should_be_available != is_available) {
-        if (is_available) {
-          extra_availability[symbol_name].insert(type);
-        } else {
-          missing_availability[symbol_name].insert(type);
-        }
-      }
-    }
-  }
-
-  for (const auto& it : symbol_database) {
-    const std::string& symbol_name = it.first;
-
-    bool symbol_error = false;
-    if (auto missing_it = missing_availability.find(symbol_name);
-        missing_it != missing_availability.end()) {
-      printf("%s: declaration marked available but symbol missing in [%s]\n", symbol_name.c_str(),
-             Join(missing_it->second, ", ").c_str());
-      symbol_error = true;
-      failed = true;
-    }
-
-    if (strict) {
-      if (auto extra_it = extra_availability.find(symbol_name);
-          extra_it != extra_availability.end()) {
-        printf("%s: declaration marked unavailable but symbol available in [%s]\n",
-               symbol_name.c_str(), Join(extra_it->second, ", ").c_str());
-        symbol_error = true;
-        failed = true;
-      }
-    }
-
-    if (symbol_error) {
-      if (auto symbol_it = header_database->symbols.find(symbol_name);
-          symbol_it != header_database->symbols.end()) {
-        symbol_it->second.dump(cwd);
-      } else {
-        errx(1, "failed to find symbol in header database");
-      }
-    }
-  }
-
-  // TODO: Verify that function/variable declarations are actually function/variable symbols.
-  return !failed;
-}
-
-static void usage(bool help = false) {
-  fprintf(stderr, "Usage: versioner [OPTION]... [HEADER_PATH] [DEPS_PATH]\n");
-  if (!help) {
-    printf("Try 'versioner -h' for more information.\n");
-    exit(1);
-  } else {
-    fprintf(stderr, "Version headers at HEADER_PATH, with DEPS_PATH/ARCH/* on the include path\n");
-    fprintf(stderr, "Autodetects paths if HEADER_PATH and DEPS_PATH are not specified\n");
-    fprintf(stderr, "\n");
-    fprintf(stderr, "Target specification (defaults to all):\n");
-    fprintf(stderr, "  -a API_LEVEL\tbuild with specified API level (can be repeated)\n");
-    fprintf(stderr, "    \t\tdefaults to %s\n", Join(default_levels).c_str());
-    fprintf(stderr, "  -r ARCH\tbuild with specified architecture (can be repeated)\n");
-    fprintf(stderr, "    \t\tvalid architectures are %s\n", Join(supported_archs).c_str());
-    fprintf(stderr, "\n");
-    fprintf(stderr, "Validation:\n");
-    fprintf(stderr, "  -p PATH\tcompare against NDK platform at PATH\n");
-    fprintf(stderr, "  -s\t\tenable strict warnings\n");
-    fprintf(stderr, "\n");
-    fprintf(stderr, "Preprocessing:\n");
-    fprintf(stderr, "  -o PATH\tpreprocess header files and emit them at PATH\n");
-    fprintf(stderr, "  -f\t\tpreprocess header files even if validation fails\n");
-    fprintf(stderr, "\n");
-    fprintf(stderr, "Miscellaneous:\n");
-    fprintf(stderr, "  -F\t\tdo not ignore FORTIFY headers by default\n");
-    fprintf(stderr, "  -d\t\tdump function availability\n");
-    fprintf(stderr, "  -j THREADS\tmaximum number of threads to use\n");
-    fprintf(stderr, "  -v\t\tenable verbose logging\n");
-    fprintf(stderr, "  -h\t\tdisplay this message\n");
-    exit(0);
-  }
-}
-
-// versioner uses a prebuilt version of clang, which is not up-to-date wrt/
-// container annotations. So disable container overflow checking. b/37775238
-extern "C" const char* __asan_default_options() {
-  return "detect_container_overflow=0";
-}
-
-int main(int argc, char** argv) {
-  std::string cwd = getWorkingDir() + "/";
-  std::string platform_dir;
-  std::set<Arch> selected_architectures;
-  std::set<int> selected_levels;
-  std::string preprocessor_output_path;
-  bool force = false;
-  bool dump = false;
-  bool ignore_fortify_headers = true;
-
-  int c;
-  while ((c = getopt(argc, argv, "a:r:p:so:fdj:vhFi")) != -1) {
-    switch (c) {
-      case 'a': {
-        char* end;
-        int api_level = strtol(optarg, &end, 10);
-        if (end == optarg || strlen(end) > 0) {
-          usage();
-        }
-
-        selected_levels.insert(api_level);
-        break;
-      }
-
-      case 'r': {
-        std::optional<Arch> arch = arch_from_string(optarg);
-        if (!arch) {
-          errx(1, "unknown architecture '%s'", optarg);
-        }
-        selected_architectures.insert(*arch);
-        break;
-      }
-
-      case 'p': {
-        if (!platform_dir.empty()) {
-          usage();
-        }
-
-        platform_dir = optarg;
-
-        if (platform_dir.empty()) {
-          usage();
-        }
-
-        struct stat st;
-        if (stat(platform_dir.c_str(), &st) != 0) {
-          err(1, "failed to stat platform directory '%s'", platform_dir.c_str());
-        }
-        if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) {
-          errx(1, "'%s' is not a file or directory", optarg);
-        }
-        break;
-      }
-
-      case 's':
-        strict = true;
-        break;
-
-      case 'o':
-        if (!preprocessor_output_path.empty()) {
-          usage();
-        }
-        preprocessor_output_path = optarg;
-        if (preprocessor_output_path.empty()) {
-          usage();
-        }
-        break;
-
-      case 'f':
-        force = true;
-        break;
-
-      case 'd':
-        dump = true;
-        break;
-
-      case 'j':
-        if (!android::base::ParseInt<int>(optarg, &max_thread_count, 1)) {
-          usage();
-        }
-        break;
-
-      case 'v':
-        verbose = true;
-        break;
-
-      case 'h':
-        usage(true);
-        break;
-
-      case 'i':
-        // Secret option for tests to -include <android/versioning.h>.
-        add_include = true;
-        break;
-
-      case 'F':
-        ignore_fortify_headers = false;
-        break;
-
-      default:
-        usage();
-        break;
-    }
-  }
-
-  if (argc - optind > 2 || optind > argc) {
-    usage();
-  }
-
-  HeaderLocationInformation location;
-
-  const char* top = getenv("ANDROID_BUILD_TOP");
-  if (!top && (optind == argc || add_include)) {
-    fprintf(stderr, "versioner: failed to autodetect bionic paths. Is ANDROID_BUILD_TOP set?\n");
-    usage();
-  }
-
-  if (optind == argc) {
-    // Neither HEADER_PATH nor DEPS_PATH were specified, so try to figure them out.
-    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]);
-    }
-
-    if (argc - optind == 2) {
-      location.dependency_dir = argv[optind + 1];
-    }
-  }
-
-  // Every file that lives in bits/fortify is logically a part of a header outside of bits/fortify.
-  // This makes the files there impossible to build on their own.
-  if (ignore_fortify_headers) {
-    std::string fortify_path = location.header_path;
-    if (!android::base::EndsWith(location.header_path, "/")) {
-      fortify_path += '/';
-    }
-    fortify_path += "bits/fortify";
-    location.ignored_directories.insert(std::move(fortify_path));
-  }
-
-  if (selected_levels.empty()) {
-    selected_levels = default_levels;
-  }
-
-  if (selected_architectures.empty()) {
-    selected_architectures = supported_archs;
-  }
-
-
-  struct stat st;
-  if (const char *path = location.header_path.c_str(); stat(path, &st) != 0) {
-    err(1, "failed to stat '%s'", path);
-  }
-
-  std::set<CompilationType> compilation_types;
-  std::optional<NdkSymbolDatabase> symbol_database;
-
-  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);
-  auto end = std::chrono::high_resolution_clock::now();
-
-  if (verbose) {
-    auto diff = (end - start) / 1.0ms;
-    printf("Compiled headers for %zu targets in %0.2LFms\n", compilation_types.size(), diff);
-  }
-
-  bool failed = false;
-  if (dump) {
-    declaration_database->dump(location.header_path + "/");
-  } else {
-    if (!validityCheck(declaration_database.get())) {
-      printf("versioner: validity check failed\n");
-      failed = true;
-    }
-
-    if (symbol_database) {
-      if (!checkVersions(compilation_types, declaration_database.get(), *symbol_database)) {
-        printf("versioner: version check failed\n");
-        failed = true;
-      }
-    }
-  }
-
-  if (!preprocessor_output_path.empty() && (force || !failed)) {
-    failed = !preprocessHeaders(preprocessor_output_path, location.header_path,
-                                declaration_database.get());
-  }
-  return failed;
-}
diff --git a/tools/versioner/src/versioner.h b/tools/versioner/src/versioner.h
deleted file mode 100644
index 225e14b..0000000
--- a/tools/versioner/src/versioner.h
+++ /dev/null
@@ -1,43 +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.
- */
-
-#pragma once
-
-#include <map>
-#include <set>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-
-extern bool strict;
-extern bool verbose;
-extern bool add_include;
-
-#define D(...)             \
-  do {                     \
-    if (verbose) {         \
-      printf(__VA_ARGS__); \
-    }                      \
-  } while (0)
-
-static const std::unordered_map<std::string, std::set<Arch>> ignored_headers = {
-  // Internal header.
-  // TODO: we should probably just admit we're never getting rid of this.
-  { "sys/_system_properties.h", supported_archs },
-
-  // time64.h #errors when included on LP64 archs.
-  { "time64.h", { Arch::arm64, Arch::riscv64, Arch::x86_64 } },
-};
diff --git a/tools/versioner/tests/.gitignore b/tools/versioner/tests/.gitignore
deleted file mode 100644
index 89f9ac0..0000000
--- a/tools/versioner/tests/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-out/
diff --git a/tools/versioner/tests/arch_specific/headers/foo.h b/tools/versioner/tests/arch_specific/headers/foo.h
deleted file mode 100644
index 4830a68..0000000
--- a/tools/versioner/tests/arch_specific/headers/foo.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo();
-
-#if defined(__i386__)
-int bar();
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/arch_specific/platforms/libc.map.txt b/tools/versioner/tests/arch_specific/platforms/libc.map.txt
deleted file mode 100644
index 5aa11ed..0000000
--- a/tools/versioner/tests/arch_specific/platforms/libc.map.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-LIBC {
-  global:
-    foo;  # arm x86
-    bar;  # x86
-};
diff --git a/tools/versioner/tests/arch_specific/run.sh b/tools/versioner/tests/arch_specific/run.sh
deleted file mode 100644
index f0d95ae..0000000
--- a/tools/versioner/tests/arch_specific/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -r x86 -a 9 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/compilation_error/expected_fail b/tools/versioner/tests/compilation_error/expected_fail
deleted file mode 100644
index f18b625..0000000
--- a/tools/versioner/tests/compilation_error/expected_fail
+++ /dev/null
@@ -1 +0,0 @@
-versioner: compilation generated warnings or errors
diff --git a/tools/versioner/tests/compilation_error/headers/foo.h b/tools/versioner/tests/compilation_error/headers/foo.h
deleted file mode 100644
index 51c087a..0000000
--- a/tools/versioner/tests/compilation_error/headers/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#error foo
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/compilation_error/platforms/libc.map.txt b/tools/versioner/tests/compilation_error/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/compilation_error/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/compilation_error/run.sh b/tools/versioner/tests/compilation_error/run.sh
deleted file mode 100644
index 7e8d489..0000000
--- a/tools/versioner/tests/compilation_error/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -i -j1
diff --git a/tools/versioner/tests/dependencies/dependencies/arm/archdep/archdep.h b/tools/versioner/tests/dependencies/dependencies/arm/archdep/archdep.h
deleted file mode 100644
index b2d357a..0000000
--- a/tools/versioner/tests/dependencies/dependencies/arm/archdep/archdep.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-typedef int arm_t;
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/dependencies/dependencies/common/foo/foodep.h b/tools/versioner/tests/dependencies/dependencies/common/foo/foodep.h
deleted file mode 100644
index baa5857..0000000
--- a/tools/versioner/tests/dependencies/dependencies/common/foo/foodep.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-typedef int foo_t;
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/dependencies/dependencies/x86/archdep/archdep.h b/tools/versioner/tests/dependencies/dependencies/x86/archdep/archdep.h
deleted file mode 100644
index b73f7cc..0000000
--- a/tools/versioner/tests/dependencies/dependencies/x86/archdep/archdep.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-typedef int x86_t;
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/dependencies/headers/foo.h b/tools/versioner/tests/dependencies/headers/foo.h
deleted file mode 100644
index 875de1b..0000000
--- a/tools/versioner/tests/dependencies/headers/foo.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#include <archdep.h>
-#include <foodep.h>
-
-#if defined(__i386__)
-x86_t foo(foo_t);
-#elif defined(__arm__)
-arm_t foo(foo_t);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/dependencies/platforms/libc.map.txt b/tools/versioner/tests/dependencies/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/dependencies/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/dependencies/run.sh b/tools/versioner/tests/dependencies/run.sh
deleted file mode 100644
index 0c17907..0000000
--- a/tools/versioner/tests/dependencies/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers dependencies -p platforms -r arm -r x86 -a 9
\ No newline at end of file
diff --git a/tools/versioner/tests/extern_cpp/headers/string.h b/tools/versioner/tests/extern_cpp/headers/string.h
deleted file mode 100644
index 5ac43ac..0000000
--- a/tools/versioner/tests/extern_cpp/headers/string.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#define __RENAME(x) __asm__(#x)
-
-#if defined(__cplusplus)
-extern "C++" char* basename(char*) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
-extern "C++" const char* basename(const char*) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
-#else
-char* basename(const char*) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
-#endif
-
-char* foo() __INTRODUCED_IN(8);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/extern_cpp/platforms/libc.map.txt b/tools/versioner/tests/extern_cpp/platforms/libc.map.txt
deleted file mode 100644
index 297d1fb..0000000
--- a/tools/versioner/tests/extern_cpp/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    __gnu_basename;  # introduced=23
-};
diff --git a/tools/versioner/tests/extern_cpp/run.sh b/tools/versioner/tests/extern_cpp/run.sh
deleted file mode 100644
index e320c95..0000000
--- a/tools/versioner/tests/extern_cpp/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 21 -a 23 -i
diff --git a/tools/versioner/tests/extern_cpp_mismatch/headers/string.h b/tools/versioner/tests/extern_cpp_mismatch/headers/string.h
deleted file mode 100644
index 66133d8..0000000
--- a/tools/versioner/tests/extern_cpp_mismatch/headers/string.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#define __RENAME(x) __asm__(#x)
-
-#if defined(__cplusplus)
-extern "C++" char* basename(char*) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
-extern "C++" const char* basename(const char*) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
-#else
-char* basename(const char*) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/extern_cpp_mismatch/platforms/libc.map.txt b/tools/versioner/tests/extern_cpp_mismatch/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/extern_cpp_mismatch/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/extern_cpp_mismatch/run.sh b/tools/versioner/tests/extern_cpp_mismatch/run.sh
deleted file mode 100644
index a34fda8..0000000
--- a/tools/versioner/tests/extern_cpp_mismatch/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/fortify_inline/headers/fcntl.h b/tools/versioner/tests/fortify_inline/headers/fcntl.h
deleted file mode 100644
index dc81ef8..0000000
--- a/tools/versioner/tests/fortify_inline/headers/fcntl.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-extern int open_real(const char* name, int flags, ...) __asm__("open");
-
-#define O_CREAT 00000100
-
-typedef unsigned int mode_t;
-
-static inline __attribute__((always_inline))
-int open(const char* name, int flags)
-    __attribute__((annotate("versioner_fortify_inline")))
-    __attribute__((overloadable))
-    __attribute__((enable_if(!(flags & O_CREAT), ""))) {
-  return open_real(name, flags);
-}
-
-static inline __attribute__((always_inline))
-int open(const char* name, int flags, mode_t mode)
-    __attribute__((annotate("versioner_fortify_inline")))
-    __attribute__((overloadable))
-    __attribute__((enable_if(flags & O_CREAT, ""))) {
-  return open_real(name, flags, mode);
-}
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/fortify_inline/platforms/libc.map.txt b/tools/versioner/tests/fortify_inline/platforms/libc.map.txt
deleted file mode 100644
index 2f09034..0000000
--- a/tools/versioner/tests/fortify_inline/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    open;
-};
diff --git a/tools/versioner/tests/fortify_inline/run.sh b/tools/versioner/tests/fortify_inline/run.sh
deleted file mode 100644
index 9bfbe6d..0000000
--- a/tools/versioner/tests/fortify_inline/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -a 12 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/inline/headers/foo.h b/tools/versioner/tests/inline/headers/foo.h
deleted file mode 100644
index a337f9c..0000000
--- a/tools/versioner/tests/inline/headers/foo.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#if __ANDROID_API__ < 12
-static int foo() {
-  return 0;
-}
-#else
-int foo() __INTRODUCED_IN(12);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/inline/platforms/libc.map.txt b/tools/versioner/tests/inline/platforms/libc.map.txt
deleted file mode 100644
index 4dced92..0000000
--- a/tools/versioner/tests/inline/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;  # introduced=12
-};
diff --git a/tools/versioner/tests/inline/run.sh b/tools/versioner/tests/inline/run.sh
deleted file mode 100644
index 9bfbe6d..0000000
--- a/tools/versioner/tests/inline/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -a 12 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/missing_api/expected_fail b/tools/versioner/tests/missing_api/expected_fail
deleted file mode 100644
index 9f097f7..0000000
--- a/tools/versioner/tests/missing_api/expected_fail
+++ /dev/null
@@ -1,4 +0,0 @@
-  foo: introduced = 9
-    extern declaration @ headers/foo.h:5:1
-      introduced = 9
-versioner: version check failed
diff --git a/tools/versioner/tests/missing_api/headers/foo.h b/tools/versioner/tests/missing_api/headers/foo.h
deleted file mode 100644
index c201dbb..0000000
--- a/tools/versioner/tests/missing_api/headers/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __INTRODUCED_IN(9);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/missing_api/platforms/libc.map.txt b/tools/versioner/tests/missing_api/platforms/libc.map.txt
deleted file mode 100644
index 3701a9d..0000000
--- a/tools/versioner/tests/missing_api/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;  # api-level=9
-};
diff --git a/tools/versioner/tests/missing_api/run.sh b/tools/versioner/tests/missing_api/run.sh
deleted file mode 100644
index 9bfbe6d..0000000
--- a/tools/versioner/tests/missing_api/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -a 12 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/missing_arch/expected_fail b/tools/versioner/tests/missing_arch/expected_fail
deleted file mode 100644
index 7b33e19..0000000
--- a/tools/versioner/tests/missing_arch/expected_fail
+++ /dev/null
@@ -1,4 +0,0 @@
-  foo: no availability
-    extern declaration @ headers/foo.h:5:1
-      no availability
-versioner: version check failed
diff --git a/tools/versioner/tests/missing_arch/headers/foo.h b/tools/versioner/tests/missing_arch/headers/foo.h
deleted file mode 100644
index 5ba4794..0000000
--- a/tools/versioner/tests/missing_arch/headers/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo();
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/missing_arch/platforms/libc.map.txt b/tools/versioner/tests/missing_arch/platforms/libc.map.txt
deleted file mode 100644
index f56190e..0000000
--- a/tools/versioner/tests/missing_arch/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;  # arm
-};
diff --git a/tools/versioner/tests/missing_arch/run.sh b/tools/versioner/tests/missing_arch/run.sh
deleted file mode 100644
index f0d95ae..0000000
--- a/tools/versioner/tests/missing_arch/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -r x86 -a 9 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/multiple_decl/headers/bar.h b/tools/versioner/tests/multiple_decl/headers/bar.h
deleted file mode 100644
index b16617b..0000000
--- a/tools/versioner/tests/multiple_decl/headers/bar.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __REMOVED_IN(12);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/multiple_decl/headers/foo.h b/tools/versioner/tests/multiple_decl/headers/foo.h
deleted file mode 100644
index b16617b..0000000
--- a/tools/versioner/tests/multiple_decl/headers/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __REMOVED_IN(12);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/multiple_decl/platforms/libc.map.txt b/tools/versioner/tests/multiple_decl/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/multiple_decl/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/multiple_decl/run.sh b/tools/versioner/tests/multiple_decl/run.sh
deleted file mode 100644
index a34fda8..0000000
--- a/tools/versioner/tests/multiple_decl/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/multiple_decl_mismatch/expected_fail b/tools/versioner/tests/multiple_decl_mismatch/expected_fail
deleted file mode 100644
index 30e7233..0000000
--- a/tools/versioner/tests/multiple_decl_mismatch/expected_fail
+++ /dev/null
@@ -1,8 +0,0 @@
-versioner: inconsistent availability for symbol 'foo'
-versioner: failed to calculate symbol availability
-  foo: invalid
-    extern declaration @ headers/bar.h:5:1
-      obsoleted = 12
-    extern declaration @ headers/foo.h:5:1
-      obsoleted = 9
-versioner: validity check failed
diff --git a/tools/versioner/tests/multiple_decl_mismatch/headers/bar.h b/tools/versioner/tests/multiple_decl_mismatch/headers/bar.h
deleted file mode 100644
index b16617b..0000000
--- a/tools/versioner/tests/multiple_decl_mismatch/headers/bar.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __REMOVED_IN(12);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/multiple_decl_mismatch/headers/foo.h b/tools/versioner/tests/multiple_decl_mismatch/headers/foo.h
deleted file mode 100644
index 8e8f98c..0000000
--- a/tools/versioner/tests/multiple_decl_mismatch/headers/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __REMOVED_IN(9);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/multiple_decl_mismatch/platforms/libc.map.txt b/tools/versioner/tests/multiple_decl_mismatch/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/multiple_decl_mismatch/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/multiple_decl_mismatch/run.sh b/tools/versioner/tests/multiple_decl_mismatch/run.sh
deleted file mode 100644
index a34fda8..0000000
--- a/tools/versioner/tests/multiple_decl_mismatch/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/multiple_definition/expected_fail b/tools/versioner/tests/multiple_definition/expected_fail
deleted file mode 100644
index 5abb833..0000000
--- a/tools/versioner/tests/multiple_definition/expected_fail
+++ /dev/null
@@ -1,7 +0,0 @@
-versioner: conflicting inline definitions for symbol foo:
-  declarations visible in: arm-9 [c, fob = 32], arm-9 [c, fob = 64], arm-12 [c, fob = 32], arm-12 [c, fob = 64], arm-9 [c++, fob = 32], arm-9 [c++, fob = 64], arm-12 [c++, fob = 32], arm-12 [c++, fob = 64]
-    static definition @ headers/foo.h:5:1
-      no availability
-    static definition @ headers/bar.h:5:1
-      no availability
-versioner: validity check failed
diff --git a/tools/versioner/tests/multiple_definition/headers/bar.h b/tools/versioner/tests/multiple_definition/headers/bar.h
deleted file mode 100644
index 29592c6..0000000
--- a/tools/versioner/tests/multiple_definition/headers/bar.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-static int foo() {
-  return 0;
-}
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/multiple_definition/headers/foo.h b/tools/versioner/tests/multiple_definition/headers/foo.h
deleted file mode 100644
index 29592c6..0000000
--- a/tools/versioner/tests/multiple_definition/headers/foo.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-static int foo() {
-  return 0;
-}
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/multiple_definition/platforms/libc.map.txt b/tools/versioner/tests/multiple_definition/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/multiple_definition/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/multiple_definition/run.sh b/tools/versioner/tests/multiple_definition/run.sh
deleted file mode 100644
index e4abbe7..0000000
--- a/tools/versioner/tests/multiple_definition/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -a 12 -i
diff --git a/tools/versioner/tests/multiple_definition_ok/headers/bar.h b/tools/versioner/tests/multiple_definition_ok/headers/bar.h
deleted file mode 100644
index 6eced51..0000000
--- a/tools/versioner/tests/multiple_definition_ok/headers/bar.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#if __ANDROID_API__ == 12
-static int foo() {
-  return 0;
-}
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/multiple_definition_ok/headers/foo.h b/tools/versioner/tests/multiple_definition_ok/headers/foo.h
deleted file mode 100644
index 773d274..0000000
--- a/tools/versioner/tests/multiple_definition_ok/headers/foo.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#if __ANDROID_API__ == 9
-static int foo() {
-  return 0;
-}
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/multiple_definition_ok/platforms/libc.map.txt b/tools/versioner/tests/multiple_definition_ok/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/multiple_definition_ok/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/multiple_definition_ok/run.sh b/tools/versioner/tests/multiple_definition_ok/run.sh
deleted file mode 100644
index e4abbe7..0000000
--- a/tools/versioner/tests/multiple_definition_ok/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -a 12 -i
diff --git a/tools/versioner/tests/obsoleted/headers/foo.h b/tools/versioner/tests/obsoleted/headers/foo.h
deleted file mode 100644
index e9630e5..0000000
--- a/tools/versioner/tests/obsoleted/headers/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __INTRODUCED_IN(9) __REMOVED_IN(11);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/obsoleted/platforms/libc.map.txt b/tools/versioner/tests/obsoleted/platforms/libc.map.txt
deleted file mode 100644
index 3701a9d..0000000
--- a/tools/versioner/tests/obsoleted/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;  # api-level=9
-};
diff --git a/tools/versioner/tests/obsoleted/run.sh b/tools/versioner/tests/obsoleted/run.sh
deleted file mode 100644
index 9bfbe6d..0000000
--- a/tools/versioner/tests/obsoleted/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -a 12 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/preprocessor/expected/foo.h b/tools/versioner/tests/preprocessor/expected/foo.h
deleted file mode 100644
index 4f74927..0000000
--- a/tools/versioner/tests/preprocessor/expected/foo.h
+++ /dev/null
@@ -1,85 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int always_available();
-
-int also_always_available() __INTRODUCED_IN(9);
-
-
-#if __ANDROID_API__ >= 13
-int needs_guard() __INTRODUCED_IN(13);
-#endif /* __ANDROID_API__ >= 13 */
-
-
-#if __ANDROID_API__ >= 12
-
-#if __ANDROID_API__ >= 13
-int needs_guard_2() __INTRODUCED_IN(13);
-#endif /* __ANDROID_API__ >= 13 */
-
-#endif
-
-#if __ANDROID_API__ >= 13
-int already_guarded() __INTRODUCED_IN(13);
-#endif
-
-#if __ANDROID_API__ > 13
-int already_guarded_2() __INTRODUCED_IN(13);
-#endif
-
-#if defined(__arm__)
-
-#if __ANDROID_API__ >= 14
-int specific_arch() __INTRODUCED_IN(14);
-#endif /* __ANDROID_API__ >= 14 */
-
-
-#if __ANDROID_API__ >= 14
-int specific_arch_already_guarded() __INTRODUCED_IN(14);
-#endif
-
-#if __ANDROID_API__ > 14
-int specific_arch_already_guarded_2() __INTRODUCED_IN(14);
-#endif
-#endif
-
-#if defined(__arm__) || defined(__i386__)
-
-#if __ANDROID_API__ >= 14
-int multiple_archs() __INTRODUCED_IN(14);
-#endif /* __ANDROID_API__ >= 14 */
-
-#endif
-
-// __INTRODUCED_IN_64(21) should be ignored.
-
-#if (!defined(__LP64__) && __ANDROID_API__ >= 24) || (defined(__LP64__))
-int multiple_introduced_1() __INTRODUCED_IN_32(24) __INTRODUCED_IN_64(21);
-#endif /* (!defined(__LP64__) && __ANDROID_API__ >= 24) || (defined(__LP64__)) */
-
-
-// This needs different guards for 32 vs 64.
-
-#if (!defined(__LP64__) && __ANDROID_API__ >= 24) || (defined(__LP64__) && __ANDROID_API__ >= 26)
-int multiple_introduced_2() __INTRODUCED_IN_32(24) __INTRODUCED_IN_64(26);
-#endif /* (!defined(__LP64__) && __ANDROID_API__ >= 24) || (defined(__LP64__) && __ANDROID_API__ >= 26) */
-
-
-// This produces both an LP64 and a not-LP64 check, but it doesn't need to check for all 64-bit
-// targets separately.
-
-#if (!defined(__LP64__) && __ANDROID_API__ >= 23) || (defined(__LP64__) && __ANDROID_API__ >= 23)
-int multiple_introduced_3() __INTRODUCED_IN_32(23) __INTRODUCED_IN_64(23);
-#endif /* (!defined(__LP64__) && __ANDROID_API__ >= 23) || (defined(__LP64__) && __ANDROID_API__ >= 23) */
-
-
-
-#if (!defined(__LP64__)) || (defined(__LP64__) && __ANDROID_API__ >= 28)
-int added_to_lp64_late() __INTRODUCED_IN_64(28);
-#endif /* (!defined(__LP64__)) || (defined(__LP64__) && __ANDROID_API__ >= 28) */
-
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor/headers/foo.h b/tools/versioner/tests/preprocessor/headers/foo.h
deleted file mode 100644
index b01d8a9..0000000
--- a/tools/versioner/tests/preprocessor/headers/foo.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int always_available();
-
-int also_always_available() __INTRODUCED_IN(9);
-
-int needs_guard() __INTRODUCED_IN(13);
-
-#if __ANDROID_API__ >= 12
-int needs_guard_2() __INTRODUCED_IN(13);
-#endif
-
-#if __ANDROID_API__ >= 13
-int already_guarded() __INTRODUCED_IN(13);
-#endif
-
-#if __ANDROID_API__ > 13
-int already_guarded_2() __INTRODUCED_IN(13);
-#endif
-
-#if defined(__arm__)
-int specific_arch() __INTRODUCED_IN(14);
-
-#if __ANDROID_API__ >= 14
-int specific_arch_already_guarded() __INTRODUCED_IN(14);
-#endif
-
-#if __ANDROID_API__ > 14
-int specific_arch_already_guarded_2() __INTRODUCED_IN(14);
-#endif
-#endif
-
-#if defined(__arm__) || defined(__i386__)
-int multiple_archs() __INTRODUCED_IN(14);
-#endif
-
-// __INTRODUCED_IN_64(21) should be ignored.
-int multiple_introduced_1() __INTRODUCED_IN_32(24) __INTRODUCED_IN_64(21);
-
-// This needs different guards for 32 vs 64.
-int multiple_introduced_2() __INTRODUCED_IN_32(24) __INTRODUCED_IN_64(26);
-
-// This produces both an LP64 and a not-LP64 check, but it doesn't need to check for all 64-bit
-// targets separately.
-int multiple_introduced_3() __INTRODUCED_IN_32(23) __INTRODUCED_IN_64(23);
-
-int added_to_lp64_late() __INTRODUCED_IN_64(28);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor/run.sh b/tools/versioner/tests/preprocessor/run.sh
deleted file mode 100644
index b039656..0000000
--- a/tools/versioner/tests/preprocessor/run.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-set -e
-
-function run_test {
-  SRC=$1
-  DST=$2
-  rm -rf $2
-  versioner -a 9 -a 12 -a 13 -a 14 -a 15 -a 21 -a 23 $1 -i -o $2
-  diff -q -w -B $2 expected
-}
-
-run_test headers out
-run_test headers/ out
-run_test headers out/
-run_test headers/ out/
-
-run_test `pwd`/headers out
-run_test `pwd`/headers/ out
-run_test `pwd`/headers out/
-run_test `pwd`/headers/ out/
-
-run_test headers `pwd`/out
-run_test headers/ `pwd`/out
-run_test headers `pwd`/out/
-run_test headers/ `pwd`/out/
-
-run_test `pwd`/headers `pwd`/out
-run_test `pwd`/headers/ `pwd`/out
-run_test `pwd`/headers `pwd`/out/
-run_test `pwd`/headers/ `pwd`/out/
diff --git a/tools/versioner/tests/preprocessor_extern_cpp/expected/foo.h b/tools/versioner/tests/preprocessor_extern_cpp/expected/foo.h
deleted file mode 100644
index 9b2d122..0000000
--- a/tools/versioner/tests/preprocessor_extern_cpp/expected/foo.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#define __RENAME(x) asm(#x)
-
-#if defined(__cplusplus)
-
-#if __ANDROID_API__ >= 24
-extern "C++" const char* strchrnul(const char*, int) __RENAME(strchrnul) __INTRODUCED_IN(24);
-#endif /* __ANDROID_API__ >= 24 */
-
-#endif
-
-#if defined(__cplusplus)
-extern "C" int foo();
-#endif
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-
-#if __ANDROID_API__ >= 24
-char* strchrnul(char*, int) __INTRODUCED_IN(24);
-#endif /* __ANDROID_API__ >= 24 */
-
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_extern_cpp/headers/foo.h b/tools/versioner/tests/preprocessor_extern_cpp/headers/foo.h
deleted file mode 100644
index de26d21..0000000
--- a/tools/versioner/tests/preprocessor_extern_cpp/headers/foo.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#define __RENAME(x) asm(#x)
-
-#if defined(__cplusplus)
-extern "C++" const char* strchrnul(const char*, int) __RENAME(strchrnul) __INTRODUCED_IN(24);
-#endif
-
-#if defined(__cplusplus)
-extern "C" int foo();
-#endif
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-char* strchrnul(char*, int) __INTRODUCED_IN(24);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_extern_cpp/run.sh b/tools/versioner/tests/preprocessor_extern_cpp/run.sh
deleted file mode 100644
index 50d9b5c..0000000
--- a/tools/versioner/tests/preprocessor_extern_cpp/run.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-set -e
-
-function run_test {
-  SRC=$1
-  DST=$2
-  rm -rf $2
-  versioner -a 9 -a 12 -a 13 -a 14 -a 15 $1 -i -o $2
-  diff -q -w -B $2 expected
-}
-
-run_test headers out
-run_test headers/ out
-run_test headers out/
-run_test headers/ out/
-
-run_test `pwd`/headers out
-run_test `pwd`/headers/ out
-run_test `pwd`/headers out/
-run_test `pwd`/headers/ out/
-
-run_test headers `pwd`/out
-run_test headers/ `pwd`/out
-run_test headers `pwd`/out/
-run_test headers/ `pwd`/out/
-
-run_test `pwd`/headers `pwd`/out
-run_test `pwd`/headers/ `pwd`/out
-run_test `pwd`/headers `pwd`/out/
-run_test `pwd`/headers/ `pwd`/out/
diff --git a/tools/versioner/tests/preprocessor_file_offset_bits/expected/foo.h b/tools/versioner/tests/preprocessor_file_offset_bits/expected/foo.h
deleted file mode 100644
index dcfaaee..0000000
--- a/tools/versioner/tests/preprocessor_file_offset_bits/expected/foo.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-typedef int off_t;
-typedef int ssize_t;
-typedef unsigned size_t;
-
-#if !defined(__LP64__) && defined(_FILE_OFFSET_BITS)
-#if _FILE_OFFSET_BITS == 64
-#define __USE_FILE_OFFSET64 1
-#endif
-#endif
-
-#define __RENAME(x) __asm__(#x)
-
-#if defined(__USE_FILE_OFFSET64) && __ANDROID_API__ >= 21
-int truncate(const char* __path, off_t __length) __RENAME(truncate64) __INTRODUCED_IN(21);
-#else
-int truncate(const char* __path, off_t __length);
-#endif
-
-#if defined(__USE_FILE_OFFSET64)
-
-#if __ANDROID_API__ >= 12
-ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset) __RENAME(pread64)
-    __INTRODUCED_IN(12);
-#endif /* __ANDROID_API__ >= 12 */
-
-#else
-ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset);
-#endif
-
-#if defined(__USE_FILE_OFFSET64)
-off_t lseek(int __fd, off_t __offset, int __whence) __RENAME(lseek64);
-#else
-off_t lseek(int __fd, off_t __offset, int __whence);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_file_offset_bits/headers/foo.h b/tools/versioner/tests/preprocessor_file_offset_bits/headers/foo.h
deleted file mode 100644
index 5ffffa8..0000000
--- a/tools/versioner/tests/preprocessor_file_offset_bits/headers/foo.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-typedef int off_t;
-typedef int ssize_t;
-typedef unsigned size_t;
-
-#if !defined(__LP64__) && defined(_FILE_OFFSET_BITS)
-#if _FILE_OFFSET_BITS == 64
-#define __USE_FILE_OFFSET64 1
-#endif
-#endif
-
-#define __RENAME(x) __asm__(#x)
-
-#if defined(__USE_FILE_OFFSET64) && __ANDROID_API__ >= 21
-int truncate(const char* __path, off_t __length) __RENAME(truncate64) __INTRODUCED_IN(21);
-#else
-int truncate(const char* __path, off_t __length);
-#endif
-
-#if defined(__USE_FILE_OFFSET64)
-ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset) __RENAME(pread64)
-    __INTRODUCED_IN(12);
-#else
-ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset);
-#endif
-
-#if defined(__USE_FILE_OFFSET64)
-off_t lseek(int __fd, off_t __offset, int __whence) __RENAME(lseek64);
-#else
-off_t lseek(int __fd, off_t __offset, int __whence);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_file_offset_bits/run.sh b/tools/versioner/tests/preprocessor_file_offset_bits/run.sh
deleted file mode 100644
index d974cba..0000000
--- a/tools/versioner/tests/preprocessor_file_offset_bits/run.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-set -e
-
-rm -rf out
-versioner headers -a 9 -a 12 -a 13 -i -o out
-diff -q -w -B out expected
diff --git a/tools/versioner/tests/preprocessor_idempotence/expected/foo.h b/tools/versioner/tests/preprocessor_idempotence/expected/foo.h
deleted file mode 100644
index bc442e5..0000000
--- a/tools/versioner/tests/preprocessor_idempotence/expected/foo.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#if __ANDROID_API__ >= 10
-int foo() __INTRODUCED_IN(10);
-#endif
-
-#if __ANDROID_API__ >= 21
-int bar(int) __INTRODUCED_IN(21);
-#endif
-
-#if __ANDROID_API__ >= 10
-int multiple_1() __INTRODUCED_IN(10);
-int multiple_2() __INTRODUCED_IN(10);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_idempotence/headers/foo.h b/tools/versioner/tests/preprocessor_idempotence/headers/foo.h
deleted file mode 100644
index bc442e5..0000000
--- a/tools/versioner/tests/preprocessor_idempotence/headers/foo.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#if __ANDROID_API__ >= 10
-int foo() __INTRODUCED_IN(10);
-#endif
-
-#if __ANDROID_API__ >= 21
-int bar(int) __INTRODUCED_IN(21);
-#endif
-
-#if __ANDROID_API__ >= 10
-int multiple_1() __INTRODUCED_IN(10);
-int multiple_2() __INTRODUCED_IN(10);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_idempotence/run.sh b/tools/versioner/tests/preprocessor_idempotence/run.sh
deleted file mode 100644
index 1b0aae2..0000000
--- a/tools/versioner/tests/preprocessor_idempotence/run.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-rm -rf out
-set -e
-versioner headers -i -o out
-diff -q -w -B out expected
diff --git a/tools/versioner/tests/preprocessor_merging/expected/foo.h b/tools/versioner/tests/preprocessor_merging/expected/foo.h
deleted file mode 100644
index ecd7f71..0000000
--- a/tools/versioner/tests/preprocessor_merging/expected/foo.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-
-#if __ANDROID_API__ >= 10
-int block_merging_1() __INTRODUCED_IN(10); // foo
-int block_merging_2() __INTRODUCED_IN(10); /* bar */
-int block_merging_3() __INTRODUCED_IN(10); /* baz
-//*/
-int block_merging_4() __INTRODUCED_IN(10);
-#endif /* __ANDROID_API__ >= 10 */
-
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_merging/headers/foo.h b/tools/versioner/tests/preprocessor_merging/headers/foo.h
deleted file mode 100644
index 7aaa471..0000000
--- a/tools/versioner/tests/preprocessor_merging/headers/foo.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int block_merging_1() __INTRODUCED_IN(10); // foo
-int block_merging_2() __INTRODUCED_IN(10); /* bar */
-int block_merging_3() __INTRODUCED_IN(10); /* baz
-//*/
-int block_merging_4() __INTRODUCED_IN(10);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_merging/run.sh b/tools/versioner/tests/preprocessor_merging/run.sh
deleted file mode 100644
index 1929757..0000000
--- a/tools/versioner/tests/preprocessor_merging/run.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-rm -rf out
-set -e
-versioner headers -a 9 -a 10 -a 11 -i -o out
-diff -q -w -B out expected
diff --git a/tools/versioner/tests/preprocessor_no_guard/expected/foo.h b/tools/versioner/tests/preprocessor_no_guard/expected/foo.h
deleted file mode 100644
index 3ef0c30..0000000
--- a/tools/versioner/tests/preprocessor_no_guard/expected/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __VERSIONER_NO_GUARD __INTRODUCED_IN(14);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_no_guard/headers/foo.h b/tools/versioner/tests/preprocessor_no_guard/headers/foo.h
deleted file mode 100644
index 3ef0c30..0000000
--- a/tools/versioner/tests/preprocessor_no_guard/headers/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __VERSIONER_NO_GUARD __INTRODUCED_IN(14);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/preprocessor_no_guard/run.sh b/tools/versioner/tests/preprocessor_no_guard/run.sh
deleted file mode 100644
index 1b0aae2..0000000
--- a/tools/versioner/tests/preprocessor_no_guard/run.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-rm -rf out
-set -e
-versioner headers -i -o out
-diff -q -w -B out expected
diff --git a/tools/versioner/tests/slow_preprocessor_idempotence/run.sh b/tools/versioner/tests/slow_preprocessor_idempotence/run.sh
deleted file mode 100644
index 6426156..0000000
--- a/tools/versioner/tests/slow_preprocessor_idempotence/run.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-rm -rf out
-set -e
-mkdir out
-versioner -o out/initial
-versioner out/initial ../../dependencies -o out/second
-diff -qrwB out/initial out/second
diff --git a/tools/versioner/tests/smoke/headers/foo.h b/tools/versioner/tests/smoke/headers/foo.h
deleted file mode 100644
index c201dbb..0000000
--- a/tools/versioner/tests/smoke/headers/foo.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-int foo() __INTRODUCED_IN(9);
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/smoke/platforms/libc.map.txt b/tools/versioner/tests/smoke/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/smoke/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/smoke/run.sh b/tools/versioner/tests/smoke/run.sh
deleted file mode 100644
index a34fda8..0000000
--- a/tools/versioner/tests/smoke/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/unnamed_bitfield/headers/foo.h b/tools/versioner/tests/unnamed_bitfield/headers/foo.h
deleted file mode 100644
index 58686c3..0000000
--- a/tools/versioner/tests/unnamed_bitfield/headers/foo.h
+++ /dev/null
@@ -1,8 +0,0 @@
-// <sys/timex.h> was causing a segfault when compiled in C++ mode because
-// versioner was trying to mangle the name of an unnamed bitfield.
-struct foo {
-  int : 32;
-  int : 32;
-  int : 32;
-  int : 32;
-};
diff --git a/tools/versioner/tests/unnamed_bitfield/platforms/libc.map.txt b/tools/versioner/tests/unnamed_bitfield/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/unnamed_bitfield/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/unnamed_bitfield/run.sh b/tools/versioner/tests/unnamed_bitfield/run.sh
deleted file mode 100644
index a34fda8..0000000
--- a/tools/versioner/tests/unnamed_bitfield/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -i
\ No newline at end of file
diff --git a/tools/versioner/tests/version_mismatch/expected_fail b/tools/versioner/tests/version_mismatch/expected_fail
deleted file mode 100644
index 95d284b..0000000
--- a/tools/versioner/tests/version_mismatch/expected_fail
+++ /dev/null
@@ -1,8 +0,0 @@
-versioner: inconsistent availability for symbol 'foo'
-versioner: failed to calculate symbol availability
-  foo: invalid
-    extern declaration @ headers/foo.h:6:1
-      introduced = 9
-    extern declaration @ headers/foo.h:8:1
-      introduced = 10
-versioner: validity check failed
diff --git a/tools/versioner/tests/version_mismatch/headers/foo.h b/tools/versioner/tests/version_mismatch/headers/foo.h
deleted file mode 100644
index ea35f36..0000000
--- a/tools/versioner/tests/version_mismatch/headers/foo.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#if __ANDROID_API__ <= 9
-int foo() __INTRODUCED_IN(9);
-#else
-int foo() __INTRODUCED_IN(10);
-#endif
-
-#if defined(__cplusplus)
-}
-#endif
diff --git a/tools/versioner/tests/version_mismatch/platforms/libc.map.txt b/tools/versioner/tests/version_mismatch/platforms/libc.map.txt
deleted file mode 100644
index 6cc4a2e..0000000
--- a/tools/versioner/tests/version_mismatch/platforms/libc.map.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBC {
-  global:
-    foo;
-};
diff --git a/tools/versioner/tests/version_mismatch/run.sh b/tools/versioner/tests/version_mismatch/run.sh
deleted file mode 100644
index 9bfbe6d..0000000
--- a/tools/versioner/tests/version_mismatch/run.sh
+++ /dev/null
@@ -1 +0,0 @@
-versioner headers -p platforms -r arm -a 9 -a 12 -i
\ No newline at end of file