llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-driver

@llvm/pr-subscribers-lld

Author: Elia Geretto (EliaGeretto)

<details>
<summary>Changes</summary>

This change eliminates the Android-specific --android-memtag-* flags from lld, 
replacing them with -z memtag-* generic equivalents. With these generic flags, 
the linker will emit only the dynamic array tags specified in the "Memtag ABI 
Extension to ELF", but no Android-specific memtag note.

In addition, this change adds an --android-memtag-note flag which should be 
used when the Android-specific memtag note should be emitted.

This change also modifies the clang driver to make use of the new flags.

---

Patch is 27.55 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/187055.diff


13 Files Affected:

- (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (+16-9) 
- (modified) clang/test/Driver/fsanitize-memtag.c (+1-1) 
- (renamed) clang/test/Driver/memtag-android.c (+24-13) 
- (added) clang/test/Driver/memtag.c (+54) 
- (modified) lld/ELF/Config.h (+8-7) 
- (modified) lld/ELF/Driver.cpp (+37-24) 
- (modified) lld/ELF/Options.td (+7-11) 
- (modified) lld/ELF/SyntheticSections.cpp (+12-9) 
- (added) lld/test/ELF/aarch64-memtag-abi.s (+58) 
- (modified) lld/test/ELF/aarch64-memtag-android-abi.s (+19-18) 
- (modified) lld/test/ELF/aarch64-memtag-globals.s (+4-4) 
- (modified) lld/test/ELF/aarch64-memtag-pauth-globals-out-of-range.s (+1-1) 
- (modified) lld/test/ELF/aarch64-memtag-pauth-globals.s (+1-1) 


``````````diff
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 9a17fa2546e68..865193be2e013 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1796,16 +1796,23 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, 
const ArgList &Args,
     CmdArgs.push_back("--export-dynamic-symbol=__cfi_check");
 
   if (SanArgs.hasMemTag()) {
-    if (!TC.getTriple().isAndroid()) {
-      TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
-          << "-fsanitize=memtag*" << TC.getTriple().str();
-    }
+    CmdArgs.push_back("-z");
     CmdArgs.push_back(
-        Args.MakeArgString("--android-memtag-mode=" + 
SanArgs.getMemtagMode()));
-    if (SanArgs.hasMemtagHeap())
-      CmdArgs.push_back("--android-memtag-heap");
-    if (SanArgs.hasMemtagStack())
-      CmdArgs.push_back("--android-memtag-stack");
+        Args.MakeArgString("memtag-mode=" + SanArgs.getMemtagMode()));
+
+    if (SanArgs.hasMemtagHeap()) {
+      CmdArgs.push_back("-z");
+      CmdArgs.push_back("memtag-heap");
+    }
+
+    if (SanArgs.hasMemtagStack()) {
+      CmdArgs.push_back("-z");
+      CmdArgs.push_back("memtag-stack");
+    }
+
+    if (TC.getTriple().isAndroid()) {
+      CmdArgs.push_back("--android-memtag-note");
+    }
   }
 
   return !StaticRuntimes.empty() || !NonWholeStaticRuntimes.empty() ||
diff --git a/clang/test/Driver/fsanitize-memtag.c 
b/clang/test/Driver/fsanitize-memtag.c
index c842e6de1b62d..cfe9a2b0c1ad9 100644
--- a/clang/test/Driver/fsanitize-memtag.c
+++ b/clang/test/Driver/fsanitize-memtag.c
@@ -12,7 +12,7 @@
 // CHECK-SANMT-MT: "-target-feature" "+mte"
 // CHECK-SANMT-MT-SAME: "-fsanitize=memtag-stack,memtag-heap,memtag-globals"
 
-// RUN: not %clang --target=aarch64-linux -fsanitize=memtag -Xclang 
-target-feature -Xclang +mte %s -### 2>&1 | FileCheck %s 
--check-prefix=CHECK-SANMT-MT
+// RUN: %clang --target=aarch64-linux -fsanitize=memtag -Xclang 
-target-feature -Xclang +mte %s -### 2>&1 | FileCheck %s 
--check-prefix=CHECK-SANMT-MT
 
 // RUN: not %clang --target=aarch64-linux -fsanitize=memtag %s -### 2>&1 | 
