Merge "Closing the stream when the function returns" into main
diff --git a/benchmarks/stdlib_benchmark.cpp b/benchmarks/stdlib_benchmark.cpp
index 9be72e7..7680b40 100644
--- a/benchmarks/stdlib_benchmark.cpp
+++ b/benchmarks/stdlib_benchmark.cpp
@@ -235,3 +235,6 @@
 BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_strtoll, strtoll(" -123", nullptr, 0));
 BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_strtoul, strtoul(" -123", nullptr, 0));
 BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_strtoull, strtoull(" -123", nullptr, 0));
+
+BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_strtol_hex, strtol("0xdeadbeef", nullptr, 0));
+BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_strtoul_hex, strtoul("0xdeadbeef", nullptr, 0));
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 0b12088..e44d998 100644
--- a/libc/bionic/bionic_call_ifunc_resolver.cpp
+++ b/libc/bionic/bionic_call_ifunc_resolver.cpp
@@ -28,9 +28,9 @@
 
 #include "private/bionic_call_ifunc_resolver.h"
 #include <sys/auxv.h>
+#include <sys/hwprobe.h>
 #include <sys/ifunc.h>
 
-#include "bionic/macros.h"
 #include "private/bionic_auxv.h"
 
 // This code is called in the linker before it has been relocated, so minimize calls into other
@@ -40,8 +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);
@@ -51,20 +51,15 @@
   return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(arg._hwcap | _IFUNC_ARG_HWCAP, &arg);
 #elif defined(__arm__)
   typedef ElfW(Addr) (*ifunc_resolver_t)(unsigned long);
-  static unsigned long hwcap;
-  static bool initialized = false;
-  if (!initialized) {
-    initialized = true;
-    hwcap = getauxval(AT_HWCAP);
-  }
+  static unsigned long hwcap = getauxval(AT_HWCAP);
   return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(hwcap);
 #elif defined(__riscv)
-  // The pointer argument is currently unused, but reserved for future
+  // The third argument is currently unused, but reserved for future
   // expansion. If we pass nullptr from the beginning, it'll be easier
   // to recognize if/when we pass actual data (and matches glibc).
-  typedef ElfW(Addr) (*ifunc_resolver_t)(uint64_t, void*);
+  typedef ElfW(Addr) (*ifunc_resolver_t)(uint64_t, __riscv_hwprobe_t, void*);
   static uint64_t hwcap = getauxval(AT_HWCAP);
-  return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(hwcap, nullptr);
+  return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(hwcap, __riscv_hwprobe, nullptr);
 #else
   typedef ElfW(Addr) (*ifunc_resolver_t)(void);
   return reinterpret_cast<ifunc_resolver_t>(resolver_addr)();
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index 181a729..f46d702 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -410,7 +410,6 @@
   // We did not enable MTE, so we do not need to arm the upgrade timer.
   __libc_shared_globals()->heap_tagging_upgrade_timer_sec = 0;
 }
-
 #else   // __aarch64__
 void __libc_init_mte(const memtag_dynamic_entries_t*, const void*, size_t, uintptr_t, void*) {}
 #endif  // __aarch64__
@@ -505,6 +504,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;
 }
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
index 792a114..a6bf7a7 100644
--- a/libc/bionic/malloc_common_dynamic.cpp
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -372,6 +372,7 @@
 extern "C" const char* __scudo_get_region_info_addr();
 extern "C" const char* __scudo_get_ring_buffer_addr();
 extern "C" size_t __scudo_get_ring_buffer_size();
+extern "C" size_t __scudo_get_stack_depot_size();
 
 // Initializes memory allocation framework once per process.
 static void MallocInitImpl(libc_globals* globals) {
@@ -385,6 +386,7 @@
   __libc_shared_globals()->scudo_region_info = __scudo_get_region_info_addr();
   __libc_shared_globals()->scudo_ring_buffer = __scudo_get_ring_buffer_addr();
   __libc_shared_globals()->scudo_ring_buffer_size = __scudo_get_ring_buffer_size();
+  __libc_shared_globals()->scudo_stack_depot_size = __scudo_get_stack_depot_size();
 #endif
 
   // Prefer malloc debug since it existed first and is a more complete
diff --git a/tests/prebuilt-elf-files/arm64/src/memtag_globals.h b/libc/include/bits/sockaddr_storage.h
similarity index 66%
rename from tests/prebuilt-elf-files/arm64/src/memtag_globals.h
rename to libc/include/bits/sockaddr_storage.h
index b9a2ef1..effafab 100644
--- a/tests/prebuilt-elf-files/arm64/src/memtag_globals.h
+++ b/libc/include/bits/sockaddr_storage.h
@@ -26,18 +26,32 @@
  * 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);
+/**
+ * @file bits/sockaddr_storage.h
+ * @brief The `sockaddr_storage` struct.
+ */
 
-void dso_check_assertions(bool enforce_tagged);
-void dso_print_variables();
+#include <sys/cdefs.h>
 
-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);
\ No newline at end of file
+#include <bits/sa_family_t.h>
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnullability-completeness"
+/**
+ * [sockaddr_storage](https://man7.org/linux/man-pages/man3/sockaddr.3type.html)
+ * is a structure large enough to contain any other `sockaddr_*` type, used to
+ * pass socket addresses without needing to know what kind of socket address
+ * you're passing.
+ */
+struct sockaddr_storage {
+  union {
+    struct {
+      sa_family_t ss_family;
+      char __data[128 - sizeof(sa_family_t)];
+    };
+    void* __align;
+  };
+};
+#pragma clang diagnostic pop
diff --git a/tests/prebuilt-elf-files/arm64/src/memtag_globals.h b/libc/include/bits/tcphdr.h
similarity index 61%
copy from tests/prebuilt-elf-files/arm64/src/memtag_globals.h
copy to libc/include/bits/tcphdr.h
index b9a2ef1..a9b6fe0 100644
--- a/tests/prebuilt-elf-files/arm64/src/memtag_globals.h
+++ b/libc/include/bits/tcphdr.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2008 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,18 +26,46 @@
  * 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 <sys/cdefs.h>
+#include <stdint.h>
 
-void dso_check_assertions(bool enforce_tagged);
-void dso_print_variables();
+__BEGIN_DECLS
 
-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);
\ No newline at end of file
+struct tcphdr {
+  __extension__ union {
+    struct {
+      uint16_t th_sport;
+      uint16_t th_dport;
+      uint32_t th_seq;
+      uint32_t th_ack;
+      uint8_t th_x2:4;
+      uint8_t th_off:4;
+      uint8_t th_flags;
+      uint16_t th_win;
+      uint16_t th_sum;
+      uint16_t th_urp;
+    };
+    struct {
+      uint16_t source;
+      uint16_t dest;
+      uint32_t seq;
+      uint32_t ack_seq;
+      uint16_t res1:4;
+      uint16_t doff:4;
+      uint16_t fin:1;
+      uint16_t syn:1;
+      uint16_t rst:1;
+      uint16_t psh:1;
+      uint16_t ack:1;
+      uint16_t urg:1;
+      uint16_t res2:2;
+      uint16_t window;
+      uint16_t check;
+      uint16_t urg_ptr;
+    };
+  };
+};
+
+__END_DECLS
diff --git a/libc/include/netinet/in.h b/libc/include/netinet/in.h
index b235e6e..163e614 100644
--- a/libc/include/netinet/in.h
+++ b/libc/include/netinet/in.h
@@ -33,20 +33,10 @@
 #include <sys/cdefs.h>
 #include <sys/socket.h>
 
