LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BoundsChecking.cpp
Go to the documentation of this file.
1 //===- 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"
17 #include "llvm/ADT/Statistic.h"
19 #include "llvm/IR/DataLayout.h"
20 #include "llvm/IR/IRBuilder.h"
21 #include "llvm/IR/Intrinsics.h"
22 #include "llvm/Pass.h"
24 #include "llvm/Support/Debug.h"
29 using namespace llvm;
30 
31 static cl::opt<bool> SingleTrapBB("bounds-checking-single-trap",
32  cl::desc("Use one trap block per function"));
33 
34 STATISTIC(ChecksAdded, "Bounds checks added");
35 STATISTIC(ChecksSkipped, "Bounds checks skipped");
36 STATISTIC(ChecksUnable, "Bounds checks unable to add");
37 
39 
40 namespace {
41  struct BoundsChecking : public FunctionPass {
42  static char ID;
43 
44  BoundsChecking() : FunctionPass(ID) {
46  }
47 
48  virtual bool runOnFunction(Function &F);
49 
50  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
51  AU.addRequired<DataLayout>();
53  }
54 
55  private:
56  const DataLayout *TD;
57  const TargetLibraryInfo *TLI;
58  ObjectSizeOffsetEvaluator *ObjSizeEval;
59  BuilderTy *Builder;
60  Instruction *Inst;
61  BasicBlock *TrapBB;
62 
63  BasicBlock *getTrapBB();
64  void emitBranchToTrap(Value *Cmp = 0);
65  bool computeAllocSize(Value *Ptr, APInt &Offset, Value* &OffsetValue,
66  APInt &Size, Value* &SizeValue);
67  bool instrument(Value *Ptr, Value *Val);
68  };
69 }
70 
71 char BoundsChecking::ID = 0;
72 INITIALIZE_PASS(BoundsChecking, "bounds-checking", "Run-time bounds checking",
73  false, false)
74 
75 
76 /// getTrapBB - create a basic block that traps. All overflowing conditions
77 /// branch to this block. There's only one trap block per function.
78 BasicBlock *BoundsChecking::getTrapBB() {
79  if (TrapBB && SingleTrapBB)
80  return TrapBB;
81 
82  Function *Fn = Inst->getParent()->getParent();
83  IRBuilder<>::InsertPointGuard Guard(*Builder);
84  TrapBB = BasicBlock::Create(Fn->getContext(), "trap", Fn);
85  Builder->SetInsertPoint(TrapBB);
86 
88  CallInst *TrapCall = Builder->CreateCall(F);
89  TrapCall->setDoesNotReturn();
90  TrapCall->setDoesNotThrow();
91  TrapCall->setDebugLoc(Inst->getDebugLoc());
92  Builder->CreateUnreachable();
93 
94  return TrapBB;
95 }
96 
97 
98 /// emitBranchToTrap - emit a branch instruction to a trap block.
99 /// If Cmp is non-null, perform a jump only if its value evaluates to true.
100 void BoundsChecking::emitBranchToTrap(Value *Cmp) {
101  // check if the comparison is always false
102  ConstantInt *C = dyn_cast_or_null<ConstantInt>(Cmp);
103  if (C) {
104  ++ChecksSkipped;
105  if (!C->getZExtValue())
106  return;
107  else
108  Cmp = 0; // unconditional branch
109  }
110  ++ChecksAdded;
111 
112  Instruction *Inst = Builder->GetInsertPoint();
113  BasicBlock *OldBB = Inst->getParent();
114  BasicBlock *Cont = OldBB->splitBasicBlock(Inst);
115  OldBB->getTerminator()->eraseFromParent();
116 
117  if (Cmp)
118  BranchInst::Create(getTrapBB(), Cont, Cmp, OldBB);
119  else
120  BranchInst::Create(getTrapBB(), OldBB);
121 }
122 
123 
124 /// instrument - adds run-time bounds checks to memory accessing instructions.
125 /// Ptr is the pointer that will be read/written, and InstVal is either the
126 /// result from the load or the value being stored. It is used to determine the
127 /// size of memory block that is touched.
128 /// Returns true if any change was made to the IR, false otherwise.
129 bool BoundsChecking::instrument(Value *Ptr, Value *InstVal) {
130  uint64_t NeededSize = TD->getTypeStoreSize(InstVal->getType());
131  DEBUG(dbgs() << "Instrument " << *Ptr << " for " << Twine(NeededSize)
132  << " bytes\n");
133 
134  SizeOffsetEvalType SizeOffset = ObjSizeEval->compute(Ptr);
135 
136  if (!ObjSizeEval->bothKnown(SizeOffset)) {
137  ++ChecksUnable;
138  return false;
139  }
140 
141  Value *Size = SizeOffset.first;
142  Value *Offset = SizeOffset.second;
143  ConstantInt *SizeCI = dyn_cast<ConstantInt>(Size);
144 
145  Type *IntTy = TD->getIntPtrType(Ptr->getType());
146  Value *NeededSizeVal = ConstantInt::get(IntTy, NeededSize);
147 
148  // three checks are required to ensure safety:
149  // . Offset >= 0 (since the offset is given from the base ptr)
150  // . Size >= Offset (unsigned)
151  // . Size - Offset >= NeededSize (unsigned)
152  //
153  // optimization: if Size >= 0 (signed), skip 1st check
154  // FIXME: add NSW/NUW here? -- we dont care if the subtraction overflows
155  Value *ObjSize = Builder->CreateSub(Size, Offset);
156  Value *Cmp2 = Builder->CreateICmpULT(Size, Offset);
157  Value *Cmp3 = Builder->CreateICmpULT(ObjSize, NeededSizeVal);
158  Value *Or = Builder->CreateOr(Cmp2, Cmp3);
159  if (!SizeCI || SizeCI->getValue().slt(0)) {
160  Value *Cmp1 = Builder->CreateICmpSLT(Offset, ConstantInt::get(IntTy, 0));
161  Or = Builder->CreateOr(Cmp1, Or);
162  }
163  emitBranchToTrap(Or);
164 
165  return true;
166 }
167 
168 bool BoundsChecking::runOnFunction(Function &F) {
169  TD = &getAnalysis<DataLayout>();
170  TLI = &getAnalysis<TargetLibraryInfo>();
171 
172  TrapBB = 0;
173  BuilderTy TheBuilder(F.getContext(), TargetFolder(TD));
174  Builder = &TheBuilder;
175  ObjectSizeOffsetEvaluator TheObjSizeEval(TD, TLI, F.getContext(),
176  /*RoundToAlign=*/true);
177  ObjSizeEval = &TheObjSizeEval;
178 
179  // check HANDLE_MEMORY_INST in include/llvm/Instruction.def for memory
180  // touching instructions
181  std::vector<Instruction*> WorkList;
182  for (inst_iterator i = inst_begin(F), e = inst_end(F); i != e; ++i) {
183  Instruction *I = &*i;
184  if (isa<LoadInst>(I) || isa<StoreInst>(I) || isa<AtomicCmpXchgInst>(I) ||
185  isa<AtomicRMWInst>(I))
186  WorkList.push_back(I);
187  }
188 
189  bool MadeChange = false;
190  for (std::vector<Instruction*>::iterator i = WorkList.begin(),
191  e = WorkList.end(); i != e; ++i) {
192  Inst = *i;
193 
194  Builder->SetInsertPoint(Inst);
195  if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
196  MadeChange |= instrument(LI->getPointerOperand(), LI);
197  } else if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
198  MadeChange |= instrument(SI->getPointerOperand(), SI->getValueOperand());
199  } else if (AtomicCmpXchgInst *AI = dyn_cast<AtomicCmpXchgInst>(Inst)) {
200  MadeChange |= instrument(AI->getPointerOperand(),AI->getCompareOperand());
201  } else if (AtomicRMWInst *AI = dyn_cast<AtomicRMWInst>(Inst)) {
202  MadeChange |= instrument(AI->getPointerOperand(), AI->getValOperand());
203  } else {
204  llvm_unreachable("unknown Instruction type");
205  }
206  }
207  return MadeChange;
208 }
209 
211  return new BoundsChecking();
212 }
static PassRegistry * getPassRegistry()
LLVMContext & getContext() const
Definition: Function.cpp:167
FunctionPass * createBoundsCheckingPass()
enable_if_c<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:266
F(f)
LoopInfoBase< BlockT, LoopT > * LI
Definition: LoopInfoImpl.h:411
AnalysisUsage & addRequired()
inst_iterator inst_begin(Function *F)
Definition: InstIterator.h:128
const APInt & getValue() const
Return the constant's value.
Definition: Constants.h:105
#define llvm_unreachable(msg)
static cl::opt< bool > SingleTrapBB("bounds-checking-single-trap", cl::desc("Use one trap block per function"))
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=0)
ID
LLVM Calling Convention Representation.
Definition: CallingConv.h:26
uint64_t getZExtValue() const
Return the zero extended value.
Definition: Constants.h:116
Evaluate the size and offset of an object pointed to by a Value*. May create code to compute the resu...
TargetFolder - Create constants with target dependent folding.
Definition: TargetFolder.h:32
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=None)
Definition: Function.cpp:683
LLVM Basic Block Representation.
Definition: BasicBlock.h:72
APInt Or(const APInt &LHS, const APInt &RHS)
Bitwise OR function for APInt.
Definition: APInt.h:1845
STATISTIC(ChecksAdded,"Bounds checks added")
INITIALIZE_PASS(BoundsChecking,"bounds-checking","Run-time bounds checking", false, false) BasicBlock *BoundsChecking
Class for constant integers.
Definition: Constants.h:51
bool slt(const APInt &RHS) const
Signed less than comparison.
Definition: APInt.cpp:547
Type * getType() const
Definition: Value.h:111
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
Definition: Constants.cpp:492
raw_ostream & dbgs()
dbgs - Return a circular-buffered debug stream.
Definition: Debug.cpp:101
Class for arbitrary precision integers.
Definition: APInt.h:75
std::pair< Value *, Value * > SizeOffsetEvalType
#define I(x, y, z)
Definition: MD5.cpp:54
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Definition: BasicBlock.cpp:120
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=0, BasicBlock *InsertBefore=0)
Creates a new BasicBlock.
Definition: BasicBlock.h:109
BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
Definition: BasicBlock.cpp:298
void setDoesNotReturn()
Module * getParent()
Definition: GlobalValue.h:286
LLVM Value Representation.
Definition: Value.h:66
#define DEBUG(X)
Definition: Debug.h:97
inst_iterator inst_end(Function *F)
Definition: InstIterator.h:129
IRBuilder< true, TargetFolder > BuilderTy
const BasicBlock * getParent() const
Definition: Instruction.h:52
INITIALIZE_PASS(GlobalMerge,"global-merge","Global Merge", false, false) bool GlobalMerge const DataLayout * TD
void initializeBoundsCheckingPass(PassRegistry &)