FileCheck %s --check-prefix=CHECK-SANMT-NOMT-0
 // CHECK-SANMT-NOMT-0: '-fsanitize=memtag-stack' requires hardware support 
(+memtag)
diff --git a/clang/test/Driver/memtag-ld.c b/clang/test/Driver/memtag-android.c
similarity index 53%
rename from clang/test/Driver/memtag-ld.c
rename to clang/test/Driver/memtag-android.c
index aef08ddc5758a..06aee761c066f 100644
--- a/clang/test/Driver/memtag-ld.c
+++ b/clang/test/Driver/memtag-android.c
@@ -1,28 +1,28 @@
 // RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \
 // RUN:   -fsanitize=memtag %s 2>&1 | FileCheck %s \
-// RUN:   --check-prefixes=CHECK-SYNC,CHECK-HEAP,CHECK-STACK
+// RUN:   
--check-prefixes=CHECK-CC1-ALL,CHECK-SYNC,CHECK-HEAP,CHECK-STACK,CHECK-NOTE
 
 // RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \
 // RUN:   -fsanitize=memtag-stack %s 2>&1 | FileCheck %s \
-// RUN:   --check-prefixes=CHECK-SYNC,CHECK-NO-HEAP,CHECK-STACK
+// RUN:   
--check-prefixes=CHECK-CC1-STACK,CHECK-SYNC,CHECK-NO-HEAP,CHECK-STACK,CHECK-NOTE
 
 // RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \
 // RUN:   -fsanitize=memtag-heap %s 2>&1 | FileCheck %s \
-// RUN:   --check-prefixes=CHECK-SYNC,CHECK-HEAP,CHECK-NO-STACK
+// RUN:   
--check-prefixes=CHECK-CC1-HEAP,CHECK-SYNC,CHECK-HEAP,CHECK-NO-STACK,CHECK-NOTE
 
 // RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \
 // RUN:   -fsanitize=memtag -fsanitize-memtag-mode=async %s 2>&1 | \
-// RUN:   FileCheck %s --check-prefixes=CHECK-ASYNC,CHECK-HEAP,CHECK-STACK
+// RUN:   FileCheck %s 
--check-prefixes=CHECK-CC1-ALL,CHECK-ASYNC,CHECK-HEAP,CHECK-STACK,CHECK-NOTE
 
 // RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \
 // RUN:   -fsanitize=memtag-stack -fsanitize-memtag-mode=async %s 2>&1 \
 // RUN:   | FileCheck %s \
-// RUN:   --check-prefixes=CHECK-ASYNC,CHECK-NO-HEAP,CHECK-STACK
+// RUN:   
--check-prefixes=CHECK-CC1-STACK,CHECK-ASYNC,CHECK-NO-HEAP,CHECK-STACK,CHECK-NOTE
 
 // RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \
 // RUN:   -fsanitize=memtag-heap -fsanitize-memtag-mode=async %s 2>&1 \
 // RUN:   | FileCheck %s \
-// RUN:   --check-prefixes=CHECK-ASYNC,CHECK-HEAP,CHECK-NO-STACK
+// RUN:   
--check-prefixes=CHECK-CC1-HEAP,CHECK-ASYNC,CHECK-HEAP,CHECK-NO-STACK,CHECK-NOTE
 
 // RUN: not %clang -### --target=aarch64-linux-android -march=armv8+memtag \
 // RUN:   -fsanitize=memtag-heap -fsanitize-memtag-mode=asymm %s 2>&1 \
@@ -33,14 +33,25 @@
 // RUN:   -fsanitize-memtag-mode=asymm -fno-sanitize=memtag %s 2>&1 \
 // RUN:   | FileCheck %s --check-prefixes=CHECK-NONE
 
