Merge "Revert "Disable signal frame unwinding tests on arm64""
diff --git a/libc/Android.bp b/libc/Android.bp
index 10f4311..6ba60ca 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1060,6 +1060,7 @@
         "bionic/get_device_api_level.cpp",
         "bionic/grp_pwd.cpp",
         "bionic/grp_pwd_file.cpp",
+        "bionic/heap_zero_init.cpp",
         "bionic/iconv.cpp",
         "bionic/icu_wrappers.cpp",
         "bionic/ifaddrs.cpp",
@@ -1078,7 +1079,6 @@
         "bionic/mblen.cpp",
         "bionic/mbrtoc16.cpp",
         "bionic/mbrtoc32.cpp",
-        "bionic/memory_mitigation_state.cpp",
         "bionic/mempcpy.cpp",
         "bionic/mkdir.cpp",
         "bionic/mkfifo.cpp",
@@ -1579,6 +1579,7 @@
         "bionic/NetdClient.cpp",
         "arch-common/bionic/crtend_so.S",
     ],
+    bazel_module: { bp2build_available: true },
 }
 
 filegroup {
@@ -1589,6 +1590,7 @@
         "bionic/malloc_common.cpp",
         "bionic/malloc_limit.cpp",
     ],
+    bazel_module: { bp2build_available: true },
 }
 
 filegroup {
@@ -1597,6 +1599,7 @@
         "arch-arm/bionic/exidx_dynamic.c",
         "arch-arm/bionic/atexit_legacy.c",
     ],
+    bazel_module: { bp2build_available: true },
 }
 
 // ========================================================
@@ -1631,6 +1634,7 @@
             "gwp_asan",
             "libc_init_dynamic",
             "libc_common_shared",
+            "libunwind-exported",
         ],
     },
 
@@ -1667,13 +1671,14 @@
             ldflags: ["-Wl,--hash-style=both"],
 
             version_script: ":libc.arm.map",
+            no_libcrt: true,
 
             shared: {
                 srcs: [":libc_sources_shared_arm"],
                 // special for arm
                 cflags: ["-DCRT_LEGACY_WORKAROUND"],
-
-                whole_static_libs: [ "libunwind_llvm" ],
+                // For backwards-compatibility, some arm32 builtins are exported from libc.so.
+                static_libs: ["libclang_rt.builtins-arm-android-exported"],
             },
 
             // Arm 32 bit does not produce complete exidx unwind information
@@ -1692,10 +1697,6 @@
             strip: {
                 keep_symbols: true,
             },
-
-            shared: {
-                whole_static_libs: [ "libgcc_stripped" ],
-            },
         },
         x86: {
             // TODO: This is to work around b/24465209. Remove after root cause is fixed.
@@ -1703,16 +1704,18 @@
             ldflags: ["-Wl,--hash-style=both"],
 
             version_script: ":libc.x86.map",
+            no_libcrt: true,
+
+            shared: {
+                // For backwards-compatibility, some x86 builtins are exported from libc.so.
+                static_libs: ["libclang_rt.builtins-i686-android-exported"],
+            },
 
             // Leave the symbols in the shared library so that stack unwinders can produce
             // meaningful name resolution.
             strip: {
                 keep_symbols: true,
             },
-
-            shared: {
-                whole_static_libs: [ "libgcc_stripped" ],
-            },
         },
         x86_64: {
             version_script: ":libc.x86_64.map",
@@ -1722,10 +1725,6 @@
             strip: {
                 keep_symbols: true,
             },
-
-            shared: {
-                whole_static_libs: [ "libgcc_stripped" ],
-            },
         },
     },
 
@@ -1758,6 +1757,7 @@
     srcs: ["libc.map.txt"],
     tool_files: [":bionic-generate-version-script"],
     cmd: "$(location :bionic-generate-version-script) arm $(in) $(out)",
+    bazel_module: { bp2build_available: true },
 }
 
 genrule {
@@ -1766,6 +1766,7 @@
     srcs: ["libc.map.txt"],
     tool_files: [":bionic-generate-version-script"],
     cmd: "$(location :bionic-generate-version-script) arm64 $(in) $(out)",
+    bazel_module: { bp2build_available: true },
 }
 
 genrule {
@@ -1774,6 +1775,7 @@
     srcs: ["libc.map.txt"],
     tool_files: [":bionic-generate-version-script"],
     cmd: "$(location :bionic-generate-version-script) x86 $(in) $(out)",
+    bazel_module: { bp2build_available: true },
 }
 
 genrule {
@@ -1782,6 +1784,7 @@
     srcs: ["libc.map.txt"],
     tool_files: [":bionic-generate-version-script"],
     cmd: "$(location :bionic-generate-version-script) x86_64 $(in) $(out)",
+    bazel_module: { bp2build_available: true },
 }
 
 // Headers that only other parts of the platform can include.
@@ -2097,6 +2100,8 @@
     local_include_dirs: ["include"],
     srcs: ["arch-common/bionic/crtbegin.c"],
     defaults: ["crt_defaults"],
+    // When using libc.a, we're using the latest library regardless of target API level.
+    min_sdk_version: "current",
 }
 
 cc_object {
@@ -2107,6 +2112,8 @@
         "crtbrand",
     ],
     defaults: ["crt_defaults"],
+    // When using libc.a, we're using the latest library regardless of target API level.
+    min_sdk_version: "current",
 }
 
 cc_object {
@@ -2246,7 +2253,6 @@
 
 ndk_library {
     name: "libc",
-    native_bridge_supported: true,
     symbol_file: "libc.map.txt",
     first_version: "9",
 }
@@ -2357,53 +2363,11 @@
     ],
 }
 
-// Generate the C++ policy sources for app and system seccomp-bpf filters.
-python_binary_host {
-    name: "genseccomp",
-    main: "tools/genseccomp.py",
-
-    srcs: [
-        "tools/genseccomp.py",
-        "tools/gensyscalls.py",
-    ],
-
-    data: [
-        "kernel/uapi/**/*.h",
-    ],
-
-    version: {
-        py2: {
-            enabled: true,
-        },
-        py3: {
-            enabled: false,
-        },
-    },
+filegroup {
+    name: "all_kernel_uapi_headers",
+    srcs: ["kernel/uapi/**/*.h"],
 }
 
-python_binary_host {
-    name: "genfunctosyscallnrs",
-    main: "tools/genfunctosyscallnrs.py",
-
-    srcs: [
-        "tools/genseccomp.py",
-        "tools/genfunctosyscallnrs.py",
-        "tools/gensyscalls.py",
-    ],
-
-    data: [
-        "kernel/uapi/**/*.h",
-    ],
-
-    version: {
-        py2: {
-            enabled: true,
-        },
-        py3: {
-            enabled: false,
-        },
-    },
-}
 
 cc_genrule {
     name: "func_to_syscall_nrs",
diff --git a/libc/NOTICE b/libc/NOTICE
index 7041e5c..f57b03a 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -1532,39 +1532,6 @@
 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. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-   This product includes software developed by the University of
-   California, Berkeley and its contributors.
-4. 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1985, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
 3. Neither the name of the University nor the names of its contributors
    may be used to endorse or promote products derived from this software
    without specific prior written permission.
@@ -2596,39 +2563,6 @@
 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. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-   This product includes software developed by the University of
-   California, Berkeley and its contributors.
-4. 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1992, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
 3. Neither the name of the University nor the names of its contributors
    may be used to endorse or promote products derived from this software
    without specific prior written permission.
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 7cf7a2d..33a8a61 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -113,6 +113,7 @@
 int         msync(const void*, size_t, int)    all
 int         mprotect(const void*, size_t, int)  all
 int         madvise(void*, size_t, int)  all
+int         process_madvise(int, const struct iovec*, size_t, int, unsigned int)     all
 int mlock(const void* addr, size_t len)    all
 int mlock2(const void* addr, size_t len, int flags)    all
 int         munlock(const void* addr, size_t len)   all
diff --git a/libc/arch-arm/generic/bionic/strlen.c b/libc/arch-arm/generic/bionic/strlen.c
index 43d9e51..a6fde8b 100644
--- a/libc/arch-arm/generic/bionic/strlen.c
+++ b/libc/arch-arm/generic/bionic/strlen.c
@@ -116,8 +116,8 @@
         "beq     2f                         \n"
         "add     %[l], %[l], #1             \n"
         "tst     %[v], #0xFF0000            \n"
-        "it      ne                         \n"
-        "addne   %[l], %[l], #1             \n"
+        "beq     2f                         \n"
+        "add     %[l], %[l], #1             \n"
         "2:                                 \n"
         : [l]"=&r"(l), [v]"=&r"(v), [t]"=&r"(t), [s]"=&r"(u.b)
         : "%[l]"(l), "%[s]"(u.b), [mask]"r"(0x80808080UL)
diff --git a/libc/arch-arm64/bionic/setjmp.S b/libc/arch-arm64/bionic/setjmp.S
index 07270c9..351516f 100644
--- a/libc/arch-arm64/bionic/setjmp.S
+++ b/libc/arch-arm64/bionic/setjmp.S
@@ -118,7 +118,7 @@
 // int sigsetjmp(sigjmp_buf env, int save_signal_mask);
 ENTRY(sigsetjmp)
 __BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(sigsetjmp)
-  hint #25 // paciasp
+  paciasp
   .cfi_negate_ra_state
   stp x0, x30, [sp, #-16]!
   .cfi_def_cfa_offset 16
@@ -186,7 +186,7 @@
 #endif
 
   mov w0, #0
-  hint #29 // autiasp
+  autiasp
   .cfi_negate_ra_state
   ret
 END(sigsetjmp)
@@ -296,7 +296,7 @@
   // Set return value.
   cmp w1, wzr
   csinc w0, w1, wzr, ne
-  hint #29 // autiasp
+  autiasp
   .cfi_negate_ra_state
   ret
 END(siglongjmp)
diff --git a/libc/arch-arm64/bionic/vfork.S b/libc/arch-arm64/bionic/vfork.S
index 81b84a3..df7b063 100644
--- a/libc/arch-arm64/bionic/vfork.S
+++ b/libc/arch-arm64/bionic/vfork.S
@@ -67,7 +67,7 @@
 
     // Clean up stack shadow in the parent process.
     // https://github.com/google/sanitizers/issues/925
-    hint #25 // paciasp
+    paciasp
     .cfi_negate_ra_state
     stp x0, x30, [sp, #-16]!
     .cfi_adjust_cfa_offset 16
@@ -81,7 +81,7 @@
     .cfi_adjust_cfa_offset -16
     .cfi_restore x0
     .cfi_restore x30
-    hint #29 // autiasp
+    autiasp
     .cfi_negate_ra_state
 
 #endif
diff --git a/libc/arch-common/bionic/crtbegin.c b/libc/arch-common/bionic/crtbegin.c
index 29b02dc..f2b6638 100644
--- a/libc/arch-common/bionic/crtbegin.c
+++ b/libc/arch-common/bionic/crtbegin.c
@@ -49,7 +49,7 @@
 #define POST "; .size _start, .-_start"
 
 #if defined(__aarch64__)
-__asm__(PRE "/* BTI J */ hint #36; mov x0,sp; b _start_main" POST);
+__asm__(PRE "bti j; mov x0,sp; b _start_main" POST);
 #elif defined(__arm__)
 __asm__(PRE "mov r0,sp; b _start_main" POST);
 #elif defined(__i386__)
diff --git a/libc/bionic/heap_tagging.cpp b/libc/bionic/heap_tagging.cpp
index 49b02da..ffbabb9 100644
--- a/libc/bionic/heap_tagging.cpp
+++ b/libc/bionic/heap_tagging.cpp
@@ -52,6 +52,9 @@
         globals->heap_pointer_tag = (reinterpret_cast<uintptr_t>(POINTER_TAG) << TAG_SHIFT) |
                                     (0xffull << CHECK_SHIFT) | (0xffull << UNTAG_SHIFT);
       });
+#if defined(USE_SCUDO)
+      scudo_malloc_disable_memory_tagging();
+#endif  // USE_SCUDO
       break;
 #if defined(USE_SCUDO)
     case M_HEAP_TAGGING_LEVEL_SYNC:
@@ -96,12 +99,7 @@
 }
 
 // Requires `g_heap_tagging_lock` to be held.
-bool SetHeapTaggingLevel(void* arg, size_t arg_size) {
-  if (arg_size != sizeof(HeapTaggingLevel)) {
-    return false;
-  }
-
-  auto tag_level = *reinterpret_cast<HeapTaggingLevel*>(arg);
+bool SetHeapTaggingLevel(HeapTaggingLevel tag_level) {
   if (tag_level == heap_tagging_level) {
     return true;
   }
diff --git a/libc/bionic/heap_tagging.h b/libc/bionic/heap_tagging.h
index db45fc1..110b6ed 100644
--- a/libc/bionic/heap_tagging.h
+++ b/libc/bionic/heap_tagging.h
@@ -42,5 +42,5 @@
 
 // These functions can be called in a multithreaded context, and thus should
 // only be called when holding the `g_heap_tagging_lock`.
-bool SetHeapTaggingLevel(void* arg, size_t arg_size);
+bool SetHeapTaggingLevel(HeapTaggingLevel level);
 HeapTaggingLevel GetHeapTaggingLevel();
diff --git a/libc/bionic/memory_mitigation_state.h b/libc/bionic/heap_zero_init.cpp
similarity index 83%
copy from libc/bionic/memory_mitigation_state.h
copy to libc/bionic/heap_zero_init.cpp
index ffa1912..f5a05e5 100644
--- a/libc/bionic/memory_mitigation_state.h
+++ b/libc/bionic/heap_zero_init.cpp
@@ -26,8 +26,14 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#include "heap_zero_init.h"
 
-#include <stddef.h>
+extern "C" void scudo_malloc_set_zero_contents(int zero_contents);
 
-bool DisableMemoryMitigations(void* arg, size_t arg_size);
+bool SetHeapZeroInitialize(bool zero_init __attribute__((__unused__))) {
+#ifdef USE_SCUDO
+  scudo_malloc_set_zero_contents(zero_init);
+  return true;
+#endif
+  return false;
+}
diff --git a/libc/bionic/memory_mitigation_state.h b/libc/bionic/heap_zero_init.h
similarity index 89%
rename from libc/bionic/memory_mitigation_state.h
rename to libc/bionic/heap_zero_init.h
index ffa1912..f78e01f 100644
--- a/libc/bionic/memory_mitigation_state.h
+++ b/libc/bionic/heap_zero_init.h
@@ -28,6 +28,6 @@
 
 #pragma once
 
-#include <stddef.h>
-
-bool DisableMemoryMitigations(void* arg, size_t arg_size);
+// Sets heap zero initialization to on (true) or off (false). Returns false on
+// failure, true otherwise.
+bool SetHeapZeroInitialize(bool zero_init);
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index f2c3f1c..01cd2e5 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -87,6 +87,11 @@
 }
 
 void __libc_init_scudo() {
+  // Heap tagging level *must* be set before interacting with Scudo, otherwise
+  // the primary will be mapped with PROT_MTE even if MTE is is not enabled in
+  // this process.
+  SetDefaultHeapTaggingLevel();
+
 // TODO(b/158870657) make this unconditional when all devices support SCUDO.
 #if defined(USE_SCUDO)
 #if defined(SCUDO_PATTERN_FILL_CONTENTS)
@@ -95,7 +100,6 @@
   scudo_malloc_set_zero_contents(1);
 #endif
 #endif
-  SetDefaultHeapTaggingLevel();
 }
 
 __BIONIC_WEAK_FOR_NATIVE_BRIDGE
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index 3705606..2e4ee11 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -39,15 +39,17 @@
 #include "libc_init_common.h"
 #include "pthread_internal.h"
 
+#include "platform/bionic/macros.h"
+#include "platform/bionic/mte.h"
 #include "platform/bionic/page.h"
+#include "private/KernelArgumentBlock.h"
+#include "private/bionic_asm.h"
+#include "private/bionic_asm_note.h"
 #include "private/bionic_call_ifunc_resolver.h"
 #include "private/bionic_elf_tls.h"
 #include "private/bionic_globals.h"
-#include "platform/bionic/macros.h"
-#include "private/bionic_asm.h"
-#include "private/bionic_asm_note.h"
 #include "private/bionic_tls.h"
-#include "private/KernelArgumentBlock.h"
+#include "sys/system_properties.h"
 
 #if __has_feature(hwaddress_sanitizer)
 #include <sanitizer/hwasan_interface.h>
@@ -61,6 +63,7 @@
 #endif
 
 extern "C" int __cxa_atexit(void (*)(void *), void *, void *);
+extern "C" const char* __gnu_basename(const char* path);
 
 static void call_array(init_func_t** list, int argc, char* argv[], char* envp[]) {
   // First element is -1, list is null-terminated
@@ -160,6 +163,30 @@
   layout.finish_layout();
 }
 
+// Get the presiding config string, in the following order of priority:
+//   1. Environment variables.
+//   2. System properties, in the order they're specified in sys_prop_names.
+// If neither of these options are specified, this function returns false.
+// Otherwise, it returns true, and the presiding options string is written to
+// the `options` buffer of size `size`. If this function returns true, `options`
+// is guaranteed to be null-terminated. `options_size` should be at least
+// PROP_VALUE_MAX.
+bool get_config_from_env_or_sysprops(const char* env_var_name, const char* const* sys_prop_names,
+                                     size_t sys_prop_names_size, char* options,
+                                     size_t options_size) {
+  const char* env = getenv(env_var_name);
+  if (env && *env != '\0') {
+    strncpy(options, env, options_size);
+    options[options_size - 1] = '\0'; // Ensure null-termination.
+    return true;
+  }
+
+  for (size_t i = 0; i < sys_prop_names_size; ++i) {
+    if (__system_property_get(sys_prop_names[i], options) && *options != '\0') return true;
+  }
+  return false;
+}
+
 #ifdef __aarch64__
 static bool __read_memtag_note(const ElfW(Nhdr)* note, const char* name, const char* desc,
                                unsigned* result) {
@@ -204,42 +231,94 @@
   return 0;
 }
 
+// Returns true if there's an environment setting (either sysprop or env var)
+// that should overwrite the ELF note, and places the equivalent heap tagging
+// level into *level.
+static bool get_environment_memtag_setting(HeapTaggingLevel* level) {
+  static const char kMemtagPrognameSyspropPrefix[] = "arm64.memtag.process.";
+
+  const char* progname = __libc_shared_globals()->init_progname;
+  if (progname == nullptr) return false;
+
+  const char* basename = __gnu_basename(progname);
+
+  static constexpr size_t kOptionsSize = PROP_VALUE_MAX;
+  char options_str[kOptionsSize];
+  size_t sysprop_size = strlen(basename) + strlen(kMemtagPrognameSyspropPrefix) + 1;
+  char* sysprop_name = static_cast<char*>(alloca(sysprop_size));
+
+  async_safe_format_buffer(sysprop_name, sysprop_size, "%s%s", kMemtagPrognameSyspropPrefix,
+                           basename);
+
+  if (!get_config_from_env_or_sysprops("MEMTAG_OPTIONS", &sysprop_name,
+                                       /* sys_prop_names_size */ 1, options_str, kOptionsSize)) {
+    return false;
+  }
+
+  if (strcmp("sync", options_str) == 0) {
+    *level = M_HEAP_TAGGING_LEVEL_SYNC;
+  } else if (strcmp("async", options_str) == 0) {
+    *level = M_HEAP_TAGGING_LEVEL_ASYNC;
+  } else if (strcmp("off", options_str) == 0) {
+    *level = M_HEAP_TAGGING_LEVEL_TBI;
+  } else {
+    async_safe_format_log(
+        ANDROID_LOG_ERROR, "libc",
+        "unrecognized memtag level: \"%s\" (options are \"sync\", \"async\", or \"off\").",
+        options_str);
+    return false;
+  }
+
+  return true;
+}
+
+// Returns the initial heap tagging level. Note: This function will never return
+// M_HEAP_TAGGING_LEVEL_NONE, if MTE isn't enabled for this process we enable
+// M_HEAP_TAGGING_LEVEL_TBI.
+static HeapTaggingLevel __get_heap_tagging_level(const void* phdr_start, size_t phdr_ct,
+                                                 uintptr_t load_bias) {
+  HeapTaggingLevel level;
+  if (get_environment_memtag_setting(&level)) return level;
+
+  unsigned note_val =
+      __get_memtag_note(reinterpret_cast<const ElfW(Phdr)*>(phdr_start), phdr_ct, load_bias);
+  if (note_val & ~(NT_MEMTAG_LEVEL_MASK | NT_MEMTAG_HEAP)) {
+    async_safe_fatal("unrecognized android.memtag note: desc = %d", note_val);
+  }
+
+  if (!(note_val & NT_MEMTAG_HEAP)) return M_HEAP_TAGGING_LEVEL_TBI;
+
+  unsigned memtag_level = note_val & NT_MEMTAG_LEVEL_MASK;
+  switch (memtag_level) {
+    case NT_MEMTAG_LEVEL_ASYNC:
+      return M_HEAP_TAGGING_LEVEL_ASYNC;
+    case NT_MEMTAG_LEVEL_DEFAULT:
+    case NT_MEMTAG_LEVEL_SYNC:
+      return M_HEAP_TAGGING_LEVEL_SYNC;
+    default:
+      async_safe_fatal("unrecognized android.memtag note: level = %d", memtag_level);
+  }
+}
+
 // Figure out the desired memory tagging mode (sync/async, heap/globals/stack) for this executable.
 // This function is called from the linker before the main executable is relocated.
 __attribute__((no_sanitize("hwaddress", "memtag"))) void __libc_init_mte(const void* phdr_start,
                                                                          size_t phdr_ct,
                                                                          uintptr_t load_bias) {
-  unsigned v =
-      __get_memtag_note(reinterpret_cast<const ElfW(Phdr)*>(phdr_start), phdr_ct, load_bias);
+  HeapTaggingLevel level = __get_heap_tagging_level(phdr_start, phdr_ct, load_bias);
 
-  if (v & ~(NT_MEMTAG_LEVEL_MASK | NT_MEMTAG_HEAP)) {
-    async_safe_fatal("unrecognized android.memtag note: desc = %d", v);
-  }
+  if (level == M_HEAP_TAGGING_LEVEL_SYNC || level == M_HEAP_TAGGING_LEVEL_ASYNC) {
+    unsigned long prctl_arg = PR_TAGGED_ADDR_ENABLE | PR_MTE_TAG_SET_NONZERO;
+    prctl_arg |= (level == M_HEAP_TAGGING_LEVEL_SYNC) ? PR_MTE_TCF_SYNC : PR_MTE_TCF_ASYNC;
 
-  if (v & NT_MEMTAG_HEAP) {
-    unsigned memtag_level = v & NT_MEMTAG_LEVEL_MASK;
-    unsigned long arg = PR_TAGGED_ADDR_ENABLE | (0xfffe << PR_MTE_TAG_SHIFT);
-    HeapTaggingLevel level;
-    switch (memtag_level) {
-      case NT_MEMTAG_LEVEL_ASYNC:
-        arg |= PR_MTE_TCF_ASYNC;
-        level = M_HEAP_TAGGING_LEVEL_ASYNC;
-        break;
-      case NT_MEMTAG_LEVEL_DEFAULT:
-      case NT_MEMTAG_LEVEL_SYNC:
-        arg |= PR_MTE_TCF_SYNC;
-        level = M_HEAP_TAGGING_LEVEL_SYNC;
-        break;
-      default:
-        async_safe_fatal("unrecognized android.memtag note: level = %d", memtag_level);
-    }
-
-    if (prctl(PR_SET_TAGGED_ADDR_CTRL, arg, 0, 0, 0) == 0) {
+    if (prctl(PR_SET_TAGGED_ADDR_CTRL, prctl_arg, 0, 0, 0) == 0) {
       __libc_shared_globals()->initial_heap_tagging_level = level;
       return;
     }
   }
 
+  // MTE was either not enabled, or wasn't supported on this device. Try and use
+  // TBI.
   if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0) == 0) {
     __libc_shared_globals()->initial_heap_tagging_level = M_HEAP_TAGGING_LEVEL_TBI;
   }
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 0ee12a7..c91efa0 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -44,10 +44,10 @@
 
 #include "gwp_asan_wrappers.h"
 #include "heap_tagging.h"
+#include "heap_zero_init.h"
 #include "malloc_common.h"
 #include "malloc_limit.h"
 #include "malloc_tagged_pointers.h"
-#include "memory_mitigation_state.h"
 
 // =============================================================================
 // Global variables instantations.
@@ -102,6 +102,15 @@
 }
 
 extern "C" int mallopt(int param, int value) {
+  // Some are handled by libc directly rather than by the allocator.
+  if (param == M_BIONIC_SET_HEAP_TAGGING_LEVEL) {
+    ScopedPthreadMutexLocker locker(&g_heap_tagging_lock);
+    return SetHeapTaggingLevel(static_cast<HeapTaggingLevel>(value));
+  }
+  if (param == M_BIONIC_ZERO_INIT) {
+    return SetHeapZeroInitialize(value);
+  }
+  // The rest we pass on...
   auto dispatch_table = GetDispatchTable();
   if (__predict_false(dispatch_table != nullptr)) {
     return dispatch_table->mallopt(param, value);
@@ -316,10 +325,6 @@
   if (opcode == M_SET_ALLOCATION_LIMIT_BYTES) {
     return LimitEnable(arg, arg_size);
   }
-  if (opcode == M_SET_HEAP_TAGGING_LEVEL) {
-    ScopedPthreadMutexLocker locker(&g_heap_tagging_lock);
-    return SetHeapTaggingLevel(arg, arg_size);
-  }
   if (opcode == M_INITIALIZE_GWP_ASAN) {
     if (arg == nullptr || arg_size != sizeof(bool)) {
       errno = EINVAL;
@@ -329,9 +334,6 @@
       return MaybeInitGwpAsan(globals, *reinterpret_cast<bool*>(arg));
     });
   }
-  if (opcode == M_DISABLE_MEMORY_MITIGATIONS) {
-    return DisableMemoryMitigations(arg, arg_size);
-  }
   errno = ENOTSUP;
   return false;
 }
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
index 2d6a1bb..3a6958c 100644
--- a/libc/bionic/malloc_common_dynamic.cpp
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -67,11 +67,11 @@
 
 #include "gwp_asan_wrappers.h"
 #include "heap_tagging.h"
+#include "heap_zero_init.h"
 #include "malloc_common.h"
 #include "malloc_common_dynamic.h"
 #include "malloc_heapprofd.h"
 #include "malloc_limit.h"
-#include "memory_mitigation_state.h"
 
 // =============================================================================
 // Global variables instantations.
@@ -523,10 +523,6 @@
     }
     return FreeMallocLeakInfo(reinterpret_cast<android_mallopt_leak_info_t*>(arg));
   }
