diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 | 
| commit | d8e91e46262bc44006913e6796843909f1ac7bcd (patch) | |
| tree | 7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/Transforms/Instrumentation/BoundsChecking.cpp | |
| parent | b7eb8e35e481a74962664b63dfb09483b200209a (diff) | |
Notes
Diffstat (limited to 'lib/Transforms/Instrumentation/BoundsChecking.cpp')
| -rw-r--r-- | lib/Transforms/Instrumentation/BoundsChecking.cpp | 82 | 
1 files changed, 43 insertions, 39 deletions
diff --git a/lib/Transforms/Instrumentation/BoundsChecking.cpp b/lib/Transforms/Instrumentation/BoundsChecking.cpp index e13db08e263c7..a0c78e0468c61 100644 --- a/lib/Transforms/Instrumentation/BoundsChecking.cpp +++ b/lib/Transforms/Instrumentation/BoundsChecking.cpp @@ -47,21 +47,17 @@ STATISTIC(ChecksUnable, "Bounds checks unable to add");  using BuilderTy = IRBuilder<TargetFolder>; -/// Adds run-time bounds checks to memory accessing instructions. +/// Gets the conditions under which memory accessing instructions will overflow.  ///  /// \p Ptr is the pointer that will be read/written, and \p InstVal is either  /// the result from the load or the value being stored. It is used to determine  /// the size of memory block that is touched.  /// -/// \p GetTrapBB is a callable that returns the trap BB to use on failure. -/// -/// Returns true if any change was made to the IR, false otherwise. -template <typename GetTrapBBT> -static bool instrumentMemAccess(Value *Ptr, Value *InstVal, -                                const DataLayout &DL, TargetLibraryInfo &TLI, -                                ObjectSizeOffsetEvaluator &ObjSizeEval, -                                BuilderTy &IRB, GetTrapBBT GetTrapBB, -                                ScalarEvolution &SE) { +/// Returns the condition under which the access will overflow. +static Value *getBoundsCheckCond(Value *Ptr, Value *InstVal, +                                 const DataLayout &DL, TargetLibraryInfo &TLI, +                                 ObjectSizeOffsetEvaluator &ObjSizeEval, +                                 BuilderTy &IRB, ScalarEvolution &SE) {    uint64_t NeededSize = DL.getTypeStoreSize(InstVal->getType());    LLVM_DEBUG(dbgs() << "Instrument " << *Ptr << " for " << Twine(NeededSize)                      << " bytes\n"); @@ -70,7 +66,7 @@ static bool instrumentMemAccess(Value *Ptr, Value *InstVal,    if (!ObjSizeEval.bothKnown(SizeOffset)) {      ++ChecksUnable; -    return false; +    return nullptr;    }    Value *Size   = SizeOffset.first; @@ -107,13 +103,23 @@ static bool instrumentMemAccess(Value *Ptr, Value *InstVal,      Or = IRB.CreateOr(Cmp1, Or);    } +  return Or; +} + +/// Adds run-time bounds checks to memory accessing instructions. +/// +/// \p Or is the condition that should guard the trap. +/// +/// \p GetTrapBB is a callable that returns the trap BB to use on failure. +template <typename GetTrapBBT> +static void insertBoundsCheck(Value *Or, BuilderTy IRB, GetTrapBBT GetTrapBB) {    // check if the comparison is always false    ConstantInt *C = dyn_cast_or_null<ConstantInt>(Or);    if (C) {      ++ChecksSkipped;      // If non-zero, nothing to do.      if (!C->getZExtValue()) -      return true; +      return;    }    ++ChecksAdded; @@ -127,12 +133,11 @@ static bool instrumentMemAccess(Value *Ptr, Value *InstVal,      // FIXME: We should really handle this differently to bypass the splitting      // the block.      BranchInst::Create(GetTrapBB(IRB), OldBB); -    return true; +    return;    }    // Create the conditional branch.    BranchInst::Create(GetTrapBB(IRB), Cont, Or, OldBB); -  return true;  }  static bool addBoundsChecking(Function &F, TargetLibraryInfo &TLI, @@ -143,11 +148,25 @@ static bool addBoundsChecking(Function &F, TargetLibraryInfo &TLI,    // check HANDLE_MEMORY_INST in include/llvm/Instruction.def for memory    // touching instructions -  std::vector<Instruction *> WorkList; +  SmallVector<std::pair<Instruction *, Value *>, 4> TrapInfo;    for (Instruction &I : instructions(F)) { -    if (isa<LoadInst>(I) || isa<StoreInst>(I) || isa<AtomicCmpXchgInst>(I) || -        isa<AtomicRMWInst>(I)) -        WorkList.push_back(&I); +    Value *Or = nullptr; +    BuilderTy IRB(I.getParent(), BasicBlock::iterator(&I), TargetFolder(DL)); +    if (LoadInst *LI = dyn_cast<LoadInst>(&I)) { +      Or = getBoundsCheckCond(LI->getPointerOperand(), LI, DL, TLI, +                              ObjSizeEval, IRB, SE); +    } else if (StoreInst *SI = dyn_cast<StoreInst>(&I)) { +      Or = getBoundsCheckCond(SI->getPointerOperand(), SI->getValueOperand(), +                              DL, TLI, ObjSizeEval, IRB, SE); +    } else if (AtomicCmpXchgInst *AI = dyn_cast<AtomicCmpXchgInst>(&I)) { +      Or = getBoundsCheckCond(AI->getPointerOperand(), AI->getCompareOperand(), +                              DL, TLI, ObjSizeEval, IRB, SE); +    } else if (AtomicRMWInst *AI = dyn_cast<AtomicRMWInst>(&I)) { +      Or = getBoundsCheckCond(AI->getPointerOperand(), AI->getValOperand(), DL, +                              TLI, ObjSizeEval, IRB, SE); +    } +    if (Or) +      TrapInfo.push_back(std::make_pair(&I, Or));    }    // Create a trapping basic block on demand using a callback. Depending on @@ -176,29 +195,14 @@ static bool addBoundsChecking(Function &F, TargetLibraryInfo &TLI,      return TrapBB;    }; -  bool MadeChange = false; -  for (Instruction *Inst : WorkList) { +  // Add the checks. +  for (const auto &Entry : TrapInfo) { +    Instruction *Inst = Entry.first;      BuilderTy IRB(Inst->getParent(), BasicBlock::iterator(Inst), TargetFolder(DL)); -    if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) { -      MadeChange |= instrumentMemAccess(LI->getPointerOperand(), LI, DL, TLI, -                                        ObjSizeEval, IRB, GetTrapBB, SE); -    } else if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) { -      MadeChange |= -          instrumentMemAccess(SI->getPointerOperand(), SI->getValueOperand(), -                              DL, TLI, ObjSizeEval, IRB, GetTrapBB, SE); -    } else if (AtomicCmpXchgInst *AI = dyn_cast<AtomicCmpXchgInst>(Inst)) { -      MadeChange |= -          instrumentMemAccess(AI->getPointerOperand(), AI->getCompareOperand(), -                              DL, TLI, ObjSizeEval, IRB, GetTrapBB, SE); -    } else if (AtomicRMWInst *AI = dyn_cast<AtomicRMWInst>(Inst)) { -      MadeChange |= -          instrumentMemAccess(AI->getPointerOperand(), AI->getValOperand(), DL, -                              TLI, ObjSizeEval, IRB, GetTrapBB, SE); -    } else { -      llvm_unreachable("unknown Instruction type"); -    } +    insertBoundsCheck(Entry.second, IRB, GetTrapBB);    } -  return MadeChange; + +  return !TrapInfo.empty();  }  PreservedAnalyses BoundsCheckingPass::run(Function &F, FunctionAnalysisManager &AM) {  | 