-// CHECK-ASYNC:             ld{{.*}} "--android-memtag-mode=async"
-// CHECK-SYNC:              ld{{.*}} "--android-memtag-mode=sync"
-// CHECK-HEAP:              "--android-memtag-heap"
-// CHECK-NO-HEAP-NOT:       "--android-memtag-heap"
-// CHECK-STACK:             "--android-memtag-stack"
-// CHECK-NO-STACK-NOT:      "--android-memtag-stack"
+// CHECK-CC1-ALL:           
"-fsanitize=memtag-stack,memtag-heap,memtag-globals"
+// CHECK-CC1-STACK:         "-fsanitize=memtag-stack"
+// CHECK-CC1-HEAP:          "-fsanitize=memtag-heap"
+
+// CHECK-ASYNC:             ld{{.*}} "-z" "memtag-mode=async"
+// CHECK-SYNC:              ld{{.*}} "-z" "memtag-mode=sync"
+// CHECK-HEAP:              "-z" "memtag-heap"
+// CHECK-NO-HEAP-NOT:       "-z" "memtag-heap"
+// CHECK-STACK:             "-z" "memtag-stack"
+// CHECK-NO-STACK-NOT:      "-z" "memtag-stack"
+
+// CHECK-NOTE:              "--android-memtag-note"
+
 // CHECK-INVALID-MODE:      invalid value 'asymm' in '-fsanitize-memtag-mode=',
 // CHECK-INVALID-MODE-SAME: expected one of: {async, sync}
-// CHECK-NONE-NOT:          ld{{.*}} "--android-memtag
+
+// CHECK-NONE-NOT:          "-fsanitize=memtag-stack"
+// CHECK-NONE-NOT:          "-fsanitize=memtag-heap"
+// CHECK-NONE-NOT:          ld{{.*}} "-z" "memtag
+// CHECK-NONE-NOT:          ld{{.*}} "--android-memtag-note"
 
 void f() {}
