Merge changes from topic "future_symbol"

* changes:
  crtbegin_static is built with min_sdk_version: "current"
  Guard __libc_current_sigrtmin/max with __builtin_available
  __INTRODUCED_IN macros add the availability attribute
diff --git a/libc/Android.bp b/libc/Android.bp
index 1a63351..0ee353d 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1631,6 +1631,7 @@
             "gwp_asan",
             "libc_init_dynamic",
             "libc_common_shared",
+            "libunwind-exported",
         ],
     },
 
@@ -1672,8 +1673,6 @@
                 srcs: [":libc_sources_shared_arm"],
                 // special for arm
                 cflags: ["-DCRT_LEGACY_WORKAROUND"],
-
-                whole_static_libs: [ "libunwind_llvm" ],
             },
 
             // Arm 32 bit does not produce complete exidx unwind information
@@ -1692,10 +1691,6 @@
             strip: {
                 keep_symbols: true,
             },
-
-            shared: {
-                whole_static_libs: [ "libgcc_stripped" ],
-            },
         },
         x86: {
             // TODO: This is to work around b/24465209. Remove after root cause is fixed.
@@ -1709,10 +1704,6 @@
             strip: {
                 keep_symbols: true,
             },
-
-            shared: {
-                whole_static_libs: [ "libgcc_stripped" ],
-            },
         },
         x86_64: {
             version_script: ":libc.x86_64.map",
@@ -1722,10 +1713,6 @@
             strip: {
                 keep_symbols: true,
             },
-
-            shared: {
-                whole_static_libs: [ "libgcc_stripped" ],
-            },
         },
     },
 
@@ -2250,7 +2237,6 @@
 
 ndk_library {
     name: "libc",
-    native_bridge_supported: true,
     symbol_file: "libc.map.txt",
     first_version: "9",
 }
diff --git a/libc/bionic/heap_tagging.cpp b/libc/bionic/heap_tagging.cpp
index 49b02da..ffbabb9 100644
--- a/libc/bionic/heap_tagging.cpp
+++ b/libc/bionic/heap_tagging.cpp
@@ -52,6 +52,9 @@
         globals->heap_pointer_tag = (reinterpret_cast<uintptr_t>(POINTER_TAG) << TAG_SHIFT) |
                                     (0xffull << CHECK_SHIFT) | (0xffull << UNTAG_SHIFT);
       });
+#if defined(USE_SCUDO)
+      scudo_malloc_disable_memory_tagging();
+#endif  // USE_SCUDO
       break;
 #if defined(USE_SCUDO)
     case M_HEAP_TAGGING_LEVEL_SYNC:
@@ -96,12 +99,7 @@
 }
 
 // Requires `g_heap_tagging_lock` to be held.
