LLVM API Documentation
00001 //===- BoundsChecking.cpp - Instrumentation for run-time bounds checking --===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements a pass that instruments the code to perform run-time 00011 // bounds checking on loads, stores, and other memory intrinsics. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #define DEBUG_TYPE "bounds-checking" 00016 #include "llvm/Transforms/Instrumentation.h" 00017 #include "llvm/ADT/Statistic.h" 00018 #include "llvm/Analysis/MemoryBuiltins.h" 00019 #include "llvm/IR/DataLayout.h" 00020 #include "llvm/IR/IRBuilder.h" 00021 #include "llvm/IR/Intrinsics.h" 00022 #include "llvm/Pass.h" 00023 #include "llvm/Support/CommandLine.h" 00024 #include "llvm/Support/Debug.h" 00025 #include "llvm/Support/InstIterator.h" 00026 #include "llvm/Support/TargetFolder.h" 00027 #include "llvm/Support/raw_ostream.h" 00028 #include "llvm/Target/TargetLibraryInfo.h" 00029 using namespace llvm; 00030 00031 static cl::opt<bool> SingleTrapBB("bounds-checking-single-trap", 00032 cl::desc("Use one trap block per function")); 00033 00034 STATISTIC(ChecksAdded, "Bounds checks added"); 00035 STATISTIC(ChecksSkipped, "Bounds checks skipped"); 00036 STATISTIC(ChecksUnable, "Bounds checks unable to add"); 00037 00038 typedef IRBuilder<true, TargetFolder> BuilderTy; 00039 00040 namespace { 00041 struct BoundsChecking : public FunctionPass { 00042 static char ID; 00043 00044 BoundsChecking() : FunctionPass(ID) { 00045 initializeBoundsCheckingPass(*PassRegistry::getPassRegistry()); 00046 } 00047 00048 virtual bool runOnFunction(Function &F); 00049 00050 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 00051 AU.addRequired<DataLayout>(); 00052 AU.addRequired<TargetLibraryInfo>(); 00053 } 00054 00055 private: 00056 const DataLayout *TD; 00057 const TargetLibraryInfo *TLI; 00058 ObjectSizeOffsetEvaluator *ObjSizeEval; 00059 BuilderTy *Builder; 00060 Instruction *Inst; 00061 BasicBlock *TrapBB; 00062 00063 BasicBlock *getTrapBB(); 00064 void emitBranchToTrap(Value *Cmp = 0); 00065 bool computeAllocSize(Value *Ptr, APInt &Offset, Value* &OffsetValue, 00066 APInt &Size, Value* &SizeValue); 00067 bool instrument(Value *Ptr, Value *Val); 00068 }; 00069 } 00070 00071 char BoundsChecking::ID = 0; 00072 INITIALIZE_PASS(BoundsChecking, "bounds-checking", "Run-time bounds checking", 00073 false, false) 00074 00075 00076 /// getTrapBB - create a basic block that traps. All overflowing conditions 00077 /// branch to this block. There's only one trap block per function. 00078 BasicBlock *BoundsChecking::getTrapBB() { 00079 if (TrapBB && SingleTrapBB) 00080 return TrapBB; 00081 00082 Function *Fn = Inst->getParent()->getParent(); 00083 BasicBlock::iterator PrevInsertPoint = Builder->GetInsertPoint(); 00084 TrapBB = BasicBlock::Create(Fn->getContext(), "trap", Fn); 00085 Builder->SetInsertPoint(TrapBB); 00086 00087 llvm::Value *F = Intrinsic::getDeclaration(Fn->getParent(), Intrinsic::trap); 00088 CallInst *TrapCall = Builder->CreateCall(F); 00089 TrapCall->setDoesNotReturn(); 00090 TrapCall->setDoesNotThrow(); 00091 TrapCall->setDebugLoc(Inst->getDebugLoc()); 00092 Builder->CreateUnreachable(); 00093 00094 Builder->SetInsertPoint(PrevInsertPoint); 00095 return TrapBB; 00096 } 00097 00098 00099 /// emitBranchToTrap - emit a branch instruction to a trap block. 00100 /// If Cmp is non-null, perform a jump only if its value evaluates to true. 00101 void BoundsChecking::emitBranchToTrap(Value *Cmp) { 00102 // check if the comparison is always false 00103 ConstantInt *C = dyn_cast_or_null<ConstantInt>(Cmp); 00104 if (C) { 00105 ++ChecksSkipped; 00106 if (!C->getZExtValue()) 00107 return; 00108 else 00109 Cmp = 0; // unconditional branch 00110 } 00111 ++ChecksAdded; 00112 00113 Instruction *Inst = Builder->GetInsertPoint(); 00114 BasicBlock *OldBB = Inst->getParent(); 00115 BasicBlock *Cont = OldBB->splitBasicBlock(Inst); 00116 OldBB->getTerminator()->eraseFromParent(); 00117 00118 if (Cmp) 00119 BranchInst::Create(getTrapBB(), Cont, Cmp, OldBB); 00120 else 00121 BranchInst::Create(getTrapBB(), OldBB); 00122 } 00123 00124 00125 /// instrument - adds run-time bounds checks to memory accessing instructions. 00126 /// Ptr is the pointer that will be read/written, and InstVal is either the 00127 /// result from the load or the value being stored. It is used to determine the 00128 /// size of memory block that is touched. 00129 /// Returns true if any change was made to the IR, false otherwise. 00130 bool BoundsChecking::instrument(Value *Ptr, Value *InstVal) { 00131 uint64_t NeededSize = TD->getTypeStoreSize(InstVal->getType()); 00132 DEBUG(dbgs() << "Instrument " << *Ptr << " for " << Twine(NeededSize) 00133 << " bytes\n"); 00134 00135 SizeOffsetEvalType SizeOffset = ObjSizeEval->compute(Ptr); 00136 00137 if (!ObjSizeEval->bothKnown(SizeOffset)) { 00138 ++ChecksUnable; 00139 return false; 00140 } 00141 00142 Value *Size = SizeOffset.first; 00143 Value *Offset = SizeOffset.second; 00144 ConstantInt *SizeCI = dyn_cast<ConstantInt>(Size); 00145 00146 Type *IntTy = TD->getIntPtrType(Ptr->getType()); 00147 Value *NeededSizeVal = ConstantInt::get(IntTy, NeededSize); 00148 00149 // three checks are required to ensure safety: 00150 // . Offset >= 0 (since the offset is given from the base ptr) 00151 // . Size >= Offset (unsigned) 00152 // . Size - Offset >= NeededSize (unsigned) 00153 // 00154 // optimization: if Size >= 0 (signed), skip 1st check 00155 // FIXME: add NSW/NUW here? -- we dont care if the subtraction overflows 00156 Value *ObjSize = Builder->CreateSub(Size, Offset); 00157 Value *Cmp2 = Builder->CreateICmpULT(Size, Offset); 00158 Value *Cmp3 = Builder->CreateICmpULT(ObjSize, NeededSizeVal); 00159 Value *Or = Builder->CreateOr(Cmp2, Cmp3); 00160 if (!SizeCI || SizeCI->getValue().slt(0)) { 00161 Value *Cmp1 = Builder->CreateICmpSLT(Offset, ConstantInt::get(IntTy, 0)); 00162 Or = Builder->CreateOr(Cmp1, Or); 00163 } 00164 emitBranchToTrap(Or); 00165 00166 return true; 00167 } 00168 00169 bool BoundsChecking::runOnFunction(Function &F) { 00170 TD = &getAnalysis<DataLayout>(); 00171 TLI = &getAnalysis<TargetLibraryInfo>(); 00172 00173 TrapBB = 0; 00174 BuilderTy TheBuilder(F.getContext(), TargetFolder(TD)); 00175 Builder = &TheBuilder; 00176 ObjectSizeOffsetEvaluator TheObjSizeEval(TD, TLI, F.getContext()); 00177 ObjSizeEval = &TheObjSizeEval; 00178 00179 // check HANDLE_MEMORY_INST in include/llvm/Instruction.def for memory 00180 // touching instructions 00181 std::vector<Instruction*> WorkList; 00182 for (inst_iterator i = inst_begin(F), e = inst_end(F); i != e; ++i) { 00183 Instruction *I = &*i; 00184 if (isa<LoadInst>(I) || isa<StoreInst>(I) || isa<AtomicCmpXchgInst>(I) || 00185 isa<AtomicRMWInst>(I)) 00186 WorkList.push_back(I); 00187 } 00188 00189 bool MadeChange = false; 00190 for (std::vector<Instruction*>::iterator i = WorkList.begin(), 00191 e = WorkList.end(); i != e; ++i) { 00192 Inst = *i; 00193 00194 Builder->SetInsertPoint(Inst); 00195 if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) { 00196 MadeChange |= instrument(LI->getPointerOperand(), LI); 00197 } else if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) { 00198 MadeChange |= instrument(SI->getPointerOperand(), SI->getValueOperand()); 00199 } else if (AtomicCmpXchgInst *AI = dyn_cast<AtomicCmpXchgInst>(Inst)) { 00200 MadeChange |= instrument(AI->getPointerOperand(),AI->getCompareOperand()); 00201 } else if (AtomicRMWInst *AI = dyn_cast<AtomicRMWInst>(Inst)) { 00202 MadeChange |= instrument(AI->getPointerOperand(), AI->getValOperand()); 00203 } else { 00204 llvm_unreachable("unknown Instruction type"); 00205 } 00206 } 00207 return MadeChange; 00208 } 00209 00210 FunctionPass *llvm::createBoundsCheckingPass() { 00211 return new BoundsChecking(); 00212 }