Merge "Add cpu-target-features binary" into main
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/docs/status.md b/docs/status.md
index 0436c40..94784de 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,
@@ -56,7 +60,9 @@
 Current libc symbols: https://android.googlesource.com/platform/bionic/+/main/libc/libc.map.txt
 
 New libc functions in API level 36:
-  * `qsort_r` (new POSIX addition).
+  * `qsort_r`, `sig2str`/`str2sig` (POSIX Issue 8 additions).
+  * GNU/BSD extension `lchmod`.
+  * 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`,
diff --git a/libc/Android.bp b/libc/Android.bp
index 42ffd37..d450f41 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -571,7 +571,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",
@@ -625,10 +624,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,
@@ -687,9 +688,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",
@@ -699,8 +702,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",
     ],
@@ -711,11 +712,7 @@
     ],
 
     local_include_dirs: [
-        "private",
         "upstream-openbsd/android/include/",
-        "upstream-openbsd/lib/libc/gdtoa/",
-        "upstream-openbsd/lib/libc/include/",
-        "upstream-openbsd/lib/libc/stdio/",
     ],
 }
 
@@ -916,6 +913,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",
@@ -1032,7 +1030,6 @@
         "bionic/thread_private.cpp",
         "bionic/threads.cpp",
         "bionic/time.cpp",
-        "bionic/time_l.cpp",
         "bionic/tmpfile.cpp",
         "bionic/umount.cpp",
         "bionic/unlink.cpp",
@@ -1416,43 +1413,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"],
@@ -1470,6 +1437,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",
+    ],
 }
 
 // ========================================================
@@ -1666,7 +1657,6 @@
     },
 
     apex_available: [
-        "//apex_available:platform",
         "com.android.runtime",
     ],
 
@@ -1697,7 +1687,7 @@
         symbol_file: "libc.map.txt",
         export_headers_as_system: true,
         export_preprocessed_headers: ["include"],
-        export_llndk_headers: ["libc_llndk_headers"],
+        export_llndk_headers: ["libc_uapi_headers"],
     },
 }
 
@@ -1808,7 +1798,7 @@
 }
 
 cc_library_headers {
-    name: "libc_llndk_headers",
+    name: "libc_uapi_headers",
     visibility: [
         "//external/musl",
     ],
@@ -1903,13 +1893,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"],
         },
     },
 }
@@ -2229,17 +2219,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 {
@@ -2259,6 +2261,7 @@
         "kernel/uapi/xen/**/*.h",
     ],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2275,6 +2278,7 @@
     to: "scsi",
     srcs: ["kernel/android/scsi/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2283,6 +2287,7 @@
     to: "arm-linux-androideabi",
     srcs: ["kernel/uapi/asm-arm/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2291,6 +2296,7 @@
     to: "aarch64-linux-android",
     srcs: ["kernel/uapi/asm-arm64/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2299,6 +2305,7 @@
     to: "riscv64-linux-android",
     srcs: ["kernel/uapi/asm-riscv/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2307,6 +2314,7 @@
     to: "i686-linux-android",
     srcs: ["kernel/uapi/asm-x86/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2315,6 +2323,7 @@
     to: "x86_64-linux-android",
     srcs: ["kernel/uapi/asm-x86/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_library {
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-arm/static_function_dispatch.S b/libc/arch-arm/static_function_dispatch.S
deleted file mode 100644
index a8235c2..0000000
--- a/libc/arch-arm/static_function_dispatch.S
+++ /dev/null
@@ -1,46 +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); \
-    b impl; \
-END(name)
-
-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)
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-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..9d7a4c9 100644
--- a/libc/arch-x86/dynamic_function_dispatch.cpp
+++ b/libc/arch-x86/dynamic_function_dispatch.cpp
@@ -26,129 +26,150 @@
  * 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_is("atom")) RETURN_FUNC(memcmp_func_t, memcmp_atom);
+  if (__builtin_cpu_supports("sse4.1")) RETURN_FUNC(memcmp_func_t, memcmp_sse4);
+  RETURN_FUNC(memcmp_func_t, memcmp_generic);
 }
+MEMCMP_SHIM()
 
-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);
+  __builtin_cpu_init();
+  if (__builtin_cpu_is("atom")) RETURN_FUNC(memset_func_t, memset_atom);
+  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_is("atom")) RETURN_FUNC(__memset_chk_func, __memset_chk_atom);
-    RETURN_FUNC(__memset_chk_func, __memset_chk_generic);
+  __builtin_cpu_init();
+  if (__builtin_cpu_is("atom")) RETURN_FUNC(__memset_chk_func_t, __memset_chk_atom);
+  RETURN_FUNC(__memset_chk_func_t, __memset_chk_generic);
 }
+__MEMSET_CHK_SHIM()
 
-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);
+  __builtin_cpu_init();
+  if (__builtin_cpu_is("atom")) RETURN_FUNC(memmove_func_t, memmove_atom);
+  RETURN_FUNC(memmove_func_t, memmove_generic);
 }
+MEMMOVE_SHIM()
 
-typedef void* memcpy_func(void*, const void*, size_t);
-DEFINE_IFUNC_FOR(memcpy) {
-    return memmove_resolver();
-}
+DEFINE_IFUNC_FOR(memcpy) { return memmove_resolver(); }
+MEMCPY_SHIM()
 
-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);
+  __builtin_cpu_init();
+  if (__builtin_cpu_is("atom")) RETURN_FUNC(strcpy_func_t, strcpy_atom);
+  RETURN_FUNC(strcpy_func_t, strcpy_generic);
 }
+STRCPY_SHIM()
 
-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);
+  __builtin_cpu_init();
+  if (__builtin_cpu_is("atom")) RETURN_FUNC(strncpy_func_t, strncpy_atom);
+  RETURN_FUNC(strncpy_func_t, strncpy_generic);
 }
+STRNCPY_SHIM()
 
-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);
+  __builtin_cpu_init();
+  if (__builtin_cpu_is("atom")) RETURN_FUNC(strlen_func_t, strlen_atom);
+  RETURN_FUNC(strlen_func_t, strlen_generic);
 }
+STRLEN_SHIM()
 
-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);
+  __builtin_cpu_init();
+  // TODO: ssse3 is required by our x86 abi!
+  if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(strcmp_func_t, strcmp_ssse3);
+  RETURN_FUNC(strcmp_func_t, strcmp_generic);
 }
+STRCMP_SHIM()
 
-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);
+  __builtin_cpu_init();
+  // TODO: ssse3 is required by our x86 abi!
+  if (__builtin_cpu_supports("ssse3"))
+    RETURN_FUNC(strncmp_func_t, strncmp_ssse3);
+  RETURN_FUNC(strncmp_func_t, strncmp_generic);
 }
+STRNCMP_SHIM()
 
-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);
+  __builtin_cpu_init();
+  // TODO: ssse3 is required by our x86 abi!
+  if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(strcat_func_t, strcat_ssse3);
+  RETURN_FUNC(strcat_func_t, strcat_generic);
 }
+STRCAT_SHIM()
 
-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);
+  __builtin_cpu_init();
+  // TODO: ssse3 is required by our x86 abi!
+  if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(strncat_func_t, strncat_ssse3);
+  RETURN_FUNC(strncat_func_t, strncat_openbsd);
 }
+STRNCAT_SHIM()
 
-typedef size_t strlcat_func(char *dst, const char *src, size_t dsize);
+typedef size_t strlcat_func_t(char*, const char*, size_t);
 DEFINE_IFUNC_FOR(strlcat) {
-    __builtin_cpu_init();
-    if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(strlcat_func, strlcat_ssse3);
-    RETURN_FUNC(strlcat_func, strlcat_openbsd);
+  __builtin_cpu_init();
+  // TODO: ssse3 is required by our x86 abi!
+  if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(strlcat_func_t, strlcat_ssse3);
+  RETURN_FUNC(strlcat_func_t, strlcat_openbsd);
 }
+DEFINE_STATIC_SHIM(size_t strlcat(char* dst, const char* src, size_t n) {
+  FORWARD(strlcat)(dst, src, n);
+})
 
-typedef size_t strlcpy_func(char *dst, const char *src, size_t dsize);
+typedef size_t strlcpy_func_t(char*, const char*, size_t);
 DEFINE_IFUNC_FOR(strlcpy) {
-    __builtin_cpu_init();
-    if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(strlcpy_func, strlcpy_ssse3);
-    RETURN_FUNC(strlcpy_func, strlcpy_openbsd);
+  __builtin_cpu_init();
+  // TODO: ssse3 is required by our x86 abi!
+  if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(strlcpy_func_t, strlcpy_ssse3);
+  RETURN_FUNC(strlcpy_func_t, strlcpy_openbsd);
 }
+DEFINE_STATIC_SHIM(size_t strlcpy(char* dst, const char* src, size_t n) {
+  FORWARD(strlcpy)(dst, src, n);
+})
 
-typedef wchar_t* wcscat_func(wchar_t *s1, const wchar_t *s2);
+typedef wchar_t* wcscat_func_t(wchar_t*, const wchar_t*);
 DEFINE_IFUNC_FOR(wcscat) {
-    __builtin_cpu_init();
-    if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(wcscat_func, wcscat_ssse3);
-    RETURN_FUNC(wcscat_func, wcscat_freebsd);
+  __builtin_cpu_init();
+  // TODO: ssse3 is required by our x86 abi!
+  if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(wcscat_func_t, wcscat_ssse3);
+  RETURN_FUNC(wcscat_func_t, wcscat_freebsd);
 }
+DEFINE_STATIC_SHIM(wchar_t* wcscat(wchar_t* dst, const wchar_t* src) {
+  FORWARD(wcscat)(dst, src);
+})
 
-typedef wchar_t* wcscpy_func(wchar_t *s1, const wchar_t *s2);
+typedef wchar_t* wcscpy_func_t(wchar_t*, const wchar_t*);
 DEFINE_IFUNC_FOR(wcscpy) {
-    __builtin_cpu_init();
-    if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(wcscpy_func, wcscpy_ssse3);
-    RETURN_FUNC(wcscpy_func, wcscpy_freebsd);
+  __builtin_cpu_init();
+  // TODO: ssse3 is required by our x86 abi!
+  if (__builtin_cpu_supports("ssse3")) RETURN_FUNC(wcscpy_func_t, wcscpy_ssse3);
+  RETURN_FUNC(wcscpy_func_t, wcscpy_freebsd);
 }
+DEFINE_STATIC_SHIM(wchar_t* wcscpy(wchar_t* dst, const wchar_t* src) {
+  FORWARD(wcscpy)(dst, src);
+})
+
+typedef int wmemcmp_func_t(const wchar_t*, const wchar_t*, size_t);
+DEFINE_IFUNC_FOR(wmemcmp) {
+  __builtin_cpu_init();
+  if (__builtin_cpu_supports("sse4.1")) RETURN_FUNC(wmemcmp_func_t, wmemcmp_sse4);
+  if (__builtin_cpu_is("atom")) RETURN_FUNC(wmemcmp_func_t, wmemcmp_atom);
+  RETURN_FUNC(wmemcmp_func_t, wmemcmp_freebsd);
+}
+DEFINE_STATIC_SHIM(int wmemcmp(const wchar_t* lhs, const wchar_t* rhs, size_t n) {
+  FORWARD(wmemcmp)(lhs, rhs, n);
+})
 
 }  // extern "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_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/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/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/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_static.cpp b/libc/bionic/libc_init_static.cpp
index ac97376..f8f7d2a 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>
@@ -293,6 +294,28 @@
   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;
@@ -366,7 +389,10 @@
           async_safe_fatal("error: failed to set PROT_MTE on main thread stack: %m");
         }
       }
-
+      struct sigaction action = {};
+      action.sa_flags = SA_SIGINFO | SA_RESTART;
+      action.sa_sigaction = __enable_mte_signal_handler;
+      sigaction(BIONIC_ENABLE_MTE, &action, nullptr);
       return;
     }
   }
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/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..65749a4 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) {
@@ -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/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..a636d08 100644
--- a/libc/bionic/stdlib_l.cpp
+++ b/libc/bionic/stdlib_l.cpp
@@ -37,23 +37,6 @@
   return strtof(s, end_ptr);
 }
 
-long strtol_l(const char* s, char** end_ptr, int base, locale_t) {
-  return strtol(s, end_ptr, base);
-}
-
 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/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/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/dlext.h b/libc/include/android/dlext.h
index b42e5b2..842ceea 100644
--- a/libc/include/android/dlext.h
+++ b/libc/include/android/dlext.h
@@ -30,7 +30,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 +174,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/legacy_stdlib_inlines.h b/libc/include/android/legacy_stdlib_inlines.h
index f0985fe..a5a07ef 100644
--- a/libc/include/android/legacy_stdlib_inlines.h
+++ b/libc/include/android/legacy_stdlib_inlines.h
@@ -46,10 +46,6 @@
   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
 
 #endif
diff --git a/libc/include/android/versioning.h b/libc/include/android/versioning.h
index 6bab291..ecbc33f 100644
--- a/libc/include/android/versioning.h
+++ b/libc/include/android/versioning.h
@@ -21,7 +21,6 @@
 #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)))
@@ -41,17 +40,10 @@
 // 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.
 #if defined(__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__)
 #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)
 #else
 #define __BIONIC_AVAILABILITY(__what, ...) __attribute__((__availability__(android,strict,__what __VA_OPT__(,) __VA_ARGS__)))
-#define __INTRODUCED_IN_NO_GUARD_FOR_NDK(api_level)
 #endif
 
 #define __INTRODUCED_IN(api_level) __BIONIC_AVAILABILITY(introduced=api_level)
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/socket.h b/libc/include/bits/fortify/socket.h
index 02f94cc..1c3605b 100644
--- a/libc/include/bits/fortify/socket.h
+++ b/libc/include/bits/fortify/socket.h
@@ -30,8 +30,7 @@
 #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);
+ssize_t __sendto_chk(int, const void* _Nonnull, size_t, size_t, int, const struct sockaddr* _Nullable, socklen_t) __INTRODUCED_IN(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/string.h b/libc/include/bits/fortify/string.h
index 7df0b05..4d32b04 100644
--- a/libc/include/bits/fortify/string.h
+++ b/libc/include/bits/fortify/string.h
@@ -38,7 +38,7 @@
 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.  */
diff --git a/libc/include/bits/getentropy.h b/libc/include/bits/getentropy.h
index a5a14f7..4cd44f7 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.
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/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..195b34a 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.
  *
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..bfc02a8 100644
--- a/libc/include/bits/seek_constants.h
+++ b/libc/include/bits/seek_constants.h
@@ -46,7 +46,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 +54,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/strcasecmp.h b/libc/include/bits/strcasecmp.h
index 23acbe5..be910ad 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,
@@ -54,7 +54,7 @@
 int strcasecmp_l(const char* _Nonnull __s1, const char* _Nonnull __s2, locale_t _Nonnull __l) __attribute_pure__ __INTRODUCED_IN(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
diff --git a/libc/include/bits/threads_inlines.h b/libc/include/bits/threads_inlines.h
index 459866e..05b785a 100644
--- a/libc/include/bits/threads_inlines.h
+++ b/libc/include/bits/threads_inlines.h
@@ -116,13 +116,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..13a4254 100644
--- a/libc/include/bits/wctype.h
+++ b/libc/include/bits/wctype.h
@@ -58,8 +58,8 @@
 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);
+wint_t towctrans(wint_t __wc, wctrans_t _Nonnull __transform) __INTRODUCED_IN(26);
+wctrans_t _Nullable wctrans(const char* _Nonnull __name) __INTRODUCED_IN(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/dirent.h b/libc/include/dirent.h
index 4f5d0fb..5333d78 100644
--- a/libc/include/dirent.h
+++ b/libc/include/dirent.h
@@ -90,7 +90,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 +98,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 +106,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 +116,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 +129,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,13 +137,13 @@
 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().
  *
@@ -152,7 +152,7 @@
 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().
  *
@@ -163,7 +163,7 @@
 long telldir(DIR* _Nonnull __dir) __INTRODUCED_IN(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 +171,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 +195,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 +209,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
@@ -224,7 +224,7 @@
 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
diff --git a/libc/include/dlfcn.h b/libc/include/dlfcn.h
index d65a409..071d50a 100644
--- a/libc/include/dlfcn.h
+++ b/libc/include/dlfcn.h
@@ -48,7 +48,7 @@
 } 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.
  *
  * Returns a pointer to an opaque handle for use with other <dlfcn.h> functions
@@ -58,7 +58,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 +84,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 +97,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 +108,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.
@@ -119,7 +119,7 @@
 void* _Nullable dlvsym(void* __BIONIC_COMPLICATED_NULLNESS __handle, const char* _Nullable __symbol, const char* _Nullable __version) __INTRODUCED_IN(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
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..d8122d7 100644
--- a/libc/include/err.h
+++ b/libc/include/err.h
@@ -43,7 +43,7 @@
 __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 +53,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 +63,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 +73,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 +83,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 +91,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 +99,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 +107,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..cb867cd 100644
--- a/libc/include/error.h
+++ b/libc/include/error.h
@@ -38,7 +38,7 @@
 __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.
  *
@@ -47,7 +47,7 @@
 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 +55,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 +64,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 +73,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.
diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h
index 16ce6fa..1e9a285 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
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/iconv.h b/libc/include/iconv.h
index 27e04bb..9da46b4 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`,
@@ -63,7 +63,7 @@
 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 +74,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.