-  if (opcode == M_SET_HEAP_TAGGING_LEVEL) {
-    ScopedPthreadMutexLocker locker(&g_heap_tagging_lock);
-    return SetHeapTaggingLevel(arg, arg_size);
-  }
   if (opcode == M_INITIALIZE_GWP_ASAN) {
     if (arg == nullptr || arg_size != sizeof(bool)) {
       errno = EINVAL;
@@ -536,9 +532,6 @@
       return MaybeInitGwpAsan(globals, *reinterpret_cast<bool*>(arg));
     });
   }
-  if (opcode == M_DISABLE_MEMORY_MITIGATIONS) {
-    return DisableMemoryMitigations(arg, arg_size);
-  }
   // Try heapprofd's mallopt, as it handles options not covered here.
   return HeapprofdMallopt(opcode, arg, arg_size);
 }
diff --git a/libc/bionic/memory_mitigation_state.cpp b/libc/bionic/memory_mitigation_state.cpp
deleted file mode 100644
index 4761d88..0000000
--- a/libc/bionic/memory_mitigation_state.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2020 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 "memory_mitigation_state.h"
-
-#include <dirent.h>
-#include <pthread.h>
-#include <semaphore.h>
-#include <stdatomic.h>
-#include <stdlib.h>
-#include <sys/prctl.h>
-#include <sys/types.h>
-
-#include <bionic/malloc.h>
-#include <bionic/mte.h>
-
-#include <private/ScopedPthreadMutexLocker.h>
-#include <private/ScopedRWLock.h>
-
-#include "heap_tagging.h"
-#include "pthread_internal.h"
-
-extern "C" void scudo_malloc_set_zero_contents(int zero_contents);
-
-bool DisableMemoryMitigations(void* arg, size_t arg_size) {
-  if (arg || arg_size) {
-    return false;
-  }
-
-#ifdef USE_SCUDO
-  scudo_malloc_set_zero_contents(0);
-#endif
-
-  ScopedPthreadMutexLocker locker(&g_heap_tagging_lock);
-
-  HeapTaggingLevel current_level = GetHeapTaggingLevel();
-  if (current_level != M_HEAP_TAGGING_LEVEL_NONE && current_level != M_HEAP_TAGGING_LEVEL_TBI) {
-    HeapTaggingLevel level = M_HEAP_TAGGING_LEVEL_NONE;
-    SetHeapTaggingLevel(reinterpret_cast<void*>(&level), sizeof(level));
-  }
-
-  return true;
-}
diff --git a/libc/include/android/legacy_signal_inlines.h b/libc/include/android/legacy_signal_inlines.h
index 90eda7d..e968c45 100644
--- a/libc/include/android/legacy_signal_inlines.h
+++ b/libc/include/android/legacy_signal_inlines.h
@@ -45,12 +45,34 @@
 int __libc_current_sigrtmin() __attribute__((__weak__)) __VERSIONER_NO_GUARD;
 
 static __inline int __ndk_legacy___libc_current_sigrtmax() {
-  if (__libc_current_sigrtmax) return __libc_current_sigrtmax();
+  /*
+   * The NDK doesn't use libclang_rt.builtins yet (https://github.com/android/ndk/issues/1231) so it
+   * can't use __builtin_available, but the platform builds with -Werror=unguarded-availability so
+   * it requires __builtin_available.
+   */
+#if defined(__ANDROID_UNGUARDED_AVAILABILITY__)
+  if (__builtin_available(android 21, *)) {
+#else
+  if (__libc_current_sigrtmax) {
+#endif
+    return __libc_current_sigrtmax();
+  }
   return __SIGRTMAX; /* Should match __libc_current_sigrtmax. */
 }
 
 static __inline int __ndk_legacy___libc_current_sigrtmin() {
-  if (__libc_current_sigrtmin) return __libc_current_sigrtmin();
+  /*
+   * The NDK doesn't use libclang_rt.builtins yet (https://github.com/android/ndk/issues/1231) so it
+   * can't use __builtin_available, but the platform builds with -Werror=unguarded-availability so
+   * it requires __builtin_available.
+   */
+#if defined(__ANDROID_UNGUARDED_AVAILABILITY__)
+  if (__builtin_available(android 21, *)) {
+#else
+  if (__libc_current_sigrtmin) {
+#endif
+    return __libc_current_sigrtmin();
+  }
   return __SIGRTMIN + 7; /* Should match __libc_current_sigrtmin. */
 }
 
diff --git a/libc/include/android/versioning.h b/libc/include/android/versioning.h
index 3ea414a..54ffc91 100644
--- a/libc/include/android/versioning.h
+++ b/libc/include/android/versioning.h
@@ -21,25 +21,85 @@
 #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) __attribute__((annotate("deprecated_in=" #api_level)))
 #define __REMOVED_IN(api_level) __attribute__((annotate("obsoleted_in=" #api_level)))
 #define __INTRODUCED_IN_32(api_level) __attribute__((annotate("introduced_in_32=" #api_level)))
 #define __INTRODUCED_IN_64(api_level) __attribute__((annotate("introduced_in_64=" #api_level)))
 #define __INTRODUCED_IN_ARM(api_level) __attribute__((annotate("introduced_in_arm=" #api_level)))
 #define __INTRODUCED_IN_X86(api_level) __attribute__((annotate("introduced_in_x86=" #api_level)))
+#define __INTRODUCED_IN_X86_NO_GUARD_FOR_NDK(api_level) __attribute__((annotate("introduced_in_x86=" #api_level))) __VERSIONER_NO_GUARD
 
 #define __VERSIONER_NO_GUARD __attribute__((annotate("versioner_no_guard")))
 #define __VERSIONER_FORTIFY_INLINE __attribute__((annotate("versioner_fortify_inline")))
 
 #else
 
-#define __INTRODUCED_IN(api_level)
-#define __DEPRECATED_IN(api_level)
-#define __REMOVED_IN(api_level)
-#define __INTRODUCED_IN_32(api_level)
+// When headers are not processed by the versioner (i.e. compiled into object files),
+// the availability attributed is emitted instead. The clang compiler will make the symbol weak
+// when targeting old api_level and enforce the reference to the symbol to be guarded with
+// __builtin_available(android api_level, *).
+
+// The 'strict' flag is required for NDK clients where the use of "-Wunguarded-availability" cannot
+// be enforced. In the case, the absence of 'strict' makes it possible to call an unavailable API
+// without the __builtin_available check, which will cause a link error at runtime.
+// Android platform build system defines this macro along with -Wunguarded-availability
+//
+// The _NO_GUARD_FOR_NDK variants keep the __VERSIONER_NO_GUARD behavior working for the NDK. This
+// allows libc++ to refer to these functions in inlines without needing to guard them, needed since
+// libc++ doesn't currently guard these calls. There's no risk to the apps though because using
+// those APIs will still cause a link error.
+#if defined(__ANDROID_UNGUARDED_AVAILABILITY__)
+#define __MAYBE_STRICT
+#define __INTRODUCED_IN_NO_GUARD_FOR_NDK(api_level) __INTRODUCED_IN_X86(api_level)
+#define __INTRODUCED_IN_X86_NO_GUARD_FOR_NDK(api_level) __INTRODUCED_IN_X86(api_level)
+#else
+#define __MAYBE_STRICT ,strict
+#define __INTRODUCED_IN_NO_GUARD_FOR_NDK(api_level)
+#define __INTRODUCED_IN_X86_NO_GUARD_FOR_NDK(api_level)
+#endif
+
+#define __INTRODUCED_IN(api_level) \
+    __attribute__((availability(android __MAYBE_STRICT,introduced=api_level)))
+#define __DEPRECATED_IN(api_level) \
+    __attribute__((availability(android __MAYBE_STRICT,deprecated=api_level)))
+#define __REMOVED_IN(api_level) \
+    __attribute__((availability(android __MAYBE_STRICT,obsoleted=api_level)))
+
+// The same availability attribute can't be annotated multiple times. Therefore, the macros are
+// defined for the configuration that it is valid for so that declarations like the below doesn't
+// cause inconsistent availability values which is an error with -Wavailability:
+//
+// void foo() __INTRODUCED_IN_32(30) __INTRODUCED_IN_64(31);
+//
+// This also takes the advantage of the fact that we never use bitness-specific macro with
+// arch-specific macro. In other words,
+//
+// void foo() __INTRODUCED_IN_ARM(30) __INTRODUCED_IN_64(31);
+//
+// hasn't been supported and won't be.
+#if !defined(__LP64__)
+#define __INTRODUCED_IN_32(api_level) \
+    __attribute__((availability(android __MAYBE_STRICT,introduced=api_level)))
 #define __INTRODUCED_IN_64(api_level)
+#else
+#define __INTRODUCED_IN_32(api_level)
+#define __INTRODUCED_IN_64(api_level) \
+    __attribute__((availability(android __MAYBE_STRICT,introduced=api_level)))
+#endif
+
+#if defined(__arm__) || defined(__aarch64__)
+#define __INTRODUCED_IN_ARM(api_level) \
+    __attribute__((availability(android __MAYBE_STRICT,introduced=api_level)))
+#define __INTRODUCED_IN_X86(api_level)
+#elif defined(__i386__) || defined(__x86_64__)
+#define __INTRODUCED_IN_ARM(api_level)
+#define __INTRODUCED_IN_X86(api_level) \
+    __attribute__((availability(android __MAYBE_STRICT,introduced=api_level)))
+#else
 #define __INTRODUCED_IN_ARM(api_level)
 #define __INTRODUCED_IN_X86(api_level)
+#endif
 
 #define __VERSIONER_NO_GUARD
 #define __VERSIONER_FORTIFY_INLINE
diff --git a/libc/include/bits/wctype.h b/libc/include/bits/wctype.h
index a51eca2..0015261 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 __transform) __INTRODUCED_IN(26) __VERSIONER_NO_GUARD;
-wctrans_t wctrans(const char* __name) __INTRODUCED_IN(26) __VERSIONER_NO_GUARD;
+wint_t towctrans(wint_t __wc, wctrans_t __transform) __INTRODUCED_IN_NO_GUARD_FOR_NDK(26);
+wctrans_t wctrans(const char* __name) __INTRODUCED_IN_NO_GUARD_FOR_NDK(26);
 
 __END_DECLS
 
diff --git a/libc/include/locale.h b/libc/include/locale.h
index 4290992..8785b24 100644
--- a/libc/include/locale.h
+++ b/libc/include/locale.h
@@ -96,7 +96,7 @@
   char int_n_sign_posn;
 };
 
-struct lconv* localeconv(void) __INTRODUCED_IN(21) __VERSIONER_NO_GUARD;
+struct lconv* localeconv(void) __INTRODUCED_IN_NO_GUARD_FOR_NDK(21);
 
 locale_t duplocale(locale_t __l) __INTRODUCED_IN(21);
 void freelocale(locale_t __l) __INTRODUCED_IN(21);
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index a237254..bae1f68 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -204,6 +204,61 @@
 #define M_TSDS_COUNT_MAX (-202)
 
 /**
+ * mallopt() option to decide whether heap memory is zero-initialized on
+ * allocation across the whole process. May be called at any time, including
+ * when multiple threads are running. An argument of zero indicates memory
+ * should not be zero-initialized, any other value indicates to initialize heap
+ * memory to zero.
+ *
+ * Note that this memory mitigations is only implemented in scudo and therefore
+ * this will have no effect when using another allocator (such as jemalloc on
+ * Android Go devices).
+ *
+ * Available since API level 31.
+ */
+#define M_BIONIC_ZERO_INIT (-203)
+
+/**
+ * mallopt() option to change the heap tagging state. May be called at any
+ * time, including when multiple threads are running.
+ * The value must be one of the M_HEAP_TAGGING_LEVEL_ constants.
+ *
+ * Available since API level 31.
+ */
+#define M_BIONIC_SET_HEAP_TAGGING_LEVEL (-204)
+
+/**
+ * Constants for use with the M_BIONIC_SET_HEAP_TAGGING_LEVEL mallopt() option.
+ */
+enum HeapTaggingLevel {
+  /**
+   * Disable heap tagging and memory tag checks (if supported).
+   * Heap tagging may not be re-enabled after being disabled.
+   */
+  M_HEAP_TAGGING_LEVEL_NONE = 0,
+#define M_HEAP_TAGGING_LEVEL_NONE M_HEAP_TAGGING_LEVEL_NONE
+  /**
+   * Address-only tagging. Heap pointers have a non-zero tag in the
+   * most significant ("top") byte which is checked in free(). Memory
+   * accesses ignore the tag using arm64's Top Byte Ignore (TBI) feature.
+   */
+  M_HEAP_TAGGING_LEVEL_TBI = 1,
+#define M_HEAP_TAGGING_LEVEL_TBI M_HEAP_TAGGING_LEVEL_TBI
+  /**
+   * Enable heap tagging and asynchronous memory tag checks (if supported).
+   * Disable stack trace collection.
+   */
+  M_HEAP_TAGGING_LEVEL_ASYNC = 2,
+#define M_HEAP_TAGGING_LEVEL_ASYNC M_HEAP_TAGGING_LEVEL_ASYNC
+  /**
+   * Enable heap tagging and synchronous memory tag checks (if supported).
+   * Enable stack trace collection.
+   */
+  M_HEAP_TAGGING_LEVEL_SYNC = 3,
+#define M_HEAP_TAGGING_LEVEL_SYNC M_HEAP_TAGGING_LEVEL_SYNC
+};
+
+/**
  * [mallopt(3)](http://man7.org/linux/man-pages/man3/mallopt.3.html) modifies
  * heap behavior. Values of `__option` are the `M_` constants from this header.
  *
diff --git a/libc/include/math.h b/libc/include/math.h
index 8c084b2..040dc96 100644
--- a/libc/include/math.h
+++ b/libc/include/math.h
@@ -178,9 +178,9 @@
 long double scalbnl(long double __x, int __exponent) __RENAME_LDBL(scalbn, 3, 3);
 
 /* TODO: once the NDK only supports >= 18, use __RENAME_LDBL here too. */
-double scalbln(double __x, long __exponent) __INTRODUCED_IN_X86(18) __VERSIONER_NO_GUARD;
-float scalblnf(float __x, long __exponent) __INTRODUCED_IN_X86(18) __VERSIONER_NO_GUARD;
-long double scalblnl(long double __x, long __exponent) __INTRODUCED_IN_X86(18) __VERSIONER_NO_GUARD;
+double scalbln(double __x, long __exponent) __INTRODUCED_IN_X86_NO_GUARD_FOR_NDK(18);
+float scalblnf(float __x, long __exponent) __INTRODUCED_IN_X86_NO_GUARD_FOR_NDK(18);
+long double scalblnl(long double __x, long __exponent) __INTRODUCED_IN_X86_NO_GUARD_FOR_NDK(18);
 
 double cbrt(double __x);
 float cbrtf(float __x);
@@ -280,11 +280,11 @@
 
 double nextafter(double __x, double __y);
 float nextafterf(float __x, float __y);
-long double nextafterl(long double __x, long double __y) __RENAME_LDBL(nextafter, 3, 21) __VERSIONER_NO_GUARD;
+long double nextafterl(long double __x, long double __y) __RENAME_LDBL_NO_GUARD_FOR_NDK(nextafter, 3, 21);
 
-double nexttoward(double __x, long double __y) __INTRODUCED_IN(18) __VERSIONER_NO_GUARD;
+double nexttoward(double __x, long double __y) __INTRODUCED_IN_NO_GUARD_FOR_NDK(18);
 float nexttowardf(float __x, long double __y);
-long double nexttowardl(long double __x, long double __y) __RENAME_LDBL(nexttoward, 18, 18) __VERSIONER_NO_GUARD;
+long double nexttowardl(long double __x, long double __y) __RENAME_LDBL_NO_GUARD_FOR_NDK(nexttoward, 18, 18);
 
 double fdim(double __x, double __y);
 float fdimf(float __x, float __y);
@@ -300,7 +300,7 @@
 
 double fma(double __x, double __y, double __z);
 float fmaf(float __x, float __y, float __z);
-long double fmal(long double __x, long double __y, long double __z) __RENAME_LDBL(fma, 3, 21) __VERSIONER_NO_GUARD;
+long double fmal(long double __x, long double __y, long double __z) __RENAME_LDBL_NO_GUARD_FOR_NDK(fma, 3, 21);
 
 #define isgreater(x, y) __builtin_isgreater((x), (y))
 #define isgreaterequal(x, y) __builtin_isgreaterequal((x), (y))
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index dc7b694..d7fdb4a 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -160,10 +160,10 @@
 const char* getprogname(void) __INTRODUCED_IN(21);
 void setprogname(const char* __name) __INTRODUCED_IN(21);
 
-int mblen(const char* __s, size_t __n) __INTRODUCED_IN(26) __VERSIONER_NO_GUARD;
+int mblen(const char* __s, size_t __n) __INTRODUCED_IN_NO_GUARD_FOR_NDK(26);
 size_t mbstowcs(wchar_t* __dst, const char* __src, size_t __n);
-int mbtowc(wchar_t* __wc_ptr, const char* __s, size_t __n) __INTRODUCED_IN(21) __VERSIONER_NO_GUARD;
-int wctomb(char* __dst, wchar_t __wc) __INTRODUCED_IN(21) __VERSIONER_NO_GUARD;
+int mbtowc(wchar_t* __wc_ptr, const char* __s, size_t __n) __INTRODUCED_IN_NO_GUARD_FOR_NDK(21);
+int wctomb(char* __dst, wchar_t __wc) __INTRODUCED_IN_NO_GUARD_FOR_NDK(21);
 
 size_t wcstombs(char* __dst, const wchar_t* __src, size_t __n);
 
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index b4556a7..b1bd713 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -202,11 +202,18 @@
  * Note that some functions have their __RENAME_LDBL commented out as a sign that although we could
  * use __RENAME_LDBL it would actually cause the function to be introduced later because the
  * `long double` variant appeared before the `double` variant.
+ *
+ * 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(__LP64__) || defined(__BIONIC_LP32_USE_LONG_DOUBLE)
 #define __RENAME_LDBL(rewrite,rewrite_api_level,regular_api_level) __INTRODUCED_IN(regular_api_level)
+#define __RENAME_LDBL_NO_GUARD_FOR_NDK(rewrite,rewrite_api_level,regular_api_level) __INTRODUCED_IN_NO_GUARD_FOR_NDK(regular_api_level)
 #else
 #define __RENAME_LDBL(rewrite,rewrite_api_level,regular_api_level) __RENAME(rewrite) __INTRODUCED_IN(rewrite_api_level)
+#define __RENAME_LDBL_NO_GUARD_FOR_NDK(rewrite,rewrite_api_level,regular_api_level) __RENAME(rewrite) __INTRODUCED_IN_NO_GUARD_FOR_NDK(rewrite_api_level)
 #endif
 
 /*
diff --git a/libc/include/sys/mman.h b/libc/include/sys/mman.h
index fe4ea7f..3b44dab 100644
--- a/libc/include/sys/mman.h
+++ b/libc/include/sys/mman.h
@@ -32,6 +32,7 @@
 #include <sys/types.h>
 #include <linux/memfd.h>
 #include <linux/mman.h>
+#include <linux/uio.h>
 
 __BEGIN_DECLS
 
@@ -161,6 +162,15 @@
  */
 int madvise(void* __addr, size_t __size, int __advice);
 