-bool SetHeapTaggingLevel(void* arg, size_t arg_size) {
-  if (arg_size != sizeof(HeapTaggingLevel)) {
-    return false;
-  }
-
-  auto tag_level = *reinterpret_cast<HeapTaggingLevel*>(arg);
+bool SetHeapTaggingLevel(HeapTaggingLevel tag_level) {
   if (tag_level == heap_tagging_level) {
     return true;
   }
diff --git a/libc/bionic/heap_tagging.h b/libc/bionic/heap_tagging.h
index db45fc1..110b6ed 100644
--- a/libc/bionic/heap_tagging.h
+++ b/libc/bionic/heap_tagging.h
@@ -42,5 +42,5 @@
 
 // These functions can be called in a multithreaded context, and thus should
 // only be called when holding the `g_heap_tagging_lock`.
-bool SetHeapTaggingLevel(void* arg, size_t arg_size);
+bool SetHeapTaggingLevel(HeapTaggingLevel level);
 HeapTaggingLevel GetHeapTaggingLevel();
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index 3705606..2e4ee11 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -39,15 +39,17 @@
 #include "libc_init_common.h"
 #include "pthread_internal.h"
 
+#include "platform/bionic/macros.h"
+#include "platform/bionic/mte.h"
 #include "platform/bionic/page.h"
+#include "private/KernelArgumentBlock.h"
+#include "private/bionic_asm.h"
+#include "private/bionic_asm_note.h"
 #include "private/bionic_call_ifunc_resolver.h"
 #include "private/bionic_elf_tls.h"
 #include "private/bionic_globals.h"
-#include "platform/bionic/macros.h"
-#include "private/bionic_asm.h"
-#include "private/bionic_asm_note.h"
 #include "private/bionic_tls.h"
-#include "private/KernelArgumentBlock.h"
+#include "sys/system_properties.h"
 
 #if __has_feature(hwaddress_sanitizer)
 #include <sanitizer/hwasan_interface.h>
@@ -61,6 +63,7 @@
 #endif
 
 extern "C" int __cxa_atexit(void (*)(void *), void *, void *);
+extern "C" const char* __gnu_basename(const char* path);
 
 static void call_array(init_func_t** list, int argc, char* argv[], char* envp[]) {
   // First element is -1, list is null-terminated
@@ -160,6 +163,30 @@
   layout.finish_layout();
 }
 
+// Get the presiding config string, in the following order of priority:
+//   1. Environment variables.
+//   2. System properties, in the order they're specified in sys_prop_names.
+// If neither of these options are specified, this function returns false.
+// Otherwise, it returns true, and the presiding options string is written to
+// the `options` buffer of size `size`. If this function returns true, `options`
+// is guaranteed to be null-terminated. `options_size` should be at least
+// PROP_VALUE_MAX.
+bool get_config_from_env_or_sysprops(const char* env_var_name, const char* const* sys_prop_names,
+                                     size_t sys_prop_names_size, char* options,
+                                     size_t options_size) {
+  const char* env = getenv(env_var_name);
+  if (env && *env != '\0') {
+    strncpy(options, env, options_size);
+    options[options_size - 1] = '\0'; // Ensure null-termination.
+    return true;
+  }
+
+  for (size_t i = 0; i < sys_prop_names_size; ++i) {
+    if (__system_property_get(sys_prop_names[i], options) && *options != '\0') return true;
+  }
+  return false;
+}
+
 #ifdef __aarch64__
 static bool __read_memtag_note(const ElfW(Nhdr)* note, const char* name, const char* desc,
                                unsigned* result) {
@@ -204,42 +231,94 @@
   return 0;
 }
 
+// Returns true if there's an environment setting (either sysprop or env var)
+// that should overwrite the ELF note, and places the equivalent heap tagging
+// level into *level.
+static bool get_environment_memtag_setting(HeapTaggingLevel* level) {
+  static const char kMemtagPrognameSyspropPrefix[] = "arm64.memtag.process.";
+
+  const char* progname = __libc_shared_globals()->init_progname;
+  if (progname == nullptr) return false;
+
+  const char* basename = __gnu_basename(progname);
+
+  static constexpr size_t kOptionsSize = PROP_VALUE_MAX;
+  char options_str[kOptionsSize];
+  size_t sysprop_size = strlen(basename) + strlen(kMemtagPrognameSyspropPrefix) + 1;
+  char* sysprop_name = static_cast<char*>(alloca(sysprop_size));
+
+  async_safe_format_buffer(sysprop_name, sysprop_size, "%s%s", kMemtagPrognameSyspropPrefix,
+                           basename);
+
+  if (!get_config_from_env_or_sysprops("MEMTAG_OPTIONS", &sysprop_name,
+                                       /* sys_prop_names_size */ 1, options_str, kOptionsSize)) {
+    return false;
+  }
+
+  if (strcmp("sync", options_str) == 0) {
+    *level = M_HEAP_TAGGING_LEVEL_SYNC;
+  } else if (strcmp("async", options_str) == 0) {
+    *level = M_HEAP_TAGGING_LEVEL_ASYNC;
+  } else if (strcmp("off", options_str) == 0) {
+    *level = M_HEAP_TAGGING_LEVEL_TBI;
+  } else {
+    async_safe_format_log(
+        ANDROID_LOG_ERROR, "libc",
+        "unrecognized memtag level: \"%s\" (options are \"sync\", \"async\", or \"off\").",
+        options_str);
+    return false;
+  }
+
+  return true;
+}
+
+// Returns the initial heap tagging level. Note: This function will never return
+// M_HEAP_TAGGING_LEVEL_NONE, if MTE isn't enabled for this process we enable
+// M_HEAP_TAGGING_LEVEL_TBI.
+static HeapTaggingLevel __get_heap_tagging_level(const void* phdr_start, size_t phdr_ct,
+                                                 uintptr_t load_bias) {
+  HeapTaggingLevel level;
+  if (get_environment_memtag_setting(&level)) return level;
+
+  unsigned note_val =
+      __get_memtag_note(reinterpret_cast<const ElfW(Phdr)*>(phdr_start), phdr_ct, load_bias);
+  if (note_val & ~(NT_MEMTAG_LEVEL_MASK | NT_MEMTAG_HEAP)) {
+    async_safe_fatal("unrecognized android.memtag note: desc = %d", note_val);
+  }
+
+  if (!(note_val & NT_MEMTAG_HEAP)) return M_HEAP_TAGGING_LEVEL_TBI;
+
+  unsigned memtag_level = note_val & NT_MEMTAG_LEVEL_MASK;
+  switch (memtag_level) {
+    case NT_MEMTAG_LEVEL_ASYNC:
+      return M_HEAP_TAGGING_LEVEL_ASYNC;
+    case NT_MEMTAG_LEVEL_DEFAULT:
+    case NT_MEMTAG_LEVEL_SYNC:
+      return M_HEAP_TAGGING_LEVEL_SYNC;
+    default:
+      async_safe_fatal("unrecognized android.memtag note: level = %d", memtag_level);
+  }
+}
+
 // Figure out the desired memory tagging mode (sync/async, heap/globals/stack) for this executable.
 // This function is called from the linker before the main executable is relocated.
 __attribute__((no_sanitize("hwaddress", "memtag"))) void __libc_init_mte(const void* phdr_start,
                                                                          size_t phdr_ct,
                                                                          uintptr_t load_bias) {
-  unsigned v =
-      __get_memtag_note(reinterpret_cast<const ElfW(Phdr)*>(phdr_start), phdr_ct, load_bias);
+  HeapTaggingLevel level = __get_heap_tagging_level(phdr_start, phdr_ct, load_bias);
 
-  if (v & ~(NT_MEMTAG_LEVEL_MASK | NT_MEMTAG_HEAP)) {
-    async_safe_fatal("unrecognized android.memtag note: desc = %d", v);
-  }
+  if (level == M_HEAP_TAGGING_LEVEL_SYNC || level == M_HEAP_TAGGING_LEVEL_ASYNC) {
+    unsigned long prctl_arg = PR_TAGGED_ADDR_ENABLE | PR_MTE_TAG_SET_NONZERO;
+    prctl_arg |= (level == M_HEAP_TAGGING_LEVEL_SYNC) ? PR_MTE_TCF_SYNC : PR_MTE_TCF_ASYNC;
 
-  if (v & NT_MEMTAG_HEAP) {
-    unsigned memtag_level = v & NT_MEMTAG_LEVEL_MASK;
-    unsigned long arg = PR_TAGGED_ADDR_ENABLE | (0xfffe << PR_MTE_TAG_SHIFT);
-    HeapTaggingLevel level;
-    switch (memtag_level) {
-      case NT_MEMTAG_LEVEL_ASYNC:
-        arg |= PR_MTE_TCF_ASYNC;
-        level = M_HEAP_TAGGING_LEVEL_ASYNC;
-        break;
-      case NT_MEMTAG_LEVEL_DEFAULT:
-      case NT_MEMTAG_LEVEL_SYNC:
-        arg |= PR_MTE_TCF_SYNC;
-        level = M_HEAP_TAGGING_LEVEL_SYNC;
-        break;
-      default:
-        async_safe_fatal("unrecognized android.memtag note: level = %d", memtag_level);
-    }
-
-    if (prctl(PR_SET_TAGGED_ADDR_CTRL, arg, 0, 0, 0) == 0) {
+    if (prctl(PR_SET_TAGGED_ADDR_CTRL, prctl_arg, 0, 0, 0) == 0) {
       __libc_shared_globals()->initial_heap_tagging_level = level;
       return;
     }
   }
 
+  // MTE was either not enabled, or wasn't supported on this device. Try and use
+  // TBI.
   if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0) == 0) {
     __libc_shared_globals()->initial_heap_tagging_level = M_HEAP_TAGGING_LEVEL_TBI;
   }
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 0ee12a7..863103d 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -102,6 +102,15 @@
 }
 
 extern "C" int mallopt(int param, int value) {
+  // Some are handled by libc directly rather than by the allocator.
+  if (param == M_BIONIC_SET_HEAP_TAGGING_LEVEL) {
+    ScopedPthreadMutexLocker locker(&g_heap_tagging_lock);
+    return SetHeapTaggingLevel(static_cast<HeapTaggingLevel>(value));
+  }
+  if (param == M_BIONIC_DISABLE_MEMORY_MITIGATIONS) {
+    return DisableMemoryMitigations(value);
+  }
+  // The rest we pass on...
   auto dispatch_table = GetDispatchTable();
   if (__predict_false(dispatch_table != nullptr)) {
     return dispatch_table->mallopt(param, value);
@@ -316,10 +325,6 @@
   if (opcode == M_SET_ALLOCATION_LIMIT_BYTES) {
     return LimitEnable(arg, arg_size);
   }
-  if (opcode == M_SET_HEAP_TAGGING_LEVEL) {
-    ScopedPthreadMutexLocker locker(&g_heap_tagging_lock);
-    return SetHeapTaggingLevel(arg, arg_size);
-  }
   if (opcode == M_INITIALIZE_GWP_ASAN) {
     if (arg == nullptr || arg_size != sizeof(bool)) {
       errno = EINVAL;
@@ -329,9 +334,6 @@
       return MaybeInitGwpAsan(globals, *reinterpret_cast<bool*>(arg));
     });
   }
-  if (opcode == M_DISABLE_MEMORY_MITIGATIONS) {
-    return DisableMemoryMitigations(arg, arg_size);
-  }
   errno = ENOTSUP;
   return false;
 }
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
index 2d6a1bb..7a221d8 100644
--- a/libc/bionic/malloc_common_dynamic.cpp
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -523,10 +523,6 @@
     }
     return FreeMallocLeakInfo(reinterpret_cast<android_mallopt_leak_info_t*>(arg));
   }
