https://github.com/EliaGeretto created https://github.com/llvm/llvm-project/pull/183275
This PR introduces new generic `--memtag-*` flags in `lld`. These flags ensure the linker behaves as described in the Memtag ABI Extension to ELF [1], but does not insert Android-specific information. In addition, memtag globals are allowed in all AArch64 targets, instead of just in Android, again following the Memtag ABI Extension. In all cases, the Android-specific behavior is unmodified. [1]: https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst >From 14cbba025e30f831a75c3f620191c0da0b2dcf5c Mon Sep 17 00:00:00 2001 From: Elia Geretto <[email protected]> Date: Fri, 20 Feb 2026 12:19:38 +0100 Subject: [PATCH 1/3] [ELF][MTE] Add generic --memtag-* options This commits duplicates the Android-specific --android-memtag-* flags, adding a generic --memtag-* variant. The only difference is that, when the generic options are used, the linker will emit only the dynamic array tags specified in the "Memtag ABI Extension to ELF", but no Android-specific memtag note. --- lld/ELF/Config.h | 15 ++++---- lld/ELF/Driver.cpp | 55 +++++++++++++++++++++------- lld/ELF/Options.td | 33 +++++++++++++---- lld/ELF/SyntheticSections.cpp | 21 ++++++----- lld/test/ELF/aarch64-memtag-abi.s | 59 +++++++++++++++++++++++++++++++ 5 files changed, 149 insertions(+), 34 deletions(-) create mode 100644 lld/test/ELF/aarch64-memtag-abi.s diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 237df52194210..b15e38c3daee1 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -511,17 +511,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 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 d7bfa7357d4ed..ae8ca1d6d9dd5 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -846,14 +846,35 @@ static StringRef getDynamicLinker(Ctx &ctx, opt::InputArgList &args) { } static int getMemtagMode(Ctx &ctx, opt::InputArgList &args) { - StringRef memtagModeArg = args.getLastArgValue(OPT_android_memtag_mode); + StringRef memtagModeArg = args.getLastArgValue(OPT_memtag_mode); + if (memtagModeArg.empty()) + 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"; + if (ctx.arg.memtagStack || ctx.arg.memtagHeap) { + bool haveAndroidStack = args.hasArg(OPT_android_memtag_stack); + bool haveAndroidHeap = args.hasArg(OPT_android_memtag_heap); + bool haveGenericStack = args.hasArg(OPT_memtag_stack); + bool haveGenericHeap = args.hasArg(OPT_memtag_heap); + + StringRef modeFlag = "--memtag-mode"; + if ((haveAndroidStack || haveAndroidHeap) && + !(haveGenericStack || haveGenericHeap)) + modeFlag = "--android-memtag-mode"; + + StringRef missingFlag = "--memtag-stack"; + if (ctx.arg.memtagStack) { + if (haveAndroidStack && !haveGenericStack) + missingFlag = "--android-memtag-stack"; + } else { + missingFlag = "--memtag-heap"; + if (haveAndroidHeap && !haveGenericHeap) + missingFlag = "--android-memtag-heap"; + } + + Warn(ctx) << modeFlag << " is unspecified, leaving " << missingFlag + << " a no-op"; + } return ELF::NT_MEMTAG_LEVEL_NONE; } @@ -864,7 +885,11 @@ static int getMemtagMode(Ctx &ctx, opt::InputArgList &args) { if (memtagModeArg == "none") return ELF::NT_MEMTAG_LEVEL_NONE; - ErrAlways(ctx) << "unknown --android-memtag-mode value: \"" << memtagModeArg + StringRef modeFlag = "--memtag-mode"; + if (args.hasArg(OPT_android_memtag_mode) && !args.hasArg(OPT_memtag_mode)) + modeFlag = "--android-memtag-mode"; + + ErrAlways(ctx) << "unknown " << modeFlag << " value: \"" << memtagModeArg << "\", should be one of {async, sync, none}"; return ELF::NT_MEMTAG_LEVEL_NONE; } @@ -1358,13 +1383,19 @@ 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 = + ctx.arg.memtagHeap = + args.hasFlag(OPT_memtag_heap, OPT_no_memtag_heap, false) || 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.memtagStack = + args.hasFlag(OPT_memtag_stack, OPT_no_memtag_stack, false) || + args.hasFlag(OPT_android_memtag_stack, OPT_no_android_memtag_stack, + false); + ctx.arg.memtagMode = getMemtagMode(ctx, args); + ctx.arg.memtagAndroidNote = args.hasArg(OPT_android_memtag_mode) || + args.hasArg(OPT_android_memtag_heap) || + args.hasArg(OPT_android_memtag_stack); ctx.arg.fatLTOObjects = args.hasFlag(OPT_fat_lto_objects, OPT_no_fat_lto_objects, false); - ctx.arg.androidMemtagMode = 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..52440951503b5 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -849,9 +849,30 @@ defm load_pass_plugins: EEq<"load-pass-plugin", "Load passes from plugin library // 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}">; +defm memtag_stack + : BB<"memtag-stack", + "Instruct the dynamic loader to prepare for MTE stack instrumentation", + "">; +defm memtag_heap + : BB<"memtag-heap", + "Instruct the dynamic loader to enable MTE protection for the heap", + "">; +defm memtag_mode : EEq<"memtag-mode", "Instruct the dynamic loader to start " + "under MTE mode {async, sync, none}">; + +// Android-specific flags that result in the emission of the Android-specific +// memtag note. +defm android_memtag_stack + : BB<"android-memtag-stack", + "Instruct the dynamic loader to prepare for MTE stack instrumentation " + "(emit Android-specific note)", + "">; +defm android_memtag_heap + : BB<"android-memtag-heap", + "Instruct the dynamic loader to enable MTE protection for the heap " + "(emit Android-specific note)", + "">; +defm android_memtag_mode + : EEq<"android-memtag-mode", + "Instruct the dynamic loader to start under MTE mode {async, sync, " + "none} (emit Android-specific note)">; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 2cfc88d8389b0..5ec226f1621f3 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1504,9 +1504,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); @@ -4500,7 +4501,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 @@ -4528,12 +4529,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 } @@ -4740,8 +4741,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..a7a1bea5b0354 --- /dev/null +++ b/lld/test/ELF/aarch64-memtag-abi.s @@ -0,0 +1,59 @@ +# REQUIRES: aarch64 + +# RUN: llvm-mc --filetype=obj -triple=aarch64-linux-gnu %s -o %t.o + +# RUN: ld.lld -shared --memtag-mode=async --memtag-heap %t.o -o %t +# RUN: llvm-readelf --memtag %t | FileCheck %s --check-prefixes=CHECK,HEAP,NOSTACK,ASYNC + +# RUN: ld.lld -shared --memtag-mode=sync --memtag-heap %t.o -o %t +# RUN: llvm-readelf --memtag %t | FileCheck %s --check-prefixes=CHECK,HEAP,NOSTACK,SYNC + +# RUN: ld.lld -shared --memtag-mode=async --memtag-stack %t.o -o %t +# RUN: llvm-readelf --memtag %t | FileCheck %s --check-prefixes=CHECK,NOHEAP,STACK,ASYNC + +# RUN: ld.lld -shared --memtag-mode=sync --memtag-stack %t.o -o %t +# RUN: llvm-readelf --memtag %t | FileCheck %s --check-prefixes=CHECK,NOHEAP,STACK,SYNC + +# RUN: ld.lld -shared --memtag-mode=async --memtag-heap \ +# RUN: --memtag-stack %t.o -o %t +# RUN: llvm-readelf --memtag %t | FileCheck %s --check-prefixes=CHECK,HEAP,STACK,ASYNC + +# RUN: ld.lld -shared --memtag-mode=sync --memtag-heap \ +# RUN: --memtag-stack %t.o -o %t +# RUN: llvm-readelf --memtag %t | FileCheck %s --check-prefixes=CHECK,HEAP,STACK,SYNC + +# RUN: ld.lld -shared --memtag-heap %t.o -o %t 2>&1 | \ +# RUN: FileCheck %s --check-prefixes=MISSING-MODE +# RUN: ld.lld -shared --memtag-stack %t.o -o %t 2>&1 | \ +# RUN: FileCheck %s --check-prefixes=MISSING-MODE +# RUN: ld.lld -shared --memtag-heap --memtag-stack %t.o -o %t 2>&1 | \ +# RUN: FileCheck %s --check-prefixes=MISSING-MODE +# MISSING-MODE: warning: --memtag-mode is unspecified, leaving +# MISSING-MODE: --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 --memtag-mode=asymm --memtag-heap 2>&1 | \ +# RUN: FileCheck %s --check-prefix=BAD-MODE +# BAD-MODE: error: unknown --memtag-mode value: "asymm", should be one of +# BAD-MODE: {async, sync, none} + +# RUN: ld.lld -static --memtag-mode=sync --memtag-heap \ +# RUN: --memtag-stack %t.o -o %t +# RUN: llvm-readelf --memtag %t | FileCheck %s --check-prefixes=STATIC + +# STATIC: Memtag Dynamic Entries: +# STATIC-NEXT: < none found > +# STATIC-NOT: Memtag Android Note + +.globl _start +_start: + ret >From 53c10b2d004bae1ebc8447f8671bde373d966c80 Mon Sep 17 00:00:00 2001 From: Elia Geretto <[email protected]> Date: Fri, 20 Feb 2026 14:20:18 +0100 Subject: [PATCH 2/3] [Driver][MTE] Use generic lld memtag flags This commit adds support for generic --memtag-* lld flags which allow to produce memtag-enabled ELFs for all supported OS-es. Android targets will still use the Android-specific --android-memtag-* lld flags. --- clang/lib/Driver/ToolChains/CommonArgs.cpp | 23 ++++++----- clang/test/Driver/fsanitize-memtag.c | 2 +- clang/test/Driver/memtag-android-ld.c | 46 ++++++++++++++++++++++ clang/test/Driver/memtag-ld.c | 30 +++++++------- 4 files changed, 76 insertions(+), 25 deletions(-) create mode 100644 clang/test/Driver/memtag-android-ld.c diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 9a17fa2546e68..7061b906b8aa4 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1796,16 +1796,21 @@ 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(); + if (TC.getTriple().isAndroid()) { + 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"); + } else { + CmdArgs.push_back( + Args.MakeArgString("--memtag-mode=" + SanArgs.getMemtagMode())); + if (SanArgs.hasMemtagHeap()) + CmdArgs.push_back("--memtag-heap"); + if (SanArgs.hasMemtagStack()) + CmdArgs.push_back("--memtag-stack"); } - 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"); } 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-android-ld.c b/clang/test/Driver/memtag-android-ld.c new file mode 100644 index 0000000000000..aef08ddc5758a --- /dev/null +++ b/clang/test/Driver/memtag-android-ld.c @@ -0,0 +1,46 @@ +// 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: %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: %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: %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: %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: %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: not %clang -### --target=aarch64-linux-android -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-android -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-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-INVALID-MODE: invalid value 'asymm' in '-fsanitize-memtag-mode=', +// CHECK-INVALID-MODE-SAME: expected one of: {async, sync} +// CHECK-NONE-NOT: ld{{.*}} "--android-memtag + +void f() {} diff --git a/clang/test/Driver/memtag-ld.c b/clang/test/Driver/memtag-ld.c index aef08ddc5758a..7c59cc24845a3 100644 --- a/clang/test/Driver/memtag-ld.c +++ b/clang/test/Driver/memtag-ld.c @@ -1,46 +1,46 @@ -// RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \ +// RUN: %clang -### --target=aarch64-linux-gnu -march=armv8+memtag \ // RUN: -fsanitize=memtag %s 2>&1 | FileCheck %s \ // RUN: --check-prefixes=CHECK-SYNC,CHECK-HEAP,CHECK-STACK -// RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \ +// RUN: %clang -### --target=aarch64-linux-gnu -march=armv8+memtag \ // RUN: -fsanitize=memtag-stack %s 2>&1 | FileCheck %s \ // RUN: --check-prefixes=CHECK-SYNC,CHECK-NO-HEAP,CHECK-STACK -// RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \ +// RUN: %clang -### --target=aarch64-linux-gnu -march=armv8+memtag \ // RUN: -fsanitize=memtag-heap %s 2>&1 | FileCheck %s \ // RUN: --check-prefixes=CHECK-SYNC,CHECK-HEAP,CHECK-NO-STACK -// RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \ +// 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-ASYNC,CHECK-HEAP,CHECK-STACK -// RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \ +// 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-ASYNC,CHECK-NO-HEAP,CHECK-STACK -// RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \ +// 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-ASYNC,CHECK-HEAP,CHECK-NO-STACK -// RUN: not %clang -### --target=aarch64-linux-android -march=armv8+memtag \ +// 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-android -march=armv8+memtag \ +// 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-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-ASYNC: ld{{.*}} "--memtag-mode=async" +// CHECK-SYNC: ld{{.*}} "--memtag-mode=sync" +// CHECK-HEAP: "--memtag-heap" +// CHECK-NO-HEAP-NOT: "--memtag-heap" +// CHECK-STACK: "--memtag-stack" +// CHECK-NO-STACK-NOT: "--memtag-stack" // 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: ld{{.*}} "--memtag void f() {} >From cbc4d5af33364255cfddaaffcf2eed7fd456f0dc Mon Sep 17 00:00:00 2001 From: Elia Geretto <[email protected]> Date: Fri, 20 Feb 2026 14:36:19 +0100 Subject: [PATCH 3/3] [AsmPrinter][MTE] Support memtag-globals for all AArch64 targets --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 4 ++-- llvm/test/MC/AArch64/global-tagging.ll | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 083b83567e47f..0eca99cfed563 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -833,10 +833,10 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { if (GV->isTagged()) { Triple T = TM.getTargetTriple(); - if (T.getArch() != Triple::aarch64 || !T.isAndroid()) + if (T.getArch() != Triple::aarch64) OutContext.reportError(SMLoc(), "tagged symbols (-fsanitize=memtag-globals) are " - "only supported on AArch64 Android"); + "only supported on AArch64"); OutStreamer->emitSymbolAttribute(EmittedSym, MCSA_Memtag); } diff --git a/llvm/test/MC/AArch64/global-tagging.ll b/llvm/test/MC/AArch64/global-tagging.ll index c8b3f52401dc1..29463b1b86ff4 100644 --- a/llvm/test/MC/AArch64/global-tagging.ll +++ b/llvm/test/MC/AArch64/global-tagging.ll @@ -1,8 +1,12 @@ -;; Tagged symbols are only available on aarch64-linux-android. -; RUN: not llc -filetype=null %s -mtriple=aarch64-unknown-linux 2>&1 | FileCheck %s --check-prefix=ERR +;; Tagged symbols are only available on AArch64. ; RUN: %if x86-registered-target %{ not llc -filetype=null %s -mtriple=x86_64-unknown-linux 2>&1 | FileCheck %s --check-prefix=ERR %} -; ERR: error: tagged symbols (-fsanitize=memtag-globals) are only supported on AArch64 Android +; ERR: error: tagged symbols (-fsanitize=memtag-globals) are only supported on AArch64 + +; RUN: llc %s -mtriple=aarch64-unknown-linux -o %t.linux.S +; RUN: FileCheck %s --input-file=%t.linux.S --check-prefix=CHECK-ASM +; RUN: llvm-mc -filetype=obj %t.linux.S -triple=aarch64-unknown-linux -o %t.linux.o +; RUN: llvm-readelf -r %t.linux.o | FileCheck %s --check-prefix=CHECK-RELOCS ; RUN: llc %s -mtriple=aarch64-linux-android31 -o %t.S ; RUN: FileCheck %s --input-file=%t.S --check-prefix=CHECK-ASM _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