-// Include linux/socket.h first to trigger the header guard without
-// the__kernel_sockaddr_storage define, so its definition uses the
-// kernel name.
-#include <linux/socket.h>
-
-// Redefine __kernel_sockaddr_storage to sockaddr_storage so that
-// the structs defined in linux/in.h use the sockaddr_storage defined
-// in sys/sockets.h.
-#define __kernel_sockaddr_storage sockaddr_storage
 #include <linux/in.h>
-#undef __kernel_sockaddr_storage
-
 #include <linux/in6.h>
 #include <linux/ipv6.h>
+#include <linux/socket.h>
 
 __BEGIN_DECLS
 
diff --git a/libc/include/netinet/tcp.h b/libc/include/netinet/tcp.h
index 147f6f7..d1c657b 100644
--- a/libc/include/netinet/tcp.h
+++ b/libc/include/netinet/tcp.h
@@ -32,47 +32,10 @@
 #include <sys/cdefs.h>
 #include <stdint.h>
 
-#define tcphdr __kernel_tcphdr
 #include <linux/tcp.h>
-#undef tcphdr
 
 __BEGIN_DECLS
 
-struct tcphdr {
-  __extension__ union {
-    struct {
-      uint16_t th_sport;
-      uint16_t th_dport;
-      uint32_t th_seq;
-      uint32_t th_ack;
-      uint8_t th_x2:4;
-      uint8_t th_off:4;
-      uint8_t th_flags;
-      uint16_t th_win;
-      uint16_t th_sum;
-      uint16_t th_urp;
-    };
-    struct {
-      uint16_t source;
-      uint16_t dest;
-      uint32_t seq;
-      uint32_t ack_seq;
-      uint16_t res1:4;
-      uint16_t doff:4;
-      uint16_t fin:1;
-      uint16_t syn:1;
-      uint16_t rst:1;
-      uint16_t psh:1;
-      uint16_t ack:1;
-      uint16_t urg:1;
-      uint16_t res2:2;
-      uint16_t window;
-      uint16_t check;
-      uint16_t urg_ptr;
-    };
-  };
-};
-
 #define TH_FIN 0x01
 #define TH_SYN 0x02
 #define TH_RST 0x04
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 4feade5..871c62c 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -74,15 +74,10 @@
 #define PTHREAD_BARRIER_SERIAL_THREAD (-1)
 #endif
 
-
 #if defined(__LP64__)
-#if defined(PAGE_SIZE)
-#define PTHREAD_STACK_MIN (4 * PAGE_SIZE)
+#define PTHREAD_STACK_MIN 16384
 #else
-#define PTHREAD_STACK_MIN 65536
-#endif
-#else
-#define PTHREAD_STACK_MIN (2 * PAGE_SIZE)
+#define PTHREAD_STACK_MIN 8192
 #endif
 
 #define PTHREAD_CREATE_DETACHED 1
diff --git a/libc/include/sys/hwprobe.h b/libc/include/sys/hwprobe.h
index b1a8400..8e69e8a 100644
--- a/libc/include/sys/hwprobe.h
+++ b/libc/include/sys/hwprobe.h
@@ -53,6 +53,14 @@
  */
 int __riscv_hwprobe(struct riscv_hwprobe* _Nonnull __pairs, size_t __pair_count, size_t __cpu_count, unsigned long* _Nullable __cpus, unsigned __flags);
 
+/**
+ * The type of the second argument passed to riscv64 ifunc resolvers.
+ * This argument allows riscv64 ifunc resolvers to call __riscv_hwprobe()
+ * without worrying about whether that relocation is resolved before
+ * the ifunc resolver is called.
+ */
+typedef int (*__riscv_hwprobe_t)(struct riscv_hwprobe* _Nonnull __pairs, size_t __pair_count, size_t __cpu_count, unsigned long* _Nullable __cpus, unsigned __flags);
+
 __END_DECLS
 
 #endif
diff --git a/libc/include/sys/socket.h b/libc/include/sys/socket.h
index 22b88cb..9402e70 100644
--- a/libc/include/sys/socket.h
+++ b/libc/include/sys/socket.h
@@ -39,6 +39,7 @@
 #include <linux/types.h>
 #include <linux/compiler.h>
 
+#include <bits/sockaddr_storage.h>
 #include <bits/sa_family_t.h>
 
 __BEGIN_DECLS
@@ -72,15 +73,6 @@
 
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wnullability-completeness"
-struct sockaddr_storage {
-  union {
-    struct {
-      sa_family_t ss_family;
-      char __data[128 - sizeof(sa_family_t)];
-    };
-    void* __align;
-  };
-};
 
 struct linger {
   int l_onoff;
diff --git a/libc/kernel/tools/cpp.py b/libc/kernel/tools/cpp.py
index 6939bda..08b786a 100755
--- a/libc/kernel/tools/cpp.py
+++ b/libc/kernel/tools/cpp.py
@@ -1247,8 +1247,8 @@
                     # Add an include for the structure to be removed of the form:
                     #  #include <bits/STRUCT_NAME.h>
                     struct_token = b.tokens[i + 1]
-                    if not structs[struct_token.id]:
-                        extra_includes.add("<bits/%s.h>" % struct_token.id)
+                    if struct_token.id in structs and structs[struct_token.id]:
+                        extra_includes.add("<%s>" % structs[struct_token.id])
 
                     # Search forward for the end of the structure.
                     # Very simple search, look for } and ; tokens.
diff --git a/libc/kernel/tools/defaults.py b/libc/kernel/tools/defaults.py
index 5340216..1d7b427 100644
--- a/libc/kernel/tools/defaults.py
+++ b/libc/kernel/tools/defaults.py
@@ -28,22 +28,23 @@
     }
 
 # This is the set of known kernel data structures we want to remove from
-# the final headers. If the map value is False, that means that in
-# addition to removing the structure, add an #include <bits/STRUCT.h>
-# to the file.
+# the final headers. If the map value is non-empty, that means that in
+# addition to removing the structure, add a #include to the file.
 kernel_structs_to_remove = {
-    # Remove the structures since they are still the same as
+    # Remove these structures since they are still the same as
     # timeval, itimerval.
-    "__kernel_old_timeval": True,
-    "__kernel_old_itimerval": True,
+    "__kernel_old_timeval": None,
+    "__kernel_old_itimerval": None,
     # Replace all of the below structures with #include <bits/STRUCT.h>
-    "epoll_event": False,
-    "flock": False,
-    "flock64": False,
-    "in_addr": False,
-    "ip_mreq_source": False,
-    "ip_msfilter": False,
-    "timespec": False,
+    "__kernel_sockaddr_storage": "bits/sockaddr_storage.h",
+    "epoll_event": "bits/epoll_event.h",
+    "flock": "bits/flock.h",
+    "flock64": "bits/flock64.h",
+    "in_addr": "bits/in_addr.h",
+    "ip_mreq_source": "bits/ip_mreq_source.h",
+    "ip_msfilter": "bits/ip_msfilter.h",
+    "tcphdr": "bits/tcphdr.h",
+    "timespec": "bits/timespec.h",
     }
 
 # define to true if you want to remove all defined(CONFIG_FOO) tests
@@ -91,6 +92,8 @@
     "__kernel_old_timeval": "timeval",
     # Do the same for __kernel_old_itimerval as for timeval.
     "__kernel_old_itimerval": "itimerval",