-  if (opcode == M_SET_HEAP_TAGGING_LEVEL) {
-    ScopedPthreadMutexLocker locker(&g_heap_tagging_lock);
-    return SetHeapTaggingLevel(arg, arg_size);
-  }
   if (opcode == M_INITIALIZE_GWP_ASAN) {
     if (arg == nullptr || arg_size != sizeof(bool)) {
       errno = EINVAL;
@@ -536,9 +532,6 @@
       return MaybeInitGwpAsan(globals, *reinterpret_cast<bool*>(arg));
     });
   }
-  if (opcode == M_DISABLE_MEMORY_MITIGATIONS) {
-    return DisableMemoryMitigations(arg, arg_size);
-  }
   // Try heapprofd's mallopt, as it handles options not covered here.
   return HeapprofdMallopt(opcode, arg, arg_size);
 }
diff --git a/libc/bionic/memory_mitigation_state.cpp b/libc/bionic/memory_mitigation_state.cpp
index 4761d88..b262f86 100644
--- a/libc/bionic/memory_mitigation_state.cpp
+++ b/libc/bionic/memory_mitigation_state.cpp
@@ -47,8 +47,8 @@
 
 extern "C" void scudo_malloc_set_zero_contents(int zero_contents);
 
-bool DisableMemoryMitigations(void* arg, size_t arg_size) {
-  if (arg || arg_size) {
+bool DisableMemoryMitigations(int arg) {
+  if (arg != 0) {
     return false;
   }
 
@@ -61,7 +61,7 @@
   HeapTaggingLevel current_level = GetHeapTaggingLevel();
   if (current_level != M_HEAP_TAGGING_LEVEL_NONE && current_level != M_HEAP_TAGGING_LEVEL_TBI) {
     HeapTaggingLevel level = M_HEAP_TAGGING_LEVEL_NONE;
-    SetHeapTaggingLevel(reinterpret_cast<void*>(&level), sizeof(level));
+    SetHeapTaggingLevel(level);
   }
 
   return true;
diff --git a/libc/bionic/memory_mitigation_state.h b/libc/bionic/memory_mitigation_state.h
index ffa1912..047b6ad 100644
--- a/libc/bionic/memory_mitigation_state.h
+++ b/libc/bionic/memory_mitigation_state.h
@@ -30,4 +30,4 @@
 
 #include <stddef.h>
 
-bool DisableMemoryMitigations(void* arg, size_t arg_size);
+bool DisableMemoryMitigations(int arg);
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index a237254..598a50b 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -204,6 +204,60 @@
 #define M_TSDS_COUNT_MAX (-202)
 
 /**
+ * mallopt() option to disable heap initialization across the whole process.
+ * If the hardware supports memory tagging, this also disables memory tagging.
+ * May be called at any time, including when multiple threads are running. The
+ * value is unused but must be set to 0.
+ *
+ * Note that these memory mitigations are only implemented in scudo and
+ * therefore this will have no effect when using another allocator (such as
+ * jemalloc on Android Go devices).
+ *
+ * Available since API level 31.
+ */
+#define M_BIONIC_DISABLE_MEMORY_MITIGATIONS (-203)
+
+/**
+ * mallopt() option to change the heap tagging state. May be called at any
+ * time, including when multiple threads are running.
+ * The value must be one of the M_HEAP_TAGGING_LEVEL_ constants.
+ *
+ * Available since API level 31.
+ */
+#define M_BIONIC_SET_HEAP_TAGGING_LEVEL (-204)
+
+/**
+ * Constants for use with the M_BIONIC_SET_HEAP_TAGGING_LEVEL mallopt() option.
+ */
+enum HeapTaggingLevel {
+  /**
+   * Disable heap tagging and memory tag checks (if supported).
+   * Heap tagging may not be re-enabled after being disabled.
+   */
+  M_HEAP_TAGGING_LEVEL_NONE = 0,
+#define M_HEAP_TAGGING_LEVEL_NONE M_HEAP_TAGGING_LEVEL_NONE
+  /**
+   * Address-only tagging. Heap pointers have a non-zero tag in the
+   * most significant ("top") byte which is checked in free(). Memory
+   * accesses ignore the tag using arm64's Top Byte Ignore (TBI) feature.
+   */
+  M_HEAP_TAGGING_LEVEL_TBI = 1,
+#define M_HEAP_TAGGING_LEVEL_TBI M_HEAP_TAGGING_LEVEL_TBI
+  /**
+   * Enable heap tagging and asynchronous memory tag checks (if supported).
+   * Disable stack trace collection.
+   */
+  M_HEAP_TAGGING_LEVEL_ASYNC = 2,
+#define M_HEAP_TAGGING_LEVEL_ASYNC M_HEAP_TAGGING_LEVEL_ASYNC
+  /**
+   * Enable heap tagging and synchronous memory tag checks (if supported).
+   * Enable stack trace collection.
+   */
+  M_HEAP_TAGGING_LEVEL_SYNC = 3,
+#define M_HEAP_TAGGING_LEVEL_SYNC M_HEAP_TAGGING_LEVEL_SYNC
+};
+
+/**
  * [mallopt(3)](http://man7.org/linux/man-pages/man3/mallopt.3.html) modifies
  * heap behavior. Values of `__option` are the `M_` constants from this header.
  *
diff --git a/libc/platform/bionic/malloc.h b/libc/platform/bionic/malloc.h
index 56badf0..b56ca74 100644
--- a/libc/platform/bionic/malloc.h
+++ b/libc/platform/bionic/malloc.h
@@ -28,6 +28,7 @@
 
 #pragma once
 
+#include <malloc.h>
 #include <stdbool.h>
 #include <stdint.h>
 
@@ -85,12 +86,6 @@
   //   arg_size = sizeof(android_mallopt_leak_info_t)
   M_FREE_MALLOC_LEAK_INFO = 7,
 #define M_FREE_MALLOC_LEAK_INFO M_FREE_MALLOC_LEAK_INFO
-  // Change the heap tagging state. May be called at any time including when
-  // multiple threads are running.
-  //   arg = HeapTaggingLevel*
-  //   arg_size = sizeof(HeapTaggingLevel)
-  M_SET_HEAP_TAGGING_LEVEL = 8,
-#define M_SET_HEAP_TAGGING_LEVEL M_SET_HEAP_TAGGING_LEVEL
   // Query whether the current process is considered to be profileable by the
   // Android platform. Result is assigned to the arg pointer's destination.
   //   arg = bool*
@@ -105,28 +100,6 @@
   //   arg_size = sizeof(bool)
   M_INITIALIZE_GWP_ASAN = 10,
 #define M_INITIALIZE_GWP_ASAN M_INITIALIZE_GWP_ASAN
-  // Disable heap initialization across the whole process. If the hardware supports memory
-  // tagging, it also disables memory tagging. May be called at any time including
-  // when multiple threads are running. arg and arg_size are unused and must be set to 0.
-  // Note that the memory mitigations are only implemented in scudo and therefore this API call will
-  // have no effect when using another allocator.
-  M_DISABLE_MEMORY_MITIGATIONS = 11,
-#define M_DISABLE_MEMORY_MITIGATIONS M_DISABLE_MEMORY_MITIGATIONS
-};
-
-enum HeapTaggingLevel {
-  // Disable heap tagging and memory tag checks if supported. Heap tagging may not be re-enabled
-  // after being disabled.
-  M_HEAP_TAGGING_LEVEL_NONE = 0,
-  // Address-only tagging. Heap pointers have a non-zero tag in the most significant byte which is
-  // checked in free(). Memory accesses ignore the tag.
-  M_HEAP_TAGGING_LEVEL_TBI = 1,
-  // Enable heap tagging and asynchronous memory tag checks if supported. Disable stack trace
-  // collection.
-  M_HEAP_TAGGING_LEVEL_ASYNC = 2,
-  // Enable heap tagging and synchronous memory tag checks if supported. Enable stack trace
-  // collection.
-  M_HEAP_TAGGING_LEVEL_SYNC = 3,
 };
 
 // Manipulates bionic-specific handling of memory allocation APIs such as
diff --git a/libc/platform/bionic/mte.h b/libc/platform/bionic/mte.h
index b11b1a6..73cd821 100644
--- a/libc/platform/bionic/mte.h
+++ b/libc/platform/bionic/mte.h
@@ -29,6 +29,13 @@
 #pragma once
 
 #include <sys/auxv.h>
+#include <sys/prctl.h>
+
+// Note: Most PR_MTE_* constants come from the upstream kernel. This tag mask
+// allows for the hardware to provision any nonzero tag. Zero tags are reserved
+// for scudo to use for the chunk headers in order to prevent linear heap
+// overflow/underflow.
+#define PR_MTE_TAG_SET_NONZERO (0xfffeUL << PR_MTE_TAG_SHIFT)
 
 inline bool mte_supported() {
 #if defined(__aarch64__)
diff --git a/libc/system_properties/context_lookup_benchmark_data.h b/libc/system_properties/context_lookup_benchmark_data.h
index 3cc3257..b928875 100644
--- a/libc/system_properties/context_lookup_benchmark_data.h
+++ b/libc/system_properties/context_lookup_benchmark_data.h
@@ -885,7 +885,6 @@
 ro.kernel.qemu             u:object_r:exported_default_prop:s0 exact bool
 ro.kernel.qemu.            u:object_r:exported_default_prop:s0
 ro.kernel.android.bootanim u:object_r:exported_default_prop:s0 exact int
-ro.kernel.ebpf.supported   u:object_r:exported_default_prop:s0 exact bool
 
 ro.oem.key1 u:object_r:exported_default_prop:s0 exact string
 
diff --git a/libdl/Android.bp b/libdl/Android.bp
index 9a31d36..91f85f9 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -216,7 +216,6 @@
 
 ndk_library {
     name: "libdl",
-    native_bridge_supported: true,
     symbol_file: "libdl.map.txt",
     first_version: "9",
 }
diff --git a/libm/Android.bp b/libm/Android.bp
index 6c8ad22..21be51b 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -516,7 +516,6 @@
 
 ndk_library {
     name: "libm",
-    native_bridge_supported: true,
     symbol_file: "libm.map.txt",
     first_version: "9",
 }
diff --git a/linker/Android.bp b/linker/Android.bp
index 3ebae59..efda312 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -232,19 +232,15 @@
     arch: {
         arm: {
             srcs: [":linker_sources_arm"],
-            static_libs: ["libunwind_llvm"],
         },
         arm64: {
             srcs: [":linker_sources_arm64"],
-            static_libs: ["libgcc_stripped"],
         },
         x86: {
             srcs: [":linker_sources_x86"],
-            static_libs: ["libgcc_stripped"],
         },
         x86_64: {
             srcs: [":linker_sources_x86_64"],
-            static_libs: ["libgcc_stripped"],
         },
     },
 
@@ -292,6 +288,7 @@
         "libc_nomalloc",
         "libc_dynamic_dispatch",
         "libm",
+        "libunwind",
     ],
 
     // Ensure that if the linker needs __gnu_Unwind_Find_exidx, then the linker will have a
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index ec6850a..af05027 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -332,7 +332,8 @@
     __libdl_info->target_sdk_version_ = __ANDROID_API__;
     __libdl_info->generate_handle();
 #if defined(__work_around_b_24465209__)
-    strlcpy(__libdl_info->old_name_, __libdl_info->soname_, sizeof(__libdl_info->old_name_));
+    strlcpy(__libdl_info->old_name_, __libdl_info->soname_.c_str(),
+            sizeof(__libdl_info->old_name_));
 #endif
   }
 
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 2481be4..c240c56 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1339,8 +1339,7 @@
                                           const char* name,
                                           soinfo** candidate) {
   return !ns->soinfo_list().visit([&](soinfo* si) {
-    const char* soname = si->get_soname();
-    if (soname != nullptr && (strcmp(name, soname) == 0)) {
+    if (strcmp(name, si->get_soname()) == 0) {
       *candidate = si;
       return false;
     }
@@ -2571,9 +2570,8 @@
 
     const char* target_soname = si_from->get_string(verneed->vn_file);
     // find it in dependencies
-    soinfo* target_si = si_from->get_children().find_if([&](const soinfo* si) {
-      return si->get_soname() != nullptr && strcmp(si->get_soname(), target_soname) == 0;
-    });
+    soinfo* target_si = si_from->get_children().find_if(
+        [&](const soinfo* si) { return strcmp(si->get_soname(), target_soname) == 0; });
 
     if (target_si == nullptr) {
       DL_ERR("cannot find \"%s\" from verneed[%zd] in DT_NEEDED list for \"%s\"",
@@ -3195,34 +3193,32 @@
     return false;
   }
 
-  // second pass - parse entries relying on strtab
-  for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
-    switch (d->d_tag) {
-      case DT_SONAME:
-        set_soname(get_string(d->d_un.d_val));
-        break;
-      case DT_RUNPATH:
-        set_dt_runpath(get_string(d->d_un.d_val));
-        break;
+  // Second pass - parse entries relying on strtab. Skip this while relocating the linker so as to
+  // avoid doing heap allocations until later in the linker's initialization.
+  if (!relocating_linker) {
+    for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
+      switch (d->d_tag) {
+        case DT_SONAME:
+          set_soname(get_string(d->d_un.d_val));
+          break;
+        case DT_RUNPATH:
+          set_dt_runpath(get_string(d->d_un.d_val));
+          break;
+      }
     }
   }
 
-  // Before M release linker was using basename in place of soname.
-  // In the case when dt_soname is absent some apps stop working
-  // because they can't find dt_needed library by soname.
-  // This workaround should keep them working. (Applies only
-  // for apps targeting sdk version < M.) Make an exception for
-  // the main executable and linker; they do not need to have dt_soname.
-  // TODO: >= O the linker doesn't need this workaround.
-  if (soname_ == nullptr &&
-      this != solist_get_somain() &&
-      (flags_ & FLAG_LINKER) == 0 &&
+  // Before M release, linker was using basename in place of soname. In the case when DT_SONAME is
+  // absent some apps stop working because they can't find DT_NEEDED library by soname. This
+  // workaround should keep them working. (Applies only for apps targeting sdk version < M.) Make
+  // an exception for the main executable, which does not need to have DT_SONAME. The linker has an
+  // DT_SONAME but the soname_ field is initialized later on.
+  if (soname_.empty() && this != solist_get_somain() && !relocating_linker &&
       get_application_target_sdk_version() < 23) {
     soname_ = basename(realpath_.c_str());
-    DL_WARN_documented_change(23,
-                              "missing-soname-enforced-for-api-level-23",
-                              "\"%s\" has no DT_SONAME (will use %s instead)",
-                              get_realpath(), soname_);
+    DL_WARN_documented_change(23, "missing-soname-enforced-for-api-level-23",
+                              "\"%s\" has no DT_SONAME (will use %s instead)", get_realpath(),
+                              soname_.c_str());
 
     // Don't call add_dlwarning because a missing DT_SONAME isn't important enough to show in the UI
   }
diff --git a/linker/linker_cfi.cpp b/linker/linker_cfi.cpp
index 87b5d34..6bc2615 100644
--- a/linker/linker_cfi.cpp
+++ b/linker/linker_cfi.cpp
@@ -133,8 +133,7 @@
 
 static soinfo* find_libdl(soinfo* solist) {
   for (soinfo* si = solist; si != nullptr; si = si->next) {
-    const char* soname = si->get_soname();
-    if (soname && strcmp(soname, "libdl.so") == 0) {
+    if (strcmp(si->get_soname(), "libdl.so") == 0) {
       return si;
     }
   }
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 59e8036..0b501a7 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -725,6 +725,13 @@
   // Initialize the linker's own global variables
   tmp_linker_so.call_constructors();
 
+  // Setting the linker soinfo's soname can allocate heap memory, so delay it until here.
+  for (const ElfW(Dyn)* d = tmp_linker_so.dynamic; d->d_tag != DT_NULL; ++d) {
+    if (d->d_tag == DT_SONAME) {
+      tmp_linker_so.set_soname(tmp_linker_so.get_string(d->d_un.d_val));
+    }
+  }
+
   // When the linker is run directly rather than acting as PT_INTERP, parse
   // arguments and determine the executable to load. When it's instead acting
   // as PT_INTERP, AT_ENTRY will refer to the loaded executable rather than the
diff --git a/linker/linker_namespaces.h b/linker/linker_namespaces.h
index 77b6622..6817901 100644
--- a/linker/linker_namespaces.h
+++ b/linker/linker_namespaces.h
@@ -56,9 +56,6 @@
   }
 
   bool is_accessible(const char* soname) const {
-    if (soname == nullptr) {
-      return false;
-    }
     return allow_all_shared_libs_ || shared_lib_sonames_.find(soname) != shared_lib_sonames_.end();
   }
 
diff --git a/linker/linker_soinfo.cpp b/linker/linker_soinfo.cpp
index 60fd242..287e757 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -485,11 +485,8 @@
 }
 
 template <typename F>
-static void call_array(const char* array_name __unused,
-                       F* functions,
-                       size_t count,
-                       bool reverse,
-                       const char* realpath) {
+static inline void call_array(const char* array_name __unused, F* functions, size_t count,
+                              bool reverse, const char* realpath) {
   if (functions == nullptr) {
     return;
   }
@@ -695,7 +692,7 @@
   if (has_min_version(2)) {
     soname_ = soname;
   }
-  strlcpy(old_name_, soname_, sizeof(old_name_));
+  strlcpy(old_name_, soname_.c_str(), sizeof(old_name_));
 #else
   soname_ = soname;
 #endif
@@ -704,12 +701,12 @@
 const char* soinfo::get_soname() const {
 #if defined(__work_around_b_24465209__)
   if (has_min_version(2)) {
-    return soname_;
+    return soname_.c_str();
   } else {
     return old_name_;
   }
 #else
-  return soname_;
+  return soname_.c_str();
 #endif
 }
 
diff --git a/linker/linker_soinfo.h b/linker/linker_soinfo.h
index 7372a51..9c589d6 100644
--- a/linker/linker_soinfo.h
+++ b/linker/linker_soinfo.h
@@ -401,7 +401,7 @@
   uint8_t* android_relocs_;
   size_t android_relocs_size_;
 
-  const char* soname_;
+  std::string soname_;
   std::string realpath_;
 
   const ElfW(Versym)* versym_;
diff --git a/tests/Android.bp b/tests/Android.bp
index e7118b3..678eae8 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -845,66 +845,95 @@
         "elftls_dlopen_ie_error_helper",
         "exec_linker_helper",
         "exec_linker_helper_lib",
-        "libtest_dt_runpath_a",
-        "libtest_dt_runpath_b",
-        "libtest_dt_runpath_c",
-        "libtest_dt_runpath_x",
-        "libtest_dt_runpath_y",
+        "heap_tagging_async_helper",
+        "heap_tagging_disabled_helper",
+        "heap_tagging_static_async_helper",
+        "heap_tagging_static_disabled_helper",
+        "heap_tagging_static_sync_helper",
+        "heap_tagging_sync_helper",
+        "ld_config_test_helper",
+        "ld_config_test_helper_lib1",
+        "ld_config_test_helper_lib2",
+        "ld_config_test_helper_lib3",
+        "ld_preload_test_helper",
+        "ld_preload_test_helper_lib1",
+        "ld_preload_test_helper_lib2",
         "libatest_simple_zip",
         "libcfi-test",
         "libcfi-test-bad",
+        "libdl_preempt_test_1",
+        "libdl_preempt_test_2",
+        "libdl_test_df_1_global",
+        "libdlext_test",
         "libdlext_test_different_soname",
         "libdlext_test_fd",
         "libdlext_test_norelro",
         "libdlext_test_recursive",
         "libdlext_test_runpath_zip_zipaligned",
-        "libdlext_test",
         "libdlext_test_zip",
         "libdlext_test_zip_zipaligned",
-        "libdl_preempt_test_1",
-        "libdl_preempt_test_2",
-        "libdl_test_df_1_global",
         "libgnu-hash-table-library",
-        "librelocations-ANDROID_RELR",
+        "libns_hidden_child_app",
+        "libns_hidden_child_global",
+        "libns_hidden_child_internal",
+        "libns_hidden_child_public",
+        "libnstest_dlopened",
+        "libnstest_ns_a_public1",
+        "libnstest_ns_a_public1_internal",
+        "libnstest_ns_b_public2",
+        "libnstest_ns_b_public3",
+        "libnstest_private",
+        "libnstest_private_external",
+        "libnstest_public",
+        "libnstest_public_internal",
+        "libnstest_root",
+        "libnstest_root_not_isolated",
         "librelocations-ANDROID_REL",
+        "librelocations-ANDROID_RELR",
         "librelocations-RELR",
         "librelocations-fat",
+        "libsegment_gap_inner",
+        "libsegment_gap_outer",
         "libsysv-hash-table-library",
-        "libtestshared",
         "libtest_atexit",
+        "libtest_check_order_dlsym",
         "libtest_check_order_dlsym_1_left",
         "libtest_check_order_dlsym_2_right",
         "libtest_check_order_dlsym_3_c",
         "libtest_check_order_dlsym_a",
         "libtest_check_order_dlsym_b",
         "libtest_check_order_dlsym_d",
-        "libtest_check_order_dlsym",
+        "libtest_check_order_reloc_root",
         "libtest_check_order_reloc_root_1",
         "libtest_check_order_reloc_root_2",
-        "libtest_check_order_reloc_root",
+        "libtest_check_order_reloc_siblings",
         "libtest_check_order_reloc_siblings_1",
         "libtest_check_order_reloc_siblings_2",
         "libtest_check_order_reloc_siblings_3",
         "libtest_check_order_reloc_siblings_a",
         "libtest_check_order_reloc_siblings_b",
+        "libtest_check_order_reloc_siblings_c",
         "libtest_check_order_reloc_siblings_c_1",
         "libtest_check_order_reloc_siblings_c_2",
-        "libtest_check_order_reloc_siblings_c",
         "libtest_check_order_reloc_siblings_d",
         "libtest_check_order_reloc_siblings_e",
         "libtest_check_order_reloc_siblings_f",
-        "libtest_check_order_reloc_siblings",
         "libtest_check_rtld_next_from_library",
         "libtest_dlopen_df_1_global",
-        "libtest_dlopen_from_ctor_main",
         "libtest_dlopen_from_ctor",
+        "libtest_dlopen_from_ctor_main",
         "libtest_dlopen_weak_undefined_func",
         "libtest_dlsym_df_1_global",
+        "libtest_dlsym_from_this",
         "libtest_dlsym_from_this_child",
         "libtest_dlsym_from_this_grandchild",
-        "libtest_dlsym_from_this",
         "libtest_dlsym_weak_func",
+        "libtest_dt_runpath_a",
+        "libtest_dt_runpath_b",
+        "libtest_dt_runpath_c",
         "libtest_dt_runpath_d",
+        "libtest_dt_runpath_x",
+        "libtest_dt_runpath_y",
         "libtest_elftls_dynamic",
         "libtest_elftls_dynamic_filler_1",
         "libtest_elftls_dynamic_filler_2",
@@ -913,83 +942,60 @@
         "libtest_elftls_shared_var_ie",
         "libtest_elftls_tprel",
         "libtest_empty",
-        "libtest_ifunc_variable_impl",
-        "libtest_ifunc_variable",
         "libtest_ifunc",
+        "libtest_ifunc_variable",
+        "libtest_ifunc_variable_impl",
+        "libtest_indirect_thread_local_dtor",
         "libtest_init_fini_order_child",
         "libtest_init_fini_order_grand_child",
-        "libtest_init_fini_order_root2",
         "libtest_init_fini_order_root",
-        "libtest_missing_symbol_child_public",
-        "libtest_missing_symbol_child_private",
-        "libtest_missing_symbol_root",
+        "libtest_init_fini_order_root2",
+        "libtest_invalid-empty_shdr_table",
+        "libtest_invalid-rw_load_segment",
+        "libtest_invalid-textrels",
+        "libtest_invalid-textrels2",
+        "libtest_invalid-unaligned_shdr_offset",
+        "libtest_invalid-zero_shdr_table_content",
+        "libtest_invalid-zero_shdr_table_offset",
+        "libtest_invalid-zero_shentsize",
+        "libtest_invalid-zero_shstrndx",
         "libtest_missing_symbol",
+        "libtest_missing_symbol_child_private",
+        "libtest_missing_symbol_child_public",
+        "libtest_missing_symbol_root",
         "libtest_nodelete_1",
         "libtest_nodelete_2",
         "libtest_nodelete_dt_flags_1",
         "libtest_pthread_atfork",
+        "libtest_relo_check_dt_needed_order",
         "libtest_relo_check_dt_needed_order_1",
         "libtest_relo_check_dt_needed_order_2",
-        "libtest_relo_check_dt_needed_order",
         "libtest_simple",
+        "libtest_thread_local_dtor",
+        "libtest_thread_local_dtor2",
         "libtest_two_parents_child",
         "libtest_two_parents_parent1",
         "libtest_two_parents_parent2",
         "libtest_versioned_lib",
         "libtest_versioned_libv1",
         "libtest_versioned_libv2",
-        "libtest_versioned_otherlib_empty",
         "libtest_versioned_otherlib",
+        "libtest_versioned_otherlib_empty",
         "libtest_versioned_uselibv1",
-        "libtest_versioned_uselibv2_other",
         "libtest_versioned_uselibv2",
+        "libtest_versioned_uselibv2_other",
         "libtest_versioned_uselibv3_other",
+        "libtest_with_dependency",
+        "libtest_with_dependency_loop",
         "libtest_with_dependency_loop_a",
         "libtest_with_dependency_loop_b",
         "libtest_with_dependency_loop_c",
-        "libtest_with_dependency_loop",
-        "libtest_with_dependency",
-        "libtest_indirect_thread_local_dtor",
-        "libtest_invalid-empty_shdr_table",
-        "libtest_invalid-rw_load_segment",
-        "libtest_invalid-unaligned_shdr_offset",
-        "libtest_invalid-zero_shdr_table_content",
-        "libtest_invalid-zero_shdr_table_offset",
-        "libtest_invalid-zero_shentsize",
-        "libtest_invalid-zero_shstrndx",
-        "libtest_invalid-textrels",
-        "libtest_invalid-textrels2",
-        "libtest_thread_local_dtor",
-        "libtest_thread_local_dtor2",
+        "libtestshared",
+        "ns_hidden_child_helper",
         "preinit_getauxval_test_helper",
         "preinit_syscall_test_helper",
-        "libnstest_private_external",
-        "libnstest_dlopened",
-        "libnstest_private",
-        "libnstest_root_not_isolated",
-        "libnstest_root",
-        "libnstest_public",
-        "libnstest_public_internal",
-        "libnstest_ns_a_public1",
-        "libnstest_ns_a_public1_internal",
-        "libnstest_ns_b_public2",
-        "libnstest_ns_b_public3",
-        "ns_hidden_child_helper",
-        "libns_hidden_child_global",
-        "libns_hidden_child_internal",
-        "libns_hidden_child_public",
-        "libns_hidden_child_app",
-        "libsegment_gap_inner",
-        "libsegment_gap_outer",
-        "ld_preload_test_helper",
-        "ld_preload_test_helper_lib1",
-        "ld_preload_test_helper_lib2",
-        "ld_config_test_helper",
-        "ld_config_test_helper_lib1",
-        "ld_config_test_helper_lib2",
-        "ld_config_test_helper_lib3",
-        "tls_properties_helper",
         "thread_exit_cb_helper",
+        "tls_properties_helper",
     ],
 }
 
diff --git a/tests/heap_tagging_level_test.cpp b/tests/heap_tagging_level_test.cpp
index 4f8f036..b3c8f22 100644
--- a/tests/heap_tagging_level_test.cpp
+++ b/tests/heap_tagging_level_test.cpp
@@ -15,10 +15,12 @@
  */
 
 #include <gtest/gtest.h>
+
+#include <malloc.h>
 #include <sys/prctl.h>
 
 #if defined(__BIONIC__)
-#include "platform/bionic/malloc.h"
+#include "gtest_globals.h"
 #include "platform/bionic/mte.h"
 #include "utils.h"
 
@@ -36,7 +38,7 @@
 }
 
 static bool SetHeapTaggingLevel(HeapTaggingLevel level) {
-  return android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &level, sizeof(level));
+  return mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, level);
 }
 #endif
 
