X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FStackProtector.cpp;h=31e9ec0ac0b9751361a75a97c3d537b34847be51;hb=e3d0e86919730784faaddcb5d9b0257c39b0804b;hp=8fe6529ef44894033c658802169ec6d1baa4b359;hpb=733bbc5320ac9d729caa8c0fe741dd516e7eda0b;p=oota-llvm.git diff --git a/lib/CodeGen/StackProtector.cpp b/lib/CodeGen/StackProtector.cpp index 8fe6529ef44..31e9ec0ac0b 100644 --- a/lib/CodeGen/StackProtector.cpp +++ b/lib/CodeGen/StackProtector.cpp @@ -16,6 +16,7 @@ #define DEBUG_TYPE "stack-protector" #include "llvm/CodeGen/Passes.h" +#include "llvm/Analysis/Dominators.h" #include "llvm/Attributes.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" @@ -25,19 +26,14 @@ #include "llvm/Module.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Target/TargetData.h" +#include "llvm/DataLayout.h" #include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/Triple.h" using namespace llvm; -// SSPBufferSize - The lower bound for a buffer to be considered for stack -// smashing protection. -static cl::opt -SSPBufferSize("stack-protector-buffer-size", cl::init(8), - cl::desc("Lower bound for a buffer to be considered for " - "stack protection")); - namespace { - class VISIBILITY_HIDDEN StackProtector : public FunctionPass { + class StackProtector : public FunctionPass { /// TLI - Keep a pointer of a TargetLowering to consult for determining /// target type sizes. const TargetLowering *TLI; @@ -45,6 +41,8 @@ namespace { Function *F; Module *M; + DominatorTree *DT; + /// InsertStackProtectors - Insert code into the prologue and epilogue of /// the function. /// @@ -57,22 +55,35 @@ namespace { /// check fails. BasicBlock *CreateFailBB(); + /// ContainsProtectableArray - Check whether the type either is an array or + /// contains an array of sufficient size so that we need stack protectors + /// for it. + bool ContainsProtectableArray(Type *Ty, bool InStruct = false) const; + /// RequiresStackProtector - Check whether or not this function needs a /// stack protector based upon the stack protector level. bool RequiresStackProtector() const; public: static char ID; // Pass identification, replacement for typeid. - StackProtector() : FunctionPass(&ID), TLI(0) {} + StackProtector() : FunctionPass(ID), TLI(0) { + initializeStackProtectorPass(*PassRegistry::getPassRegistry()); + } StackProtector(const TargetLowering *tli) - : FunctionPass(&ID), TLI(tli) {} + : FunctionPass(ID), TLI(tli) { + initializeStackProtectorPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreserved(); + } virtual bool runOnFunction(Function &Fn); }; } // end anonymous namespace char StackProtector::ID = 0; -static RegisterPass -X("stack-protector", "Insert stack protectors"); +INITIALIZE_PASS(StackProtector, "stack-protector", + "Insert stack protectors", false, false) FunctionPass *llvm::createStackProtectorPass(const TargetLowering *tli) { return new StackProtector(tli); @@ -81,25 +92,57 @@ FunctionPass *llvm::createStackProtectorPass(const TargetLowering *tli) { bool StackProtector::runOnFunction(Function &Fn) { F = &Fn; M = F->getParent(); + DT = getAnalysisIfAvailable(); if (!RequiresStackProtector()) return false; - + return InsertStackProtectors(); } +/// ContainsProtectableArray - Check whether the type either is an array or +/// contains a char array of sufficient size so that we need stack protectors +/// for it. +bool StackProtector::ContainsProtectableArray(Type *Ty, bool InStruct) const { + if (!Ty) return false; + if (ArrayType *AT = dyn_cast(Ty)) { + const TargetMachine &TM = TLI->getTargetMachine(); + if (!AT->getElementType()->isIntegerTy(8)) { + Triple Trip(TM.getTargetTriple()); + + // If we're on a non-Darwin platform or we're inside of a structure, don't + // add stack protectors unless the array is a character array. + if (InStruct || !Trip.isOSDarwin()) + return false; + } + + // If an array has more than SSPBufferSize bytes of allocated space, then we + // emit stack protectors. + if (TM.Options.SSPBufferSize <= TLI->getDataLayout()->getTypeAllocSize(AT)) + return true; + } + + const StructType *ST = dyn_cast(Ty); + if (!ST) return false; + + for (StructType::element_iterator I = ST->element_begin(), + E = ST->element_end(); I != E; ++I) + if (ContainsProtectableArray(*I, true)) + return true; + + return false; +} + /// RequiresStackProtector - Check whether or not this function needs a stack /// protector based upon the stack protector level. The heuristic we use is to /// add a guard variable to functions that call alloca, and functions with /// buffers larger than SSPBufferSize bytes. bool StackProtector::RequiresStackProtector() const { - if (F->hasFnAttr(Attribute::StackProtectReq)) + if (F->getFnAttributes().hasAttribute(Attributes::StackProtectReq)) return true; - if (!F->hasFnAttr(Attribute::StackProtect)) + if (!F->getFnAttributes().hasAttribute(Attributes::StackProtect)) return false; - const TargetData *TD = TLI->getTargetData(); - for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { BasicBlock *BB = I; @@ -111,11 +154,8 @@ bool StackProtector::RequiresStackProtector() const { // protectors. return true; - if (const ArrayType *AT = dyn_cast(AI->getAllocatedType())) - // If an array has more than SSPBufferSize bytes of allocated space, - // then we emit stack protectors. - if (SSPBufferSize <= TD->getABITypeSize(AT)) - return true; + if (ContainsProtectableArray(AI->getAllocatedType())) + return true; } } @@ -130,12 +170,12 @@ bool StackProtector::RequiresStackProtector() const { /// value. It calls __stack_chk_fail if they differ. bool StackProtector::InsertStackProtectors() { BasicBlock *FailBB = 0; // The basic block to jump to if check fails. + BasicBlock *FailBBDom = 0; // FailBB's dominator. AllocaInst *AI = 0; // Place on stack that stores the stack guard. - Constant *StackGuardVar = 0; // The stack guard variable. + Value *StackGuardVar = 0; // The stack guard variable. for (Function::iterator I = F->begin(), E = F->end(); I != E; ) { BasicBlock *BB = I++; - ReturnInst *RI = dyn_cast(BB->getTerminator()); if (!RI) continue; @@ -147,9 +187,18 @@ bool StackProtector::InsertStackProtectors() { // StackGuardSlot = alloca i8* // StackGuard = load __stack_chk_guard // call void @llvm.stackprotect.create(StackGuard, StackGuardSlot) - // - PointerType *PtrTy = PointerType::getUnqual(Type::Int8Ty); - StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard", PtrTy); + // + PointerType *PtrTy = Type::getInt8PtrTy(RI->getContext()); + unsigned AddressSpace, Offset; + if (TLI->getStackCookieLocation(AddressSpace, Offset)) { + Constant *OffsetVal = + ConstantInt::get(Type::getInt32Ty(RI->getContext()), Offset); + + StackGuardVar = ConstantExpr::getIntToPtr(OffsetVal, + PointerType::get(PtrTy, AddressSpace)); + } else { + StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard", PtrTy); + } BasicBlock &Entry = F->getEntryBlock(); Instruction *InsPt = &Entry.front(); @@ -159,8 +208,8 @@ bool StackProtector::InsertStackProtectors() { Value *Args[] = { LI, AI }; CallInst:: - Create(Intrinsic::getDeclaration(M, Intrinsic::stackprotector_create), - &Args[0], array_endof(Args), "", InsPt); + Create(Intrinsic::getDeclaration(M, Intrinsic::stackprotector), + Args, "", InsPt); // Create the basic block to jump to when the guard check fails. FailBB = CreateFailBB(); @@ -191,6 +240,14 @@ bool StackProtector::InsertStackProtectors() { // Split the basic block before the return instruction. BasicBlock *NewBB = BB->splitBasicBlock(RI, "SP_return"); + if (DT && DT->isReachableFromEntry(BB)) { + DT->addNewBlock(NewBB, BB); + FailBBDom = FailBBDom ? DT->findNearestCommonDominator(FailBBDom, BB) :BB; + } + + // Remove default branch instruction to the new BB. + BB->getTerminator()->eraseFromParent(); + // Move the newly created basic block to the point right after the old basic // block so that it's in the "fall through" position. NewBB->moveAfter(BB); @@ -198,7 +255,7 @@ bool StackProtector::InsertStackProtectors() { // Generate the stack protector instructions in the old basic block. LoadInst *LI1 = new LoadInst(StackGuardVar, "", false, BB); LoadInst *LI2 = new LoadInst(AI, "", true, BB); - ICmpInst *Cmp = new ICmpInst(CmpInst::ICMP_EQ, LI1, LI2, "", BB); + ICmpInst *Cmp = new ICmpInst(*BB, CmpInst::ICMP_EQ, LI1, LI2, ""); BranchInst::Create(NewBB, FailBB, Cmp, BB); } @@ -206,16 +263,21 @@ bool StackProtector::InsertStackProtectors() { // statements in the function. if (!FailBB) return false; + if (DT && FailBBDom) + DT->addNewBlock(FailBB, FailBBDom); + return true; } /// CreateFailBB - Create a basic block to jump to when the stack protector /// check fails. BasicBlock *StackProtector::CreateFailBB() { - BasicBlock *FailBB = BasicBlock::Create("CallStackCheckFailBlk", F); + BasicBlock *FailBB = BasicBlock::Create(F->getContext(), + "CallStackCheckFailBlk", F); Constant *StackChkFail = - M->getOrInsertFunction("__stack_chk_fail", Type::VoidTy, NULL); + M->getOrInsertFunction("__stack_chk_fail", + Type::getVoidTy(F->getContext()), NULL); CallInst::Create(StackChkFail, "", FailBB); - new UnreachableInst(FailBB); + new UnreachableInst(F->getContext(), FailBB); return FailBB; }