diff --git a/libc/include/ifaddrs.h b/libc/include/ifaddrs.h
index 7c0dcbf..c4d0e10 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,
@@ -83,7 +83,7 @@
 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.
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/link.h b/libc/include/link.h
index ee1fc42..216502e 100644
--- a/libc/include/link.h
+++ b/libc/include/link.h
@@ -99,7 +99,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..5904519 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
@@ -58,7 +58,7 @@
 void* _Nullable malloc(size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(1) __wur;
 
 /**
- * [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
@@ -67,7 +67,7 @@
 void* _Nullable calloc(size_t __item_count, size_t __item_size) __mallocfunc __BIONIC_ALLOC_SIZE(1,2) __wur;
 
 /**
- * [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
@@ -76,8 +76,11 @@
  */
 void* _Nullable realloc(void* _Nullable __ptr, size_t __byte_count) __BIONIC_ALLOC_SIZE(2) __wur;
 
+// Remove the explicit guard once //external/giflib has been fixed so that it no
+// longer provides a conflicting definition: http://b/352784252
+#if __ANDROID_API__ >= 29
 /**
- * [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
@@ -88,15 +91,16 @@
  * (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);
+#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
@@ -107,7 +111,7 @@
 void* _Nullable memalign(size_t __alignment, size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(2) __wur;
 
 /**
- * [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;
@@ -140,7 +144,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 +156,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:
@@ -349,7 +353,7 @@
 #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.
@@ -359,7 +363,7 @@
 int mallopt(int __option, int __value) __INTRODUCED_IN(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.
  *
@@ -370,7 +374,7 @@
 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 +385,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 +396,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.
  *
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/nl_types.h b/libc/include/nl_types.h
index f4d7f43..6c9935d 100644
--- a/libc/include/nl_types.h
+++ b/libc/include/nl_types.h
@@ -56,7 +56,7 @@
 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)`.
  *
@@ -65,7 +65,7 @@
 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,7 +75,7 @@
 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`.
  */
diff --git a/libc/include/poll.h b/libc/include/poll.h
index 6bdc886..0dda3da 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.
  *
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 0163c07..33c637f 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -70,9 +70,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
@@ -246,26 +244,20 @@
 int pthread_rwlock_unlock(pthread_rwlock_t* _Nonnull __rwlock);
 int pthread_rwlock_wrlock(pthread_rwlock_t* _Nonnull __rwlock);
 
-#if __ANDROID_API__ >= 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
 
 pthread_t pthread_self(void) __attribute_const__;
 
diff --git a/libc/include/pty.h b/libc/include/pty.h
index be447d6..1cfb772 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.
  *
@@ -52,7 +52,7 @@
 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,
diff --git a/libc/include/sched.h b/libc/include/sched.h
index 9f043b6..e8f7736 100644
--- a/libc/include/sched.h
+++ b/libc/include/sched.h
@@ -45,42 +45,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 +116,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 +124,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 +132,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 +140,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 +148,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 +156,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 +166,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 +175,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 +183,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 +191,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 +219,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 +227,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..85e31ee 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.
@@ -88,7 +88,7 @@
 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 +98,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.
@@ -113,7 +113,7 @@
 #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.
@@ -123,7 +123,7 @@
 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 +131,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.
@@ -144,7 +144,7 @@
 #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 +155,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 +168,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 +177,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 +192,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 +203,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/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..893fa9d 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -122,6 +122,34 @@
 int sigwaitinfo(const sigset_t* _Nonnull __set, siginfo_t* _Nullable __info) __INTRODUCED_IN(23);
 int sigwaitinfo64(const sigset64_t* _Nonnull __set, siginfo_t* _Nullable __info) __INTRODUCED_IN(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.
+ */
+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);
+
 __END_DECLS
 
 #endif
diff --git a/libc/include/spawn.h b/libc/include/spawn.h
index 3ce402f..f366239 100644
--- a/libc/include/spawn.h
+++ b/libc/include/spawn.h
@@ -46,14 +46,17 @@
 #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);
+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);
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index 279c658..d99d032 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -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,25 +172,25 @@
 #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.
  *
