Skip to content

Commit fa34951

Browse files
committed
Reland "[MTE] Add -fsanitize=memtag* and friends."
Differential Revision: https://reviews.llvm.org/D118948
1 parent 4f4752e commit fa34951

16 files changed

+151
-33
lines changed

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,8 @@ def err_drv_ropi_incompatible_with_cxx : Error<
483483
"ROPI is not compatible with c++">;
484484

485485
def err_stack_tagging_requires_hardware_feature : Error<
486-
"'-fsanitize=memtag' requires hardware support (+memtag)">;
486+
"'-fsanitize=memtag-stack' requires hardware support (+memtag). For Armv8 or "
487+
"Armv9, try compiling with -march=armv8a+memtag or -march=armv9a+memtag">;
487488

488489
def err_cmse_pi_are_incompatible : Error<
489490
"cmse is not compatible with %select{RWPI|ROPI}0">;

clang/include/clang/Basic/Features.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ FEATURE(leak_sanitizer,
4545
FEATURE(hwaddress_sanitizer,
4646
LangOpts.Sanitize.hasOneOf(SanitizerKind::HWAddress |
4747
SanitizerKind::KernelHWAddress))
48-
FEATURE(memtag_sanitizer, LangOpts.Sanitize.has(SanitizerKind::MemTag))
48+
FEATURE(memtag_stack,
49+
LangOpts.Sanitize.has(SanitizerKind::MemtagStack))
50+
FEATURE(memtag_heap,
51+
LangOpts.Sanitize.has(SanitizerKind::MemtagHeap))
4952
FEATURE(xray_instrument, LangOpts.XRayInstrument)
5053
FEATURE(undefined_behavior_sanitizer,
5154
LangOpts.Sanitize.hasOneOf(SanitizerKind::Undefined))

clang/include/clang/Basic/Sanitizers.def

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ SANITIZER("hwaddress", HWAddress)
5656
SANITIZER("kernel-hwaddress", KernelHWAddress)
5757

5858
// A variant of AddressSanitizer using AArch64 MTE extension.
59-
SANITIZER("memtag", MemTag)
59+
SANITIZER("memtag-stack", MemtagStack)
60+
SANITIZER("memtag-heap", MemtagHeap)
61+
SANITIZER_GROUP("memtag", MemTag, MemtagStack | MemtagHeap)
6062

6163
// MemorySanitizer
6264
SANITIZER("memory", Memory)

clang/include/clang/Driver/Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,6 +1641,9 @@ def fsanitize_address_outline_instrumentation : Flag<["-"], "fsanitize-address-o
16411641
def fno_sanitize_address_outline_instrumentation : Flag<["-"], "fno-sanitize-address-outline-instrumentation">,
16421642
Group<f_clang_Group>,
16431643
HelpText<"Use default code inlining logic for the address sanitizer">;
1644+
def fsanitize_memtag_mode_EQ : Joined<["-"], "fsanitize-memtag-mode=">,
1645+
Group<f_clang_Group>,
1646+
HelpText<"Set default MTE mode to 'sync' (default) or 'async'">;
16441647
def fsanitize_hwaddress_experimental_aliasing
16451648
: Flag<["-"], "fsanitize-hwaddress-experimental-aliasing">,
16461649
Group<f_clang_Group>,

clang/include/clang/Driver/SanitizerArgs.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ class SanitizerArgs {
6464
llvm::AsanDetectStackUseAfterReturnMode AsanUseAfterReturn =
6565
llvm::AsanDetectStackUseAfterReturnMode::Invalid;
6666

67+
std::string MemtagMode;
68+
6769
public:
6870
/// Parses the sanitizer arguments from an argument list.
6971
SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
@@ -97,6 +99,18 @@ class SanitizerArgs {
9799
bool needsStatsRt() const { return Stats; }
98100
bool needsScudoRt() const { return Sanitizers.has(SanitizerKind::Scudo); }
99101

102+
bool hasMemTag() const { return hasMemtagHeap() || hasMemtagStack(); }
103+
bool hasMemtagHeap() const {
104+
return Sanitizers.has(SanitizerKind::MemtagHeap);
105+
}
106+
bool hasMemtagStack() const {
107+
return Sanitizers.has(SanitizerKind::MemtagStack);
108+
}
109+
const std::string &getMemtagMode() const {
110+
assert(!MemtagMode.empty());
111+
return MemtagMode;
112+
}
113+
100114
bool requiresPIE() const;
101115
bool needsUnwindTables() const;
102116
bool needsLTO() const;

clang/lib/CodeGen/CGDeclCXX.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -458,8 +458,8 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrCleanUpFunction(
458458
!isInNoSanitizeList(SanitizerKind::KernelHWAddress, Fn, Loc))
459459
Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);
460460

461-
if (getLangOpts().Sanitize.has(SanitizerKind::MemTag) &&
462-
!isInNoSanitizeList(SanitizerKind::MemTag, Fn, Loc))
461+
if (getLangOpts().Sanitize.has(SanitizerKind::MemtagStack) &&
462+
!isInNoSanitizeList(SanitizerKind::MemtagStack, Fn, Loc))
463463
Fn->addFnAttr(llvm::Attribute::SanitizeMemTag);
464464

465465
if (getLangOpts().Sanitize.has(SanitizerKind::Thread) &&

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
780780
if (SanOpts.hasOneOf(SanitizerKind::HWAddress |
781781
SanitizerKind::KernelHWAddress))
782782
Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);
783-
if (SanOpts.has(SanitizerKind::MemTag))
783+
if (SanOpts.has(SanitizerKind::MemtagStack))
784784
Fn->addFnAttr(llvm::Attribute::SanitizeMemTag);
785785
if (SanOpts.has(SanitizerKind::Thread))
786786
Fn->addFnAttr(llvm::Attribute::SanitizeThread);

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ void CodeGenModule::Release() {
735735
LangOptions::SignReturnAddressScopeKind::None)
736736
getModule().addModuleFlag(llvm::Module::Override,
737737
"sign-return-address-buildattr", 1);
738-
if (LangOpts.Sanitize.has(SanitizerKind::MemTag))
738+
if (LangOpts.Sanitize.has(SanitizerKind::MemtagStack))
739739
getModule().addModuleFlag(llvm::Module::Override,
740740
"tag-stack-memory-buildattr", 1);
741741

clang/lib/Driver/SanitizerArgs.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ static const SanitizerMask NeedsUnwindTables =
4444
static const SanitizerMask SupportsCoverage =
4545
SanitizerKind::Address | SanitizerKind::HWAddress |
4646
SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
47-
SanitizerKind::MemTag | SanitizerKind::Memory |
48-
SanitizerKind::KernelMemory | SanitizerKind::Leak |
47+
SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
48+
SanitizerKind::Memory | SanitizerKind::KernelMemory | SanitizerKind::Leak |
4949
SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |
5050
SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
5151
SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
@@ -73,7 +73,7 @@ static const SanitizerMask CFIClasses =
7373
SanitizerKind::CFIUnrelatedCast;
7474
static const SanitizerMask CompatibleWithMinimalRuntime =
7575
TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack |
76-
SanitizerKind::MemTag;
76+
SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap;
7777

7878
enum CoverageFeature {
7979
CoverageFunc = 1 << 0,
@@ -651,6 +651,18 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
651651
MsanParamRetval = false;
652652
}
653653

654+
if (AllAddedKinds & SanitizerKind::MemTag) {
655+
StringRef S =
656+
Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ, "sync");
657+
if (S == "async" || S == "sync") {
658+
MemtagMode = S.str();
659+
} else {
660+
D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)
661+
<< "-fsanitize-memtag-mode=" << S << "{async, sync}";
662+
MemtagMode = "sync";
663+
}
664+
}
665+
654666
if (AllAddedKinds & SanitizerKind::Thread) {
655667
TsanMemoryAccess = Args.hasFlag(
656668
options::OPT_fsanitize_thread_memory_access,
@@ -1231,7 +1243,8 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
12311243
<< "-fvisibility=";
12321244
}
12331245

1234-
if (Sanitizers.has(SanitizerKind::MemTag) && !hasTargetFeatureMTE(CmdArgs))
1246+
if (Sanitizers.has(SanitizerKind::MemtagStack) &&
1247+
!hasTargetFeatureMTE(CmdArgs))
12351248
TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature);
12361249
}
12371250

