55#define DEBUG_TYPE "stack-protector"
57STATISTIC(NumFunProtected,
"Number of functions protected");
58STATISTIC(NumAddrTaken,
"Number of local variables that have their address"
75 bool &HasPrologue,
bool &HasIRCheck);
99 if (LI == Layout.end())
110 Info.RequireStackProtector =
112 Info.SSPBufferSize =
F.getFnAttributeAsParsedInteger(
113 "stack-protector-buffer-size", SSPLayoutInfo::DefaultSSPBufferSize);
125 if (!Info.RequireStackProtector)
130 if (
F.hasPersonalityFn()) {
140 if (!LibcallLowering) {
142 "' analysis required");
149 LibcallLowering->getLibcallLowering(*STI);
153 Info.HasPrologue, Info.HasIRCheck);
154#ifdef EXPENSIVE_CHECKS
156 DTU.getDomTree().verify(DominatorTree::VerificationLevel::Full)) &&
157 "Failed to maintain validity of domtree!");
173 "Insert stack protectors",
false,
true)
192 DTU.emplace(DTWP->getDomTree(), DomTreeUpdater::UpdateStrategy::Lazy);
194 LayoutInfo.HasPrologue =
false;
195 LayoutInfo.HasIRCheck =
false;
198 "stack-protector-buffer-size", SSPLayoutInfo::DefaultSSPBufferSize);
220 LayoutInfo.HasPrologue, LayoutInfo.HasIRCheck);
221#ifdef EXPENSIVE_CHECKS
223 DTU->getDomTree().verify(DominatorTree::VerificationLevel::Full)) &&
224 "Failed to maintain validity of domtree!");
234 bool &IsLarge,
bool Strong,
239 if (!AT->getElementType()->isIntegerTy(8)) {
244 if (!Strong && (InStruct || !M->getTargetTriple().isOSDarwin()))
250 if (SSPBufferSize <= M->getDataLayout().getTypeAllocSize(AT)) {
264 bool NeedsProtector =
false;
265 for (
Type *ET : ST->elements())
272 NeedsProtector =
true;
275 return NeedsProtector;
299 if (MemLoc && MemLoc->Size.hasValue() &&
302 switch (
I->getOpcode()) {
303 case Instruction::Store:
307 case Instruction::AtomicCmpXchg:
313 case Instruction::AtomicRMW:
317 case Instruction::PtrToInt:
321 case Instruction::Call: {
325 if (!CI->isDebugOrPseudoInst() && !CI->isLifetimeStartOrEnd())
329 case Instruction::Invoke:
331 case Instruction::GetElementPtr: {
337 unsigned IndexSize =
DL.getIndexTypeSizeInBits(
I->getType());
353 case Instruction::BitCast:
354 case Instruction::Select:
355 case Instruction::AddrSpaceCast:
359 case Instruction::PHI: {
363 auto [It, Inserted] = VisitedPHIs.
try_emplace(PN, AllocSize);
372 It->second.AllocSize = AllocSize;
373 ++It->second.NumDecreased;
379 case Instruction::Load:
380 case Instruction::Ret:
399 if (
II->getIntrinsicID() == Intrinsic::stackprotector)
418 SSPLayoutMap *Layout) {
421 bool NeedsProtector =
false;
428 unsigned SSPBufferSize =
F->getFnAttributeAsParsedInteger(
429 "stack-protector-buffer-size", SSPLayoutInfo::DefaultSSPBufferSize);
431 if (
F->hasFnAttribute(Attribute::SafeStack))
439 if (
F->hasFnAttribute(Attribute::StackProtectReq)) {
444 <<
"Stack protection applied to function "
446 <<
" due to a function attribute or command-line switch";
448 NeedsProtector =
true;
450 }
else if (
F->hasFnAttribute(Attribute::StackProtectStrong))
452 else if (!
F->hasFnAttribute(Attribute::StackProtect))
458 if (
const MDNode *MD = AI->getMetadata(
"stack-protector")) {
463 if (AI->isArrayAllocation()) {
464 auto RemarkBuilder = [&]() {
467 <<
"Stack protection applied to function "
469 <<
" due to a call to alloca or use of a variable length "
473 if (CI->getLimitedValue(SSPBufferSize) >= SSPBufferSize) {
480 ORE.
emit(RemarkBuilder);
481 NeedsProtector =
true;
488 ORE.
emit(RemarkBuilder);
489 NeedsProtector =
true;
497 ORE.
emit(RemarkBuilder);
498 NeedsProtector =
true;
503 bool IsLarge =
false;
505 IsLarge, Strong,
false)) {
508 Layout->
insert(std::make_pair(
513 <<
"Stack protection applied to function "
515 <<
" due to a stack allocated buffer or struct containing a "
518 NeedsProtector =
true;
523 std::optional<TypeSize> AllocSize =
524 AI->getAllocationSize(M->getDataLayout());
532 "StackProtectorAddressTaken", &
I)
533 <<
"Stack protection applied to function "
535 <<
" due to the address of a local variable being taken";
537 NeedsProtector =
true;
547 return NeedsProtector;
555 bool *SupportsSelectionDAGSP =
nullptr) {
557 StringRef GuardMode = M->getStackProtectorGuard();
558 if ((GuardMode ==
"tls" || GuardMode.
empty()) && Guard)
559 return B.CreateLoad(
B.getPtrTy(), Guard,
true,
"StackGuard");
572 if (SupportsSelectionDAGSP)
573 *SupportsSelectionDAGSP =
true;
575 return B.CreateIntrinsic(Intrinsic::stackguard, {});
592 bool SupportsSelectionDAGSP =
false;
595 AI =
B.CreateAlloca(PtrTy,
nullptr,
"StackGuardSlot");
599 B.CreateIntrinsic(Intrinsic::stackprotector, {GuardSlot, AI});
600 return SupportsSelectionDAGSP;
607 auto *M =
F->getParent();
612 bool SupportsSelectionDAGSP =
624 for (
auto &Inst : BB) {
626 IB && (IB->getIntrinsicID() == Intrinsic::eh_sjlj_callsite)) {
635 if (CB->doesNotReturn() && !CB->doesNotThrow()) {
647 SupportsSelectionDAGSP &=
653 if (SupportsSelectionDAGSP)
660 assert(SPCall &&
"Call to llvm.stackprotector is missing");
683 LoadInst *Guard =
B.CreateLoad(
B.getPtrTy(), AI,
true,
"Guard");
685 Call->setAttributes(GuardCheck->getAttributes());
686 Call->setCallingConv(GuardCheck->getCallingConv());
722 LoadInst *LI2 =
B.CreateLoad(
B.getPtrTy(), AI,
true);
730 SuccessProb.getNumerator());
741 Cmp->setPredicate(Cmp->getInversePredicate());
742 BI->swapSuccessors();
752 auto *M =
F->getParent();
756 if (
F->getSubprogram())
757 B.SetCurrentDebugLocation(
762 if (RTLIB::LibcallImpl ChkFailImpl =
764 StackChkFail = M->getOrInsertFunction(
767 }
else if (RTLIB::LibcallImpl SSHImpl =
769 StackChkFail = M->getOrInsertFunction(
772 Args.push_back(
B.CreateGlobalString(
F->getName(),
"SSH"));
774 Context.emitError(
"no libcall available for stack protector");
779 Call->addFnAttr(Attribute::NoReturn);
782 B.CreateUnreachable();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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")
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)
This file defines the SmallVector class.
static bool CreatePrologue(Function *F, Module *M, Instruction *CheckLoc, const TargetLoweringBase *TLI, const LibcallLoweringInfo &Libcalls, AllocaInst *&AI)
Insert code into the entry block that stores the stack guard variable onto the stack:
static Value * getStackGuard(const TargetLoweringBase &TLI, const LibcallLoweringInfo &Libcalls, Module *M, IRBuilder<> &B, bool *SupportsSelectionDAGSP=nullptr)
Create a stack guard loading and populate whether SelectionDAG SSP is supported.
static bool HasAddressTaken(const Instruction *AI, TypeSize AllocSize, Module *M, PhiMap &VisitedPHIs)
Check whether a stack allocation has its address taken.
static bool InsertStackProtectors(const TargetLowering &TLI, const LibcallLoweringInfo &Libcalls, Function *F, DomTreeUpdater *DTU, bool &HasPrologue, bool &HasIRCheck)
InsertStackProtectors - Insert code into the prologue and epilogue of the function.
static cl::opt< bool > DisableCheckNoReturn("disable-check-noreturn-call", cl::init(false), cl::Hidden)
SmallDenseMap< const PHINode *, PhiInfo, 16 > PhiMap
static bool ContainsProtectableArray(Type *Ty, Module *M, unsigned SSPBufferSize, bool &IsLarge, bool Strong, bool InStruct)
static BasicBlock * CreateFailBB(Function *F, const LibcallLoweringInfo &Libcalls)
CreateFailBB - Create a basic block to jump to when the stack protector check fails.
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
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.
LLVM_ABI 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.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
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...
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
Tracks which library functions to use for a particular subtarget.
LLVM_ABI RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Return the lowering's selection of implementation call for Call.
Record a mapping from subtarget to LibcallLoweringInfo.
An instruction for reading from memory.
LLVM_ABI 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 LLVM_ABI std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
A Module instance is used to store all the information related to an LLVM module.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
AnalysisType * getAnalysisIfAvailable() const
getAnalysisIfAvailable<AnalysisType>() - Subclasses use this function to get analysis information tha...
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.
PreservedAnalyses & 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
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 ...
Function * getSSPStackGuardCheck(const Module &M, const LibcallLoweringInfo &Libcalls) const
If the target has a standard stack protection check function that performs validation and error handl...
virtual bool useStackGuardXorFP() const
If this function returns true, stack protection checks should XOR the frame pointer (or whichever poi...
virtual Value * getIRStackGuard(IRBuilderBase &IRB, const LibcallLoweringInfo &Libcalls) const
If the target has a standard location for the stack protector guard, returns the address of that loca...
const TargetMachine & getTargetMachine() const
virtual void insertSSPDeclarations(Module &M, const LibcallLoweringInfo &Libcalls) const
Inserts necessary declarations for SSP (stack protection) purpose.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Primary interface to the complete machine description for the target machine.
Target-Independent Code Generator Pass Configuration Options.
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetLowering * getTargetLowering() const
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
LLVM Value Representation.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
iterator_range< user_iterator > users()
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)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
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...
LLVM_ABI FunctionPass * createStackProtectorPass()
createStackProtectorPass - This pass adds stack protectors to functions.
LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
bool isFuncletEHPersonality(EHPersonality Pers)
Returns true if this is a personality function that invokes handler funclets (which must return to it...
bool isInTailCallPosition(const CallBase &Call, const TargetMachine &TM, bool ReturnsFirstArg=false)
Test if the given instruction is in a position to be optimized with a tail-call.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI 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 ...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
PhiInfo(TypeSize AllocSize)
static constexpr unsigned MaxNumDecreased
A special type used by analysis passes to provide an address that identifies that particular analysis...
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.