LLVM: lib/CodeGen/StackProtector.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
51#include
52#include
53
54using namespace llvm;
55
56#define DEBUG_TYPE "stack-protector"
57
58STATISTIC(NumFunProtected, "Number of functions protected");
59STATISTIC(NumAddrTaken, "Number of local variables that have their address"
60 " taken.");
61
66
67
68
69
70
71
72
75 bool &HasIRCheck);
76
77
78
80
82 return HasPrologue && !HasIRCheck && isa(BB.getTerminator());
83}
84
86 if (Layout.empty())
87 return;
88
91 continue;
92
94 if (!AI)
95 continue;
96
98 if (LI == Layout.end())
99 continue;
100
102 }
103}
104
107
109 Info.RequireStackProtector =
111 Info.SSPBufferSize = F.getFnAttributeAsParsedInteger(
112 "stack-protector-buffer-size", SSPLayoutInfo::DefaultSSPBufferSize);
114}
115
117
122 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
123
124 if (.RequireStackProtector)
126
127
128
129 if (F.hasPersonalityFn()) {
133 }
134
135 ++NumFunProtected;
137 Info.HasPrologue, Info.HasIRCheck);
138#ifdef EXPENSIVE_CHECKS
139 assert((!DT || DT->verify(DominatorTree::VerificationLevel::Full)) &&
140 "Failed to maintain validity of domtree!");
141#endif
142
143 if (!Changed)
148 return PA;
149}
150
152
155}
156
158 "Insert stack protectors", false, true)
163
165
169}
170
172 F = &Fn;
174 if (auto *DTWP = getAnalysisIfAvailable())
175 DTU.emplace(DTWP->getDomTree(), DomTreeUpdater::UpdateStrategy::Lazy);
176 TM = &getAnalysis().getTM<TargetMachine>();
177 LayoutInfo.HasPrologue = false;
178 LayoutInfo.HasIRCheck = false;
179
181 "stack-protector-buffer-size", SSPLayoutInfo::DefaultSSPBufferSize);
183 return false;
184
185
186
190 return false;
191 }
192
193 ++NumFunProtected;
194 bool Changed =
196 LayoutInfo.HasPrologue, LayoutInfo.HasIRCheck);
197#ifdef EXPENSIVE_CHECKS
199 DTU->getDomTree().verify(DominatorTree::VerificationLevel::Full)) &&
200 "Failed to maintain validity of domtree!");
201#endif
202 DTU.reset();
203 return Changed;
204}
205
206
207
208
210 bool &IsLarge, bool Strong,
211 bool InStruct) {
212 if (!Ty)
213 return false;
214 if (ArrayType *AT = dyn_cast(Ty)) {
215 if (!AT->getElementType()->isIntegerTy(8)) {
216
217
218
219
220 if (!Strong && (InStruct || (M->getTargetTriple()).isOSDarwin()))
221 return false;
222 }
223
224
225
226 if (SSPBufferSize <= M->getDataLayout().getTypeAllocSize(AT)) {
227 IsLarge = true;
228 return true;
229 }
230
231 if (Strong)
232
233 return true;
234 }
235
236 const StructType *ST = dyn_cast(Ty);
237 if (!ST)
238 return false;
239
240 bool NeedsProtector = false;
241 for (Type *ET : ST->elements())
243
244
245
246 if (IsLarge)
247 return true;
248 NeedsProtector = true;
249 }
250
251 return NeedsProtector;
252}
253
254
259 for (const User *U : AI->users()) {
260 const auto *I = cast(U);
261
262
264 if (MemLoc && MemLoc->Size.hasValue() &&
266 return true;
267 switch (I->getOpcode()) {
268 case Instruction::Store:
269 if (AI == cast(I)->getValueOperand())
270 return true;
271 break;
272 case Instruction::AtomicCmpXchg:
273
274
275 if (AI == cast(I)->getNewValOperand())
276 return true;
277 break;
278 case Instruction::PtrToInt:
279 if (AI == cast(I)->getOperand(0))
280 return true;
281 break;
282 case Instruction::Call: {
283
284
285 const auto *CI = cast(I);
286 if (!CI->isDebugOrPseudoInst() && !CI->isLifetimeStartOrEnd())
287 return true;
288 break;
289 }
290 case Instruction::Invoke:
291 return true;
292 case Instruction::GetElementPtr: {
293
294
295
296
298 unsigned IndexSize = DL.getIndexTypeSizeInBits(I->getType());
300 if (->accumulateConstantOffset(DL, Offset))
301 return true;
304 return true;
305
306
307
311 return true;
312 break;
313 }
314 case Instruction::BitCast:
315 case Instruction::Select:
316 case Instruction::AddrSpaceCast:
318 return true;
319 break;
320 case Instruction::PHI: {
321
322
323 const auto *PN = cast(I);
324 if (VisitedPHIs.insert(PN).second)
326 return true;
327 break;
328 }
329 case Instruction::Load:
330 case Instruction::AtomicRMW:
331 case Instruction::Ret:
332
333
334
335
336
337 break;
338 default:
339
340
341 return true;
342 }
343 }
344 return false;
345}
346
347
348
352 if (const auto *II = dyn_cast(&I))
353 if (II->getIntrinsicID() == Intrinsic::stackprotector)
354 return II;
355 return nullptr;
356}
357
358
359
360
361
362
363
364
365
366
367
368
369
370
373 Module *M = F->getParent();
374 bool Strong = false;
375 bool NeedsProtector = false;
376
377
378
379
381
382 unsigned SSPBufferSize = F->getFnAttributeAsParsedInteger(
383 "stack-protector-buffer-size", SSPLayoutInfo::DefaultSSPBufferSize);
384
385 if (F->hasFnAttribute(Attribute::SafeStack))
386 return false;
387
388
389
390
392
393 if (F->hasFnAttribute(Attribute::StackProtectReq)) {
394 if (!Layout)
395 return true;
396 ORE.emit([&]() {
398 << "Stack protection applied to function "
400 << " due to a function attribute or command-line switch";
401 });
402 NeedsProtector = true;
403 Strong = true;
404 } else if (F->hasFnAttribute(Attribute::StackProtectStrong))
405 Strong = true;
406 else if (->hasFnAttribute(Attribute::StackProtect))
407 return false;
408
411 if (const AllocaInst *AI = dyn_cast(&I)) {
412 if (AI->isArrayAllocation()) {
413 auto RemarkBuilder = [&]() {
415 &I)
416 << "Stack protection applied to function "
418 << " due to a call to alloca or use of a variable length "
419 "array";
420 };
421 if (const auto *CI = dyn_cast(AI->getArraySize())) {
422 if (CI->getLimitedValue(SSPBufferSize) >= SSPBufferSize) {
423
424
425 if (!Layout)
426 return true;
429 ORE.emit(RemarkBuilder);
430 NeedsProtector = true;
431 } else if (Strong) {
432
433 if (!Layout)
434 return true;
437 ORE.emit(RemarkBuilder);
438 NeedsProtector = true;
439 }
440 } else {
441
442 if (!Layout)
443 return true;
446 ORE.emit(RemarkBuilder);
447 NeedsProtector = true;
448 }
449 continue;
450 }
451
452 bool IsLarge = false;
454 IsLarge, Strong, false)) {
455 if (!Layout)
456 return true;
457 Layout->insert(std::make_pair(
460 ORE.emit([&]() {
462 << "Stack protection applied to function "
464 << " due to a stack allocated buffer or struct containing a "
465 "buffer";
466 });
467 NeedsProtector = true;
468 continue;
469 }
470
471 if (Strong &&
473 AI, M->getDataLayout().getTypeAllocSize(AI->getAllocatedType()),
474 M, VisitedPHIs)) {
475 ++NumAddrTaken;
476 if (!Layout)
477 return true;
479 ORE.emit([&]() {
481 &I)
482 << "Stack protection applied to function "
484 << " due to the address of a local variable being taken";
485 });
486 NeedsProtector = true;
487 }
488
489
490 VisitedPHIs.clear();
491 }
492 }
493 }
494
495 return NeedsProtector;
496}
497
498
499
502 bool *SupportsSelectionDAGSP = nullptr) {
504 StringRef GuardMode = M->getStackProtectorGuard();
505 if ((GuardMode == "tls" || GuardMode.empty()) && Guard)
506 return B.CreateLoad(B.getPtrTy(), Guard, true, "StackGuard");
507
508
509
510
511
512
513
514
515
516
517
518
519 if (SupportsSelectionDAGSP)
520 *SupportsSelectionDAGSP = true;
522 return B.CreateIntrinsic(Intrinsic::stackguard, {}, {});
523}
524
525
526
527
528
529
530
531
532
533
534
537 bool SupportsSelectionDAGSP = false;
540 AI = B.CreateAlloca(PtrTy, nullptr, "StackGuardSlot");
541
543 B.CreateIntrinsic(Intrinsic::stackprotector, {}, {GuardSlot, AI});
544 return SupportsSelectionDAGSP;
545}
546
549 bool &HasIRCheck) {
550 auto *M = F->getParent();
551 auto *TLI = TM->getSubtargetImpl(*F)->getTargetLowering();
552
553
554
555
556 bool SupportsSelectionDAGSP =
557 TLI->useStackGuardXorFP() ||
559 AllocaInst *AI = nullptr;
561
563
564 if (&BB == FailBB)
565 continue;
566 Instruction *CheckLoc = dyn_cast(BB.getTerminator());
568 for (auto &Inst : BB)
569 if (auto *CB = dyn_cast(&Inst))
570
571
572 if (CB->doesNotReturn() && !CB->doesNotThrow()) {
573 CheckLoc = CB;
574 break;
575 }
576
577 if (!CheckLoc)
578 continue;
579
580
581 if (!HasPrologue) {
582 HasPrologue = true;
583 SupportsSelectionDAGSP &= CreatePrologue(F, M, CheckLoc, TLI, AI);
584 }
585
586
587
588 if (SupportsSelectionDAGSP)
589 break;
590
591
592
593 if (!AI) {
595 assert(SPCall && "Call to llvm.stackprotector is missing");
597 }
598
599
600
601
602 HasIRCheck = true;
603
604
605
606
607
608
610 if (Prev && isa(Prev) && cast(Prev)->isTailCall())
611 CheckLoc = Prev;
612 else if (Prev) {
614 if (Prev && isa(Prev) && cast(Prev)->isTailCall())
615 CheckLoc = Prev;
616 }
617
618
619
620
621 if (Function *GuardCheck = TLI->getSSPStackGuardCheck(*M)) {
622
623
625 LoadInst *Guard = B.CreateLoad(B.getPtrTy(), AI, true, "Guard");
626 CallInst *Call = B.CreateCall(GuardCheck, {Guard});
627 Call->setAttributes(GuardCheck->getAttributes());
628 Call->setCallingConv(GuardCheck->getCallingConv());
629 } else {
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659 if (!FailBB)
661
664 LoadInst *LI2 = B.CreateLoad(B.getPtrTy(), AI, true);
665 auto *Cmp = cast(B.CreateICmpNE(Guard, LI2));
666 auto SuccessProb =
668 auto FailureProb =
672 SuccessProb.getNumerator());
673
675 false, Weights, DTU,
676 nullptr, FailBB);
677
678 auto *BI = cast(Cmp->getParent()->getTerminator());
679 BasicBlock *NewBB = BI->getSuccessor(1);
680 NewBB->setName("SP_return");
682
683 Cmp->setPredicate(Cmp->getInversePredicate());
684 BI->swapSuccessors();
685 }
686 }
687
688
689
690 return HasPrologue;
691}
692
694 auto *M = F->getParent();
698 if (F->getSubprogram())
699 B.SetCurrentDebugLocation(
704 StackChkFail = M->getOrInsertFunction("__stack_smash_handler",
707 Args.push_back(B.CreateGlobalString(F->getName(), "SSH"));
708 } else {
709 StackChkFail =
710 M->getOrInsertFunction("__stack_chk_fail", Type::getVoidTy(Context));
711 }
712 cast(StackChkFail.getCallee())->addFnAttr(Attribute::NoReturn);
713 B.CreateCall(StackChkFail, Args);
714 B.CreateUnreachable();
715 return FailBB;
716}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Module.h This file contains the declarations for the Module class.
This file provides utility analysis objects describing memory locations.
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static bool HasAddressTaken(const Instruction *AI, TypeSize AllocSize, Module *M, SmallPtrSet< const PHINode *, 16 > &VisitedPHIs)
Check whether a stack allocation has its address taken.
static Value * getStackGuard(const TargetLoweringBase *TLI, Module *M, IRBuilder<> &B, bool *SupportsSelectionDAGSP=nullptr)
Create a stack guard loading and populate whether SelectionDAG SSP is supported.
static bool InsertStackProtectors(const TargetMachine *TM, Function *F, DomTreeUpdater *DTU, bool &HasPrologue, bool &HasIRCheck)
InsertStackProtectors - Insert code into the prologue and epilogue of the function.
static BasicBlock * CreateFailBB(Function *F, const Triple &Trip)
CreateFailBB - Create a basic block to jump to when the stack protector check fails.
static cl::opt< bool > DisableCheckNoReturn("disable-check-noreturn-call", cl::init(false), cl::Hidden)
static bool CreatePrologue(Function *F, Module *M, Instruction *CheckLoc, const TargetLoweringBase *TLI, AllocaInst *&AI)
Insert code into the entry block that stores the stack guard variable onto the stack:
static bool ContainsProtectableArray(Type *Ty, Module *M, unsigned SSPBufferSize, bool &IsLarge, bool Strong, bool InStruct)
static cl::opt< bool > EnableSelectionDAGSP("enable-selectiondag-sp", cl::init(true), cl::Hidden)
static const CallInst * findStackProtectorIntrinsic(Function &F)
Search for the first call to the llvm.stackprotector intrinsic and return it if present.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file describes how to lower LLVM code to machine code.
Target-Independent Code Generator Pass Configuration Options pass.
Class for arbitrary precision integers.
an instruction to allocate memory on the stack
A container for analyses that lazily runs them and caches their results.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
void moveAfter(BasicBlock *MovePos)
Unlink this basic block from its current function and insert it right after MovePos in the function M...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
static BranchProbability getBranchProbStackProtector(bool IsLikely)
Value * getArgOperand(unsigned i) const
This class represents a function call, abstracting a target machine's calling convention.
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
bool verify(VerificationLevel VL=VerificationLevel::Full) const
verify - checks if the tree is correct.
Legacy analysis pass which computes a DominatorTree.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionPass class - This class is used to implement most global optimizations.
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
bool hasPersonalityFn() const
Check whether this function has a personality function.
Constant * getPersonalityFn() const
Get the personality function associated with this function.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Module * getParent()
Get the module that this global value is contained inside of...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
const Instruction * getPrevNonDebugInstruction(bool SkipPseudoOp=false) const
Return a pointer to the previous non-debug instruction in the same basic block as 'this',...
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight, bool IsExpected=false)
Return metadata containing two branch weights.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
const AllocaInst * getObjectAllocation(int ObjectIdx) const
Return the underlying Alloca of the specified stack object if it exists.
@ SSPLK_SmallArray
Array or nested array < SSP-buffer-size.
@ SSPLK_LargeArray
Array or nested array >= SSP-buffer-size.
@ SSPLK_AddrOf
The address of this allocation is exposed and triggered protection.
void setObjectSSPLayout(int ObjectIdx, SSPLayoutKind Kind)
int getObjectIndexEnd() const
Return one past the maximum frame object index.
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
static std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
A Module instance is used to store all the information related to an LLVM module.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void preserve()
Mark an analysis as preserved.
static bool requiresStackProtector(Function *F, SSPLayoutMap *Layout=nullptr)
Check whether or not F needs a stack protector based upon the stack protector level.
Result run(Function &F, FunctionAnalysisManager &FAM)
void copyToMachineFrameInfo(MachineFrameInfo &MFI) const
bool shouldEmitSDCheck(const BasicBlock &BB) const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
static bool requiresStackProtector(Function *F, SSPLayoutMap *Layout=nullptr)
Check whether or not F needs a stack protector based upon the stack protector level.
bool runOnFunction(Function &Fn) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
Class to represent struct types.
This base class for TargetLowering contains the SelectionDAG-independent parts that can be used from ...
virtual Value * getIRStackGuard(IRBuilderBase &IRB) const
If the target has a standard location for the stack protector guard, returns the address of that loca...
virtual void insertSSPDeclarations(Module &M) const
Inserts necessary declarations for SSP (stack protection) purpose.
Primary interface to the complete machine description for the target machine.
Target-Independent Code Generator Pass Configuration Options.
Triple - Helper class for working with autoconf configuration names.
bool isOSDarwin() const
Is this a "Darwin" OS (macOS, iOS, tvOS, watchOS, XROS, or DriverKit).
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static Type * getVoidTy(LLVMContext &C)
LLVM Value Representation.
void setName(const Twine &Name)
Change the name of the value.
iterator_range< user_iterator > users()
LLVMContext & getContext() const
All values hold a context through their type.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
static constexpr bool isKnownGT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
static constexpr bool isKnownGE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
initializer< Ty > init(const Ty &Val)
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
FunctionPass * createStackProtectorPass()
createStackProtectorPass - This pass adds stack protectors to functions.
void initializeStackProtectorPass(PassRegistry &)
EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
bool isFuncletEHPersonality(EHPersonality Pers)
Returns true if this is a personality function that invokes handler funclets (which must return to it...
Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
A special type used by analysis passes to provide an address that identifies that particular analysis...