summaryrefslogtreecommitdiff
path: root/lib/CodeGen/StackProtector.cpp
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2008-11-18 05:32:11 +0000
committerBill Wendling <isanbard@gmail.com>2008-11-18 05:32:11 +0000
commitc3348a77f7e1bdc8e52a9f70fd190555df34d7c1 (patch)
tree0bbc5bcc103d759dc39b07c274adf028889e6b10 /lib/CodeGen/StackProtector.cpp
parent6c2fe2237bf21aa4bfe05ba3135d82e66235e97d (diff)
downloadllvm-c3348a77f7e1bdc8e52a9f70fd190555df34d7c1.tar.gz
llvm-c3348a77f7e1bdc8e52a9f70fd190555df34d7c1.tar.bz2
llvm-c3348a77f7e1bdc8e52a9f70fd190555df34d7c1.tar.xz
- Use "moveAfter" instead of "remove/insert" of a basic block.
- Use less indentation in coding. - Shorten description. - Update comments. - Move code around git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59496 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/StackProtector.cpp')
-rw-r--r--lib/CodeGen/StackProtector.cpp207
1 files changed, 104 insertions, 103 deletions
diff --git a/lib/CodeGen/StackProtector.cpp b/lib/CodeGen/StackProtector.cpp
index d724bd71f8..10b5d6d07f 100644
--- a/lib/CodeGen/StackProtector.cpp
+++ b/lib/CodeGen/StackProtector.cpp
@@ -33,8 +33,8 @@ using namespace llvm;
// smashing protection.
static cl::opt<unsigned>
SSPBufferSize("stack-protector-buffer-size", cl::init(8),
- cl::desc("The lower bound for a buffer to be considered for "
- "stack smashing protection."));
+ cl::desc("Lower bound for a buffer to be considered for "
+ "stack protection"));
namespace {
class VISIBILITY_HIDDEN StackProtector : public FunctionPass {
@@ -87,6 +87,41 @@ bool StackProtector::runOnFunction(Function &Fn) {
return InsertStackProtectors();
}
+/// 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))
+ return true;
+
+ if (!F->hasFnAttr(Attribute::StackProtect))
+ return false;
+
+ const TargetData *TD = TLI->getTargetData();
+
+ for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
+ BasicBlock *BB = I;
+
+ for (BasicBlock::iterator
+ II = BB->begin(), IE = BB->end(); II != IE; ++II)
+ if (AllocaInst *AI = dyn_cast<AllocaInst>(II)) {
+ if (AI->isArrayAllocation())
+ // This is a call to alloca with a variable size. Emit stack
+ // protectors.
+ return true;
+
+ if (const ArrayType *AT = dyn_cast<ArrayType>(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;
+ }
+ }
+
+ return false;
+}
+
/// InsertStackProtectors - Insert code into the prologue and epilogue of the
/// function.
///
@@ -94,77 +129,79 @@ bool StackProtector::runOnFunction(Function &Fn) {
/// - The epilogue checks the value stored in the prologue against the original
/// value. It calls __stack_chk_fail if they differ.
bool StackProtector::InsertStackProtectors() {
- // 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
- //
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;
-
- if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
- if (!FailBB) {
- // Insert code into the entry block that stores the __stack_chk_guard
- // variable onto the stack.
- 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_create),
- &Args[0], array_endof(Args), "", InsPt);
-
- // Create the basic block to jump to when the guard check fails.
- FailBB = CreateFailBB();
- }
-
- ++I; // Skip to the next block so that we don't resplit the return block.
-
- // Split the basic block before the return instruction.
- BasicBlock *NewBB = BB->splitBasicBlock(RI, "SP_return");
-
- // 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->removeFromParent();
- F->getBasicBlockList().insert(I, NewBB);
-
- // Generate the stack protector instructions in the old basic block.
- LoadInst *LI1 = new LoadInst(StackGuardVar, "", false, BB);
- CallInst *CI = CallInst::
- Create(Intrinsic::getDeclaration(M, Intrinsic::stackprotector_check),
- AI, "", BB);
- ICmpInst *Cmp = new ICmpInst(CmpInst::ICMP_EQ, CI, LI1, "", BB);
- BranchInst::Create(NewBB, FailBB, Cmp, BB);
- } else {
- ++I;
+ 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_create),
+ &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 = call i8* @llvm.stackprotect.check(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");
+
+ // 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 *LI = new LoadInst(StackGuardVar, "", false, BB);
+ CallInst *CI = CallInst::
+ Create(Intrinsic::getDeclaration(M, Intrinsic::stackprotector_check),
+ AI, "", BB);
+ ICmpInst *Cmp = new ICmpInst(CmpInst::ICMP_EQ, CI, LI, "", BB);
+ BranchInst::Create(NewBB, FailBB, Cmp, BB);
}
// Return if we didn't modify any basic blocks. I.e., there are no return
@@ -184,39 +221,3 @@ BasicBlock *StackProtector::CreateFailBB() {
new UnreachableInst(FailBB);
return FailBB;
}
-
-/// 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 8 bytes.
-bool StackProtector::RequiresStackProtector() const {
- if (F->hasFnAttr(Attribute::StackProtectReq))
- return true;
-
- if (F->hasFnAttr(Attribute::StackProtect)) {
- const TargetData *TD = TLI->getTargetData();
-
- for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
- BasicBlock *BB = I;
-
- for (BasicBlock::iterator
- II = BB->begin(), IE = BB->end(); II != IE; ++II)
- if (AllocaInst *AI = dyn_cast<AllocaInst>(II)) {
- if (AI->isArrayAllocation())
- // This is a call to alloca with a variable size. Emit stack
- // protectors.
- return true;
-
- if (const ArrayType *AT = dyn_cast<ArrayType>(AI->getAllocatedType()))
- // If an array has more than 8 bytes of allocated space, then we
- // emit stack protectors.
- if (SSPBufferSize <= TD->getABITypeSize(AT))
- return true;
- }
- }
-
- return false;
- }
-
- return false;
-}