+/**
+ * [process_madvise(2)](http://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.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
+int process_madvise(int __pid_fd, const struct iovec* __iov, size_t __count, int __advice, unsigned int __flags);
+
 #if defined(__USE_GNU)
 
 /**
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index a17a33f..f4f35ac 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1552,12 +1552,13 @@
 
 LIBC_S { # introduced=S
   global:
-    ffsl;
-    ffsll;
     __libc_get_static_tls_bounds;
     __libc_register_thread_exit_callback;
     __libc_iterate_dynamic_tls;
     __libc_register_dynamic_tls_listeners;
+    ffsl;
+    ffsll;
+    process_madvise;
 } LIBC_R;
 
 LIBC_PRIVATE {
diff --git a/libc/platform/bionic/malloc.h b/libc/platform/bionic/malloc.h
index 56badf0..b56ca74 100644
--- a/libc/platform/bionic/malloc.h
+++ b/libc/platform/bionic/malloc.h
@@ -28,6 +28,7 @@
 
 #pragma once
 
+#include <malloc.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -85,12 +86,6 @@
   //   arg_size = sizeof(android_mallopt_leak_info_t)
   M_FREE_MALLOC_LEAK_INFO = 7,
 #define M_FREE_MALLOC_LEAK_INFO M_FREE_MALLOC_LEAK_INFO
-  // Change the heap tagging state. May be called at any time including when
-  // multiple threads are running.
-  //   arg = HeapTaggingLevel*
-  //   arg_size = sizeof(HeapTaggingLevel)
-  M_SET_HEAP_TAGGING_LEVEL = 8,
-#define M_SET_HEAP_TAGGING_LEVEL M_SET_HEAP_TAGGING_LEVEL
   // Query whether the current process is considered to be profileable by the
   // Android platform. Result is assigned to the arg pointer's destination.
   //   arg = bool*
@@ -105,28 +100,6 @@
   //   arg_size = sizeof(bool)
   M_INITIALIZE_GWP_ASAN = 10,
 #define M_INITIALIZE_GWP_ASAN M_INITIALIZE_GWP_ASAN
-  // Disable heap initialization across the whole process. If the hardware supports memory
-  // tagging, it also disables memory tagging. May be called at any time including
-  // when multiple threads are running. arg and arg_size are unused and must be set to 0.
-  // Note that the memory mitigations are only implemented in scudo and therefore this API call will
-  // have no effect when using another allocator.
-  M_DISABLE_MEMORY_MITIGATIONS = 11,
-#define M_DISABLE_MEMORY_MITIGATIONS M_DISABLE_MEMORY_MITIGATIONS
-};
-
-enum HeapTaggingLevel {
-  // Disable heap tagging and memory tag checks if supported. Heap tagging may not be re-enabled
-  // after being disabled.
-  M_HEAP_TAGGING_LEVEL_NONE = 0,
-  // Address-only tagging. Heap pointers have a non-zero tag in the most significant byte which is
-  // checked in free(). Memory accesses ignore the tag.
-  M_HEAP_TAGGING_LEVEL_TBI = 1,
-  // Enable heap tagging and asynchronous memory tag checks if supported. Disable stack trace
-  // collection.
-  M_HEAP_TAGGING_LEVEL_ASYNC = 2,
-  // Enable heap tagging and synchronous memory tag checks if supported. Enable stack trace
-  // collection.
-  M_HEAP_TAGGING_LEVEL_SYNC = 3,
 };
 
 // Manipulates bionic-specific handling of memory allocation APIs such as
diff --git a/libc/platform/bionic/mte.h b/libc/platform/bionic/mte.h
index b11b1a6..73cd821 100644
--- a/libc/platform/bionic/mte.h
+++ b/libc/platform/bionic/mte.h
@@ -29,6 +29,13 @@
 #pragma once
 
 #include <sys/auxv.h>
+#include <sys/prctl.h>
+
+// Note: Most PR_MTE_* constants come from the upstream kernel. This tag mask
+// allows for the hardware to provision any nonzero tag. Zero tags are reserved
+// for scudo to use for the chunk headers in order to prevent linear heap
+// overflow/underflow.
+#define PR_MTE_TAG_SET_NONZERO (0xfffeUL << PR_MTE_TAG_SHIFT)
 
 inline bool mte_supported() {
 #if defined(__aarch64__)
diff --git a/libc/private/bionic_asm_arm64.h b/libc/private/bionic_asm_arm64.h
index e73f25d..ee51a8e 100644
--- a/libc/private/bionic_asm_arm64.h
+++ b/libc/private/bionic_asm_arm64.h
@@ -45,7 +45,7 @@
 #if defined(__ARM_FEATURE_BTI_DEFAULT)
 #define __bionic_asm_aarch64_feature_bti    (1 << 0)
 #undef __bionic_asm_custom_entry
-#define __bionic_asm_custom_entry(f)        hint #34  // BTI C
+#define __bionic_asm_custom_entry(f)        bti c
 #else
 #define __bionic_asm_aarch64_feature_bti    0
 #endif
diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp
index c7b1ba4..c429ff2 100644
--- a/libc/stdio/stdio.cpp
+++ b/libc/stdio/stdio.cpp
@@ -50,11 +50,12 @@
 
 #include <async_safe/log.h>
 
-#include "local.h"
 #include "glue.h"
+#include "local.h"
+#include "private/ErrnoRestorer.h"
+#include "private/FdPath.h"
 #include "private/__bionic_get_shell_path.h"
 #include "private/bionic_fortify.h"
-#include "private/ErrnoRestorer.h"
 #include "private/thread_private.h"
 
 #include "private/bsd_sys_param.h" // For ALIGN/ALIGNBYTES.
@@ -225,25 +226,21 @@
   _fwalk(__sflush);
 }
 
-static FILE* __fopen(int fd, int flags) {
+static FILE* __FILE_init(FILE* fp, int fd, int flags) {
+  if (fp == nullptr) return nullptr;
+
 #if !defined(__LP64__)
-  if (fd > SHRT_MAX) {
-    errno = EMFILE;
-    return nullptr;
-  }
+  if (fd > SHRT_MAX) __fortify_fatal("stdio: fd %d > SHRT_MAX", fd);
 #endif
 
-  FILE* fp = __sfp();
-  if (fp != nullptr) {
-    fp->_file = fd;
-    android_fdsan_exchange_owner_tag(fd, 0, __get_file_tag(fp));
-    fp->_flags = flags;
-    fp->_cookie = fp;
-    fp->_read = __sread;
-    fp->_write = __swrite;
-    fp->_close = __sclose;
-    _EXT(fp)->_seek64 = __sseek64;
-  }
+  fp->_file = fd;
+  android_fdsan_exchange_owner_tag(fd, 0, __get_file_tag(fp));
+  fp->_flags = flags;
+  fp->_cookie = fp;
+  fp->_read = __sread;
+  fp->_write = __swrite;
+  fp->_close = __sclose;
+  _EXT(fp)->_seek64 = __sseek64;
   return fp;
 }
 
@@ -257,14 +254,15 @@
     return nullptr;
   }
 
-  FILE* fp = __fopen(fd, flags);
+  FILE* fp = __FILE_init(__sfp(), fd, flags);
   if (fp == nullptr) {
     ErrnoRestorer errno_restorer;
     close(fd);
     return nullptr;
   }
 
-  // For append mode, even though we use O_APPEND, we need to seek to the end now.
+  // For append mode, O_APPEND sets the write position for free, but we need to
+  // set the read position manually.
   if ((mode_flags & O_APPEND) != 0) __sseek64(fp, 0, SEEK_END);
   return fp;
 }
@@ -295,15 +293,26 @@
     fcntl(fd, F_SETFD, tmp | FD_CLOEXEC);
   }
 
-  return __fopen(fd, flags);
+  return __FILE_init(__sfp(), fd, flags);
 }
 
-// Re-direct an existing, open (probably) file to some other file.
-// ANSI is written such that the original file gets closed if at
-// all possible, no matter what.
-// TODO: rewrite this mess completely.
 FILE* freopen(const char* file, const char* mode, FILE* fp) {
   CHECK_FP(fp);
+
+  // POSIX says: "If pathname is a null pointer, the freopen() function shall
+  // attempt to change the mode of the stream to that specified by mode, as if
+  // the name of the file currently associated with the stream had been used. In
+  // this case, the file descriptor associated with the stream need not be
+  // closed if the call to freopen() succeeds. It is implementation-defined
+  // which changes of mode are permitted (if any), and under what
+  // circumstances."
+  //
+  // Linux is quite restrictive about what changes you can make with F_SETFL,
+  // and in particular won't let you touch the access bits. It's easiest and
+  // most effective to just rely on /proc/self/fd/...
+  FdPath fd_path(fp->_file);
+  if (file == nullptr) file = fd_path.c_str();
+
   int mode_flags;
   int flags = __sflags(mode, &mode_flags);
   if (flags == 0) {
@@ -313,6 +322,8 @@
 
   ScopedFileLock sfl(fp);
 
+  // TODO: rewrite this mess completely.
+
   // There are actually programs that depend on being able to "freopen"
   // descriptors that weren't originally open.  Keep this from breaking.
   // Remember whether the stream was open to begin with, and which file
@@ -382,24 +393,12 @@
     }
   }
 
-  // _file is only a short.
-  if (fd > SHRT_MAX) {
-      fp->_flags = 0; // Release.
-      errno = EMFILE;
-      return nullptr;
-  }
+  __FILE_init(fp, fd, flags);
 
-  fp->_flags = flags;
-  fp->_file = fd;
-  android_fdsan_exchange_owner_tag(fd, 0, __get_file_tag(fp));
-  fp->_cookie = fp;
-  fp->_read = __sread;
-  fp->_write = __swrite;
-  fp->_close = __sclose;
-  _EXT(fp)->_seek64 = __sseek64;
-
-  // For append mode, even though we use O_APPEND, we need to seek to the end now.
+  // For append mode, O_APPEND sets the write position for free, but we need to
+  // set the read position manually.
   if ((mode_flags & O_APPEND) != 0) __sseek64(fp, 0, SEEK_END);
+
   return fp;
 }
 __strong_alias(freopen64, freopen);
diff --git a/libc/tools/Android.bp b/libc/tools/Android.bp
index 13179a0..bf515ca 100644
--- a/libc/tools/Android.bp
+++ b/libc/tools/Android.bp
@@ -2,3 +2,33 @@
     name: "bionic-gensyscalls",
     srcs: ["gensyscalls.py"]
 }
+
+// Generate the C++ policy sources for app and system seccomp-bpf filters.
+python_binary_host {
+    name: "genseccomp",
+    main: "genseccomp.py",
+
+    srcs: [
+        "genseccomp.py",
+        "gensyscalls.py",
+    ],
+
+    data: [
+        ":all_kernel_uapi_headers",
+    ],
+}
+
+python_binary_host {
+    name: "genfunctosyscallnrs",
+    main: "genfunctosyscallnrs.py",
+
+    srcs: [
+        "genseccomp.py",
+        "genfunctosyscallnrs.py",
+        "gensyscalls.py",
+    ],
+
+    data: [
+        ":all_kernel_uapi_headers",
+    ],
+}
diff --git a/libc/tools/generate-NOTICE.py b/libc/tools/generate_notice.py
similarity index 60%
rename from libc/tools/generate-NOTICE.py
rename to libc/tools/generate_notice.py
index b6deb9c..e0e6b32 100755
--- a/libc/tools/generate-NOTICE.py
+++ b/libc/tools/generate_notice.py
@@ -1,28 +1,29 @@
 #!/usr/bin/env python
-# Run with directory arguments from any directory, with no special setup required.
+# Run with directory arguments from any directory, with no special setup
+# required.
 
-import ftplib
-import hashlib
 import os
+from pathlib import Path
 import re
-import shutil
-import string
-import subprocess
 import sys
-import tarfile
-import tempfile
+from typing import Sequence
 
 VERBOSE = False
 
+copyrights = set()
+
+
 def warn(s):
     sys.stderr.write("warning: %s\n" % s)
 
+
 def warn_verbose(s):
     if VERBOSE:
         warn(s)
 
-def is_interesting(path):
-    path = path.lower()
+
+def is_interesting(path_str: str) -> bool:
+    path = Path(path_str.lower())
     uninteresting_extensions = [
         ".bp",
         ".map",
@@ -33,12 +34,13 @@
         ".swp",
         ".txt",
     ]
-    if os.path.splitext(path)[1] in uninteresting_extensions:
+    if path.suffix in uninteresting_extensions:
         return False
-    if path.endswith("/notice") or path.endswith("/readme") or path.endswith("/pylintrc"):
+    if path.name in {"notice", "readme", "pylintrc"}:
         return False
     return True
 
+
 def is_auto_generated(content):
     if "Generated by gensyscalls.py" in content or "generated by genserv.py" in content:
         return True
@@ -46,14 +48,40 @@
         return True
     return False
 
-copyrights = set()
 
-def extract_copyright_at(lines, i):
-    hash = lines[i].startswith("#")
+def is_copyright_end(line: str, first_line_was_hash: bool) -> bool:
+    endings = [
+        " $FreeBSD: ",
+        "$Citrus$",
+        "$FreeBSD$",
+        "*/",
+        "From: @(#)",
+        # OpenBSD likes to say where stuff originally came from:
+        "Original version ID:",
+        "\t$Citrus: ",
+        "\t$NetBSD: ",
+        "\t$OpenBSD: ",
+        "\t@(#)",
+        "\tcitrus Id: ",
+        "\tfrom: @(#)",
+        "from OpenBSD:",
+    ]
+    if first_line_was_hash and not line:
+        return True
+
+    for ending in endings:
+        if ending in line:
+            return True
+
+    return False
+
+
+def extract_copyright_at(lines: Sequence[str], i: int) -> int:
+    first_line_was_hash = lines[i].startswith("#")
 
     # Do we need to back up to find the start of the copyright header?
     start = i
-    if not hash:
+    if not first_line_was_hash:
         while start > 0:
             if "/*" in lines[start - 1]:
                 break
@@ -62,20 +90,7 @@
     # Read comment lines until we hit something that terminates a
     # copyright header.
     while i < len(lines):
-        if "*/" in lines[i]:
-            break
-        if hash and len(lines[i]) == 0:
-            break
-        if "\t@(#)" in lines[i] or "\tfrom: @(#)" in lines[i] or "From: @(#)" in lines[i] or "from OpenBSD:" in lines[i]:
-            break
-        if "\tcitrus Id: " in lines[i]:
-            break
-        if "\t$Citrus: " in lines[i] or "\t$OpenBSD: " in lines[i] or " $FreeBSD: " in lines[i] or "\t$NetBSD: " in lines[i]:
-            break
-        if "$FreeBSD$" in lines[i] or "$Citrus$" in lines[i]:
-            break
-        # OpenBSD likes to say where stuff originally came from:
-        if "Original version ID:" in lines[i]:
+        if is_copyright_end(lines[i], first_line_was_hash):
             break
         i += 1
 
@@ -83,7 +98,10 @@
 
     # Trim trailing cruft.
     while end > 0:
-        if lines[end - 1] != " *" and lines[end - 1] != " * ====================================================":
+        line = lines[end - 1]
+        if line not in {
+                " *", " * ===================================================="
+        }:
             break
         end -= 1
 
@@ -92,7 +110,7 @@
     for line in lines[start:end]:
         line = line.replace("\t", "    ")
         line = line.replace("/* ", "")
-        line = re.sub("^ \* ", "", line)
+        line = re.sub(r"^ \* ", "", line)
         line = line.replace("** ", "")
         line = line.replace("# ", "")
         if "SPDX-License-Identifier:" in line:
@@ -102,7 +120,7 @@
         line = line.replace("--Copyright--", "")
         line = line.rstrip()
         # These come last and take care of "blank" comment lines.
-        if line == "#" or line == " *" or line == "**" or line == "-":
+        if line in {"#", " *", "**", "-"}:
             line = ""
         clean_lines.append(line)
 
@@ -112,19 +130,18 @@
     while clean_lines[len(clean_lines) - 1] == "":
         clean_lines = clean_lines[0:(len(clean_lines) - 1)]
 
-    copyright = "\n".join(clean_lines)
-    copyrights.add(copyright)
+    copyrights.add("\n".join(clean_lines))
 
     return i
 
 
-def do_file(path):
-    with open(path, "r") as the_file:
-        try:
-            content = open(path, "r").read().decode("utf-8")
-        except UnicodeDecodeError:
-            warn("bad UTF-8 in %s" % path)
-            content = open(path, "r").read().decode("iso-8859-1")
+def do_file(path: str) -> None:
+    raw = Path(path).read_bytes()
+    try:
+        content = raw.decode("utf-8")
+    except UnicodeDecodeError:
+        warn("bad UTF-8 in %s" % path)
+        content = raw.decode("iso-8859-1")
 
     lines = content.split("\n")
 
@@ -140,10 +157,12 @@
         if "public domain" in content.lower():
             warn_verbose("ignoring public domain file %s" % path)
             return
-        warn('no copyright notice found in "%s" (%d lines)' % (path, len(lines)))
+        warn('no copyright notice found in "%s" (%d lines)' %
+             (path, len(lines)))
         return
 
-    # Manually iterate because extract_copyright_at tells us how many lines to skip.
+    # Manually iterate because extract_copyright_at tells us how many lines to
+    # skip.
     i = 0
     while i < len(lines):
         if "Copyright" in lines[i] and not "@(#) Copyright" in lines[i]:
@@ -152,7 +171,7 @@
             i += 1
 
 
-def do_dir(path):
+def do_dir(arg):
     for directory, sub_directories, filenames in os.walk(arg):
         if ".git" in sub_directories:
             sub_directories.remove(".git")
@@ -164,20 +183,23 @@
                 do_file(path)
 
 
-args = sys.argv[1:]
-if len(args) == 0:
-    args = [ "." ]
+def main() -> None:
+    args = sys.argv[1:]
+    if len(args) == 0:
+        args = ["."]
 
-for arg in args:
-    if os.path.isdir(arg):
-        do_dir(arg)
-    else:
-        do_file(arg)
+    for arg in args:
+        if os.path.isdir(arg):
+            do_dir(arg)
+        else:
+            do_file(arg)
 
-for copyright in sorted(copyrights):
-    print copyright.encode("utf-8")
-    print
-    print "-------------------------------------------------------------------"
-    print
+    for notice in sorted(copyrights):
+        print(notice)
+        print()
+        print("-" * 67)
+        print()
 
-sys.exit(0)
+
+if __name__ == "__main__":
+    main()
diff --git a/libc/tools/genfunctosyscallnrs.py b/libc/tools/genfunctosyscallnrs.py
index ecfc8ab..26642f9 100755
--- a/libc/tools/genfunctosyscallnrs.py
+++ b/libc/tools/genfunctosyscallnrs.py
@@ -1,60 +1,71 @@
 #!/usr/bin/env python
 
 import argparse
-import collections
 import logging
 import os
 import re
-import subprocess
-import textwrap
 
 from gensyscalls import SupportedArchitectures, SysCallsTxtParser
 from genseccomp import parse_syscall_NRs
 
-def load_syscall_names_from_file(file_path, architecture):
-  parser = SysCallsTxtParser()
-  parser.parse_open_file(open(file_path))
-  arch_map = {}
-  for syscall in parser.syscalls:
-    if syscall.get(architecture):
-      arch_map[syscall["func"]] = syscall["name"];
 
-  return arch_map
+def load_syscall_names_from_file(file_path, architecture):
+    parser = SysCallsTxtParser()
+    parser.parse_open_file(open(file_path))
+    arch_map = {}
+    for syscall in parser.syscalls:
+        if syscall.get(architecture):
+            arch_map[syscall["func"]] = syscall["name"]
+
+    return arch_map
+
 
 def gen_syscall_nrs(out_file, base_syscall_file, syscall_NRs):
-  for arch in SupportedArchitectures:
-    base_names = load_syscall_names_from_file(base_syscall_file, arch)
+    for arch in SupportedArchitectures:
+        base_names = load_syscall_names_from_file(base_syscall_file, arch)
 
-    for func,syscall in base_names.iteritems():
-      out_file.write("#define __" + arch + "_" + func + " " + str(syscall_NRs[arch][syscall]) + ";\n")
+        for func, syscall in base_names.items():
+            out_file.write("#define __" + arch + "_" + func + " " +
+                           str(syscall_NRs[arch][syscall]) + ";\n")
+
 
 def main():
-  parser = argparse.ArgumentParser(
-      description="Generates a mapping of bionic functions to system call numbers per architecture.")
-  parser.add_argument("--verbose", "-v", help="Enables verbose logging.")
-  parser.add_argument("--out-dir",
-                      help="The output directory for the output files")
-  parser.add_argument("base_file", metavar="base-file", type=str,
-                      help="The path of the base syscall list (SYSCALLS.TXT).")
-  parser.add_argument("files", metavar="FILE", type=str, nargs="+",
-                      help=("A syscall name-number mapping file for an architecture.\n"))
-  args = parser.parse_args()
+    parser = argparse.ArgumentParser(
+        description=
+        "Generates a mapping of bionic functions to system call numbers per architecture."
+    )
+    parser.add_argument("--verbose", "-v", help="Enables verbose logging.")
+    parser.add_argument("--out-dir",
+                        help="The output directory for the output files")
+    parser.add_argument(
+        "base_file",
+        metavar="base-file",
+        type=str,
+        help="The path of the base syscall list (SYSCALLS.TXT).")
+    parser.add_argument(
+        "files",
+        metavar="FILE",
+        type=str,
+        nargs="+",
+        help=("A syscall name-number mapping file for an architecture.\n"))
+    args = parser.parse_args()
 
-  if args.verbose:
-    logging.basicConfig(level=logging.DEBUG)
-  else:
-    logging.basicConfig(level=logging.INFO)
+    if args.verbose:
+        logging.basicConfig(level=logging.DEBUG)
+    else:
+        logging.basicConfig(level=logging.INFO)
 
-  syscall_files = []
-  syscall_NRs = {}
-  for filename in args.files:
-    m = re.search(r"libseccomp_gen_syscall_nrs_([^/]+)", filename)
-    syscall_NRs[m.group(1)] = parse_syscall_NRs(filename)
+    syscall_NRs = {}
+    for filename in args.files:
+        m = re.search(r"libseccomp_gen_syscall_nrs_([^/]+)", filename)
+        syscall_NRs[m.group(1)] = parse_syscall_NRs(filename)
 
-  output_path = os.path.join(args.out_dir, "func_to_syscall_nrs.h")
-  with open(output_path, "w") as output_file:
-    gen_syscall_nrs(out_file=output_file,
-             syscall_NRs=syscall_NRs, base_syscall_file=args.base_file)
+    output_path = os.path.join(args.out_dir, "func_to_syscall_nrs.h")
+    with open(output_path, "w") as output_file:
+        gen_syscall_nrs(out_file=output_file,
+                        syscall_NRs=syscall_NRs,
+                        base_syscall_file=args.base_file)
+
 
 if __name__ == "__main__":
-  main()
+    main()
diff --git a/libc/tools/genseccomp.py b/libc/tools/genseccomp.py
index 89eeb44..a78f6c1 100755
--- a/libc/tools/genseccomp.py
+++ b/libc/tools/genseccomp.py
@@ -1,11 +1,10 @@
 #!/usr/bin/env python
 
 import argparse
-import collections
 import logging
+import operator
 import os
 import re
-import subprocess
 import textwrap
 
 from gensyscalls import SupportedArchitectures, SysCallsTxtParser
@@ -16,7 +15,7 @@
 BPF_ALLOW = "BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW)"
 
 
-class SyscallRange(object):
+class SyscallRange:
   def __init__(self, name, value):
     self.names = [name]
     self.begin = value
@@ -35,23 +34,23 @@
 def load_syscall_names_from_file(file_path, architecture):
   parser = SysCallsTxtParser()
   parser.parse_open_file(open(file_path))
-  return set([x["name"] for x in parser.syscalls if x.get(architecture)])
+  return {x["name"] for x in parser.syscalls if x.get(architecture)}
 
 
 def load_syscall_priorities_from_file(file_path):
   format_re = re.compile(r'^\s*([A-Za-z_][A-Za-z0-9_]+)\s*$')
   priorities = []
-  with open(file_path) as f:
-    for line in f:
-      m = format_re.match(line)
-      if not m:
+  with open(file_path) as priority_file:
+    for line in priority_file:
+      match = format_re.match(line)
+      if match is None:
         continue
       try:
-        name = m.group(1)
+        name = match.group(1)
         priorities.append(name)
-      except:
-        logging.debug('Failed to parse %s from %s', (line, file_path))
-        pass
+      except IndexError:
+        # TODO: This should be impossible becauase it wouldn't have matched?
+        logging.exception('Failed to parse %s from %s', line, file_path)
 
   return priorities
 
@@ -93,7 +92,7 @@
   with open(names_path) as f:
     for line in f:
       m = constant_re.match(line)
-      if not m:
+      if m is None:
         continue
       try:
         name = m.group(1)
@@ -102,12 +101,21 @@
                                   m.group(2)))
 
         constants[name] = value
-      except:
+      except:  # pylint: disable=bare-except
+        # TODO: This seems wrong.
+        # Key error doesn't seem like the error the original author was trying
+        # to catch. It looks like the intent was to catch IndexError from
+        # match.group() for non-matching lines, but that's impossible because
+        # the match object is checked and continued if not matched. What
+        # actually happens is that KeyError is thrown by constants[x.group(0)]
+        # on at least the first run because the dict is empty.
+        #
+        # It's also matching syntax errors because not all C integer literals
+        # are valid Python integer literals, e.g. 10L.
         logging.debug('Failed to parse %s', line)
-        pass
 
   syscalls = {}
-  for name, value in constants.iteritems():
+  for name, value in constants.items():
     if not name.startswith("__NR_") and not name.startswith("__ARM_NR"):
       continue
     if name.startswith("__NR_"):
@@ -120,7 +128,7 @@
 
 def convert_NRs_to_ranges(syscalls):
   # Sort the values so we convert to ranges and binary chop
-  syscalls = sorted(syscalls, lambda x, y: cmp(x[1], y[1]))
+  syscalls = sorted(syscalls, key=operator.itemgetter(1))
 
   # Turn into a list of ranges. Keep the names for the comments
   ranges = []