clang/lib/Driver/ToolChains/CommonArgs.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,19 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
10141014
if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic)
10151015
CmdArgs.push_back("--export-dynamic-symbol=__cfi_check");
10161016

1017+
if (SanArgs.hasMemTag()) {
1018+
if (!TC.getTriple().isAndroid()) {
1019+
TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
1020+
<< "-fsanitize=memtag*" << TC.getTriple().str();
1021+
}
1022+
CmdArgs.push_back(
1023+
Args.MakeArgString("--android-memtag-mode=" + SanArgs.getMemtagMode()));
1024+
if (SanArgs.hasMemtagHeap())
1025+
CmdArgs.push_back("--android-memtag-heap");
1026+
if (SanArgs.hasMemtagStack())
1027+
CmdArgs.push_back("--android-memtag-stack");
1028+
}
1029+
10171030
return !StaticRuntimes.empty() || !NonWholeStaticRuntimes.empty();
10181031
}
10191032

clang/test/CodeGen/memtag-attr.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,27 @@
44
// RUN: %clang_cc1 -triple aarch64-unknown-linux -disable-O0-optnone \
55
// RUN: -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NO %s
66

7-
// RUN: %clang_cc1 -triple aarch64-unknown-linux -fsanitize=memtag \
7+
// RUN: %clang_cc1 -triple aarch64-unknown-linux -fsanitize=memtag-stack \
88
// RUN: -disable-O0-optnone -emit-llvm -o - %s | \
99
// RUN: FileCheck -check-prefix=CHECK-MEMTAG %s
1010