diff --git a/clang/test/Driver/memtag.c b/clang/test/Driver/memtag.c
new file mode 100644
index 0000000000000..488acf68aa422
--- /dev/null
+++ b/clang/test/Driver/memtag.c
@@ -0,0 +1,54 @@
+// RUN: %clang -### --target=aarch64-linux-gnu -march=armv8+memtag \
+// RUN:   -fsanitize=memtag %s 2>&1 | FileCheck %s \
+// RUN:   --check-prefixes=CHECK-CC1-ALL,CHECK-SYNC,CHECK-HEAP,CHECK-STACK
+
+// RUN: %clang -### --target=aarch64-linux-gnu -march=armv8+memtag \
+// RUN:   -fsanitize=memtag-stack %s 2>&1 | FileCheck %s \
+// RUN:   --check-prefixes=CHECK-CC1-STACK,CHECK-SYNC,CHECK-NO-HEAP,CHECK-STACK
+
+// RUN: %clang -### --target=aarch64-linux-gnu -march=armv8+memtag \
+// RUN:   -fsanitize=memtag-heap %s 2>&1 | FileCheck %s \
+// RUN:   --check-prefixes=CHECK-CC1-HEAP,CHECK-SYNC,CHECK-HEAP,CHECK-NO-STACK
+
+// RUN: %clang -### --target=aarch64-linux-gnu -march=armv8+memtag \
+// RUN:   -fsanitize=memtag -fsanitize-memtag-mode=async %s 2>&1 | \
+// RUN:   FileCheck %s 
--check-prefixes=CHECK-CC1-ALL,CHECK-ASYNC,CHECK-HEAP,CHECK-STACK
+
+// RUN: %clang -### --target=aarch64-linux-gnu -march=armv8+memtag \
+// RUN:   -fsanitize=memtag-stack -fsanitize-memtag-mode=async %s 2>&1 \
+// RUN:   | FileCheck %s \
+// RUN:   
--check-prefixes=CHECK-CC1-STACK,CHECK-ASYNC,CHECK-NO-HEAP,CHECK-STACK
+
+// RUN: %clang -### --target=aarch64-linux-gnu -march=armv8+memtag \
+// RUN:   -fsanitize=memtag-heap -fsanitize-memtag-mode=async %s 2>&1 \
+// RUN:   | FileCheck %s \
+// RUN:   --check-prefixes=CHECK-CC1-HEAP,CHECK-ASYNC,CHECK-HEAP,CHECK-NO-STACK
+
+// RUN: not %clang -### --target=aarch64-linux-gnu -march=armv8+memtag \
+// RUN:   -fsanitize=memtag-heap -fsanitize-memtag-mode=asymm %s 2>&1 \
+// RUN:   | FileCheck %s --check-prefixes=CHECK-INVALID-MODE
+
+// RUN: not %clang -### --target=aarch64-linux-gnu -march=armv8+memtag \
+// RUN:   -fsanitize=memtag-stack -fsanitize=memtag-heap \
+// RUN:   -fsanitize-memtag-mode=asymm -fno-sanitize=memtag %s 2>&1 \
+// RUN:   | FileCheck %s --check-prefixes=CHECK-NONE
+
+// CHECK-CC1-ALL:           
"-fsanitize=memtag-stack,memtag-heap,memtag-globals"
+// CHECK-CC1-STACK:         "-fsanitize=memtag-stack"
+// CHECK-CC1-HEAP:          "-fsanitize=memtag-heap"
+
+// CHECK-ASYNC:             ld{{.*}} "-z" "memtag-mode=async"
+// CHECK-SYNC:              ld{{.*}} "-z" "memtag-mode=sync"
+// CHECK-HEAP:              "-z" "memtag-heap"
+// CHECK-NO-HEAP-NOT:       "-z" "memtag-heap"
+// CHECK-STACK:             "-z" "memtag-stack"
+// CHECK-NO-STACK-NOT:      "-z" "memtag-stack"
+
+// CHECK-INVALID-MODE:      invalid value 'asymm' in '-fsanitize-memtag-mode=',
+// CHECK-INVALID-MODE-SAME: expected one of: {async, sync}
+
+// CHECK-NONE-NOT:          "-fsanitize=memtag-stack"
+// CHECK-NONE-NOT:          "-fsanitize=memtag-heap"
+// CHECK-NONE-NOT:          ld{{.*}} "-z" "memtag
+
+void f() {}
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index a9f74460f6f99..75b29be08c2b6 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -508,17 +508,18 @@ struct Config {
   // 4 for ELF32, 8 for ELF64.
   int wordsize;
 
-  // Mode of MTE to write to the ELF note. Should be one of NT_MEMTAG_ASYNC 
(for
-  // async), NT_MEMTAG_SYNC (for sync), or NT_MEMTAG_LEVEL_NONE (for none). If
-  // async or sync is enabled, write the ELF note specifying the default MTE
-  // mode.
-  int androidMemtagMode;
+  // Mode of MTE to write to the dynamic array. Should be one of 
NT_MEMTAG_ASYNC
+  // (for async), NT_MEMTAG_SYNC (for sync), or NT_MEMTAG_LEVEL_NONE (for 
none).
+  // If async or sync is enabled, write the tag specifying the default MTE 
mode.
+  int memtagMode;
   // Signal to the dynamic loader to enable heap MTE.
-  bool androidMemtagHeap;
+  bool memtagHeap;
   // Signal to the dynamic loader that this binary expects stack MTE. 
Generally,
   // this means to map the primary and thread stacks as PROT_MTE. Note: This is
   // not supported on Android 11 & 12.
-  bool androidMemtagStack;
+  bool memtagStack;
+  // Whether to emit the Android-specific legacy memtag note.
+  bool memtagAndroidNote;
 
   // When using a unified pre-link LTO pipeline, specify the backend LTO mode.
   LtoKind ltoKind = LtoKind::Default;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index fac8fa2db04d6..bd745195714d3 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -630,6 +630,27 @@ static ZicfissPolicy getZZicfiss(Ctx &ctx, 
opt::InputArgList &args) {
   return ret;
 }
 
+static int getZMemtagMode(Ctx &ctx, opt::InputArgList &args) {
+  auto ret = ELF::NT_MEMTAG_LEVEL_NONE;
+
+  for (auto *arg : args.filtered(OPT_z)) {
+    std::pair<StringRef, StringRef> kv = StringRef(arg->getValue()).split('=');
+    if (kv.first == "memtag-mode") {
+      arg->claim();
+      if (kv.second == "none")
+        ret = ELF::NT_MEMTAG_LEVEL_NONE;
+      else if (kv.second == "sync")
+        ret = ELF::NT_MEMTAG_LEVEL_SYNC;
+      else if (kv.second == "async")
+        ret = ELF::NT_MEMTAG_LEVEL_ASYNC;
+      else
+        ErrAlways(ctx) << "unknown -z memtag-mode= value: " << kv.second;
+    }
+  }
+
+  return ret;
+}
+
 // Report a warning for an unknown -z option.
 static void checkZOptions(Ctx &ctx, opt::InputArgList &args) {
   // This function is called before getTarget(), when certain options are not
@@ -846,27 +867,20 @@ static StringRef getDynamicLinker(Ctx &ctx, 
opt::InputArgList &args) {
 }
 
 static int getMemtagMode(Ctx &ctx, opt::InputArgList &args) {
-  StringRef memtagModeArg = args.getLastArgValue(OPT_android_memtag_mode);
-  if (memtagModeArg.empty()) {
-    if (ctx.arg.androidMemtagStack)
-      Warn(ctx) << "--android-memtag-mode is unspecified, leaving "
-                   "--android-memtag-stack a no-op";
-    else if (ctx.arg.androidMemtagHeap)
-      Warn(ctx) << "--android-memtag-mode is unspecified, leaving "
-                   "--android-memtag-heap a no-op";
-    return ELF::NT_MEMTAG_LEVEL_NONE;
+  auto memtagMode = getZMemtagMode(ctx, args);
+  if (memtagMode == ELF::NT_MEMTAG_LEVEL_NONE) {
+    if (ctx.arg.memtagStack)
+      Warn(ctx) << "-z memtag-mode is none, leaving "
+                   "-z memtag-stack a no-op";
+    if (ctx.arg.memtagHeap)
+      Warn(ctx) << "-z memtag-mode is none, leaving "
+                   "-z memtag-heap a no-op";
+    if (ctx.arg.memtagAndroidNote)
+      Warn(ctx) << "-z memtag-mode is none, leaving "
+                   "--android-memtag-note a no-op";
   }
 
-  if (memtagModeArg == "sync")
-    return ELF::NT_MEMTAG_LEVEL_SYNC;
-  if (memtagModeArg == "async")
-    return ELF::NT_MEMTAG_LEVEL_ASYNC;
-  if (memtagModeArg == "none")
-    return ELF::NT_MEMTAG_LEVEL_NONE;
-
-  ErrAlways(ctx) << "unknown --android-memtag-mode value: \"" << memtagModeArg
-                 << "\", should be one of {async, sync, none}";
-  return ELF::NT_MEMTAG_LEVEL_NONE;
+  return memtagMode;
 }
 
 static ICFLevel getICF(opt::InputArgList &args) {
@@ -1358,13 +1372,12 @@ static void readConfigs(Ctx &ctx, opt::InputArgList 
&args) {
       hasZOption(args, "muldefs") ||
       args.hasFlag(OPT_allow_multiple_definition,
                    OPT_no_allow_multiple_definition, false);
-  ctx.arg.androidMemtagHeap =
-      args.hasFlag(OPT_android_memtag_heap, OPT_no_android_memtag_heap, false);
-  ctx.arg.androidMemtagStack = args.hasFlag(OPT_android_memtag_stack,
-                                            OPT_no_android_memtag_stack, 
false);
+  ctx.arg.memtagHeap = hasZOption(args, "memtag-heap");
+  ctx.arg.memtagStack = hasZOption(args, "memtag-stack");
+  ctx.arg.memtagAndroidNote = args.hasArg(OPT_android_memtag_note);
   ctx.arg.fatLTOObjects =
       args.hasFlag(OPT_fat_lto_objects, OPT_no_fat_lto_objects, false);
-  ctx.arg.androidMemtagMode = getMemtagMode(ctx, args);
+  ctx.arg.memtagMode = getMemtagMode(ctx, args);
   ctx.arg.auxiliaryList = args::getStrings(args, OPT_auxiliary);
   ctx.arg.armBe8 = args.hasArg(OPT_be8);
   if (opt::Arg *arg = args.getLastArg(
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index c2111e58c12b9..d262f34c9d1dd 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -844,14 +844,10 @@ defm check_dynamic_relocations: 
BB<"check-dynamic-relocations",
 
 defm load_pass_plugins: EEq<"load-pass-plugin", "Load passes from plugin 
library">;
 
-// Hidden options, used by clang's -fsanitize=memtag-* options to emit an ELF
-// note to designate what kinds of memory (stack/heap) should be protected 
using
-// ARM's MTE on armv8.5+. A binary's desire for stack MTE can't be obtained
-// implicitly, so we have a specific bit in the note to signal to the loader to
-// remap the stack as PROT_MTE.
-defm android_memtag_stack: BB<"android-memtag-stack",
-    "Instruct the dynamic loader to prepare for MTE stack instrumentation", 
"">;
-defm android_memtag_heap: BB<"android-memtag-heap",
-    "Instruct the dynamic loader to enable MTE protection for the heap", "">;
-defm android_memtag_mode: EEq<"android-memtag-mode",
-    "Instruct the dynamic loader to start under MTE mode {async, sync, none}">;
+// Hidden option, used by clang's -fsanitize=memtag-* option to emit an ELF 
note
+// to designate what kinds of memory (stack/heap) should be protected using
+// ARM's MTE on armv8.5+. This note is Android-specific and it is used only in
+// older SDK versions.
+defm android_memtag_note
+    : BB<"android-memtag-note", "Emit the Android-specific legacy memtag note",
+         "">;
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index b696ff11d2232..fdd66fcd9611d 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1334,9 +1334,10 @@ DynamicSection<ELFT>::computeContents() {
       addInt(DT_AARCH64_PAC_PLT, 0);
 
     if (hasMemtag(ctx)) {
-      addInt(DT_AARCH64_MEMTAG_MODE, ctx.arg.androidMemtagMode == 
NT_MEMTAG_LEVEL_ASYNC);
-      addInt(DT_AARCH64_MEMTAG_HEAP, ctx.arg.androidMemtagHeap);
-      addInt(DT_AARCH64_MEMTAG_STACK, ctx.arg.androidMemtagStack);
+      addInt(DT_AARCH64_MEMTAG_MODE,
+             ctx.arg.memtagMode == NT_MEMTAG_LEVEL_ASYNC);
+      addInt(DT_AARCH64_MEMTAG_HEAP, ctx.arg.memtagHeap);
+      addInt(DT_AARCH64_MEMTAG_STACK, ctx.arg.memtagStack);
       if (ctx.mainPart->memtagGlobalDescriptors->isNeeded()) {
         addInSec(DT_AARCH64_MEMTAG_GLOBALS,
                  *ctx.mainPart->memtagGlobalDescriptors);
@@ -4297,7 +4298,7 @@ static bool needsInterpSection(Ctx &ctx) {
 
 bool elf::hasMemtag(Ctx &ctx) {
   return ctx.arg.emachine == EM_AARCH64 &&
-         ctx.arg.androidMemtagMode != ELF::NT_MEMTAG_LEVEL_NONE;
+         ctx.arg.memtagMode != ELF::NT_MEMTAG_LEVEL_NONE;
 }
 
 // Fully static executables don't support MTE globals at this point in time, as
@@ -4325,12 +4326,12 @@ void MemtagAndroidNote::writeTo(uint8_t *buf) {
   buf += 12 + alignTo(sizeof(kMemtagAndroidNoteName), 4);
 
   uint32_t value = 0;
-  value |= ctx.arg.androidMemtagMode;
-  if (ctx.arg.androidMemtagHeap)
+  value |= ctx.arg.memtagMode;
+  if (ctx.arg.memtagHeap)
     value |= ELF::NT_MEMTAG_HEAP;
   // Note, MTE stack is an ABI break. Attempting to run an MTE stack-enabled
   // binary on Android 11 or 12 will result in a checkfail in the loader.
-  if (ctx.arg.androidMemtagStack)
+  if (ctx.arg.memtagStack)
     value |= ELF::NT_MEMTAG_STACK;
   write32(ctx, buf, value); // note value
 }
@@ -4525,8 +4526,10 @@ template <class ELFT> void 
elf::createSyntheticSections(Ctx &ctx) {
     part.dynamic = std::make_unique<DynamicSection<ELFT>>(ctx);
 
     if (hasMemtag(ctx)) {
-      part.memtagAndroidNote = std::make_unique<MemtagAndroidNote>(ctx);
-      add(*part.memtagAndroidNote);
+      if (ctx.arg.memtagAndroidNote) {
+        part.memtagAndroidNote = std::make_unique<MemtagAndroidNote>(ctx);
+        add(*part.memtagAndroidNote);
+      }
       if (canHaveMemtagGlobals(ctx)) {
         part.memtagGlobalDescriptors =
             std::make_unique<MemtagGlobalDescriptors>(ctx);
diff --git a/lld/test/ELF/aarch64-memtag-abi.s 
b/lld/test/ELF/aarch64-memtag-abi.s
new file mode 100644
index 0000000000000..86e53edc1fbaf
--- /dev/null
+++ b/lld/test/ELF/aarch64-memtag-abi.s
@@ -0,0 +1,58 @@
+# REQUIRES: aarch64
+
+# RUN: llvm-mc --filetype=obj -triple=aarch64-linux-gnu %s -o %t.o
+
+# RUN: ld.lld -shared -z memtag-mode=async -z memtag-heap %t.o -o %t
+# RUN: llvm-readelf --memtag %t | FileCheck %s 
--check-prefixes=CHECK,HEAP,NOSTACK,ASYNC
+
+# RUN: ld.lld -shared -z memtag-mode=sync -z memtag-heap %t.o -o %t
+# RUN: llvm-readelf --memtag %t | FileCheck %s 
--check-prefixes=CHECK,HEAP,NOSTACK,SYNC
+
+# RUN: ld.lld -shared -z memtag-mode=async -z memtag-stack %t.o -o %t
+# RUN: llvm-readelf --memtag %t | FileCheck %s 
--check-prefixes=CHECK,NOHEAP,STACK,ASYNC
+
+# RUN: ld.lld -shared -z memtag-mode=sync -z memtag-stack %t.o -o %t
+# RUN: llvm-readelf --memtag %t | FileCheck %s 
--check-prefixes=CHECK,NOHEAP,STACK,SYNC
+
+# RUN: ld.lld -shared -z memtag-mode=async -z memtag-heap \
+# RUN:    -z memtag-stack %t.o -o %t
+# RUN: llvm-readelf --memtag %t | FileCheck %s 
--check-prefixes=CHECK,HEAP,STACK,ASYNC
+
+# RUN: ld.lld -shared -z memtag-mode=sync -z memtag-heap \
+# RUN:    -z memtag-stack %t.o -o %t
+# RUN: llvm-readelf --memtag %t | FileCheck %s 
--check-prefixes=CHECK,HEAP,STACK,SYNC
+
+# RUN: ld.lld -shared -z memtag-heap %t.o -o %t 2>&1 | \
+# RUN:    FileCheck %s --check-prefixes=MISSING-MODE
+# RUN: ld.lld -shared -z memtag-stack %t.o -o %t 2>&1 | \
+# RUN:    FileCheck %s --check-prefixes=MISSING-MODE
+# RUN: ld.lld -shared -z memtag-heap -z memtag-stack %t.o -o %t 2>&1 | \
+# RUN:    FileCheck %s --check-prefixes=MISSING-MODE
+# MISSING-MODE: warning: -z memtag-mode is none, leaving
+# MISSING-MODE-SAME: -z memtag-{{(heap|stack)}} a no-op
+
+# CHECK: Memtag Dynamic Entries
+# SYNC:    AARCH64_MEMTAG_MODE: Synchronous (0)
+# ASYNC:   AARCH64_MEMTAG_MODE: Asynchronous (1)
+# HEAP:    AARCH64_MEMTAG_HEAP: Enabled (1)
+# NOHEAP:  AARCH64_MEMTAG_HEAP: Disabled (0)
+# STACK:   AARCH64_MEMTAG_STACK: Enabled (1)
+# NOSTACK: AARCH64_MEMTAG_STACK: Disabled (0)
+
+# CHECK-NOT: Memtag Android Note
+
+# RUN: not ld.lld -shared -z memtag-mode=asymm -z memtag-heap 2>&1 | \
+# RUN:    FileCheck %s --check-prefix=BAD-MODE
+# BAD-MODE: error: unknown -z memtag-mode= value: asymm
+
+# RUN: ld.lld -static -z memtag-mode=sync -z memtag-heap \
+# RUN:    -z memtag-stack %t.o -o %t
+# RUN: llvm-rea...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/187055
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to