@@ -90,7 +92,8 @@
 
   std::unique_ptr<int[]> p = std::make_unique<int[]>(4);
 
-  // First, check that memory tagging is enabled and the default tag checking level is async.
+  // First, check that memory tagging is enabled and the default tag checking level is sync.
+  // cc_test targets get sync MTE by default.
   // We assume that scudo is used on all MTE enabled hardware; scudo inserts a header with a
   // mismatching tag before each allocation.
   EXPECT_EXIT(
@@ -98,15 +101,15 @@
         ScopedSignalHandler ssh(SIGSEGV, ExitWithSiCode, SA_SIGINFO);
         p[-1] = 42;
       },
-      testing::ExitedWithCode(SEGV_MTEAERR), "");
+      testing::ExitedWithCode(SEGV_MTESERR), "");
 
-  EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_SYNC));
+  EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_ASYNC));
   EXPECT_EXIT(
       {
         ScopedSignalHandler ssh(SIGSEGV, ExitWithSiCode, SA_SIGINFO);
         p[-1] = 42;
       },
-      testing::ExitedWithCode(SEGV_MTESERR), "");
+      testing::ExitedWithCode(SEGV_MTEAERR), "");
 
   EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_NONE));
   volatile int oob ATTRIBUTE_UNUSED = p[-1];
