blob: 76730b3f15963e412d764ac5915ef77e84e0010f [file] [log] [blame]
Nuno Lopes5c525b52012-05-22 17:19:09 +00001//===- BoundsChecking.cpp - Instrumentation for run-time bounds checking --===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements a pass that instruments the code to perform run-time
11// bounds checking on loads, stores, and other memory intrinsics.
12//
13//===----------------------------------------------------------------------===//
14
15#define DEBUG_TYPE "bounds-checking"
16#include "llvm/Transforms/Scalar.h"
17#include "llvm/ADT/Statistic.h"
Nuno Lopes988a0892012-05-29 22:32:51 +000018#include "llvm/Analysis/LoopInfo.h"
19#include "llvm/Analysis/ScalarEvolution.h"
20#include "llvm/Analysis/ScalarEvolutionExpander.h"
21#include "llvm/Analysis/ScalarEvolutionExpressions.h"
Nuno Lopes5c525b52012-05-22 17:19:09 +000022#include "llvm/Support/Debug.h"
23#include "llvm/Support/InstIterator.h"
24#include "llvm/Support/IRBuilder.h"
Nuno Lopes2f0a7482012-05-22 22:02:19 +000025#include "llvm/Support/raw_ostream.h"
Nuno Lopes5c525b52012-05-22 17:19:09 +000026#include "llvm/Support/TargetFolder.h"
27#include "llvm/Target/TargetData.h"
28#include "llvm/Transforms/Utils/Local.h"
29#include "llvm/GlobalVariable.h"
30#include "llvm/Instructions.h"
31#include "llvm/Intrinsics.h"
Nuno Lopes6a06e682012-05-25 16:54:04 +000032#include "llvm/Metadata.h"
Nuno Lopes5c525b52012-05-22 17:19:09 +000033#include "llvm/Operator.h"
34#include "llvm/Pass.h"
35using namespace llvm;
36
37STATISTIC(ChecksAdded, "Bounds checks added");
38STATISTIC(ChecksSkipped, "Bounds checks skipped");
39STATISTIC(ChecksUnable, "Bounds checks unable to add");
Nuno Lopes988a0892012-05-29 22:32:51 +000040STATISTIC(ChecksUnableInterproc, "Bounds checks unable to add (interprocedural)");
41STATISTIC(ChecksUnableLoad, "Bounds checks unable to add (LoadInst)");
Nuno Lopes5c525b52012-05-22 17:19:09 +000042
43typedef IRBuilder<true, TargetFolder> BuilderTy;
44
45namespace {
46 enum ConstTriState {
47 NotConst, Const, Dunno
48 };
49
50 struct BoundsChecking : public FunctionPass {
Nuno Lopes5c525b52012-05-22 17:19:09 +000051 static char ID;
52
53 BoundsChecking(unsigned _Penalty = 5) : FunctionPass(ID), Penalty(_Penalty){
54 initializeBoundsCheckingPass(*PassRegistry::getPassRegistry());
55 }
56
Nuno Lopes5c525b52012-05-22 17:19:09 +000057 virtual bool runOnFunction(Function &F);
58
59 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
60 AU.addRequired<TargetData>();
Nuno Lopes988a0892012-05-29 22:32:51 +000061 AU.addRequired<LoopInfo>();
62 AU.addRequired<ScalarEvolution>();
Nuno Lopes5c525b52012-05-22 17:19:09 +000063 }
Nuno Lopes2f0a7482012-05-22 22:02:19 +000064
65 private:
66 const TargetData *TD;
Nuno Lopes988a0892012-05-29 22:32:51 +000067 LoopInfo *LI;
68 ScalarEvolution *SE;
Nuno Lopes2f0a7482012-05-22 22:02:19 +000069 BuilderTy *Builder;
70 Function *Fn;
71 BasicBlock *TrapBB;
72 unsigned Penalty;
73
74 BasicBlock *getTrapBB();
Nuno Lopes2b526302012-05-23 16:24:52 +000075 void emitBranchToTrap(Value *Cmp = 0);
Nuno Lopes2f0a7482012-05-22 22:02:19 +000076 ConstTriState computeAllocSize(Value *Alloc, uint64_t &Size,
77 Value* &SizeValue);
78 bool instrument(Value *Ptr, Value *Val);
Nuno Lopes5c525b52012-05-22 17:19:09 +000079 };
80}
81
82char BoundsChecking::ID = 0;
Nuno Lopes988a0892012-05-29 22:32:51 +000083INITIALIZE_PASS_BEGIN(BoundsChecking, "bounds-checking",
84 "Run-time bounds checking", false, false)
85INITIALIZE_PASS_DEPENDENCY(ScalarEvolution)
86INITIALIZE_PASS_END(BoundsChecking, "bounds-checking",
87 "Run-time bounds checking", false, false)
Nuno Lopes5c525b52012-05-22 17:19:09 +000088
89
90/// getTrapBB - create a basic block that traps. All overflowing conditions
91/// branch to this block. There's only one trap block per function.
92BasicBlock *BoundsChecking::getTrapBB() {
93 if (TrapBB)
94 return TrapBB;
95
96 BasicBlock::iterator PrevInsertPoint = Builder->GetInsertPoint();
97 TrapBB = BasicBlock::Create(Fn->getContext(), "trap", Fn);
98 Builder->SetInsertPoint(TrapBB);
99
100 llvm::Value *F = Intrinsic::getDeclaration(Fn->getParent(), Intrinsic::trap);
101 CallInst *TrapCall = Builder->CreateCall(F);
102 TrapCall->setDoesNotReturn();
103 TrapCall->setDoesNotThrow();
104 Builder->CreateUnreachable();
105
106 Builder->SetInsertPoint(PrevInsertPoint);
107 return TrapBB;
108}
109
110
Nuno Lopes2b526302012-05-23 16:24:52 +0000111/// emitBranchToTrap - emit a branch instruction to a trap block.
112/// If Cmp is non-null, perform a jump only if its value evaluates to true.
113void BoundsChecking::emitBranchToTrap(Value *Cmp) {
114 Instruction *Inst = Builder->GetInsertPoint();
115 BasicBlock *OldBB = Inst->getParent();
116 BasicBlock *Cont = OldBB->splitBasicBlock(Inst);
117 OldBB->getTerminator()->eraseFromParent();
118
Nuno Lopes2b526302012-05-23 16:24:52 +0000119 if (Cmp)
120 BranchInst::Create(getTrapBB(), Cont, Cmp, OldBB);
121 else
122 BranchInst::Create(getTrapBB(), OldBB);
123}
124
125
Nuno Lopes5c525b52012-05-22 17:19:09 +0000126/// computeAllocSize - compute the object size allocated by an allocation
127/// site. Returns NotConst if the size is not constant (in SizeValue), Const if
128/// the size is constant (in Size), and Dunno if the size could not be
129/// determined within the given maximum Penalty that the computation would
130/// incurr at run-time.
131ConstTriState BoundsChecking::computeAllocSize(Value *Alloc, uint64_t &Size,
132 Value* &SizeValue) {
Nuno Lopes6a06e682012-05-25 16:54:04 +0000133 IntegerType *RetTy = TD->getIntPtrType(Fn->getContext());
134
135 // global variable with definitive size
Nuno Lopes5c525b52012-05-22 17:19:09 +0000136 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Alloc)) {
137 if (GV->hasDefinitiveInitializer()) {
138 Constant *C = GV->getInitializer();
139 Size = TD->getTypeAllocSize(C->getType());
140 return Const;
141 }
142 return Dunno;
143
Nuno Lopes6a06e682012-05-25 16:54:04 +0000144 // stack allocation
Nuno Lopes5c525b52012-05-22 17:19:09 +0000145 } else if (AllocaInst *AI = dyn_cast<AllocaInst>(Alloc)) {
146 if (!AI->getAllocatedType()->isSized())
147 return Dunno;
148
149 Size = TD->getTypeAllocSize(AI->getAllocatedType());
150 if (!AI->isArrayAllocation())
151 return Const; // we are done
152
153 Value *ArraySize = AI->getArraySize();
154 if (const ConstantInt *C = dyn_cast<ConstantInt>(ArraySize)) {
155 Size *= C->getZExtValue();
156 return Const;
157 }
158
159 if (Penalty < 2)
160 return Dunno;
161
162 SizeValue = ConstantInt::get(ArraySize->getType(), Size);
163 SizeValue = Builder->CreateMul(SizeValue, ArraySize);
164 return NotConst;
165
Nuno Lopesd72d67d2012-05-25 21:15:17 +0000166 // function arguments
167 } else if (Argument *A = dyn_cast<Argument>(Alloc)) {
Nuno Lopes988a0892012-05-29 22:32:51 +0000168 if (!A->hasByValAttr()) {
169 ++ChecksUnableInterproc;
Nuno Lopesd72d67d2012-05-25 21:15:17 +0000170 return Dunno;
Nuno Lopes988a0892012-05-29 22:32:51 +0000171 }
Nuno Lopesd72d67d2012-05-25 21:15:17 +0000172
173 PointerType *PT = cast<PointerType>(A->getType());
174 Size = TD->getTypeAllocSize(PT->getElementType());
175 return Const;
176
Nuno Lopes6a06e682012-05-25 16:54:04 +0000177 // ptr = select(ptr1, ptr2)
178 } else if (SelectInst *SI = dyn_cast<SelectInst>(Alloc)) {
179 uint64_t SizeFalse;
180 Value *SizeValueFalse;
181 ConstTriState TrueConst = computeAllocSize(SI->getTrueValue(), Size,
182 SizeValue);
183 ConstTriState FalseConst = computeAllocSize(SI->getFalseValue(), SizeFalse,
184 SizeValueFalse);
185
186 if (TrueConst == Const && FalseConst == Const && Size == SizeFalse)
187 return Const;
188
189 if (Penalty < 2 || (TrueConst == Dunno && FalseConst == Dunno))
190 return Dunno;
191
192 // if one of the branches is Dunno, assume it is ok and check just the other
193 APInt MaxSize = APInt::getMaxValue(TD->getTypeSizeInBits(RetTy));
194
195 if (TrueConst == Const)
196 SizeValue = ConstantInt::get(RetTy, Size);
197 else if (TrueConst == Dunno)
198 SizeValue = ConstantInt::get(RetTy, MaxSize);
199
200 if (FalseConst == Const)
201 SizeValueFalse = ConstantInt::get(RetTy, SizeFalse);
202 else if (FalseConst == Dunno)
203 SizeValueFalse = ConstantInt::get(RetTy, MaxSize);
204
205 SizeValue = Builder->CreateSelect(SI->getCondition(), SizeValue,
206 SizeValueFalse);
207 return NotConst;
208
209 // call allocation function
Nuno Lopes2f0a7482012-05-22 22:02:19 +0000210 } else if (CallInst *CI = dyn_cast<CallInst>(Alloc)) {
Nuno Lopes6a06e682012-05-25 16:54:04 +0000211 SmallVector<unsigned, 4> Args;
Nuno Lopes5c525b52012-05-22 17:19:09 +0000212
Nuno Lopes6a06e682012-05-25 16:54:04 +0000213 if (MDNode *MD = CI->getMetadata("alloc_size")) {
214 for (unsigned i = 0, e = MD->getNumOperands(); i != e; ++i)
215 Args.push_back(cast<ConstantInt>(MD->getOperand(i))->getZExtValue());
216
217 } else if (Function *Callee = CI->getCalledFunction()) {
218 FunctionType *FTy = Callee->getFunctionType();
219
Nuno Lopes2f0a7482012-05-22 22:02:19 +0000220 // alloc(size)
Nuno Lopes6a06e682012-05-25 16:54:04 +0000221 if (FTy->getNumParams() == 1 && FTy->getParamType(0)->isIntegerTy()) {
222 if ((Callee->getName() == "malloc" ||
223 Callee->getName() == "valloc" ||
224 Callee->getName() == "_Znwj" || // operator new(unsigned int)
225 Callee->getName() == "_Znwm" || // operator new(unsigned long)
226 Callee->getName() == "_Znaj" || // operator new[](unsigned int)
227 Callee->getName() == "_Znam")) {
228 Args.push_back(0);
Nuno Lopes2f0a7482012-05-22 22:02:19 +0000229 }
Nuno Lopes6a06e682012-05-25 16:54:04 +0000230 } else if (FTy->getNumParams() == 2) {
231 // alloc(_, x)
232 if (FTy->getParamType(1)->isIntegerTy() &&
233 ((Callee->getName() == "realloc" ||
234 Callee->getName() == "reallocf"))) {
235 Args.push_back(1);
236
237 // alloc(x, y)
238 } else if (FTy->getParamType(0)->isIntegerTy() &&
239 FTy->getParamType(1)->isIntegerTy() &&
240 Callee->getName() == "calloc") {
241 Args.push_back(0);
242 Args.push_back(1);
243 }
Nuno Lopes2f0a7482012-05-22 22:02:19 +0000244 }
Nuno Lopes6a06e682012-05-25 16:54:04 +0000245 }
246
247 if (Args.empty())
Nuno Lopes2f0a7482012-05-22 22:02:19 +0000248 return Dunno;
Nuno Lopes2f0a7482012-05-22 22:02:19 +0000249
Nuno Lopes6a06e682012-05-25 16:54:04 +0000250 // check if all arguments are constant. if so, the object size is also const
251 bool AllConst = true;
252 for (SmallVectorImpl<unsigned>::iterator I = Args.begin(), E = Args.end();
253 I != E; ++I) {
254 if (!isa<ConstantInt>(CI->getArgOperand(*I))) {
255 AllConst = false;
256 break;
Nuno Lopes2f0a7482012-05-22 22:02:19 +0000257 }
258 }
Nuno Lopes6a06e682012-05-25 16:54:04 +0000259
260 if (AllConst) {
261 Size = 1;
262 for (SmallVectorImpl<unsigned>::iterator I = Args.begin(), E = Args.end();
263 I != E; ++I) {
264 ConstantInt *Arg = cast<ConstantInt>(CI->getArgOperand(*I));
265 Size *= (size_t)Arg->getZExtValue();
266 }
267 return Const;
268 }
269
270 if (Penalty < 2)
271 return Dunno;
272
273 // not all arguments are constant, so create a sequence of multiplications
274 bool First = true;
275 for (SmallVectorImpl<unsigned>::iterator I = Args.begin(), E = Args.end();
276 I != E; ++I) {
277 Value *Arg = CI->getArgOperand(*I);
278 if (First) {
279 SizeValue = Arg;
280 First = false;
281 continue;
282 }
283 SizeValue = Builder->CreateMul(SizeValue, Arg);
284 }
Nuno Lopes6a06e682012-05-25 16:54:04 +0000285 return NotConst;
286
Nuno Lopes2f0a7482012-05-22 22:02:19 +0000287 // TODO: handle more standard functions:
288 // - strdup / strndup
289 // - strcpy / strncpy
290 // - memcpy / memmove
291 // - strcat / strncat
Nuno Lopes988a0892012-05-29 22:32:51 +0000292
293 } else if (isa<LoadInst>(Alloc)) {
294 ++ChecksUnableLoad;
295 return Dunno;
Nuno Lopes5c525b52012-05-22 17:19:09 +0000296 }
297
Nuno Lopes5c525b52012-05-22 17:19:09 +0000298 return Dunno;
299}
300
301
Nuno Lopes2f0a7482012-05-22 22:02:19 +0000302/// instrument - adds run-time bounds checks to memory accessing instructions.
303/// Ptr is the pointer that will be read/written, and InstVal is either the
304/// result from the load or the value being stored. It is used to determine the
305/// size of memory block that is touched.
306/// Returns true if any change was made to the IR, false otherwise.
Nuno Lopes5c525b52012-05-22 17:19:09 +0000307bool BoundsChecking::instrument(Value *Ptr, Value *InstVal) {
308 uint64_t NeededSize = TD->getTypeStoreSize(InstVal->getType());
309 DEBUG(dbgs() << "Instrument " << *Ptr << " for " << Twine(NeededSize)
310 << " bytes\n");
311
Nuno Lopes988a0892012-05-29 22:32:51 +0000312 Type *SizeTy = TD->getIntPtrType(Fn->getContext());
Nuno Lopes5c525b52012-05-22 17:19:09 +0000313
314 // Get to the real allocated thing and offset as fast as possible.
315 Ptr = Ptr->stripPointerCasts();
Nuno Lopes5c525b52012-05-22 17:19:09 +0000316
Nuno Lopes988a0892012-05-29 22:32:51 +0000317 // try to hoist the check if the instruction is inside a loop
318 Value *LoopOffset = 0;
319 if (Loop *L = LI->getLoopFor(Builder->GetInsertPoint()->getParent())) {
320 const SCEV *PtrSCEV = SE->getSCEVAtScope(Ptr, L->getParentLoop());
321 const SCEV *BaseSCEV = SE->getPointerBase(PtrSCEV);
322
323 if (const SCEVUnknown *PointerBase = dyn_cast<SCEVUnknown>(BaseSCEV)) {
324 Ptr = PointerBase->getValue()->stripPointerCasts();
325 Instruction *InsertPoint = L->getLoopPreheader()->getFirstInsertionPt();
326 Builder->SetInsertPoint(InsertPoint);
327
328 SCEVExpander Expander(*SE, "bounds-checking");
329 const SCEV *OffsetSCEV = SE->getMinusSCEV(PtrSCEV, PointerBase);
330 LoopOffset = Expander.expandCodeFor(OffsetSCEV, SizeTy, InsertPoint);
331 }
332 }
333
334 GEPOperator *GEP = dyn_cast<GEPOperator>(Ptr);
335 if (GEP) {
Nuno Lopes5c525b52012-05-22 17:19:09 +0000336 // check if we will be able to get the offset
337 if (!GEP->hasAllConstantIndices() && Penalty < 2) {
338 ++ChecksUnable;
339 return false;
340 }
341 Ptr = GEP->getPointerOperand()->stripPointerCasts();
342 }
343
344 uint64_t Size = 0;
345 Value *SizeValue = 0;
346 ConstTriState ConstAlloc = computeAllocSize(Ptr, Size, SizeValue);
347 if (ConstAlloc == Dunno) {
Nuno Lopes988a0892012-05-29 22:32:51 +0000348 DEBUG(dbgs() << "computeAllocSize failed:\n" << *Ptr << "\n");
Nuno Lopes5c525b52012-05-22 17:19:09 +0000349 ++ChecksUnable;
350 return false;
351 }
352 assert(ConstAlloc == Const || SizeValue);
353
354 uint64_t Offset = 0;
355 Value *OffsetValue = 0;
356
357 if (GEP) {
358 if (GEP->hasAllConstantIndices()) {
359 SmallVector<Value*, 8> Ops(GEP->idx_begin(), GEP->idx_end());
360 assert(GEP->getPointerOperandType()->isPointerTy());
361 Offset = TD->getIndexedOffset(GEP->getPointerOperandType(), Ops);
362 } else {
363 OffsetValue = EmitGEPOffset(Builder, *TD, GEP);
364 }
365 }
366
Nuno Lopes988a0892012-05-29 22:32:51 +0000367 if (!LoopOffset && !OffsetValue && ConstAlloc == Const) {
Nuno Lopes5c525b52012-05-22 17:19:09 +0000368 if (Size < Offset || (Size - Offset) < NeededSize) {
369 // Out of bounds
Nuno Lopes2b526302012-05-23 16:24:52 +0000370 emitBranchToTrap();
Nuno Lopes5c525b52012-05-22 17:19:09 +0000371 ++ChecksAdded;
372 return true;
373 }
374 // in bounds
375 ++ChecksSkipped;
376 return false;
377 }
378
Nuno Lopes988a0892012-05-29 22:32:51 +0000379 if (!OffsetValue)
Nuno Lopes5c525b52012-05-22 17:19:09 +0000380 OffsetValue = ConstantInt::get(SizeTy, Offset);
381
382 if (SizeValue)
383 SizeValue = Builder->CreateZExt(SizeValue, SizeTy);
384 else
385 SizeValue = ConstantInt::get(SizeTy, Size);
386
Nuno Lopes988a0892012-05-29 22:32:51 +0000387 // add the loop offset if the check was hoisted
388 if (LoopOffset)
389 OffsetValue = Builder->CreateAdd(OffsetValue, LoopOffset);
390
Nuno Lopes5c525b52012-05-22 17:19:09 +0000391 Value *NeededSizeVal = ConstantInt::get(SizeTy, NeededSize);
392 Value *ObjSize = Builder->CreateSub(SizeValue, OffsetValue);
393 Value *Cmp1 = Builder->CreateICmpULT(SizeValue, OffsetValue);
394 Value *Cmp2 = Builder->CreateICmpULT(ObjSize, NeededSizeVal);
395 Value *Or = Builder->CreateOr(Cmp1, Cmp2);
Nuno Lopes2b526302012-05-23 16:24:52 +0000396 emitBranchToTrap(Or);
Nuno Lopes5c525b52012-05-22 17:19:09 +0000397
Nuno Lopes5c525b52012-05-22 17:19:09 +0000398 ++ChecksAdded;
399 return true;
400}
401
402bool BoundsChecking::runOnFunction(Function &F) {
403 TD = &getAnalysis<TargetData>();
Nuno Lopes988a0892012-05-29 22:32:51 +0000404 LI = &getAnalysis<LoopInfo>();
405 SE = &getAnalysis<ScalarEvolution>();
Nuno Lopes5c525b52012-05-22 17:19:09 +0000406
407 TrapBB = 0;
408 Fn = &F;
409 BuilderTy TheBuilder(F.getContext(), TargetFolder(TD));
410 Builder = &TheBuilder;
411
412 // check HANDLE_MEMORY_INST in include/llvm/Instruction.def for memory
413 // touching instructions
414 std::vector<Instruction*> WorkList;
415 for (inst_iterator i = inst_begin(F), e = inst_end(F); i != e; ++i) {
416 Instruction *I = &*i;
417 if (isa<LoadInst>(I) || isa<StoreInst>(I) || isa<AtomicCmpXchgInst>(I) ||
418 isa<AtomicRMWInst>(I))
419 WorkList.push_back(I);
420 }
421
422 bool MadeChange = false;
Nuno Lopes2f0a7482012-05-22 22:02:19 +0000423 for (std::vector<Instruction*>::iterator i = WorkList.begin(),
424 e = WorkList.end(); i != e; ++i) {
425 Instruction *I = *i;
Nuno Lopes5c525b52012-05-22 17:19:09 +0000426
427 Builder->SetInsertPoint(I);
428 if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
429 MadeChange |= instrument(LI->getPointerOperand(), LI);
430 } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
431 MadeChange |= instrument(SI->getPointerOperand(), SI->getValueOperand());
432 } else if (AtomicCmpXchgInst *AI = dyn_cast<AtomicCmpXchgInst>(I)) {
433 MadeChange |= instrument(AI->getPointerOperand(),AI->getCompareOperand());
434 } else if (AtomicRMWInst *AI = dyn_cast<AtomicRMWInst>(I)) {
435 MadeChange |= instrument(AI->getPointerOperand(), AI->getValOperand());
436 } else {
437 llvm_unreachable("unknown Instruction type");
438 }
439 }
440 return MadeChange;
441}
442
443FunctionPass *llvm::createBoundsCheckingPass(unsigned Penalty) {
444 return new BoundsChecking(Penalty);
445}