[llvm-commits] [llvm] r59496 - /llvm/trunk/lib/CodeGen/StackProtector.cpp

Bill Wendling isanbard at gmail.com
Mon Nov 17 21:32:12 PST 2008


Author: void
Date: Mon Nov 17 23:32:11 2008
New Revision: 59496

URL: http://llvm.org/viewvc/llvm-project?rev=59496&view=rev
Log:
- Use "moveAfter" instead of "remove/insert" of a basic block.
- Use less indentation in coding.
- Shorten description.
- Update comments.
- Move code around

Modified:
    llvm/trunk/lib/CodeGen/StackProtector.cpp

Modified: llvm/trunk/lib/CodeGen/StackProtector.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/StackProtector.cpp?rev=59496&r1=59495&r2=59496&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/StackProtector.cpp (original)
+++ llvm/trunk/lib/CodeGen/StackProtector.cpp Mon Nov 17 23:32:11 2008
@@ -33,8 +33,8 @@
 // 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 @@
   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 @@
 ///  - 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;
+    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();
-      }
+    ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator());
+    if (!RI) continue;
 
-      ++I; // Skip to the next block so that we don't resplit the return block.
+    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);
 
-      // 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;
+      // 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 @@
   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;
-}





More information about the llvm-commits mailing list