@@ -148,12 +156,12 @@
     # We will replace {fail} and {allow} with appropriate range jumps later
     return [BPF_JGE.format(ranges[0].end, "{fail}", "{allow}") +
             ", //" + "|".join(ranges[0].names)]
-  else:
-    half = (len(ranges) + 1) / 2
-    first = convert_to_intermediate_bpf(ranges[:half])
-    second = convert_to_intermediate_bpf(ranges[half:])
-    jump = [BPF_JGE.format(ranges[half].begin, len(first), 0) + ","]
-    return jump + first + second
+
+  half = (len(ranges) + 1) // 2
+  first = convert_to_intermediate_bpf(ranges[:half])
+  second = convert_to_intermediate_bpf(ranges[half:])
+  jump = [BPF_JGE.format(ranges[half].begin, len(first), 0) + ","]
+  return jump + first + second
 
 
 # Converts the prioritized syscalls to a bpf list that  is prepended to the
@@ -162,7 +170,7 @@
 # immediately
 def convert_priority_to_intermediate_bpf(priority_syscalls):
   result = []
-  for i, syscall in enumerate(priority_syscalls):
+  for syscall in priority_syscalls:
     result.append(BPF_JEQ.format(syscall[1], "{allow}", 0) +
                   ", //" + syscall[0])
   return result
@@ -227,7 +235,8 @@
   return convert_bpf_to_output(bpf, architecture, name_modifier)
 
 
-def gen_policy(name_modifier, out_dir, base_syscall_file, syscall_files, syscall_NRs, priority_file):
+def gen_policy(name_modifier, out_dir, base_syscall_file, syscall_files,
+               syscall_NRs, priority_file):
   for arch in SupportedArchitectures:
     base_names = load_syscall_names_from_file(base_syscall_file, arch)
     allowlist_names = set()
@@ -251,7 +260,6 @@
     output = construct_bpf(allowed_syscalls, arch, name_modifier, priorities)
 
     # And output policy
-    existing = ""
     filename_modifier = "_" + name_modifier if name_modifier else ""
     output_path = os.path.join(out_dir,
                                "{}{}_policy.cpp".format(arch, filename_modifier))
@@ -274,8 +282,8 @@
                       help=("The path of the input files. In order to "
                             "simplify the build rules, it can take any of the "
                             "following files: \n"
-                            "* /blocklist.*\.txt$/ syscall blocklist.\n"
-                            "* /allowlist.*\.txt$/ syscall allowlist.\n"
+                            "* /blocklist.*\\.txt$/ syscall blocklist.\n"
+                            "* /allowlist.*\\.txt$/ syscall allowlist.\n"
                             "* /priority.txt$/ priorities for bpf rules.\n"
                             "* otherwise, syscall name-number mapping.\n"))
   args = parser.parse_args()
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index 0e0e25f..d8d4302 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -5,7 +5,6 @@
 # makefiles used to build all the stubs.
 
 import atexit
-import commands
 import filecmp
 import glob
 import re
@@ -315,7 +314,7 @@
         self.lineno   = 0
 
     def E(self, msg):
-        print "%d: %s" % (self.lineno, msg)
+        print("%d: %s" % (self.lineno, msg))
 
     def parse_line(self, line):
         """ parse a syscall spec line.
@@ -340,7 +339,7 @@
             return
 
         syscall_func = return_type[-1]
-        return_type  = string.join(return_type[:-1],' ')
+        return_type  = ' '.join(return_type[:-1])
         socketcall_id = -1
 
         pos_colon = syscall_func.find(':')
@@ -372,13 +371,13 @@
             alias_delim = syscall_name.find('|')
             if alias_delim > 0:
                 syscall_name = syscall_name[:alias_delim]
-            syscall_aliases = string.split(alias_list, ',')
+            syscall_aliases = alias_list.split(',')
         else:
             syscall_aliases = []
 
         if pos_rparen > pos_lparen+1:
             syscall_params = line[pos_lparen+1:pos_rparen].split(',')
-            params         = string.join(syscall_params,',')
+            params         = ','.join(syscall_params)
         else:
             syscall_params = []
             params         = "void"
@@ -398,7 +397,7 @@
             for arch in SupportedArchitectures:
                 t[arch] = True
         else:
-            for arch in string.split(arch_list, ','):
+            for arch in arch_list.split(','):
                 if arch == "lp32":
                     for arch in SupportedArchitectures:
                         if "64" not in arch:
@@ -464,7 +463,7 @@
 
 if __name__ == "__main__":
     if len(sys.argv) < 2:
-      print "Usage: gensyscalls.py ARCH SOURCE_FILE"
+      print("Usage: gensyscalls.py ARCH SOURCE_FILE")
       sys.exit(1)
 
     arch = sys.argv[1]
diff --git a/libc/tools/mypy.ini b/libc/tools/mypy.ini
new file mode 100644
index 0000000..0269354
--- /dev/null
+++ b/libc/tools/mypy.ini
@@ -0,0 +1,3 @@
+[mypy]
+# TODO: Enable.
+# disallow_untyped_defs = True
diff --git a/libc/tools/pylintrc b/libc/tools/pylintrc
new file mode 100644
index 0000000..df319e3
--- /dev/null
+++ b/libc/tools/pylintrc
@@ -0,0 +1,8 @@
+[MESSAGES CONTROL]
+disable=
+    eval-used,
+    design,
+    fixme,
+    invalid-name,
+    logging-fstring-interpolation,
+    missing-docstring
diff --git a/libc/tools/test_genseccomp.py b/libc/tools/test_genseccomp.py
index 812218e..8bd3517 100755
--- a/libc/tools/test_genseccomp.py
+++ b/libc/tools/test_genseccomp.py
@@ -1,176 +1,65 @@
 #!/usr/bin/env python
 # Unit tests for genseccomp.py
 
-import cStringIO
 import textwrap
 import unittest
 
 import genseccomp
 
 class TestGenseccomp(unittest.TestCase):
-  def setUp(self):
-    genseccomp.set_dir()
-
-  def get_config(self, arch):
-    for i in genseccomp.POLICY_CONFIGS:
-      if i[0] == arch:
-        return i
-    self.fail("No such architecture")
-
-  def get_headers(self, arch):
-    return self.get_config(arch)[1]
-
-  def get_switches(self, arch):
-    return self.get_config(arch)[2]
-
-  def test_get_names(self):
-    bionic = cStringIO.StringIO(textwrap.dedent("""\
-int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) arm,x86
-int         fchown:fchown(int, uid_t, gid_t)    arm64,x86_64
-    """))
-
-    allowlist = cStringIO.StringIO(textwrap.dedent("""\
-ssize_t     read(int, void*, size_t)        all
-    """))
-
-    empty = cStringIO.StringIO(textwrap.dedent("""\
-    """))
-
-    names = genseccomp.get_names([bionic, allowlist, empty], "arm")
-    bionic.seek(0)
-    allowlist.seek(0)
-    empty.seek(0)
-    names64 = genseccomp.get_names([bionic, allowlist, empty], "arm64")
-    bionic.seek(0)
-    allowlist.seek(0)
-    empty.seek(0)
-
-    self.assertIn("fchown", names64)
-    self.assertNotIn("fchown", names)
-    self.assertIn("_llseek", names)
-    self.assertNotIn("_llseek", names64)
-    self.assertIn("read", names)
-    self.assertIn("read", names64)
-
-    # Blocklist item must be in bionic
-    blocklist = cStringIO.StringIO(textwrap.dedent("""\
-int         fchown2:fchown2(int, uid_t, gid_t)    arm64,x86_64
-    """))
-    with self.assertRaises(RuntimeError):
-      genseccomp.get_names([bionic, allowlist, blocklist], "arm")
-    bionic.seek(0)
-    allowlist.seek(0)
-    blocklist.seek(0)
-
-    # Test blocklist item is removed
-    blocklist = cStringIO.StringIO(textwrap.dedent("""\
-int         fchown:fchown(int, uid_t, gid_t)    arm64,x86_64
-    """))
-    names = genseccomp.get_names([bionic, allowlist, blocklist], "arm64")
-    bionic.seek(0)
-    allowlist.seek(0)
-    blocklist.seek(0)
-    self.assertIn("read", names)
-    self.assertNotIn("fchown", names)
-
-    # Blocklist item must not be in allowlist
-    allowlist = cStringIO.StringIO(textwrap.dedent("""\
-int         fchown:fchown(int, uid_t, gid_t)    arm64,x86_64
-    """))
-    with self.assertRaises(RuntimeError):
-      genseccomp.get_names([empty, allowlist, blocklist], "arm")
-    empty.seek(0)
-    allowlist.seek(0)
-    blocklist.seek(0)
-
-    # No dups in bionic and allowlist
-    allowlist = cStringIO.StringIO(textwrap.dedent("""\
-int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) arm,x86
-    """))
-    with self.assertRaises(RuntimeError):
-      genseccomp.get_names([bionic, allowlist, empty], "arm")
-    bionic.seek(0)
-    allowlist.seek(0)
-    empty.seek(0)
-
-  def test_convert_names_to_NRs(self):
-    self.assertEquals(genseccomp.convert_names_to_NRs(["open"],
-                                                      self.get_headers("arm"),
-                                                      self.get_switches("arm")),
-                      [("open", 5)])
-
-    self.assertEquals(genseccomp.convert_names_to_NRs(["__ARM_NR_set_tls"],
-                                                      self.get_headers("arm"),
-                                                      self.get_switches("arm")),
-                      [('__ARM_NR_set_tls', 983045)])
-
-    self.assertEquals(genseccomp.convert_names_to_NRs(["openat"],
-                                                      self.get_headers("arm64"),
-                                                      self.get_switches("arm64")),
-                      [("openat", 56)])
-
-    self.assertEquals(genseccomp.convert_names_to_NRs(["openat"],
-                                                      self.get_headers("x86"),
-                                                      self.get_switches("x86")),
-                      [("openat", 295)])
-
-    self.assertEquals(genseccomp.convert_names_to_NRs(["openat"],
-                                                      self.get_headers("x86_64"),
-                                                      self.get_switches("x86_64")),
-                      [("openat", 257)])
-
-
   def test_convert_NRs_to_ranges(self):
     ranges = genseccomp.convert_NRs_to_ranges([("b", 2), ("a", 1)])
-    self.assertEquals(len(ranges), 1)
-    self.assertEquals(ranges[0].begin, 1)
-    self.assertEquals(ranges[0].end, 3)
-    self.assertItemsEqual(ranges[0].names, ["a", "b"])
+    self.assertEqual(len(ranges), 1)
+    self.assertEqual(ranges[0].begin, 1)
+    self.assertEqual(ranges[0].end, 3)
+    self.assertEqual(set(ranges[0].names), {"a", "b"})
 
     ranges = genseccomp.convert_NRs_to_ranges([("b", 3), ("a", 1)])
-    self.assertEquals(len(ranges), 2)
-    self.assertEquals(ranges[0].begin, 1)
-    self.assertEquals(ranges[0].end, 2)
-    self.assertItemsEqual(ranges[0].names, ["a"])
-    self.assertEquals(ranges[1].begin, 3)
-    self.assertEquals(ranges[1].end, 4)
-    self.assertItemsEqual(ranges[1].names, ["b"])
+    self.assertEqual(len(ranges), 2)
+    self.assertEqual(ranges[0].begin, 1)
+    self.assertEqual(ranges[0].end, 2)
+    self.assertEqual(set(ranges[0].names), {"a"})
+    self.assertEqual(ranges[1].begin, 3)
+    self.assertEqual(ranges[1].end, 4)
+    self.assertEqual(set(ranges[1].names), {"b"})
 
   def test_convert_to_intermediate_bpf(self):
     ranges = genseccomp.convert_NRs_to_ranges([("b", 2), ("a", 1)])
     bpf = genseccomp.convert_to_intermediate_bpf(ranges)
-    self.assertEquals(bpf, ['BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 3, {fail}, {allow}), //a|b'])
+    self.assertEqual(bpf, ['BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 3, {fail}, {allow}), //a|b'])
 
     ranges = genseccomp.convert_NRs_to_ranges([("b", 3), ("a", 1)])
     bpf = genseccomp.convert_to_intermediate_bpf(ranges)
-    self.assertEquals(bpf, ['BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 3, 1, 0),',
+    self.assertEqual(bpf, ['BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 3, 1, 0),',
                             'BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 2, {fail}, {allow}), //a',
                             'BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4, {fail}, {allow}), //b'])
 
   def test_convert_ranges_to_bpf(self):
     ranges = genseccomp.convert_NRs_to_ranges([("b", 2), ("a", 1)])
-    bpf = genseccomp.convert_ranges_to_bpf(ranges)
-    self.assertEquals(bpf, ['BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 1, 0, 2),',
+    bpf = genseccomp.convert_ranges_to_bpf(ranges, priority_syscalls=[])
+    self.assertEqual(bpf, ['BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 1, 0, 2),',
                             'BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 3, 1, 0), //a|b',
                             'BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),'])
 
     ranges = genseccomp.convert_NRs_to_ranges([("b", 3), ("a", 1)])
-    bpf = genseccomp.convert_ranges_to_bpf(ranges)
-    self.assertEquals(bpf, ['BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 1, 0, 4),',
+    bpf = genseccomp.convert_ranges_to_bpf(ranges, priority_syscalls=[])
+    self.assertEqual(bpf, ['BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 1, 0, 4),',
                             'BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 3, 1, 0),',
                             'BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 2, 2, 1), //a',
                             'BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4, 1, 0), //b',
                             'BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),'])
 
   def test_convert_bpf_to_output(self):
-    output = genseccomp.convert_bpf_to_output(["line1", "line2"], "arm")
+    output = genseccomp.convert_bpf_to_output(["line1", "line2"],
+                                              "arm",
+                                              name_modifier="")
     expected_output = textwrap.dedent("""\
-    // Autogenerated file - edit at your peril!!
+    // File autogenerated by genseccomp.py - edit at your peril!!
 
     #include <linux/filter.h>
     #include <errno.h>
 
