llvm.org GIT mirror llvm / e9e6bdf
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 Bill Wendling 11 years ago
7 changed file(s) with 28 addition(s) and 45 deletion(s). Raw diff Collapse all Expand all
4646 const Attributes NoInline = 1<<11; // inline=never
4747 const Attributes AlwaysInline = 1<<12; // inline=always
4848 const Attributes OptimizeForSize = 1<<13; // opt_size
49 const Attributes StackProtect = 1<<14; // Stack protection.
50 const Attributes StackProtectReq = 1<<15; // Stack protection required.
4951 const Attributes Alignment = 0xffff<<16; ///< Alignment of parameter (16 bits)
5052 // 0 = unknown, else in clear (not log)
5153
5456
5557 /// @brief Attributes that only apply to function.
5658 const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly |
57 NoInline | AlwaysInline | OptimizeForSize;
59 NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq;
5860
5961 /// @brief Parameter attributes that do not apply to vararg call arguments.
6062 const Attributes VarArgsIncompatible = StructRet;
2424 class TargetMachine;
2525 class TargetLowering;
2626 class RegisterCoalescer;
27
28 /// StackProtectorLevel - An enumeration for when to determin when to turn
29 /// stack smashing protection (SSP) on.
30 namespace SSP {
31 enum StackProtectorLevel {
32 OFF, // Stack protectors are off.
33 SOME, // Stack protectors on only for functions that require them.
34 ALL // Stack protectors on for all functions.
35 };
36 } // end SSP namespace
3727
3828 /// createUnreachableBlockEliminationPass - The LLVM code generator does not
3929 /// work well with unreachable basic blocks (what live ranges make sense for a
203193 FunctionPass *createStackSlotColoringPass();
204194
205195 /// createStackProtectorPass - This pass adds stack protectors to functions.
206 FunctionPass *createStackProtectorPass(SSP::StackProtectorLevel lvl,
207 const TargetLowering *tli);
196 FunctionPass *createStackProtectorPass(const TargetLowering *tli);
208197
209198 } // End llvm namespace
210199
498498 KEYWORD("noinline", NOINLINE);
499499 KEYWORD("alwaysinline", ALWAYSINLINE);
500500 KEYWORD("optsize", OPTSIZE);
501 KEYWORD("ssp", SSP);
502 KEYWORD("sspreq", SSPREQ);
501503
502504 KEYWORD("type", TYPE);
503505 KEYWORD("opaque", OPAQUE);
11361136
11371137 // Function Attributes
11381138 %token SIGNEXT ZEROEXT NORETURN INREG SRET NOUNWIND NOALIAS BYVAL NEST
1139 %token READNONE READONLY GC OPTSIZE NOINLINE ALWAYSINLINE
1139 %token READNONE READONLY GC OPTSIZE NOINLINE ALWAYSINLINE SSP SSPREQ
11401140
11411141 // Visibility Styles
11421142 %token DEFAULT HIDDEN PROTECTED
13041304 | READONLY { $$ = Attribute::ReadOnly; }
13051305 | NOINLINE { $$ = Attribute::NoInline; }
13061306 | ALWAYSINLINE { $$ = Attribute::AlwaysInline; }
1307 | OPTSIZE { $$ = Attribute::OptimizeForSize; }
1307 | OPTSIZE { $$ = Attribute::OptimizeForSize; }
1308 | SSP { $$ = Attribute::StackProtect; }
1309 | SSPREQ { $$ = Attribute::StackProtectReq; }
13081310 ;
13091311
13101312 OptFuncAttrs : /* empty */ { $$ = Attribute::None; }
5959 EnableFastISelOption("fast-isel", cl::Hidden,
6060 cl::desc("Enable the experimental \"fast\" instruction selector"));
6161
62 // Enable stack protectors.
63 static cl::opt
64 EnableStackProtector("enable-stack-protector",
65 cl::desc("Stack canary protection level: (default: off)"),
66 cl::init(SSP::OFF),
67 cl::values(clEnumValN(SSP::ALL, "all",
68 "All functions get stack protectors."),
69 clEnumValN(SSP::SOME, "some",
70 "Only functions requiring stack protectors get them."),
71 clEnumValN(SSP::OFF, "off",
72 "No functions get stack protectors."),
73 clEnumValEnd));
74
7562 FileModel::Model
7663 LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
7764 raw_ostream &Out,
177164 if (!Fast)
178165 PM.add(createCodeGenPreparePass(getTargetLowering()));
179166
180 if (EnableStackProtector != SSP::OFF)
181 PM.add(createStackProtectorPass(EnableStackProtector, getTargetLowering()));
167 PM.add(createStackProtectorPass(getTargetLowering()));
182168
183169 if (PrintISelInput)
184170 PM.add(createPrintFunctionPass("\n\n"
1515
1616 #define DEBUG_TYPE "stack-protector"
1717 #include "llvm/CodeGen/Passes.h"
18 #include "llvm/Attributes.h"
1819 #include "llvm/Constants.h"
1920 #include "llvm/DerivedTypes.h"
2021 #include "llvm/Function.h"
3637
3738 namespace {
3839 class VISIBILITY_HIDDEN StackProtector : public FunctionPass {
39 /// Level - The level of stack protection.
40 SSP::StackProtectorLevel Level;
41
4240 /// TLI - Keep a pointer of a TargetLowering to consult for determining
4341 /// target type sizes.
4442 const TargetLowering *TLI;
6361 bool RequiresStackProtector() const;
6462 public:
6563 static char ID; // Pass identification, replacement for typeid.
66 StackProtector() : FunctionPass(&ID), Level(SSP::OFF), TLI(0) {}
67 StackProtector(SSP::StackProtectorLevel lvl, const TargetLowering *tli)
68 : FunctionPass(&ID), Level(lvl), TLI(tli) {}
64 StackProtector() : FunctionPass(&ID), TLI(0) {}
65 StackProtector(const TargetLowering *tli)
66 : FunctionPass(&ID), TLI(tli) {}
6967
7068 virtual bool runOnFunction(Function &Fn);
7169 };
7573 static RegisterPass
7674 X("stack-protector", "Insert stack protectors");
7775
78 FunctionPass *llvm::createStackProtectorPass(SSP::StackProtectorLevel lvl,
79 const TargetLowering *tli) {
80 return new StackProtector(lvl, tli);
76 FunctionPass *llvm::createStackProtectorPass(const TargetLowering *tli) {
77 return new StackProtector(tli);
8178 }
8279
8380 bool StackProtector::runOnFunction(Function &Fn) {
192189 /// add a guard variable to functions that call alloca, and functions with
193190 /// buffers larger than 8 bytes.
194191 bool StackProtector::RequiresStackProtector() const {
195 switch (Level) {
196 default: return false;
197 case SSP::ALL: return true;
198 case SSP::SOME: {
192 if (F->hasFnAttr(Attribute::StackProtectReq))
193 return true;
194
195 if (F->hasFnAttr(Attribute::StackProtect)) {
199196 const TargetData *TD = TLI->getTargetData();
200197
201198 for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
219216
220217 return false;
221218 }
222 }
223 }
219
220 return false;
221 }
5252 Result += "noinline ";
5353 if (Attrs & Attribute::AlwaysInline)
5454 Result += "alwaysinline ";
55 if (Attrs & Attribute::StackProtect)
56 Result += "ssp ";
57 if (Attrs & Attribute::StackProtectReq)
58 Result += "sspreq ";
5559 if (Attrs & Attribute::Alignment) {
5660 Result += "align ";
5761 Result += utostr((Attrs & Attribute::Alignment) >> 16);