-/// InsertStackProtectorEpilogue - Insert code before the return instructions
-/// checking the stack value that was stored in the prologue. If it isn't the
-/// same as the original value, then call a "failure" function.
-void StackProtector::InsertStackProtectorEpilogue() {
- // Create the basic block to jump to when the guard check fails.
- CreateFailBB();
-
- Function::iterator I = F->begin(), E = F->end();
- std::vector<BasicBlock*> ReturnBBs;
- ReturnBBs.reserve(F->size());
-
- for (; I != E; ++I)
- if (isa<ReturnInst>(I->getTerminator()))
- ReturnBBs.push_back(I);
-
- if (ReturnBBs.empty()) return; // Odd, but could happen. . .
-
- // Loop through the basic blocks that have return instructions. Convert this:
- //
- // return:
- // ...
- // ret ...
- //
- // into this:
- //
- // return:
- // ...
- // %1 = load __stack_chk_guard
- // %2 = load <stored stack guard>
- // %3 = cmp i1 %1, %2
- // br i1 %3, label %SPRet, label %CallStackCheckFailBlk
- //
- // SPRet:
- // ret ...
- //
- // CallStackCheckFailBlk:
- // call void @__stack_chk_fail()
- // unreachable
- //
- for (std::vector<BasicBlock*>::iterator
- II = ReturnBBs.begin(), IE = ReturnBBs.end(); II != IE; ++II) {
- BasicBlock *BB = *II;
- ReturnInst *RI = cast<ReturnInst>(BB->getTerminator());
- Function::iterator InsPt = BB; ++InsPt; // Insertion point for new BB.
-
- BasicBlock *NewBB = BasicBlock::Create("SPRet", F, InsPt);
-
- // Move the return instruction into the new basic block.
- RI->removeFromParent();
- NewBB->getInstList().insert(NewBB->begin(), RI);
-
- LoadInst *LI2 = new LoadInst(StackGuardVar, "", false, BB);
- LoadInst *LI1 = new LoadInst(StackProtFrameSlot, "", true, BB);
- ICmpInst *Cmp = new ICmpInst(CmpInst::ICMP_EQ, LI1, LI2, "", BB);
+/// InsertStackProtectors - Insert code into the prologue and epilogue of the
+/// function.
+///
+/// - The prologue code loads and stores the stack guard onto the stack.
+/// - The epilogue checks the value stored in the prologue against the original
+/// value. It calls __stack_chk_fail if they differ.
+bool StackProtector::InsertStackProtectors() {
+ BasicBlock *FailBB = 0; // The basic block to jump to if check fails.
+ AllocaInst *AI = 0; // Place on stack that stores the stack guard.
+ Constant *StackGuardVar = 0; // The stack guard variable.
+
+ for (Function::iterator I = F->begin(), E = F->end(); I != E; ) {
+ BasicBlock *BB = I++;
+
+ ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator());
+ if (!RI) continue;
+
+ if (!FailBB) {
+ // Insert code into the entry block that stores the __stack_chk_guard
+ // variable onto the stack:
+ //
+ // entry:
+ // 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);
+
+ BasicBlock &Entry = F->getEntryBlock();
+ Instruction *InsPt = &Entry.front();
+
+ AI = new AllocaInst(PtrTy, "StackGuardSlot", InsPt);
+ LoadInst *LI = new LoadInst(StackGuardVar, "StackGuard", false, InsPt);
+
+ Value *Args[] = { LI, AI };
+ CallInst::
+ Create(Intrinsic::getDeclaration(M, Intrinsic::stackprotector),
+ &Args[0], array_endof(Args), "", InsPt);
+
+ // Create the basic block to jump to when the guard check fails.
+ FailBB = CreateFailBB();
+ }
+
+ // For each block with a return instruction, convert this:
+ //
+ // return:
+ // ...
+ // ret ...
+ //
+ // into this:
+ //
+ // return:
+ // ...
+ // %1 = load __stack_chk_guard
+ // %2 = load StackGuardSlot
+ // %3 = cmp i1 %1, %2
+ // br i1 %3, label %SP_return, label %CallStackCheckFailBlk
+ //
+ // SP_return:
+ // ret ...
+ //
+ // CallStackCheckFailBlk:
+ // call void @__stack_chk_fail()
+ // unreachable
+
+ // Split the basic block before the return instruction.
+ BasicBlock *NewBB = BB->splitBasicBlock(RI, "SP_return");
+
+ // 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);
+
+ // 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(*BB, CmpInst::ICMP_EQ, LI1, LI2, "");