From e9e6bdf27fca46dc9eca2ebdf73e03747d1859ab Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Thu, 13 Nov 2008 01:02:14 +0000 Subject: [PATCH] Implement stack protectors as function attributes: "ssp" and "sspreq". git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59202 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Attributes.h | 4 +++- include/llvm/CodeGen/Passes.h | 13 +------------ lib/AsmParser/LLLexer.cpp | 2 ++ lib/AsmParser/llvmAsmParser.y | 6 ++++-- lib/CodeGen/LLVMTargetMachine.cpp | 16 +--------------- lib/CodeGen/StackProtector.cpp | 26 ++++++++++++-------------- lib/VMCore/Attributes.cpp | 4 ++++ 7 files changed, 27 insertions(+), 44 deletions(-) diff --git a/include/llvm/Attributes.h b/include/llvm/Attributes.h index b2117dd6be7..57f4e17c47f 100644 --- a/include/llvm/Attributes.h +++ b/include/llvm/Attributes.h @@ -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; diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index a9333098547..e9d26cf4c23 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -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 diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index 39d62bf71cf..20b2b888b1f 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -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); diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index 36b827d6b72..af8e3afee3f 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -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; } diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index fee70b00154..2397a160e93 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -60,19 +60,6 @@ static cl::opt EnableFastISelOption("fast-isel", cl::Hidden, cl::desc("Enable the experimental \"fast\" instruction selector")); -// Enable stack protectors. -static cl::opt -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" diff --git a/lib/CodeGen/StackProtector.cpp b/lib/CodeGen/StackProtector.cpp index 746addeba44..d724bd71f80 100644 --- a/lib/CodeGen/StackProtector.cpp +++ b/lib/CodeGen/StackProtector.cpp @@ -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 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; } diff --git a/lib/VMCore/Attributes.cpp b/lib/VMCore/Attributes.cpp index 433b79d77c9..92acc111be9 100644 --- a/lib/VMCore/Attributes.cpp +++ b/lib/VMCore/Attributes.cpp @@ -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);