[llvm] 0867edf - [HWASan] Add basic stack tagging support for LAM.
Matt Morehouse via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 11 08:22:29 PDT 2021
Author: Matt Morehouse
Date: 2021-06-11T08:21:17-07:00
New Revision: 0867edfc643891c22ef089f8f6a4dadc691f0742
URL: https://github.com/llvm/llvm-project/commit/0867edfc643891c22ef089f8f6a4dadc691f0742
DIFF: https://github.com/llvm/llvm-project/commit/0867edfc643891c22ef089f8f6a4dadc691f0742.diff
LOG: [HWASan] Add basic stack tagging support for LAM.
Adds the basic instrumentation needed for stack tagging.
Currently does not support stack short granules or TLS stack histories,
since a different code path is followed for the callback instrumentation
we use.
We may simply wait to support these two features until we switch to
a custom calling convention.
Patch By: xiangzhangllvm, morehouse
Reviewed By: vitalybuka
Differential Revision: https://reviews.llvm.org/D102901
Added:
llvm/test/Instrumentation/HWAddressSanitizer/X86/alloca-array.ll
llvm/test/Instrumentation/HWAddressSanitizer/X86/alloca-with-calls.ll
llvm/test/Instrumentation/HWAddressSanitizer/X86/alloca.ll
Modified:
clang/lib/Driver/SanitizerArgs.cpp
clang/test/Driver/fsanitize.c
compiler-rt/test/hwasan/TestCases/deep-recursion.c
compiler-rt/test/hwasan/TestCases/longjmp.c
compiler-rt/test/hwasan/TestCases/mem-intrinsics.c
compiler-rt/test/hwasan/TestCases/rich-stack.c
compiler-rt/test/hwasan/TestCases/stack-history-length.c
compiler-rt/test/hwasan/TestCases/stack-oob.c
compiler-rt/test/hwasan/TestCases/stack-uar-dynamic.c
compiler-rt/test/hwasan/TestCases/stack-uar-realign.c
compiler-rt/test/hwasan/TestCases/stack-uar.c
llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
Removed:
################################################################################
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 9c54bd5fbab6c..244d22b08ca0a 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -1059,6 +1059,11 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
CmdArgs.push_back("-tsan-instrument-atomics=0");
}
+ if (HwasanUseAliases) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-hwasan-experimental-use-page-aliases=1");
+ }
+
if (CfiCrossDso)
CmdArgs.push_back("-fsanitize-cfi-cross-dso");
diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c
index 7febfd02a1ad7..baa37b5fd79d9 100644
--- a/clang/test/Driver/fsanitize.c
+++ b/clang/test/Driver/fsanitize.c
@@ -895,6 +895,9 @@
// CHECK-HWASAN-PLATFORM-ABI: "-default-function-attr" "hwasan-abi=platform"
// CHECK-HWASAN-FOO-ABI: error: invalid value 'foo' in '-fsanitize-hwaddress-abi=foo'
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress -fsanitize-hwaddress-experimental-aliasing %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-HWASAN-ALIAS
+// CHECK-HWASAN-ALIAS: "-mllvm" "-hwasan-experimental-use-page-aliases=1"
+
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address,pointer-compare,pointer-subtract %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-POINTER-ALL
// RUN: %clang -target x86_64-linux-gnu -fsanitize=pointer-compare %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-POINTER-CMP-NEEDS-ADDRESS
// RUN: %clang -target x86_64-linux-gnu -fsanitize=pointer-subtract %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-POINTER-SUB-NEEDS-ADDRESS
diff --git a/compiler-rt/test/hwasan/TestCases/deep-recursion.c b/compiler-rt/test/hwasan/TestCases/deep-recursion.c
index 081becabdbfd4..d29c5fbb951d6 100644
--- a/compiler-rt/test/hwasan/TestCases/deep-recursion.c
+++ b/compiler-rt/test/hwasan/TestCases/deep-recursion.c
@@ -7,7 +7,7 @@
// REQUIRES: stable-runtime
-// Stack aliasing is not implemented on x86.
+// Stack histories are currently not recorded on x86.
// XFAIL: x86_64
#include <stdlib.h>
diff --git a/compiler-rt/test/hwasan/TestCases/longjmp.c b/compiler-rt/test/hwasan/TestCases/longjmp.c
index 2e3431ca6abe4..700a1cbee329c 100644
--- a/compiler-rt/test/hwasan/TestCases/longjmp.c
+++ b/compiler-rt/test/hwasan/TestCases/longjmp.c
@@ -1,10 +1,7 @@
// RUN: %clang_hwasan -O0 -DNEGATIVE %s -o %t && %run %t 2>&1
// RUN: %clang_hwasan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
-// REQUIRES: stable-runtime
-
-// Stack aliasing is not implemented on x86.
-// XFAIL: x86_64
+// REQUIRES: stable-runtime, pointer-tagging
#include <stdlib.h>
#include <assert.h>
diff --git a/compiler-rt/test/hwasan/TestCases/mem-intrinsics.c b/compiler-rt/test/hwasan/TestCases/mem-intrinsics.c
index 1c8df8676f98b..07a93958e0be1 100644
--- a/compiler-rt/test/hwasan/TestCases/mem-intrinsics.c
+++ b/compiler-rt/test/hwasan/TestCases/mem-intrinsics.c
@@ -3,10 +3,7 @@
// RUN: %clang_hwasan %s -DTEST_NO=3 -mllvm -hwasan-instrument-mem-intrinsics -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=WRITE
// RUN: %clang_hwasan %s -DTEST_NO=2 -mllvm -hwasan-instrument-mem-intrinsics -o %t && not %env_hwasan_opts=halt_on_error=0 %run %t 2>&1 | FileCheck %s --check-prefix=RECOVER
-// REQUIRES: stable-runtime
-
-// Stack aliasing is not implemented on x86.
-// XFAIL: x86_64
+// REQUIRES: stable-runtime, pointer-tagging
#include <stdio.h>
#include <stdlib.h>
diff --git a/compiler-rt/test/hwasan/TestCases/rich-stack.c b/compiler-rt/test/hwasan/TestCases/rich-stack.c
index ce04709f0cc93..c6c2f9bca6691 100644
--- a/compiler-rt/test/hwasan/TestCases/rich-stack.c
+++ b/compiler-rt/test/hwasan/TestCases/rich-stack.c
@@ -1,10 +1,7 @@
// Test how stack frames are reported (not fully implemented yet).
// RUN: %clang_hwasan %s -o %t
// RUN: not %run %t 3 2 -1 2>&1 | FileCheck %s --check-prefix=R321
-// REQUIRES: stable-runtime
-
-// Stack aliasing is not implemented on x86.
-// XFAIL: x86_64
+// REQUIRES: stable-runtime, pointer-tagging
#include <stdint.h>
#include <stdlib.h>
@@ -64,7 +61,7 @@ int main(int argc, char **argv) {
// R321: HWAddressSanitizer: tag-mismatch
// R321-NEXT: WRITE of size 8
-// R321-NEXT: in BAR
+// R321: in BAR
// R321-NEXT: in FOO
// R321-NEXT: in main
// R321: is located in stack of thread T0
diff --git a/compiler-rt/test/hwasan/TestCases/stack-history-length.c b/compiler-rt/test/hwasan/TestCases/stack-history-length.c
index 14a085e509ef0..510a9afeae5aa 100644
--- a/compiler-rt/test/hwasan/TestCases/stack-history-length.c
+++ b/compiler-rt/test/hwasan/TestCases/stack-history-length.c
@@ -4,7 +4,7 @@
// REQUIRES: stable-runtime
-// Stack aliasing is not implemented on x86.
+// Stack histories are currently not recorded on x86.
// XFAIL: x86_64
#include <stdlib.h>
diff --git a/compiler-rt/test/hwasan/TestCases/stack-oob.c b/compiler-rt/test/hwasan/TestCases/stack-oob.c
index c052752b0ad87..1088300c74bc1 100644
--- a/compiler-rt/test/hwasan/TestCases/stack-oob.c
+++ b/compiler-rt/test/hwasan/TestCases/stack-oob.c
@@ -9,7 +9,7 @@
// REQUIRES: stable-runtime
-// Stack aliasing is not implemented on x86.
+// Stack short granules are currently not implemented on x86.
// XFAIL: x86_64
#include <stdlib.h>
diff --git a/compiler-rt/test/hwasan/TestCases/stack-uar-dynamic.c b/compiler-rt/test/hwasan/TestCases/stack-uar-dynamic.c
index ae453f66c4c44..57426f1e66132 100644
--- a/compiler-rt/test/hwasan/TestCases/stack-uar-dynamic.c
+++ b/compiler-rt/test/hwasan/TestCases/stack-uar-dynamic.c
@@ -4,7 +4,7 @@
// still be using FP-relative debug info locations that we can use to find stack
// objects.
-// Stack aliasing is not implemented on x86.
+// Stack histories are currently not recorded on x86.
// XFAIL: x86_64
__attribute((noinline))
diff --git a/compiler-rt/test/hwasan/TestCases/stack-uar-realign.c b/compiler-rt/test/hwasan/TestCases/stack-uar-realign.c
index fa602404d256d..bbaeef7f9f7b7 100644
--- a/compiler-rt/test/hwasan/TestCases/stack-uar-realign.c
+++ b/compiler-rt/test/hwasan/TestCases/stack-uar-realign.c
@@ -6,8 +6,7 @@
// be able to handle this case somehow (e.g. by using a
diff erent register for
// DW_AT_frame_base) but at least we shouldn't get confused by it.
-// Stack aliasing is not implemented on x86.
-// XFAIL: x86_64
+// REQUIRES: pointer-tagging
__attribute((noinline))
char *buggy() {
diff --git a/compiler-rt/test/hwasan/TestCases/stack-uar.c b/compiler-rt/test/hwasan/TestCases/stack-uar.c
index d251995d2e850..113f36c319204 100644
--- a/compiler-rt/test/hwasan/TestCases/stack-uar.c
+++ b/compiler-rt/test/hwasan/TestCases/stack-uar.c
@@ -4,7 +4,7 @@
// REQUIRES: stable-runtime
-// Stack aliasing is not implemented on x86.
+// Stack histories currently are not recorded on x86.
// XFAIL: x86_64
void USE(void *x) { // pretend_to_do_something(void *x)
diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index 9b02410f09075..060cc1c98c45f 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -69,7 +69,6 @@ static const size_t kNumberOfAccessSizes = 5;
static const size_t kDefaultShadowScale = 4;
static const uint64_t kDynamicShadowSentinel =
std::numeric_limits<uint64_t>::max();
-static const unsigned kPointerTagShift = 56;
static const unsigned kShadowBaseAlignment = 32;
@@ -186,6 +185,11 @@ static cl::opt<bool> ClInlineAllChecks("hwasan-inline-all-checks",
cl::desc("inline all checks"),
cl::Hidden, cl::init(false));
+// Enabled from clang by "-fsanitize-hwaddress-experimental-aliasing".
+static cl::opt<bool> ClUsePageAliases("hwasan-experimental-use-page-aliases",
+ cl::desc("Use page aliasing in HWASan"),
+ cl::Hidden, cl::init(false));
+
namespace {
/// An instrumentation pass implementing detection of addressability bugs
@@ -242,6 +246,9 @@ class HWAddressSanitizer {
Value *getUARTag(IRBuilder<> &IRB, Value *StackTag);
Value *getHwasanThreadSlotPtr(IRBuilder<> &IRB, Type *Ty);
+ Value *applyTagMask(IRBuilder<> &IRB, Value *OldTag);
+ unsigned retagMask(unsigned AllocaNo);
+
void emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord);
void instrumentGlobal(GlobalVariable *GV, uint8_t Tag);
@@ -298,6 +305,9 @@ class HWAddressSanitizer {
bool HasMatchAllTag = false;
uint8_t MatchAllTag = 0;
+ unsigned PointerTagShift;
+ uint64_t TagMaskByte;
+
Function *HwasanCtorFunction;
FunctionCallee HwasanMemoryAccessCallback[2][kNumberOfAccessSizes];
@@ -489,11 +499,17 @@ void HWAddressSanitizer::initializeModule() {
TargetTriple = Triple(M.getTargetTriple());
- // x86_64 uses userspace pointer aliases, currently heap-only with callback
- // instrumentation only.
- UsePageAliases = TargetTriple.getArch() == Triple::x86_64;
- InstrumentWithCalls = UsePageAliases ? true : ClInstrumentWithCalls;
+ // x86_64 currently has two modes:
+ // - Intel LAM (default)
+ // - pointer aliasing
+ // Pointer aliasing mode is heap only. LAM mode is heap+stack, with support
+ // planned for globals as well.
+ bool IsX86_64 = TargetTriple.getArch() == Triple::x86_64;
+ UsePageAliases = ClUsePageAliases && IsX86_64;
+ InstrumentWithCalls = IsX86_64 ? true : ClInstrumentWithCalls;
InstrumentStack = UsePageAliases ? false : ClInstrumentStack;
+ PointerTagShift = IsX86_64 ? 57 : 56;
+ TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
Mapping.init(TargetTriple, InstrumentWithCalls);
@@ -537,7 +553,9 @@ void HWAddressSanitizer::initializeModule() {
createHwasanCtorComdat();
bool InstrumentGlobals =
ClGlobals.getNumOccurrences() ? ClGlobals : NewRuntime;
- if (InstrumentGlobals && !UsePageAliases)
+
+ // TODO: Support globals for x86_64 in non-aliasing mode.
+ if (InstrumentGlobals && !IsX86_64)
instrumentGlobals();
bool InstrumentPersonalityFunctions =
@@ -759,7 +777,7 @@ void HWAddressSanitizer::instrumentMemAccessInline(Value *Ptr, bool IsWrite,
}
Value *PtrLong = IRB.CreatePointerCast(Ptr, IntptrTy);
- Value *PtrTag = IRB.CreateTrunc(IRB.CreateLShr(PtrLong, kPointerTagShift),
+ Value *PtrTag = IRB.CreateTrunc(IRB.CreateLShr(PtrLong, PointerTagShift),
IRB.getInt8Ty());
Value *AddrLong = untagPointer(IRB, PtrLong);
Value *Shadow = memToShadow(AddrLong, IRB);
@@ -927,7 +945,10 @@ bool HWAddressSanitizer::tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag,
return true;
}
-static unsigned RetagMask(unsigned AllocaNo) {
+unsigned HWAddressSanitizer::retagMask(unsigned AllocaNo) {
+ if (TargetTriple.getArch() == Triple::x86_64)
+ return AllocaNo & TagMaskByte;
+
// A list of 8-bit numbers that have at most one run of non-zero bits.
// x = x ^ (mask << 56) can be encoded as a single armv8 instruction for these
// masks.
@@ -945,6 +966,16 @@ static unsigned RetagMask(unsigned AllocaNo) {
return FastMasks[AllocaNo % (sizeof(FastMasks) / sizeof(FastMasks[0]))];
}
+Value *HWAddressSanitizer::applyTagMask(IRBuilder<> &IRB, Value *OldTag) {
+ if (TargetTriple.getArch() == Triple::x86_64) {
+ Constant *TagMask = ConstantInt::get(IntptrTy, TagMaskByte);
+ Value *NewTag = IRB.CreateAnd(OldTag, TagMask);
+ return NewTag;
+ }
+ // aarch64 uses 8-bit tags, so no mask is needed.
+ return OldTag;
+}
+
Value *HWAddressSanitizer::getNextTagWithCall(IRBuilder<> &IRB) {
return IRB.CreateZExt(IRB.CreateCall(HwasanGenerateTagFunc), IntptrTy);
}
@@ -968,8 +999,9 @@ Value *HWAddressSanitizer::getStackBaseTag(IRBuilder<> &IRB) {
// between functions).
Value *StackPointerLong = IRB.CreatePointerCast(StackPointer, IntptrTy);
Value *StackTag =
- IRB.CreateXor(StackPointerLong, IRB.CreateLShr(StackPointerLong, 20),
- "hwasan.stack.base.tag");
+ applyTagMask(IRB, IRB.CreateXor(StackPointerLong,
+ IRB.CreateLShr(StackPointerLong, 20)));
+ StackTag->setName("hwasan.stack.base.tag");
return StackTag;
}
@@ -978,7 +1010,7 @@ Value *HWAddressSanitizer::getAllocaTag(IRBuilder<> &IRB, Value *StackTag,
if (ClGenerateTagsWithCalls)
return getNextTagWithCall(IRB);
return IRB.CreateXor(StackTag,
- ConstantInt::get(IntptrTy, RetagMask(AllocaNo)));
+ ConstantInt::get(IntptrTy, retagMask(AllocaNo)));
}
Value *HWAddressSanitizer::getUARTag(IRBuilder<> &IRB, Value *StackTag) {
@@ -986,7 +1018,7 @@ Value *HWAddressSanitizer::getUARTag(IRBuilder<> &IRB, Value *StackTag) {
return ConstantInt::get(IntptrTy, 0);
if (ClGenerateTagsWithCalls)
return getNextTagWithCall(IRB);
- return IRB.CreateXor(StackTag, ConstantInt::get(IntptrTy, 0xFFU));
+ return IRB.CreateXor(StackTag, ConstantInt::get(IntptrTy, TagMaskByte));
}
// Add a tag to an address.
@@ -996,13 +1028,13 @@ Value *HWAddressSanitizer::tagPointer(IRBuilder<> &IRB, Type *Ty,
Value *TaggedPtrLong;
if (CompileKernel) {
// Kernel addresses have 0xFF in the most significant byte.
- Value *ShiftedTag = IRB.CreateOr(
- IRB.CreateShl(Tag, kPointerTagShift),
- ConstantInt::get(IntptrTy, (1ULL << kPointerTagShift) - 1));
+ Value *ShiftedTag =
+ IRB.CreateOr(IRB.CreateShl(Tag, PointerTagShift),
+ ConstantInt::get(IntptrTy, (1ULL << PointerTagShift) - 1));
TaggedPtrLong = IRB.CreateAnd(PtrLong, ShiftedTag);
} else {
- // Userspace can simply do OR (tag << 56);
- Value *ShiftedTag = IRB.CreateShl(Tag, kPointerTagShift);
+ // Userspace can simply do OR (tag << PointerTagShift);
+ Value *ShiftedTag = IRB.CreateShl(Tag, PointerTagShift);
TaggedPtrLong = IRB.CreateOr(PtrLong, ShiftedTag);
}
return IRB.CreateIntToPtr(TaggedPtrLong, Ty);
@@ -1016,12 +1048,12 @@ Value *HWAddressSanitizer::untagPointer(IRBuilder<> &IRB, Value *PtrLong) {
// Kernel addresses have 0xFF in the most significant byte.
UntaggedPtrLong =
IRB.CreateOr(PtrLong, ConstantInt::get(PtrLong->getType(),
- 0xFFULL << kPointerTagShift));
+ 0xFFULL << PointerTagShift));
} else {
// Userspace addresses have 0x00.
- UntaggedPtrLong = IRB.CreateAnd(
- PtrLong,
- ConstantInt::get(PtrLong->getType(), ~(0xFFULL << kPointerTagShift)));
+ UntaggedPtrLong =
+ IRB.CreateAnd(PtrLong, ConstantInt::get(PtrLong->getType(),
+ ~(0xFFULL << PointerTagShift)));
}
return UntaggedPtrLong;
}
@@ -1171,7 +1203,7 @@ bool HWAddressSanitizer::instrumentStack(
// Tag offset logically applies to the alloca pointer, and it makes sense
// to put it at the beginning of the expression.
SmallVector<uint64_t, 8> NewOps = {dwarf::DW_OP_LLVM_tag_offset,
- RetagMask(N)};
+ retagMask(N)};
auto Locations = DDI->location_ops();
unsigned LocNo = std::distance(Locations.begin(), find(Locations, AI));
DDI->setExpression(
@@ -1428,7 +1460,7 @@ void HWAddressSanitizer::instrumentGlobal(GlobalVariable *GV, uint8_t Tag) {
Constant *Aliasee = ConstantExpr::getIntToPtr(
ConstantExpr::getAdd(
ConstantExpr::getPtrToInt(NewGV, Int64Ty),
- ConstantInt::get(Int64Ty, uint64_t(Tag) << kPointerTagShift)),
+ ConstantInt::get(Int64Ty, uint64_t(Tag) << PointerTagShift)),
GV->getType());
auto *Alias = GlobalAlias::create(GV->getValueType(), GV->getAddressSpace(),
GV->getLinkage(), "", Aliasee, &M);
diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/X86/alloca-array.ll b/llvm/test/Instrumentation/HWAddressSanitizer/X86/alloca-array.ll
new file mode 100644
index 0000000000000..3bf6c84c88d3c
--- /dev/null
+++ b/llvm/test/Instrumentation/HWAddressSanitizer/X86/alloca-array.ll
@@ -0,0 +1,15 @@
+; RUN: opt < %s -hwasan -S | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @use(i8*, i8*)
+
+define void @test_alloca() sanitize_hwaddress {
+ ; CHECK: alloca { [4 x i8], [12 x i8] }, align 16
+ %x = alloca i8, i64 4
+ ; CHECK: alloca i8, i64 16, align 16
+ %y = alloca i8, i64 16
+ call void @use(i8* %x, i8* %y)
+ ret void
+}
diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/X86/alloca-with-calls.ll b/llvm/test/Instrumentation/HWAddressSanitizer/X86/alloca-with-calls.ll
new file mode 100644
index 0000000000000..79e9117646110
--- /dev/null
+++ b/llvm/test/Instrumentation/HWAddressSanitizer/X86/alloca-with-calls.ll
@@ -0,0 +1,23 @@
+; Test alloca instrumentation when tags are generated by HWASan function.
+;
+; RUN: opt < %s -hwasan -hwasan-generate-tags-with-calls -S | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @use32(i32*)
+
+define void @test_alloca() sanitize_hwaddress {
+; CHECK-LABEL: @test_alloca(
+; CHECK: %[[BC:[^ ]*]] = bitcast { i32, [12 x i8] }* %x to i32*
+; CHECK: %[[T1:[^ ]*]] = call i8 @__hwasan_generate_tag()
+; CHECK: %[[A:[^ ]*]] = zext i8 %[[T1]] to i64
+; CHECK: %[[B:[^ ]*]] = ptrtoint i32* %[[BC]] to i64
+; CHECK: %[[C:[^ ]*]] = shl i64 %[[A]], 57
+; CHECK: or i64 %[[B]], %[[C]]
+
+entry:
+ %x = alloca i32, align 4
+ call void @use32(i32* nonnull %x)
+ ret void
+}
diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/X86/alloca.ll b/llvm/test/Instrumentation/HWAddressSanitizer/X86/alloca.ll
new file mode 100644
index 0000000000000..d2ac398caac88
--- /dev/null
+++ b/llvm/test/Instrumentation/HWAddressSanitizer/X86/alloca.ll
@@ -0,0 +1,45 @@
+; Test alloca instrumentation.
+;
+; RUN: opt < %s -hwasan -S | FileCheck %s --check-prefixes=CHECK,NO-UAR-TAGS
+; RUN: opt < %s -hwasan -hwasan-uar-retag-to-zero=0 -S | FileCheck %s --check-prefixes=CHECK,UAR-TAGS
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @use32(i32*)
+
+define void @test_alloca() sanitize_hwaddress {
+; CHECK-LABEL: @test_alloca(
+; CHECK: %[[FP:[^ ]*]] = call i8* @llvm.frameaddress.p0i8(i32 0)
+; CHECK: %[[A:[^ ]*]] = ptrtoint i8* %[[FP]] to i64
+; CHECK: %[[B:[^ ]*]] = lshr i64 %[[A]], 20
+; CHECK: %[[A_XOR_B:[^ ]*]] = xor i64 %[[A]], %[[B]]
+; CHECK: %[[BASE_TAG:[^ ]*]] = and i64 %[[A_XOR_B]], 63
+
+; CHECK: %[[X:[^ ]*]] = alloca { i32, [12 x i8] }, align 16
+; CHECK: %[[X_BC:[^ ]*]] = bitcast { i32, [12 x i8] }* %[[X]] to i32*
+; CHECK: %[[X_TAG:[^ ]*]] = xor i64 %[[BASE_TAG]], 0
+; CHECK: %[[X1:[^ ]*]] = ptrtoint i32* %[[X_BC]] to i64
+; CHECK: %[[C:[^ ]*]] = shl i64 %[[X_TAG]], 57
+; CHECK: %[[D:[^ ]*]] = or i64 %[[X1]], %[[C]]
+; CHECK: %[[X_HWASAN:[^ ]*]] = inttoptr i64 %[[D]] to i32*
+
+; CHECK: %[[X_TAG2:[^ ]*]] = trunc i64 %[[X_TAG]] to i8
+; CHECK: %[[X_I8:[^ ]*]] = bitcast i32* %[[X_BC]] to i8*
+; CHECK: call void @__hwasan_tag_memory(i8* %[[X_I8]], i8 %[[X_TAG2]], i64 16)
+
+; CHECK: call void @use32(i32* nonnull %[[X_HWASAN]])
+
+; UAR-TAGS: %[[BASE_TAG_COMPL:[^ ]*]] = xor i64 %[[BASE_TAG]], 63
+; UAR-TAGS: %[[X_TAG_UAR:[^ ]*]] = trunc i64 %[[BASE_TAG_COMPL]] to i8
+; CHECK: %[[X_I8_2:[^ ]*]] = bitcast i32* %[[X_BC]] to i8*
+; NO-UAR-TAGS: call void @__hwasan_tag_memory(i8* %[[X_I8_2]], i8 0, i64 16)
+; UAR-TAGS: call void @__hwasan_tag_memory(i8* %[[X_I8_2]], i8 %[[X_TAG_UAR]], i64 16)
+; CHECK: ret void
+
+
+entry:
+ %x = alloca i32, align 4
+ call void @use32(i32* nonnull %x)
+ ret void
+}
More information about the llvm-commits
mailing list