+    # Do the same for __kernel_sockaddr_storage.
+    "__kernel_sockaddr_storage": "sockaddr_storage",
     # Replace __packed with __attribute__((__packed__)) to avoid depending
     # on sys/cdefs.h
     "__packed": "__attribute__((__packed__))",
diff --git a/libc/kernel/uapi/linux/in.h b/libc/kernel/uapi/linux/in.h
index e784690..44efdd8 100644
--- a/libc/kernel/uapi/linux/in.h
+++ b/libc/kernel/uapi/linux/in.h
@@ -148,32 +148,32 @@
 #define IP_MSFILTER_SIZE(numsrc) (sizeof(struct ip_msfilter) - sizeof(__u32) + (numsrc) * sizeof(__u32))
 struct group_req {
   __u32 gr_interface;
-  struct __kernel_sockaddr_storage gr_group;
+  struct sockaddr_storage gr_group;
 };
 struct group_source_req {
   __u32 gsr_interface;
-  struct __kernel_sockaddr_storage gsr_group;
-  struct __kernel_sockaddr_storage gsr_source;
+  struct sockaddr_storage gsr_group;
+  struct sockaddr_storage gsr_source;
 };
 struct group_filter {
   union {
     struct {
       __u32 gf_interface_aux;
-      struct __kernel_sockaddr_storage gf_group_aux;
+      struct sockaddr_storage gf_group_aux;
       __u32 gf_fmode_aux;
       __u32 gf_numsrc_aux;
-      struct __kernel_sockaddr_storage gf_slist[1];
+      struct sockaddr_storage gf_slist[1];
     };
     struct {
       __u32 gf_interface;
-      struct __kernel_sockaddr_storage gf_group;
+      struct sockaddr_storage gf_group;
       __u32 gf_fmode;
       __u32 gf_numsrc;
-      struct __kernel_sockaddr_storage gf_slist_flex[];
+      struct sockaddr_storage gf_slist_flex[];
     };
   };
 };
-#define GROUP_FILTER_SIZE(numsrc) (sizeof(struct group_filter) - sizeof(struct __kernel_sockaddr_storage) + (numsrc) * sizeof(struct __kernel_sockaddr_storage))
+#define GROUP_FILTER_SIZE(numsrc) (sizeof(struct group_filter) - sizeof(struct sockaddr_storage) + (numsrc) * sizeof(struct sockaddr_storage))
 #endif
 #if __UAPI_DEF_IN_PKTINFO
 struct in_pktinfo {
diff --git a/libc/kernel/uapi/linux/mptcp.h b/libc/kernel/uapi/linux/mptcp.h
index f00abae..d97f29b 100644
--- a/libc/kernel/uapi/linux/mptcp.h
+++ b/libc/kernel/uapi/linux/mptcp.h
@@ -163,13 +163,13 @@
     struct sockaddr sa_local;
     struct sockaddr_in sin_local;
     struct sockaddr_in6 sin6_local;
-    struct __kernel_sockaddr_storage ss_local;
+    struct sockaddr_storage ss_local;
   };
   union {
     struct sockaddr sa_remote;
     struct sockaddr_in sin_remote;
     struct sockaddr_in6 sin6_remote;
-    struct __kernel_sockaddr_storage ss_remote;
+    struct sockaddr_storage ss_remote;
   };
 };
 struct mptcp_subflow_info {
diff --git a/libc/kernel/uapi/linux/rds.h b/libc/kernel/uapi/linux/rds.h
index bc41946..e2a7a38 100644
--- a/libc/kernel/uapi/linux/rds.h
+++ b/libc/kernel/uapi/linux/rds.h
@@ -205,7 +205,7 @@
   __u64 flags;
 };
 struct rds_get_mr_for_dest_args {
-  struct __kernel_sockaddr_storage dest_addr;
+  struct sockaddr_storage dest_addr;
   struct rds_iovec vec;
   __u64 cookie_addr;
   __u64 flags;
diff --git a/libc/kernel/uapi/linux/socket.h b/libc/kernel/uapi/linux/socket.h
index 936f44a..27890a4 100644
--- a/libc/kernel/uapi/linux/socket.h
+++ b/libc/kernel/uapi/linux/socket.h
@@ -6,17 +6,9 @@
  */
 #ifndef _UAPI_LINUX_SOCKET_H
 #define _UAPI_LINUX_SOCKET_H
+#include <bits/sockaddr_storage.h>
 #define _K_SS_MAXSIZE 128
 typedef unsigned short __kernel_sa_family_t;
-struct __kernel_sockaddr_storage {
-  union {
-    struct {
-      __kernel_sa_family_t ss_family;
-      char __data[_K_SS_MAXSIZE - sizeof(unsigned short)];
-    };
-    void * __align;
-  };
-};
 #define SOCK_SNDBUF_LOCK 1
 #define SOCK_RCVBUF_LOCK 2
 #define SOCK_BUF_LOCK_MASK (SOCK_SNDBUF_LOCK | SOCK_RCVBUF_LOCK)
diff --git a/libc/kernel/uapi/linux/tcp.h b/libc/kernel/uapi/linux/tcp.h
index 843b6ef..65bab54 100644
--- a/libc/kernel/uapi/linux/tcp.h
+++ b/libc/kernel/uapi/linux/tcp.h
@@ -6,25 +6,10 @@
  */
 #ifndef _UAPI_LINUX_TCP_H
 #define _UAPI_LINUX_TCP_H
+#include <bits/tcphdr.h>
 #include <linux/types.h>
 #include <asm/byteorder.h>
 #include <linux/socket.h>
-struct tcphdr {
-  __be16 source;
-  __be16 dest;
-  __be32 seq;
-  __be32 ack_seq;
-#ifdef __LITTLE_ENDIAN_BITFIELD
-  __u16 res1 : 4, doff : 4, fin : 1, syn : 1, rst : 1, psh : 1, ack : 1, urg : 1, ece : 1, cwr : 1;
-#elif defined(__BIG_ENDIAN_BITFIELD)
-  __u16 doff : 4, res1 : 4, cwr : 1, ece : 1, urg : 1, ack : 1, psh : 1, rst : 1, syn : 1, fin : 1;
-#else
-#error "Adjust your <asm/byteorder.h> defines"
-#endif
-  __be16 window;
-  __sum16 check;
-  __be16 urg_ptr;
-};
 union tcp_word_hdr {
   struct tcphdr hdr;
   __be32 words[5];
@@ -217,7 +202,7 @@
 #define TCP_MD5SIG_FLAG_PREFIX 0x1
 #define TCP_MD5SIG_FLAG_IFINDEX 0x2
 struct tcp_md5sig {
-  struct __kernel_sockaddr_storage tcpm_addr;
+  struct sockaddr_storage tcpm_addr;
   __u8 tcpm_flags;
   __u8 tcpm_prefixlen;
   __u16 tcpm_keylen;
diff --git a/libc/kernel/uapi/rdma/rdma_user_cm.h b/libc/kernel/uapi/rdma/rdma_user_cm.h
index dbe79bc..5228e62 100644
--- a/libc/kernel/uapi/rdma/rdma_user_cm.h
+++ b/libc/kernel/uapi/rdma/rdma_user_cm.h
@@ -76,7 +76,7 @@
   __u32 id;
   __u16 addr_size;
   __u16 reserved;
-  struct __kernel_sockaddr_storage addr;
+  struct sockaddr_storage addr;
 };
 struct rdma_ucm_resolve_ip {
   struct sockaddr_in6 src_addr;
@@ -90,8 +90,8 @@
   __u16 src_size;
   __u16 dst_size;
   __u32 reserved;
-  struct __kernel_sockaddr_storage src_addr;
-  struct __kernel_sockaddr_storage dst_addr;
+  struct sockaddr_storage src_addr;
+  struct sockaddr_storage dst_addr;
 };
 struct rdma_ucm_resolve_route {
   __u32 id;
@@ -125,8 +125,8 @@
   __u16 pkey;
   __u16 src_size;
   __u16 dst_size;
-  struct __kernel_sockaddr_storage src_addr;
-  struct __kernel_sockaddr_storage dst_addr;
+  struct sockaddr_storage src_addr;
+  struct sockaddr_storage dst_addr;
   __u32 ibdev_index;
   __u32 reserved1;
 };
@@ -213,7 +213,7 @@
   __u32 id;
   __u16 addr_size;
   __u16 join_flags;
-  struct __kernel_sockaddr_storage addr;
+  struct sockaddr_storage addr;
 };
 struct rdma_ucm_get_event {
   __aligned_u64 response;
diff --git a/libc/platform/bionic/macros.h b/libc/platform/bionic/macros.h
index b781731..93268c1 100644
--- a/libc/platform/bionic/macros.h
+++ b/libc/platform/bionic/macros.h
@@ -97,17 +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 variables 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.
-#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 dc25098..73cd821 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/prctl.h>
 
@@ -47,36 +46,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.
-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 15b570d..8ea7d4d 100644
--- a/libc/private/bionic_globals.h
+++ b/libc/private/bionic_globals.h
@@ -130,6 +130,7 @@
   const char* scudo_region_info = nullptr;
   const char* scudo_ring_buffer = nullptr;
   size_t scudo_ring_buffer_size = 0;
+  size_t scudo_stack_depot_size = 0;
 
   HeapTaggingLevel initial_heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE;
   bool initial_memtag_stack = false;
diff --git a/libc/tools/generate_notice.py b/libc/tools/generate_notice.py
index 505708a..69d2d00 100755
--- a/libc/tools/generate_notice.py
+++ b/libc/tools/generate_notice.py
@@ -45,14 +45,6 @@
     return True
 
 
-def is_auto_generated(content):
-    if "Generated by gensyscalls.py" in content or "generated by genserv.py" in content:
-        return True
-    if "This header was automatically generated from a Linux kernel header" in content:
-        return True
-    return False
-
-
 def is_copyright_end(line: str, first_line_was_hash: bool) -> bool:
     endings = [
         " $FreeBSD: ",
@@ -153,10 +145,6 @@
         warn_verbose("ignoring short file %s" % path)
         return
 
-    if is_auto_generated(content):
-        warn_verbose("ignoring auto-generated file %s" % path)
-        return
-
     if not "Copyright" in content:
         if "public domain" in content.lower():
             warn_verbose("ignoring public domain file %s" % path)
diff --git a/libdl/Android.bp b/libdl/Android.bp
index 762aeef..3bda856 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -226,10 +226,6 @@
         "//apex_available:platform",
         "com.android.runtime",
     ],
-
-    lto: {
-        never: true,
-    },
 }
 
 ndk_library {
diff --git a/linker/Android.bp b/linker/Android.bp
index 2875263..2ca962a 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -328,10 +328,6 @@
 
     sanitize: {
         hwaddress: false,
-        // TODO(mitchp): For now, disable MTE globals in the linker. MTE globals
-        // change the relocation semantics, and GVs that are touched before the
-        // linker has the chance to relocate itself have to be annotated.
-        memtag_globals: false,
     },
 
     static_libs: [
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 13ce6ef..135eaa3 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.
 
@@ -2340,7 +2339,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,
@@ -2771,11 +2770,8 @@
 }
 
 void soinfo::apply_relr_reloc(ElfW(Addr) offset) {
-  ElfW(Addr)* tagged_address = reinterpret_cast<ElfW(Addr)*>(
-      get_tagged_address(reinterpret_cast<void*>(offset + load_bias)));
-  ElfW(Addr) tagged_result = reinterpret_cast<ElfW(Addr)>(
-      get_tagged_address(reinterpret_cast<void*>(*tagged_address + load_bias)));
-  *tagged_address = tagged_result;
+  ElfW(Addr) address = offset + load_bias;
+  *reinterpret_cast<ElfW(Addr)*>(address) += load_bias;
 }
 
 // Process relocations in SHT_RELR section (experimental).
@@ -3308,18 +3304,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 (mte_supported() && memtag_globals() && memtag_globalssz() &&
-      remap_memtag_globals_segments(phdr, phnum, base) == 0) {
-    tag_globals();
-    protect_memtag_globals_ro_segments(phdr, phnum, base);
-  }
-
   flags_ |= FLAG_PRELINKED;
   return true;
 }
@@ -3391,14 +3375,6 @@
     return false;
   }
 
