[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