Implement stack protectors as function attributes: "ssp" and "sspreq".
authorBill Wendling <isanbard@gmail.com>
Thu, 13 Nov 2008 01:02:14 +0000 (01:02 +0000)
committerBill Wendling <isanbard@gmail.com>
Thu, 13 Nov 2008 01:02:14 +0000 (01:02 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59202 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Attributes.h
include/llvm/CodeGen/Passes.h
lib/AsmParser/LLLexer.cpp
lib/AsmParser/llvmAsmParser.y
lib/CodeGen/LLVMTargetMachine.cpp
lib/CodeGen/StackProtector.cpp
lib/VMCore/Attributes.cpp

index b2117dd6be76432f933b1f76d408daed63cc863e..57f4e17c47fea25ad2615d0f4d7cfeec9d773321 100644 (file)
@@ -47,6 +47,8 @@ const Attributes ReadOnly  = 1<<10; ///< Function only reads from memory
 const Attributes NoInline        = 1<<11; // inline=never 
 const Attributes AlwaysInline    = 1<<12; // inline=always
 const Attributes OptimizeForSize = 1<<13; // opt_size
+const Attributes StackProtect    = 1<<14; // Stack protection.
+const Attributes StackProtectReq = 1<<15; // Stack protection required.
 const Attributes Alignment = 0xffff<<16; ///< Alignment of parameter (16 bits)
                                     // 0 = unknown, else in clear (not log)
                                     
@@ -55,7 +57,7 @@ const Attributes ParameterOnly = ByVal | Nest | StructRet;
 
 /// @brief Attributes that only apply to function.
 const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly | 
-  NoInline | AlwaysInline | OptimizeForSize;
+  NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq;
 
 /// @brief Parameter attributes that do not apply to vararg call arguments.
 const Attributes VarArgsIncompatible = StructRet;
index a933309854713e57269f4393323fdd8d6831a565..e9d26cf4c235e15bc4009bcb1a5dfce754f43ba8 100644 (file)
@@ -26,16 +26,6 @@ namespace llvm {
   class TargetLowering;
   class RegisterCoalescer;
 
-  /// StackProtectorLevel - An enumeration for when to determin when to turn
-  /// stack smashing protection (SSP) on.
-  namespace SSP {
-    enum StackProtectorLevel {
-      OFF,          // Stack protectors are off.
-      SOME,         // Stack protectors on only for functions that require them.
-      ALL           // Stack protectors on for all functions.
-    };
-  } // end SSP namespace
-
   /// createUnreachableBlockEliminationPass - The LLVM code generator does not
   /// work well with unreachable basic blocks (what live ranges make sense for a
   /// block that cannot be reached?).  As such, a code generator should either
@@ -204,8 +194,7 @@ namespace llvm {
   FunctionPass *createStackSlotColoringPass();
 
   /// createStackProtectorPass - This pass adds stack protectors to functions.
-  FunctionPass *createStackProtectorPass(SSP::StackProtectorLevel lvl,
-                                         const TargetLowering *tli);
+  FunctionPass *createStackProtectorPass(const TargetLowering *tli);
 
 } // End llvm namespace
 
index 39d62bf71cff10bcfcf1ea07cb1965c0115a5f85..20b2b888b1f1f29a3132570c6b569bc3b520efed 100644 (file)
@@ -499,6 +499,8 @@ int LLLexer::LexIdentifier() {
   KEYWORD("noinline", NOINLINE);
   KEYWORD("alwaysinline", ALWAYSINLINE);
   KEYWORD("optsize", OPTSIZE);
+  KEYWORD("ssp", SSP);
+  KEYWORD("sspreq", SSPREQ);
 
   KEYWORD("type", TYPE);
   KEYWORD("opaque", OPAQUE);
index 36b827d6b726548032f6d72f34efff7a6e00fd68..af8e3afee3f6213abce006c314634c24dbac03af 100644 (file)
@@ -1137,7 +1137,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
 
 // Function Attributes
 %token SIGNEXT ZEROEXT NORETURN INREG SRET NOUNWIND NOALIAS BYVAL NEST
-%token READNONE READONLY GC OPTSIZE NOINLINE ALWAYSINLINE
+%token READNONE READONLY GC OPTSIZE NOINLINE ALWAYSINLINE SSP SSPREQ
 
 // Visibility Styles
 %token DEFAULT HIDDEN PROTECTED
@@ -1305,7 +1305,9 @@ FuncAttr      : NORETURN { $$ = Attribute::NoReturn; }
               | READONLY { $$ = Attribute::ReadOnly; }
               | NOINLINE { $$ = Attribute::NoInline; }
               | ALWAYSINLINE { $$ = Attribute::AlwaysInline; }
-              | OPTSIZE { $$ = Attribute::OptimizeForSize; }
+              | OPTSIZE  { $$ = Attribute::OptimizeForSize; }
+              | SSP      { $$ = Attribute::StackProtect; }
+              | SSPREQ   { $$ = Attribute::StackProtectReq; }
               ;
 
 OptFuncAttrs  : /* empty */ { $$ = Attribute::None; }
index fee70b00154baf1b77f32c281e0fa5bb4e3cee5a..2397a160e933d1722810e133d12fbdc1d6b83669 100644 (file)
@@ -60,19 +60,6 @@ static cl::opt<cl::boolOrDefault>
 EnableFastISelOption("fast-isel", cl::Hidden,
   cl::desc("Enable the experimental \"fast\" instruction selector"));
 
-// Enable stack protectors.
-static cl::opt<SSP::StackProtectorLevel>
-EnableStackProtector("enable-stack-protector",
-                     cl::desc("Stack canary protection level: (default: off)"),
-                     cl::init(SSP::OFF),
-                     cl::values(clEnumValN(SSP::ALL,  "all",
-                                         "All functions get stack protectors."),
-                                clEnumValN(SSP::SOME, "some",
-                         "Only functions requiring stack protectors get them."),
-                                clEnumValN(SSP::OFF,  "off",
-                                          "No functions get stack protectors."),
-                                clEnumValEnd));
-
 FileModel::Model
 LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
                                        raw_ostream &Out,
@@ -178,8 +165,7 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, bool Fast) {
   if (!Fast)
     PM.add(createCodeGenPreparePass(getTargetLowering()));
 
-  if (EnableStackProtector != SSP::OFF)
-    PM.add(createStackProtectorPass(EnableStackProtector, getTargetLowering()));
+  PM.add(createStackProtectorPass(getTargetLowering()));
 
   if (PrintISelInput)
     PM.add(createPrintFunctionPass("\n\n"
index 746addeba44e41d1f4c872cebcf5c39c5f396fdf..d724bd71f8042d7282b3811c17ee28e9256a7e86 100644 (file)
@@ -16,6 +16,7 @@
 
 #define DEBUG_TYPE "stack-protector"
 #include "llvm/CodeGen/Passes.h"
+#include "llvm/Attributes.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Function.h"
@@ -37,9 +38,6 @@ SSPBufferSize("stack-protector-buffer-size", cl::init(8),
 
 namespace {
   class VISIBILITY_HIDDEN StackProtector : public FunctionPass {
-    /// Level - The level of stack protection.
-    SSP::StackProtectorLevel Level;
-
     /// TLI - Keep a pointer of a TargetLowering to consult for determining
     /// target type sizes.
     const TargetLowering *TLI;
@@ -64,9 +62,9 @@ namespace {
     bool RequiresStackProtector() const;
   public:
     static char ID;             // Pass identification, replacement for typeid.
-    StackProtector() : FunctionPass(&ID), Level(SSP::OFF), TLI(0) {}
-    StackProtector(SSP::StackProtectorLevel lvl, const TargetLowering *tli)
-      : FunctionPass(&ID), Level(lvl), TLI(tli) {}
+    StackProtector() : FunctionPass(&ID), TLI(0) {}
+    StackProtector(const TargetLowering *tli)
+      : FunctionPass(&ID), TLI(tli) {}
 
     virtual bool runOnFunction(Function &Fn);
   };
@@ -76,9 +74,8 @@ char StackProtector::ID = 0;
 static RegisterPass<StackProtector>
 X("stack-protector", "Insert stack protectors");
 
-FunctionPass *llvm::createStackProtectorPass(SSP::StackProtectorLevel lvl,
-                                             const TargetLowering *tli) {
-  return new StackProtector(lvl, tli);
+FunctionPass *llvm::createStackProtectorPass(const TargetLowering *tli) {
+  return new StackProtector(tli);
 }
 
 bool StackProtector::runOnFunction(Function &Fn) {
@@ -193,10 +190,10 @@ BasicBlock *StackProtector::CreateFailBB() {
 /// add a guard variable to functions that call alloca, and functions with
 /// buffers larger than 8 bytes.
 bool StackProtector::RequiresStackProtector() const {
-  switch (Level) {
-  default: return false;
-  case SSP::ALL: return true;
-  case SSP::SOME: {
+  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) {
@@ -220,5 +217,6 @@ bool StackProtector::RequiresStackProtector() const {
 
     return false;
   }
-  }
+
+  return false;
 }
index 433b79d77c9ba2da3934dfd9a79b98794449e82a..92acc111be952f21ddcc3b2570c525492ceb7757 100644 (file)
@@ -53,6 +53,10 @@ std::string Attribute::getAsString(Attributes Attrs) {
     Result += "noinline ";
   if (Attrs & Attribute::AlwaysInline)
     Result += "alwaysinline ";
+  if (Attrs & Attribute::StackProtect)
+    Result += "ssp ";
+  if (Attrs & Attribute::StackProtectReq)
+    Result += "sspreq ";
   if (Attrs & Attribute::Alignment) {
     Result += "align ";
     Result += utostr((Attrs & Attribute::Alignment) >> 16);