https://github.com/EliaGeretto updated https://github.com/llvm/llvm-project/pull/183275
>From c788ae3b3ca7db508ecf07997cfea9b559d62d81 Mon Sep 17 00:00:00 2001 From: Elia Geretto <[email protected]> Date: Fri, 20 Feb 2026 12:19:38 +0100 Subject: [PATCH 1/4] [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 | 92 +++++++++++++++++------ lld/ELF/SyntheticSections.cpp | 21 +++--- lld/test/ELF/aarch64-memtag-abi.s | 58 ++++++++++++++ lld/test/ELF/aarch64-memtag-android-abi.s | 5 +- 5 files changed, 150 insertions(+), 41 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..48a4573b30cb4 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -630,6 +630,47 @@ 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; +} + +static int getAndroidMemtagMode(Ctx &ctx, opt::InputArgList &args) { + auto ret = ELF::NT_MEMTAG_LEVEL_NONE; + + StringRef androidMemtagModeArg = + args.getLastArgValue(OPT_android_memtag_mode); + if (!androidMemtagModeArg.empty()) { + if (androidMemtagModeArg == "none") + ret = ELF::NT_MEMTAG_LEVEL_NONE; + else if (androidMemtagModeArg == "sync") + ret = ELF::NT_MEMTAG_LEVEL_SYNC; + else if (androidMemtagModeArg == "async") + ret = ELF::NT_MEMTAG_LEVEL_ASYNC; + else + ErrAlways(ctx) << "unknown --android-memtag-mode value: " + << androidMemtagModeArg; + } + + 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 +887,29 @@ 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 " + if (!ctx.arg.memtagAndroidNote) { + 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"; + } + return memtagMode; + } + + auto memtagMode = getAndroidMemtagMode(ctx, args); + if (memtagMode == ELF::NT_MEMTAG_LEVEL_NONE) { + if (ctx.arg.memtagStack) + Warn(ctx) << "--android-memtag-mode is none, leaving " "--android-memtag-stack a no-op"; - else if (ctx.arg.androidMemtagHeap) - Warn(ctx) << "--android-memtag-mode is unspecified, leaving " + else if (ctx.arg.memtagHeap) + Warn(ctx) << "--android-memtag-mode is none, leaving " "--android-memtag-heap a no-op"; - return ELF::NT_MEMTAG_LEVEL_NONE; } - - 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 +1401,18 @@ 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 = + hasZOption(args, "memtag-heap") || 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 = hasZOption(args, "memtag-stack") || + args.hasFlag(OPT_android_memtag_stack, + OPT_no_android_memtag_stack, false); + 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.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/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..154f15c6b986f --- /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: -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-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 diff --git a/lld/test/ELF/aarch64-memtag-android-abi.s b/lld/test/ELF/aarch64-memtag-android-abi.s index 57c85dcfe81d0..ca82c3963a389 100644 --- a/lld/test/ELF/aarch64-memtag-android-abi.s +++ b/lld/test/ELF/aarch64-memtag-android-abi.s @@ -32,7 +32,7 @@ # RUN: FileCheck %s --check-prefixes=MISSING-MODE # RUN: ld.lld -shared --android-memtag-heap --android-memtag-stack %t.o -o %t 2>&1 | \ # RUN: FileCheck %s --check-prefixes=MISSING-MODE -# MISSING-MODE: warning: --android-memtag-mode is unspecified, leaving +# MISSING-MODE: warning: --android-memtag-mode is none, leaving # MISSING-MODE: --android-memtag-{{(heap|stack)}} a no-op # CHECK: Memtag Dynamic Entries @@ -53,8 +53,7 @@ # RUN: not ld.lld -shared --android-memtag-mode=asymm --android-memtag-heap 2>&1 | \ # RUN: FileCheck %s --check-prefix=BAD-MODE -# BAD-MODE: error: unknown --android-memtag-mode value: "asymm", should be one of -# BAD-MODE: {async, sync, none} +# BAD-MODE: error: unknown --android-memtag-mode value: asymm # RUN: ld.lld -static --android-memtag-mode=sync --android-memtag-heap \ # RUN: --android-memtag-stack %t.o -o %t >From 7add554d62fe2e7658d62fad9651e0e7f979fdb7 Mon Sep 17 00:00:00 2001 From: Elia Geretto <[email protected]> Date: Fri, 20 Feb 2026 14:20:18 +0100 Subject: [PATCH 2/4] [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 | 28 ++++++++----- 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, 81 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..19df0204e757c 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1796,16 +1796,26 @@ 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("-z"); + CmdArgs.push_back( + 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"); + } } - 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 ff7ac190270d437444252c563369bab6a2ffbbcf Mon Sep 17 00:00:00 2001 From: Elia Geretto <[email protected]> Date: Fri, 20 Feb 2026 14:36:19 +0100 Subject: [PATCH 3/4] [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 >From 88acad115a1dce4cb57289e71378917f951503ca Mon Sep 17 00:00:00 2001 From: Elia Geretto <[email protected]> Date: Fri, 27 Feb 2026 10:59:45 +0100 Subject: [PATCH 4/4] fixup! [Driver][MTE] Use generic lld memtag flags --- clang/test/Driver/memtag-ld.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/clang/test/Driver/memtag-ld.c b/clang/test/Driver/memtag-ld.c index 7c59cc24845a3..05a648a6ac7a1 100644 --- a/clang/test/Driver/memtag-ld.c +++ b/clang/test/Driver/memtag-ld.c @@ -33,14 +33,14 @@ // RUN: -fsanitize-memtag-mode=asymm -fno-sanitize=memtag %s 2>&1 \ // RUN: | FileCheck %s --check-prefixes=CHECK-NONE -// 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-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: ld{{.*}} "--memtag +// CHECK-NONE-NOT: ld{{.*}} "-z" "memtag void f() {} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