-  if (mte_supported() && memtag_globals() && memtag_globalssz()) {
-    // The linker's full path is not available until the main executable is loaded, as it's obtained
-    // from DT_INTERP. We manually rename the linker's segments later, but have a best-effort name
-    // in case we find a bug prior to loading the main executable.
-    const char* soname = is_linker() ? "linker" : get_realpath();
-    name_memtag_globals_segments(phdr, phnum, base, soname);
-  }
-
   /* Handle serializing/sharing the RELRO segment */
   if (extinfo && (extinfo->flags & ANDROID_DLEXT_WRITE_RELRO)) {
     if (phdr_table_serialize_gnu_relro(phdr, phnum, load_bias,
@@ -3431,47 +3407,6 @@
   return true;
 }
 
-// https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#global-variable-tagging
-void soinfo::tag_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 = 0;
-  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;
-  constexpr uint64_t kMemtagStepVarintReservedBits = 3;
-
-  while (decoder.has_bytes()) {
-    uint64_t value = decoder.pop_front();
-    uint64_t step = value >> kMemtagStepVarintReservedBits;
-    uint64_t granules_to_tag = value & ((1 << kMemtagStepVarintReservedBits) - 1);
-    if (granules_to_tag == 0) {
-      granules_to_tag = decoder.pop_front() + 1;
-    }
-
-    addr += step * kTagGranuleSize;
-    void* tagged_addr = insert_random_tag(reinterpret_cast<void*>(addr + load_bias), 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 < granules_to_tag; k++) {
-      auto* granule = static_cast<uint8_t*>(tagged_addr) + k * kTagGranuleSize;
-      set_memory_tag(static_cast<void*>(granule));
-    }
-    addr += granules_to_tag * 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_debuggerd_android.cpp b/linker/linker_debuggerd_android.cpp
index ab6fc30..444da78 100644
--- a/linker/linker_debuggerd_android.cpp
+++ b/linker/linker_debuggerd_android.cpp
@@ -44,6 +44,7 @@
       .scudo_region_info = __libc_shared_globals()->scudo_region_info,
       .scudo_ring_buffer = __libc_shared_globals()->scudo_ring_buffer,
       .scudo_ring_buffer_size = __libc_shared_globals()->scudo_ring_buffer_size,
+      .scudo_stack_depot_size = __libc_shared_globals()->scudo_stack_depot_size,
   };
 }
 
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index c1a8929..5f5eba4 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -44,9 +44,7 @@
 #include "linker_tls.h"
 #include "linker_utils.h"
 
-#include "platform/bionic/macros.h"
 #include "private/KernelArgumentBlock.h"
-#include "private/bionic_auxv.h"
 #include "private/bionic_call_ifunc_resolver.h"
 #include "private/bionic_globals.h"
 #include "private/bionic_tls.h"
@@ -80,8 +78,7 @@
 // TODO (dimtiry): remove somain, rename solist to solist_head
 static soinfo* solist;
 static soinfo* sonext;
-// main process, always the one after libdl_info
-BIONIC_USED_BEFORE_LINKER_RELOCATES static soinfo* somain;
+static soinfo* somain; // main process, always the one after libdl_info
 static soinfo* solinker;
 static soinfo* vdso; // vdso if present
 
@@ -393,16 +390,9 @@
     interp = kFallbackLinkerPath;
   }
   solinker->set_realpath(interp);
