Merge "Reland "Tidy up and document <limits.h>."" into main
diff --git a/libc/Android.bp b/libc/Android.bp
index ae6df52..d9b3658 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -353,7 +353,6 @@
         "-Wno-unused-parameter",
         "-include netbsd-compat.h",
         "-Wframe-larger-than=66000",
-        "-include private/bsd_sys_param.h",
     ],
 
     local_include_dirs: [
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
index 0d557f1..1b539f2 100644
--- a/libc/bionic/__libc_init_main_thread.cpp
+++ b/libc/bionic/__libc_init_main_thread.cpp
@@ -44,7 +44,7 @@
 // Declared in "private/bionic_ssp.h".
 uintptr_t __stack_chk_guard = 0;
 
-BIONIC_USED_BEFORE_LINKER_RELOCATES static pthread_internal_t main_thread;
+static pthread_internal_t main_thread;
 
 // Setup for the main thread. For dynamic executables, this is called by the
 // linker _before_ libc is mapped in memory. This means that all writes to
diff --git a/libc/bionic/bionic_call_ifunc_resolver.cpp b/libc/bionic/bionic_call_ifunc_resolver.cpp
index d5a812c..e44d998 100644
--- a/libc/bionic/bionic_call_ifunc_resolver.cpp
+++ b/libc/bionic/bionic_call_ifunc_resolver.cpp
@@ -31,7 +31,6 @@
 #include <sys/hwprobe.h>
 #include <sys/ifunc.h>
 
-#include "bionic/macros.h"
 #include "private/bionic_auxv.h"
 
 // This code is called in the linker before it has been relocated, so minimize calls into other
@@ -41,8 +40,8 @@
 ElfW(Addr) __bionic_call_ifunc_resolver(ElfW(Addr) resolver_addr) {
 #if defined(__aarch64__)
   typedef ElfW(Addr) (*ifunc_resolver_t)(uint64_t, __ifunc_arg_t*);
-  BIONIC_USED_BEFORE_LINKER_RELOCATES static __ifunc_arg_t arg;
-  BIONIC_USED_BEFORE_LINKER_RELOCATES static bool initialized = false;
+  static __ifunc_arg_t arg;
+  static bool initialized = false;
   if (!initialized) {
     initialized = true;
     arg._size = sizeof(__ifunc_arg_t);
diff --git a/libc/bionic/fts.c b/libc/bionic/fts.c
index 1287267..c36835e 100644
--- a/libc/bionic/fts.c
+++ b/libc/bionic/fts.c
@@ -29,7 +29,6 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/param.h>	/* ALIGN */
 #include <sys/stat.h>
 
 #include <dirent.h>
@@ -37,6 +36,7 @@
 #include <fcntl.h>
 #include <fts.h>
 #include <limits.h>
+#include <stdalign.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -912,10 +912,14 @@
 	 * be careful that the stat structure is reasonably aligned.  Since the
 	 * fts_name field is declared to be of size 1, the fts_name pointer is
 	 * namelen + 2 before the first possible address of the stat structure.
+	 *
+	 * We can't use the same trick FreeBSD uses here because our fts_name
+	 * is a char[1] rather than a char*. This is also the reason we don't
+	 * need to say `namelen + 1`. We just assume the worst alignment.
 	 */
 	len = sizeof(FTSENT) + namelen;
 	if (!ISSET(FTS_NOSTAT))
-		len += sizeof(struct stat) + ALIGNBYTES;
+		len += alignof(struct stat) + sizeof(struct stat);
 	if ((p = calloc(1, len)) == NULL)
 		return (NULL);
 
@@ -923,7 +927,7 @@
 	p->fts_namelen = namelen;
 	p->fts_instr = FTS_NOINSTR;
 	if (!ISSET(FTS_NOSTAT))
-		p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2);
+		p->fts_statp = (struct stat *)__builtin_align_up(p->fts_name + namelen + 2, alignof(struct stat));
 	memcpy(p->fts_name, name, namelen);
 
 	return (p);
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index ae86da1..7c46113 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -344,12 +344,19 @@
 // This function is called from the linker before the main executable is relocated.
 __attribute__((no_sanitize("hwaddress", "memtag"))) void __libc_init_mte(
     const memtag_dynamic_entries_t* memtag_dynamic_entries, const void* phdr_start, size_t phdr_ct,
-    uintptr_t load_bias) {
+    uintptr_t load_bias, void* stack_top) {
   bool memtag_stack = false;
   HeapTaggingLevel level =
       __get_tagging_level(memtag_dynamic_entries, phdr_start, phdr_ct, load_bias, &memtag_stack);
-  __libc_shared_globals()->initial_memtag_stack = memtag_stack;
-
+  // initial_memtag_stack is used by the linker (in linker.cpp) to communicate than any library
+  // linked by this executable enables memtag-stack.
+  // memtag_stack is also set for static executables if they request memtag stack via the note,
+  // in which case it will differ from initial_memtag_stack.
+  if (__libc_shared_globals()->initial_memtag_stack || memtag_stack) {
+    memtag_stack = true;
+    __libc_shared_globals()->initial_memtag_stack_abi = true;
+    __get_bionic_tcb()->tls_slot(TLS_SLOT_STACK_MTE) = __allocate_stack_mte_ringbuffer(0, nullptr);
+  }
   if (int64_t timed_upgrade = __get_memtag_upgrade_secs()) {
     if (level == M_HEAP_TAGGING_LEVEL_ASYNC) {
       async_safe_format_log(ANDROID_LOG_INFO, "libc",
@@ -373,7 +380,15 @@
     if (prctl(PR_SET_TAGGED_ADDR_CTRL, prctl_arg | PR_MTE_TCF_SYNC, 0, 0, 0) == 0 ||
         prctl(PR_SET_TAGGED_ADDR_CTRL, prctl_arg, 0, 0, 0) == 0) {
       __libc_shared_globals()->initial_heap_tagging_level = level;
+      __libc_shared_globals()->initial_memtag_stack = memtag_stack;
 
+      if (memtag_stack) {
+        void* pg_start =
+            reinterpret_cast<void*>(page_start(reinterpret_cast<uintptr_t>(stack_top)));
+        if (mprotect(pg_start, page_size(), PROT_READ | PROT_WRITE | PROT_MTE | PROT_GROWSDOWN)) {
+          async_safe_fatal("error: failed to set PROT_MTE on main thread stack: %m");
+        }
+      }
       struct sigaction action = {};
       action.sa_flags = SA_SIGINFO | SA_RESTART;
       action.sa_sigaction = __enable_mte_signal_handler;
@@ -389,36 +404,11 @@
   }
   // We did not enable MTE, so we do not need to arm the upgrade timer.
   __libc_shared_globals()->heap_tagging_upgrade_timer_sec = 0;
+  // We also didn't enable memtag_stack.
+  __libc_shared_globals()->initial_memtag_stack = false;
 }
-
-// Figure out whether we need to map the stack as PROT_MTE.
-// For dynamic executables, this has to be called after loading all
-// DT_NEEDED libraries, in case one of them needs stack MTE.
-__attribute__((no_sanitize("hwaddress", "memtag"))) void __libc_init_mte_stack(void* stack_top) {
-  if (!__libc_shared_globals()->initial_memtag_stack) {
-    return;
-  }
-
-  // Even if the device doesn't support MTE, we have to allocate stack
-  // history buffers for code compiled for stack MTE. That is because the
-  // codegen expects a buffer to be present in TLS_SLOT_STACK_MTE either
-  // way.
-  __libc_shared_globals()->initial_memtag_stack_abi = true;
-  __get_bionic_tcb()->tls_slot(TLS_SLOT_STACK_MTE) = __allocate_stack_mte_ringbuffer(0, nullptr);
-
-  if (!__libc_mte_enabled()) {
-    __libc_shared_globals()->initial_memtag_stack = false;
-    return;
-  }
-  void* pg_start = reinterpret_cast<void*>(page_start(reinterpret_cast<uintptr_t>(stack_top)));
-  if (mprotect(pg_start, page_size(), PROT_READ | PROT_WRITE | PROT_MTE | PROT_GROWSDOWN)) {
-    async_safe_fatal("error: failed to set PROT_MTE on main thread stack: %m");
-  }
-}
-
 #else   // __aarch64__
-void __libc_init_mte(const memtag_dynamic_entries_t*, const void*, size_t, uintptr_t) {}
-void __libc_init_mte_stack(void*) {}
+void __libc_init_mte(const memtag_dynamic_entries_t*, const void*, size_t, uintptr_t, void*) {}
 #endif  // __aarch64__
 
 void __libc_init_profiling_handlers() {
@@ -446,8 +436,7 @@
   __libc_init_common();
   __libc_init_mte(/*memtag_dynamic_entries=*/nullptr,
                   reinterpret_cast<ElfW(Phdr)*>(getauxval(AT_PHDR)), getauxval(AT_PHNUM),
-                  /*load_bias = */ 0);
-  __libc_init_mte_stack(/*stack_top = */ raw_args);
+                  /*load_bias = */ 0, /*stack_top = */ raw_args);
   __libc_init_scudo();
   __libc_init_profiling_handlers();
   __libc_init_fork_handler();
@@ -519,11 +508,6 @@
 // compiled with -ffreestanding to avoid implicit string.h function calls. (It shouldn't strictly
 // be necessary, though.)
 __LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals() {
-  BIONIC_USED_BEFORE_LINKER_RELOCATES static libc_shared_globals globals;
+  static libc_shared_globals globals;
   return &globals;
 }
-
-__LIBC_HIDDEN__ bool __libc_mte_enabled() {
-  HeapTaggingLevel lvl = __libc_shared_globals()->initial_heap_tagging_level;
-  return lvl == M_HEAP_TAGGING_LEVEL_SYNC || lvl == M_HEAP_TAGGING_LEVEL_ASYNC;
-}
diff --git a/libc/bionic/stdlib_l.cpp b/libc/bionic/stdlib_l.cpp
index a636d08..58a9079 100644
--- a/libc/bionic/stdlib_l.cpp
+++ b/libc/bionic/stdlib_l.cpp
@@ -26,17 +26,11 @@
  * SUCH DAMAGE.
  */
 
+#define __BIONIC_STDLIB_INLINE /* Out of line. */
 #include <stdlib.h>
-#include <xlocale.h>
+#include <bits/stdlib_inlines.h>
 
-double strtod_l(const char* s, char** end_ptr, locale_t) {
-  return strtod(s, end_ptr);
-}
-
-float strtof_l(const char* s, char** end_ptr, locale_t) {
-  return strtof(s, end_ptr);
-}
-
+// strtold_l was introduced in API level 21, so it isn't polyfilled any more.
 long double strtold_l(const char* s, char** end_ptr, locale_t) {
   return strtold(s, end_ptr);
 }
diff --git a/libc/dns/net/gethnamaddr.c b/libc/dns/net/gethnamaddr.c
index add124f..1ffabfa 100644
--- a/libc/dns/net/gethnamaddr.c
+++ b/libc/dns/net/gethnamaddr.c
@@ -495,7 +495,7 @@
 	*he = NO_RECOVERY;
 	return NULL;
 success:
-	bp = (char *)ALIGN(bp);
+	bp = __builtin_align_up(bp, sizeof(uintptr_t));
 	n = (int)(ap - aliases);
 	qlen = (n + 1) * sizeof(*hent->h_aliases);
 	if ((size_t)(ep - bp) < qlen)
@@ -616,7 +616,7 @@
 	}
 
 	// Fix alignment after variable-length data.
-	ptr = (char*)ALIGN(ptr);
+	ptr = __builtin_align_up(ptr, sizeof(uintptr_t));
 
 	int aliases_len = ((int)(aliases - aliases_ptrs) + 1) * sizeof(*hp->h_aliases);
 	if (ptr + aliases_len > hbuf_end) {
@@ -653,7 +653,7 @@
 	}
 
 	// Fix alignment after variable-length data.
-	ptr = (char*)ALIGN(ptr);
+	ptr = __builtin_align_up(ptr, sizeof(uintptr_t));
 
 	int addrs_len = ((int)(addr_p - addr_ptrs) + 1) * sizeof(*hp->h_addr_list);
 	if (ptr + addrs_len > hbuf_end) {
diff --git a/libc/dns/net/sethostent.c b/libc/dns/net/sethostent.c
index 5c4bdb5..8ea4315 100644
--- a/libc/dns/net/sethostent.c
+++ b/libc/dns/net/sethostent.c
@@ -198,7 +198,7 @@
 				HENT_SCOPY(aliases[anum], hp->h_aliases[anum],
 				    ptr, len);
 			}
-			ptr = (void *)ALIGN(ptr);
+			ptr = __builtin_align_up(ptr, sizeof(uintptr_t));
 			if ((size_t)(ptr - buf) >= info->buflen)
 				goto nospc;
 		}
diff --git a/libc/execinfo/include/execinfo.h b/libc/execinfo/include/execinfo.h
index e092c00..c8f9e21 100644
--- a/libc/execinfo/include/execinfo.h
+++ b/libc/execinfo/include/execinfo.h
@@ -30,8 +30,10 @@
 
 /*
  * This file is exported as part of libexecinfo for use with musl, which doesn't
- * define __INTRODUCED_IN.  Stub it out.
+ * define __INTRODUCED_IN or __BIONIC_AVAILABILITY_GUARD.  Stub them out.
  */
 #define __INTRODUCED_IN(x)
+#define __BIONIC_AVAILABILITY_GUARD(x) 1
 #include <bionic/execinfo.h>
+#undef __BIONIC_AVAILABILITY_GUARD
 #undef __INTRODUCED_IN
diff --git a/libc/include/android/crash_detail.h b/libc/include/android/crash_detail.h
index 946a3ab..490ec8c 100644
--- a/libc/include/android/crash_detail.h
+++ b/libc/include/android/crash_detail.h
@@ -33,9 +33,10 @@
  * @brief Attach extra information to android crashes.
  */
 
-#include <stddef.h>
 #include <sys/cdefs.h>
 
+#include <stddef.h>
+
 __BEGIN_DECLS
 
 typedef struct crash_detail_t crash_detail_t;
diff --git a/libc/include/android/dlext.h b/libc/include/android/dlext.h
index 842ceea..d8d2752 100644
--- a/libc/include/android/dlext.h
+++ b/libc/include/android/dlext.h
@@ -16,10 +16,11 @@
 
 #pragma once
 
+#include <sys/cdefs.h>
+
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
-#include <sys/cdefs.h>
 #include <sys/types.h>  /* for off64_t */
 
 /**
diff --git a/libc/include/android/fdsan.h b/libc/include/android/fdsan.h
index 4540498..fd0a63f 100644
--- a/libc/include/android/fdsan.h
+++ b/libc/include/android/fdsan.h
@@ -28,9 +28,10 @@
 
 #pragma once
 
+#include <sys/cdefs.h>
+
 #include <stdbool.h>
 #include <stdint.h>
-#include <sys/cdefs.h>
 
 __BEGIN_DECLS
 
diff --git a/libc/include/android/legacy_stdlib_inlines.h b/libc/include/android/legacy_stdlib_inlines.h
index a5a07ef..d228e67 100644
--- a/libc/include/android/legacy_stdlib_inlines.h
+++ b/libc/include/android/legacy_stdlib_inlines.h
@@ -30,22 +30,9 @@
 
 #include <sys/cdefs.h>
 
-
 #if __ANDROID_API__ < 26
 
-#include <stdlib.h>
-#include <xlocale.h>
-
-__BEGIN_DECLS
-
-static __inline double strtod_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, locale_t _Nonnull __l) {
-  return strtod(__s, __end_ptr);
-}
-
-static __inline float strtof_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, locale_t _Nonnull __l) {
-  return strtof(__s, __end_ptr);
-}
-
-__END_DECLS
+#define __BIONIC_THREADS_INLINE static __inline
+#include <bits/stdlib_inlines.h>
 
 #endif
diff --git a/libc/include/android/set_abort_message.h b/libc/include/android/set_abort_message.h
index a778057..6ad5678 100644
--- a/libc/include/android/set_abort_message.h
+++ b/libc/include/android/set_abort_message.h
@@ -33,10 +33,11 @@
  * @brief The android_set_abort_message() function.
  */
 
+#include <sys/cdefs.h>
+
 #include <stddef.h>
 #include <stdint.h>
 #include <string.h>
-#include <sys/cdefs.h>
 
 __BEGIN_DECLS
 
diff --git a/libc/include/android/versioning.h b/libc/include/android/versioning.h
index b09cf14..1676a72 100644
--- a/libc/include/android/versioning.h
+++ b/libc/include/android/versioning.h
@@ -32,6 +32,11 @@
 // load even on systems too old to contain the API, but calls must be guarded
 // with `__builtin_available(android api_level, *)` to avoid segfaults.
 #define __BIONIC_AVAILABILITY(__what, ...) __attribute__((__availability__(android,__what __VA_OPT__(,) __VA_ARGS__)))
+
+// When the caller is using weak API references, we should expose the decls for
+// APIs which are not available in the caller's minSdkVersion, otherwise there's
+// no way to take advantage of the weak references.
+#define __BIONIC_AVAILABILITY_GUARD(api_level) 1
 #else
 // The 'strict' flag is required for NDK clients where the code was not written
 // to handle the case where the API was available at build-time but not at
@@ -40,6 +45,17 @@
 // compile in this mode (or worse, if the build doesn't use
 // -Werror=unguarded-availability, it would build but crash at runtime).
 #define __BIONIC_AVAILABILITY(__what, ...) __attribute__((__availability__(android,strict,__what __VA_OPT__(,) __VA_ARGS__)))
+
+// When the caller is using strict API references, we hide APIs which are not
+// available in the caller's minSdkVersion. This is a bionic-only deviation in
+// behavior from the rest of the NDK headers, but it's necessary to maintain
+// source compatibility with 3p libraries that either can't correctly detect API
+// availability (either incorrectly detecting as always-available or as
+// never-available, but neither is true), or define their own polyfills which
+// conflict with our declarations.
+//
+// https://github.com/android/ndk/issues/2081
+#define __BIONIC_AVAILABILITY_GUARD(api_level) (__ANDROID_MIN_SDK_VERSION__ >= (api_level))
 #endif
 
 #pragma clang diagnostic push
@@ -69,4 +85,5 @@
 #if defined(__ANDROID_VNDK__)
 #undef __BIONIC_AVAILABILITY
 #define __BIONIC_AVAILABILITY(api_level, ...)
+#define __BIONIC_AVAILABILITY_GUARD(api_level) 1
 #endif // defined(__ANDROID_VNDK__)
diff --git a/libc/include/arpa/ftp.h b/libc/include/arpa/ftp.h
index 081c037..fecbf7f 100644
--- a/libc/include/arpa/ftp.h
+++ b/libc/include/arpa/ftp.h
@@ -34,6 +34,8 @@
 #ifndef _ARPA_FTP_H_
 #define	_ARPA_FTP_H_
 
+#include <sys/cdefs.h>
+
 /* Definitions for FTP; see RFC-765. */
 
 /*
diff --git a/libc/include/arpa/inet.h b/libc/include/arpa/inet.h
index f00f2c1..ce9dd93 100644
--- a/libc/include/arpa/inet.h
+++ b/libc/include/arpa/inet.h
@@ -29,9 +29,10 @@
 #ifndef _ARPA_INET_H_
 #define _ARPA_INET_H_
 
+#include <sys/cdefs.h>
+
 #include <netinet/in.h>
 #include <stdint.h>
-#include <sys/cdefs.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
diff --git a/libc/include/arpa/nameser.h b/libc/include/arpa/nameser.h
index 97109ee..7f8b9ba 100644
--- a/libc/include/arpa/nameser.h
+++ b/libc/include/arpa/nameser.h
@@ -55,9 +55,10 @@
 
 #define BIND_4_COMPAT
 
-#include <sys/types.h>
 #include <sys/cdefs.h>
 
+#include <sys/types.h>
+
 /*
  * Revision information.  This is the release date in YYYYMMDD format.
  * It can change every day so the right thing to do with it is use it
diff --git a/libc/include/arpa/nameser_compat.h b/libc/include/arpa/nameser_compat.h
index e4e9335..027e5ca 100644
--- a/libc/include/arpa/nameser_compat.h
+++ b/libc/include/arpa/nameser_compat.h
@@ -40,9 +40,10 @@
 #ifndef _ARPA_NAMESER_COMPAT_
 #define	_ARPA_NAMESER_COMPAT_
 
-#include <endian.h>
 #include <sys/cdefs.h>
 
+#include <endian.h>
+
 #define	__BIND		19950621	/* (DEAD) interface version stamp. */
 
 /*
diff --git a/libc/include/arpa/telnet.h b/libc/include/arpa/telnet.h
index 758e9b8..30d8f21 100644
--- a/libc/include/arpa/telnet.h
+++ b/libc/include/arpa/telnet.h
@@ -33,6 +33,8 @@
 #ifndef _ARPA_TELNET_H_
 #define	_ARPA_TELNET_H_
 
+#include <sys/cdefs.h>
+
 /*
  * Definitions for the TELNET protocol.
  */
diff --git a/libc/include/bits/bionic_multibyte_result.h b/libc/include/bits/bionic_multibyte_result.h
index 0d5cf21..930e67c 100644
--- a/libc/include/bits/bionic_multibyte_result.h
+++ b/libc/include/bits/bionic_multibyte_result.h
@@ -34,9 +34,10 @@
  * conversion APIs defined by C.
  */
 
-#include <stddef.h>
 #include <sys/cdefs.h>
 
+#include <stddef.h>
+
 __BEGIN_DECLS
 
 /**
diff --git a/libc/include/bits/seek_constants.h b/libc/include/bits/seek_constants.h
index bfc02a8..a4fffb2 100644
--- a/libc/include/bits/seek_constants.h
+++ b/libc/include/bits/seek_constants.h
@@ -33,6 +33,8 @@
  * @brief The `SEEK_` constants.
  */
 
+#include <sys/cdefs.h>
+
 /** Seek to an absolute offset. */
 #define SEEK_SET 0
 /** Seek relative to the current offset. */
diff --git a/libc/include/bits/stdatomic.h b/libc/include/bits/stdatomic.h
index c74eafd..ebdc9e5 100644
--- a/libc/include/bits/stdatomic.h
+++ b/libc/include/bits/stdatomic.h
@@ -134,6 +134,8 @@
 	memory_order_seq_cst = __ATOMIC_SEQ_CST
 } memory_order;
 
+#define kill_dependency(y) (y)
+
 /*
  * 7.17.4 Fences.
  */
diff --git a/tests/libs/memtag_globals.h b/libc/include/bits/stdlib_inlines.h
similarity index 70%
rename from tests/libs/memtag_globals.h
rename to libc/include/bits/stdlib_inlines.h
index a03abae..fffca19 100644
--- a/tests/libs/memtag_globals.h
+++ b/libc/include/bits/stdlib_inlines.h
@@ -26,18 +26,23 @@
  * SUCH DAMAGE.
  */
 
-#include <utility>
-#include <vector>
+#pragma once
 
-void check_tagged(const void* a);
-void check_untagged(const void* a);
-void check_matching_tags(const void* a, const void* b);
-void check_eq(const void* a, const void* b);
+#include <xlocale.h>
+#include <sys/cdefs.h>
 
-void dso_check_assertions(bool enforce_tagged);
-void dso_print_variables();
+#if !defined(__BIONIC_STDLIB_INLINE)
+#define __BIONIC_STDLIB_INLINE static __inline
+#endif
 
-void print_variable_address(const char* name, const void* ptr);
-void print_variables(const char* header,
-                     const std::vector<std::pair<const char*, const void*>>& tagged_variables,
-                     const std::vector<std::pair<const char*, const void*>>& untagged_variables);
+__BEGIN_DECLS
+
+__BIONIC_STDLIB_INLINE double strtod_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, locale_t _Nonnull __l) {
+  return strtod(__s, __end_ptr);
+}
+
+__BIONIC_STDLIB_INLINE float strtof_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, locale_t _Nonnull __l) {
+  return strtof(__s, __end_ptr);
+}
+
+__END_DECLS
diff --git a/libc/include/bits/swab.h b/libc/include/bits/swab.h
index 9591c2e..da2865a 100644
--- a/libc/include/bits/swab.h
+++ b/libc/include/bits/swab.h
@@ -28,8 +28,9 @@
 
 #pragma once
 
