forked from OSchip/llvm-project
[MSAN] Allow emitting checks for struct types
Differential Revision: https://reviews.llvm.org/D82680
This commit is contained in:
parent
7eb213499e
commit
3285b24249
|
@ -1149,11 +1149,11 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
|||
const DataLayout &DL = F.getParent()->getDataLayout();
|
||||
const Align OriginAlignment = std::max(kMinOriginAlignment, Alignment);
|
||||
unsigned StoreSize = DL.getTypeStoreSize(Shadow->getType());
|
||||
if (Shadow->getType()->isAggregateType()) {
|
||||
if (Shadow->getType()->isArrayTy()) {
|
||||
paintOrigin(IRB, updateOrigin(Origin, IRB), OriginPtr, StoreSize,
|
||||
OriginAlignment);
|
||||
} else {
|
||||
Value *ConvertedShadow = convertToShadowTyNoVec(Shadow, IRB);
|
||||
Value *ConvertedShadow = convertShadowToScalar(Shadow, IRB);
|
||||
if (auto *ConstantShadow = dyn_cast<Constant>(ConvertedShadow)) {
|
||||
if (ClCheckConstantShadow && !ConstantShadow->isZeroValue())
|
||||
paintOrigin(IRB, updateOrigin(Origin, IRB), OriginPtr, StoreSize,
|
||||
|
@ -1172,8 +1172,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
|||
IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()),
|
||||
Origin});
|
||||
} else {
|
||||
Value *Cmp = IRB.CreateICmpNE(
|
||||
ConvertedShadow, getCleanShadow(ConvertedShadow), "_mscmp");
|
||||
Value *Cmp = convertToBool(ConvertedShadow, IRB, "_mscmp");
|
||||
Instruction *CheckTerm = SplitBlockAndInsertIfThen(
|
||||
Cmp, &*IRB.GetInsertPoint(), false, MS.OriginStoreWeights);
|
||||
IRBuilder<> IRBNew(CheckTerm);
|
||||
|
@ -1224,7 +1223,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
|||
bool AsCall) {
|
||||
IRBuilder<> IRB(OrigIns);
|
||||
LLVM_DEBUG(dbgs() << " SHAD0 : " << *Shadow << "\n");
|
||||
Value *ConvertedShadow = convertToShadowTyNoVec(Shadow, IRB);
|
||||
Value *ConvertedShadow = convertShadowToScalar(Shadow, IRB);
|
||||
LLVM_DEBUG(dbgs() << " SHAD1 : " << *ConvertedShadow << "\n");
|
||||
|
||||
if (auto *ConstantShadow = dyn_cast<Constant>(ConvertedShadow)) {
|
||||
|
@ -1246,8 +1245,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
|||
? Origin
|
||||
: (Value *)IRB.getInt32(0)});
|
||||
} else {
|
||||
Value *Cmp = IRB.CreateICmpNE(ConvertedShadow,
|
||||
getCleanShadow(ConvertedShadow), "_mscmp");
|
||||
Value *Cmp = convertToBool(ConvertedShadow, IRB, "_mscmp");
|
||||
Instruction *CheckTerm = SplitBlockAndInsertIfThen(
|
||||
Cmp, OrigIns,
|
||||
/* Unreachable */ !MS.Recover, MS.ColdCallWeights);
|
||||
|
@ -1391,14 +1389,49 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
|||
return ty;
|
||||
}
|
||||
|
||||
/// Convert a shadow value to it's flattened variant.
|
||||
Value *convertToShadowTyNoVec(Value *V, IRBuilder<> &IRB) {
|
||||
/// Extract combined shadow of struct elements as a bool
|
||||
Value *collapseStructShadow(StructType *Struct, Value *Shadow,
|
||||
IRBuilder<> &IRB) {
|
||||
Value *FalseVal = IRB.getIntN(/* width */ 1, /* value */ 0);
|
||||
Value *Aggregator = FalseVal;
|
||||
|
||||
for (unsigned Idx = 0; Idx < Struct->getNumElements(); Idx++) {
|
||||
// Combine by ORing together each element's bool shadow
|
||||
Value *ShadowItem = IRB.CreateExtractValue(Shadow, Idx);
|
||||
Value *ShadowInner = convertShadowToScalar(ShadowItem, IRB);
|
||||
Value *ShadowBool = convertToBool(ShadowInner, IRB);
|
||||
|
||||
if (Aggregator != FalseVal)
|
||||
Aggregator = IRB.CreateOr(Aggregator, ShadowBool);
|
||||
else
|
||||
Aggregator = ShadowBool;
|
||||
}
|
||||
|
||||
return Aggregator;
|
||||
}
|
||||
|
||||
/// Convert a shadow value to it's flattened variant. The resulting
|
||||
/// shadow may not necessarily have the same bit width as the input
|
||||
/// value, but it will always be comparable to zero.
|
||||
Value *convertShadowToScalar(Value *V, IRBuilder<> &IRB) {
|
||||
if (StructType *Struct = dyn_cast<StructType>(V->getType()))
|
||||
return collapseStructShadow(Struct, V, IRB);
|
||||
Type *Ty = V->getType();
|
||||
Type *NoVecTy = getShadowTyNoVec(Ty);
|
||||
if (Ty == NoVecTy) return V;
|
||||
return IRB.CreateBitCast(V, NoVecTy);
|
||||
}
|
||||
|
||||
// Convert a scalar value to an i1 by comparing with 0
|
||||
Value *convertToBool(Value *V, IRBuilder<> &IRB, const Twine &name = "") {
|
||||
Type *VTy = V->getType();
|
||||
assert(VTy->isIntegerTy());
|
||||
if (VTy->getIntegerBitWidth() == 1)
|
||||
// Just converting a bool to a bool, so do nothing.
|
||||
return V;
|
||||
return IRB.CreateICmpNE(V, ConstantInt::get(VTy, 0), name);
|
||||
}
|
||||
|
||||
/// Compute the integer shadow offset that corresponds to a given
|
||||
/// application address.
|
||||
///
|
||||
|
@ -1732,8 +1765,10 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
|||
if (!InsertChecks) return;
|
||||
#ifndef NDEBUG
|
||||
Type *ShadowTy = Shadow->getType();
|
||||
assert((isa<IntegerType>(ShadowTy) || isa<VectorType>(ShadowTy)) &&
|
||||
"Can only insert checks for integer and vector shadow types");
|
||||
assert(
|
||||
(isa<IntegerType>(ShadowTy) || isa<VectorType>(ShadowTy) ||
|
||||
isa<StructType>(ShadowTy)) &&
|
||||
"Can only insert checks for integer, vector, and struct shadow types");
|
||||
#endif
|
||||
InstrumentationList.push_back(
|
||||
ShadowOriginAndInsertPoint(Shadow, Origin, OrigIns));
|
||||
|
@ -2088,7 +2123,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
|||
Constant *ConstOrigin = dyn_cast<Constant>(OpOrigin);
|
||||
// No point in adding something that might result in 0 origin value.
|
||||
if (!ConstOrigin || !ConstOrigin->isNullValue()) {
|
||||
Value *FlatShadow = MSV->convertToShadowTyNoVec(OpShadow, IRB);
|
||||
Value *FlatShadow = MSV->convertShadowToScalar(OpShadow, IRB);
|
||||
Value *Cond =
|
||||
IRB.CreateICmpNE(FlatShadow, MSV->getCleanShadow(FlatShadow));
|
||||
Origin = IRB.CreateSelect(Cond, OpOrigin, Origin);
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S -passes='module(msan-module),function(msan)' 2>&1 | \
|
||||
; RUN: FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,CHECK-ORIGINS %s
|
||||
|
||||
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
; CHECK-LABEL: @main
|
||||
define { i32, i8 } @main() sanitize_memory {
|
||||
; CHECK: [[P:%.*]] = inttoptr i64 0 to { i32, i8 }*
|
||||
%p = inttoptr i64 0 to { i32, i8 } *
|
||||
; CHECK: [[O:%.*]] = load { i32, i8 }, { i32, i8 }* [[P]]
|
||||
%o = load { i32, i8 }, { i32, i8 } *%p
|
||||
; CHECK: [[FIELD0:%.+]] = extractvalue { i32, i8 } %_msld, 0
|
||||
; CHECK: [[F0_POISONED:%.+]] = icmp ne i32 [[FIELD0]]
|
||||
; CHECK: [[FIELD1:%.+]] = extractvalue { i32, i8 } %_msld, 1
|
||||
; CHECK: [[F1_POISONED:%.+]] = icmp ne i8 [[FIELD1]]
|
||||
; CHECK: [[F1_OR:%.+]] = or i1 [[F0_POISONED]], [[F1_POISONED]]
|
||||
; CHECK-NOT: icmp ne i1 {{.*}}, false
|
||||
; CHECK: br i1 [[F1_OR]]
|
||||
; CHECK: call void @__msan_warning
|
||||
; CHECK: ret { i32, i8 } [[O]]
|
||||
ret { i32, i8 } %o
|
||||
}
|
|
@ -92,8 +92,7 @@ if.else: ; preds = %entry
|
|||
; CHECK: [[MSPROP:%.*]] = trunc i8 [[MSLD]] to i1
|
||||
|
||||
; Is the shadow poisoned?
|
||||
; CHECK: [[MSCMP:%.*]] = icmp ne i1 [[MSPROP]], false
|
||||
; CHECK: br i1 [[MSCMP]], label %[[IFTRUE:.*]], label {{.*}}
|
||||
; CHECK: br i1 [[MSPROP]], label %[[IFTRUE:.*]], label {{.*}}
|
||||
|
||||
; If yes, raise a warning.
|
||||
; CHECK: [[IFTRUE]]:
|
||||
|
|
Loading…
Reference in New Issue