-  if (solinker->memtag_globals() && solinker->memtag_globalssz()) {
-    name_memtag_globals_segments(solinker->phdr, solinker->phnum, solinker->load_bias,
-                                 solinker->get_realpath());
-  }
   init_link_map_head(*solinker);
 
 #if defined(__aarch64__)
-  __libc_init_mte(somain->memtag_dynamic_entries(), somain->phdr, somain->phnum, somain->load_bias,
-                  args.argv);
-
   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.
@@ -414,6 +404,9 @@
                      strerror(errno));
     }
   }
+
+  __libc_init_mte(somain->memtag_dynamic_entries(), somain->phdr, somain->phnum, somain->load_bias,
+                  args.argv);
 #endif
 
   // Register the main executable and the linker upfront to have
@@ -612,7 +605,7 @@
 const unsigned kRelSzTag = DT_RELSZ;
 #endif
 
-BIONIC_USED_BEFORE_LINKER_RELOCATES extern __LIBC_HIDDEN__ ElfW(Ehdr) __ehdr_start;
+extern __LIBC_HIDDEN__ ElfW(Ehdr) __ehdr_start;
 
 static void call_ifunc_resolvers_for_section(RelType* begin, RelType* end) {
   auto ehdr = reinterpret_cast<ElfW(Addr)>(&__ehdr_start);
@@ -670,16 +663,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* dest, const void* src, size_t n) {
-  char* dest_bytes = reinterpret_cast<char*>(dest);
-  const char* src_bytes = reinterpret_cast<const char*>(src);
-  for (size_t i = 0; i < n; ++i) {
-    dest_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 53fc58b..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* dest, const void* src, size_t n);
\ No newline at end of file
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index bec6994..0ad0fd5 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -36,12 +36,10 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include "android-base/unique_fd.h"
 #include "linker.h"
-#include "linker_debug.h"
 #include "linker_dlwarning.h"
 #include "linker_globals.h"
-#include "linker_main.h"
+#include "linker_debug.h"
 #include "linker_utils.h"
 
 #include "private/CFIShadow.h" // For kLibraryAlignment
@@ -864,108 +862,6 @@
   return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, prot);
 }
 
