Use store operation to poison allocas for lifetime analysis.

Summary:
Calling __asan_poison_stack_memory and __asan_unpoison_stack_memory for small
variables is too expensive.

Code is disabled by default and can be enabled by -asan-experimental-poisoning.

PR27453

Reviewers: eugenis

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D23947

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@279984 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Vitaly Buka 2016-08-29 18:17:21 +00:00
parent 997a485279
commit b8ae70f140
3 changed files with 731 additions and 95 deletions

View File

@ -55,6 +55,7 @@
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
#include <algorithm>
#include <iomanip>
#include <limits>
#include <sstream>
#include <string>
#include <system_error>
@ -811,11 +812,19 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
/// Finds alloca where the value comes from.
AllocaInst *findAllocaForValue(Value *V);
void poisonStackFrameInline(ArrayRef<uint8_t> ShadowBytes, size_t Begin,
size_t End, IRBuilder<> &IRB, Value *ShadowBase,
bool DoPoison);
void poisonStackFrame(ArrayRef<uint8_t> ShadowBytes, IRBuilder<> &IRB,
Value *ShadowBase, bool DoPoison);
// Copies bytes from ShadowBytes into shadow memory for indexes where
// ShadowMask is not zero. If ShadowMask[i] is zero, we assume that
// ShadowBytes[i] is constantly zero and doesn't need to be overwritten.
void copyToShadow(ArrayRef<uint8_t> ShadowMask, ArrayRef<uint8_t> ShadowBytes,
IRBuilder<> &IRB, Value *ShadowBase);
void copyToShadow(ArrayRef<uint8_t> ShadowMask, ArrayRef<uint8_t> ShadowBytes,
size_t Begin, size_t End, IRBuilder<> &IRB,
Value *ShadowBase);
void copyToShadowInline(ArrayRef<uint8_t> ShadowMask,
ArrayRef<uint8_t> ShadowBytes, size_t Begin,
size_t End, IRBuilder<> &IRB, Value *ShadowBase);
void poisonAlloca(Value *V, uint64_t Size, IRBuilder<> &IRB, bool DoPoison);
Value *createAllocaForLayout(IRBuilder<> &IRB, const ASanStackFrameLayout &L,
@ -1958,15 +1967,11 @@ void FunctionStackPoisoner::initializeCallbacks(Module &M) {
kAsanAllocasUnpoison, IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr));
}
// If DoPoison is true function copies ShadowBytes into shadow memory.
// If DoPoison is false function sets 0s into shadow memory.
// Function assumes that if ShadowBytes[i] is 0, then corresponding shadow
// memory is constant for duration of the function and it contains 0s. So we
// will try to minimize writes into corresponding addresses of the real shadow
// memory.
void FunctionStackPoisoner::poisonStackFrameInline(
ArrayRef<uint8_t> ShadowBytes, size_t Begin, size_t End, IRBuilder<> &IRB,
Value *ShadowBase, bool DoPoison) {
void FunctionStackPoisoner::copyToShadowInline(ArrayRef<uint8_t> ShadowMask,
ArrayRef<uint8_t> ShadowBytes,
size_t Begin, size_t End,
IRBuilder<> &IRB,
Value *ShadowBase) {
if (Begin >= End)
return;
@ -1976,11 +1981,12 @@ void FunctionStackPoisoner::poisonStackFrameInline(
const bool IsLittleEndian = F.getParent()->getDataLayout().isLittleEndian();
// Poison given range in shadow using larges store size with out leading and
// trailing zeros. Zeros never change, so they need neither poisoning nor
// up-poisoning, but we don't mind if some of them get into a middle of a
// store.
// trailing zeros in ShadowMask. Zeros never change, so they need neither
// poisoning nor up-poisoning. Still we don't mind if some of them get into a
// middle of a store.
for (size_t i = Begin; i < End;) {
if (!ShadowBytes[i]) {
if (!ShadowMask[i]) {
assert(!ShadowBytes[i]);
++i;
continue;
}
@ -1991,22 +1997,17 @@ void FunctionStackPoisoner::poisonStackFrameInline(
StoreSizeInBytes /= 2;
// Minimize store size by trimming trailing zeros.
for (size_t j = StoreSizeInBytes - 1; j && !ShadowBytes[i + j]; --j) {
for (size_t j = StoreSizeInBytes - 1; j && !ShadowMask[i + j]; --j) {
while (j <= StoreSizeInBytes / 2)
StoreSizeInBytes /= 2;
}
uint64_t Val = 0;
if (DoPoison) {
for (size_t j = 0; j < StoreSizeInBytes; j++) {
if (IsLittleEndian)
Val |= (uint64_t)ShadowBytes[i + j] << (8 * j);
else
Val = (Val << 8) | ShadowBytes[i + j];
}
assert(Val); // Impossible because ShadowBytes[i] != 0
} else {
Val = 0;
for (size_t j = 0; j < StoreSizeInBytes; j++) {
if (IsLittleEndian)
Val |= (uint64_t)ShadowBytes[i + j] << (8 * j);
else
Val = (Val << 8) | ShadowBytes[i + j];
}
Value *Ptr = IRB.CreateAdd(ShadowBase, ConstantInt::get(IntptrTy, i));
@ -2018,30 +2019,33 @@ void FunctionStackPoisoner::poisonStackFrameInline(
}
}
void FunctionStackPoisoner::poisonStackFrame(ArrayRef<uint8_t> ShadowBytes,
IRBuilder<> &IRB,
Value *ShadowBase, bool DoPoison) {
auto ValueToWrite = [&](size_t i) {
if (DoPoison)
return ShadowBytes[i];
return static_cast<uint8_t>(0);
};
void FunctionStackPoisoner::copyToShadow(ArrayRef<uint8_t> ShadowMask,
ArrayRef<uint8_t> ShadowBytes,
IRBuilder<> &IRB, Value *ShadowBase) {
copyToShadow(ShadowMask, ShadowBytes, 0, ShadowMask.size(), IRB, ShadowBase);
}
const size_t End = ShadowBytes.size();
size_t Done = 0;
for (size_t i = 0, j = 1; i < End; i = j++) {
if (!ShadowBytes[i])
void FunctionStackPoisoner::copyToShadow(ArrayRef<uint8_t> ShadowMask,
ArrayRef<uint8_t> ShadowBytes,
size_t Begin, size_t End,
IRBuilder<> &IRB, Value *ShadowBase) {
assert(ShadowMask.size() == ShadowBytes.size());
size_t Done = Begin;
for (size_t i = Begin, j = Begin + 1; i < End; i = j++) {
if (!ShadowMask[i]) {
assert(!ShadowBytes[i]);
continue;
uint8_t Val = ValueToWrite(i);
}
uint8_t Val = ShadowBytes[i];
if (!AsanSetShadowFunc[Val])
continue;
// Skip same values.
for (; j < End && ShadowBytes[j] && Val == ValueToWrite(j); ++j) {
for (; j < End && ShadowMask[j] && Val == ShadowBytes[j]; ++j) {
}
if (j - i >= ClMaxInlinePoisoningSize) {
poisonStackFrameInline(ShadowBytes, Done, i, IRB, ShadowBase, DoPoison);
copyToShadowInline(ShadowMask, ShadowBytes, Done, i, IRB, ShadowBase);
IRB.CreateCall(AsanSetShadowFunc[Val],
{IRB.CreateAdd(ShadowBase, ConstantInt::get(IntptrTy, i)),
ConstantInt::get(IntptrTy, j - i)});
@ -2049,7 +2053,7 @@ void FunctionStackPoisoner::poisonStackFrame(ArrayRef<uint8_t> ShadowBytes,
}
}
poisonStackFrameInline(ShadowBytes, Done, End, IRB, ShadowBase, DoPoison);
copyToShadowInline(ShadowMask, ShadowBytes, Done, End, IRB, ShadowBase);
}
// Fake stack allocator (asan_fake_stack.h) has 11 size classes
@ -2155,23 +2159,33 @@ void FunctionStackPoisoner::processStaticAllocas() {
// If we have a call to llvm.localescape, keep it in the entry block.
if (LocalEscapeCall) LocalEscapeCall->moveBefore(InsBefore);
// Insert poison calls for lifetime intrinsics for static allocas.
// Find static allocas with lifetime analysis.
DenseMap<const AllocaInst *, const ASanStackVariableDescription *>
AllocaToSVDMap;
for (const auto &APC : StaticAllocaPoisonCallVec) {
assert(APC.InsBefore);
assert(APC.AI);
assert(ASan.isInterestingAlloca(*APC.AI));
assert(APC.AI->isStaticAlloca());
IRBuilder<> IRB(APC.InsBefore);
poisonAlloca(APC.AI, APC.Size, IRB, APC.DoPoison);
if (ClExperimentalPoisoning) {
AllocaToSVDMap[APC.AI] = nullptr;
} else {
IRBuilder<> IRB(APC.InsBefore);
poisonAlloca(APC.AI, APC.Size, IRB, APC.DoPoison);
}
}
SmallVector<ASanStackVariableDescription, 16> SVD;
SVD.reserve(AllocaVec.size());
for (AllocaInst *AI : AllocaVec) {
size_t UseAfterScopePoisonSize =
AllocaToSVDMap.find(AI) != AllocaToSVDMap.end()
? ASan.getAllocaSizeInBytes(*AI)
: 0;
ASanStackVariableDescription D = {AI->getName().data(),
ASan.getAllocaSizeInBytes(*AI),
0,
UseAfterScopePoisonSize,
AI->getAlignment(),
AI,
0};
@ -2182,8 +2196,7 @@ void FunctionStackPoisoner::processStaticAllocas() {
size_t MinHeaderSize = ASan.LongSize / 2;
const ASanStackFrameLayout &L =
ComputeASanStackFrameLayout(SVD, 1ULL << Mapping.Scale, MinHeaderSize);
const SmallVector<uint8_t, 64> &ShadowBytes =
GetShadowBytesAfterScope(SVD, L);
DEBUG(dbgs() << L.DescriptionString << " --- " << L.FrameSize << "\n");
uint64_t LocalStackSize = L.FrameSize;
bool DoStackMalloc = ClUseAfterReturn && !ASan.CompileKernel &&
@ -2278,22 +2291,55 @@ void FunctionStackPoisoner::processStaticAllocas() {
IntptrPtrTy);
IRB.CreateStore(IRB.CreatePointerCast(&F, IntptrTy), BasePlus2);
// Poison the stack redzones at the entry.
const auto &ShadowAfterScope = GetShadowBytesAfterScope(SVD, L);
// Poison the stack red zones at the entry.
Value *ShadowBase = ASan.memToShadow(LocalStackBase, IRB);
poisonStackFrame(ShadowBytes, IRB, ShadowBase, true);
// As mask we must use most poisoned case: red zones and after scope.
// As bytes we can use either the same or just red zones only.
copyToShadow(ShadowAfterScope, ShadowAfterScope, IRB, ShadowBase);
if (ClExperimentalPoisoning && !StaticAllocaPoisonCallVec.empty()) {
// Complete AllocaToSVDMap
for (const auto &Desc : SVD) {
auto It = AllocaToSVDMap.find(Desc.AI);
if (It != AllocaToSVDMap.end()) {
It->second = &Desc;
}
}
const auto &ShadowInScope = GetShadowBytes(SVD, L);
// Poison static allocas near lifetime intrinsics.
for (const auto &APC : StaticAllocaPoisonCallVec) {
// Must be already set.
assert(AllocaToSVDMap[APC.AI]);
const auto &Desc = *AllocaToSVDMap[APC.AI];
assert(Desc.Offset % L.Granularity == 0);
size_t Begin = Desc.Offset / L.Granularity;
size_t End = Begin + (APC.Size + L.Granularity - 1) / L.Granularity;
IRBuilder<> IRB(APC.InsBefore);
copyToShadow(ShadowAfterScope,
APC.DoPoison ? ShadowAfterScope : ShadowInScope, Begin, End,
IRB, ShadowBase);
}
}
SmallVector<uint8_t, 64> ShadowClean(ShadowAfterScope.size(), 0);
auto UnpoisonStack = [&](IRBuilder<> &IRB) {
// Do this always as poisonAlloca can be disabled with
// detect_stack_use_after_scope=0.
poisonStackFrame(ShadowBytes, IRB, ShadowBase, false);
if (!StaticAllocaPoisonCallVec.empty()) {
copyToShadow(ShadowAfterScope, ShadowClean, IRB, ShadowBase);
if (!ClExperimentalPoisoning && !StaticAllocaPoisonCallVec.empty()) {
// If we poisoned some allocas in llvm.lifetime analysis,
// unpoison whole stack frame now.
poisonAlloca(LocalStackBase, LocalStackSize, IRB, false);
}
};
SmallVector<uint8_t, 64> ShadowBytesAfterReturn;
SmallVector<uint8_t, 64> ShadowAfterReturn;
// (Un)poison the stack before all ret instructions.
for (auto Ret : RetVec) {
@ -2321,9 +2367,10 @@ void FunctionStackPoisoner::processStaticAllocas() {
IRBuilder<> IRBPoison(ThenTerm);
if (StackMallocIdx <= 4) {
int ClassSize = kMinStackMallocSize << StackMallocIdx;
ShadowBytesAfterReturn.resize(ClassSize >> Mapping.Scale,
kAsanStackUseAfterReturnMagic);
poisonStackFrame(ShadowBytesAfterReturn, IRBPoison, ShadowBase, true);
ShadowAfterReturn.resize(ClassSize / L.Granularity,
kAsanStackUseAfterReturnMagic);
copyToShadow(ShadowAfterReturn, ShadowAfterReturn, IRBPoison,
ShadowBase);
Value *SavedFlagPtrPtr = IRBPoison.CreateAdd(
FakeStack,
ConstantInt::get(IntptrTy, ClassSize - ASan.LongSize / 8));

View File

@ -0,0 +1,324 @@
; Test check the following function parts: ENTRY, LIFE (lifetime), FAKE (fake stack) and EXIT.
; Test each part can have prefix: no prefix (regular), UAS (use-after-scope), EXP (new poisoning) and UAS-EXP (use-after-scope with new poisoning)
; Regular stack poisoning.
; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning=0 -asan-use-after-scope=0 -S | FileCheck --check-prefixes=CHECK,ENTRY,LIFE,FAKE,EXIT %s
; Optimized poisoning. Only fake stack part is different from the first test.
; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning=1 -asan-use-after-scope=0 -S | FileCheck --check-prefixes=CHECK,ENTRY,LIFE,FAKE-EXP,EXIT %s
; Regular stack poisoning with stack-use-after-scope. Only lifetime checks are different from the first test.
; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning=0 -asan-use-after-scope=1 -S | FileCheck --check-prefixes=CHECK,ENTRY,LIFE-UAS,FAKE,EXIT %s
; Optimized poisoning with stack-use-after-scope.
; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning=1 -asan-use-after-scope=1 -S | FileCheck --check-prefixes=CHECK,ENTRY-UAS-EXP,LIFE-UAS-EXP,FAKE-EXP,EXIT-EXP %s
target datalayout = "E-m:e-i64:64-n32:64"
target triple = "powerpc64-unknown-linux-gnu"
declare void @Foo(i8*)
define void @Bar() uwtable sanitize_address {
entry:
%x = alloca [650 x i8], align 16
%xx = getelementptr inbounds [650 x i8], [650 x i8]* %x, i64 0, i64 0
%y = alloca [13 x i8], align 1
%yy = getelementptr inbounds [13 x i8], [13 x i8]* %y, i64 0, i64 0
%z = alloca [40 x i8], align 1
%zz = getelementptr inbounds [40 x i8], [40 x i8]* %z, i64 0, i64 0
; CHECK: [[SHADOW_BASE:%[0-9]+]] = add i64 %{{[0-9]+}}, 2199023255552
; F1F1F1F1
; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
; ENTRY-NEXT: store [[TYPE]] -235802127, [[TYPE]]* [[PTR]], align 1
; 02F2F2F2F2F2F2F2
; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 85
; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; ENTRY-NEXT: store [[TYPE]] 212499257711850226, [[TYPE]]* [[PTR]], align 1
; F2F2F2F2F2F2F2F2
; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 93
; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; ENTRY-NEXT: store [[TYPE]] -940422246894996750, [[TYPE]]* [[PTR]], align 1
; F20005F2F2000000
; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 101
; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; ENTRY-NEXT: store [[TYPE]] -1008799775530680320, [[TYPE]]* [[PTR]], align 1
; F3F3F3F3
; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 111
; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
; ENTRY-NEXT: store [[TYPE]] -202116109, [[TYPE]]* [[PTR]], align 1
; F3
; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 115
; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
; ENTRY-NEXT: store [[TYPE]] -13, [[TYPE]]* [[PTR]], align 1
; F1F1F1F1
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -235802127, [[TYPE]]* [[PTR]], align 1
; F8F8F8...
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 4
; ENTRY-UAS-EXP-NEXT: call void @__asan_set_shadow_f8(i64 [[OFFSET]], i64 82)
; F2F2F2F2F2F2F2F2
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 86
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -940422246894996750, [[TYPE]]* [[PTR]], align 1
; F2F2F2F2F2F2F2F2
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 94
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -940422246894996750, [[TYPE]]* [[PTR]], align 1
; F8F8F2F2F8F8F8F8
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 102
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -506387832706107144, [[TYPE]]* [[PTR]], align 1
; F8F3F3F3
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 110
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -118230029, [[TYPE]]* [[PTR]], align 1
; F3F3
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 114
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i16]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -3085, [[TYPE]]* [[PTR]], align 1
; CHECK-LABEL: %xx = getelementptr inbounds
; CHECK-NEXT: %yy = getelementptr inbounds
; CHECK-NEXT: %zz = getelementptr inbounds
call void @llvm.lifetime.start(i64 650, i8* %xx)
; LIFE-UAS: call void @__asan_unpoison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE:650]])
; 0000...
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 4
; ENTRY-UAS-EXP-NEXT: call void @__asan_set_shadow_00(i64 [[OFFSET]], i64 81)
; 02
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 85
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] 2, [[TYPE]]* [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.start(i64 650, i8* %xx)
call void @Foo(i8* %xx)
; CHECK-NEXT: call void @Foo(i8* %xx)
call void @llvm.lifetime.end(i64 650, i8* %xx)
; LIFE-UAS: call void @__asan_poison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE]])
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 4
; ENTRY-UAS-EXP-NEXT: call void @__asan_set_shadow_f8(i64 [[OFFSET]], i64 82)
; CHECK-NEXT: call void @llvm.lifetime.end(i64 650, i8* %xx)
call void @llvm.lifetime.start(i64 13, i8* %yy)
; LIFE-UAS: call void @__asan_unpoison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE:13]])
; 0005
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 102
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i16]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] 5, [[TYPE]]* [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.start(i64 13, i8* %yy)
call void @Foo(i8* %yy)
; CHECK-NEXT: call void @Foo(i8* %yy)
call void @llvm.lifetime.end(i64 13, i8* %yy)
; LIFE-UAS: call void @__asan_poison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE]])
; F8F8
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 102
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i16]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -1800, [[TYPE]]* [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.end(i64 13, i8* %yy)
call void @llvm.lifetime.start(i64 40, i8* %zz)
; LIFE-UAS: call void @__asan_unpoison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE:40]])
; 00000000
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 106
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
; 00
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 110
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.start(i64 40, i8* %zz)
call void @Foo(i8* %zz)
; CHECK-NEXT: call void @Foo(i8* %zz)
call void @llvm.lifetime.end(i64 40, i8* %zz)
; LIFE-UAS: call void @__asan_poison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE]])
; F8F8F8F8
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 106
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -117901064, [[TYPE]]* [[PTR]], align 1
; F8
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 110
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -8, [[TYPE]]* [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.end(i64 40, i8* %zz)
; CHECK-LABEL: <label>
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 8
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 16
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 24
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 32
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 40
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 48
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 56
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 64
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 72
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 80
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 88
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 96
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 104
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 112
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 120
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; FAKE-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
; FAKE-EXP-NEXT: call void @__asan_set_shadow_f5(i64 [[OFFSET]], i64 128)
; CHECK-NOT: add i64 [[SHADOW_BASE]]
; CHECK-LABEL: <label>
; 00000000
; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
; 0000000000000000
; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 85
; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
; 0000000000000000
; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 93
; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
; 0000000000000000
; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 101
; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
; 00000000
; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 111
; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
; 00
; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 115
; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
; 0000...
; EXIT-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
; EXIT-EXP-NEXT: call void @__asan_set_shadow_00(i64 [[OFFSET]], i64 116)
; CHECK-NOT: add i64 [[SHADOW_BASE]]
ret void
; CHECK-LABEL: <label>
; CHECK: ret void
}
declare void @llvm.lifetime.start(i64, i8* nocapture)
declare void @llvm.lifetime.end(i64, i8* nocapture)
; CHECK-ON: declare void @__asan_set_shadow_00(i64, i64)
; CHECK-ON: declare void @__asan_set_shadow_f1(i64, i64)
; CHECK-ON: declare void @__asan_set_shadow_f2(i64, i64)
; CHECK-ON: declare void @__asan_set_shadow_f3(i64, i64)
; CHECK-ON: declare void @__asan_set_shadow_f5(i64, i64)
; CHECK-ON: declare void @__asan_set_shadow_f8(i64, i64)
; CHECK-OFF-NOT: declare void @__asan_set_shadow_

