blob: 63d1daf77faa3d74522bbe140b32614d72c3fce0 [file] [log] [blame]
//===- InitAllocas.cpp - Initialize allocas with pointers -------//
//
// The SAFECode Compiler
//
// 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 file implements a pass that ensures that uninitialized memory created
// by alloca instructions is not used to violate memory safety. It can do this
// in one of two ways:
//
// o) Promote the allocations from stack to heap.
// o) Insert code to initialize the newly allocated memory.
//
// The current implementation implements the latter, but code for the former is
// available but disabled.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "init-allocas"
#include "safecode/InitAllocas.h"
#include "safecode/Utility.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Pass.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Debug.h"
#include <vector>
using namespace llvm;
char llvm::InitAllocas::ID = 0;
static RegisterPass<InitAllocas>
Z ("initallocas", "Initialize stack allocations containing pointers");
namespace {
STATISTIC (InitedAllocas, "Allocas Initialized");
}
//
// Function: getInsertionPoint()
//
// Description:
// Given an alloca instruction, skip past all subsequent alloca instructions
// to find an ideal insertion point for instrumenting the alloca.
//
static inline Instruction *
getInsertionPoint (AllocaInst & AI) {
//
// Start with the instruction immediently after the alloca.
//
BasicBlock::iterator InsertPt = &AI;
++InsertPt;
//
// Keep skipping over instructions while they are allocas.
//
while (isa<AllocaInst>(InsertPt))
++InsertPt;
return InsertPt;
}
namespace llvm {
bool
InitAllocas::doInitialization (Module & M) {
//
// Create needed LLVM types.
//
Type * VoidType = Type::getVoidTy(M.getContext());
Type * Int1Type = IntegerType::getInt1Ty(M.getContext());
Type * Int8Type = IntegerType::getInt8Ty(M.getContext());
Type * Int32Type = IntegerType::getInt32Ty(M.getContext());
Type * VoidPtrType = PointerType::getUnqual(Int8Type);
//
// Add the memset function to the program.
//
M.getOrInsertFunction ("llvm.memset.p0i8.i32",
VoidType,
VoidPtrType,
Int8Type,
Int32Type,
Int32Type,
Int1Type,
NULL);
return true;
}
//
// Method: visitAllocaInst()
//
// Description:
// This method instruments an alloca instruction so that it is zero'ed out
// before any data is loaded from it.
//
void
InitAllocas::visitAllocaInst (AllocaInst & AI) {
//
// Scan for a place to insert the instruction to initialize the
// allocated memory.
//
Instruction * InsertPt = getInsertionPoint (AI);
//
// Zero the alloca with a memset. If this is done more efficiently with stores
// SelectionDAG will lower it appropriately based on target information.
//
DataLayout & TD = getAnalysis<DataLayout>();
//
// Get various types that we'll need.
//
Type * Int1Type = IntegerType::getInt1Ty(AI.getContext());
Type * Int8Type = IntegerType::getInt8Ty(AI.getContext());
Type * Int32Type = IntegerType::getInt32Ty(AI.getContext());
Type * VoidPtrType = getVoidPtrType (AI.getContext());
Type * AllocType = AI.getAllocatedType();
//
// Create a call to memset.
//
Module * M = AI.getParent()->getParent()->getParent();
Function * Memset = cast<Function>(M->getFunction ("llvm.memset.p0i8.i32"));
std::vector<Value *> args;
args.push_back (castTo (&AI, VoidPtrType, AI.getName().str(), InsertPt));
args.push_back (ConstantInt::get(Int8Type, 0));
args.push_back (ConstantInt::get(Int32Type,TD.getTypeAllocSize(AllocType)));
args.push_back (ConstantInt::get(Int32Type,
TD.getABITypeAlignment(AllocType)));
args.push_back (ConstantInt::get(Int1Type, 0));
CallInst::Create (Memset, args, "", InsertPt);
//
// Update statistics.
//
++InitedAllocas;
return;
}
bool
InitAllocas::runOnFunction (Function &F) {
// Don't bother processing external functions
if (F.isDeclaration())
return false;
visit (F);
return true;
}
}