-#include <stdint.h>
 #include <sys/cdefs.h>
+
+#include <stdint.h>
 #include <sys/types.h>
 
 #if !defined(__BIONIC_SWAB_INLINE)
diff --git a/libc/include/bits/termios_inlines.h b/libc/include/bits/termios_inlines.h
index a884b59..bb04e4d 100644
--- a/libc/include/bits/termios_inlines.h
+++ b/libc/include/bits/termios_inlines.h
@@ -29,8 +29,9 @@
 #ifndef _BITS_TERMIOS_INLINES_H_
 #define _BITS_TERMIOS_INLINES_H_
 
-#include <errno.h>
 #include <sys/cdefs.h>
+
+#include <errno.h>
 #include <sys/ioctl.h>
 #include <sys/types.h>
 
diff --git a/libc/include/bits/termios_winsize_inlines.h b/libc/include/bits/termios_winsize_inlines.h
index ae246e4..86777b0 100644
--- a/libc/include/bits/termios_winsize_inlines.h
+++ b/libc/include/bits/termios_winsize_inlines.h
@@ -28,8 +28,9 @@
 
 #pragma once
 
-#include <errno.h>
 #include <sys/cdefs.h>
+
+#include <errno.h>
 #include <sys/ioctl.h>
 #include <sys/types.h>
 
diff --git a/libc/include/bits/threads_inlines.h b/libc/include/bits/threads_inlines.h
index 05b785a..ab294c1 100644
--- a/libc/include/bits/threads_inlines.h
+++ b/libc/include/bits/threads_inlines.h
@@ -28,6 +28,8 @@
 
 #pragma once
 
+#include <sys/cdefs.h>
+
 #include <threads.h>
 
 #include <errno.h>
diff --git a/libc/include/dirent.h b/libc/include/dirent.h
index 5333d78..2695305 100644
--- a/libc/include/dirent.h
+++ b/libc/include/dirent.h
@@ -33,8 +33,9 @@
  * @brief Directory entry iteration.
  */
 
-#include <stdint.h>
 #include <sys/cdefs.h>
+
+#include <stdint.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
diff --git a/libc/include/dlfcn.h b/libc/include/dlfcn.h
index 071d50a..1b0d11b 100644
--- a/libc/include/dlfcn.h
+++ b/libc/include/dlfcn.h
@@ -28,9 +28,10 @@
 
 #pragma once
 
-#include <stdint.h>
 #include <sys/cdefs.h>
 
+#include <stdint.h>
+
 __BEGIN_DECLS
 
 /**
diff --git a/libc/include/err.h b/libc/include/err.h
index d8122d7..4a1841b 100644
--- a/libc/include/err.h
+++ b/libc/include/err.h
@@ -36,8 +36,9 @@
  * @brief BSD error reporting functions. See `<error.h>` for the GNU equivalent.
  */
 
-#include <stdarg.h>
 #include <sys/cdefs.h>
+
+#include <stdarg.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
diff --git a/libc/include/error.h b/libc/include/error.h
index cb867cd..4d6a965 100644
--- a/libc/include/error.h
+++ b/libc/include/error.h
@@ -37,6 +37,9 @@
 
 __BEGIN_DECLS
 
+// These cause issues with gnulib's polyfill
+// https://github.com/android/ndk/issues/2081
+#if __ANDROID_API__ >= 23
 /**
  * [error_print_progname(3)](https://man7.org/linux/man-pages/man3/error_print_progname.3.html) is
  * a function pointer that, if non-null, is called by error() instead of prefixing errors with the
@@ -45,7 +48,9 @@
  * Available since API level 23.
  */
 extern void (* _Nullable error_print_progname)(void) __INTRODUCED_IN(23);
+#endif
 
+#if __ANDROID_API__ >= 23
 /**
  * [error_message_count(3)](https://man7.org/linux/man-pages/man3/error_message_count.3.html) is
  * a global count of the number of calls to error() and error_at_line().
@@ -53,6 +58,7 @@
  * Available since API level 23.
  */
 extern unsigned int error_message_count __INTRODUCED_IN(23);
+#endif
 
 /**
  * [error_one_per_line(3)](https://man7.org/linux/man-pages/man3/error_one_per_line.3.html) is
diff --git a/libc/include/inttypes.h b/libc/include/inttypes.h
index 9fcd9f3..790030e 100644
--- a/libc/include/inttypes.h
+++ b/libc/include/inttypes.h
@@ -19,8 +19,8 @@
 #ifndef	_INTTYPES_H_
 #define	_INTTYPES_H_
 
-#include <stdint.h>
 #include <sys/cdefs.h>
+#include <stdint.h>
 
 #ifdef __LP64__
 #define __PRI_64_prefix  "l"
diff --git a/libc/include/link.h b/libc/include/link.h
index 216502e..331070e 100644
--- a/libc/include/link.h
+++ b/libc/include/link.h
@@ -33,8 +33,9 @@
  * @brief Extra dynamic linker functionality (see also <dlfcn.h>).
  */
 
-#include <stdint.h>
 #include <sys/cdefs.h>
+
+#include <stdint.h>
 #include <sys/types.h>
 
 #include <elf.h>
diff --git a/libc/include/mntent.h b/libc/include/mntent.h
index 9a31838..b4d1233 100644
--- a/libc/include/mntent.h
+++ b/libc/include/mntent.h
@@ -29,8 +29,9 @@
 #ifndef _MNTENT_H_
 #define _MNTENT_H_
 
-#include <stdio.h>
 #include <sys/cdefs.h>
+
+#include <stdio.h>
 #include <paths.h>  /* for _PATH_MOUNTED */
 
 #define MOUNTED _PATH_MOUNTED
diff --git a/libc/include/net/if.h b/libc/include/net/if.h
index 79b4195..4bbdb21 100644
--- a/libc/include/net/if.h
+++ b/libc/include/net/if.h
@@ -29,9 +29,10 @@
 #ifndef _NET_IF_H_
 #define _NET_IF_H_
 
+#include <sys/cdefs.h>
+
 #include <sys/socket.h>
 #include <linux/if.h>
-#include <sys/cdefs.h>
 
 #ifndef IF_NAMESIZE
 #define IF_NAMESIZE IFNAMSIZ