View File

@ -1,5 +1,17 @@
; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning -S | FileCheck --check-prefixes=CHECK-ON,CHECK %s
; RUN: opt < %s -asan -asan-module -S | FileCheck --check-prefixes=CHECK-OFF,CHECK %s
; Test check the following function parts: ENTRY, LIFE (lifetime), FAKE (fake stack) and EXIT.
; Test each part can have prefix: no prefix (regular), UAS (use-after-scope), EXP (new poisoning) and UAS-EXP (use-after-scope with new poisoning)
; Regular stack poisoning.
; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning=0 -asan-use-after-scope=0 -S | FileCheck --check-prefixes=CHECK,ENTRY,LIFE,FAKE,EXIT %s
; Optimized poisoning. Only fake stack part is different from the first test.
; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning=1 -asan-use-after-scope=0 -S | FileCheck --check-prefixes=CHECK,ENTRY,LIFE,FAKE-EXP,EXIT %s
; Regular stack poisoning with stack-use-after-scope. Only lifetime checks are different from the first test.
; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning=0 -asan-use-after-scope=1 -S | FileCheck --check-prefixes=CHECK,ENTRY,LIFE-UAS,FAKE,EXIT %s
; Optimized poisoning with stack-use-after-scope.
; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning=1 -asan-use-after-scope=1 -S | FileCheck --check-prefixes=CHECK,ENTRY-UAS-EXP,LIFE-UAS-EXP,FAKE-EXP,EXIT-EXP %s
target datalayout = "e-i64:64-f80:128-s:64-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@ -8,47 +20,300 @@ declare void @Foo(i8*)
define void @Bar() uwtable sanitize_address {
entry:
; CHECK: store i32 -235802127
; CHECK: store i64 -868082074056920318
; CHECK: store i64 -868082074056920077
; CHECK: store i16 -3085
; CHECK: store i8 -13
; CHECK-LABEL: call void @Foo
; CHECK-LABEL: <label>
; CHECK-ON-NOT: store i64
; CHECK-ON: call void @__asan_set_shadow_f5(i64 %{{[0-9]+}}, i64 128)
; CHECK-OFF-NOT: call void @__asan_set_shadow_f5
; CHECK-OFF: store i64 -723401728380766731
; CHECK-OFF: store i64 -723401728380766731
; CHECK-OFF: store i64 -723401728380766731
; CHECK-OFF: store i64 -723401728380766731
; CHECK-OFF: store i64 -723401728380766731
; CHECK-OFF: store i64 -723401728380766731
; CHECK-OFF: store i64 -723401728380766731
; CHECK-OFF: store i64 -723401728380766731
; CHECK-OFF: store i64 -723401728380766731
; CHECK-OFF: store i64 -723401728380766731
; And more...
%x = alloca [650 x i8], align 16
%xx = getelementptr inbounds [650 x i8], [650 x i8]* %x, i64 0, i64 0
%y = alloca [13 x i8], align 1
%yy = getelementptr inbounds [13 x i8], [13 x i8]* %y, i64 0, i64 0
%z = alloca [40 x i8], align 1
%zz = getelementptr inbounds [40 x i8], [40 x i8]* %z, i64 0, i64 0
; CHECK: [[SHADOW_BASE:%[0-9]+]] = add i64 %{{[0-9]+}}, 2147450880
; F1F1F1F1
; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
; ENTRY-NEXT: store [[TYPE]] -235802127, [[TYPE]]* [[PTR]], align 1
; 02F2F2F2F2F2F2F2
; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 85
; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; ENTRY-NEXT: store [[TYPE]] -940422246894996990, [[TYPE]]* [[PTR]], align 1
; F2F2F2F2F2F2F2F2
; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 93
; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; ENTRY-NEXT: store [[TYPE]] -940422246894996750, [[TYPE]]* [[PTR]], align 1
; F20005F2F2000000
; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 101
; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; ENTRY-NEXT: store [[TYPE]] 1043442499826, [[TYPE]]* [[PTR]], align 1
; F3F3F3F3
; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 111
; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
; ENTRY-NEXT: store [[TYPE]] -202116109, [[TYPE]]* [[PTR]], align 1
; F3
; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 115
; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
; ENTRY-NEXT: store [[TYPE]] -13, [[TYPE]]* [[PTR]], align 1
; F1F1F1F1
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -235802127, [[TYPE]]* [[PTR]], align 1
; F8F8F8...
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 4
; ENTRY-UAS-EXP-NEXT: call void @__asan_set_shadow_f8(i64 [[OFFSET]], i64 82)
; F2F2F2F2F2F2F2F2
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 86
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -940422246894996750, [[TYPE]]* [[PTR]], align 1
; F2F2F2F2F2F2F2F2
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 94
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -940422246894996750, [[TYPE]]* [[PTR]], align 1
; F8F8F2F2F8F8F8F8
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 102
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -506381209967593224, [[TYPE]]* [[PTR]], align 1
; F8F3F3F3
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 110
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -202116104, [[TYPE]]* [[PTR]], align 1
; F3F3
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 114
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i16]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -3085, [[TYPE]]* [[PTR]], align 1
; CHECK-LABEL: %xx = getelementptr inbounds
; CHECK-NEXT: %yy = getelementptr inbounds
; CHECK-NEXT: %zz = getelementptr inbounds
call void @llvm.lifetime.start(i64 650, i8* %xx)
; LIFE-UAS: call void @__asan_unpoison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE:650]])
; 0000...
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 4
; ENTRY-UAS-EXP-NEXT: call void @__asan_set_shadow_00(i64 [[OFFSET]], i64 81)
; 02
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 85
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] 2, [[TYPE]]* [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.start(i64 650, i8* %xx)
call void @Foo(i8* %xx)
; CHECK-NEXT: call void @Foo(i8* %xx)
call void @llvm.lifetime.end(i64 650, i8* %xx)
; LIFE-UAS: call void @__asan_poison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE]])
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 4
; ENTRY-UAS-EXP-NEXT: call void @__asan_set_shadow_f8(i64 [[OFFSET]], i64 82)
; CHECK-NEXT: call void @llvm.lifetime.end(i64 650, i8* %xx)
call void @llvm.lifetime.start(i64 13, i8* %yy)
; LIFE-UAS: call void @__asan_unpoison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE:13]])
; 0005
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 102
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i16]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] 1280, [[TYPE]]* [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.start(i64 13, i8* %yy)
call void @Foo(i8* %yy)
; CHECK-NEXT: call void @Foo(i8* %yy)
call void @llvm.lifetime.end(i64 13, i8* %yy)
; LIFE-UAS: call void @__asan_poison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE]])
; F8F8
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 102
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i16]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -1800, [[TYPE]]* [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.end(i64 13, i8* %yy)
call void @llvm.lifetime.start(i64 40, i8* %zz)
; LIFE-UAS: call void @__asan_unpoison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE:40]])
; 00000000
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 106
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
; 00
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 110
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.start(i64 40, i8* %zz)
call void @Foo(i8* %zz)
; CHECK-NEXT: call void @Foo(i8* %zz)
call void @llvm.lifetime.end(i64 40, i8* %zz)
; LIFE-UAS: call void @__asan_poison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE]])
; F8F8F8F8
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 106
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -117901064, [[TYPE]]* [[PTR]], align 1
; F8
; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 110
; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -8, [[TYPE]]* [[PTR]], align 1
; CHECK-NEXT: call void @llvm.lifetime.end(i64 40, i8* %zz)
; CHECK-LABEL: <label>
; CHECK-NOT: call void @__asan_set_shadow_00
; CHECK: store i32 0
; CHECK: store i64 0
; CHECK: store i64 0
; CHECK: store i16 0
; CHECK: store i8 0
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 8
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 16
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 24
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 32
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 40
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 48
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 56
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 64
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 72
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 80
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 88
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 96
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 104
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 112
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; F5F5F5F5F5F5F5F5
; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 120
; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
; FAKE-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
; FAKE-EXP-NEXT: call void @__asan_set_shadow_f5(i64 [[OFFSET]], i64 128)
; CHECK-NOT: add i64 [[SHADOW_BASE]]
; CHECK-LABEL: <label>
; 00000000
; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
; 0000000000000000
; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 85
; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
; 0000000000000000
; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 93
; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
; 0000000000000000
; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 101
; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
; 00000000
; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 111
; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
; 00
; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 115
; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
; 0000...
; EXIT-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
; EXIT-EXP-NEXT: call void @__asan_set_shadow_00(i64 [[OFFSET]], i64 116)
; CHECK-NOT: add i64 [[SHADOW_BASE]]
ret void
; CHECK-LABEL: <label>
; CHECK: ret void
%x = alloca [650 x i8], align 16
%arraydecay = getelementptr inbounds [650 x i8], [650 x i8]* %x, i64 0, i64 0
call void @Foo(i8* %arraydecay)
ret void
}
declare void @llvm.lifetime.start(i64, i8* nocapture)
declare void @llvm.lifetime.end(i64, i8* nocapture)
; CHECK-ON: declare void @__asan_set_shadow_00(i64, i64)
; CHECK-ON: declare void @__asan_set_shadow_f1(i64, i64)
; CHECK-ON: declare void @__asan_set_shadow_f2(i64, i64)