@@ -177,3 +180,34 @@
   GTEST_SKIP() << "bionic/arm64 only";
 #endif
 }
+
+enum class MemtagNote { NONE, ASYNC, SYNC };
+class MemtagNoteTest : public testing::TestWithParam<std::tuple<MemtagNote, bool>> {};
+
+TEST_P(MemtagNoteTest, SEGV) {
+#if defined(__BIONIC__) && defined(__aarch64__)
+  if (!(getauxval(AT_HWCAP2) & HWCAP2_MTE)) {
+    GTEST_SKIP() << "requires MTE support";
+  }
+
+  const char* kNoteSuffix[] = {"disabled", "async", "sync"};
+  const char* kExpectedOutput[] = {"normal exit\n", "SEGV_MTEAERR\n", "SEGV_MTESERR\n"};
+
+  MemtagNote note = std::get<0>(GetParam());
+  bool isStatic = std::get<1>(GetParam());
+  std::string helper_base = std::string("heap_tagging_") + (isStatic ? "static_" : "") +
+                            kNoteSuffix[static_cast<int>(note)] + "_helper";
+  fprintf(stderr, "=== %s\n", helper_base.c_str());
+  std::string helper = GetTestlibRoot() + "/" + helper_base + "/" + helper_base;
+  chmod(helper.c_str(), 0755);
+  ExecTestHelper eth;
+  eth.SetArgs({helper.c_str(), nullptr});
+  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0,
+          kExpectedOutput[static_cast<int>(note)]);
+#endif
+}
+
+INSTANTIATE_TEST_SUITE_P(, MemtagNoteTest,
+                         testing::Combine(testing::Values(MemtagNote::NONE, MemtagNote::ASYNC,
+                                                          MemtagNote::SYNC),
+                                          testing::Bool()));
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 4b86faf..385d120 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -1579,3 +1579,85 @@
     defaults: ["bionic_testlib_defaults"],
     srcs: ["relocations.cpp"],
 }
