- std::vector<BasicBlock*> ReturnBBs;
-
- for (Function::iterator I = F->begin(); I != F->end(); ++I)
- if (isa<ReturnInst>(I->getTerminator()))
- ReturnBBs.push_back(I);
-
- // If this function doesn't return, don't bother with stack protectors.
- if (ReturnBBs.empty()) return false;
-
- // Insert code into the entry block that stores the __stack_chk_guard variable
- // onto the stack.
- BasicBlock &Entry = F->getEntryBlock();
- Instruction *InsertPt = &Entry.front();
-
- const PointerType *GuardTy = PointerType::getUnqual(Type::Int8Ty);
-
- // The global variable for the stack guard.
- Constant *StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard", GuardTy);
- LoadInst *LI = new LoadInst(StackGuardVar, "StackGuard", false, InsertPt);
- CallInst::
- Create(Intrinsic::getDeclaration(M, Intrinsic::stackprotector_create),
- LI, "", InsertPt);
-
- // Create the basic block to jump to when the guard check fails.
- BasicBlock *FailBB = CreateFailBB();
-
- // 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 %SP_return, label %CallStackCheckFailBlk
- //
- // SP_return:
- // ret ...
- //
- // CallStackCheckFailBlk:
- // call void @__stack_chk_fail()
- // unreachable
- //
- for (std::vector<BasicBlock*>::iterator
- I = ReturnBBs.begin(), E = ReturnBBs.end(); I != E; ++I) {
- BasicBlock *BB = *I;
- ReturnInst *RI = cast<ReturnInst>(BB->getTerminator());
- Function::iterator InsPt = BB; ++InsPt; // Insertion point for new BB.
+ 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.
+ 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<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 = 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();
+
+ 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, "", 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