-    #include "seccomp_bpfs.h"
+    #include "seccomp/seccomp_bpfs.h"
     const sock_filter arm_filter[] = {
     line1
     line2
@@ -178,43 +67,7 @@
 
     const size_t arm_filter_size = sizeof(arm_filter) / sizeof(struct sock_filter);
     """)
-    self.assertEquals(output, expected_output)
-
-  def test_construct_bpf(self):
-    syscalls = cStringIO.StringIO(textwrap.dedent("""\
-    int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) arm,x86
-    int         fchown:fchown(int, uid_t, gid_t)    arm64,x86_64
-    """))
-
-    allowlist = cStringIO.StringIO(textwrap.dedent("""\
-    ssize_t     read(int, void*, size_t)        all
-    """))
-
-    blocklist = cStringIO.StringIO(textwrap.dedent("""\
-    """))
-
-    syscall_files = [syscalls, allowlist, blocklist]
-    output = genseccomp.construct_bpf(syscall_files, "arm", self.get_headers("arm"),
-                                      self.get_switches("arm"))
-
-    expected_output = textwrap.dedent("""\
-    // Autogenerated file - edit at your peril!!
-
-    #include <linux/filter.h>
-    #include <errno.h>
-
-    #include "seccomp_bpfs.h"
-    const sock_filter arm_filter[] = {
-    BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 3, 0, 4),
-    BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 140, 1, 0),
-    BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4, 2, 1), //read
-    BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 141, 1, 0), //_llseek
-    BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
-    };
-
-    const size_t arm_filter_size = sizeof(arm_filter) / sizeof(struct sock_filter);
-    """)
-    self.assertEquals(output, expected_output)
+    self.assertEqual(output, expected_output)
 
 
 if __name__ == '__main__':
diff --git a/libdl/Android.bp b/libdl/Android.bp
index 9a31d36..5c9fc9c 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -59,7 +59,7 @@
         "-Wl,--exclude-libs=libgcc_stripped.a",
         "-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
         "-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
-        "-Wl,--exclude-libs=libclang_rt.builtins-x86-android.a",
+        "-Wl,--exclude-libs=libclang_rt.builtins-i686-android.a",
         "-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a",
     ],
 
@@ -156,7 +156,7 @@
         "-Wl,--exclude-libs=libgcc_stripped.a",
         "-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
         "-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
-        "-Wl,--exclude-libs=libclang_rt.builtins-x86-android.a",
+        "-Wl,--exclude-libs=libclang_rt.builtins-i686-android.a",
         "-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a",
     ],
 
@@ -216,7 +216,6 @@
 
 ndk_library {
     name: "libdl",
-    native_bridge_supported: true,
     symbol_file: "libdl.map.txt",
     first_version: "9",
 }
diff --git a/libm/Android.bp b/libm/Android.bp
index 6c8ad22..723d126 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -287,6 +287,11 @@
             pack_relocations: false,
             ldflags: ["-Wl,--hash-style=both"],
             version_script: ":libm.arm.map",
+            no_libcrt: true,
+            shared: {
+                // For backwards-compatibility, some arm32 builtins are exported from libm.so.
+                static_libs: ["libclang_rt.builtins-arm-android-exported"],
+            },
         },
 
         arm64: {
@@ -470,6 +475,7 @@
         "-fno-math-errno",
         "-Wall",
         "-Werror",
+        "-Wno-ignored-pragmas",
         "-Wno-missing-braces",
         "-Wno-parentheses",
         "-Wno-sign-compare",
@@ -516,7 +522,6 @@
 
 ndk_library {
     name: "libm",
-    native_bridge_supported: true,
     symbol_file: "libm.map.txt",
     first_version: "9",
 }
diff --git a/libm/upstream-freebsd/lib/msun/bsdsrc/b_exp.c b/libm/upstream-freebsd/lib/msun/bsdsrc/b_exp.c
index febc1ad..89a2905 100644
--- a/libm/upstream-freebsd/lib/msun/bsdsrc/b_exp.c
+++ b/libm/upstream-freebsd/lib/msun/bsdsrc/b_exp.c
@@ -1,5 +1,5 @@
 /*-
- * SPDX-License-Identifier: BSD-4-Clause
+ * SPDX-License-Identifier: BSD-3-Clause
  *
  * Copyright (c) 1985, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -12,11 +12,7 @@
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -35,7 +31,7 @@
 
 /* @(#)exp.c	8.1 (Berkeley) 6/4/93 */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/bsdsrc/b_exp.c 325966 2017-11-18 14:26:50Z pfg $");
+__FBSDID("$FreeBSD$");
 
 
 /* EXP(X)
diff --git a/libm/upstream-freebsd/lib/msun/bsdsrc/b_log.c b/libm/upstream-freebsd/lib/msun/bsdsrc/b_log.c
index 8102226..c164dfa 100644
--- a/libm/upstream-freebsd/lib/msun/bsdsrc/b_log.c
+++ b/libm/upstream-freebsd/lib/msun/bsdsrc/b_log.c
@@ -1,5 +1,5 @@
 /*-
- * SPDX-License-Identifier: BSD-4-Clause
+ * SPDX-License-Identifier: BSD-3-Clause
  *
  * Copyright (c) 1992, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -12,11 +12,7 @@
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -35,7 +31,7 @@
 
 /* @(#)log.c	8.2 (Berkeley) 11/30/93 */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/bsdsrc/b_log.c 326670 2017-12-07 20:41:23Z dim $");
+__FBSDID("$FreeBSD$");
 
 #include <math.h>
 
diff --git a/libm/upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c b/libm/upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c
index e530649..5cb1f93 100644
--- a/libm/upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c
+++ b/libm/upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c
@@ -1,5 +1,5 @@
 /*-
- * SPDX-License-Identifier: BSD-4-Clause
+ * SPDX-License-Identifier: BSD-3-Clause
  *
  * Copyright (c) 1992, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -12,11 +12,7 @@
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -35,7 +31,7 @@
 
 /* @(#)gamma.c	8.1 (Berkeley) 6/4/93 */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/bsdsrc/b_tgamma.c 325966 2017-11-18 14:26:50Z pfg $");
+__FBSDID("$FreeBSD$");
 
 /*
  * This code by P. McIlroy, Oct 1992;
diff --git a/libm/upstream-freebsd/lib/msun/bsdsrc/mathimpl.h b/libm/upstream-freebsd/lib/msun/bsdsrc/mathimpl.h
index e38ea4f..abf2996 100644
--- a/libm/upstream-freebsd/lib/msun/bsdsrc/mathimpl.h
+++ b/libm/upstream-freebsd/lib/msun/bsdsrc/mathimpl.h
@@ -33,7 +33,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)mathimpl.h	8.1 (Berkeley) 6/4/93
- * $FreeBSD: head/lib/msun/bsdsrc/mathimpl.h 325966 2017-11-18 14:26:50Z pfg $
+ * $FreeBSD$
  */
 
 #ifndef _MATHIMPL_H_
diff --git a/libm/upstream-freebsd/lib/msun/ld128/e_powl.c b/libm/upstream-freebsd/lib/msun/ld128/e_powl.c
index 2f3ee55..12b92a1 100644
--- a/libm/upstream-freebsd/lib/msun/ld128/e_powl.c
+++ b/libm/upstream-freebsd/lib/msun/ld128/e_powl.c
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/ld128/e_powl.c 342651 2018-12-31 15:43:06Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/ld128/e_rem_pio2l.h b/libm/upstream-freebsd/lib/msun/ld128/e_rem_pio2l.h
index 1ed79ae..fcef399 100644
--- a/libm/upstream-freebsd/lib/msun/ld128/e_rem_pio2l.h
+++ b/libm/upstream-freebsd/lib/msun/ld128/e_rem_pio2l.h
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/ld128/e_rem_pio2l.h 336545 2018-07-20 12:42:24Z bde $");
+__FBSDID("$FreeBSD$");
 
 /* ld128 version of __ieee754_rem_pio2l(x,y)
  * 
diff --git a/libm/upstream-freebsd/lib/msun/ld128/invtrig.c b/libm/upstream-freebsd/lib/msun/ld128/invtrig.c
index e89a226..ab93732 100644
--- a/libm/upstream-freebsd/lib/msun/ld128/invtrig.c
+++ b/libm/upstream-freebsd/lib/msun/ld128/invtrig.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/ld128/invtrig.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include "invtrig.h"
 
diff --git a/libm/upstream-freebsd/lib/msun/ld128/invtrig.h b/libm/upstream-freebsd/lib/msun/ld128/invtrig.h
index fd1302a..423b568 100644
--- a/libm/upstream-freebsd/lib/msun/ld128/invtrig.h
+++ b/libm/upstream-freebsd/lib/msun/ld128/invtrig.h
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/msun/ld128/invtrig.h 326219 2017-11-26 02:00:33Z pfg $
+ * $FreeBSD$
  */
 
 #include <float.h>
diff --git a/libm/upstream-freebsd/lib/msun/ld128/k_expl.h b/libm/upstream-freebsd/lib/msun/ld128/k_expl.h
index b80d00e..159338f 100644
--- a/libm/upstream-freebsd/lib/msun/ld128/k_expl.h
+++ b/libm/upstream-freebsd/lib/msun/ld128/k_expl.h
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/ld128/k_expl.h 336545 2018-07-20 12:42:24Z bde $");
+__FBSDID("$FreeBSD$");
 
 /*
  * ld128 version of k_expl.h.  See ../ld80/s_expl.c for most comments.
@@ -265,7 +265,8 @@
 /*
  * XXX: the rest of the functions are identical for ld80 and ld128.
  * However, we should use scalbnl() for ld128, since long double
- * multiplication is very slow on the only supported ld128 arch (sparc64).
+ * multiplication was very slow on sparc64 and no new evaluation has
+ * been made for aarch64 and/or riscv.
  */
 
 static inline void
@@ -299,7 +300,7 @@
 static inline long double complex
 __ldexp_cexpl(long double complex z, int expt)
 {
-	long double exp_x, hi, lo;
+	long double c, exp_x, hi, lo, s;
 	long double x, y, scale1, scale2;
 	int half_expt, k;
 
@@ -307,16 +308,17 @@
 	y = cimagl(z);
 	__k_expl(x, &hi, &lo, &k);
 
-	exp_x = (lo + hi) * 0x1p16382;
+	exp_x = (lo + hi) * 0x1p16382L;
 	expt += k - 16382;
 
 	scale1 = 1;
 	half_expt = expt / 2;
 	SET_LDBL_EXPSIGN(scale1, BIAS + half_expt);
 	scale2 = 1;
-	SET_LDBL_EXPSIGN(scale1, BIAS + expt - half_expt);
+	SET_LDBL_EXPSIGN(scale2, BIAS + expt - half_expt);
 
-	return (CMPLXL(cos(y) * exp_x * scale1 * scale2,
-	    sinl(y) * exp_x * scale1 * scale2));
+	sincosl(y, &s, &c);
+	return (CMPLXL(c * exp_x * scale1 * scale2,
+	    s * exp_x * scale1 * scale2));
 }
 #endif /* _COMPLEX_H */
diff --git a/libm/upstream-freebsd/lib/msun/ld128/s_exp2l.c b/libm/upstream-freebsd/lib/msun/ld128/s_exp2l.c
index effeb78..ee3d2c7 100644
--- a/libm/upstream-freebsd/lib/msun/ld128/s_exp2l.c
+++ b/libm/upstream-freebsd/lib/msun/ld128/s_exp2l.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/ld128/s_exp2l.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 #include <stdint.h>
diff --git a/libm/upstream-freebsd/lib/msun/ld128/s_expl.c b/libm/upstream-freebsd/lib/msun/ld128/s_expl.c
index f4c18be..5b786af 100644
--- a/libm/upstream-freebsd/lib/msun/ld128/s_expl.c
+++ b/libm/upstream-freebsd/lib/msun/ld128/s_expl.c
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/ld128/s_expl.c 336545 2018-07-20 12:42:24Z bde $");
+__FBSDID("$FreeBSD$");
 
 /*
  * ld128 version of s_expl.c.  See ../ld80/s_expl.c for most comments.
@@ -92,7 +92,10 @@
 	t = SUM2P(hi, lo);
 
 	/* Scale by 2**k. */
-	/* XXX sparc64 multiplication is so slow that scalbnl() is faster. */
+	/*
+	 * XXX sparc64 multiplication was so slow that scalbnl() is faster,
+	 * but performance on aarch64 and riscv hasn't yet been quantified.
+	 */
 	if (k >= LDBL_MIN_EXP) {
 		if (k == LDBL_MAX_EXP)
 			RETURNI(t * 2 * 0x1p16383L);
diff --git a/libm/upstream-freebsd/lib/msun/ld128/s_logl.c b/libm/upstream-freebsd/lib/msun/ld128/s_logl.c
index 6c9981b..93a2a7c 100644
--- a/libm/upstream-freebsd/lib/msun/ld128/s_logl.c
+++ b/libm/upstream-freebsd/lib/msun/ld128/s_logl.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/ld128/s_logl.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 /**
  * Implementation of the natural logarithm of x for 128-bit format.
@@ -535,16 +535,17 @@
 	 * efficiency than is gained.
 	 */
 	/*
-	 * Use double precision operations wherever possible, since long
-	 * double operations are emulated and are very slow on the only
-	 * known machines that support ld128 (sparc64).  Also, don't try
-	 * to improve parallelism by increasing the number of operations,
-	 * since any parallelism on such machines is needed for the
-	 * emulation.  Horner's method is good for this, and is also good
-	 * for accuracy.  Horner's method doesn't handle the `lo' term
-	 * well, either for efficiency or accuracy.  However, for accuracy
-	 * we evaluate d * d * P2 separately to take advantage of
-	 * by P2 being exact, and this gives a good place to sum the 'lo'
+	 * Use double precision operations wherever possible, since
+	 * long double operations are emulated and were very slow on
+	 * the old sparc64 and unknown on the newer aarch64 and riscv
+	 * machines.  Also, don't try to improve parallelism by
+	 * increasing the number of operations, since any parallelism
+	 * on such machines is needed for the emulation.  Horner's
+	 * method is good for this, and is also good for accuracy.
+	 * Horner's method doesn't handle the `lo' term well, either
+	 * for efficiency or accuracy.  However, for accuracy we
+	 * evaluate d * d * P2 separately to take advantage of by P2
+	 * being exact, and this gives a good place to sum the 'lo'
 	 * term too.
 	 */
 	dd = (double)d;
diff --git a/libm/upstream-freebsd/lib/msun/ld128/s_nanl.c b/libm/upstream-freebsd/lib/msun/ld128/s_nanl.c
index 1b8196f..45d10e5 100644
--- a/libm/upstream-freebsd/lib/msun/ld128/s_nanl.c
+++ b/libm/upstream-freebsd/lib/msun/ld128/s_nanl.c
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/msun/ld128/s_nanl.c 326219 2017-11-26 02:00:33Z pfg $
+ * $FreeBSD$
  */
 
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/catrig.c b/libm/upstream-freebsd/lib/msun/src/catrig.c
index 4a2d076..431d8e6 100644
--- a/libm/upstream-freebsd/lib/msun/src/catrig.c
+++ b/libm/upstream-freebsd/lib/msun/src/catrig.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/catrig.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <float.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/catrigf.c b/libm/upstream-freebsd/lib/msun/src/catrigf.c
index e251871..62bcd39 100644
--- a/libm/upstream-freebsd/lib/msun/src/catrigf.c
+++ b/libm/upstream-freebsd/lib/msun/src/catrigf.c
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/catrigf.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <float.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/catrigl.c b/libm/upstream-freebsd/lib/msun/src/catrigl.c
index 63b068a..e66f87a 100644
--- a/libm/upstream-freebsd/lib/msun/src/catrigl.c
+++ b/libm/upstream-freebsd/lib/msun/src/catrigl.c
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/catrigl.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <float.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/e_asin.c b/libm/upstream-freebsd/lib/msun/src/e_asin.c
index d750658..931b270 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_asin.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_asin.c
@@ -12,7 +12,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_asin.c 317349 2017-04-23 22:31:12Z pfg $");
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_asin(x)
  * Method :                  
diff --git a/libm/upstream-freebsd/lib/msun/src/e_atan2.c b/libm/upstream-freebsd/lib/msun/src/e_atan2.c
index bef9df8..231a161 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_atan2.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_atan2.c
@@ -13,7 +13,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_atan2.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_atan2(y,x)
  * Method :
diff --git a/libm/upstream-freebsd/lib/msun/src/e_atan2f.c b/libm/upstream-freebsd/lib/msun/src/e_atan2f.c
index 0ce9bc0..346d767 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_atan2f.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_atan2f.c
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_atan2f.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include "math.h"
 #include "math_private.h"
diff --git a/libm/upstream-freebsd/lib/msun/src/e_atan2l.c b/libm/upstream-freebsd/lib/msun/src/e_atan2l.c
index 8f80acc..94ebdec 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_atan2l.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_atan2l.c
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_atan2l.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD$");
 
 /*
  * See comments in e_atan2.c.
diff --git a/libm/upstream-freebsd/lib/msun/src/e_coshl.c b/libm/upstream-freebsd/lib/msun/src/e_coshl.c
index 0002bb5..4e3b283 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_coshl.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_coshl.c
@@ -12,7 +12,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_coshl.c 306527 2016-09-30 20:20:07Z emaste $");
+__FBSDID("$FreeBSD$");
 
 /*
  * See e_cosh.c for complete comments.
diff --git a/libm/upstream-freebsd/lib/msun/src/e_exp.c b/libm/upstream-freebsd/lib/msun/src/e_exp.c
index dd88d3e..dd04d8e 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_exp.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_exp.c
@@ -11,7 +11,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_exp.c 352710 2019-09-25 18:50:57Z dim $");
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_exp(x)
  * Returns the exponential of x.
diff --git a/libm/upstream-freebsd/lib/msun/src/e_expf.c b/libm/upstream-freebsd/lib/msun/src/e_expf.c
index aaf6d5f..4903d55 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_expf.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_expf.c
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_expf.c 352710 2019-09-25 18:50:57Z dim $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 
diff --git a/libm/upstream-freebsd/lib/msun/src/e_fmod.c b/libm/upstream-freebsd/lib/msun/src/e_fmod.c
index fbb2d93..3a28dc4 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_fmod.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_fmod.c
@@ -12,7 +12,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_fmod.c 336663 2018-07-24 10:10:16Z bde $");
+__FBSDID("$FreeBSD$");
 
 /* 
  * __ieee754_fmod(x,y)
diff --git a/libm/upstream-freebsd/lib/msun/src/e_fmodf.c b/libm/upstream-freebsd/lib/msun/src/e_fmodf.c
index 3783a88..1b6bf36 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_fmodf.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_fmodf.c
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_fmodf.c 336663 2018-07-24 10:10:16Z bde $");
+__FBSDID("$FreeBSD$");
 
 /*
  * __ieee754_fmodf(x,y)
diff --git a/libm/upstream-freebsd/lib/msun/src/e_fmodl.c b/libm/upstream-freebsd/lib/msun/src/e_fmodl.c
index 77d1642..ad3bcc3 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_fmodl.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_fmodl.c
@@ -11,7 +11,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_fmodl.c 336663 2018-07-24 10:10:16Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 #include <stdint.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/e_hypot.c b/libm/upstream-freebsd/lib/msun/src/e_hypot.c
index 0c16767..7c455bb 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_hypot.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_hypot.c
@@ -12,7 +12,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_hypot.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_hypot(x,y)
  *
@@ -118,10 +118,8 @@
 	    w  = sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b)));
 	}
 	if(k!=0) {
-	    u_int32_t high;
-	    t1 = 1.0;
-	    GET_HIGH_WORD(high,t1);
-	    SET_HIGH_WORD(t1,high+(k<<20));
+	    t1 = 0.0;
+	    SET_HIGH_WORD(t1,(1023+k)<<20);
 	    return t1*w;
 	} else return w;
 }
diff --git a/libm/upstream-freebsd/lib/msun/src/e_hypotf.c b/libm/upstream-freebsd/lib/msun/src/e_hypotf.c
index 79e4697..0061026 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_hypotf.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_hypotf.c
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_hypotf.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include "math.h"
 #include "math_private.h"
@@ -77,7 +77,7 @@
 	    w  = __ieee754_sqrtf(t1*y1-(w*(-w)-(t1*y2+t2*b)));
 	}
 	if(k!=0) {
-	    SET_FLOAT_WORD(t1,0x3f800000+(k<<23));
+	    SET_FLOAT_WORD(t1,(127+k)<<23);
 	    return t1*w;
 	} else return w;
 }
diff --git a/libm/upstream-freebsd/lib/msun/src/e_hypotl.c b/libm/upstream-freebsd/lib/msun/src/e_hypotl.c
index 5603b6e..9189b1f 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_hypotl.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_hypotl.c
@@ -11,7 +11,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_hypotl.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD$");
 
 /* long double version of hypot().  See e_hypot.c for most comments. */
 
diff --git a/libm/upstream-freebsd/lib/msun/src/e_j0.c b/libm/upstream-freebsd/lib/msun/src/e_j0.c
index a008b42..5d862b6 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_j0.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_j0.c
@@ -11,7 +11,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_j0.c 343953 2019-02-10 08:46:07Z peterj $");
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_j0(x), __ieee754_y0(x)
  * Bessel function of the first and second kinds of order zero.
diff --git a/libm/upstream-freebsd/lib/msun/src/e_j0f.c b/libm/upstream-freebsd/lib/msun/src/e_j0f.c
index 495a5e5..1c5ef4d 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_j0f.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_j0f.c
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_j0f.c 343953 2019-02-10 08:46:07Z peterj $");
+__FBSDID("$FreeBSD$");
 
 /*
  * See e_j0.c for complete comments.
diff --git a/libm/upstream-freebsd/lib/msun/src/e_j1.c b/libm/upstream-freebsd/lib/msun/src/e_j1.c
index 6d1c41c..fb44627 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_j1.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_j1.c
@@ -11,7 +11,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_j1.c 343953 2019-02-10 08:46:07Z peterj $");
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_j1(x), __ieee754_y1(x)
  * Bessel function of the first and second kinds of order zero.
diff --git a/libm/upstream-freebsd/lib/msun/src/e_j1f.c b/libm/upstream-freebsd/lib/msun/src/e_j1f.c
index 31fc28a..c6c45c1 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_j1f.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_j1f.c
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_j1f.c 343953 2019-02-10 08:46:07Z peterj $");
+__FBSDID("$FreeBSD$");
 
 /*
  * See e_j1.c for complete comments.
diff --git a/libm/upstream-freebsd/lib/msun/src/e_jn.c b/libm/upstream-freebsd/lib/msun/src/e_jn.c
index c039cf2..c7ba7da 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_jn.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_jn.c
@@ -11,7 +11,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_jn.c 343953 2019-02-10 08:46:07Z peterj $");
+__FBSDID("$FreeBSD$");
 
 /*
  * __ieee754_jn(n, x), __ieee754_yn(n, x)
diff --git a/libm/upstream-freebsd/lib/msun/src/e_jnf.c b/libm/upstream-freebsd/lib/msun/src/e_jnf.c
index c82d5cf..965feeb 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_jnf.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_jnf.c
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_jnf.c 279856 2015-03-10 17:10:54Z kargl $");
+__FBSDID("$FreeBSD$");
 
 /*
  * See e_jn.c for complete comments.
diff --git a/libm/upstream-freebsd/lib/msun/src/e_lgammaf_r.c b/libm/upstream-freebsd/lib/msun/src/e_lgammaf_r.c
index 46bdd6f..48346c3 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_lgammaf_r.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_lgammaf_r.c
@@ -15,7 +15,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_lgammaf_r.c 306709 2016-10-05 17:04:58Z emaste $");
+__FBSDID("$FreeBSD$");
 
 #include "math.h"
 #include "math_private.h"
diff --git a/libm/upstream-freebsd/lib/msun/src/e_pow.c b/libm/upstream-freebsd/lib/msun/src/e_pow.c
index b4f6a5a..52b2f5c 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_pow.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_pow.c
@@ -10,7 +10,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_pow.c 342851 2019-01-07 17:35:09Z pfg $");
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_pow(x,y) return x**y
  *
diff --git a/libm/upstream-freebsd/lib/msun/src/e_powf.c b/libm/upstream-freebsd/lib/msun/src/e_powf.c
index 13dd4eb..53f1d37 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_powf.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_powf.c
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_powf.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include "math.h"
 #include "math_private.h"
diff --git a/libm/upstream-freebsd/lib/msun/src/e_rem_pio2.c b/libm/upstream-freebsd/lib/msun/src/e_rem_pio2.c
index 3e62c2b..47b6513 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_rem_pio2.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_rem_pio2.c
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_rem_pio2.c 336545 2018-07-20 12:42:24Z bde $");
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_rem_pio2(x,y)
  * 
diff --git a/libm/upstream-freebsd/lib/msun/src/e_rem_pio2f.c b/libm/upstream-freebsd/lib/msun/src/e_rem_pio2f.c
index 2a89d27..597f613 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_rem_pio2f.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_rem_pio2f.c
@@ -15,7 +15,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_rem_pio2f.c 336545 2018-07-20 12:42:24Z bde $");
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_rem_pio2f(x,y)
  *
diff --git a/libm/upstream-freebsd/lib/msun/src/e_remainder.c b/libm/upstream-freebsd/lib/msun/src/e_remainder.c
index 334d282..a4ae0b7 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_remainder.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_remainder.c
@@ -12,7 +12,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_remainder.c 336663 2018-07-24 10:10:16Z bde $");
+__FBSDID("$FreeBSD$");
 
 /* __ieee754_remainder(x,p)
  * Return :                  
diff --git a/libm/upstream-freebsd/lib/msun/src/e_remainderf.c b/libm/upstream-freebsd/lib/msun/src/e_remainderf.c
index ba3e07a..8004493 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_remainderf.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_remainderf.c
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_remainderf.c 336663 2018-07-24 10:10:16Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include "math.h"
 #include "math_private.h"
diff --git a/libm/upstream-freebsd/lib/msun/src/e_remainderl.c b/libm/upstream-freebsd/lib/msun/src/e_remainderl.c
index 6e4a4da..4a67863 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_remainderl.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_remainderl.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_remainderl.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <math.h>
 
diff --git a/libm/upstream-freebsd/lib/msun/src/e_sinhl.c b/libm/upstream-freebsd/lib/msun/src/e_sinhl.c
index 21dd8b2..38d3df1 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_sinhl.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_sinhl.c
@@ -12,7 +12,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_sinhl.c 306527 2016-09-30 20:20:07Z emaste $");
+__FBSDID("$FreeBSD$");
 
 /*
  * See e_sinh.c for complete comments.
diff --git a/libm/upstream-freebsd/lib/msun/src/e_sqrtl.c b/libm/upstream-freebsd/lib/msun/src/e_sqrtl.c
index fbb3a10..565d963 100644
--- a/libm/upstream-freebsd/lib/msun/src/e_sqrtl.c
+++ b/libm/upstream-freebsd/lib/msun/src/e_sqrtl.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_sqrtl.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <fenv.h>
 #include <float.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/k_exp.c b/libm/upstream-freebsd/lib/msun/src/k_exp.c
index 7cc083f..dd15ff4 100644
--- a/libm/upstream-freebsd/lib/msun/src/k_exp.c
+++ b/libm/upstream-freebsd/lib/msun/src/k_exp.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/k_exp.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 
@@ -88,7 +88,7 @@
 double complex
 __ldexp_cexp(double complex z, int expt)
 {
-	double x, y, exp_x, scale1, scale2;
+	double c, exp_x, s, scale1, scale2, x, y;
 	int ex_expt, half_expt;
 
 	x = creal(z);
@@ -105,6 +105,7 @@
 	half_expt = expt - half_expt;
 	INSERT_WORDS(scale2, (0x3ff + half_expt) << 20, 0);
 
-	return (CMPLX(cos(y) * exp_x * scale1 * scale2,
-	    sin(y) * exp_x * scale1 * scale2));
+	sincos(y, &s, &c);
+	return (CMPLX(c * exp_x * scale1 * scale2,
+	    s * exp_x * scale1 * scale2));
 }
diff --git a/libm/upstream-freebsd/lib/msun/src/k_expf.c b/libm/upstream-freebsd/lib/msun/src/k_expf.c
index 5aa5c76..80e629b 100644
--- a/libm/upstream-freebsd/lib/msun/src/k_expf.c
+++ b/libm/upstream-freebsd/lib/msun/src/k_expf.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/k_expf.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 
@@ -71,7 +71,7 @@
 float complex
 __ldexp_cexpf(float complex z, int expt)
 {
-	float x, y, exp_x, scale1, scale2;
+	float c, exp_x, s, scale1, scale2, x, y;
 	int ex_expt, half_expt;
 
 	x = crealf(z);
@@ -84,6 +84,7 @@
 	half_expt = expt - half_expt;
 	SET_FLOAT_WORD(scale2, (0x7f + half_expt) << 23);
 
-	return (CMPLXF(cosf(y) * exp_x * scale1 * scale2,
-	    sinf(y) * exp_x * scale1 * scale2));
+	sincosf(y, &s, &c);
+	return (CMPLXF(c * exp_x * scale1 * scale2,
+	    s * exp_x * scale1 * scale2));
 }
diff --git a/libm/upstream-freebsd/lib/msun/src/k_rem_pio2.c b/libm/upstream-freebsd/lib/msun/src/k_rem_pio2.c
index 0869e03..0a717f7 100644
--- a/libm/upstream-freebsd/lib/msun/src/k_rem_pio2.c
+++ b/libm/upstream-freebsd/lib/msun/src/k_rem_pio2.c
@@ -12,7 +12,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/k_rem_pio2.c 342651 2018-12-31 15:43:06Z pfg $");
+__FBSDID("$FreeBSD$");
 
 /*
  * __kernel_rem_pio2(x,y,e0,nx,prec)
diff --git a/libm/upstream-freebsd/lib/msun/src/k_sincos.h b/libm/upstream-freebsd/lib/msun/src/k_sincos.h
index b83e690..6f03be2 100644
--- a/libm/upstream-freebsd/lib/msun/src/k_sincos.h
+++ b/libm/upstream-freebsd/lib/msun/src/k_sincos.h
@@ -12,7 +12,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/k_sincos.h 319047 2017-05-28 06:13:38Z mmel $");
+__FBSDID("$FreeBSD$");
 
 static const double
 S1  = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
diff --git a/libm/upstream-freebsd/lib/msun/src/k_sincosf.h b/libm/upstream-freebsd/lib/msun/src/k_sincosf.h
index ad51e83..073986d 100644
--- a/libm/upstream-freebsd/lib/msun/src/k_sincosf.h
+++ b/libm/upstream-freebsd/lib/msun/src/k_sincosf.h
@@ -12,7 +12,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/k_sincosf.h 319047 2017-05-28 06:13:38Z mmel $");
+__FBSDID("$FreeBSD$");
 
 /* |sin(x)/x - s(x)| < 2**-37.5 (~[-4.89e-12, 4.824e-12]). */
 static const double
diff --git a/libm/upstream-freebsd/lib/msun/src/k_sincosl.h b/libm/upstream-freebsd/lib/msun/src/k_sincosl.h
index 423948e..4d4dc69 100644
--- a/libm/upstream-freebsd/lib/msun/src/k_sincosl.h
+++ b/libm/upstream-freebsd/lib/msun/src/k_sincosl.h
@@ -13,7 +13,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/k_sincosl.h 319047 2017-05-28 06:13:38Z mmel $");
+__FBSDID("$FreeBSD$");
 
 #if LDBL_MANT_DIG == 64		/* ld80 version of k_sincosl.c. */
 
@@ -28,8 +28,8 @@
 #define	C1	((long double)C1hi + C1lo)
 #else
 static const long double
-C1 =  0.0416666666666666666136L;	/*  0xaaaaaaaaaaaaaa9b.0p-68 */
-S1 = -0.166666666666666666671L,		/* -0xaaaaaaaaaaaaaaab.0p-66 */
+C1 =  0.0416666666666666666136L,	/*  0xaaaaaaaaaaaaaa9b.0p-68 */
+S1 = -0.166666666666666666671L;		/* -0xaaaaaaaaaaaaaaab.0p-66 */
 #endif
 
 static const double
diff --git a/libm/upstream-freebsd/lib/msun/src/math_private.h b/libm/upstream-freebsd/lib/msun/src/math_private.h
index bc3d516..b91b54c 100644
--- a/libm/upstream-freebsd/lib/msun/src/math_private.h
+++ b/libm/upstream-freebsd/lib/msun/src/math_private.h
@@ -11,7 +11,7 @@
 
 /*
  * from: @(#)fdlibm.h 5.1 93/09/24
- * $FreeBSD: head/lib/msun/src/math_private.h 336663 2018-07-24 10:10:16Z bde $
+ * $FreeBSD$
  */
 
 #ifndef _MATH_PRIVATE_H_
diff --git a/libm/upstream-freebsd/lib/msun/src/s_carg.c b/libm/upstream-freebsd/lib/msun/src/s_carg.c
index d0f9ced..1611b9d 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_carg.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_carg.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_carg.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cargf.c b/libm/upstream-freebsd/lib/msun/src/s_cargf.c
index e4a76f4..71c705d 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cargf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cargf.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_cargf.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cargl.c b/libm/upstream-freebsd/lib/msun/src/s_cargl.c
index 9885d60..96c3336 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cargl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cargl.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_cargl.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cbrt.c b/libm/upstream-freebsd/lib/msun/src/s_cbrt.c
index 268425e..0e609e1 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cbrt.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cbrt.c
@@ -13,7 +13,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_cbrt.c 342563 2018-12-28 01:34:08Z jhibbits $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 #include "math.h"
diff --git a/libm/upstream-freebsd/lib/msun/src/s_ccosh.c b/libm/upstream-freebsd/lib/msun/src/s_ccosh.c
index da568f4..7652b3c 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_ccosh.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_ccosh.c
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_ccosh.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_ccoshf.c b/libm/upstream-freebsd/lib/msun/src/s_ccoshf.c
index 4aeea63..5d7a09b 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_ccoshf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_ccoshf.c
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_ccoshf.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cexp.c b/libm/upstream-freebsd/lib/msun/src/s_cexp.c
index a2b9154..2ef8ba1 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cexp.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cexp.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_cexp.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cexpf.c b/libm/upstream-freebsd/lib/msun/src/s_cexpf.c
index ee7512b..b815c99 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cexpf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cexpf.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_cexpf.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cimag.c b/libm/upstream-freebsd/lib/msun/src/s_cimag.c
index e89ee12..1f383cb 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cimag.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cimag.c
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/msun/src/s_cimag.c 326219 2017-11-26 02:00:33Z pfg $
+ * $FreeBSD$
  */
 
 #include <complex.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cimagf.c b/libm/upstream-freebsd/lib/msun/src/s_cimagf.c
index 2bfce10..86a43c1 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cimagf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cimagf.c
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/msun/src/s_cimagf.c 326219 2017-11-26 02:00:33Z pfg $
+ * $FreeBSD$
  */
 
 #include <complex.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cimagl.c b/libm/upstream-freebsd/lib/msun/src/s_cimagl.c
index fafeaff..6d87950 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cimagl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cimagl.c
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/msun/src/s_cimagl.c 326219 2017-11-26 02:00:33Z pfg $
+ * $FreeBSD$
  */
 
 #include <complex.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_clog.c b/libm/upstream-freebsd/lib/msun/src/s_clog.c
index 2c31095..8150fa7 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_clog.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_clog.c
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_clog.c 333577 2018-05-13 09:54:34Z kib $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <float.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_clogf.c b/libm/upstream-freebsd/lib/msun/src/s_clogf.c
index d94977d..19a9445 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_clogf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_clogf.c
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_clogf.c 333577 2018-05-13 09:54:34Z kib $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <float.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_clogl.c b/libm/upstream-freebsd/lib/msun/src/s_clogl.c
index 9f56ca3..e59a137 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_clogl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_clogl.c
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_clogl.c 333577 2018-05-13 09:54:34Z kib $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <float.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_conj.c b/libm/upstream-freebsd/lib/msun/src/s_conj.c
index 8e4d3fc..dc56f48 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_conj.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_conj.c
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/msun/src/s_conj.c 326219 2017-11-26 02:00:33Z pfg $
+ * $FreeBSD$
  */
 
 #include <complex.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_conjf.c b/libm/upstream-freebsd/lib/msun/src/s_conjf.c
index f691894..3fd8b8f 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_conjf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_conjf.c
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/msun/src/s_conjf.c 326219 2017-11-26 02:00:33Z pfg $
+ * $FreeBSD$
  */
 
 #include <complex.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_conjl.c b/libm/upstream-freebsd/lib/msun/src/s_conjl.c
index 00f315a..d2f8d0f 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_conjl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_conjl.c
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/msun/src/s_conjl.c 326219 2017-11-26 02:00:33Z pfg $
+ * $FreeBSD$
  */
 
 #include <complex.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_copysignl.c b/libm/upstream-freebsd/lib/msun/src/s_copysignl.c
index cef101e..bd67447 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_copysignl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_copysignl.c
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/msun/src/s_copysignl.c 326219 2017-11-26 02:00:33Z pfg $
+ * $FreeBSD$
  */
 
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cosl.c b/libm/upstream-freebsd/lib/msun/src/s_cosl.c
index 72c2dd3..46a2e86 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cosl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cosl.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_cosl.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 /*
  * Limited testing on pseudorandom numbers drawn within [-2e8:4e8] shows
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cpow.c b/libm/upstream-freebsd/lib/msun/src/s_cpow.c
index 1cb99aa..cdc57bd 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cpow.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cpow.c
@@ -44,7 +44,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_cpow.c 336563 2018-07-20 18:27:30Z dim $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <float.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cpowf.c b/libm/upstream-freebsd/lib/msun/src/s_cpowf.c
index a2ef525..aeb773b 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cpowf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cpowf.c
@@ -44,7 +44,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_cpowf.c 336563 2018-07-20 18:27:30Z dim $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cpowl.c b/libm/upstream-freebsd/lib/msun/src/s_cpowl.c
index f9c6373..5d43b55 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cpowl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cpowl.c
@@ -44,7 +44,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_cpowl.c 336563 2018-07-20 18:27:30Z dim $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cproj.c b/libm/upstream-freebsd/lib/msun/src/s_cproj.c
index 7677b5f..38e7747 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cproj.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cproj.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_cproj.c 342563 2018-12-28 01:34:08Z jhibbits $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <float.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cprojf.c b/libm/upstream-freebsd/lib/msun/src/s_cprojf.c
index f29f8d7..af4c3a8 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cprojf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cprojf.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_cprojf.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_cprojl.c b/libm/upstream-freebsd/lib/msun/src/s_cprojl.c
index c9242cb..16df514 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_cprojl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_cprojl.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_cprojl.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_creal.c b/libm/upstream-freebsd/lib/msun/src/s_creal.c
index a30c7f6..69a10f2 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_creal.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_creal.c
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/msun/src/s_creal.c 326219 2017-11-26 02:00:33Z pfg $
+ * $FreeBSD$
  */
 
 #include <complex.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_crealf.c b/libm/upstream-freebsd/lib/msun/src/s_crealf.c
index 95469d8..83e4d46 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_crealf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_crealf.c
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/msun/src/s_crealf.c 326219 2017-11-26 02:00:33Z pfg $
+ * $FreeBSD$
  */
 
 #include <complex.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_creall.c b/libm/upstream-freebsd/lib/msun/src/s_creall.c
index e34f761..538b7d5 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_creall.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_creall.c
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/msun/src/s_creall.c 326219 2017-11-26 02:00:33Z pfg $
+ * $FreeBSD$
  */
 
 #include <complex.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_csinh.c b/libm/upstream-freebsd/lib/msun/src/s_csinh.c
index 7408b13..09b2dcb 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_csinh.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_csinh.c
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_csinh.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_csinhf.c b/libm/upstream-freebsd/lib/msun/src/s_csinhf.c
index 6e29f19..ba1a794 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_csinhf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_csinhf.c
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_csinhf.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_csqrt.c b/libm/upstream-freebsd/lib/msun/src/s_csqrt.c
index 215b7d7..d172efc 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_csqrt.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_csqrt.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_csqrt.c 336488 2018-07-19 15:04:10Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <float.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_csqrtf.c b/libm/upstream-freebsd/lib/msun/src/s_csqrtf.c
index 16d3266..6836a39 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_csqrtf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_csqrtf.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_csqrtf.c 336412 2018-07-17 12:01:59Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_csqrtl.c b/libm/upstream-freebsd/lib/msun/src/s_csqrtl.c
index e58e4ae..40bc59d 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_csqrtl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_csqrtl.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_csqrtl.c 336488 2018-07-19 15:04:10Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <float.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_ctanh.c b/libm/upstream-freebsd/lib/msun/src/s_ctanh.c
index d005baf..88afeb5 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_ctanh.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_ctanh.c
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_ctanh.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_ctanhf.c b/libm/upstream-freebsd/lib/msun/src/s_ctanhf.c
index 06825a3..d2bd0b6 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_ctanhf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_ctanhf.c
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_ctanhf.c 336362 2018-07-17 07:42:14Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include <complex.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_erf.c b/libm/upstream-freebsd/lib/msun/src/s_erf.c
index 3e39d80..5f22847 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_erf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_erf.c
@@ -11,7 +11,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_erf.c 342563 2018-12-28 01:34:08Z jhibbits $");
+__FBSDID("$FreeBSD$");
 
 /* double erf(double x)
  * double erfc(double x)
diff --git a/libm/upstream-freebsd/lib/msun/src/s_exp2.c b/libm/upstream-freebsd/lib/msun/src/s_exp2.c
index dc3fb02..bc36e55 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_exp2.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_exp2.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_exp2.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 
diff --git a/libm/upstream-freebsd/lib/msun/src/s_exp2f.c b/libm/upstream-freebsd/lib/msun/src/s_exp2f.c
index e587b06..c082924 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_exp2f.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_exp2f.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_exp2f.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 
diff --git a/libm/upstream-freebsd/lib/msun/src/s_expm1.c b/libm/upstream-freebsd/lib/msun/src/s_expm1.c
index 21256ce..844f103 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_expm1.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_expm1.c
@@ -11,7 +11,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_expm1.c 352710 2019-09-25 18:50:57Z dim $");
+__FBSDID("$FreeBSD$");
 
 /* expm1(x)
  * Returns exp(x)-1, the exponential of x minus 1.
diff --git a/libm/upstream-freebsd/lib/msun/src/s_expm1f.c b/libm/upstream-freebsd/lib/msun/src/s_expm1f.c
index 4d9ab36..b47daac 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_expm1f.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_expm1f.c
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_expm1f.c 352710 2019-09-25 18:50:57Z dim $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 
diff --git a/libm/upstream-freebsd/lib/msun/src/s_fabsl.c b/libm/upstream-freebsd/lib/msun/src/s_fabsl.c
index 0eef5b7..5076d8a 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_fabsl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_fabsl.c
@@ -27,7 +27,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/msun/src/s_fabsl.c 326219 2017-11-26 02:00:33Z pfg $
+ * $FreeBSD$
  */
 
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_fdim.c b/libm/upstream-freebsd/lib/msun/src/s_fdim.c
index bb22474..c40c3e9 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_fdim.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_fdim.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_fdim.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <math.h>
 
diff --git a/libm/upstream-freebsd/lib/msun/src/s_fma.c b/libm/upstream-freebsd/lib/msun/src/s_fma.c
index 4472537..41a6424 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_fma.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_fma.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_fma.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <fenv.h>
 #include <float.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_fmaf.c b/libm/upstream-freebsd/lib/msun/src/s_fmaf.c
index 88a86f2..389cf1b 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_fmaf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_fmaf.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_fmaf.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <fenv.h>
 
diff --git a/libm/upstream-freebsd/lib/msun/src/s_fmal.c b/libm/upstream-freebsd/lib/msun/src/s_fmal.c
index 3c1910a..a379346 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_fmal.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_fmal.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_fmal.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <fenv.h>
 #include <float.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_fmax.c b/libm/upstream-freebsd/lib/msun/src/s_fmax.c
index ba0bf6b..0c234bc 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_fmax.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_fmax.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_fmax.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_fmaxf.c b/libm/upstream-freebsd/lib/msun/src/s_fmaxf.c
index 6a3f06b..8e9d1ba 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_fmaxf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_fmaxf.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_fmaxf.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <math.h>
 
diff --git a/libm/upstream-freebsd/lib/msun/src/s_fmaxl.c b/libm/upstream-freebsd/lib/msun/src/s_fmaxl.c
index 4f0ee31..c0d7c88 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_fmaxl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_fmaxl.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_fmaxl.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <math.h>
 
diff --git a/libm/upstream-freebsd/lib/msun/src/s_fmin.c b/libm/upstream-freebsd/lib/msun/src/s_fmin.c
index d49bedb..d7f24c1 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_fmin.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_fmin.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_fmin.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_fminf.c b/libm/upstream-freebsd/lib/msun/src/s_fminf.c
index 3c88228..2583167 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_fminf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_fminf.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_fminf.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <math.h>
 
diff --git a/libm/upstream-freebsd/lib/msun/src/s_fminl.c b/libm/upstream-freebsd/lib/msun/src/s_fminl.c
index aa6cc9f..97604b3 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_fminl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_fminl.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_fminl.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <math.h>
 
diff --git a/libm/upstream-freebsd/lib/msun/src/s_frexpl.c b/libm/upstream-freebsd/lib/msun/src/s_frexpl.c
index 310f2e3..66e284f 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_frexpl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_frexpl.c
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/msun/src/s_frexpl.c 326219 2017-11-26 02:00:33Z pfg $
+ * $FreeBSD$
  */
 
 #include <float.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_logbl.c b/libm/upstream-freebsd/lib/msun/src/s_logbl.c
index ae71302..ee1a91f 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_logbl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_logbl.c
@@ -11,7 +11,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_logbl.c 306409 2016-09-28 14:48:34Z emaste $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 #include <limits.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_lrint.c b/libm/upstream-freebsd/lib/msun/src/s_lrint.c
index 0e15999..ad9b978 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_lrint.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_lrint.c
@@ -31,7 +31,7 @@
 #include <math.h>
 
 #ifndef type
-__FBSDID("$FreeBSD: head/lib/msun/src/s_lrint.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 #define type		double
 #define	roundit		rint
 #define dtype		long
diff --git a/libm/upstream-freebsd/lib/msun/src/s_lround.c b/libm/upstream-freebsd/lib/msun/src/s_lround.c
index ce2aee7..66d9183 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_lround.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_lround.c
@@ -32,7 +32,7 @@
 #include <math.h>
 
 #ifndef type
-__FBSDID("$FreeBSD: head/lib/msun/src/s_lround.c 353329 2019-10-08 21:39:51Z brooks $");
+__FBSDID("$FreeBSD$");
 #define type		double
 #define	roundit		round
 #define dtype		long
diff --git a/libm/upstream-freebsd/lib/msun/src/s_modfl.c b/libm/upstream-freebsd/lib/msun/src/s_modfl.c
index 2f884d2..2d83bbe 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_modfl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_modfl.c
@@ -35,7 +35,7 @@
  * is preserved.
  * ====================================================
  *
- * $FreeBSD: head/lib/msun/src/s_modfl.c 326219 2017-11-26 02:00:33Z pfg $
+ * $FreeBSD$
  */
 
 #include <float.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_nan.c b/libm/upstream-freebsd/lib/msun/src/s_nan.c
index 4a25df0..1769244 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_nan.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_nan.c
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/lib/msun/src/s_nan.c 326219 2017-11-26 02:00:33Z pfg $
+ * $FreeBSD$
  */
 
 #include <sys/endian.h>
@@ -66,14 +66,15 @@
 		;
 
 	/* Scan backwards, filling in the bits in words[] as we go. */
-#if _BYTE_ORDER == _LITTLE_ENDIAN
 	for (bitpos = 0; bitpos < 32 * num_words; bitpos += 4) {
-#else
-	for (bitpos = 32 * num_words - 4; bitpos >= 0; bitpos -= 4) {
-#endif
 		if (--si < 0)
 			break;
+#if _BYTE_ORDER == _LITTLE_ENDIAN
 		words[bitpos / 32] |= digittoint(s[si]) << (bitpos % 32);
+#else
+		words[num_words - 1 - bitpos / 32] |=
+		    digittoint(s[si]) << (bitpos % 32);
+#endif
 	}
 }
 
diff --git a/libm/upstream-freebsd/lib/msun/src/s_nearbyint.c b/libm/upstream-freebsd/lib/msun/src/s_nearbyint.c
index 0ea6ce7..796dbaf 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_nearbyint.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_nearbyint.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_nearbyint.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <fenv.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_remquo.c b/libm/upstream-freebsd/lib/msun/src/s_remquo.c
index be6a2e8..6a111df 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_remquo.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_remquo.c
@@ -11,7 +11,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_remquo.c 336663 2018-07-24 10:10:16Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 
diff --git a/libm/upstream-freebsd/lib/msun/src/s_remquof.c b/libm/upstream-freebsd/lib/msun/src/s_remquof.c
index 775672f..f4c1016 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_remquof.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_remquof.c
@@ -11,7 +11,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_remquof.c 336663 2018-07-24 10:10:16Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include "math.h"
 #include "math_private.h"
diff --git a/libm/upstream-freebsd/lib/msun/src/s_remquol.c b/libm/upstream-freebsd/lib/msun/src/s_remquol.c
index 5ac13e4..a9f5813 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_remquol.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_remquol.c
@@ -11,7 +11,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_remquol.c 336665 2018-07-24 11:50:05Z bde $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 #include <stdint.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_rintl.c b/libm/upstream-freebsd/lib/msun/src/s_rintl.c
index a05f4c4..1e9824d 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_rintl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_rintl.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_rintl.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 #include <math.h>
diff --git a/libm/upstream-freebsd/lib/msun/src/s_round.c b/libm/upstream-freebsd/lib/msun/src/s_round.c
index cdf6b97..ca25f8e 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_round.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_round.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_round.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 
diff --git a/libm/upstream-freebsd/lib/msun/src/s_roundf.c b/libm/upstream-freebsd/lib/msun/src/s_roundf.c
index 37be766..5bbf6b3 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_roundf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_roundf.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_roundf.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include "math.h"
 #include "math_private.h"
diff --git a/libm/upstream-freebsd/lib/msun/src/s_roundl.c b/libm/upstream-freebsd/lib/msun/src/s_roundl.c
index 22f956c..8d1c02a 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_roundl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_roundl.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_roundl.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 #ifdef __i386__
diff --git a/libm/upstream-freebsd/lib/msun/src/s_scalbln.c b/libm/upstream-freebsd/lib/msun/src/s_scalbln.c
index 52e3d78..c27420c 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_scalbln.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_scalbln.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_scalbln.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <math.h>
 
diff --git a/libm/upstream-freebsd/lib/msun/src/s_scalbn.c b/libm/upstream-freebsd/lib/msun/src/s_scalbn.c
index 52b0d27..b048b05 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_scalbn.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_scalbn.c
@@ -11,7 +11,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_scalbn.c 306409 2016-09-28 14:48:34Z emaste $");
+__FBSDID("$FreeBSD$");
 
 /*
  * scalbn (double x, int n)
diff --git a/libm/upstream-freebsd/lib/msun/src/s_scalbnf.c b/libm/upstream-freebsd/lib/msun/src/s_scalbnf.c
index d78fe24..21d001c 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_scalbnf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_scalbnf.c
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_scalbnf.c 306409 2016-09-28 14:48:34Z emaste $");
+__FBSDID("$FreeBSD$");
 
 #include "math.h"
 #include "math_private.h"
diff --git a/libm/upstream-freebsd/lib/msun/src/s_scalbnl.c b/libm/upstream-freebsd/lib/msun/src/s_scalbnl.c
index a7822e2..28b0cf9 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_scalbnl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_scalbnl.c
@@ -11,7 +11,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_scalbnl.c 306409 2016-09-28 14:48:34Z emaste $");
+__FBSDID("$FreeBSD$");
 
 /*
  * scalbnl (long double x, int n)
diff --git a/libm/upstream-freebsd/lib/msun/src/s_sincos.c b/libm/upstream-freebsd/lib/msun/src/s_sincos.c
index 72b2d64..85e8d74 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_sincos.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_sincos.c
@@ -13,7 +13,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_sincos.c 319047 2017-05-28 06:13:38Z mmel $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 
diff --git a/libm/upstream-freebsd/lib/msun/src/s_sincosf.c b/libm/upstream-freebsd/lib/msun/src/s_sincosf.c
index 4aaa780..755ff05 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_sincosf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_sincosf.c
@@ -16,7 +16,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_sincosf.c 319047 2017-05-28 06:13:38Z mmel $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 
diff --git a/libm/upstream-freebsd/lib/msun/src/s_sincosl.c b/libm/upstream-freebsd/lib/msun/src/s_sincosl.c
index 75cf24d..aef36c2 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_sincosl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_sincosl.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_sincosl.c 319047 2017-05-28 06:13:38Z mmel $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 #ifdef __i386__
diff --git a/libm/upstream-freebsd/lib/msun/src/s_sinl.c b/libm/upstream-freebsd/lib/msun/src/s_sinl.c
index 1bdbbc5..f1ef84c 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_sinl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_sinl.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_sinl.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <float.h>
 #ifdef __i386__
diff --git a/libm/upstream-freebsd/lib/msun/src/s_tanhl.c b/libm/upstream-freebsd/lib/msun/src/s_tanhl.c
index 696039f..b753186 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_tanhl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_tanhl.c
@@ -13,7 +13,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_tanhl.c 306527 2016-09-30 20:20:07Z emaste $");
+__FBSDID("$FreeBSD$");
 
 /*
  * See s_tanh.c for complete comments.
diff --git a/libm/upstream-freebsd/lib/msun/src/s_tanl.c b/libm/upstream-freebsd/lib/msun/src/s_tanl.c
index 1928176..0c5228e 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_tanl.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_tanl.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_tanl.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 /*
  * Limited testing on pseudorandom numbers drawn within [0:4e8] shows
diff --git a/libm/upstream-freebsd/lib/msun/src/s_tgammaf.c b/libm/upstream-freebsd/lib/msun/src/s_tgammaf.c
index 8527e16..1fd46e8 100644
--- a/libm/upstream-freebsd/lib/msun/src/s_tgammaf.c
+++ b/libm/upstream-freebsd/lib/msun/src/s_tgammaf.c
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/s_tgammaf.c 326219 2017-11-26 02:00:33Z pfg $");
+__FBSDID("$FreeBSD$");
 
 #include <math.h>
 
diff --git a/linker/Android.bp b/linker/Android.bp
index 3ebae59..06e6fbc 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -232,19 +232,15 @@
     arch: {
         arm: {
             srcs: [":linker_sources_arm"],
-            static_libs: ["libunwind_llvm"],
         },
         arm64: {
             srcs: [":linker_sources_arm64"],
-            static_libs: ["libgcc_stripped"],
         },
         x86: {
             srcs: [":linker_sources_x86"],
-            static_libs: ["libgcc_stripped"],
         },
         x86_64: {
             srcs: [":linker_sources_x86_64"],
-            static_libs: ["libgcc_stripped"],
         },
     },
 
@@ -292,6 +288,7 @@
         "libc_nomalloc",
         "libc_dynamic_dispatch",
         "libm",
+        "libunwind",
     ],
 
     // Ensure that if the linker needs __gnu_Unwind_Find_exidx, then the linker will have a
@@ -395,6 +392,7 @@
 sh_binary {
     name: "ldd",
     src: "ldd",
+    bazel_module: { bp2build_available: true },
 }
 
 cc_library {
@@ -412,7 +410,7 @@
         "-Wl,--exclude-libs=libgcc_stripped.a",
         "-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
         "-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
-        "-Wl,--exclude-libs=libclang_rt.builtins-x86-android.a",
+        "-Wl,--exclude-libs=libclang_rt.builtins-i686-android.a",
         "-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a",
     ],
 
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 772e7b8..af05027 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -328,7 +328,7 @@
     __libdl_info->ref_count_ = 1;
     __libdl_info->strtab_size_ = linker_si.strtab_size_;
     __libdl_info->local_group_root_ = __libdl_info;
-    __libdl_info->soname_ = linker_si.soname_.c_str();
+    __libdl_info->soname_ = linker_si.soname_;
     __libdl_info->target_sdk_version_ = __ANDROID_API__;
     __libdl_info->generate_handle();
 #if defined(__work_around_b_24465209__)
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 77824f6..3488f5c 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1242,7 +1242,7 @@
     return false;
   }
 
-  // find and set DT_RUNPATH and dt_soname
+  // Find and set DT_RUNPATH, DT_SONAME, and DT_FLAGS_1.
   // Note that these field values are temporary and are
   // going to be overwritten on soinfo::prelink_image
   // with values from PT_LOAD segments.
@@ -1254,6 +1254,10 @@
     if (d->d_tag == DT_SONAME) {
       si->set_soname(elf_reader.get_string(d->d_un.d_val));
     }
+    // We need to identify a DF_1_GLOBAL library early so we can link it to namespaces.
+    if (d->d_tag == DT_FLAGS_1) {
+      si->set_dt_flags_1(d->d_un.d_val);
+    }
   }
 
 #if !defined(__ANDROID__)
@@ -1552,6 +1556,7 @@
   });
 
   ZipArchiveCache zip_archive_cache;
+  soinfo_list_t new_global_group_members;
 
   // Step 1: expand the list of load_tasks to include
   // all DT_NEEDED libraries (do not load them just yet)
@@ -1586,13 +1591,31 @@
 
     // When ld_preloads is not null, the first
     // ld_preloads_count libs are in fact ld_preloads.
+    bool is_ld_preload = false;
     if (ld_preloads != nullptr && soinfos_count < ld_preloads_count) {
       ld_preloads->push_back(si);
+      is_ld_preload = true;
     }
 
     if (soinfos_count < library_names_count) {
       soinfos[soinfos_count++] = si;
     }
+
+    // Add the new global group members to all initial namespaces. Do this secondary namespace setup
+    // at the same time that libraries are added to their primary namespace so that the order of
+    // global group members is the same in the every namespace. Only add a library to a namespace
+    // once, even if it appears multiple times in the dependency graph.
+    if (is_ld_preload || (si->get_dt_flags_1() & DF_1_GLOBAL) != 0) {
+      if (!si->is_linked() && namespaces != nullptr && !new_global_group_members.contains(si)) {
+        new_global_group_members.push_back(si);
+        for (auto linked_ns : *namespaces) {
+          if (si->get_primary_namespace() != linked_ns) {
+            linked_ns->add_soinfo(si);
+            si->add_secondary_namespace(linked_ns);
+          }
+        }
+      }
+    }
   }
 
   // Step 2: Load libraries in random order (see b/24047022)
@@ -1649,39 +1672,15 @@
     register_soinfo_tls(si);
   }
 
-  // Step 4: Construct the global group. Note: DF_1_GLOBAL bit of a library is
-  // determined at step 3.
-
-  // Step 4-1: DF_1_GLOBAL bit is force set for LD_PRELOADed libs because they
-  // must be added to the global group
+  // Step 4: Construct the global group. DF_1_GLOBAL bit is force set for LD_PRELOADed libs because
+  // they must be added to the global group. Note: The DF_1_GLOBAL bit for a library is normally set
+  // in step 3.
   if (ld_preloads != nullptr) {
     for (auto&& si : *ld_preloads) {
       si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
     }
   }
 
-  // Step 4-2: Gather all DF_1_GLOBAL libs which were newly loaded during this
-  // run. These will be the new member of the global group
-  soinfo_list_t new_global_group_members;
-  for (auto&& task : load_tasks) {
-    soinfo* si = task->get_soinfo();
-    if (!si->is_linked() && (si->get_dt_flags_1() & DF_1_GLOBAL) != 0) {
-      new_global_group_members.push_back(si);
-    }
-  }
-
-  // Step 4-3: Add the new global group members to all the linked namespaces
-  if (namespaces != nullptr) {
-    for (auto linked_ns : *namespaces) {
-      for (auto si : new_global_group_members) {
-        if (si->get_primary_namespace() != linked_ns) {
-          linked_ns->add_soinfo(si);
-          si->add_secondary_namespace(linked_ns);
-        }
-      }
-    }
-  }
-
   // Step 5: Collect roots of local_groups.
   // Whenever needed_by->si link crosses a namespace boundary it forms its own local_group.
   // Here we collect new roots to link them separately later on. Note that we need to avoid
@@ -3193,26 +3192,27 @@
     return false;
   }
 
-  // second pass - parse entries relying on strtab
-  for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
-    switch (d->d_tag) {
-      case DT_SONAME:
-        set_soname(get_string(d->d_un.d_val));
-        break;
-      case DT_RUNPATH:
-        set_dt_runpath(get_string(d->d_un.d_val));
-        break;
+  // Second pass - parse entries relying on strtab. Skip this while relocating the linker so as to
+  // avoid doing heap allocations until later in the linker's initialization.
+  if (!relocating_linker) {
+    for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
+      switch (d->d_tag) {
+        case DT_SONAME:
+          set_soname(get_string(d->d_un.d_val));
+          break;
+        case DT_RUNPATH:
+          set_dt_runpath(get_string(d->d_un.d_val));
+          break;
+      }
     }
   }
 
-  // Before M release linker was using basename in place of soname.
-  // In the case when dt_soname is absent some apps stop working
-  // because they can't find dt_needed library by soname.
-  // This workaround should keep them working. (Applies only
-  // for apps targeting sdk version < M.) Make an exception for
-  // the main executable and linker; they do not need to have dt_soname.
-  // TODO: >= O the linker doesn't need this workaround.
-  if (soname_.empty() && this != solist_get_somain() && (flags_ & FLAG_LINKER) == 0 &&
+  // Before M release, linker was using basename in place of soname. In the case when DT_SONAME is
+  // absent some apps stop working because they can't find DT_NEEDED library by soname. This
+  // workaround should keep them working. (Applies only for apps targeting sdk version < M.) Make
+  // an exception for the main executable, which does not need to have DT_SONAME. The linker has an
+  // DT_SONAME but the soname_ field is initialized later on.
+  if (soname_.empty() && this != solist_get_somain() && !relocating_linker &&
       get_application_target_sdk_version() < 23) {
     soname_ = basename(realpath_.c_str());
     DL_WARN_documented_change(23, "missing-soname-enforced-for-api-level-23",
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 59e8036..0b501a7 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -725,6 +725,13 @@
   // Initialize the linker's own global variables
   tmp_linker_so.call_constructors();
 
+  // Setting the linker soinfo's soname can allocate heap memory, so delay it until here.
+  for (const ElfW(Dyn)* d = tmp_linker_so.dynamic; d->d_tag != DT_NULL; ++d) {
+    if (d->d_tag == DT_SONAME) {
+      tmp_linker_so.set_soname(tmp_linker_so.get_string(d->d_un.d_val));
+    }
+  }
+
   // When the linker is run directly rather than acting as PT_INTERP, parse
   // arguments and determine the executable to load. When it's instead acting
   // as PT_INTERP, AT_ENTRY will refer to the loaded executable rather than the
diff --git a/linker/linker_soinfo.cpp b/linker/linker_soinfo.cpp
index f44cb1c..287e757 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -485,11 +485,8 @@
 }
 
 template <typename F>
-static void call_array(const char* array_name __unused,
-                       F* functions,
-                       size_t count,
-                       bool reverse,
-                       const char* realpath) {
+static inline void call_array(const char* array_name __unused, F* functions, size_t count,
+                              bool reverse, const char* realpath) {
   if (functions == nullptr) {
     return;
   }
diff --git a/tests/Android.bp b/tests/Android.bp
index e7118b3..5840018 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -17,7 +17,6 @@
 cc_defaults {
     name: "bionic_tests_defaults",
     host_supported: true,
-    cpp_std: "experimental",
     target: {
         darwin: {
             enabled: false,
@@ -559,6 +558,7 @@
         "-U_FORTIFY_SOURCE",
     ],
     srcs: ["fortify_test_main.cpp"],
+    tidy: false,
     target: {
         host: {
             clang_cflags: ["-D__clang__"],
@@ -597,6 +597,7 @@
         "-D__clang_analyzer__",
     ],
     srcs: ["clang_fortify_tests.cpp"],
+    tidy: false,
 }
 
 cc_test_library {
@@ -638,6 +639,7 @@
         "-U_FORTIFY_SOURCE",
     ],
     srcs: ["clang_fortify_tests.cpp"],
+    tidy: false,
     target: {
         host: {
             clang_cflags: ["-D__clang__"],
@@ -845,66 +847,95 @@
         "elftls_dlopen_ie_error_helper",
         "exec_linker_helper",
         "exec_linker_helper_lib",
-        "libtest_dt_runpath_a",
-        "libtest_dt_runpath_b",
-        "libtest_dt_runpath_c",
-        "libtest_dt_runpath_x",
-        "libtest_dt_runpath_y",
+        "heap_tagging_async_helper",
+        "heap_tagging_disabled_helper",
+        "heap_tagging_static_async_helper",
+        "heap_tagging_static_disabled_helper",
+        "heap_tagging_static_sync_helper",
+        "heap_tagging_sync_helper",
+        "ld_config_test_helper",
+        "ld_config_test_helper_lib1",
+        "ld_config_test_helper_lib2",
+        "ld_config_test_helper_lib3",
+        "ld_preload_test_helper",
+        "ld_preload_test_helper_lib1",
+        "ld_preload_test_helper_lib2",
         "libatest_simple_zip",
         "libcfi-test",
         "libcfi-test-bad",
+        "libdl_preempt_test_1",
+        "libdl_preempt_test_2",
+        "libdl_test_df_1_global",
+        "libdlext_test",
         "libdlext_test_different_soname",
         "libdlext_test_fd",
         "libdlext_test_norelro",
         "libdlext_test_recursive",
         "libdlext_test_runpath_zip_zipaligned",
-        "libdlext_test",
         "libdlext_test_zip",
         "libdlext_test_zip_zipaligned",
-        "libdl_preempt_test_1",
-        "libdl_preempt_test_2",
-        "libdl_test_df_1_global",
         "libgnu-hash-table-library",
-        "librelocations-ANDROID_RELR",
+        "libns_hidden_child_app",
+        "libns_hidden_child_global",
+        "libns_hidden_child_internal",
+        "libns_hidden_child_public",
+        "libnstest_dlopened",
+        "libnstest_ns_a_public1",
+        "libnstest_ns_a_public1_internal",
+        "libnstest_ns_b_public2",
+        "libnstest_ns_b_public3",
+        "libnstest_private",
+        "libnstest_private_external",
+        "libnstest_public",
+        "libnstest_public_internal",
+        "libnstest_root",
+        "libnstest_root_not_isolated",
         "librelocations-ANDROID_REL",
+        "librelocations-ANDROID_RELR",
         "librelocations-RELR",
         "librelocations-fat",
+        "libsegment_gap_inner",
+        "libsegment_gap_outer",
         "libsysv-hash-table-library",
-        "libtestshared",
         "libtest_atexit",
+        "libtest_check_order_dlsym",
         "libtest_check_order_dlsym_1_left",
         "libtest_check_order_dlsym_2_right",
         "libtest_check_order_dlsym_3_c",
         "libtest_check_order_dlsym_a",
         "libtest_check_order_dlsym_b",
         "libtest_check_order_dlsym_d",
-        "libtest_check_order_dlsym",
+        "libtest_check_order_reloc_root",
         "libtest_check_order_reloc_root_1",
         "libtest_check_order_reloc_root_2",
-        "libtest_check_order_reloc_root",
+        "libtest_check_order_reloc_siblings",
         "libtest_check_order_reloc_siblings_1",
         "libtest_check_order_reloc_siblings_2",
         "libtest_check_order_reloc_siblings_3",
         "libtest_check_order_reloc_siblings_a",
         "libtest_check_order_reloc_siblings_b",
+        "libtest_check_order_reloc_siblings_c",
         "libtest_check_order_reloc_siblings_c_1",
         "libtest_check_order_reloc_siblings_c_2",
-        "libtest_check_order_reloc_siblings_c",
         "libtest_check_order_reloc_siblings_d",
         "libtest_check_order_reloc_siblings_e",
         "libtest_check_order_reloc_siblings_f",
-        "libtest_check_order_reloc_siblings",
         "libtest_check_rtld_next_from_library",
         "libtest_dlopen_df_1_global",
-        "libtest_dlopen_from_ctor_main",
         "libtest_dlopen_from_ctor",
+        "libtest_dlopen_from_ctor_main",
         "libtest_dlopen_weak_undefined_func",
         "libtest_dlsym_df_1_global",
+        "libtest_dlsym_from_this",
         "libtest_dlsym_from_this_child",
         "libtest_dlsym_from_this_grandchild",
-        "libtest_dlsym_from_this",
         "libtest_dlsym_weak_func",
+        "libtest_dt_runpath_a",
+        "libtest_dt_runpath_b",
+        "libtest_dt_runpath_c",
         "libtest_dt_runpath_d",
+        "libtest_dt_runpath_x",
+        "libtest_dt_runpath_y",
         "libtest_elftls_dynamic",
         "libtest_elftls_dynamic_filler_1",
         "libtest_elftls_dynamic_filler_2",
@@ -913,83 +944,60 @@
         "libtest_elftls_shared_var_ie",
         "libtest_elftls_tprel",
         "libtest_empty",
-        "libtest_ifunc_variable_impl",
-        "libtest_ifunc_variable",
         "libtest_ifunc",
+        "libtest_ifunc_variable",
+        "libtest_ifunc_variable_impl",
+        "libtest_indirect_thread_local_dtor",
         "libtest_init_fini_order_child",
         "libtest_init_fini_order_grand_child",
-        "libtest_init_fini_order_root2",
         "libtest_init_fini_order_root",
-        "libtest_missing_symbol_child_public",
-        "libtest_missing_symbol_child_private",
-        "libtest_missing_symbol_root",
+        "libtest_init_fini_order_root2",
+        "libtest_invalid-empty_shdr_table",
+        "libtest_invalid-rw_load_segment",
+        "libtest_invalid-textrels",
+        "libtest_invalid-textrels2",
+        "libtest_invalid-unaligned_shdr_offset",
+        "libtest_invalid-zero_shdr_table_content",
+        "libtest_invalid-zero_shdr_table_offset",
+        "libtest_invalid-zero_shentsize",
+        "libtest_invalid-zero_shstrndx",
         "libtest_missing_symbol",
+        "libtest_missing_symbol_child_private",
+        "libtest_missing_symbol_child_public",
+        "libtest_missing_symbol_root",
         "libtest_nodelete_1",
         "libtest_nodelete_2",
         "libtest_nodelete_dt_flags_1",
         "libtest_pthread_atfork",
+        "libtest_relo_check_dt_needed_order",
         "libtest_relo_check_dt_needed_order_1",
         "libtest_relo_check_dt_needed_order_2",
-        "libtest_relo_check_dt_needed_order",
         "libtest_simple",
+        "libtest_thread_local_dtor",
+        "libtest_thread_local_dtor2",
         "libtest_two_parents_child",
         "libtest_two_parents_parent1",
         "libtest_two_parents_parent2",
         "libtest_versioned_lib",
         "libtest_versioned_libv1",
         "libtest_versioned_libv2",
-        "libtest_versioned_otherlib_empty",
         "libtest_versioned_otherlib",
+        "libtest_versioned_otherlib_empty",
         "libtest_versioned_uselibv1",
-        "libtest_versioned_uselibv2_other",
         "libtest_versioned_uselibv2",
+        "libtest_versioned_uselibv2_other",
         "libtest_versioned_uselibv3_other",
+        "libtest_with_dependency",
+        "libtest_with_dependency_loop",
         "libtest_with_dependency_loop_a",
         "libtest_with_dependency_loop_b",
         "libtest_with_dependency_loop_c",
-        "libtest_with_dependency_loop",
-        "libtest_with_dependency",
-        "libtest_indirect_thread_local_dtor",
-        "libtest_invalid-empty_shdr_table",
-        "libtest_invalid-rw_load_segment",
-        "libtest_invalid-unaligned_shdr_offset",
-        "libtest_invalid-zero_shdr_table_content",
-        "libtest_invalid-zero_shdr_table_offset",
-        "libtest_invalid-zero_shentsize",
-        "libtest_invalid-zero_shstrndx",
-        "libtest_invalid-textrels",
-        "libtest_invalid-textrels2",
-        "libtest_thread_local_dtor",
-        "libtest_thread_local_dtor2",
+        "libtestshared",
+        "ns_hidden_child_helper",
         "preinit_getauxval_test_helper",
         "preinit_syscall_test_helper",
-        "libnstest_private_external",
-        "libnstest_dlopened",
-        "libnstest_private",
-        "libnstest_root_not_isolated",
-        "libnstest_root",
-        "libnstest_public",
-        "libnstest_public_internal",
-        "libnstest_ns_a_public1",
-        "libnstest_ns_a_public1_internal",
-        "libnstest_ns_b_public2",
-        "libnstest_ns_b_public3",
-        "ns_hidden_child_helper",
-        "libns_hidden_child_global",
-        "libns_hidden_child_internal",
-        "libns_hidden_child_public",
-        "libns_hidden_child_app",
-        "libsegment_gap_inner",
-        "libsegment_gap_outer",
-        "ld_preload_test_helper",
-        "ld_preload_test_helper_lib1",
-        "ld_preload_test_helper_lib2",
-        "ld_config_test_helper",
-        "ld_config_test_helper_lib1",
-        "ld_config_test_helper_lib2",
-        "ld_config_test_helper_lib3",
-        "tls_properties_helper",
         "thread_exit_cb_helper",
+        "tls_properties_helper",
     ],
 }
 
@@ -1008,6 +1016,10 @@
 
     // For now, these tests run forever, so do not use the isolation framework.
     isolated: false,
+    // Running forever, do not consider unit test.
+    test_options: {
+        unit_test: false,
+    },
 
     srcs: [
         "malloc_stress_test.cpp",
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index 6adba19..6c9bf3f 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -268,8 +268,16 @@
 }
 #endif
 
-// _lib1.so and _lib2.so are now searchable by having another namespace 'ns2'
+// lib1.so and lib2.so are now searchable by having another namespace 'ns2'
 // whose search paths include the 'ns2/' subdir.
+//
+// lib1.so is linked with DF_1_GLOBAL, so both it and the executable are added
+// to every namespace.
+//
+// namespace configuration ('*' indicates primary ns)
+//  - default: exe[*], lib1.so
+//  - ns2: exe, lib1.so[*], lib2.so[*]
+//
 TEST(dl, exec_with_ld_config_file) {
 #if defined(__BIONIC__)
   SKIP_WITH_HWASAN << "libclang_rt.hwasan is not found with custom ld config";
@@ -285,13 +293,28 @@
   ExecTestHelper eth;
   eth.SetArgs({ helper.c_str(), nullptr });
   eth.SetEnv({ env.c_str(), nullptr });
-  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, "12345");
+  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0,
+          "foo lib1\n"
+          "lib1_call_funcs\n"
+          "foo lib1\n"
+          "bar lib2\n");
 #endif
 }
 
-// _lib3.so has same symbol as lib2.so but returns 54321. _lib3.so is
-// LD_PRELOADed. This test is to ensure LD_PRELOADed libs are available to
-// additional namespaces other than the default namespace.
+// lib3.so has same foo and bar symbols as lib2.so. lib3.so is LD_PRELOADed.
+// This test ensures that LD_PRELOADed libs are available to all namespaces.
+//
+// namespace configuration ('*' indicates primary ns)
+//  - default: exe[*], lib3.so[*], lib1.so
+//  - ns2: exe, lib3.so, lib1.so[*], lib2.so[*]
+//
+// Ensure that, in both namespaces, a call to foo calls the lib3.so symbol,
+// which then calls the lib1.so symbol using RTLD_NEXT. Ensure that RTLD_NEXT
+// finds nothing when called from lib1.so.
+//
+// For the bar symbol, lib3.so's primary namespace is the default namespace, but
+// lib2.so is not in the default namespace, so using RTLD_NEXT from lib3.so
+// doesn't find the symbol in lib2.so.
 TEST(dl, exec_with_ld_config_file_with_ld_preload) {
 #if defined(__BIONIC__)
   SKIP_WITH_HWASAN << "libclang_rt.hwasan is not found with custom ld config";
@@ -308,7 +331,17 @@
   ExecTestHelper eth;
   eth.SetArgs({ helper.c_str(), nullptr });
   eth.SetEnv({ env.c_str(), env2.c_str(), nullptr });
-  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, "54321");
+  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0,
+          "foo lib3\n"
+          "foo lib1\n"
+          "lib1_call_funcs\n"
+          "foo lib3\n"
+          "foo lib1\n"
+          "bar lib3\n"
+          "lib3_call_funcs\n"
+          "foo lib3\n"
+          "foo lib1\n"
+          "bar lib3\n");
 #endif
 }
 
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 01bf8ab..e3caf0e 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -717,13 +717,12 @@
   uint64_t addr = reinterpret_cast<uint64_t>(ptr);
   std::string found_name = "<not found>";
 
-  EXPECT_TRUE(android::procinfo::ReadMapFile(
-      "/proc/self/maps",
-      [&](uint64_t start, uint64_t end, uint16_t, uint16_t, ino_t, const char* name) {
-        if (addr >= start && addr < end) {
-          found_name = name;
-        }
-      }));
+  EXPECT_TRUE(android::procinfo::ReadMapFile("/proc/self/maps",
+                                             [&](const android::procinfo::MapInfo& mapinfo) {
+                                               if (addr >= mapinfo.start && addr < mapinfo.end) {
+                                                 found_name = mapinfo.name;
+                                               }
+                                             }));
 
   return found_name;
 }
diff --git a/tests/eventfd_test.cpp b/tests/eventfd_test.cpp
index 3c303c2..eb423c1 100644
--- a/tests/eventfd_test.cpp
+++ b/tests/eventfd_test.cpp
@@ -51,7 +51,7 @@
   constexpr unsigned int kInitialValue = 2;
   int fd = eventfd(kInitialValue, EFD_CLOEXEC);
   ASSERT_NE(-1, fd);
-  AssertCloseOnExec(fd, true);
+  ASSERT_TRUE(CloseOnExec(fd));
 
   eventfd_t value = 123;
   ASSERT_EQ(0, eventfd_read(fd, &value));
@@ -61,7 +61,7 @@
 
   fd = eventfd(kInitialValue, EFD_NONBLOCK | EFD_CLOEXEC);
   ASSERT_NE(-1, fd);
-  AssertCloseOnExec(fd, true);
+  ASSERT_TRUE(CloseOnExec(fd));
 
   value = 123;
   ASSERT_EQ(0, eventfd_read(fd, &value));
diff --git a/tests/heap_tagging_level_test.cpp b/tests/heap_tagging_level_test.cpp
index 4f8f036..b3c8f22 100644
--- a/tests/heap_tagging_level_test.cpp
+++ b/tests/heap_tagging_level_test.cpp
@@ -15,10 +15,12 @@
  */
 
 #include <gtest/gtest.h>
+
+#include <malloc.h>
 #include <sys/prctl.h>
 
 #if defined(__BIONIC__)
-#include "platform/bionic/malloc.h"
+#include "gtest_globals.h"
 #include "platform/bionic/mte.h"
 #include "utils.h"
 
@@ -36,7 +38,7 @@
 }
 
 static bool SetHeapTaggingLevel(HeapTaggingLevel level) {
-  return android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &level, sizeof(level));
+  return mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, level);
 }
 #endif
 
@@ -90,7 +92,8 @@
 
   std::unique_ptr<int[]> p = std::make_unique<int[]>(4);
 
-  // First, check that memory tagging is enabled and the default tag checking level is async.
+  // First, check that memory tagging is enabled and the default tag checking level is sync.
+  // cc_test targets get sync MTE by default.
   // We assume that scudo is used on all MTE enabled hardware; scudo inserts a header with a
   // mismatching tag before each allocation.
   EXPECT_EXIT(
@@ -98,15 +101,15 @@
         ScopedSignalHandler ssh(SIGSEGV, ExitWithSiCode, SA_SIGINFO);
         p[-1] = 42;
       },
-      testing::ExitedWithCode(SEGV_MTEAERR), "");
+      testing::ExitedWithCode(SEGV_MTESERR), "");
 
-  EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_SYNC));
+  EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_ASYNC));
   EXPECT_EXIT(
       {
         ScopedSignalHandler ssh(SIGSEGV, ExitWithSiCode, SA_SIGINFO);
         p[-1] = 42;
       },
-      testing::ExitedWithCode(SEGV_MTESERR), "");
+      testing::ExitedWithCode(SEGV_MTEAERR), "");
 
   EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_NONE));
   volatile int oob ATTRIBUTE_UNUSED = p[-1];
@@ -177,3 +180,34 @@
   GTEST_SKIP() << "bionic/arm64 only";
 #endif
 }
+
+enum class MemtagNote { NONE, ASYNC, SYNC };
+class MemtagNoteTest : public testing::TestWithParam<std::tuple<MemtagNote, bool>> {};
+
+TEST_P(MemtagNoteTest, SEGV) {
+#if defined(__BIONIC__) && defined(__aarch64__)
+  if (!(getauxval(AT_HWCAP2) & HWCAP2_MTE)) {
+    GTEST_SKIP() << "requires MTE support";
+  }
+
+  const char* kNoteSuffix[] = {"disabled", "async", "sync"};
+  const char* kExpectedOutput[] = {"normal exit\n", "SEGV_MTEAERR\n", "SEGV_MTESERR\n"};
+
+  MemtagNote note = std::get<0>(GetParam());
+  bool isStatic = std::get<1>(GetParam());
+  std::string helper_base = std::string("heap_tagging_") + (isStatic ? "static_" : "") +
+                            kNoteSuffix[static_cast<int>(note)] + "_helper";
+  fprintf(stderr, "=== %s\n", helper_base.c_str());
+  std::string helper = GetTestlibRoot() + "/" + helper_base + "/" + helper_base;
+  chmod(helper.c_str(), 0755);
+  ExecTestHelper eth;
+  eth.SetArgs({helper.c_str(), nullptr});
+  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0,
+          kExpectedOutput[static_cast<int>(note)]);
+#endif
+}
+
+INSTANTIATE_TEST_SUITE_P(, MemtagNoteTest,
+                         testing::Combine(testing::Values(MemtagNote::NONE, MemtagNote::ASYNC,
+                                                          MemtagNote::SYNC),
+                                          testing::Bool()));
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 4b86faf..ba1c198 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -1478,6 +1478,8 @@
     srcs: ["ld_config_test_helper_lib1.cpp"],
     shared_libs: ["ld_config_test_helper_lib2"],
     relative_install_path: "bionic-loader-test-libs/ns2",
+    // Mark the library DF_1_GLOBAL so it is added to every linker namespace.
+    ldflags: ["-Wl,-z,global"]
 }
 
 cc_test_library {
@@ -1579,3 +1581,85 @@
     defaults: ["bionic_testlib_defaults"],
     srcs: ["relocations.cpp"],
 }
+
+cc_defaults {
+  name: "bionic_targets_only",
+  enabled: false,
+  target: {
+     android: {
+       enabled: true,
+     },
+     linux_bionic: {
+       enabled: true,
+     },
+   },
+}
+
+cc_test {
+   name: "heap_tagging_sync_helper",
+   defaults: ["bionic_testlib_defaults", "bionic_targets_only"],
+   srcs: ["heap_tagging_helper.cpp"],
+   sanitize: {
+     memtag_heap: true,
+     diag: {
+       memtag_heap: true,
+     },
+   },
+}
+
+cc_test {
+   name: "heap_tagging_async_helper",
+   defaults: ["bionic_testlib_defaults", "bionic_targets_only"],
+   srcs: ["heap_tagging_helper.cpp"],
+   sanitize: {
+     memtag_heap: true,
+     diag: {
+       memtag_heap: false,
+     },
+   },
+}
+
+cc_test {
+   name: "heap_tagging_disabled_helper",
+   defaults: ["bionic_testlib_defaults", "bionic_targets_only"],
+   srcs: ["heap_tagging_helper.cpp"],
+   sanitize: {
+     memtag_heap: false,
+   },
+}
+
+cc_test {
+   name: "heap_tagging_static_sync_helper",
+   defaults: ["bionic_testlib_defaults", "bionic_targets_only"],
+   srcs: ["heap_tagging_helper.cpp"],
+   static_executable: true,
+   sanitize: {
+     memtag_heap: true,
+     diag: {
+       memtag_heap: true,
+     },
+   },
+}
+
+cc_test {
+   name: "heap_tagging_static_async_helper",
+   defaults: ["bionic_testlib_defaults", "bionic_targets_only"],
+   srcs: ["heap_tagging_helper.cpp"],
+   static_executable: true,
+   sanitize: {
+     memtag_heap: true,
+     diag: {
+       memtag_heap: false,
+     },
+   },
+}
+
+cc_test {
+   name: "heap_tagging_static_disabled_helper",
+   defaults: ["bionic_testlib_defaults", "bionic_targets_only"],
+   srcs: ["heap_tagging_helper.cpp"],
+   static_executable: true,
+   sanitize: {
+     memtag_heap: false,
+   },
+}
diff --git a/tests/libs/heap_tagging_helper.cpp b/tests/libs/heap_tagging_helper.cpp
new file mode 100644
index 0000000..1a970f2
--- /dev/null
+++ b/tests/libs/heap_tagging_helper.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <signal.h>
+#include <stdio.h>
+#include <sys/cdefs.h>
+#include <unistd.h>
+#include <memory>
+
+void action(int signo, siginfo_t* info __unused, void*) {
+#ifdef __ANDROID__
+  if (signo == 11 && info->si_code == SEGV_MTEAERR) {
+    fprintf(stderr, "SEGV_MTEAERR\n");
+    _exit(0);
+  }
+
+  if (signo == 11 && info->si_code == SEGV_MTESERR) {
+    fprintf(stderr, "SEGV_MTESERR\n");
+    _exit(0);
+  }
+#endif
+
+  fprintf(stderr, "signo %d\n", signo);
+  _exit(0);
+}
+
+__attribute__((optnone)) int main() {
+  struct sigaction sa = {};
+  sa.sa_sigaction = action;
+  sa.sa_flags = SA_SIGINFO;
+  sigaction(SIGSEGV, &sa, nullptr);
+
+  std::unique_ptr<int[]> p = std::make_unique<int[]>(4);
+  volatile int oob = p[-1];
+  (void)oob;
+
+  fprintf(stderr, "normal exit\n");
+  return 0;
+}
diff --git a/tests/libs/ld_config_test_helper.cpp b/tests/libs/ld_config_test_helper.cpp
index 87e512e..1249121 100644
--- a/tests/libs/ld_config_test_helper.cpp
+++ b/tests/libs/ld_config_test_helper.cpp
@@ -22,7 +22,9 @@
 #endif
 #include <unistd.h>
 
-extern int get_value_from_lib();
+extern "C" void foo();
+void lib1_call_funcs();
+__attribute__((weak)) void lib3_call_funcs();
 
 int main() {
   bool skip_vdso_check = false;
@@ -45,6 +47,9 @@
     dlclose(handle);
   }
 
-  printf("%d", get_value_from_lib());
+  foo();
+  lib1_call_funcs();
+  if (lib3_call_funcs) lib3_call_funcs();
+
   return 0;
 }
diff --git a/tests/libs/ld_config_test_helper_lib1.cpp b/tests/libs/ld_config_test_helper_lib1.cpp
index fc5401a..ffa9a45 100644
--- a/tests/libs/ld_config_test_helper_lib1.cpp
+++ b/tests/libs/ld_config_test_helper_lib1.cpp
@@ -1,4 +1,19 @@
-extern int get_value_from_another_lib();
-int get_value_from_lib() {
-  return get_value_from_another_lib();
+#include <dlfcn.h>
+#include <stdio.h>
+
+// Mark foo and bar weak so that Clang allows the run-time linker to decide which DSO's symbol to
+// use.
+
+__attribute__((weak)) extern "C" void foo() {
+  printf("foo lib1\n");
+  void (*next)(void) = reinterpret_cast<void (*)()>(dlsym(RTLD_NEXT, "foo"));
+  if (next != nullptr) next();
+}
+
+__attribute__((weak)) extern "C" void bar();
+
+void lib1_call_funcs() {
+  printf("lib1_call_funcs\n");
+  foo();
+  bar();
 }
diff --git a/tests/libs/ld_config_test_helper_lib2.cpp b/tests/libs/ld_config_test_helper_lib2.cpp
index a620a6c..d5bca2c 100644
--- a/tests/libs/ld_config_test_helper_lib2.cpp
+++ b/tests/libs/ld_config_test_helper_lib2.cpp
@@ -1,3 +1,11 @@
-int get_value_from_another_lib() {
-  return 12345;
+#include <dlfcn.h>
+#include <stdio.h>
+
+// Mark foo and bar weak so that Clang allows the run-time linker to decide which DSO's symbol to
+// use.
+
+__attribute__((weak)) extern "C" void bar() {
+  printf("bar lib2\n");
+  void (*next)(void) = reinterpret_cast<void (*)()>(dlsym(RTLD_NEXT, "bar"));
+  if (next != nullptr) next();
 }
diff --git a/tests/libs/ld_config_test_helper_lib3.cpp b/tests/libs/ld_config_test_helper_lib3.cpp
index 93d1cd8..94e1570 100644
--- a/tests/libs/ld_config_test_helper_lib3.cpp
+++ b/tests/libs/ld_config_test_helper_lib3.cpp
@@ -1,3 +1,23 @@
-int get_value_from_another_lib() {
-  return 54321;
+#include <dlfcn.h>
+#include <stdio.h>
+
+// Mark foo and bar weak so that Clang allows the run-time linker to decide which DSO's symbol to
+// use.
+
+__attribute__((weak)) extern "C" void foo() {
+  printf("foo lib3\n");
+  void (*next)(void) = reinterpret_cast<void (*)()>(dlsym(RTLD_NEXT, "foo"));
+  if (next != nullptr) next();
+}
+
+__attribute__((weak)) extern "C" void bar() {
+  printf("bar lib3\n");
+  void (*next)(void) = reinterpret_cast<void (*)()>(dlsym(RTLD_NEXT, "bar"));
+  if (next != nullptr) next();
+}
+
+void lib3_call_funcs() {
+  printf("lib3_call_funcs\n");
+  foo();
+  bar();
 }
diff --git a/tests/make_fortify_compile_test.mk b/tests/make_fortify_compile_test.mk
index 8270f29..c36dfdd 100644
--- a/tests/make_fortify_compile_test.mk
+++ b/tests/make_fortify_compile_test.mk
@@ -9,6 +9,7 @@
 
 LOCAL_CLANG := true
 LOCAL_MODULE := bionic-compile-time-tests$(FORTIFY_LEVEL)-clang++
+LOCAL_TIDY := false
 LOCAL_CPPFLAGS := -Wall -Wno-error
 LOCAL_CPPFLAGS += -fno-color-diagnostics -ferror-limit=10000 -Xclang -verify
 LOCAL_CPPFLAGS += -DCOMPILATION_TESTS=1 -Wformat-nonliteral
diff --git a/tests/malloc_iterate_test.cpp b/tests/malloc_iterate_test.cpp
index 738a57b..e896c90 100644
--- a/tests/malloc_iterate_test.cpp
+++ b/tests/malloc_iterate_test.cpp
@@ -95,7 +95,8 @@
   test_data->total_allocated_bytes = 0;
 
   // Find all of the maps that are from the native allocator.
-  auto callback = [&](uint64_t start, uint64_t end, uint16_t, uint64_t, ino_t, const char* name) {
+  auto callback = [&](uint64_t start, uint64_t end, uint16_t, uint64_t, ino_t, const char* name,
+                      bool) {
     if (strcmp(name, "[anon:libc_malloc]") == 0 || strncmp(name, "[anon:scudo:", 12) == 0 ||
         strncmp(name, "[anon:GWP-ASan", 14) == 0) {
       malloc_iterate(start, end - start, SavePointers, test_data);
@@ -192,7 +193,8 @@
   TestDataType test_data = {};
 
   // Only attempt to get memory data for maps that are not from the native allocator.
-  auto callback = [&](uint64_t start, uint64_t end, uint16_t, uint64_t, ino_t, const char* name) {
+  auto callback = [&](uint64_t start, uint64_t end, uint16_t, uint64_t, ino_t, const char* name,
+                      bool) {
     if (strcmp(name, "[anon:libc_malloc]") != 0 && strncmp(name, "[anon:scudo:", 12) != 0 &&
         strncmp(name, "[anon:GWP-ASan", 14) != 0) {
       size_t total = test_data.total_allocated_bytes;
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index bddd9ab..3a09258 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -32,8 +32,10 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include <algorithm>
 #include <atomic>
 #include <thread>
+#include <vector>
 
 #include <tinyxml2.h>
 
@@ -1256,7 +1258,67 @@
 #endif
 }
 
-TEST(android_mallopt, disable_memory_mitigations) {
+void TestHeapZeroing(int num_iterations, int (*get_alloc_size)(int iteration)) {
+  std::vector<void*> allocs;
+  constexpr int kMaxBytesToCheckZero = 64;
+  const char kBlankMemory[kMaxBytesToCheckZero] = {};
+
+  for (int i = 0; i < num_iterations; ++i) {
+    int size = get_alloc_size(i);
+    allocs.push_back(malloc(size));
+    memset(allocs.back(), 'X', std::min(size, kMaxBytesToCheckZero));
+  }
+
+  for (void* alloc : allocs) {
+    free(alloc);
+  }
+  allocs.clear();
+
+  for (int i = 0; i < num_iterations; ++i) {
+    int size = get_alloc_size(i);
+    allocs.push_back(malloc(size));
+    ASSERT_EQ(0, memcmp(allocs.back(), kBlankMemory, std::min(size, kMaxBytesToCheckZero)));
+  }
+
+  for (void* alloc : allocs) {
+    free(alloc);
+  }
+}
+
+TEST(malloc, zero_init) {
+#if defined(__BIONIC__)
+  SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
+  bool allocator_scudo;
+  GetAllocatorVersion(&allocator_scudo);
+  if (!allocator_scudo) {
+    GTEST_SKIP() << "scudo allocator only test";
+  }
+
+  mallopt(M_BIONIC_ZERO_INIT, 1);
+
+  // Test using a block of 4K small (1-32 byte) allocations.
+  TestHeapZeroing(/* num_iterations */ 0x1000, [](int iteration) -> int {
+    return 1 + iteration % 32;
+  });
+
+  // Also test large allocations that land in the scudo secondary, as this is
+  // the only part of Scudo that's changed by enabling zero initialization with
+  // MTE. Uses 32 allocations, totalling 60MiB memory. Decay time (time to
+  // release secondary allocations back to the OS) was modified to 0ms/1ms by
+  // mallopt_decay. Ensure that we delay for at least a second before releasing
+  // pages to the OS in order to avoid implicit zeroing by the kernel.
+  mallopt(M_DECAY_TIME, 1000);
+  TestHeapZeroing(/* num_iterations */ 32, [](int iteration) -> int {
+    return 1 << (19 + iteration % 4);
+  });
+
+#else
+  GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
+// Note that MTE is enabled on cc_tests on devices that support MTE.
+TEST(malloc, disable_mte) {
 #if defined(__BIONIC__)
   if (!mte_supported()) {
     GTEST_SKIP() << "This function can only be tested with MTE";
@@ -1275,7 +1337,7 @@
                    },
                    &sem));
 
-  ASSERT_TRUE(android_mallopt(M_DISABLE_MEMORY_MITIGATIONS, nullptr, 0));
+  ASSERT_EQ(1, mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, M_HEAP_TAGGING_LEVEL_NONE));
   ASSERT_EQ(0, sem_post(&sem));
 
   int my_tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index f465458..ffbb667 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -803,15 +803,13 @@
 #endif
 
 TEST(signal, sigset_size) {
-  // The setjmp implementations for ARM, AArch64, x86, and x86_64 assume that sigset_t can fit in a
-  // long. This is true because ARM and x86 have broken rt signal support, and AArch64 and x86_64
-  // both have a SIGRTMAX defined as 64.
-#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__)
+  // The setjmp implementations assume that sigset_t can fit in a
+  // long. This is true because ARM and x86 have broken rt signal support,
+  // and AArch64 and x86_64 both have a SIGRTMAX defined as 64.
 #if defined(__BIONIC__)
   static_assert(sizeof(sigset_t) <= sizeof(long), "sigset_t doesn't fit in a long");
 #endif
   static_assert(sizeof(sigset64_t)*8 >= 64, "sigset64_t too small for real-time signals");
-#endif
 }
 
 TEST(signal, sigignore_EINVAL) {
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 5680f95..afbbf26 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -1956,34 +1956,64 @@
 #endif
 }
 
-TEST(STDIO_TEST, fdopen_CLOEXEC) {
-  int fd = open("/proc/version", O_RDONLY);
-  ASSERT_TRUE(fd != -1);
-
+TEST(STDIO_TEST, fdopen_add_CLOEXEC) {
   // This fd doesn't have O_CLOEXEC...
-  AssertCloseOnExec(fd, false);
-
-  FILE* fp = fdopen(fd, "re");
-  ASSERT_TRUE(fp != nullptr);
-
+  int fd = open("/proc/version", O_RDONLY);
+  ASSERT_FALSE(CloseOnExec(fd));
   // ...but the new one does.
-  AssertCloseOnExec(fileno(fp), true);
+  FILE* fp = fdopen(fd, "re");
+  ASSERT_TRUE(CloseOnExec(fileno(fp)));
+  fclose(fp);
+}
+
+TEST(STDIO_TEST, fdopen_remove_CLOEXEC) {
+  // This fd has O_CLOEXEC...
+  int fd = open("/proc/version", O_RDONLY | O_CLOEXEC);
+  ASSERT_TRUE(CloseOnExec(fd));
+  // ...but the new one doesn't.
+  FILE* fp = fdopen(fd, "r");
+  ASSERT_TRUE(CloseOnExec(fileno(fp)));
+  fclose(fp);
+}
+
+TEST(STDIO_TEST, freopen_add_CLOEXEC) {
+  // This FILE* doesn't have O_CLOEXEC...
+  FILE* fp = fopen("/proc/version", "r");
+  ASSERT_FALSE(CloseOnExec(fileno(fp)));
+  // ...but the new one does.
+  fp = freopen("/proc/version", "re", fp);
+  ASSERT_TRUE(CloseOnExec(fileno(fp)));
 
   fclose(fp);
 }
 
-TEST(STDIO_TEST, freopen_CLOEXEC) {
-  FILE* fp = fopen("/proc/version", "r");
-  ASSERT_TRUE(fp != nullptr);
+TEST(STDIO_TEST, freopen_remove_CLOEXEC) {
+  // This FILE* has O_CLOEXEC...
+  FILE* fp = fopen("/proc/version", "re");
+  ASSERT_TRUE(CloseOnExec(fileno(fp)));
+  // ...but the new one doesn't.
+  fp = freopen("/proc/version", "r", fp);
+  ASSERT_FALSE(CloseOnExec(fileno(fp)));
+  fclose(fp);
+}
 
+TEST(STDIO_TEST, freopen_null_filename_add_CLOEXEC) {
   // This FILE* doesn't have O_CLOEXEC...
-  AssertCloseOnExec(fileno(fp), false);
-
-  fp = freopen("/proc/version", "re", fp);
-
+  FILE* fp = fopen("/proc/version", "r");
+  ASSERT_FALSE(CloseOnExec(fileno(fp)));
   // ...but the new one does.
-  AssertCloseOnExec(fileno(fp), true);
+  fp = freopen(nullptr, "re", fp);
+  ASSERT_TRUE(CloseOnExec(fileno(fp)));
+  fclose(fp);
+}
 
+TEST(STDIO_TEST, freopen_null_filename_remove_CLOEXEC) {
+  // This FILE* has O_CLOEXEC...
+  FILE* fp = fopen("/proc/version", "re");
+  ASSERT_TRUE(CloseOnExec(fileno(fp)));
+  // ...but the new one doesn't.
+  fp = freopen(nullptr, "r", fp);
+  ASSERT_FALSE(CloseOnExec(fileno(fp)));
   fclose(fp);
 }
 
@@ -2883,3 +2913,24 @@
   char buf[L_tmpnam];
   tmpnam_test(buf);
 }
+
+TEST(STDIO_TEST, freopen_null_filename_mode) {
+  TemporaryFile tf;
+  FILE* fp = fopen(tf.path, "r");
+  ASSERT_TRUE(fp != nullptr);
+
+  // "r" = O_RDONLY
+  char buf[1];
+  ASSERT_EQ(0, read(fileno(fp), buf, 1));
+  ASSERT_EQ(-1, write(fileno(fp), "hello", 1));
+  // "r+" = O_RDWR
+  fp = freopen(nullptr, "r+", fp);
+  ASSERT_EQ(0, read(fileno(fp), buf, 1));
+  ASSERT_EQ(1, write(fileno(fp), "hello", 1));
+  // "w" = O_WRONLY
+  fp = freopen(nullptr, "w", fp);
+  ASSERT_EQ(-1, read(fileno(fp), buf, 1));
+  ASSERT_EQ(1, write(fileno(fp), "hello", 1));
+
+  fclose(fp);
+}
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index c7b2ad8..bb1fd7c 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -456,12 +456,12 @@
 
 TEST(stdlib, mkostemp64) {
   MyTemporaryFile tf([](char* path) { return mkostemp64(path, O_CLOEXEC); });
-  AssertCloseOnExec(tf.fd, true);
+  ASSERT_TRUE(CloseOnExec(tf.fd));
 }
 
 TEST(stdlib, mkostemp) {
   MyTemporaryFile tf([](char* path) { return mkostemp(path, O_CLOEXEC); });
-  AssertCloseOnExec(tf.fd, true);
+  ASSERT_TRUE(CloseOnExec(tf.fd));
 }
 
 TEST(stdlib, mkstemp64) {
diff --git a/tests/sys_epoll_test.cpp b/tests/sys_epoll_test.cpp
index 18cf380..fb2a48f 100644
--- a/tests/sys_epoll_test.cpp
+++ b/tests/sys_epoll_test.cpp
@@ -83,14 +83,14 @@
 TEST(sys_epoll, epoll_create1) {
   int fd;
   fd = epoll_create(1);
-  AssertCloseOnExec(fd, false);
+  ASSERT_FALSE(CloseOnExec(fd));
   close(fd);
 
   fd = epoll_create1(0);
-  AssertCloseOnExec(fd, false);
+  ASSERT_FALSE(CloseOnExec(fd));
   close(fd);
 
   fd = epoll_create1(EPOLL_CLOEXEC);
-  AssertCloseOnExec(fd, true);
+  ASSERT_TRUE(CloseOnExec(fd));
   close(fd);
 }
diff --git a/tests/sys_socket_test.cpp b/tests/sys_socket_test.cpp
index 0342547..421a817 100644
--- a/tests/sys_socket_test.cpp
+++ b/tests/sys_socket_test.cpp
@@ -109,7 +109,7 @@
   ASSERT_NE(fd_acc, -1) << strerror(errno);
 
   // Check that SOCK_CLOEXEC was set properly.
-  AssertCloseOnExec(fd_acc, true);
+  ASSERT_TRUE(CloseOnExec(fd_acc));
 
   close(fd_acc);
 }
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index b1de0a4..93ba426 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -851,11 +851,11 @@
 }
 
 TEST(time, clock) {
-  // clock(3) is hard to test, but a 1s sleep should cost less than 5ms.
+  // clock(3) is hard to test, but a 1s sleep should cost less than 10ms.
   clock_t t0 = clock();
   sleep(1);
   clock_t t1 = clock();
-  ASSERT_LT(t1 - t0, 5 * (CLOCKS_PER_SEC / 1000));
+  ASSERT_LT(t1 - t0, 10 * (CLOCKS_PER_SEC / 1000));
 }
 
 static pid_t GetInvalidPid() {
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 41ca8b4..595ba90 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -1166,10 +1166,10 @@
 TEST(UNISTD_TEST, dup3) {
   int fd = open("/proc/version", O_RDONLY);
   ASSERT_EQ(666, dup3(fd, 666, 0));
-  AssertCloseOnExec(666, false);
+  ASSERT_FALSE(CloseOnExec(666));
   close(666);
   ASSERT_EQ(667, dup3(fd, 667, O_CLOEXEC));
-  AssertCloseOnExec(667, true);
+  ASSERT_TRUE(CloseOnExec(667));
   close(667);
   close(fd);
 }
diff --git a/tests/utils.h b/tests/utils.h
index 94ff050..145ba1a 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -185,10 +185,14 @@
   }
 }
 
-static inline void AssertCloseOnExec(int fd, bool close_on_exec) {
+static inline bool CloseOnExec(int fd) {
   int flags = fcntl(fd, F_GETFD);
-  ASSERT_NE(flags, -1);
-  ASSERT_EQ(close_on_exec ? FD_CLOEXEC : 0, flags & FD_CLOEXEC);
+  // This isn't ideal, but the alternatives are worse:
+  // * If we return void and use ASSERT_NE here, we get failures at utils.h:191
+  //   rather than in the relevant test.
+  // * If we ignore failures of fcntl(), well, that's obviously a bad idea.
+  if (flags == -1) abort();
+  return flags & FD_CLOEXEC;
 }
 
 // The absolute path to the executable
diff --git a/tools/Android.bp b/tools/Android.bp
index c540c3c..dfeea19 100644
--- a/tools/Android.bp
+++ b/tools/Android.bp
@@ -3,4 +3,5 @@
 filegroup {
     name: "bionic-generate-version-script",
     srcs: ["generate-version-script.py"],
+    bazel_module: { bp2build_available: true },
 }
diff --git a/tools/update_notice.sh b/tools/update_notice.sh
index a309bc2..302974f 100755
--- a/tools/update_notice.sh
+++ b/tools/update_notice.sh
@@ -1,7 +1,11 @@
 #!/bin/bash
 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
 cd $DIR/..
-./libc/tools/generate-NOTICE.py libc libm > libc/NOTICE
+python3 ./libc/tools/generate_notice.py libc libm > libc/NOTICE
+if [ $? -ne 0 ]; then
+  >&2 echo NOTICE file generation failed
+  exit 1
+fi
 
 git diff --exit-code HEAD libc/NOTICE
 exit $?