+
+cc_defaults {
+  name: "bionic_targets_only",
+  enabled: false,
+  target: {
+     android: {
+       enabled: true,
+     },
+     linux_bionic: {
+       enabled: true,
+     },
+   },
+}
+
+cc_test {
+   name: "heap_tagging_sync_helper",
+   defaults: ["bionic_testlib_defaults", "bionic_targets_only"],
+   srcs: ["heap_tagging_helper.cpp"],
+   sanitize: {
+     memtag_heap: true,
+     diag: {
+       memtag_heap: true,
+     },
+   },
+}
+
+cc_test {
+   name: "heap_tagging_async_helper",
+   defaults: ["bionic_testlib_defaults", "bionic_targets_only"],
+   srcs: ["heap_tagging_helper.cpp"],
+   sanitize: {
+     memtag_heap: true,
+     diag: {
+       memtag_heap: false,
+     },
+   },
+}
+
+cc_test {
+   name: "heap_tagging_disabled_helper",
+   defaults: ["bionic_testlib_defaults", "bionic_targets_only"],
+   srcs: ["heap_tagging_helper.cpp"],
+   sanitize: {
+     memtag_heap: false,
+   },
+}
+
+cc_test {
+   name: "heap_tagging_static_sync_helper",
+   defaults: ["bionic_testlib_defaults", "bionic_targets_only"],
+   srcs: ["heap_tagging_helper.cpp"],
+   static_executable: true,
+   sanitize: {
+     memtag_heap: true,
+     diag: {
+       memtag_heap: true,
+     },
+   },
+}
+
+cc_test {
+   name: "heap_tagging_static_async_helper",
+   defaults: ["bionic_testlib_defaults", "bionic_targets_only"],
+   srcs: ["heap_tagging_helper.cpp"],
+   static_executable: true,
+   sanitize: {
+     memtag_heap: true,
+     diag: {
+       memtag_heap: false,
+     },
+   },
+}
+
+cc_test {
+   name: "heap_tagging_static_disabled_helper",
+   defaults: ["bionic_testlib_defaults", "bionic_targets_only"],
+   srcs: ["heap_tagging_helper.cpp"],
+   static_executable: true,
+   sanitize: {
+     memtag_heap: false,
+   },
+}
diff --git a/tests/libs/heap_tagging_helper.cpp b/tests/libs/heap_tagging_helper.cpp
new file mode 100644
index 0000000..1a970f2
--- /dev/null
+++ b/tests/libs/heap_tagging_helper.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <signal.h>
+#include <stdio.h>
+#include <sys/cdefs.h>
+#include <unistd.h>
+#include <memory>
+
+void action(int signo, siginfo_t* info __unused, void*) {
+#ifdef __ANDROID__
+  if (signo == 11 && info->si_code == SEGV_MTEAERR) {
+    fprintf(stderr, "SEGV_MTEAERR\n");
+    _exit(0);
+  }
+
+  if (signo == 11 && info->si_code == SEGV_MTESERR) {
+    fprintf(stderr, "SEGV_MTESERR\n");
+    _exit(0);
+  }
+#endif
+
+  fprintf(stderr, "signo %d\n", signo);
+  _exit(0);
+}
+
+__attribute__((optnone)) int main() {
+  struct sigaction sa = {};
+  sa.sa_sigaction = action;
+  sa.sa_flags = SA_SIGINFO;
+  sigaction(SIGSEGV, &sa, nullptr);
+
+  std::unique_ptr<int[]> p = std::make_unique<int[]>(4);
+  volatile int oob = p[-1];
+  (void)oob;
+
+  fprintf(stderr, "normal exit\n");
+  return 0;
+}
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index bddd9ab..b35bba9 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -1256,7 +1256,7 @@
 #endif
 }
 
