llvm.org GIT mirror llvm / 4598b40
[stackprotector] Update the StackProtector pass to perform datalayout analysis. This modifies the pass to classify every SSP-triggering AllocaInst according to an SSPLayoutKind (LargeArray, SmallArray, AddrOf). This analysis is collected by the pass and made available for use, but no other pass uses it yet. The next patch will make use of this analysis in PEI and StackSlot passes. The end goal is to support ssp-strong stack layout rules. WIP. Differential Revision: http://llvm-reviews.chandlerc.com/D1789 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@193653 91177308-0d34-0410-b5e6-96231b3b80d8 Josh Magee 7 years ago
2 changed file(s) with 91 addition(s) and 29 deletion(s). Raw diff Collapse all Expand all
1818
1919 #include "llvm/ADT/SmallPtrSet.h"
2020 #include "llvm/ADT/Triple.h"
21 #include "llvm/ADT/ValueMap.h"
2122 #include "llvm/Pass.h"
2223 #include "llvm/Target/TargetLowering.h"
2324
2829 class PHINode;
2930
3031 class StackProtector : public FunctionPass {
32 public:
33 /// SSPLayoutKind. Stack Smashing Protection (SSP) rules require that
34 /// vulnerable stack allocations are located close the stack protector.
35 enum SSPLayoutKind {
36 SSPLK_None, //< Did not trigger a stack protector. No effect on data
37 //< layout.
38 SSPLK_LargeArray, //< Array or nested array >= SSP-buffer-size. Closest
39 //< to the stack protector.
40 SSPLK_SmallArray, //< Array or nested array < SSP-buffer-size. 2nd closest
41 //< to the stack protector.
42 SSPLK_AddrOf //< The address of this allocation is exposed and
43 //< triggered protection. 3rd closest to the protector.
44 };
45
46 /// A mapping of AllocaInsts to their required SSP layout.
47 typedef ValueMap SSPLayoutMap;
48
49 private:
3150 const TargetMachine *TM;
3251
3352 /// TLI - Keep a pointer of a TargetLowering to consult for determining
3958 Module *M;
4059
4160 DominatorTree *DT;
61
62 /// Layout - Mapping of allocations to the required SSPLayoutKind.
63 /// StackProtector analysis will update this map when determining if an
64 /// AllocaInst triggers a stack protector.
65 SSPLayoutMap Layout;
4266
4367 /// \brief The minimum size of buffers that will receive stack smashing
4468 /// protection when -fstack-protection is used.
6589 /// ContainsProtectableArray - Check whether the type either is an array or
6690 /// contains an array of sufficient size so that we need stack protectors
6791 /// for it.
68 bool ContainsProtectableArray(Type *Ty, bool Strong = false,
92 /// \param [out] IsLarge is set to true if a protectable array is found and
93 /// it is "large" ( >= ssp-buffer-size). In the case of a structure with
94 /// multiple arrays, this gets set if any of them is large.
95 bool ContainsProtectableArray(Type *Ty, bool &IsLarge, bool Strong = false,
6996 bool InStruct = false) const;
7097
7198 /// \brief Check whether a stack allocation has its address taken.
89116 AU.addPreserved();
90117 }
91118
119 SSPLayoutKind getSSPLayout(const AllocaInst *AI) const;
120
92121 virtual bool runOnFunction(Function &Fn);
93122 };
94123 } // end namespace llvm
4747
4848 char StackProtector::ID = 0;
4949 INITIALIZE_PASS(StackProtector, "stack-protector",
50 "Insert stack protectors", false, false)
50 "Insert stack protectors", false, true)
5151
5252 FunctionPass *llvm::createStackProtectorPass(const TargetMachine *TM) {
5353 return new StackProtector(TM);
54 }
55
56 StackProtector::SSPLayoutKind StackProtector::getSSPLayout(const AllocaInst *AI)
57 const {
58 return AI ? Layout.lookup(AI) : SSPLK_None;
5459 }
5560
5661 bool StackProtector::runOnFunction(Function &Fn) {
7176 return InsertStackProtectors();
7277 }
7378
74 /// ContainsProtectableArray - Check whether the type either is an array or
75 /// contains a char array of sufficient size so that we need stack protectors
76 /// for it.
77 bool StackProtector::ContainsProtectableArray(Type *Ty, bool Strong,
78 bool InStruct) const {
79 /// \param [out] IsLarge is set to true if a protectable array is found and
80 /// it is "large" ( >= ssp-buffer-size). In the case of a structure with
81 /// multiple arrays, this gets set if any of them is large.
82 bool StackProtector::ContainsProtectableArray(Type *Ty, bool &IsLarge,
83 bool Strong, bool InStruct)
84 const {
7985 if (!Ty) return false;
8086 if (ArrayType *AT = dyn_cast(Ty)) {
81 // In strong mode any array, regardless of type and size, triggers a
82 // protector
83 if (Strong)
84 return true;
8587 if (!AT->getElementType()->isIntegerTy(8)) {
8688 // If we're on a non-Darwin platform or we're inside of a structure, don't
8789 // add stack protectors unless the array is a character array.
88 if (InStruct || !Trip.isOSDarwin())
89 return false;
90 // However, in strong mode any array, regardless of type and size,
91 // triggers a protector.
92 if (!Strong && (InStruct || !Trip.isOSDarwin()))
93 return false;
9094 }
9195
9296 // If an array has more than SSPBufferSize bytes of allocated space, then we
9397 // emit stack protectors.
94 if (SSPBufferSize <= TLI->getDataLayout()->getTypeAllocSize(AT))
98 if (SSPBufferSize <= TLI->getDataLayout()->getTypeAllocSize(AT)) {
99 IsLarge = true;
100 return true;
101 }
102
103 if (Strong)
104 // Require a protector for all arrays in strong mode
95105 return true;
96106 }
97107
98108 const StructType *ST = dyn_cast(Ty);
99109 if (!ST) return false;
100110
111 bool NeedsProtector = false;
101112 for (StructType::element_iterator I = ST->element_begin(),
102113 E = ST->element_end(); I != E; ++I)
103 if (ContainsProtectableArray(*I, Strong, true))
104 return true;
105
106 return false;
114 if (ContainsProtectableArray(*I, IsLarge, Strong, true)) {
115 // If the element is a protectable array and is large (>= SSPBufferSize)
116 // then we are done. If the protectable array is not large, then
117 // keep looking in case a subsequent element is a large array.
118 if (IsLarge)
119 return true;
120 NeedsProtector = true;
121 }
122
123 return NeedsProtector;
107124 }
108125
109126 bool StackProtector::HasAddressTaken(const Instruction *AI) {
155172 /// address taken.
156173 bool StackProtector::RequiresStackProtector() {
157174 bool Strong = false;
175 bool NeedsProtector = false;
158176 if (F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
159 Attribute::StackProtectReq))
160 return true;
161 else if (F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
162 Attribute::StackProtectStrong))
177 Attribute::StackProtectReq)) {
178 NeedsProtector = true;
179 Strong = true; // Use the same heuristic as strong to determine SSPLayout
180 } else if (F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
181 Attribute::StackProtectStrong))
163182 Strong = true;
164183 else if (!F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
165184 Attribute::StackProtect))
179198
180199 if (const ConstantInt *CI =
181200 dyn_cast(AI->getArraySize())) {
182 if (CI->getLimitedValue(SSPBufferSize) >= SSPBufferSize)
201 if (CI->getLimitedValue(SSPBufferSize) >= SSPBufferSize) {
183202 // A call to alloca with size >= SSPBufferSize requires
184203 // stack protectors.
185 return true;
204 Layout.insert(std::make_pair(AI, SSPLK_LargeArray));
205 NeedsProtector = true;
206 } else if (Strong) {
207 // Require protectors for all alloca calls in strong mode.
208 Layout.insert(std::make_pair(AI, SSPLK_SmallArray));
209 NeedsProtector = true;
210 }
186211 } else {
187212 // A call to alloca with a variable size requires protectors.
188 return true;
213 Layout.insert(std::make_pair(AI, SSPLK_LargeArray));
214 NeedsProtector = true;
189215 }
216 continue;
190217 }
191218
192 if (ContainsProtectableArray(AI->getAllocatedType(), Strong))
193 return true;
219 bool IsLarge = false;
220 if (ContainsProtectableArray(AI->getAllocatedType(), IsLarge, Strong)) {
221 Layout.insert(std::make_pair(AI, IsLarge ? SSPLK_LargeArray
222 : SSPLK_SmallArray));
223 NeedsProtector = true;
224 continue;
225 }
194226
195227 if (Strong && HasAddressTaken(AI)) {
196228 ++NumAddrTaken;
197 return true;
229 Layout.insert(std::make_pair(AI, SSPLK_AddrOf));
230 NeedsProtector = true;
198231 }
199232 }
200233 }
201234 }
202235
203 return false;
236 return NeedsProtector;
204237 }
205238
206239 static bool InstructionWillNotHaveChain(const Instruction *I) {