diff --git a/libc/include/stdio_ext.h b/libc/include/stdio_ext.h
index 8b106a6..d426a4a 100644
--- a/libc/include/stdio_ext.h
+++ b/libc/include/stdio_ext.h
@@ -39,7 +39,7 @@
 __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.
@@ -47,7 +47,7 @@
 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.
@@ -55,7 +55,7 @@
 int __freadable(FILE* _Nonnull __fp) __INTRODUCED_IN(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.
@@ -63,7 +63,7 @@
 int __freading(FILE* _Nonnull __fp) __INTRODUCED_IN(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.
@@ -71,7 +71,7 @@
 int __fwritable(FILE* _Nonnull __fp) __INTRODUCED_IN(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.
@@ -79,7 +79,7 @@
 int __fwriting(FILE* _Nonnull __fp) __INTRODUCED_IN(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.
@@ -87,15 +87,13 @@
 int __flbf(FILE* _Nonnull __fp) __INTRODUCED_IN(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.
@@ -111,7 +109,7 @@
 size_t __freadahead(FILE* _Nonnull __fp) __INTRODUCED_IN(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.
@@ -134,7 +132,7 @@
 #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`.
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index b160e6b..b31b122 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -68,28 +68,23 @@
 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);
-
 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);
-
-double strtod(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr);
-long double strtold(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr);
-
-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__;
+/**
+ * [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.
+ */
+__wur void* _Nullable aligned_alloc(size_t __alignment, size_t __size) __INTRODUCED_IN(28);
 
 __wur 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,13 +95,13 @@
  * 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,
@@ -115,13 +110,13 @@
 __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));
 
 /**
- * [qsort(3)](http://man7.org/linux/man-pages/man3/qsort.3.html) sorts an array
+ * [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)](http://man7.org/linux/man-pages/man3/qsort_r.3.html) sorts an
+ * [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.
  *
@@ -180,7 +175,7 @@
 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.
  *
@@ -192,7 +187,7 @@
 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);
+int mblen(const char* _Nullable __s, size_t __n) __INTRODUCED_IN(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);
@@ -210,22 +205,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 a67df4c..7c1c3be 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -57,7 +57,7 @@
 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,7 +65,7 @@
 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.
  *
@@ -108,8 +108,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 +144,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
@@ -133,7 +160,7 @@
 #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.
  *
diff --git a/libc/include/strings.h b/libc/include/strings.h
index 4b8cc08..d203bd2 100644
--- a/libc/include/strings.h
+++ b/libc/include/strings.h
@@ -72,7 +72,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 +83,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 +94,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/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/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/epoll.h b/libc/include/sys/epoll.h
index 2bad655..a5e3c14 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,
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..1a0e7f6 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,7 +126,7 @@
 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.
@@ -136,7 +136,7 @@
 int mlock2(const void* _Nonnull __addr, size_t __size, int __flags) __INTRODUCED_IN(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 +144,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 +152,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 +160,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.
  *
@@ -176,7 +176,7 @@
 #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.
@@ -212,7 +212,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.
@@ -222,4 +222,16 @@
  */
 int posix_madvise(void* _Nonnull __addr, size_t __size, int __advice) __INTRODUCED_IN(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.
+ */
+int mseal(void* _Nonnull __addr, size_t __size, unsigned long __flags) __INTRODUCED_IN(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/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/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..6e32705 100644
--- a/libc/include/sys/quota.h
+++ b/libc/include/sys/quota.h
@@ -45,7 +45,7 @@
 __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.
  *
diff --git a/libc/include/sys/random.h b/libc/include/sys/random.h
index 2ff5349..fcea419 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.
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/select.h b/libc/include/sys/select.h
index 437a234..d5b3495 100644
--- a/libc/include/sys/select.h
+++ b/libc/include/sys/select.h
@@ -87,7 +87,7 @@
 #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.
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/signalfd.h b/libc/include/sys/signalfd.h
index 2be9bdc..5568b7d 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.
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index f916573..bb188fe 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -99,7 +99,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 +142,145 @@
 #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.
+ */
+int lchmod(const char* _Nonnull __path, mode_t __mode) __INTRODUCED_IN(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.
+ */
+int mkfifoat(int __dir_fd, const char* _Nonnull __path, mode_t __mode) __INTRODUCED_IN(23);
 
 /**
  * Used in the tv_nsec field of an argument to utimensat()/futimens()
@@ -205,7 +324,7 @@
 
 #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.
diff --git a/libc/include/sys/statvfs.h b/libc/include/sys/statvfs.h
index 7bc5e63..2feca81 100644
--- a/libc/include/sys/statvfs.h
+++ b/libc/include/sys/statvfs.h
@@ -92,7 +92,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 +100,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/sysinfo.h b/libc/include/sys/sysinfo.h
index cae5c49..5956feb 100644
--- a/libc/include/sys/sysinfo.h
+++ b/libc/include/sys/sysinfo.h
@@ -39,14 +39,14 @@
 __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.
@@ -56,7 +56,7 @@
 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 +66,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 +76,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.
diff --git a/libc/include/sys/timerfd.h b/libc/include/sys/timerfd.h
index de1f55b..bfa9a55 100644
--- a/libc/include/sys/timerfd.h
+++ b/libc/include/sys/timerfd.h
@@ -33,20 +33,23 @@
  * @brief Timer file descriptors.
  */
 
-#include <fcntl.h> /* For O_CLOEXEC and O_NONBLOCK. */
+#include <fcntl.h>
+#include <linux/timerfd.h>
 #include <time.h>
 #include <sys/cdefs.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 +62,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 +70,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..828eb47 100644
--- a/libc/include/sys/timex.h
+++ b/libc/include/sys/timex.h
@@ -40,7 +40,7 @@
 __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.
  *
diff --git a/libc/include/sys/uio.h b/libc/include/sys/uio.h
index c8c64ae..d3e6561 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.
  *
@@ -72,7 +72,7 @@
 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.
  *
@@ -98,7 +98,7 @@
 ssize_t pwritev64(int __fd, const struct iovec* _Nonnull __iov, int __count, off64_t __offset) __INTRODUCED_IN(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.
  *
@@ -110,7 +110,7 @@
 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.
  *
@@ -136,7 +136,7 @@
 ssize_t pwritev64v2(int __fd, const struct iovec* _Nonnull __iov, int __count, off64_t __offset, int __flags) __INTRODUCED_IN(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,
@@ -147,7 +147,7 @@
 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,
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..1a640ba 100644
--- a/libc/include/sys/vfs.h
+++ b/libc/include/sys/vfs.h
@@ -40,6 +40,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/xattr.h b/libc/include/sys/xattr.h
index 745f50c..38c11e2 100644
--- a/libc/include/sys/xattr.h
+++ b/libc/include/sys/xattr.h
@@ -40,7 +40,7 @@
 __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 +55,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 +69,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 +84,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 +96,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 +107,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 +119,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 +131,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 +142,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 +154,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 +163,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 +172,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..33979f0 100644
--- a/libc/include/syslog.h
+++ b/libc/include/syslog.h
@@ -212,34 +212,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/time.h b/libc/include/time.h
index f448851..e9d6569 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()
@@ -169,7 +169,7 @@
 time_t mktime_z(timezone_t _Nonnull __tz, struct tm* _Nonnull __tm) __INTRODUCED_IN(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 +180,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`.
  *
@@ -208,7 +208,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 +219,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 +235,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 +245,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 +261,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 +273,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 +283,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
@@ -328,7 +328,7 @@
 void tzfree(timezone_t _Nullable __tz) __INTRODUCED_IN(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,7 +340,7 @@
 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.
@@ -348,7 +348,7 @@
 int clock_getcpuclockid(pid_t __pid, clockid_t* _Nonnull __clock) __INTRODUCED_IN(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 +356,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 +364,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 +375,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 +383,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 +391,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 +399,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 +407,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 +415,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.
  *
diff --git a/libc/include/uchar.h b/libc/include/uchar.h
index 626372a..55a36e7 100644
--- a/libc/include/uchar.h
+++ b/libc/include/uchar.h
@@ -55,7 +55,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 +64,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 +73,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..e1c268f 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -79,7 +79,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,
@@ -103,7 +103,7 @@
 pid_t _Fork(void) __INTRODUCED_IN(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 +114,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 +122,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.
@@ -150,7 +150,7 @@
 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 +161,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 +172,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 +183,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 +194,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 +205,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 +216,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 +227,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
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/wchar.h b/libc/include/wchar.h
index c4e9679..e86f94d 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);
@@ -94,20 +94,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);
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 35e67c8..0d2e42f 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -591,6 +591,7 @@
     killpg;
     klogctl;
     labs;
+    lchmod; # introduced=36
     lchown;
     lcong48; # introduced=23
     ldexp;
@@ -670,6 +671,7 @@
     mprotect;
     mrand48;
     mremap;
+    mseal; # introduced=36
     msync;
     munlock;
     munlockall;
@@ -953,6 +955,7 @@
     setvbuf;
     setxattr;
     shutdown;
+    sig2str; # introduced=36
     sigaction;
     sigaddset;
     sigaltstack;
@@ -995,6 +998,7 @@
     stdout; # var introduced=23
     stpcpy;
     stpncpy;
+    str2sig; # introduced=36
     strcasecmp;
     strcasecmp_l; # introduced=23
     strcasestr;
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/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..37b9665 100644
--- a/libc/stdio/stdio.cpp
+++ b/libc/stdio/stdio.cpp
@@ -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/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-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/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/linker_main.cpp b/linker/linker_main.cpp
index 0e5fb96..86b6509 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -250,12 +250,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.
@@ -380,7 +374,12 @@
   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);
diff --git a/tests/Android.bp b/tests/Android.bp
index cfaeced..deb2843 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -566,12 +566,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 {
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/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/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/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/stdlib_test.cpp b/tests/stdlib_test.cpp
index 3216066..fac9b9b 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -519,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/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_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/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;