StackProtector.cpp revision 53aac15a607d66926e586c7fc57634f6be4ef443
1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//===-- StackProtector.cpp - Stack Protector Insertion --------------------===// 2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// The LLVM Compiler Infrastructure 4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// This file is distributed under the University of Illinois Open Source 6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// License. See LICENSE.TXT for details. 7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//===----------------------------------------------------------------------===// 9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// This pass inserts stack protectors into functions which need them. A variable 11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// with a random value in it is stored onto the stack before the local variables 12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// are allocated. Upon exiting the block, the stored value is checked. If it's 13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// changed, then there was some sort of violation and the program aborts. 14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//===----------------------------------------------------------------------===// 16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define DEBUG_TYPE "stack-protector" 18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/CodeGen/Passes.h" 19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/Analysis/Dominators.h" 20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/Attributes.h" 21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/Constants.h" 22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/DerivedTypes.h" 23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/Function.h" 24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/Instructions.h" 25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/Intrinsics.h" 26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/Module.h" 27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/Pass.h" 28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/Support/CommandLine.h" 29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/Target/TargetData.h" 30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/Target/TargetLowering.h" 31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgusing namespace llvm; 32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// SSPBufferSize - The lower bound for a buffer to be considered for stack 34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// smashing protection. 35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic cl::opt<unsigned> 36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgSSPBufferSize("stack-protector-buffer-size", cl::init(8), 37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org cl::desc("Lower bound for a buffer to be considered for " 38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "stack protection")); 39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace { 41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org class StackProtector : public FunctionPass { 42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /// TLI - Keep a pointer of a TargetLowering to consult for determining 43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /// target type sizes. 44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const TargetLowering *TLI; 45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Function *F; 47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Module *M; 48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DominatorTree* DT; 50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /// InsertStackProtectors - Insert code into the prologue and epilogue of 52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /// the function. 53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /// 54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /// - The prologue code loads and stores the stack guard onto the stack. 55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /// - The epilogue checks the value stored in the prologue against the 56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /// original value. It calls __stack_chk_fail if they differ. 57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool InsertStackProtectors(); 58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /// CreateFailBB - Create a basic block to jump to when the stack protector 60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /// check fails. 61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org BasicBlock *CreateFailBB(); 62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /// RequiresStackProtector - Check whether or not this function needs a 64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /// stack protector based upon the stack protector level. 65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool RequiresStackProtector() const; 66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org public: 67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org static char ID; // Pass identification, replacement for typeid. 68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org StackProtector() : FunctionPass(ID), TLI(0) { 69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org initializeStackProtectorPass(*PassRegistry::getPassRegistry()); 70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org StackProtector(const TargetLowering *tli) 72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org : FunctionPass(ID), TLI(tli) { 73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org initializeStackProtectorPass(*PassRegistry::getPassRegistry()); 74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual void getAnalysisUsage(AnalysisUsage &AU) const { 77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org AU.addPreserved<DominatorTree>(); 78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual bool runOnFunction(Function &Fn); 81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org }; 82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} // end anonymous namespace 83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgchar StackProtector::ID = 0; 85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgINITIALIZE_PASS(StackProtector, "stack-protector", 86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "Insert stack protectors", false, false) 87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgFunctionPass *llvm::createStackProtectorPass(const TargetLowering *tli) { 89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return new StackProtector(tli); 90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool StackProtector::runOnFunction(Function &Fn) { 93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org F = &Fn; 94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org M = F->getParent(); 95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DT = getAnalysisIfAvailable<DominatorTree>(); 96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!RequiresStackProtector()) return false; 98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return InsertStackProtectors(); 100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// RequiresStackProtector - Check whether or not this function needs a stack 103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// protector based upon the stack protector level. The heuristic we use is to 104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// add a guard variable to functions that call alloca, and functions with 105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// buffers larger than SSPBufferSize bytes. 106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool StackProtector::RequiresStackProtector() const { 107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (F->hasFnAttr(Attribute::StackProtectReq)) 108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!F->hasFnAttr(Attribute::StackProtect)) 111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const TargetData *TD = TLI->getTargetData(); 114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { 116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org BasicBlock *BB = I; 117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (BasicBlock::iterator 119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org II = BB->begin(), IE = BB->end(); II != IE; ++II) 120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (AllocaInst *AI = dyn_cast<AllocaInst>(II)) { 121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (AI->isArrayAllocation()) 122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // This is a call to alloca with a variable size. Emit stack 123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // protectors. 124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (const ArrayType *AT = dyn_cast<ArrayType>(AI->getAllocatedType())) { 127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // We apparently only care about character arrays. 128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!AT->getElementType()->isIntegerTy(8)) 129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org continue; 130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // If an array has more than SSPBufferSize bytes of allocated space, 132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // then we emit stack protectors. 133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (SSPBufferSize <= TD->getTypeAllocSize(AT)) 134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// InsertStackProtectors - Insert code into the prologue and epilogue of the 143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// function. 144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// 145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// - The prologue code loads and stores the stack guard onto the stack. 146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// - The epilogue checks the value stored in the prologue against the original 147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// value. It calls __stack_chk_fail if they differ. 148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool StackProtector::InsertStackProtectors() { 149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org BasicBlock *FailBB = 0; // The basic block to jump to if check fails. 150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org BasicBlock *FailBBDom = 0; // FailBB's dominator. 151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org AllocaInst *AI = 0; // Place on stack that stores the stack guard. 152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Value *StackGuardVar = 0; // The stack guard variable. 153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (Function::iterator I = F->begin(), E = F->end(); I != E; ) { 155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org BasicBlock *BB = I++; 156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator()); 158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!RI) continue; 159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!FailBB) { 161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Insert code into the entry block that stores the __stack_chk_guard 162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // variable onto the stack: 163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // 164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // entry: 165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // StackGuardSlot = alloca i8* 166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // StackGuard = load __stack_chk_guard 167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // call void @llvm.stackprotect.create(StackGuard, StackGuardSlot) 168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // 169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const PointerType *PtrTy = Type::getInt8PtrTy(RI->getContext()); 170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned AddressSpace, Offset; 171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (TLI->getStackCookieLocation(AddressSpace, Offset)) { 172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Constant *OffsetVal = 173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ConstantInt::get(Type::getInt32Ty(RI->getContext()), Offset); 174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org StackGuardVar = ConstantExpr::getIntToPtr(OffsetVal, 176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PointerType::get(PtrTy, AddressSpace)); 177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard", PtrTy); 179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org BasicBlock &Entry = F->getEntryBlock(); 182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Instruction *InsPt = &Entry.front(); 183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org AI = new AllocaInst(PtrTy, "StackGuardSlot", InsPt); 185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LoadInst *LI = new LoadInst(StackGuardVar, "StackGuard", false, InsPt); 186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Value *Args[] = { LI, AI }; 188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CallInst:: 189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Create(Intrinsic::getDeclaration(M, Intrinsic::stackprotector), 190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org &Args[0], array_endof(Args), "", InsPt); 191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Create the basic block to jump to when the guard check fails. 193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org FailBB = CreateFailBB(); 194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (DT) 195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org FailBBDom = DT->isReachableFromEntry(BB) ? BB : 0; 196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // For each block with a return instruction, convert this: 199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // 200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // return: 201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // ... 202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // ret ... 203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // 204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // into this: 205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // 206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // return: 207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // ... 208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // %1 = load __stack_chk_guard 209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // %2 = load StackGuardSlot 210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // %3 = cmp i1 %1, %2 211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // br i1 %3, label %SP_return, label %CallStackCheckFailBlk 212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // 213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // SP_return: 214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // ret ... 215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // 216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // CallStackCheckFailBlk: 217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // call void @__stack_chk_fail() 218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // unreachable 219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Split the basic block before the return instruction. 221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org BasicBlock *NewBB = BB->splitBasicBlock(RI, "SP_return"); 222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (DT && DT->isReachableFromEntry(BB)) { 223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DT->addNewBlock(NewBB, BB); 224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org FailBBDom = DT->findNearestCommonDominator(FailBBDom, BB); 225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Remove default branch instruction to the new BB. 228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org BB->getTerminator()->eraseFromParent(); 229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Move the newly created basic block to the point right after the old basic 231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // block so that it's in the "fall through" position. 232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org NewBB->moveAfter(BB); 233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Generate the stack protector instructions in the old basic block. 235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LoadInst *LI1 = new LoadInst(StackGuardVar, "", false, BB); 236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LoadInst *LI2 = new LoadInst(AI, "", true, BB); 237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ICmpInst *Cmp = new ICmpInst(*BB, CmpInst::ICMP_EQ, LI1, LI2, ""); 238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org BranchInst::Create(NewBB, FailBB, Cmp, BB); 239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Return if we didn't modify any basic blocks. I.e., there are no return 242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // statements in the function. 243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!FailBB) return false; 244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (DT && FailBBDom) 246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org DT->addNewBlock(FailBB, FailBBDom); 247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// CreateFailBB - Create a basic block to jump to when the stack protector 252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// check fails. 253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgBasicBlock *StackProtector::CreateFailBB() { 254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org BasicBlock *FailBB = BasicBlock::Create(F->getContext(), 255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "CallStackCheckFailBlk", F); 256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Constant *StackChkFail = 257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org M->getOrInsertFunction("__stack_chk_fail", 258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Type::getVoidTy(F->getContext()), NULL); 259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CallInst::Create(StackChkFail, "", FailBB); 260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org new UnreachableInst(F->getContext(), FailBB); 261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return FailBB; 262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org