diff --git a/libc/include/netinet/icmp6.h b/libc/include/netinet/icmp6.h
index 2b237a8..ebd9f6c 100644
--- a/libc/include/netinet/icmp6.h
+++ b/libc/include/netinet/icmp6.h
@@ -65,9 +65,10 @@
 #ifndef _NETINET_ICMP6_H_
 #define _NETINET_ICMP6_H_
 
-#include <netinet/in.h> /* android-added: glibc source compatibility. */
 #include <sys/cdefs.h>
 
+#include <netinet/in.h> /* android-added: glibc source compatibility. */
+
 #define ICMPV6_PLD_MAXLEN	1232	/* IPV6_MMTU - sizeof(struct ip6_hdr)
 					   - sizeof(struct icmp6_hdr) */
 
diff --git a/libc/include/netinet/in.h b/libc/include/netinet/in.h
index 163e614..d4ce302 100644
--- a/libc/include/netinet/in.h
+++ b/libc/include/netinet/in.h
@@ -28,9 +28,10 @@
 
 #pragma once
 
+#include <sys/cdefs.h>
+
 #include <endian.h>
 #include <netinet/in6.h>
-#include <sys/cdefs.h>
 #include <sys/socket.h>
 
 #include <linux/in.h>
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index d718b40..2fa10bb 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -33,11 +33,12 @@
  * @brief POSIX threads.
  */
 
+#include <sys/cdefs.h>
+
 #include <limits.h>
 #include <bits/page_size.h>
 #include <bits/pthread_types.h>
 #include <sched.h>
-#include <sys/cdefs.h>
 #include <sys/types.h>
 #include <time.h>
 
diff --git a/libc/include/resolv.h b/libc/include/resolv.h
index f25484a..4367359 100644
--- a/libc/include/resolv.h
+++ b/libc/include/resolv.h
@@ -29,9 +29,10 @@
 #ifndef _RESOLV_H_
 #define _RESOLV_H_
 
+#include <sys/cdefs.h>
+
 #include <sys/param.h>
 #include <sys/types.h>
-#include <sys/cdefs.h>
 #include <sys/socket.h>
 #include <stdio.h>
 #include <arpa/nameser.h>
diff --git a/libc/include/sched.h b/libc/include/sched.h
index e8f7736..7a2dcad 100644
--- a/libc/include/sched.h
+++ b/libc/include/sched.h
@@ -33,9 +33,10 @@
  * @brief Thread execution scheduling.
  */
 
+#include <sys/cdefs.h>
+
 #include <bits/timespec.h>
 #include <linux/sched.h>
-#include <sys/cdefs.h>
 
 __BEGIN_DECLS
 
diff --git a/libc/include/stdint.h b/libc/include/stdint.h
index 322a81c..772fe8b 100644
--- a/libc/include/stdint.h
+++ b/libc/include/stdint.h
@@ -29,9 +29,10 @@
 #ifndef _STDINT_H
 #define _STDINT_H
 
+#include <sys/cdefs.h>
+
 #include <bits/wchar_limits.h>
 #include <stddef.h>
-#include <sys/cdefs.h>
 
 typedef signed char __int8_t;
 typedef unsigned char __uint8_t;
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index d24f6af..4912c0a 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -272,7 +272,12 @@
 int putc_unlocked(int __ch, FILE* _Nonnull __fp);
 int putchar_unlocked(int __ch);
 
+// This causes issues with a polyfill in libconfuse
+// https://github.com/android/ndk/issues/2081
+#if __ANDROID_API__ >= 23
 __nodiscard FILE* _Nullable fmemopen(void* _Nullable __buf, size_t __size, const char* _Nonnull __mode) __INTRODUCED_IN(23);
+#endif
+
 __nodiscard FILE* _Nullable open_memstream(char* _Nonnull * _Nonnull __ptr, size_t* _Nonnull __size_ptr) __INTRODUCED_IN(23);
 
 #if defined(__USE_BSD) || defined(__BIONIC__) /* Historically bionic exposed these. */
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 076a978..2c918d4 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -29,11 +29,12 @@
 #ifndef _STDLIB_H
 #define _STDLIB_H
 
+#include <sys/cdefs.h>
+
 #include <alloca.h>
 #include <bits/wait.h>
 #include <malloc.h>
 #include <stddef.h>
-#include <sys/cdefs.h>
 #include <xlocale.h>
 
 __BEGIN_DECLS
diff --git a/libc/include/string.h b/libc/include/string.h
index 7c1c3be..873ea82 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -52,8 +52,12 @@
 int memcmp(const void* _Nonnull __lhs, const void* _Nonnull __rhs, size_t __n) __attribute_pure__;
 void* _Nonnull memcpy(void* _Nonnull, const void* _Nonnull, size_t);
 #if defined(__USE_GNU)
+// This conflicts with a polyfill in gettext-libintl
+// https://github.com/android/ndk/issues/2081
+#if __ANDROID_API__ >= 23
 void* _Nonnull mempcpy(void* _Nonnull __dst, const void* _Nonnull __src, size_t __n) __INTRODUCED_IN(23);
 #endif
+#endif
 void* _Nonnull memmove(void* _Nonnull __dst, const void* _Nonnull __src, size_t __n);
 
 /**
diff --git a/libc/include/strings.h b/libc/include/strings.h
index d203bd2..7543edc 100644
--- a/libc/include/strings.h
+++ b/libc/include/strings.h
@@ -43,8 +43,9 @@
  * @brief Extra string functions.
  */
 
-#include <sys/types.h>
 #include <sys/cdefs.h>
+
+#include <sys/types.h>
 #include <xlocale.h>
 
 #include <bits/strcasecmp.h>
diff --git a/libc/include/sys/cachectl.h b/libc/include/sys/cachectl.h
index b5fabe3..d06d683 100644
--- a/libc/include/sys/cachectl.h
+++ b/libc/include/sys/cachectl.h
@@ -48,7 +48,7 @@
 
 /**
  * __riscv_flush_icache(2) flushes the instruction cache for the given range of addresses.
- * The address range is currently (Linux 6.4) ignored, so both pointers may be null.
+ * The address range is currently (Linux 6.12) ignored, so both pointers may be null.
  *
  * Returns 0 on success, and returns -1 and sets `errno` on failure.
  */
diff --git a/libc/include/sys/param.h b/libc/include/sys/param.h
index 1c991ae..99b6a07 100644
--- a/libc/include/sys/param.h
+++ b/libc/include/sys/param.h
@@ -33,10 +33,11 @@
  * @brief Various macros.
  */
 
+#include <sys/cdefs.h>
+
 #include <endian.h>
 #include <limits.h>
 #include <linux/param.h>
-#include <sys/cdefs.h>
 
 /** The unit of `st_blocks` in `struct stat`. */
 #define DEV_BSIZE 512
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index 2633b69..ed52bcc 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -33,9 +33,10 @@
  * @brief File status.
  */
 
+#include <sys/cdefs.h>
+
 #include <bits/timespec.h>
 #include <linux/stat.h>
-#include <sys/cdefs.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
diff --git a/libc/include/sys/statvfs.h b/libc/include/sys/statvfs.h
index 2feca81..860824b 100644
--- a/libc/include/sys/statvfs.h
+++ b/libc/include/sys/statvfs.h
@@ -21,8 +21,9 @@
  * @brief Filesystem statistics.
  */
 
-#include <stdint.h>
 #include <sys/cdefs.h>
+
+#include <stdint.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h
index a49323d..9341ffb 100644
--- a/libc/include/sys/syscall.h
+++ b/libc/include/sys/syscall.h
@@ -29,9 +29,10 @@
 #ifndef _SYS_SYSCALL_H_
 #define _SYS_SYSCALL_H_
 
+#include <sys/cdefs.h>
+
 #include <asm/unistd.h> /* Linux kernel __NR_* names. */
 #include <bits/glibc-syscalls.h> /* glibc-compatible SYS_* aliases. */
-#include <sys/cdefs.h>
 
 /* The syscall function itself is declared in <unistd.h>, not here. */
 
diff --git a/libc/include/sys/timerfd.h b/libc/include/sys/timerfd.h
index bfa9a55..f7f1ffa 100644
--- a/libc/include/sys/timerfd.h
+++ b/libc/include/sys/timerfd.h
@@ -33,10 +33,11 @@
  * @brief Timer file descriptors.
  */
 
+#include <sys/cdefs.h>
+
 #include <fcntl.h>
 #include <linux/timerfd.h>
 #include <time.h>
-#include <sys/cdefs.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h
index 4622a4e..0446260 100644
--- a/libc/include/sys/types.h
+++ b/libc/include/sys/types.h
@@ -29,9 +29,10 @@
 #ifndef _SYS_TYPES_H_
 #define _SYS_TYPES_H_
 
+#include <sys/cdefs.h>
+
 #include <stddef.h>
 #include <stdint.h>
-#include <sys/cdefs.h>
 
 #include <linux/types.h>
 #include <linux/posix_types.h>
diff --git a/libc/include/sys/un.h b/libc/include/sys/un.h
index 83c1d17..c2bfcb0 100644
--- a/libc/include/sys/un.h
+++ b/libc/include/sys/un.h
@@ -33,9 +33,10 @@
  * @brief Unix domain sockets.
  */
 
+#include <sys/cdefs.h>
+
 #include <bits/sa_family_t.h>
 #include <linux/un.h>
-#include <sys/cdefs.h>
 
 #if defined(__USE_BSD) || defined(__USE_GNU)
 #include <string.h>
diff --git a/libc/include/sys/vfs.h b/libc/include/sys/vfs.h
index 1a640ba..5d078be 100644
--- a/libc/include/sys/vfs.h
+++ b/libc/include/sys/vfs.h
@@ -29,8 +29,9 @@
 #ifndef _SYS_VFS_H_
 #define _SYS_VFS_H_
 
-#include <stdint.h>
 #include <sys/cdefs.h>
+
+#include <stdint.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
diff --git a/libc/include/sys/wait.h b/libc/include/sys/wait.h
index 5208366..632aa43 100644
--- a/libc/include/sys/wait.h
+++ b/libc/include/sys/wait.h
@@ -28,8 +28,9 @@
 
 #pragma once
 
-#include <bits/wait.h>
 #include <sys/cdefs.h>
+
+#include <bits/wait.h>
 #include <sys/types.h>
 #include <sys/resource.h>
 #include <linux/wait.h>
diff --git a/libc/include/sys/xattr.h b/libc/include/sys/xattr.h
index 38c11e2..ebe4eb8 100644
--- a/libc/include/sys/xattr.h
+++ b/libc/include/sys/xattr.h
@@ -33,8 +33,9 @@
  * @brief Extended attribute functions.
  */
 
-#include <linux/xattr.h>
 #include <sys/cdefs.h>
+
+#include <linux/xattr.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
diff --git a/libc/include/syslog.h b/libc/include/syslog.h
index 33979f0..7a594f1 100644
--- a/libc/include/syslog.h
+++ b/libc/include/syslog.h
@@ -56,8 +56,9 @@
 
 #pragma once
 
-#include <stdio.h>
 #include <sys/cdefs.h>
+
+#include <stdio.h>
 #include <stdarg.h>
 
 __BEGIN_DECLS
diff --git a/libc/include/uchar.h b/libc/include/uchar.h
index 55a36e7..94efb2d 100644
--- a/libc/include/uchar.h
+++ b/libc/include/uchar.h
@@ -33,9 +33,10 @@
  * @brief Unicode functions.
  */
 
-#include <stddef.h>
 #include <sys/cdefs.h>
 
+#include <stddef.h>
+
 #include <bits/bionic_multibyte_result.h>
 #include <bits/mbstate_t.h>
 
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 9bc01f0..f11990d 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -28,8 +28,9 @@
 
 #pragma once
 
-#include <stddef.h>
 #include <sys/cdefs.h>
+
+#include <stddef.h>
 #include <sys/types.h>
 #include <sys/select.h>
 
diff --git a/libc/include/wctype.h b/libc/include/wctype.h
index 4f6f81f..2b7f972 100644
--- a/libc/include/wctype.h
+++ b/libc/include/wctype.h
@@ -29,8 +29,9 @@
 #ifndef _WCTYPE_H_
 #define _WCTYPE_H_
 
-#include <bits/wctype.h>
 #include <sys/cdefs.h>
+
+#include <bits/wctype.h>
 #include <xlocale.h>
 
 __BEGIN_DECLS
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 0d2e42f..d8636a2 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -591,7 +591,6 @@
     killpg;
     klogctl;
     labs;
-    lchmod; # introduced=36
     lchown;
     lcong48; # introduced=23
     ldexp;
@@ -671,7 +670,6 @@
     mprotect;
     mrand48;
     mremap;
-    mseal; # introduced=36
     msync;
     munlock;
     munlockall;
@@ -846,7 +844,6 @@
     pwrite;
     pwrite64;
     qsort;
-    qsort_r; # introduced=36
     quick_exit;
     raise;
     rand;
@@ -955,7 +952,6 @@
     setvbuf;
     setxattr;
     shutdown;
-    sig2str; # introduced=36
     sigaction;
     sigaddset;
     sigaltstack;
@@ -998,7 +994,6 @@
     stdout; # var introduced=23
     stpcpy;
     stpncpy;
-    str2sig; # introduced=36
     strcasecmp;
     strcasecmp_l; # introduced=23
     strcasestr;
@@ -1613,6 +1608,15 @@
     __system_properties_zygote_reload; # apex
 } LIBC_U;
 
+LIBC_36 { # introduced=36
+  global:
+    lchmod;
+    mseal;
+    qsort_r;
+    sig2str;
+    str2sig;
+} LIBC_V;
+
 LIBC_PRIVATE {
   global:
     __accept4; # arm x86
diff --git a/libc/platform/bionic/macros.h b/libc/platform/bionic/macros.h
index 837583e..93268c1 100644
--- a/libc/platform/bionic/macros.h
+++ b/libc/platform/bionic/macros.h
@@ -97,26 +97,3 @@
 static inline T* _Nonnull untag_address(T* _Nonnull p) {
   return reinterpret_cast<T*>(untag_address(reinterpret_cast<uintptr_t>(p)));
 }
-
-// MTE globals protects internal and external global variables. One of the main
-// things that MTE globals does is force all global variable accesses to go
-// through the GOT. In the linker though, some global variables are accessed (or
-// address-taken) prior to relocations being processed. Because relocations
-// haven't run yet, the GOT entry hasn't been populated, and this leads to
-// crashes. Thus, any globals used by the linker prior to relocation should be
-// annotated with this attribute, which suppresses tagging of this global
-// variable, restoring the pc-relative address computation.
-//
-// A way to find global variables that need this attribute is to build the
-// linker/libc with `SANITIZE_TARGET=memtag_globals`, push them onto a device
-// (it doesn't have to be MTE capable), and then run an executable using
-// LD_LIBRARY_PATH and using the linker in interpreter mode (e.g.
-// `LD_LIBRARY_PATH=/data/tmp/ /data/tmp/linker64 /data/tmp/my_binary`). A
-// good heuristic is that the global variable is in a file that should be
-// compiled with `-ffreestanding` (but there are global variables there that
-// don't need thisattribute).
-#if __has_feature(memtag_globals)
-#define BIONIC_USED_BEFORE_LINKER_RELOCATES __attribute__((no_sanitize("memtag")))
-#else  // __has_feature(memtag_globals)
-#define BIONIC_USED_BEFORE_LINKER_RELOCATES
-#endif  // __has_feature(memtag_globals)
diff --git a/libc/platform/bionic/mte.h b/libc/platform/bionic/mte.h
index 423ed0f..98b3d27 100644
--- a/libc/platform/bionic/mte.h
+++ b/libc/platform/bionic/mte.h
@@ -28,7 +28,6 @@
 
 #pragma once
 
-#include <stddef.h>
 #include <sys/auxv.h>
 #include <sys/mman.h>
 #include <sys/prctl.h>
@@ -50,36 +49,6 @@
   return supported;
 }
 
