blob: a0560f99428979f33f4350c3b8dd39f572cfd462 [file] [log] [blame]
//===- GEPChecks.cpp - Insert GEP run-time checks ------------------------- --//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass instruments GEPs with run-time checks to ensure safe array and
// structure indexing.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "safecode"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/CommandLine.h"
#include "safecode/GEPChecks.h"
#include "safecode/Utility.h"
namespace llvm {
char InsertGEPChecks::ID = 0;
static RegisterPass<InsertGEPChecks>
X ("gepchecks", "Insert GEP run-time checks");
//
// Command Line Options
//
// Disable checks on pure structure indexing
cl::opt<bool> DisableStructChecks ("disable-structgepchecks", cl::Hidden,
cl::init(false),
cl::desc("Disable Struct GEP Checks"));
// Pass Statistics
namespace {
STATISTIC (GEPChecks, "Bounds Checks Added");
STATISTIC (SafeGEP, "GEPs proven safe by SAFECode");
}
//
// Method: visitGetElementPtrInst()
//
// Description:
// This method checks to see if the specified GEP is safe. If it cannot prove
// it safe, it then adds a run-time check for it.
//
void
InsertGEPChecks::visitGetElementPtrInst (GetElementPtrInst & GEP) {
//
// Determine if the GEP is safe. If it is, then don't do anything.
//
if (abcPass->isGEPSafe(&GEP)) {
++SafeGEP;
return;
}
//
// If this only indexes into a structure, ignore it.
//
if (DisableStructChecks && indexesStructsOnly (&GEP)) {
return;
}
//
// Get the function in which the GEP instruction lives.
//
Value * PH = ConstantPointerNull::get (getVoidPtrType(GEP.getContext()));
BasicBlock::iterator InsertPt = &GEP;
++InsertPt;
Instruction * ResultPtr = castTo (&GEP,
getVoidPtrType(GEP.getContext()),
GEP.getName() + ".cast",
InsertPt);
//
// Make this an actual cast instruction; it will make it easier to update
// DSA.
//
Value * SrcPtr = castTo (GEP.getPointerOperand(),
getVoidPtrType(GEP.getContext()),
GEP.getName()+".cast",
InsertPt);
//
// Create the call to the run-time check.
//
std::vector<Value *> args(1, PH);
args.push_back (SrcPtr);
args.push_back (ResultPtr);
CallInst * CI = CallInst::Create (PoolCheckArrayUI, args, "", InsertPt);
//
// Add debugging info metadata to the run-time check.
//
if (MDNode * MD = GEP.getMetadata ("dbg"))
CI->setMetadata ("dbg", MD);
//
// Update the statistics.
//
++GEPChecks;
return;
}
//
// Method: doInitialization()
//
// Description:
// Perform module-level initialization before the pass is run. For this
// pass, we need to create a function prototype for the GEP check function.
//
// Inputs:
// M - A reference to the LLVM module to modify.
//
// Return value:
// true - This LLVM module has been modified.
//
bool
InsertGEPChecks::doInitialization (Module & M) {
//
// Create a function prototype for the function that performs incomplete
// pointer arithmetic (GEP) checks.
//
Type * VoidPtrTy = getVoidPtrType (M.getContext());
M.getOrInsertFunction ("boundscheckui",
VoidPtrTy,
VoidPtrTy,
VoidPtrTy,
VoidPtrTy,
NULL);
return true;
}
bool
InsertGEPChecks::runOnFunction (Function & F) {
//
// Get pointers to required analysis passes.
//
TD = &getAnalysis<TargetData>();
abcPass = &getAnalysis<ArrayBoundsCheckLocal>();
//
// Get a pointer to the run-time check function.
//
PoolCheckArrayUI = F.getParent()->getFunction ("boundscheckui");
//
// Visit all of the instructions in the function.
//
visit (F);
return true;
}
}