1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 11:02:59 +02:00

[ASan] Make ASan instrument variable-masked loads and stores

Summary: Previously we only supported constant-masked loads and stores.

Reviewers: kcc, RKSimon, pgousseau, gbedwell, vitalybuka

Subscribers: llvm-commits

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

llvm-svn: 291238
This commit is contained in:
Filipe Cabecinhas 2017-01-06 15:24:51 +00:00
parent a949cf108b
commit 368bad5905
2 changed files with 129 additions and 43 deletions

View File

@ -514,7 +514,8 @@ struct AddressSanitizer : public FunctionPass {
void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore,
Value *Addr, uint32_t TypeSize, bool IsWrite,
Value *SizeArgument, bool UseCalls, uint32_t Exp);
void instrumentUnusualSizeOrAlignment(Instruction *I, Value *Addr,
void instrumentUnusualSizeOrAlignment(Instruction *I,
Instruction *InsertBefore, Value *Addr,
uint32_t TypeSize, bool IsWrite,
Value *SizeArgument, bool UseCalls,
uint32_t Exp);
@ -1056,20 +1057,18 @@ Value *AddressSanitizer::isInterestingMemoryAccess(Instruction *I,
return nullptr;
*IsWrite = false;
}
// Only instrument if the mask is constant for now.
if (isa<ConstantVector>(CI->getOperand(2 + OpOffset))) {
auto BasePtr = CI->getOperand(0 + OpOffset);
auto Ty = cast<PointerType>(BasePtr->getType())->getElementType();
*TypeSize = DL.getTypeStoreSizeInBits(Ty);
if (auto AlignmentConstant =
dyn_cast<ConstantInt>(CI->getOperand(1 + OpOffset)))
*Alignment = (unsigned)AlignmentConstant->getZExtValue();
else
*Alignment = 1; // No alignment guarantees. We probably got Undef
if (MaybeMask)
*MaybeMask = CI->getOperand(2 + OpOffset);
PtrOperand = BasePtr;
}
auto BasePtr = CI->getOperand(0 + OpOffset);
auto Ty = cast<PointerType>(BasePtr->getType())->getElementType();
*TypeSize = DL.getTypeStoreSizeInBits(Ty);
if (auto AlignmentConstant =
dyn_cast<ConstantInt>(CI->getOperand(1 + OpOffset)))
*Alignment = (unsigned)AlignmentConstant->getZExtValue();
else
*Alignment = 1; // No alignment guarantees. We probably got Undef
if (MaybeMask)
*MaybeMask = CI->getOperand(2 + OpOffset);
PtrOperand = BasePtr;
}
}
@ -1130,24 +1129,25 @@ void AddressSanitizer::instrumentPointerComparisonOrSubtraction(
}
static void doInstrumentAddress(AddressSanitizer *Pass, Instruction *I,
Value *Addr, unsigned Alignment,
unsigned Granularity, uint32_t TypeSize,
bool IsWrite, Value *SizeArgument,
bool UseCalls, uint32_t Exp) {
Instruction *InsertBefore, Value *Addr,
unsigned Alignment, unsigned Granularity,
uint32_t TypeSize, bool IsWrite,
Value *SizeArgument, bool UseCalls,
uint32_t Exp) {
// Instrument a 1-, 2-, 4-, 8-, or 16- byte access with one check
// if the data is properly aligned.
if ((TypeSize == 8 || TypeSize == 16 || TypeSize == 32 || TypeSize == 64 ||
TypeSize == 128) &&
(Alignment >= Granularity || Alignment == 0 || Alignment >= TypeSize / 8))
return Pass->instrumentAddress(I, I, Addr, TypeSize, IsWrite, nullptr,
UseCalls, Exp);
Pass->instrumentUnusualSizeOrAlignment(I, Addr, TypeSize, IsWrite, nullptr,
UseCalls, Exp);
return Pass->instrumentAddress(I, InsertBefore, Addr, TypeSize, IsWrite,
nullptr, UseCalls, Exp);
Pass->instrumentUnusualSizeOrAlignment(I, InsertBefore, Addr, TypeSize,
IsWrite, nullptr, UseCalls, Exp);
}
static void instrumentMaskedLoadOrStore(AddressSanitizer *Pass,
const DataLayout &DL, Type *IntptrTy,
ConstantVector *Mask, Instruction *I,
Value *Mask, Instruction *I,
Value *Addr, unsigned Alignment,
unsigned Granularity, uint32_t TypeSize,
bool IsWrite, Value *SizeArgument,
@ -1157,15 +1157,30 @@ static void instrumentMaskedLoadOrStore(AddressSanitizer *Pass,
unsigned Num = VTy->getVectorNumElements();
auto Zero = ConstantInt::get(IntptrTy, 0);
for (unsigned Idx = 0; Idx < Num; ++Idx) {
// dyn_cast as we might get UndefValue
auto Masked = dyn_cast<ConstantInt>(Mask->getOperand(Idx));
if (Masked && Masked->isAllOnesValue()) {
Value *InstrumentedAddress = nullptr;
Instruction *InsertBefore = I;
if (auto *Vector = dyn_cast<ConstantVector>(Mask)) {
// dyn_cast as we might get UndefValue
if (auto *Masked = dyn_cast<ConstantInt>(Vector->getOperand(Idx))) {
if (Masked->isNullValue())
// Mask is constant false, so no instrumentation needed.
continue;
// If we have a true or undef value, fall through to doInstrumentAddress
// with InsertBefore == I
}
} else {
IRBuilder<> IRB(I);
auto InstrumentedAddress =
IRB.CreateGEP(Addr, {Zero, ConstantInt::get(IntptrTy, Idx)});
doInstrumentAddress(Pass, I, InstrumentedAddress, Alignment, Granularity,
ElemTypeSize, IsWrite, SizeArgument, UseCalls, Exp);
Value *MaskElem = IRB.CreateExtractElement(Mask, Idx);
TerminatorInst *ThenTerm = SplitBlockAndInsertIfThen(MaskElem, I, false);
InsertBefore = ThenTerm;
}
IRBuilder<> IRB(InsertBefore);
InstrumentedAddress =
IRB.CreateGEP(Addr, {Zero, ConstantInt::get(IntptrTy, Idx)});
doInstrumentAddress(Pass, I, InsertBefore, InstrumentedAddress, Alignment,
Granularity, ElemTypeSize, IsWrite, SizeArgument,
UseCalls, Exp);
}
}
@ -1220,12 +1235,11 @@ void AddressSanitizer::instrumentMop(ObjectSizeOffsetVisitor &ObjSizeVis,
unsigned Granularity = 1 << Mapping.Scale;
if (MaybeMask) {
auto Mask = cast<ConstantVector>(MaybeMask);
instrumentMaskedLoadOrStore(this, DL, IntptrTy, Mask, I, Addr, Alignment,
Granularity, TypeSize, IsWrite, nullptr,
UseCalls, Exp);
instrumentMaskedLoadOrStore(this, DL, IntptrTy, MaybeMask, I, Addr,
Alignment, Granularity, TypeSize, IsWrite,
nullptr, UseCalls, Exp);
} else {
doInstrumentAddress(this, I, Addr, Alignment, Granularity, TypeSize,
doInstrumentAddress(this, I, I, Addr, Alignment, Granularity, TypeSize,
IsWrite, nullptr, UseCalls, Exp);
}
}
@ -1342,9 +1356,9 @@ void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
// and the last bytes. We call __asan_report_*_n(addr, real_size) to be able
// to report the actual access size.
void AddressSanitizer::instrumentUnusualSizeOrAlignment(
Instruction *I, Value *Addr, uint32_t TypeSize, bool IsWrite,
Value *SizeArgument, bool UseCalls, uint32_t Exp) {
IRBuilder<> IRB(I);
Instruction *I, Instruction *InsertBefore, Value *Addr, uint32_t TypeSize,
bool IsWrite, Value *SizeArgument, bool UseCalls, uint32_t Exp) {
IRBuilder<> IRB(InsertBefore);
Value *Size = ConstantInt::get(IntptrTy, TypeSize / 8);
Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
if (UseCalls) {
@ -1358,8 +1372,8 @@ void AddressSanitizer::instrumentUnusualSizeOrAlignment(
Value *LastByte = IRB.CreateIntToPtr(
IRB.CreateAdd(AddrLong, ConstantInt::get(IntptrTy, TypeSize / 8 - 1)),
Addr->getType());
instrumentAddress(I, I, Addr, 8, IsWrite, Size, false, Exp);
instrumentAddress(I, I, LastByte, 8, IsWrite, Size, false, Exp);
instrumentAddress(I, InsertBefore, Addr, 8, IsWrite, Size, false, Exp);
instrumentAddress(I, InsertBefore, LastByte, 8, IsWrite, Size, false, Exp);
}
}

View File

@ -73,7 +73,43 @@ define void @store.v4i64.0001(<4 x i32*> %arg) sanitize_address {
define void @store.v4f32.variable(<4 x float> %arg, <4 x i1> %mask) sanitize_address {
; ALL-LABEL: @store.v4f32.variable
%p = load <4 x float>*, <4 x float>** @v4f32, align 8
; ALL-NOT: call void @__asan_store
; STORE: [[MASK0:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 0
; STORE: br i1 [[MASK0]], label %[[THEN0:[0-9A-Za-z]+]], label %[[AFTER0:[0-9A-Za-z]+]]
; STORE: <label>:[[THEN0]]:
; STORE: [[GEP0:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 0
; STORE: [[PGEP0:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP0]] to i64
; STORE: call void @__asan_store4(i64 [[PGEP0]])
; STORE: br label %[[AFTER0]]
; STORE: <label>:[[AFTER0]]
; STORE: [[MASK1:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 1
; STORE: br i1 [[MASK1]], label %[[THEN1:[0-9A-Za-z]+]], label %[[AFTER1:[0-9A-Za-z]+]]
; STORE: <label>:[[THEN1]]:
; STORE: [[GEP1:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 1
; STORE: [[PGEP1:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP1]] to i64
; STORE: call void @__asan_store4(i64 [[PGEP1]])
; STORE: br label %[[AFTER1]]
; STORE: <label>:[[AFTER1]]
; STORE: [[MASK2:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 2
; STORE: br i1 [[MASK2]], label %[[THEN2:[0-9A-Za-z]+]], label %[[AFTER2:[0-9A-Za-z]+]]
; STORE: <label>:[[THEN2]]:
; STORE: [[GEP2:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 2
; STORE: [[PGEP2:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP2]] to i64
; STORE: call void @__asan_store4(i64 [[PGEP2]])
; STORE: br label %[[AFTER2]]
; STORE: <label>:[[AFTER2]]
; STORE: [[MASK3:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 3
; STORE: br i1 [[MASK3]], label %[[THEN3:[0-9A-Za-z]+]], label %[[AFTER3:[0-9A-Za-z]+]]
; STORE: <label>:[[THEN3]]:
; STORE: [[GEP3:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 3
; STORE: [[PGEP3:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP3]] to i64
; STORE: call void @__asan_store4(i64 [[PGEP3]])
; STORE: br label %[[AFTER3]]
; STORE: <label>:[[AFTER3]]
; STORE: tail call void @llvm.masked.store.v4f32.p0v4f32(<4 x float> %arg, <4 x float>* %p, i32 4, <4 x i1> %mask)
tail call void @llvm.masked.store.v4f32.p0v4f32(<4 x float> %arg, <4 x float>* %p, i32 4, <4 x i1> %mask)
ret void
}
@ -165,7 +201,43 @@ define <4 x i32*> @load.v4i64.0001(<4 x i32*> %arg) sanitize_address {
define <4 x float> @load.v4f32.variable(<4 x float> %arg, <4 x i1> %mask) sanitize_address {
; ALL-LABEL: @load.v4f32.variable
%p = load <4 x float>*, <4 x float>** @v4f32, align 8
; ALL-NOT: call void @__asan_load
; LOAD: [[MASK0:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 0
; LOAD: br i1 [[MASK0]], label %[[THEN0:[0-9A-Za-z]+]], label %[[AFTER0:[0-9A-Za-z]+]]
; LOAD: <label>:[[THEN0]]:
; LOAD: [[GEP0:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 0
; LOAD: [[PGEP0:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP0]] to i64
; LOAD: call void @__asan_load4(i64 [[PGEP0]])
; LOAD: br label %[[AFTER0]]
; LOAD: <label>:[[AFTER0]]
; LOAD: [[MASK1:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 1
; LOAD: br i1 [[MASK1]], label %[[THEN1:[0-9A-Za-z]+]], label %[[AFTER1:[0-9A-Za-z]+]]
; LOAD: <label>:[[THEN1]]:
; LOAD: [[GEP1:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 1
; LOAD: [[PGEP1:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP1]] to i64
; LOAD: call void @__asan_load4(i64 [[PGEP1]])
; LOAD: br label %[[AFTER1]]
; LOAD: <label>:[[AFTER1]]
; LOAD: [[MASK2:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 2
; LOAD: br i1 [[MASK2]], label %[[THEN2:[0-9A-Za-z]+]], label %[[AFTER2:[0-9A-Za-z]+]]
; LOAD: <label>:[[THEN2]]:
; LOAD: [[GEP2:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 2
; LOAD: [[PGEP2:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP2]] to i64
; LOAD: call void @__asan_load4(i64 [[PGEP2]])
; LOAD: br label %[[AFTER2]]
; LOAD: <label>:[[AFTER2]]
; LOAD: [[MASK3:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 3
; LOAD: br i1 [[MASK3]], label %[[THEN3:[0-9A-Za-z]+]], label %[[AFTER3:[0-9A-Za-z]+]]
; LOAD: <label>:[[THEN3]]:
; LOAD: [[GEP3:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 3
; LOAD: [[PGEP3:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP3]] to i64
; LOAD: call void @__asan_load4(i64 [[PGEP3]])
; LOAD: br label %[[AFTER3]]
; LOAD: <label>:[[AFTER3]]
; LOAD: tail call <4 x float> @llvm.masked.load.v4f32.p0v4f32(<4 x float>* %p, i32 4, <4 x i1> %mask, <4 x float> %arg)
%res = tail call <4 x float> @llvm.masked.load.v4f32.p0v4f32(<4 x float>* %p, i32 4, <4 x i1> %mask, <4 x float> %arg)
ret <4 x float> %res
}