-TEST(android_mallopt, disable_memory_mitigations) {
+TEST(malloc, disable_memory_mitigations) {
 #if defined(__BIONIC__)
   if (!mte_supported()) {
     GTEST_SKIP() << "This function can only be tested with MTE";
@@ -1275,7 +1275,7 @@
                    },
                    &sem));
 
-  ASSERT_TRUE(android_mallopt(M_DISABLE_MEMORY_MITIGATIONS, nullptr, 0));
+  ASSERT_EQ(1, mallopt(M_BIONIC_DISABLE_MEMORY_MITIGATIONS, 0));
   ASSERT_EQ(0, sem_post(&sem));
 
   int my_tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
diff --git a/tests/stack_unwinding_test.cpp b/tests/stack_unwinding_test.cpp
index 0ff6f30..7fb2247 100644
--- a/tests/stack_unwinding_test.cpp
+++ b/tests/stack_unwinding_test.cpp
@@ -82,7 +82,7 @@
 
 static UnwindData g_unwind_data;
 
-static void noinline UnwindSignalHandler(int) {
+__attribute__((unused)) static void noinline UnwindSignalHandler(int) {
   _Unwind_Backtrace(FrameCounter, &g_unwind_data.handler_frame_count);
 
   g_unwind_data.handler_one_deeper_frame_count = unwind_one_frame_deeper();
@@ -98,7 +98,7 @@
   EXPECT_EQ(unwind_data.handler_frame_count + 1, unwind_data.handler_one_deeper_frame_count);
 }
 
-static void noinline UnwindTest() {
+__attribute__((unused)) static void noinline UnwindTest() {
   g_unwind_data = {};
 
   _Unwind_Backtrace(FrameCounter, &g_unwind_data.expected_frame_count);
@@ -112,14 +112,24 @@
 }
 
 TEST(stack_unwinding, unwind_through_signal_frame) {
+#if defined(__aarch64__)
+  // A newer libunwind.a update should restore signal frame unwinding on arm64.
+  GTEST_SKIP() << "signal frame unwinding temporarily broken on arm64 -- b/153025717";
+#else
   ScopedSignalHandler ssh(SIGUSR1, UnwindSignalHandler);
 
   UnwindTest();
+#endif
 }
 
 // On LP32, the SA_SIGINFO flag gets you __restore_rt instead of __restore.
 TEST(stack_unwinding, unwind_through_signal_frame_SA_SIGINFO) {
+#if defined(__aarch64__)
+  // A newer libunwind.a update should restore signal frame unwinding on arm64.
+  GTEST_SKIP() << "signal frame unwinding temporarily broken on arm64 -- b/153025717";
+#else
   ScopedSignalHandler ssh(SIGUSR1, UnwindSignalHandler, SA_SIGINFO);
 
   UnwindTest();
+#endif
 }