11-
int HasSanitizeMemTag() { return 1; }
12-
// CHECK-NO: {{Function Attrs: mustprogress noinline nounwind$}}
13-
// CHECK-MEMTAG: Function Attrs: mustprogress noinline nounwind sanitize_memtag
11+
// RUN: %clang --target=aarch64-unknown-linux -march=armv8a+memtag \
12+
// RUN: -fsanitize=memtag -disable-O0-optnone -S -emit-llvm -o - %s | \
13+
// RUN: FileCheck -check-prefix=CHECK-MEMTAG %s
14+
15+
extern "C" int HasSanitizeMemTag() { return 1; }
16+
// CHECK-NO: Function Attrs
17+
// CHECK-NO-NOT: sanitize_memtag
18+
// CHECK-NO-NEXT: define {{.*}} @HasSanitizeMemTag(
19+
// CHECK-MEMTAG: Function Attrs: {{.*}} sanitize_memtag
20+
// CHECK-MEMTAG-NEXT: define {{.*}} @HasSanitizeMemTag(
1421

15-
__attribute__((no_sanitize("memtag"))) int NoSanitizeQuoteAddress() {
22+
extern "C" __attribute__((no_sanitize("memtag"))) int NoSanitizeQuoteAddress() {
1623
return 0;
1724
}
18-
// CHECK-NO: {{Function Attrs: mustprogress noinline nounwind$}}
19-
// CHECK-MEMTAG: {{Function Attrs: mustprogress noinline nounwind$}}
25+
// CHECK-NO: Function Attrs
26+
// CHECK-NO-NOT: sanitize_memtag
27+
// CHECK-NO-NEXT: define {{.*}} @NoSanitizeQuoteAddress(
28+
// CHECK-MEMTAG: Function Attrs
29+
// CHECK-MEMTAG-NOT: sanitize_memtag
30+
// CHECK-MEMTAG-NEXT: define {{.*}} @NoSanitizeQuoteAddress(

clang/test/Driver/fsanitize.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,13 +195,13 @@
195195

196196
// RUN: %clang -target aarch64-linux -fsanitize=memtag -march=armv8-a+memtag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANMT-MT
197197
// CHECK-SANMT-MT: "-target-feature" "+mte"
198-
// CHECK-SANMT-MT-SAME: "-fsanitize=memtag"
198+
// CHECK-SANMT-MT-SAME: "-fsanitize=memtag-stack,memtag-heap"
199199

200200
// RUN: %clang -target aarch64-linux -fsanitize=memtag %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANMT-NOMT-0
201-
// CHECK-SANMT-NOMT-0: '-fsanitize=memtag' requires hardware support (+memtag)
201+
// CHECK-SANMT-NOMT-0: '-fsanitize=memtag-stack' requires hardware support (+memtag)
202202

203203
// RUN: %clang -target aarch64-linux -fsanitize=memtag -I +mte %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANMT-NOMT-1
204-
// CHECK-SANMT-NOMT-1: '-fsanitize=memtag' requires hardware support (+memtag)
204+
// CHECK-SANMT-NOMT-1: '-fsanitize=memtag-stack' requires hardware support (+memtag)
205205

206206
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-use-after-scope %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-USE-AFTER-SCOPE
207207
// RUN: %clang_cl --target=x86_64-windows -fsanitize=address -fsanitize-address-use-after-scope -### -- %s 2>&1 | FileCheck %s --check-prefix=CHECK-USE-AFTER-SCOPE
@@ -801,7 +801,7 @@
801801
// CHECK-INTSAN-MINIMAL: "-fsanitize-minimal-runtime"
802802

803803
// RUN: %clang -target aarch64-linux-android -march=armv8-a+memtag -fsanitize=memtag -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MEMTAG-MINIMAL
804-
// CHECK-MEMTAG-MINIMAL: "-fsanitize=memtag"
804+
// CHECK-MEMTAG-MINIMAL: "-fsanitize=memtag-stack,memtag-heap"
805805
// CHECK-MEMTAG-MINIMAL: "-fsanitize-minimal-runtime"
806806

807807
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize=function -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-FUNCTION-MINIMAL

clang/test/Driver/memtag-ld.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \
2+
// RUN: -fsanitize=memtag %s 2>&1 | FileCheck %s \
3+
// RUN: --check-prefixes=CHECK-SYNC,CHECK-HEAP,CHECK-STACK
4+
5+
// RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \
6+
// RUN: -fsanitize=memtag-stack %s 2>&1 | FileCheck %s \
7+
// RUN: --check-prefixes=CHECK-SYNC,CHECK-NO-HEAP,CHECK-STACK
8+
9+
// RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \
10+
// RUN: -fsanitize=memtag-heap %s 2>&1 | FileCheck %s \
11+
// RUN: --check-prefixes=CHECK-SYNC,CHECK-HEAP,CHECK-NO-STACK
12+
13+
// RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \
14+
// RUN: -fsanitize=memtag -fsanitize-memtag-mode=async %s 2>&1 | \
15+
// RUN: FileCheck %s --check-prefixes=CHECK-ASYNC,CHECK-HEAP,CHECK-STACK
16+
17+
// RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \
18+
// RUN: -fsanitize=memtag-stack -fsanitize-memtag-mode=async %s 2>&1 \
19+
// RUN: | FileCheck %s \
20+
// RUN: --check-prefixes=CHECK-ASYNC,CHECK-NO-HEAP,CHECK-STACK
21+
22+
// RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \
23+
// RUN: -fsanitize=memtag-heap -fsanitize-memtag-mode=async %s 2>&1 \
24+
// RUN: | FileCheck %s \
25+
// RUN: --check-prefixes=CHECK-ASYNC,CHECK-HEAP,CHECK-NO-STACK
26+
27+
// RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \
28+
// RUN: -fsanitize=memtag-heap -fsanitize-memtag-mode=asymm %s 2>&1 \
29+
// RUN: | FileCheck %s --check-prefixes=CHECK-INVALID-MODE
30+
31+
// RUN: %clang -### --target=aarch64-linux-android -march=armv8+memtag \
32+
// RUN: -fsanitize=memtag-stack -fsanitize=memtag-heap \
33+
// RUN: -fsanitize-memtag-mode=asymm -fno-sanitize=memtag %s 2>&1 \
34+
// RUN: | FileCheck %s --check-prefixes=CHECK-NONE
35+
36+
// CHECK-ASYNC: ld{{.*}} "--android-memtag-mode=async"
37+
// CHECK-SYNC: ld{{.*}} "--android-memtag-mode=sync"
38+
// CHECK-HEAP: "--android-memtag-heap"
39+
// CHECK-NO-HEAP-NOT: "--android-memtag-heap"
40+
// CHECK-STACK: "--android-memtag-stack"
41+
// CHECK-NO-STACK-NOT: "--android-memtag-stack"
42+
// CHECK-INVALID-MODE: invalid value 'asymm' in '-fsanitize-memtag-mode=',
43+
// CHECK-INVALID-MODE-SAME: expected one of: {async, sync}
44+
// CHECK-NONE-NOT: ld{{.*}} "--android-memtag
45+
46+
void f() {}
File renamed without changes.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %clang_cc1 -E -fsanitize=memtag-stack %s -o - | FileCheck --check-prefix=CHECK-MEMTAG-STACK %s
2+
// RUN: %clang_cc1 -E -fsanitize=memtag-heap %s -o - | FileCheck --check-prefix=CHECK-MEMTAG-HEAP %s
3+
// RUN: %clang -E -fsanitize=memtag --target=aarch64-unknown-linux -march=armv8a+memtag %s -o - \
4+
// RUN: | FileCheck --check-prefixes=CHECK-MEMTAG-STACK,CHECK-MEMTAG-HEAP %s
5+
// RUN: %clang_cc1 -E %s -o - | FileCheck --check-prefix=CHECK-NO-MEMTAG %s
6+
7+
#if __has_feature(memtag_stack)
8+
int MemTagSanitizerStack();
9+
#else
10+
int MemTagSanitizerNoStack();
11+
#endif
12+
13+
#if __has_feature(memtag_heap)
14+
int MemTagSanitizerHeap();
15+
#else
16+
int MemTagSanitizerNoHeap();
17+
#endif
18+
19+
// CHECK-MEMTAG-STACK: MemTagSanitizerStack
20+
// CHECK-MEMTAG-HEAP: MemTagSanitizerHeap
21+
22+
// CHECK-NO-MEMTAG: MemTagSanitizerNoStack
23+
// CHECK-NO-MEMTAG: MemTagSanitizerNoHeap

clang/test/Lexer/has_feature_memtag_sanitizer.cpp

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)