-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.
- *
- * Input:
- *   phdr_table  -> program header table
- *   phdr_count  -> number of entries in tables
- *   load_bias   -> load bias
- * Return:
- *   0 on success, -1 on failure (error code in errno).
- */
-int remap_memtag_globals_segments(const ElfW(Phdr) * phdr_table, size_t phdr_count,
-                                  ElfW(Addr) load_bias) {
-  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).
-#if defined(__aarch64__)
-    prot |= PROT_MTE;
-#endif  // defined(__aarch64__)
-    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);
-  }
-
-  return 0;
-}
-
-void protect_memtag_globals_ro_segments(const ElfW(Phdr) * phdr_table, size_t phdr_count,
-                                        ElfW(Addr) load_bias) {
-  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;
-    }
-
-#if defined(__aarch64__)
-    prot |= PROT_MTE;
-#endif  // defined(__aarch64__)
-
-    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);
-  }
-}
-
-void name_memtag_globals_segments(const ElfW(Phdr) * phdr_table, size_t phdr_count,
-                                  ElfW(Addr) load_bias, const char* soname) {
-  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. The previous Android-kernel specific implementation captured the name
-    // by pointer from userspace, which meant we had to persist the name permanently in memory.
-    // Since Android13-5.10 (https://android-review.git.corp.google.com/c/kernel/common/+/1934723)
-    // though, we use the upstream-kernel implementation
-    // (https://github.com/torvalds/linux/commit/9a10064f5625d5572c3626c1516e0bebc6c9fe9b), which
-    // copies the name into kernel memory. It's a safe bet that any devices with Android 14 are
-    // using a kernel >= 5.10.
-    constexpr unsigned kVmaNameLimit = 80;
-    char vma_name[kVmaNameLimit];
-    async_safe_format_buffer(vma_name, kVmaNameLimit, "memtag:%s+0x%" PRIxPTR, soname,
-                             page_start(phdr->p_vaddr));
-    prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, reinterpret_cast<void*>(seg_page_start),
-          seg_page_aligned_size, vma_name);
-  }
-}
-
 /* 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 092ea5d..98bf020 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -148,12 +148,3 @@
 
 const char* phdr_table_get_interpreter_name(const ElfW(Phdr)* phdr_table, size_t phdr_count,
                                             ElfW(Addr) load_bias);
-
-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);
diff --git a/linker/linker_relocate.cpp b/linker/linker_relocate.cpp
index 1ee7bc6..952dade 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:
@@ -159,19 +157,12 @@
 
 static bool process_relocation_general(Relocator& relocator, const rel_t& reloc);
 
-static ElfW(Addr) apply_memtag(ElfW(Addr) 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)));
-}
-
 template <RelocMode Mode>
 __attribute__((always_inline))
 static bool process_relocation_impl(Relocator& relocator, const rel_t& reloc) {
   constexpr bool IsGeneral = Mode == RelocMode::General;
 
-  void* const rel_target =
-      reinterpret_cast<void*>(apply_memtag(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);
 
@@ -334,7 +325,7 @@
     // common in non-platform binaries.
     if (r_type == R_GENERIC_ABSOLUTE) {
       count_relocation_if<IsGeneral>(kRelocAbsolute);
-      const ElfW(Addr) result = apply_memtag(sym_addr) + get_addend_rel();
+      const ElfW(Addr) result = sym_addr + get_addend_rel();
       trace_reloc("RELO ABSOLUTE %16p <- %16p %s",
                   rel_target, reinterpret_cast<void*>(result), sym_name);
       *static_cast<ElfW(Addr)*>(rel_target) = result;
@@ -344,29 +335,16 @@
       // document (IHI0044F) specifies that R_ARM_GLOB_DAT has an addend, but Bionic isn't adding
       // it.
       count_relocation_if<IsGeneral>(kRelocAbsolute);
-      ElfW(Addr) result = apply_memtag(sym_addr) + get_addend_norel();
-      trace_reloc("RELO GLOB_DAT %16p <- %16p %s", rel_target, reinterpret_cast<void*>(result),
-                  sym_name);
+      const ElfW(Addr) result = sym_addr + get_addend_norel();
+      trace_reloc("RELO GLOB_DAT %16p <- %16p %s",
+                  rel_target, reinterpret_cast<void*>(result), sym_name);
       *static_cast<ElfW(Addr)*>(rel_target) = result;
       return true;
     } else if (r_type == R_GENERIC_RELATIVE) {
       // In practice, r_sym is always zero, but if it weren't, the linker would still look up the
       // referenced symbol (and abort if the symbol isn't found), even though it isn't used.
       count_relocation_if<IsGeneral>(kRelocRelative);
-      ElfW(Addr) result;
-      // 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->memtag_globals() && relocator.si->memtag_globalssz()) {
-        int64_t* place = static_cast<int64_t*>(rel_target);
-        int64_t offset = *place;
-        result = apply_memtag(relocator.si->load_bias + get_addend_rel() + offset) - offset;
-      } else {
-        result = relocator.si->load_bias + get_addend_rel();
-      }
+      const ElfW(Addr) result = relocator.si->load_bias + get_addend_rel();
       trace_reloc("RELO RELATIVE %16p <- %16p",
                   rel_target, reinterpret_cast<void*>(result));
       *static_cast<ElfW(Addr)*>(rel_target) = result;
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.h b/linker/linker_soinfo.h
index 092cbcc..622719d 100644
--- a/linker/linker_soinfo.h
+++ b/linker/linker_soinfo.h
@@ -66,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);
 
@@ -258,8 +257,6 @@
                   const android_dlextinfo* extinfo, size_t* relro_fd_offset);
   bool protect_relro();
 
-  void tag_globals();
-
   void add_child(soinfo* child);
   void remove_all_links();
 
diff --git a/linker/linker_utils_test.cpp b/linker/linker_utils_test.cpp
index 0b881d4..ac98416 100644
--- a/linker/linker_utils_test.cpp
+++ b/linker/linker_utils_test.cpp
@@ -105,15 +105,35 @@
 }
 
 TEST(linker_utils, page_start) {
-  ASSERT_EQ(0x0001000U, page_start(0x0001000));
-  ASSERT_EQ(0x3002000U, page_start(0x300222f));
-  ASSERT_EQ(0x6001000U, page_start(0x6001fff));
+  const size_t kPageSize = page_size();
+
+  if (kPageSize == 4096) {
+    ASSERT_EQ(0x0001000U, page_start(0x0001000));
+    ASSERT_EQ(0x3002000U, page_start(0x300222f));
+    ASSERT_EQ(0x6001000U, page_start(0x6001fff));
+  } else if (kPageSize == 16384) {
+    ASSERT_EQ(0x0004000U, page_start(0x0004000));
+    ASSERT_EQ(0x3008000U, page_start(0x300822f));
+    ASSERT_EQ(0x6004000U, page_start(0x6004fff));
+  } else {
+    FAIL() << "Page size not supported " << kPageSize;
+  }
 }
 
 TEST(linker_utils, page_offset) {
-  ASSERT_EQ(0x0U, page_offset(0x0001000));
-  ASSERT_EQ(0x22fU, page_offset(0x300222f));
-  ASSERT_EQ(0xfffU, page_offset(0x6001fff));
+  const size_t kPageSize = page_size();
+
+  if (kPageSize == 4096) {
+    ASSERT_EQ(0x0U, page_offset(0x0001000));
+    ASSERT_EQ(0x22fU, page_offset(0x30222f));
+    ASSERT_EQ(0xfffU, page_offset(0x6001fff));
+  } else if (kPageSize == 16384) {
+    ASSERT_EQ(0x0U, page_offset(0x0004000));
+    ASSERT_EQ(0x322fU, page_offset(0x30322f));
+    ASSERT_EQ(0x3fffU, page_offset(0x6003fff));
+  } else {
+    FAIL() << "Page size not supported " << kPageSize;
+  }
 }
 
 TEST(linker_utils, safe_add) {
diff --git a/tests/Android.bp b/tests/Android.bp
index 3aea968..a53418a 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -353,89 +353,6 @@
     },
 }
 
-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,
-        }
-    },
-    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
-}
-
-/// The following library and binary is to be used for testing the bionic linker
-/// against memtag globals. While we wait for the compiler to be updated, the
-/// files come as prebuilts (built using) the corresponding 'regular'
-/// cc_test_library and cc_test rules below, just with a tip-of-tree version of
-/// LLVM.
-///
-/// Updating the prebuilts can be done by installing a tip-of-tree compiler, and
-/// running:
-///  - m memtag_globals_binary memtag_globals_dso
-///  - cp $ANDROID_PRODUCT_OUT/symbols/data/nativetest64/bionic-loader-test-libs/prebuilt-elf-files/memtag_globals_* \
-///    $ANDROID_BUILD_TOP/bionic/tests/prebuilt-elf-files/arm64/
-///
-// cc_test_library {
-//     name: "memtag_globals_dso",
-//     defaults: [ "memtag_globals_defaults" ],
-//     srcs: ["prebuilt-elf-files/arm64/src/memtag_globals_dso.cpp"],
-// }
-//
-// cc_test {
-//     name: "memtag_globals_binary",
-//     // Not actually a '.so' file, this is an executable; but the only way to
-//     // get soong to be able to produce a properly located and linked prebuilt
-//     // variant of this binary was through the cc_prebuilt_test_library_shared
-//     // rule, which appends '.so' to the end. Once the prebuilts are removed,
-//     // the suffix can be removed.
-//     suffix: ".so",
-//     defaults: [ "memtag_globals_defaults" ],
-//     srcs: ["prebuilt-elf-files/arm64/src/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_prebuilt_test_library_shared {
-    name: "memtag_globals_dso",
-    defaults: [ "memtag_globals_defaults" ],
-    arch: {
-        arm64: {
-            srcs: ["prebuilt-elf-files/arm64/memtag_globals_dso.so"],
-        },
-    }
-}
-
-cc_prebuilt_test_library_shared {
-    name: "memtag_globals_binary",
-    defaults: [ "memtag_globals_defaults" ],
-    arch: {
-        arm64: {
-            srcs: ["prebuilt-elf-files/arm64/memtag_globals_binary.so"],
-            shared_libs: [ "memtag_globals_dso" ],
-        },
-    }
-}
-
 // -----------------------------------------------------------------------------
 // All standard tests.
 // -----------------------------------------------------------------------------
@@ -510,7 +427,6 @@
         "math_test.cpp",
         "membarrier_test.cpp",
         "memtag_stack_test.cpp",
-        "memtag_globals_test.cpp",
         "mntent_test.cpp",
         "mte_test.cpp",
         "netdb_test.cpp",
@@ -667,18 +583,6 @@
     shared: {
         enabled: false,
     },
-    cflags: [
-        "-fno-emulated-tls",
-    ],
-    // With fuzzer builds, compiler instrumentation generates a reference to the
-    // __sancov_lowest_stack variable, which (for now) is defined by the fuzzer
-    // library as an emutls symbol. The -fno-emulated-tls flag above configures
-    // the compiler to reference an ordinary ELF TLS __sancov_lowest_stack
-    // symbol instead, which isn't defined. Disable the fuzzer for this test
-    // until the platform is switched to ELF TLS.
-    sanitize: {
-        fuzzer: false,
-    },
 }
 
 cc_test_library {
@@ -697,18 +601,6 @@
     shared: {
         enabled: false,
     },
-    cflags: [
-        "-fno-emulated-tls",
-    ],
-    // With fuzzer builds, compiler instrumentation generates a reference to the
-    // __sancov_lowest_stack variable, which (for now) is defined by the fuzzer
-    // library as an emutls symbol. The -fno-emulated-tls flag above configures
-    // the compiler to reference an ordinary ELF TLS __sancov_lowest_stack
-    // symbol instead, which isn't defined. Disable the fuzzer for this test
-    // until the platform is switched to ELF TLS.
-    sanitize: {
-        fuzzer: false,
-    },
 }
 
 cc_test_library {
@@ -966,8 +858,6 @@
         "preinit_syscall_test_helper",
         "thread_exit_cb_helper",
         "tls_properties_helper",
-        "memtag_globals_binary",
-        "memtag_globals_dso",
     ],
     data_libs: [
         "libatest_simple_zip",
diff --git a/tests/ifunc_test.cpp b/tests/ifunc_test.cpp
index 1fdbf1a..09d987d 100644
--- a/tests/ifunc_test.cpp
+++ b/tests/ifunc_test.cpp
@@ -65,18 +65,18 @@
 #include <sys/hwprobe.h>
 
 static uint64_t g_hwcap;
+static __riscv_hwprobe_t g_hwprobe_ptr;
+static void* g_null;
 
 static riscv_hwprobe g_hwprobes[] = {{.key = RISCV_HWPROBE_KEY_IMA_EXT_0}};
 
-extern "C" fn_ptr_t hwcap_resolver(uint64_t hwcap, void* null) {
-  // Check hwcap like arm32/arm64.
+extern "C" fn_ptr_t hwcap_resolver(uint64_t hwcap, __riscv_hwprobe_t hwprobe_ptr, void* null) {
   g_hwcap = hwcap;
-
-  // For now, the pointer argument is reserved for future expansion.
-  if (null != NULL) abort();
+  g_hwprobe_ptr = hwprobe_ptr;
+  g_null = null;
 
   // Ensure that __riscv_hwprobe() can be called from an ifunc.
-  if (__riscv_hwprobe(g_hwprobes, 1, 0, nullptr, 0) != 0) return nullptr;
+  if ((*hwprobe_ptr)(g_hwprobes, 1, 0, nullptr, 0) != 0) return nullptr;
   return ret42;
 }
 
@@ -102,7 +102,11 @@
 #elif defined(__arm__)
   EXPECT_EQ(getauxval(AT_HWCAP), g_hwcap);
 #elif defined(__riscv)
+  printf("hwcap=%lx hwprobe_ptr=%p (__riscv_hwprobe=%p) null=%p\n", g_hwcap, g_hwprobe_ptr,
+         __riscv_hwprobe, g_null);
+
   EXPECT_EQ(getauxval(AT_HWCAP), g_hwcap);
+  EXPECT_EQ(nullptr, g_null);
 
   riscv_hwprobe probes[] = {{.key = RISCV_HWPROBE_KEY_IMA_EXT_0}};
   ASSERT_EQ(0, __riscv_hwprobe(probes, 1, 0, nullptr, 0));
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 51f5ac6..0bef469 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -29,11 +29,11 @@
         "-Wl,--rpath,${ORIGIN}",
         "-Wl,--enable-new-dtags",
     ],
+    static_libs: ["libbase"],
     relative_install_path: "bionic-loader-test-libs",
     gtest: false,
     sanitize: {
         address: false,
-        fuzzer: false,
     },
     stl: "libc++_static",
     target: {
@@ -53,14 +53,12 @@
     name: "libtest_elftls_shared_var",
     defaults: ["bionic_testlib_defaults"],
     srcs: ["elftls_shared_var.cpp"],
-    cflags: ["-fno-emulated-tls"],
 }
 
 cc_test_library {
     name: "libtest_elftls_shared_var_ie",
     defaults: ["bionic_testlib_defaults"],
     srcs: ["elftls_shared_var_ie.cpp"],
-    cflags: ["-fno-emulated-tls"],
     shared_libs: ["libtest_elftls_shared_var"],
 }
 
@@ -68,7 +66,6 @@
     name: "libtest_elftls_tprel",
     defaults: ["bionic_testlib_defaults"],
     srcs: ["elftls_tprel.cpp"],
-    cflags: ["-fno-emulated-tls"],
 }
 
 cc_test {
@@ -82,7 +79,6 @@
     name: "libtest_elftls_dynamic",
     defaults: ["bionic_testlib_defaults"],
     srcs: ["elftls_dynamic.cpp"],
-    cflags: ["-fno-emulated-tls"],
     shared_libs: ["libtest_elftls_shared_var"],
 }
 
@@ -90,14 +86,12 @@
    name: "thread_exit_cb_helper",
    defaults: ["bionic_testlib_defaults"],
    srcs: ["thread_exit_cb_helper.cpp"],
-   cflags: ["-fno-emulated-tls"],
 }
 
 cc_test {
    name: "tls_properties_helper",
    defaults: ["bionic_testlib_defaults"],
    srcs: ["tls_properties_helper.cpp"],
-   cflags: ["-fno-emulated-tls"],
    shared_libs: ["libtest_elftls_shared_var"],
 }
 
@@ -107,7 +101,6 @@
     defaults: ["bionic_testlib_defaults"],
     srcs: ["elftls_dynamic_filler.cpp"],
     cflags: [
-        "-fno-emulated-tls",
         "-DTLS_FILLER=100",
     ],
 }
@@ -117,7 +110,6 @@
     defaults: ["bionic_testlib_defaults"],
     srcs: ["elftls_dynamic_filler.cpp"],
     cflags: [
-        "-fno-emulated-tls",
         "-DTLS_FILLER=200",
     ],
 }
@@ -127,7 +119,6 @@
     defaults: ["bionic_testlib_defaults"],
     srcs: ["elftls_dynamic_filler.cpp"],
     cflags: [
-        "-fno-emulated-tls",
         "-DTLS_FILLER=300",
     ],
 }
@@ -645,7 +636,6 @@
     ],
     sanitize: {
         address: false,
-        fuzzer: false,
     },
     stl: "libc++_static",
     target: {
@@ -1739,10 +1729,6 @@
         " $(location soong_zip) -o $(out).unaligned -L 0 -C $(genDir)/zipdir -D $(genDir)/zipdir &&" +
         " $(location bionic_tests_zipalign) 4096 $(out).unaligned $(out)",
 
-    bazel_module: {
-        // Depends on soong_zip, which is not available yet.
-        bp2build_available: false
-    },
 }
 
 cc_genrule {
@@ -1781,9 +1767,4 @@
         " touch $(genDir)/zipdir/empty_file.txt &&" +
         " $(location soong_zip) -o $(out).unaligned -L 0 -C $(genDir)/zipdir -D $(genDir)/zipdir &&" +
         " $(location bionic_tests_zipalign) 4096 $(out).unaligned $(out)",
-
-    bazel_module: {
-        // Depends on soong_zip, which is not available yet.
-        bp2build_available: false
-    },
 }
diff --git a/tests/libs/heap_tagging_helper.cpp b/tests/libs/heap_tagging_helper.cpp
index ed5601a..7aad392 100644
--- a/tests/libs/heap_tagging_helper.cpp
+++ b/tests/libs/heap_tagging_helper.cpp
@@ -16,12 +16,15 @@
 
 #include <signal.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <sys/auxv.h>
 #include <sys/cdefs.h>
 #include <sys/mman.h>
 #include <unistd.h>
 #include <memory>
 
+#include <android-base/stringprintf.h>
+
 void action(int signo, siginfo_t* info __unused, void*) {
 #ifdef __ANDROID__
   if (signo == 11 && info->si_code == SEGV_MTEAERR) {
@@ -89,6 +92,13 @@
   }
 #endif  // __aarch64__
 
+  // In fact, make sure that there are no tagged mappings at all.
+  auto cmd = android::base::StringPrintf("cat /proc/%d/smaps | grep -E 'VmFlags:.* mt'", getpid());
+  if (system(cmd.c_str()) == 0) {
+    fprintf(stderr, "unexpected PROT_MTE mappings found\n");
+    return 1;
+  }
+
   fprintf(stderr, "normal exit\n");
   return 0;
 }
diff --git a/tests/memtag_globals_test.cpp b/tests/memtag_globals_test.cpp
deleted file mode 100644
index 4482c8a..0000000
--- a/tests/memtag_globals_test.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <gtest/gtest.h>
-
-#if defined(__BIONIC__)
-#include "gtest_globals.h"
-#include "platform/bionic/mte.h"
-#include "utils.h"
-#endif
-
-#include <android-base/test_utils.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <string>
-
-TEST(MemtagGlobalsTest, test) {
-    SKIP_WITH_HWASAN << "b/313613493";
-#if defined(__BIONIC__) && defined(__aarch64__)
-  std::string binary = GetPrebuiltElfDir() + "/memtag_globals_binary.so";
-  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) << "\n";
-      },
-      // We catch the global-buffer-overflow and crash only when MTE is
-      // supported.
-      mte_supported() ? -SIGSEGV : 0, "Assertions were passed");
-#else
-  GTEST_SKIP() << "bionic/arm64 only";
-#endif
-}
diff --git a/tests/prebuilt-elf-files/arm64/memtag_globals_binary.so b/tests/prebuilt-elf-files/arm64/memtag_globals_binary.so
deleted file mode 100755
index 43d7443..0000000
--- a/tests/prebuilt-elf-files/arm64/memtag_globals_binary.so
+++ /dev/null
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/memtag_globals_dso.so b/tests/prebuilt-elf-files/arm64/memtag_globals_dso.so
deleted file mode 100755
index f472a70..0000000
--- a/tests/prebuilt-elf-files/arm64/memtag_globals_dso.so
+++ /dev/null
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/src/memtag_globals_binary.cpp b/tests/prebuilt-elf-files/arm64/src/memtag_globals_binary.cpp
deleted file mode 100644
index c9ad261..0000000
--- a/tests/prebuilt-elf-files/arm64/src/memtag_globals_binary.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <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;
-}
\ No newline at end of file
diff --git a/tests/prebuilt-elf-files/arm64/src/memtag_globals_dso.cpp b/tests/prebuilt-elf-files/arm64/src/memtag_globals_dso.cpp
deleted file mode 100644
index 877108e..0000000
--- a/tests/prebuilt-elf-files/arm64/src/memtag_globals_dso.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <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/pthread_test.cpp b/tests/pthread_test.cpp
index 73090e1..749d687 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include <sys/cdefs.h>
 #include <sys/mman.h>
+#include <sys/param.h>
 #include <sys/prctl.h>
 #include <sys/resource.h>
 #include <sys/syscall.h>
@@ -784,7 +785,7 @@
   size_t guard_size;
   ASSERT_EQ(0, pthread_attr_getguardsize(&attributes, &guard_size));
   ASSERT_EQ(128U, guard_size);
-  ASSERT_EQ(4096U, GetActualGuardSize(attributes));
+  ASSERT_EQ(static_cast<unsigned long>(getpagesize()), GetActualGuardSize(attributes));
 }
 
 TEST(pthread, pthread_attr_setguardsize_reasonable) {
@@ -808,7 +809,7 @@
   size_t guard_size;
   ASSERT_EQ(0, pthread_attr_getguardsize(&attributes, &guard_size));
   ASSERT_EQ(32*1024U + 1, guard_size);
-  ASSERT_EQ(36*1024U, GetActualGuardSize(attributes));
+  ASSERT_EQ(roundup(32 * 1024U + 1, getpagesize()), GetActualGuardSize(attributes));
 }
 
 TEST(pthread, pthread_attr_setguardsize_enormous) {
diff --git a/tests/semaphore_test.cpp b/tests/semaphore_test.cpp
index 5b061be..5558134 100644
--- a/tests/semaphore_test.cpp
+++ b/tests/semaphore_test.cpp
@@ -52,7 +52,7 @@
 
   // Too large an initial value.
   errno = 0;
-  ASSERT_EQ(-1, sem_init(&s, 0, SEM_VALUE_MAX + 1));
+  ASSERT_EQ(-1, sem_init(&s, 0, static_cast<unsigned>(SEM_VALUE_MAX) + 1));
   ASSERT_ERRNO(EINVAL);
 
   ASSERT_EQ(0, sem_destroy(&s));
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 21c79c8..4793150 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -901,6 +901,12 @@
   ASSERT_ERRNO(ERANGE);
   ASSERT_EQ('\0', *end_p);
 
+  // Junk at the end of a valid conversion.
+  errno = 0;
+  ASSERT_EQ(static_cast<T>(123), fn("123abc", &end_p, 0));
+  ASSERT_ERRNO(0);
+  ASSERT_STREQ("abc", end_p);
+
   // In case of overflow, strto* leaves us pointing past the end of the number,
   // not at the digit that overflowed.
   end_p = nullptr;
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 6a94507..e9a3080 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -1127,8 +1127,8 @@
 
 TEST(UNISTD_TEST, sysconf_SC_ARG_MAX) {
   // Since Linux 2.6.23, ARG_MAX isn't a constant and depends on RLIMIT_STACK.
-  // See prepare_arg_pages() in the kernel for the gory details:
-  // https://elixir.bootlin.com/linux/v5.3.11/source/fs/exec.c#L451
+  // See setup_arg_pages() in the kernel for the gory details:
+  // https://elixir.bootlin.com/linux/v6.6.4/source/fs/exec.c#L749
 
   // Get our current limit, and set things up so we restore the limit.
   rlimit rl;
@@ -1145,19 +1145,24 @@
   // _SC_ARG_MAX should be 1/4 the stack size.
   EXPECT_EQ(static_cast<long>(rl.rlim_cur / 4), sysconf(_SC_ARG_MAX));
 
-  // If you have a really small stack, the kernel still guarantees "32 pages" (see fs/exec.c).
+  // If you have a really small stack, the kernel still guarantees a stack
+  // expansion of 128KiB (see setup_arg_pages() in fs/exec.c).
   rl.rlim_cur = 1024;
   rl.rlim_max = RLIM_INFINITY;
   ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
 
-  EXPECT_EQ(static_cast<long>(32 * sysconf(_SC_PAGE_SIZE)), sysconf(_SC_ARG_MAX));
+  // The stack expansion number is defined in fs/exec.c.
+  // https://elixir.bootlin.com/linux/v6.6.4/source/fs/exec.c#L845
+  constexpr long kernel_stack_expansion = 131072;
+  EXPECT_EQ(kernel_stack_expansion, sysconf(_SC_ARG_MAX));
 
-  // With a 128-page stack limit, we know exactly what _SC_ARG_MAX should be...
-  rl.rlim_cur = 128 * sysconf(_SC_PAGE_SIZE);
+  // If you have a large stack, the kernel will keep the stack
+  // expansion to 128KiB (see setup_arg_pages() in fs/exec.c).
+  rl.rlim_cur = 524288;
   rl.rlim_max = RLIM_INFINITY;
   ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
 
-  EXPECT_EQ(static_cast<long>((128 * sysconf(_SC_PAGE_SIZE)) / 4), sysconf(_SC_ARG_MAX));
+  EXPECT_EQ(kernel_stack_expansion, sysconf(_SC_ARG_MAX));
 }
 
 TEST(UNISTD_TEST, sysconf_unknown) {