-inline void* get_tagged_address(const void* ptr) {
-#if defined(__aarch64__)
-  if (mte_supported()) {
-    __asm__ __volatile__(".arch_extension mte; ldg %0, [%0]" : "+r"(ptr));
-  }
-#endif  // aarch64
-  return const_cast<void*>(ptr);
-}
-
-// Inserts a random tag tag to `ptr`, using any of the set lower 16 bits in
-// `mask` to exclude the corresponding tag from being generated. Note: This does
-// not tag memory. This generates a pointer to be used with set_memory_tag.
-inline void* insert_random_tag(const void* ptr, __attribute__((unused)) uint64_t mask = 0) {
-#if defined(__aarch64__)
-  if (mte_supported() && ptr) {
-    __asm__ __volatile__(".arch_extension mte; irg %0, %0, %1" : "+r"(ptr) : "r"(mask));
-  }
-#endif  // aarch64
-  return const_cast<void*>(ptr);
-}
-
-// Stores the address tag in `ptr` to memory, at `ptr`.
-inline void set_memory_tag(__attribute__((unused)) void* ptr) {
-#if defined(__aarch64__)
-  if (mte_supported()) {
-    __asm__ __volatile__(".arch_extension mte; stg %0, [%0]" : "+r"(ptr));
-  }
-#endif  // aarch64
-}
-
 #ifdef __aarch64__
 class ScopedDisableMTE {
   size_t prev_tco_;
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
index 02713fc..a1bebda 100644
--- a/libc/private/bionic_globals.h
+++ b/libc/private/bionic_globals.h
@@ -157,7 +157,6 @@
 };
 
 __LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals();
-__LIBC_HIDDEN__ bool __libc_mte_enabled();
 __LIBC_HIDDEN__ void __libc_init_fdsan();
 __LIBC_HIDDEN__ void __libc_init_fdtrack();
 __LIBC_HIDDEN__ void __libc_init_profiling_handlers();
diff --git a/libc/private/bsd_sys_param.h b/libc/private/bsd_sys_param.h
deleted file mode 100644
index ab54aa0..0000000
--- a/libc/private/bsd_sys_param.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <inttypes.h>
-
-/* OpenBSD has these in <sys/param.h>, but "ALIGN" isn't something we want to reserve. */
-#define ALIGNBYTES (sizeof(uintptr_t) - 1)
-#define ALIGN(p) ((__BIONIC_CAST(reinterpret_cast, uintptr_t, p) + ALIGNBYTES) & ~ALIGNBYTES)
diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp
index 37b9665..a5f2f81 100644
--- a/libc/stdio/stdio.cpp
+++ b/libc/stdio/stdio.cpp
@@ -58,8 +58,6 @@
 #include "private/bionic_fortify.h"
 #include "private/thread_private.h"
 
-#include "private/bsd_sys_param.h" // For ALIGN/ALIGNBYTES.
-
 #define	NDYNAMIC 10		/* add ten more whenever necessary */
 
 #define PRINTF_IMPL(expr) \
@@ -135,12 +133,14 @@
 };
 
 static glue* moreglue(int n) {
-  char* data = new char[sizeof(glue) + ALIGNBYTES + n * sizeof(FILE) + n * sizeof(__sfileext)];
+  char* data = new char[sizeof(glue) +
+                        alignof(FILE) + n * sizeof(FILE) +
+                        alignof(__sfileext) + n * sizeof(__sfileext)];
   if (data == nullptr) return nullptr;
 
   glue* g = reinterpret_cast<glue*>(data);
-  FILE* p = reinterpret_cast<FILE*>(ALIGN(data + sizeof(*g)));
-  __sfileext* pext = reinterpret_cast<__sfileext*>(ALIGN(data + sizeof(*g)) + n * sizeof(FILE));
+  FILE* p = reinterpret_cast<FILE*>(__builtin_align_up(g + 1, alignof(FILE)));
+  __sfileext* pext = reinterpret_cast<__sfileext*>(__builtin_align_up(p + n, alignof(__sfileext)));
   g->next = nullptr;
   g->niobs = n;
   g->iobs = p;
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index cbc52b5..ac6840a 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -25,8 +25,6 @@
 
 #include <sys/random.h> // For getentropy.
 
-#include "private/bsd_sys_param.h"
-
 #define __BEGIN_HIDDEN_DECLS _Pragma("GCC visibility push(hidden)")
 #define __END_HIDDEN_DECLS _Pragma("GCC visibility pop")
 
diff --git a/linker/Android.bp b/linker/Android.bp
index 847a9b2..a06ca29 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -108,12 +108,6 @@
 
     // We need to access Bionic private headers in the linker.
     include_dirs: ["bionic/libc"],
-
-    sanitize: {
-        // Supporting memtag_globals in the linker would be tricky,
-        // because it relocates itself very early.
-        memtag_globals: false,
-    },
 }
 
 // ========================================================
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 82f2728..fee19f4 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -331,7 +331,6 @@
     __libdl_info->gnu_bloom_filter_ = linker_si.gnu_bloom_filter_;
     __libdl_info->gnu_bucket_ = linker_si.gnu_bucket_;
     __libdl_info->gnu_chain_ = linker_si.gnu_chain_;
-    __libdl_info->memtag_dynamic_entries_ = linker_si.memtag_dynamic_entries_;
 
     __libdl_info->ref_count_ = 1;
     __libdl_info->strtab_size_ = linker_si.strtab_size_;
diff --git a/linker/linker.cpp b/linker/linker.cpp
index ed3f121..88d02dc 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -51,7 +51,6 @@
 #include <android-base/scopeguard.h>
 #include <async_safe/log.h>
 #include <bionic/pthread_internal.h>
-#include <platform/bionic/mte.h>
 
 // Private C library headers.
 
@@ -1698,19 +1697,11 @@
     }
   }
 
-  // The WebView loader uses RELRO sharing in order to promote page sharing of the large RELRO
-  // segment, as it's full of C++ vtables. Because MTE globals, by default, applies random tags to
-  // each global variable, the RELRO segment is polluted and unique for each process. In order to
-  // allow sharing, but still provide some protection, we use deterministic global tagging schemes
-  // for DSOs that are loaded through android_dlopen_ext, such as those loaded by WebView.
-  bool deterministic_memtag_globals =
-      extinfo && extinfo->flags & (ANDROID_DLEXT_WRITE_RELRO | ANDROID_DLEXT_USE_RELRO);
-
   // Step 3: pre-link all DT_NEEDED libraries in breadth first order.
   bool any_memtag_stack = false;
   for (auto&& task : load_tasks) {
     soinfo* si = task->get_soinfo();
-    if (!si->is_linked() && !si->prelink_image(deterministic_memtag_globals)) {
+    if (!si->is_linked() && !si->prelink_image()) {
       return false;
     }
     // si->memtag_stack() needs to be called after si->prelink_image() which populates
@@ -2370,7 +2361,7 @@
         void* tls_block = get_tls_block_for_this_thread(tls_module, /*should_alloc=*/true);
         *symbol = static_cast<char*>(tls_block) + sym->st_value;
       } else {
-        *symbol = get_tagged_address(reinterpret_cast<void*>(found->resolve_symbol_address(sym)));
+        *symbol = reinterpret_cast<void*>(found->resolve_symbol_address(sym));
       }
       failure_guard.Disable();
       LD_LOG(kLogDlsym,
@@ -2800,25 +2791,15 @@
   return true;
 }
 
-static void apply_relr_reloc(ElfW(Addr) offset, ElfW(Addr) load_bias, bool has_memtag_globals) {
-  ElfW(Addr) destination = offset + load_bias;
-  if (!has_memtag_globals) {
-    *reinterpret_cast<ElfW(Addr)*>(destination) += load_bias;
-    return;
-  }
-
-  ElfW(Addr)* tagged_destination =
-      reinterpret_cast<ElfW(Addr)*>(get_tagged_address(reinterpret_cast<void*>(destination)));
-  ElfW(Addr) tagged_value = reinterpret_cast<ElfW(Addr)>(
-      get_tagged_address(reinterpret_cast<void*>(*tagged_destination + load_bias)));
-  *tagged_destination = tagged_value;
+static void apply_relr_reloc(ElfW(Addr) offset, ElfW(Addr) load_bias) {
+  ElfW(Addr) address = offset + load_bias;
+  *reinterpret_cast<ElfW(Addr)*>(address) += load_bias;
 }
 
 // Process relocations in SHT_RELR section (experimental).
 // Details of the encoding are described in this post:
 //   https://groups.google.com/d/msg/generic-abi/bX460iggiKg/Pi9aSwwABgAJ
-bool relocate_relr(const ElfW(Relr) * begin, const ElfW(Relr) * end, ElfW(Addr) load_bias,
-                   bool has_memtag_globals) {
+bool relocate_relr(const ElfW(Relr)* begin, const ElfW(Relr)* end, ElfW(Addr) load_bias) {
   constexpr size_t wordsize = sizeof(ElfW(Addr));
 
   ElfW(Addr) base = 0;
@@ -2829,7 +2810,7 @@
     if ((entry&1) == 0) {
       // Even entry: encodes the offset for next relocation.
       offset = static_cast<ElfW(Addr)>(entry);
-      apply_relr_reloc(offset, load_bias, has_memtag_globals);
+      apply_relr_reloc(offset, load_bias);
       // Set base offset for subsequent bitmap entries.
       base = offset + wordsize;
       continue;
@@ -2840,7 +2821,7 @@
     while (entry != 0) {
       entry >>= 1;
       if ((entry&1) != 0) {
-        apply_relr_reloc(offset, load_bias, has_memtag_globals);
+        apply_relr_reloc(offset, load_bias);
       }
       offset += wordsize;
     }
@@ -2855,7 +2836,7 @@
 // An empty list of soinfos
 static soinfo_list_t g_empty_list;
 
-bool soinfo::prelink_image(bool deterministic_memtag_globals) {
+bool soinfo::prelink_image() {
   if (flags_ & FLAG_PRELINKED) return true;
   /* Extract dynamic section */
   ElfW(Word) dynamic_flags = 0;
@@ -3344,18 +3325,6 @@
   // it each time we look up a symbol with a version.
   if (!validate_verdef_section(this)) return false;
 
-  // MTE globals requires remapping data segments with PROT_MTE as anonymous mappings, because file
-  // based mappings may not be backed by tag-capable memory (see "MAP_ANONYMOUS" on
-  // https://www.kernel.org/doc/html/latest/arch/arm64/memory-tagging-extension.html). This is only
-  // done if the binary has MTE globals (evidenced by the dynamic table entries), as it destroys
-  // page sharing. It's also only done on devices that support MTE, because the act of remapping
-  // pages is unnecessary on non-MTE devices (where we might still run MTE-globals enabled code).
-  if (should_tag_memtag_globals() &&
-      remap_memtag_globals_segments(phdr, phnum, base) == 0) {
-    tag_globals(deterministic_memtag_globals);
-    protect_memtag_globals_ro_segments(phdr, phnum, base);
-  }
-
   flags_ |= FLAG_PRELINKED;
   return true;
 }
@@ -3428,10 +3397,6 @@
     return false;
   }
 
-  if (should_tag_memtag_globals()) {
-    name_memtag_globals_segments(phdr, phnum, base, get_realpath(), vma_names_);
-  }
-
   /* Handle serializing/sharing the RELRO segment */
   if (extinfo && (extinfo->flags & ANDROID_DLEXT_WRITE_RELRO)) {
     if (phdr_table_serialize_gnu_relro(phdr, phnum, load_bias,
@@ -3470,54 +3435,6 @@
   return true;
 }
 
-// https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#global-variable-tagging
-void soinfo::tag_globals(bool deterministic_memtag_globals) {
-  if (is_linked()) return;
-  if (flags_ & FLAG_GLOBALS_TAGGED) return;
-  flags_ |= FLAG_GLOBALS_TAGGED;
-
-  constexpr size_t kTagGranuleSize = 16;
-  const uint8_t* descriptor_stream = reinterpret_cast<const uint8_t*>(memtag_globals());
-
-  if (memtag_globalssz() == 0) {
-    DL_ERR("Invalid memtag descriptor pool size: %zu", memtag_globalssz());
-  }
-
-  uint64_t addr = load_bias;
-  uleb128_decoder decoder(descriptor_stream, memtag_globalssz());
-  // Don't ever generate tag zero, to easily distinguish between tagged and
-  // untagged globals in register/tag dumps.
-  uint64_t last_tag_mask = 1;
-  uint64_t last_tag = 1;
-  constexpr uint64_t kDistanceReservedBits = 3;
-
-  while (decoder.has_bytes()) {
-    uint64_t value = decoder.pop_front();
-    uint64_t distance = (value >> kDistanceReservedBits) * kTagGranuleSize;
-    uint64_t ngranules = value & ((1 << kDistanceReservedBits) - 1);
-    if (ngranules == 0) {
-      ngranules = decoder.pop_front() + 1;
-    }
-
-    addr += distance;
-    void* tagged_addr;
-    if (deterministic_memtag_globals) {
-      tagged_addr = reinterpret_cast<void*>(addr | (last_tag++ << 56));
-      if (last_tag > (1 << kTagGranuleSize)) last_tag = 1;
-    } else {
-      tagged_addr = insert_random_tag(reinterpret_cast<void*>(addr), last_tag_mask);
-      uint64_t tag = (reinterpret_cast<uint64_t>(tagged_addr) >> 56) & 0x0f;
-      last_tag_mask = 1 | (1 << tag);
-    }
-
-    for (size_t k = 0; k < ngranules; k++) {
-      auto* granule = static_cast<uint8_t*>(tagged_addr) + k * kTagGranuleSize;
-      set_memory_tag(static_cast<void*>(granule));
-    }
-    addr += ngranules * kTagGranuleSize;
-  }
-}
-
 static std::vector<android_namespace_t*> init_default_namespace_no_config(bool is_asan, bool is_hwasan) {
   g_default_namespace.set_isolated(false);
   auto default_ld_paths = is_asan ? kAsanDefaultLdPaths : (
diff --git a/linker/linker.h b/linker/linker.h
index b696fd9..ac2222d 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -179,8 +179,7 @@
 int get_application_target_sdk_version();
 ElfW(Versym) find_verdef_version_index(const soinfo* si, const version_info* vi);
 bool validate_verdef_section(const soinfo* si);
-bool relocate_relr(const ElfW(Relr) * begin, const ElfW(Relr) * end, ElfW(Addr) load_bias,
-                   bool has_memtag_globals);
+bool relocate_relr(const ElfW(Relr)* begin, const ElfW(Relr)* end, ElfW(Addr) load_bias);
 
 struct platform_properties {
 #if defined(__aarch64__)
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index f65f82d..48ed723 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -46,7 +46,6 @@
 #include "linker_tls.h"
 #include "linker_utils.h"
 
-#include "platform/bionic/macros.h"
 #include "private/KernelArgumentBlock.h"
 #include "private/bionic_call_ifunc_resolver.h"
 #include "private/bionic_globals.h"
@@ -72,9 +71,7 @@
 static void set_bss_vma_name(soinfo* si);
 
 void __libc_init_mte(const memtag_dynamic_entries_t* memtag_dynamic_entries, const void* phdr_start,
-                     size_t phdr_count, uintptr_t load_bias);
-
-void __libc_init_mte_stack(void* stack_top);
+                     size_t phdr_count, uintptr_t load_bias, void* stack_top);
 
 static void __linker_cannot_link(const char* argv0) {
   __linker_error("CANNOT LINK EXECUTABLE \"%s\": %s", argv0, linker_get_error_buffer());
@@ -368,8 +365,6 @@
   init_link_map_head(*solinker);
 
 #if defined(__aarch64__)
-  __libc_init_mte(somain->memtag_dynamic_entries(), somain->phdr, somain->phnum, somain->load_bias);
-
   if (exe_to_load == nullptr) {
     // Kernel does not add PROT_BTI to executable pages of the loaded ELF.
     // Apply appropriate protections here if it is needed.
@@ -470,7 +465,8 @@
 #if defined(__aarch64__)
   // This has to happen after the find_libraries, which will have collected any possible
   // libraries that request memtag_stack in the dynamic section.
-  __libc_init_mte_stack(args.argv);
+  __libc_init_mte(somain->memtag_dynamic_entries(), somain->phdr, somain->phnum, somain->load_bias,
+                  args.argv);
 #endif
 
   linker_finalize_static_tls();
@@ -629,13 +625,8 @@
     // Apply RELR relocations first so that the GOT is initialized for ifunc
     // resolvers.
     if (relr && relrsz) {
-      // Nothing has tagged the memtag globals here, so it is pointless either
-      // way to handle them, the tags will be zero anyway.
-      // That is moot though, because the linker does not use memtag_globals
-      // in the first place.
       relocate_relr(reinterpret_cast<ElfW(Relr*)>(ehdr + relr),
-                    reinterpret_cast<ElfW(Relr*)>(ehdr + relr + relrsz), ehdr,
-                    /*has_memtag_globals=*/ false);
+                    reinterpret_cast<ElfW(Relr*)>(ehdr + relr + relrsz), ehdr);
     }
     if (pltrel && pltrelsz) {
       call_ifunc_resolvers_for_section(reinterpret_cast<RelType*>(ehdr + pltrel),
@@ -655,16 +646,6 @@
   }
 }
 
-// Remapping MTE globals segments happens before the linker relocates itself, and so can't use
-// memcpy() from string.h. This function is compiled with -ffreestanding.
-void linker_memcpy(void* dst, const void* src, size_t n) {
-  char* dst_bytes = reinterpret_cast<char*>(dst);
-  const char* src_bytes = reinterpret_cast<const char*>(src);
-  for (size_t i = 0; i < n; ++i) {
-    dst_bytes[i] = src_bytes[i];
-  }
-}
-
 // Detect an attempt to run the linker on itself. e.g.:
 //   /system/bin/linker64 /system/bin/linker64
 // Use priority-1 to run this constructor before other constructors.
diff --git a/linker/linker_main.h b/linker/linker_main.h
index ffbcf0f..724f43c 100644
--- a/linker/linker_main.h
+++ b/linker/linker_main.h
@@ -70,5 +70,3 @@
 soinfo* solist_get_head();
 soinfo* solist_get_somain();
 soinfo* solist_get_vdso();
-
-void linker_memcpy(void* dst, const void* src, size_t n);
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 2bdd7f8..7691031 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -37,12 +37,9 @@
 #include <unistd.h>
 
 #include "linker.h"
-#include "linker_debug.h"
 #include "linker_dlwarning.h"
 #include "linker_globals.h"
-#include "linker_logger.h"
-#include "linker_main.h"
-#include "linker_soinfo.h"
+#include "linker_debug.h"
 #include "linker_utils.h"
 
 #include "private/bionic_asm_note.h"
@@ -1175,125 +1172,6 @@
                                    should_use_16kib_app_compat);
 }
 
-static bool segment_needs_memtag_globals_remapping(const ElfW(Phdr) * phdr) {
-  // For now, MTE globals is only supported on writeable data segments.
-  return phdr->p_type == PT_LOAD && !(phdr->p_flags & PF_X) && (phdr->p_flags & PF_W);
-}
-
-/* When MTE globals are requested by the binary, and when the hardware supports
- * it, remap the executable's PT_LOAD data pages to have PROT_MTE.
- *
- * Returns 0 on success, -1 on failure (error code in errno).
- */
-int remap_memtag_globals_segments(const ElfW(Phdr) * phdr_table __unused,
-                                  size_t phdr_count __unused, ElfW(Addr) load_bias __unused) {
-#if defined(__aarch64__)
-  for (const ElfW(Phdr)* phdr = phdr_table; phdr < phdr_table + phdr_count; phdr++) {
-    if (!segment_needs_memtag_globals_remapping(phdr)) {
-      continue;
-    }
-
-    uintptr_t seg_page_start = page_start(phdr->p_vaddr) + load_bias;
-    uintptr_t seg_page_end = page_end(phdr->p_vaddr + phdr->p_memsz) + load_bias;
-    size_t seg_page_aligned_size = seg_page_end - seg_page_start;
-
-    int prot = PFLAGS_TO_PROT(phdr->p_flags);
-    // For anonymous private mappings, it may be possible to simply mprotect()
-    // the PROT_MTE flag over the top. For file-based mappings, this will fail,
-    // and we'll need to fall back. We also allow PROT_WRITE here to allow
-    // writing memory tags (in `soinfo::tag_globals()`), and set these sections
-    // back to read-only after tags are applied (similar to RELRO).
-    prot |= PROT_MTE;
-    if (mprotect(reinterpret_cast<void*>(seg_page_start), seg_page_aligned_size,
-                 prot | PROT_WRITE) == 0) {
-      continue;
-    }
-
-    void* mapping_copy = mmap(nullptr, seg_page_aligned_size, PROT_READ | PROT_WRITE,
-                              MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-    linker_memcpy(mapping_copy, reinterpret_cast<void*>(seg_page_start), seg_page_aligned_size);
-
-    void* seg_addr = mmap(reinterpret_cast<void*>(seg_page_start), seg_page_aligned_size,
-                          prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-    if (seg_addr == MAP_FAILED) return -1;
-
-    linker_memcpy(seg_addr, mapping_copy, seg_page_aligned_size);
-    munmap(mapping_copy, seg_page_aligned_size);
-  }
-#endif  // defined(__aarch64__)
-  return 0;
-}
-
-void protect_memtag_globals_ro_segments(const ElfW(Phdr) * phdr_table __unused,
-                                        size_t phdr_count __unused, ElfW(Addr) load_bias __unused) {
-#if defined(__aarch64__)
-  for (const ElfW(Phdr)* phdr = phdr_table; phdr < phdr_table + phdr_count; phdr++) {
-    int prot = PFLAGS_TO_PROT(phdr->p_flags);
-    if (!segment_needs_memtag_globals_remapping(phdr) || (prot & PROT_WRITE)) {
-      continue;
-    }
-
-    prot |= PROT_MTE;
-
-    uintptr_t seg_page_start = page_start(phdr->p_vaddr) + load_bias;
-    uintptr_t seg_page_end = page_end(phdr->p_vaddr + phdr->p_memsz) + load_bias;
-    size_t seg_page_aligned_size = seg_page_end - seg_page_start;
-    mprotect(reinterpret_cast<void*>(seg_page_start), seg_page_aligned_size, prot);
-  }
-#endif  // defined(__aarch64__)
-}
-
-void name_memtag_globals_segments(const ElfW(Phdr) * phdr_table, size_t phdr_count,
-                                  ElfW(Addr) load_bias, const char* soname,
-                                  std::list<std::string>& vma_names) {
-  for (const ElfW(Phdr)* phdr = phdr_table; phdr < phdr_table + phdr_count; phdr++) {
-    if (!segment_needs_memtag_globals_remapping(phdr)) {
-      continue;
-    }
-
-    uintptr_t seg_page_start = page_start(phdr->p_vaddr) + load_bias;
-    uintptr_t seg_page_end = page_end(phdr->p_vaddr + phdr->p_memsz) + load_bias;
-    size_t seg_page_aligned_size = seg_page_end - seg_page_start;
-
-    // For file-based mappings that we're now forcing to be anonymous mappings, set the VMA name to
-    // make debugging easier.
-    // Once we are targeting only devices that run kernel 5.10 or newer (and thus include
-    // https://android-review.git.corp.google.com/c/kernel/common/+/1934723 which causes the
-    // VMA_ANON_NAME to be copied into the kernel), we can get rid of the storage here.
-    // For now, that is not the case:
-    // https://source.android.com/docs/core/architecture/kernel/android-common#compatibility-matrix
-    constexpr int kVmaNameLimit = 80;
-    std::string& vma_name = vma_names.emplace_back('\0', kVmaNameLimit);
-    int full_vma_length =
-        async_safe_format_buffer(vma_name.data(), kVmaNameLimit, "mt:%s+%" PRIxPTR, soname,
-                                 page_start(phdr->p_vaddr)) +
-        /* include the null terminator */ 1;
-    // There's an upper limit of 80 characters, including the null terminator, in the anonymous VMA
-    // name. If we run over that limit, we end up truncating the segment offset and parts of the
-    // DSO's name, starting on the right hand side of the basename. Because the basename is the most
-    // important thing, chop off the soname from the left hand side first.
-    //
-    // Example (with '#' as the null terminator):
-    //   - "mt:/data/nativetest64/bionic-unit-tests/bionic-loader-test-libs/libdlext_test.so+e000#"
-    //     is a `full_vma_length` == 86.
-    //
-    // We need to left-truncate (86 - 80) 6 characters from the soname, plus the
-    // `vma_truncation_prefix`, so 9 characters total.
-    if (full_vma_length > kVmaNameLimit) {
-      const char vma_truncation_prefix[] = "...";
-      int soname_truncated_bytes =
-          full_vma_length - kVmaNameLimit + sizeof(vma_truncation_prefix) - 1;
-      async_safe_format_buffer(vma_name.data(), kVmaNameLimit, "mt:%s%s+%" PRIxPTR,
-                               vma_truncation_prefix, soname + soname_truncated_bytes,
-                               page_start(phdr->p_vaddr));
-    }
-    if (prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, reinterpret_cast<void*>(seg_page_start),
-              seg_page_aligned_size, vma_name.data()) != 0) {
-      DL_WARN("Failed to re-name memtag global segment.");
-    }
-  }
-}
-
 /* Change the protection of all loaded segments in memory to writable.
  * This is useful before performing relocations. Once completed, you
  * will have to call phdr_table_protect_segments to restore the original
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index 353970c..2f159f3 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -39,8 +39,6 @@
 #include "linker_mapped_file_fragment.h"
 #include "linker_note_gnu_property.h"
 
-#include <list>
-
 #define MAYBE_MAP_FLAG(x, from, to)  (((x) & (from)) ? (to) : 0)
 #define PFLAGS_TO_PROT(x)            (MAYBE_MAP_FLAG((x), PF_X, PROT_EXEC) | \
                                       MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \
@@ -190,13 +188,3 @@
                                             ElfW(Addr) load_bias);
 
 bool page_size_migration_supported();
-
-int remap_memtag_globals_segments(const ElfW(Phdr) * phdr_table, size_t phdr_count,
-                                  ElfW(Addr) load_bias);
-
-void protect_memtag_globals_ro_segments(const ElfW(Phdr) * phdr_table, size_t phdr_count,
-                                        ElfW(Addr) load_bias);
-
-void name_memtag_globals_segments(const ElfW(Phdr) * phdr_table, size_t phdr_count,
-                                  ElfW(Addr) load_bias, const char* soname,
-                                  std::list<std::string>& vma_names);
diff --git a/linker/linker_phdr_16kib_compat.cpp b/linker/linker_phdr_16kib_compat.cpp
index e084635..a4d8459 100644
--- a/linker/linker_phdr_16kib_compat.cpp
+++ b/linker/linker_phdr_16kib_compat.cpp
@@ -223,8 +223,6 @@
   // the zip offset must be added to find the segment offset.
   const ElfW(Addr) offset = file_offset_ + align_down(phdr->p_offset, kCompatPageSize);
 
-  int prot = PFLAGS_TO_PROT(phdr->p_flags);
-
   CHECK(should_use_16kib_app_compat_);
 
   // Since the 4KiB max-page-size ELF is not properly aligned, loading it by
diff --git a/linker/linker_relocate.cpp b/linker/linker_relocate.cpp
index bbf8359..0470f87 100644
--- a/linker/linker_relocate.cpp
+++ b/linker/linker_relocate.cpp
@@ -44,8 +44,6 @@
 #include "linker_soinfo.h"
 #include "private/bionic_globals.h"
 
-#include <platform/bionic/mte.h>
-
 static bool is_tls_reloc(ElfW(Word) type) {
   switch (type) {
     case R_GENERIC_TLS_DTPMOD:
@@ -165,8 +163,7 @@
 static bool process_relocation_impl(Relocator& relocator, const rel_t& reloc) {
   constexpr bool IsGeneral = Mode == RelocMode::General;
 
-  void* const rel_target = reinterpret_cast<void*>(
-      relocator.si->apply_memtag_if_mte_globals(reloc.r_offset + relocator.si->load_bias));
+  void* const rel_target = reinterpret_cast<void*>(reloc.r_offset + relocator.si->load_bias);
   const uint32_t r_type = ELFW(R_TYPE)(reloc.r_info);
   const uint32_t r_sym = ELFW(R_SYM)(reloc.r_info);
 
@@ -319,7 +316,6 @@
     // common in non-platform binaries.
     if (r_type == R_GENERIC_ABSOLUTE) {
       count_relocation_if<IsGeneral>(kRelocAbsolute);
-      if (found_in) sym_addr = found_in->apply_memtag_if_mte_globals(sym_addr);
       const ElfW(Addr) result = sym_addr + get_addend_rel();
       LD_DEBUG(reloc && IsGeneral, "RELO ABSOLUTE %16p <- %16p %s",
                rel_target, reinterpret_cast<void*>(result), sym_name);
@@ -330,7 +326,6 @@
       // document (IHI0044F) specifies that R_ARM_GLOB_DAT has an addend, but Bionic isn't adding
       // it.
       count_relocation_if<IsGeneral>(kRelocAbsolute);
-      if (found_in) sym_addr = found_in->apply_memtag_if_mte_globals(sym_addr);
       const ElfW(Addr) result = sym_addr + get_addend_norel();
       LD_DEBUG(reloc && IsGeneral, "RELO GLOB_DAT %16p <- %16p %s",
                rel_target, reinterpret_cast<void*>(result), sym_name);
@@ -340,18 +335,7 @@
       // In practice, r_sym is always zero, but if it weren't, the linker would still look up the
       // referenced symbol (and abort if the symbol isn't found), even though it isn't used.
       count_relocation_if<IsGeneral>(kRelocRelative);
-      ElfW(Addr) result = relocator.si->load_bias + get_addend_rel();
-      // MTE globals reuses the place bits for additional tag-derivation metadata for
-      // R_AARCH64_RELATIVE relocations, which makes it incompatible with
-      // `-Wl,--apply-dynamic-relocs`. This is enforced by lld, however there's nothing stopping
-      // Android binaries (particularly prebuilts) from building with this linker flag if they're
-      // not built with MTE globals. Thus, don't use the new relocation semantics if this DSO
-      // doesn't have MTE globals.
-      if (relocator.si->should_tag_memtag_globals()) {
-        int64_t* place = static_cast<int64_t*>(rel_target);
-        int64_t offset = *place;
-        result = relocator.si->apply_memtag_if_mte_globals(result + offset) - offset;
-      }
+      const ElfW(Addr) result = relocator.si->load_bias + get_addend_rel();
       LD_DEBUG(reloc && IsGeneral, "RELO RELATIVE %16p <- %16p",
                rel_target, reinterpret_cast<void*>(result));
       *static_cast<ElfW(Addr)*>(rel_target) = result;
@@ -616,7 +600,7 @@
     LD_DEBUG(reloc, "[ relocating %s relr ]", get_realpath());
     const ElfW(Relr)* begin = relr_;
     const ElfW(Relr)* end = relr_ + relr_count_;
-    if (!relocate_relr(begin, end, load_bias, should_tag_memtag_globals())) {
+    if (!relocate_relr(begin, end, load_bias)) {
       return false;
     }
   }
diff --git a/linker/linker_sleb128.h b/linker/linker_sleb128.h
index f48fda8..6bb3199 100644
--- a/linker/linker_sleb128.h
+++ b/linker/linker_sleb128.h
@@ -69,32 +69,3 @@
   const uint8_t* current_;
   const uint8_t* const end_;
 };
-
-class uleb128_decoder {
- public:
-  uleb128_decoder(const uint8_t* buffer, size_t count) : current_(buffer), end_(buffer + count) {}
-
-  uint64_t pop_front() {
-    uint64_t value = 0;
-
-    size_t shift = 0;
-    uint8_t byte;
-
-    do {
-      if (current_ >= end_) {
-        async_safe_fatal("uleb128_decoder ran out of bounds");
-      }
-      byte = *current_++;
-      value |= (static_cast<size_t>(byte & 127) << shift);
-      shift += 7;
-    } while (byte & 128);
-
-    return value;
-  }
-
-  bool has_bytes() { return current_ < end_; }
-
- private:
-  const uint8_t* current_;
-  const uint8_t* const end_;
-};
diff --git a/linker/linker_soinfo.cpp b/linker/linker_soinfo.cpp
index 176c133..0549d36 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -44,8 +44,6 @@
 #include "linker_logger.h"
 #include "linker_relocate.h"
 #include "linker_utils.h"
-#include "platform/bionic/mte.h"
-#include "private/bionic_globals.h"
 
 SymbolLookupList::SymbolLookupList(soinfo* si)
     : sole_lib_(si->get_lookup_lib()), begin_(&sole_lib_), end_(&sole_lib_ + 1) {
@@ -306,12 +304,6 @@
   return is_gnu_hash() ? gnu_lookup(symbol_name, vi) : elf_lookup(symbol_name, vi);
 }
 
-ElfW(Addr) soinfo::apply_memtag_if_mte_globals(ElfW(Addr) sym_addr) const {
-  if (!should_tag_memtag_globals()) return sym_addr;
-  if (sym_addr == 0) return sym_addr;  // Handle undefined weak symbols.
-  return reinterpret_cast<ElfW(Addr)>(get_tagged_address(reinterpret_cast<void*>(sym_addr)));
-}
-
 const ElfW(Sym)* soinfo::gnu_lookup(SymbolName& symbol_name, const version_info* vi) const {
   const uint32_t hash = symbol_name.gnu_hash();
 
diff --git a/linker/linker_soinfo.h b/linker/linker_soinfo.h
index 64f8aea..a776c1f 100644
--- a/linker/linker_soinfo.h
+++ b/linker/linker_soinfo.h
@@ -30,7 +30,6 @@
 
 #include <link.h>
 
-#include <list>
 #include <memory>
 #include <string>
 #include <vector>
@@ -67,10 +66,9 @@
                                          // soinfo is executed and this flag is
                                          // unset.
 #define FLAG_PRELINKED        0x00000400 // prelink_image has successfully processed this soinfo
-#define FLAG_GLOBALS_TAGGED   0x00000800 // globals have been tagged by MTE.
 #define FLAG_NEW_SOINFO       0x40000000 // new soinfo format
 
-#define SOINFO_VERSION 7
+#define SOINFO_VERSION 6
 
 ElfW(Addr) call_ifunc_resolver(ElfW(Addr) resolver_addr);
 
@@ -254,14 +252,11 @@
   void call_constructors();
   void call_destructors();
   void call_pre_init_constructors();
-  bool prelink_image(bool deterministic_memtag_globals = false);
+  bool prelink_image();
   bool link_image(const SymbolLookupList& lookup_list, soinfo* local_group_root,
                   const android_dlextinfo* extinfo, size_t* relro_fd_offset);
   bool protect_relro();
 
-  void tag_globals(bool deterministic_memtag_globals);
-  ElfW(Addr) apply_memtag_if_mte_globals(ElfW(Addr) sym_addr) const;
-
   void add_child(soinfo* child);
   void remove_all_links();
 
@@ -373,10 +368,6 @@
    should_pad_segments_ = should_pad_segments;
   }
   bool should_pad_segments() const { return should_pad_segments_; }
-  bool should_tag_memtag_globals() const {
-    return !is_linker() && memtag_globals() && memtag_globalssz() > 0 && __libc_mte_enabled();
-  }
-  std::list<std::string>& vma_names() { return vma_names_; };
 
   void set_should_use_16kib_app_compat(bool should_use_16kib_app_compat) {
     should_use_16kib_app_compat_ = should_use_16kib_app_compat;
@@ -473,8 +464,6 @@
   // version >= 7
   memtag_dynamic_entries_t memtag_dynamic_entries_;
 
-  std::list<std::string> vma_names_;
-
   // Pad gaps between segments when memory mapping?
   bool should_pad_segments_ = false;
 
diff --git a/tests/Android.bp b/tests/Android.bp
index ea03c08..b537483 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -429,7 +429,6 @@
         "math_test.cpp",
         "membarrier_test.cpp",
         "memtag_stack_test.cpp",
-        "memtag_globals_test.cpp",
         "mntent_test.cpp",
         "mte_test.cpp",
         "netdb_test.cpp",
@@ -897,11 +896,6 @@
         "preinit_syscall_test_helper",
         "thread_exit_cb_helper",
         "tls_properties_helper",
-        "memtag_globals_binary",
-        "memtag_globals_binary_static",
-        "mte_globals_relr_regression_test_b_314038442",
-        "mte_globals_relr_regression_test_b_314038442_mte",
-        "memtag_globals_dso",
     ],
     data_libs: [
         "libatest_simple_zip",
@@ -1223,6 +1217,7 @@
 
     shared_libs: [
         "libbase",
+        "liblog",
     ],
 
     target: {
@@ -1292,11 +1287,6 @@
         "heap_tagging_static_disabled_helper",
         "heap_tagging_static_sync_helper",
         "heap_tagging_sync_helper",
-        "memtag_globals_binary",
-        "memtag_globals_binary_static",
-        "memtag_globals_dso",
-        "mte_globals_relr_regression_test_b_314038442",
-        "mte_globals_relr_regression_test_b_314038442_mte",
         "stack_tagging_helper",
         "stack_tagging_static_helper",
     ],
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 8b26cb0..570da2a 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -21,7 +21,6 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
-#include <link.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
@@ -41,13 +40,11 @@
 #include <procinfo/process_map.h>
 #include <ziparchive/zip_archive.h>
 
-#include "bionic/mte.h"
-#include "bionic/page.h"
 #include "core_shared_libs.h"
-#include "dlext_private.h"
-#include "dlfcn_symlink_support.h"
 #include "gtest_globals.h"
 #include "utils.h"
+#include "dlext_private.h"
+#include "dlfcn_symlink_support.h"
 
 #define ASSERT_DL_NOTNULL(ptr) \
     ASSERT_TRUE((ptr) != nullptr) << "dlerror: " << dlerror()
@@ -1961,14 +1958,6 @@
   dlclose(ns_a_handle3);
 }
 
-static inline int MapPflagsToProtFlags(uint32_t flags) {
-  int prot_flags = 0;
-  if (PF_X & flags) prot_flags |= PROT_EXEC;
-  if (PF_W & flags) prot_flags |= PROT_WRITE;
-  if (PF_R & flags) prot_flags |= PROT_READ;
-  return prot_flags;
-}
-
 TEST(dlext, ns_anonymous) {
   static const char* root_lib = "libnstest_root.so";
   std::string shared_libs = g_core_shared_libs + ":" + g_public_lib;
@@ -2010,45 +1999,30 @@
   typedef const char* (*fn_t)();
   fn_t ns_get_dlopened_string_private = reinterpret_cast<fn_t>(ns_get_dlopened_string_addr);
 
-  Dl_info private_library_info;
-  ASSERT_NE(dladdr(reinterpret_cast<void*>(ns_get_dlopened_string_addr), &private_library_info), 0)
-      << dlerror();
-  std::vector<map_record> maps_to_copy;
-  bool has_executable_segment = false;
+  std::vector<map_record> maps;
+  Maps::parse_maps(&maps);
+
   uintptr_t addr_start = 0;
   uintptr_t addr_end = 0;
-  std::tuple dl_iterate_arg = {&private_library_info, &maps_to_copy, &has_executable_segment,
-                               &addr_start, &addr_end};
-  ASSERT_EQ(
-      1, dl_iterate_phdr(
-             [](dl_phdr_info* info, size_t /*size*/, void* data) -> int {
-               auto [private_library_info, maps_to_copy, has_executable_segment, addr_start,
-                     addr_end] = *reinterpret_cast<decltype(dl_iterate_arg)*>(data);
-               if (info->dlpi_addr != reinterpret_cast<ElfW(Addr)>(private_library_info->dli_fbase))
-                 return 0;
+  bool has_executable_segment = false;
+  std::vector<map_record> maps_to_copy;
 
-               for (size_t i = 0; i < info->dlpi_phnum; ++i) {
-                 const ElfW(Phdr)* phdr = info->dlpi_phdr + i;
-                 if (phdr->p_type != PT_LOAD) continue;
-                 *has_executable_segment |= phdr->p_flags & PF_X;
-                 uintptr_t mapping_start = page_start(info->dlpi_addr + phdr->p_vaddr);
-                 uintptr_t mapping_end = page_end(info->dlpi_addr + phdr->p_vaddr + phdr->p_memsz);
-                 if (*addr_start == 0 || mapping_start < *addr_start) *addr_start = mapping_start;
-                 if (*addr_end == 0 || mapping_end > *addr_end) *addr_end = mapping_end;
-                 maps_to_copy->push_back({
-                     .addr_start = mapping_start,
-                     .addr_end = mapping_end,
-                     .perms = MapPflagsToProtFlags(phdr->p_flags),
-                 });
-               }
-               return 1;
-             },
-             &dl_iterate_arg));
+  for (const auto& rec : maps) {
+    if (rec.pathname == private_library_absolute_path) {
+      if (addr_start == 0) {
+        addr_start = rec.addr_start;
+      }
+      addr_end = rec.addr_end;
+      has_executable_segment = has_executable_segment || (rec.perms & PROT_EXEC) != 0;
+
+      maps_to_copy.push_back(rec);
+    }
+  }
 
   // Some validity checks.
-  ASSERT_NE(maps_to_copy.size(), 0u);
   ASSERT_TRUE(addr_start > 0);
   ASSERT_TRUE(addr_end > 0);
+  ASSERT_TRUE(maps_to_copy.size() > 0);
   ASSERT_TRUE(ns_get_dlopened_string_addr > addr_start);
   ASSERT_TRUE(ns_get_dlopened_string_addr < addr_end);
 
@@ -2078,26 +2052,19 @@
   ASSERT_EQ(ret, 0) << "Failed to stat library";
   size_t file_size = file_stat.st_size;
 
-  {
-    // Disable MTE while copying the PROT_MTE-protected global variables from
-    // the existing mappings. We don't really care about turning on PROT_MTE for
-    // the new copy of the mappings, as this isn't the behaviour under test and
-    // tags will be ignored. This only applies for MTE-enabled devices.
-    ScopedDisableMTE disable_mte_for_copying_global_variables;
-    for (const auto& rec : maps_to_copy) {
-      uintptr_t offset = rec.addr_start - addr_start;
-      size_t size = rec.addr_end - rec.addr_start;
-      void* addr = reinterpret_cast<void*>(reserved_addr + offset);
-      void* map =
-          mmap(addr, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
-      ASSERT_TRUE(map != MAP_FAILED);
-      // Attempting the below memcpy from a portion of the map that is off the end of
-      // the backing file will cause the kernel to throw a SIGBUS
-      size_t _size =
-          ::android::procinfo::MappedFileSize(rec.addr_start, rec.addr_end, rec.offset, file_size);
-      memcpy(map, reinterpret_cast<void*>(rec.addr_start), _size);
-      mprotect(map, size, rec.perms);
-    }
+  for (const auto& rec : maps_to_copy) {
+    uintptr_t offset = rec.addr_start - addr_start;
+    size_t size = rec.addr_end - rec.addr_start;
+    void* addr = reinterpret_cast<void*>(reserved_addr + offset);
+    void* map = mmap(addr, size, PROT_READ | PROT_WRITE,
+                     MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
+    ASSERT_TRUE(map != MAP_FAILED);
+    // Attempting the below memcpy from a portion of the map that is off the end of
+    // the backing file will cause the kernel to throw a SIGBUS
+    size_t _size = ::android::procinfo::MappedFileSize(rec.addr_start, rec.addr_end,
+                                                       rec.offset, file_size);
+    memcpy(map, reinterpret_cast<void*>(rec.addr_start), _size);
+    mprotect(map, size, rec.perms);
   }
 
   // call the function copy
diff --git a/tests/headers/posix/stdatomic_h.c b/tests/headers/posix/stdatomic_h.c
new file mode 100644
index 0000000..05be859
--- /dev/null
+++ b/tests/headers/posix/stdatomic_h.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdatomic.h>
+
+#include "header_checks.h"
+
+static void stdatomic_h() {
+  TYPE(atomic_flag);
+  TYPE(atomic_bool);
+  TYPE(atomic_char);
+  TYPE(atomic_schar);
+  TYPE(atomic_uchar);
+  TYPE(atomic_short);
+  TYPE(atomic_ushort);
+  TYPE(atomic_int);
+  TYPE(atomic_uint);
+  TYPE(atomic_long);
+  TYPE(atomic_ulong);
+  TYPE(atomic_llong);
+  TYPE(atomic_ullong);
+#if !defined(__GLIBC__)
+  TYPE(atomic_char16_t);
+  TYPE(atomic_char32_t);
+#endif
+  TYPE(atomic_wchar_t);
+  TYPE(atomic_int_least8_t);
+  TYPE(atomic_uint_least8_t);
+  TYPE(atomic_int_least16_t);
+  TYPE(atomic_uint_least16_t);
+  TYPE(atomic_int_least32_t);
+  TYPE(atomic_uint_least32_t);
+  TYPE(atomic_int_least64_t);
+  TYPE(atomic_uint_least64_t);
+  TYPE(atomic_int_fast8_t);
+  TYPE(atomic_uint_fast8_t);
+  TYPE(atomic_int_fast16_t);
+  TYPE(atomic_uint_fast16_t);
+  TYPE(atomic_int_fast32_t);
+  TYPE(atomic_uint_fast32_t);
+  TYPE(atomic_int_fast64_t);
+  TYPE(atomic_uint_fast64_t);
+  TYPE(atomic_intptr_t);
+  TYPE(atomic_uintptr_t);
+  TYPE(atomic_size_t);
+  TYPE(atomic_ptrdiff_t);
+  TYPE(atomic_intmax_t);
+  TYPE(atomic_uintmax_t);
+
+  memory_order m1 = memory_order_relaxed;
+  memory_order m2 = memory_order_consume;
+  memory_order m3 = memory_order_acquire;
+  memory_order m4 = memory_order_release;
+  memory_order m5 = memory_order_acq_rel;
+  memory_order m6 = memory_order_seq_cst;
+
+  MACRO(ATOMIC_BOOL_LOCK_FREE);
+  MACRO(ATOMIC_CHAR_LOCK_FREE);
+  MACRO(ATOMIC_CHAR16_T_LOCK_FREE);
+  MACRO(ATOMIC_CHAR32_T_LOCK_FREE);
+  MACRO(ATOMIC_WCHAR_T_LOCK_FREE);
+  MACRO(ATOMIC_SHORT_LOCK_FREE);
+  MACRO(ATOMIC_INT_LOCK_FREE);
+  MACRO(ATOMIC_LONG_LOCK_FREE);
+  MACRO(ATOMIC_LLONG_LOCK_FREE);
+  MACRO(ATOMIC_POINTER_LOCK_FREE);
+
+  atomic_flag f = ATOMIC_FLAG_INIT;
+  atomic_int i = ATOMIC_VAR_INIT(123);
+
+  // TODO: remove this #if after the next toolchain update (http://b/374104004).
+#if !defined(__GLIBC__)
+  i = kill_dependency(i);
+#endif
+
+#if !defined(atomic_compare_exchange_strong)
+#error atomic_compare_exchange_strong
+#endif
+#if !defined(atomic_compare_exchange_strong_explicit)
+#error atomic_compare_exchange_strong_explicit
+#endif
+#if !defined(atomic_compare_exchange_weak)
+#error atomic_compare_exchange_weak
+#endif
+#if !defined(atomic_compare_exchange_weak_explicit)
+#error atomic_compare_exchange_weak_explicit
+#endif
+#if !defined(atomic_exchange)
+#error atomic_exchange
+#endif
+#if !defined(atomic_exchange_explicit)
+#error atomic_exchange_explicit
+#endif
+#if !defined(atomic_fetch_add)
+#error atomic_fetch_add
+#endif
+#if !defined(atomic_fetch_add_explicit)
+#error atomic_fetch_add_explicit
+#endif
+#if !defined(atomic_fetch_and)
+#error atomic_fetch_and
+#endif
+#if !defined(atomic_fetch_and_explicit)
+#error atomic_fetch_and_explicit
+#endif
+#if !defined(atomic_fetch_or)
+#error atomic_fetch_or
+#endif
+#if !defined(atomic_fetch_or_explicit)
+#error atomic_fetch_or_explicit
+#endif
+#if !defined(atomic_fetch_sub)
+#error atomic_fetch_sub
+#endif
+#if !defined(atomic_fetch_sub_explicit)
+#error atomic_fetch_sub_explicit
+#endif
+#if !defined(atomic_fetch_xor)
+#error atomic_fetch_xor
+#endif
+#if !defined(atomic_fetch_xor_explicit)
+#error atomic_fetch_xor_explicit
+#endif
+#if !defined(atomic_init)
+#error atomic_init
+#endif
+#if !defined(atomic_is_lock_free)
+#error atomic_is_lock_free
+#endif
+#if !defined(atomic_load)
+#error atomic_load
+#endif
+#if !defined(atomic_load_explicit)
+#error atomic_load_explicit
+#endif
+#if !defined(atomic_store)
+#error atomic_store
+#endif
+#if !defined(atomic_store_explicit)
+#error atomic_store_explicit
+#endif
+
+  FUNCTION(atomic_flag_clear, void (*f)(volatile atomic_flag*));
+  FUNCTION(atomic_flag_clear_explicit, void (*f)(volatile atomic_flag*, memory_order));
+  FUNCTION(atomic_flag_test_and_set, bool (*f)(volatile atomic_flag*));
+  FUNCTION(atomic_flag_test_and_set_explicit, bool (*f)(volatile atomic_flag*, memory_order));
+
+  FUNCTION(atomic_signal_fence, void (*f)(memory_order));
+  FUNCTION(atomic_thread_fence, void (*f)(memory_order));
+}
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 5b86e78..d13ee60 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -1903,89 +1903,3 @@
         " $(location soong_zip) -o $(out).unaligned -L 0 -C $(genDir)/zipdir -D $(genDir)/zipdir &&" +
         " $(location bionic_tests_zipalign) 16384 $(out).unaligned $(out)",
 }
-
-cc_defaults {
-    name: "memtag_globals_defaults",
-    defaults: [
-        "bionic_testlib_defaults",
-        "bionic_targets_only"
-    ],
-    cflags: [
-        "-Wno-array-bounds",
-        "-Wno-unused-variable",
-    ],
-    header_libs: ["bionic_libc_platform_headers"],
-    sanitize: {
-        hwaddress: false,
-        memtag_heap: true,
-        memtag_globals: true,
-        diag: {
-            memtag_heap: true,
-        }
-    },
-}
-
-cc_test_library {
-    name: "memtag_globals_dso",
-    defaults: [ "memtag_globals_defaults" ],
-    srcs: ["memtag_globals_dso.cpp"],
-}
-
-cc_test {
-    name: "memtag_globals_binary",
-    defaults: [ "memtag_globals_defaults" ],
-    srcs: ["memtag_globals_binary.cpp"],
-    shared_libs: [ "memtag_globals_dso" ],
-    // This binary is used in the bionic-unit-tests as a data dependency, and is
-    // in the same folder as memtag_globals_dso. But, the default cc_test rules
-    // make this binary (when just explicitly built and shoved in
-    // /data/nativetest64/) end up in a subfolder called
-    // 'memtag_globals_binary'. When this happens, the explicit build fails to
-    // find the DSO because the default rpath is just ${ORIGIN}, and because we
-    // want this to be usable both from bionic-unit-tests and explicit builds,
-    // let's just not put it in a subdirectory.
-    no_named_install_directory: true,
-}
-
-cc_test {
-    name: "memtag_globals_binary_static",
-    defaults: [ "memtag_globals_defaults" ],
-    srcs: ["memtag_globals_binary.cpp"],
-    static_libs: [ "memtag_globals_dso" ],
-    no_named_install_directory: true,
-    static_executable: true,
-}
-
-// This is a regression test for b/314038442, where binaries built *without* MTE
-// globals would have out-of-bounds RELR relocations, which where then `ldg`'d,
-// which resulted in linker crashes.
-cc_test {
-  name: "mte_globals_relr_regression_test_b_314038442",
-  defaults: [
-        "bionic_testlib_defaults",
-        "bionic_targets_only"
-    ],
-    cflags: [ "-Wno-array-bounds" ],
-    ldflags: [ "-Wl,--pack-dyn-relocs=relr" ],
-    srcs: ["mte_globals_relr_regression_test_b_314038442.cpp"],
-    no_named_install_directory: true,
-    sanitize: {
-        memtag_globals: false,
-    },
-}
-
-// Same test as above, but also for MTE globals, just for the sake of it.
-cc_test {
-  name: "mte_globals_relr_regression_test_b_314038442_mte",
-  defaults: [
-        "bionic_testlib_defaults",
-        "bionic_targets_only"
-    ],
-    cflags: [ "-Wno-array-bounds" ],
-    ldflags: [ "-Wl,--pack-dyn-relocs=relr" ],
-    srcs: ["mte_globals_relr_regression_test_b_314038442.cpp"],
-    no_named_install_directory: true,
-    sanitize: {
-      memtag_globals: true,
-    },
-}
diff --git a/tests/libs/memtag_globals_binary.cpp b/tests/libs/memtag_globals_binary.cpp
deleted file mode 100644
index 9248728..0000000
--- a/tests/libs/memtag_globals_binary.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <string>
-#include <vector>
-
-#include "memtag_globals.h"
-
-// Adapted from the LLD test suite: lld/test/ELF/Inputs/aarch64-memtag-globals.s
-
-/// Global variables defined here, of various semantics.
-char global[30] = {};
-__attribute__((no_sanitize("memtag"))) int global_untagged = 0;
-const int const_global = 0;
-static const int hidden_const_global = 0;
-static char hidden_global[12] = {};
-__attribute__((visibility("hidden"))) int hidden_attr_global = 0;
-__attribute__((visibility("hidden"))) const int hidden_attr_const_global = 0;
-
-/// Should be untagged.
-__thread int tls_global;
-__thread static int hidden_tls_global;
-
-/// Tagged, from the other file.
-extern int global_extern;
-/// Untagged, from the other file.
-extern __attribute__((no_sanitize("memtag"))) int global_extern_untagged;
-/// Tagged here, but untagged in the definition found in the sister objfile
-/// (explicitly).
-extern int global_extern_untagged_definition_but_tagged_import;
-
-/// ABS64 relocations. Also, forces symtab entries for local and external
-/// globals.
-char* pointer_to_global = &global[0];
-char* pointer_inside_global = &global[17];
-char* pointer_to_global_end = &global[30];
-char* pointer_past_global_end = &global[48];
-int* pointer_to_global_untagged = &global_untagged;
-const int* pointer_to_const_global = &const_global;
-/// RELATIVE relocations.
-const int* pointer_to_hidden_const_global = &hidden_const_global;
-char* pointer_to_hidden_global = &hidden_global[0];
-int* pointer_to_hidden_attr_global = &hidden_attr_global;
-const int* pointer_to_hidden_attr_const_global = &hidden_attr_const_global;
-/// RELATIVE relocations with special AArch64 MemtagABI semantics, with the
-/// offset ('12' or '16') encoded in the place.
-char* pointer_to_hidden_global_end = &hidden_global[12];
-char* pointer_past_hidden_global_end = &hidden_global[16];
-/// ABS64 relocations.
-int* pointer_to_global_extern = &global_extern;
-int* pointer_to_global_extern_untagged = &global_extern_untagged;
-int* pointer_to_global_extern_untagged_definition_but_tagged_import =
-    &global_extern_untagged_definition_but_tagged_import;
-
-// Force materialization of these globals into the symtab.
-int* get_address_to_tls_global() {
-  return &tls_global;
-}
-int* get_address_to_hidden_tls_global() {
-  return &hidden_tls_global;
-}
-
-static const std::vector<std::pair<const char*, const void*>>& get_expected_tagged_vars() {
-  static std::vector<std::pair<const char*, const void*>> expected_tagged_vars = {
-      {"global", &global},
-      {"pointer_inside_global", pointer_inside_global},
-      {"pointer_to_global_end", pointer_to_global_end},
-      {"pointer_past_global_end", pointer_past_global_end},
-      {"hidden_global", &hidden_global},
-      {"hidden_attr_global", &hidden_attr_global},
-      {"global_extern", &global_extern},
-  };
-  return expected_tagged_vars;
-}
-
-static const std::vector<std::pair<const char*, const void*>>& get_expected_untagged_vars() {
-  static std::vector<std::pair<const char*, const void*>> expected_untagged_vars = {
-      {"global_extern_untagged", &global_extern_untagged},
-      {"global_extern_untagged_definition_but_tagged_import",
-       &global_extern_untagged_definition_but_tagged_import},
-      {"global_untagged", &global_untagged},
-      {"const_global", &const_global},
-      {"hidden_const_global", &hidden_const_global},
-      {"hidden_attr_const_global", &hidden_attr_const_global},
-      {"tls_global", &tls_global},
-      {"hidden_tls_global", &hidden_tls_global},
-  };
-  return expected_untagged_vars;
-}
-
-void exe_print_variables() {
-  print_variables("  Variables accessible from the binary:\n", get_expected_tagged_vars(),
-                  get_expected_untagged_vars());
-}
-
-// Dump the addresses of the global variables to stderr
-void dso_print();
-void dso_print_others();
-
-void exe_check_assertions(bool check_pointers_are_tagged) {
-  // Check that non-const variables are writeable.
-  *pointer_to_global = 0;
-  *pointer_inside_global = 0;
-  *(pointer_to_global_end - 1) = 0;
-  *pointer_to_global_untagged = 0;
-  *pointer_to_hidden_global = 0;
-  *pointer_to_hidden_attr_global = 0;
-  *(pointer_to_hidden_global_end - 1) = 0;
-  *pointer_to_global_extern = 0;
-  *pointer_to_global_extern_untagged = 0;
-  *pointer_to_global_extern_untagged_definition_but_tagged_import = 0;
-
-  if (check_pointers_are_tagged) {
-    for (const auto& [_, pointer] : get_expected_tagged_vars()) {
-      check_tagged(pointer);
-    }
-  }
-
-  for (const auto& [_, pointer] : get_expected_untagged_vars()) {
-    check_untagged(pointer);
-  }
-
-  check_matching_tags(pointer_to_global, pointer_inside_global);
-  check_matching_tags(pointer_to_global, pointer_to_global_end);
-  check_matching_tags(pointer_to_global, pointer_past_global_end);
-  check_eq(pointer_inside_global, pointer_to_global + 17);
-  check_eq(pointer_to_global_end, pointer_to_global + 30);
-  check_eq(pointer_past_global_end, pointer_to_global + 48);
-
-  check_matching_tags(pointer_to_hidden_global, pointer_to_hidden_global_end);
-  check_matching_tags(pointer_to_hidden_global, pointer_past_hidden_global_end);
-  check_eq(pointer_to_hidden_global_end, pointer_to_hidden_global + 12);
-  check_eq(pointer_past_hidden_global_end, pointer_to_hidden_global + 16);
-}
-
-void crash() {
-  *pointer_past_global_end = 0;
-}
-
-int main(int argc, char** argv) {
-  bool check_pointers_are_tagged = false;
-  // For an MTE-capable device, provide argv[1] == '1' to enable the assertions
-  // that pointers should be tagged.
-  if (argc >= 2 && argv[1][0] == '1') {
-    check_pointers_are_tagged = true;
-  }
-
-  char* heap_ptr = static_cast<char*>(malloc(1));
-  print_variable_address("heap address", heap_ptr);
-  *heap_ptr = 0;
-  if (check_pointers_are_tagged) check_tagged(heap_ptr);
-  free(heap_ptr);
-
-  exe_print_variables();
-  dso_print_variables();
-
-  exe_check_assertions(check_pointers_are_tagged);
-  dso_check_assertions(check_pointers_are_tagged);
-
-  printf("Assertions were passed. Now doing a global-buffer-overflow.\n");
-  fflush(stdout);
-  crash();
-  printf("global-buffer-overflow went uncaught.\n");
-  return 0;
-}
diff --git a/tests/libs/memtag_globals_dso.cpp b/tests/libs/memtag_globals_dso.cpp
deleted file mode 100644
index 9ed264e..0000000
--- a/tests/libs/memtag_globals_dso.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <vector>
-
-#include "memtag_globals.h"
-
-// Adapted from the LLD test suite: lld/test/ELF/Inputs/aarch64-memtag-globals.s
-
-int global_extern;
-static int global_extern_hidden;
-__attribute__((no_sanitize("memtag"))) int global_extern_untagged;
-__attribute__((no_sanitize("memtag"))) int global_extern_untagged_definition_but_tagged_import;
-
-void assertion_failure() {
-  exit(1);
-}
-
-void check_tagged(const void* a) {
-  uintptr_t a_uptr = reinterpret_cast<uintptr_t>(a);
-#if defined(__aarch64__)
-  if ((a_uptr >> 56) == 0) {
-    fprintf(stderr, "**********************************\n");
-    fprintf(stderr, "Failed assertion:\n");
-    fprintf(stderr, "  tag(0x%zx) != 0\n", a_uptr);
-    fprintf(stderr, "**********************************\n");
-
-    assertion_failure();
-  }
-#endif  // defined(__aarch64__)
-}
-
-void check_untagged(const void* a) {
-  uintptr_t a_uptr = reinterpret_cast<uintptr_t>(a);
-#if defined(__aarch64__)
-  if ((a_uptr >> 56) != 0) {
-    fprintf(stderr, "**********************************\n");
-    fprintf(stderr, "Failed assertion:\n");
-    fprintf(stderr, "  tag(0x%zx) == 0\n", a_uptr);
-    fprintf(stderr, "**********************************\n");
-
-    assertion_failure();
-  }
-#endif  // defined(__aarch64__)
-}
-
-void check_matching_tags(const void* a, const void* b) {
-  uintptr_t a_uptr = reinterpret_cast<uintptr_t>(a);
-  uintptr_t b_uptr = reinterpret_cast<uintptr_t>(b);
-#if defined(__aarch64__)
-  if (a_uptr >> 56 != b_uptr >> 56) {
-    fprintf(stderr, "**********************************\n");
-    fprintf(stderr, "Failed assertion:\n");
-    fprintf(stderr, "  tag(0x%zx) != tag(0x%zx)\n", a_uptr, b_uptr);
-    fprintf(stderr, "**********************************\n");
-
-    assertion_failure();
-  }
-#endif  // defined(__aarch64__)
-}
-
-void check_eq(const void* a, const void* b) {
-  if (a != b) {
-    fprintf(stderr, "**********************************\n");
-    fprintf(stderr, "Failed assertion:\n");
-    fprintf(stderr, "  %p != %p\n", a, b);
-    fprintf(stderr, "**********************************\n");
-
-    assertion_failure();
-  }
-}
-
-#define LONGEST_VARIABLE_NAME "51"
-void print_variable_address(const char* name, const void* ptr) {
-  printf("%" LONGEST_VARIABLE_NAME "s: %16p\n", name, ptr);
-}
-
-static const std::vector<std::pair<const char*, const void*>>& get_expected_tagged_vars() {
-  static std::vector<std::pair<const char*, const void*>> expected_tagged_vars = {
-      {"global_extern", &global_extern},
-      {"global_extern_hidden", &global_extern_hidden},
-  };
-  return expected_tagged_vars;
-}
-
-static const std::vector<std::pair<const char*, const void*>>& get_expected_untagged_vars() {
-  static std::vector<std::pair<const char*, const void*>> expected_untagged_vars = {
-      {"global_extern_untagged", &global_extern_untagged},
-      {"global_extern_untagged_definition_but_tagged_import",
-       &global_extern_untagged_definition_but_tagged_import},
-  };
-  return expected_untagged_vars;
-}
-
-void dso_print_variables() {
-  print_variables("  Variables declared in the DSO:\n", get_expected_tagged_vars(),
-                  get_expected_untagged_vars());
-}
-
-void print_variables(const char* header,
-                     const std::vector<std::pair<const char*, const void*>>& tagged_variables,
-                     const std::vector<std::pair<const char*, const void*>>& untagged_variables) {
-  printf("==========================================================\n");
-  printf("%s", header);
-  printf("==========================================================\n");
-  printf(" Variables expected to be tagged:\n");
-  printf("----------------------------------------------------------\n");
-  for (const auto& [name, pointer] : tagged_variables) {
-    print_variable_address(name, pointer);
-  }
-
-  printf("\n----------------------------------------------------------\n");
-  printf(" Variables expected to be untagged:\n");
-  printf("----------------------------------------------------------\n");
-  for (const auto& [name, pointer] : untagged_variables) {
-    print_variable_address(name, pointer);
-  }
-  printf("\n");
-}
-
-void dso_check_assertions(bool check_pointers_are_tagged) {
-  // Check that non-const variables are writeable.
-  global_extern = 0;
-  global_extern_hidden = 0;
-  global_extern_untagged = 0;
-  global_extern_untagged_definition_but_tagged_import = 0;
-
-  if (check_pointers_are_tagged) {
-    for (const auto& [_, pointer] : get_expected_tagged_vars()) {
-      check_tagged(pointer);
-    }
-  }
-
-  for (const auto& [_, pointer] : get_expected_untagged_vars()) {
-    check_untagged(pointer);
-  }
-}
diff --git a/tests/libs/mte_globals_relr_regression_test_b_314038442.cpp b/tests/libs/mte_globals_relr_regression_test_b_314038442.cpp
deleted file mode 100644
index 20bbba9..0000000
--- a/tests/libs/mte_globals_relr_regression_test_b_314038442.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdint.h>
-#include <stdio.h>
-
-static volatile char array[0x10000];
-volatile char* volatile oob_ptr = &array[0x111111111];
-
-unsigned char get_tag(__attribute__((unused)) volatile void* ptr) {
-#if defined(__aarch64__)
-  return static_cast<unsigned char>(reinterpret_cast<uintptr_t>(ptr) >> 56) & 0xf;
-#else   // !defined(__aarch64__)
-  return 0;
-#endif  // defined(__aarch64__)
-}
-
-int main() {
-  printf("Program loaded successfully. %p %p. ", array, oob_ptr);
-  if (get_tag(array) != get_tag(oob_ptr)) {
-    printf("Tags are mismatched!\n");
-    return 1;
-  }
-  if (get_tag(array) == 0) {
-    printf("Tags are zero!\n");
-  } else {
-    printf("Tags are non-zero\n");
-  }
-  return 0;
-}
diff --git a/tests/malloc_stress_test.cpp b/tests/malloc_stress_test.cpp
index b5b06ab..00f5919 100644
--- a/tests/malloc_stress_test.cpp
+++ b/tests/malloc_stress_test.cpp
@@ -27,10 +27,58 @@
 #include <thread>
 #include <vector>
 
-#include <android-base/strings.h>
 #if defined(__BIONIC__)
 #include <meminfo/procmeminfo.h>
 #include <procinfo/process_map.h>
+
+#include <log/log.h>
+#include <log/log_read.h>
+#endif
+
+#if defined(__BIONIC__)
+static void PrintLogStats(uint64_t& last_time) {
+  logger_list* logger =
+      android_logger_list_open(android_name_to_log_id("main"), ANDROID_LOG_NONBLOCK, 0, getpid());
+  if (logger == nullptr) {
+    printf("Failed to open log for main\n");
+    return;
+  }
+
+  uint64_t last_message_time = last_time;
+  while (true) {
+    log_msg entry;
+    ssize_t retval = android_logger_list_read(logger, &entry);
+    if (retval == 0) {
+      break;
+    }
+    if (retval < 0) {
+      if (retval == -EINTR) {
+        continue;
+      }
+      // EAGAIN means there is nothing left to read when ANDROID_LOG_NONBLOCK is set.
+      if (retval != -EAGAIN) {
+        printf("Failed to read log entry: %s\n", strerrordesc_np(retval));
+      }
+      break;
+    }
+    if (entry.msg() == nullptr) {
+      continue;
+    }
+    // Only print allocator tagged log entries.
+    std::string_view tag(entry.msg() + 1);
+    if (tag != "scudo" && tag != "jemalloc") {
+      continue;
+    }
+    if (entry.nsec() > last_time) {
+      printf("  %s\n", &tag.back() + 2);
+      // Only update the last time outside this loop just in case two or more
+      // messages have the same timestamp.
+      last_message_time = entry.nsec();
+    }
+  }
+  android_logger_list_close(logger);
+  last_time = last_message_time;
+}
 #endif
 
 TEST(malloc_stress, multiple_threads_forever) {
@@ -45,6 +93,8 @@
 #endif
   uint64_t mallinfo_min = UINT64_MAX;
   uint64_t mallinfo_max = 0;
+
+  uint64_t last_message_time = 0;
   for (size_t i = 0; ; i++) {
     printf("Pass %zu\n", i);
 
@@ -74,8 +124,8 @@
     uint64_t rss_bytes = 0;
     uint64_t vss_bytes = 0;
     for (auto& vma : maps) {
-      if (vma.name == "[anon:libc_malloc]" || android::base::StartsWith(vma.name, "[anon:scudo:") ||
-          android::base::StartsWith(vma.name, "[anon:GWP-ASan")) {
+      if (vma.name == "[anon:libc_malloc]" || vma.name.starts_with("[anon:scudo:") ||
+          vma.name.starts_with("[anon:GWP-ASan")) {
         android::meminfo::Vma update_vma(vma);
         ASSERT_TRUE(proc_mem.FillInVmaStats(update_vma));
         rss_bytes += update_vma.usage.rss;
@@ -112,5 +162,15 @@
     printf("Allocated memory %zu %0.2fMB\n", mallinfo_bytes, mallinfo_bytes / (1024.0 * 1024.0));
     printf("  Min %" PRIu64 " %0.2fMB\n", mallinfo_min, mallinfo_min / (1024.0 * 1024.0));
     printf("  Max %" PRIu64 " %0.2fMB\n", mallinfo_max, mallinfo_max / (1024.0 * 1024.0));
+
+#if defined(__BIONIC__)
+    if (((i + 1) % 100) == 0) {
+      // Send native allocator stats to the log
+      mallopt(M_LOG_STATS, 0);
+
+      printf("Log stats:\n");
+      PrintLogStats(last_message_time);
+    }
+#endif
   }
 }
diff --git a/tests/memtag_globals_test.cpp b/tests/memtag_globals_test.cpp
deleted file mode 100644
index ff93e7b..0000000
--- a/tests/memtag_globals_test.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <gtest/gtest.h>
-
-#if defined(__BIONIC__)
-#include "gtest_globals.h"
-#include "utils.h"
-#endif  // defined(__BIONIC__)
-
-#include <android-base/test_utils.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <string>
-#include <tuple>
-
-#include "platform/bionic/mte.h"
-
-class MemtagGlobalsTest : public testing::TestWithParam<bool> {};
-
-TEST_P(MemtagGlobalsTest, test) {
-  SKIP_WITH_HWASAN << "MTE globals tests are incompatible with HWASan";
-#if defined(__BIONIC__) && defined(__aarch64__)
-  std::string binary = GetTestLibRoot() + "/memtag_globals_binary";
-  bool is_static = MemtagGlobalsTest::GetParam();
-  if (is_static) {
-    binary += "_static";
-  }
-
-  chmod(binary.c_str(), 0755);
-  ExecTestHelper eth;
-  eth.SetArgs({binary.c_str(), nullptr});
-  eth.Run(
-      [&]() {
-        execve(binary.c_str(), eth.GetArgs(), eth.GetEnv());
-        GTEST_FAIL() << "Failed to execve: " << strerror(errno) << " " << binary.c_str();
-      },
-      // We catch the global-buffer-overflow and crash only when MTE globals is
-      // supported. Note that MTE globals is unsupported for fully static
-      // executables, but we should still make sure the binary passes its
-      // assertions, just that global variables won't be tagged.
-      (mte_supported() && !is_static) ? -SIGSEGV : 0, "Assertions were passed");
-#else
-  GTEST_SKIP() << "bionic/arm64 only";
-#endif
-}
-
-INSTANTIATE_TEST_SUITE_P(MemtagGlobalsTest, MemtagGlobalsTest, testing::Bool(),
-                         [](const ::testing::TestParamInfo<MemtagGlobalsTest::ParamType>& info) {
-                           if (info.param) return "MemtagGlobalsTest_static";
-                           return "MemtagGlobalsTest";
-                         });
-
-TEST(MemtagGlobalsTest, RelrRegressionTestForb314038442) {
-  SKIP_WITH_HWASAN << "MTE globals tests are incompatible with HWASan";
-#if defined(__BIONIC__) && defined(__aarch64__)
-  std::string binary = GetTestLibRoot() + "/mte_globals_relr_regression_test_b_314038442";
-  chmod(binary.c_str(), 0755);
-  ExecTestHelper eth;
-  eth.SetArgs({binary.c_str(), nullptr});
-  eth.Run(
-      [&]() {
-        execve(binary.c_str(), eth.GetArgs(), eth.GetEnv());
-        GTEST_FAIL() << "Failed to execve: " << strerror(errno) << " " << binary.c_str();
-      },
-      /* exit code */ 0, "Program loaded successfully.*Tags are zero!");
-#else
-  GTEST_SKIP() << "bionic/arm64 only";
-#endif
-}
-
-TEST(MemtagGlobalsTest, RelrRegressionTestForb314038442WithMteGlobals) {
-  if (!mte_supported()) GTEST_SKIP() << "Must have MTE support.";
-#if defined(__BIONIC__) && defined(__aarch64__)
-  std::string binary = GetTestLibRoot() + "/mte_globals_relr_regression_test_b_314038442_mte";
-  chmod(binary.c_str(), 0755);
-  ExecTestHelper eth;
-  eth.SetArgs({binary.c_str(), nullptr});
-  eth.Run(
-      [&]() {
-        execve(binary.c_str(), eth.GetArgs(), eth.GetEnv());
-        GTEST_FAIL() << "Failed to execve: " << strerror(errno) << " " << binary.c_str();
-      },
-      /* exit code */ 0, "Program loaded successfully.*Tags are non-zero");
-#else
-  GTEST_SKIP() << "bionic/arm64 only";
-#endif
-}
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index 289a483..502405f 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -740,12 +740,8 @@
     // Set the second half of ptr to the expected pattern in ptr2.
     memset(state.ptr + state.MAX_LEN, '\1', state.MAX_LEN);
     memcpy(state.ptr + state.MAX_LEN, state.ptr1, copy_len);
-    size_t expected_end;
     if (copy_len > ptr1_len) {
       memset(state.ptr + state.MAX_LEN + ptr1_len, '\0', copy_len - ptr1_len);
-      expected_end = ptr1_len;
-    } else {
-      expected_end = copy_len;
     }
 
     ASSERT_EQ(state.ptr2, strncpy(state.ptr2, state.ptr1, copy_len));