56#define DEBUG_TYPE "stack-protector"
58STATISTIC(NumFunProtected,
"Number of functions protected");
59STATISTIC(NumAddrTaken,
"Number of local variables that have their address"
82 return HasPrologue && !HasIRCheck && isa<ReturnInst>(BB.
getTerminator());
98 if (LI == Layout.
end())
109 Info.RequireStackProtector =
111 Info.SSPBufferSize =
F.getFnAttributeAsParsedInteger(
112 "stack-protector-buffer-size", SSPLayoutInfo::DefaultSSPBufferSize);
124 if (!
Info.RequireStackProtector)
129 if (
F.hasPersonalityFn()) {
138#ifdef EXPENSIVE_CHECKS
139 assert((!DT || DT->verify(DominatorTree::VerificationLevel::Full)) &&
140 "Failed to maintain validity of domtree!");
158 "Insert stack protectors",
false,
true)
174 if (
auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>())
175 DTU.emplace(DTWP->getDomTree(), DomTreeUpdater::UpdateStrategy::Lazy);
176 TM = &getAnalysis<TargetPassConfig>().getTM<
TargetMachine>();
177 LayoutInfo.HasPrologue =
false;
178 LayoutInfo.HasIRCheck =
false;
181 "stack-protector-buffer-size", SSPLayoutInfo::DefaultSSPBufferSize);
196 LayoutInfo.HasPrologue, LayoutInfo.HasIRCheck);
197#ifdef EXPENSIVE_CHECKS
199 DTU->getDomTree().verify(DominatorTree::VerificationLevel::Full)) &&
200 "Failed to maintain validity of domtree!");
210 bool &IsLarge,
bool Strong,
214 if (
ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
215 if (!AT->getElementType()->isIntegerTy(8)) {
226 if (SSPBufferSize <= M->getDataLayout().getTypeAllocSize(AT)) {
236 const StructType *ST = dyn_cast<StructType>(Ty);
240 bool NeedsProtector =
false;
241 for (
Type *ET : ST->elements())
248 NeedsProtector =
true;
251 return NeedsProtector;
260 const auto *
I = cast<Instruction>(U);
264 if (MemLoc && MemLoc->Size.hasValue() &&
267 switch (
I->getOpcode()) {
268 case Instruction::Store:
269 if (AI == cast<StoreInst>(
I)->getValueOperand())
272 case Instruction::AtomicCmpXchg:
275 if (AI == cast<AtomicCmpXchgInst>(
I)->getNewValOperand())
278 case Instruction::PtrToInt:
279 if (AI == cast<PtrToIntInst>(
I)->getOperand(0))
282 case Instruction::Call: {
285 const auto *CI = cast<CallInst>(
I);
286 if (!CI->isDebugOrPseudoInst() && !CI->isLifetimeStartOrEnd())
290 case Instruction::Invoke:
292 case Instruction::GetElementPtr: {
298 unsigned IndexSize =
DL.getIndexTypeSizeInBits(
I->getType());
314 case Instruction::BitCast:
315 case Instruction::Select:
316 case Instruction::AddrSpaceCast:
320 case Instruction::PHI: {
323 const auto *PN = cast<PHINode>(
I);
324 if (VisitedPHIs.
insert(PN).second)
329 case Instruction::Load:
330 case Instruction::AtomicRMW:
331 case Instruction::Ret:
352 if (
const auto *
II = dyn_cast<IntrinsicInst>(&
I))
353 if (
II->getIntrinsicID() == Intrinsic::stackprotector)
375 bool NeedsProtector =
false;
382 unsigned SSPBufferSize =
F->getFnAttributeAsParsedInteger(
383 "stack-protector-buffer-size", SSPLayoutInfo::DefaultSSPBufferSize);
385 if (
F->hasFnAttribute(Attribute::SafeStack))
393 if (
F->hasFnAttribute(Attribute::StackProtectReq)) {
398 <<
"Stack protection applied to function "
400 <<
" due to a function attribute or command-line switch";
402 NeedsProtector =
true;
404 }
else if (
F->hasFnAttribute(Attribute::StackProtectStrong))
406 else if (!
F->hasFnAttribute(Attribute::StackProtect))
411 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(&
I)) {
412 if (AI->isArrayAllocation()) {
413 auto RemarkBuilder = [&]() {
416 <<
"Stack protection applied to function "
418 <<
" due to a call to alloca or use of a variable length "
421 if (
const auto *CI = dyn_cast<ConstantInt>(AI->getArraySize())) {
422 if (CI->getLimitedValue(SSPBufferSize) >= SSPBufferSize) {
429 ORE.
emit(RemarkBuilder);
430 NeedsProtector =
true;
437 ORE.
emit(RemarkBuilder);
438 NeedsProtector =
true;
446 ORE.
emit(RemarkBuilder);
447 NeedsProtector =
true;
452 bool IsLarge =
false;
454 IsLarge, Strong,
false)) {
457 Layout->
insert(std::make_pair(
462 <<
"Stack protection applied to function "
464 <<
" due to a stack allocated buffer or struct containing a "
467 NeedsProtector =
true;
473 AI, M->getDataLayout().getTypeAllocSize(AI->getAllocatedType()),
482 <<
"Stack protection applied to function "
484 <<
" due to the address of a local variable being taken";
486 NeedsProtector =
true;
495 return NeedsProtector;
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");
519 if (SupportsSelectionDAGSP)
520 *SupportsSelectionDAGSP =
true;
537 bool SupportsSelectionDAGSP =
false;
540 AI =
B.CreateAlloca(PtrTy,
nullptr,
"StackGuardSlot");
545 return SupportsSelectionDAGSP;
551 auto *M =
F->getParent();
552 auto *TLI = TM->getSubtargetImpl(*F)->getTargetLowering();
557 bool SupportsSelectionDAGSP =
558 TLI->useStackGuardXorFP() ||
567 Instruction *CheckLoc = dyn_cast<ReturnInst>(BB.getTerminator());
569 for (
auto &Inst : BB)
570 if (
auto *CB = dyn_cast<CallBase>(&Inst))
573 if (CB->doesNotReturn() && !CB->doesNotThrow()) {
589 if (SupportsSelectionDAGSP)
596 assert(SPCall &&
"Call to llvm.stackprotector is missing");
611 if (Prev && isa<CallInst>(Prev) && cast<CallInst>(Prev)->isTailCall())
615 if (Prev && isa<CallInst>(Prev) && cast<CallInst>(Prev)->isTailCall())
622 if (
Function *GuardCheck = TLI->getSSPStackGuardCheck(*M)) {
626 LoadInst *Guard =
B.CreateLoad(
B.getPtrTy(), AI,
true,
"Guard");
627 CallInst *Call =
B.CreateCall(GuardCheck, {Guard});
628 Call->setAttributes(GuardCheck->getAttributes());
629 Call->setCallingConv(GuardCheck->getCallingConv());
665 LoadInst *LI2 =
B.CreateLoad(
B.getPtrTy(), AI,
true);
666 auto *Cmp = cast<ICmpInst>(
B.CreateICmpNE(Guard, LI2));
673 SuccessProb.getNumerator());
679 auto *BI = cast<BranchInst>(Cmp->getParent()->getTerminator());
684 Cmp->setPredicate(Cmp->getInversePredicate());
685 BI->swapSuccessors();
695 auto *M =
F->getParent();
699 if (
F->getSubprogram())
700 B.SetCurrentDebugLocation(
705 StackChkFail = M->getOrInsertFunction(
"__stack_smash_handler",
708 Args.push_back(
B.CreateGlobalStringPtr(
F->getName(),
"SSH"));
713 cast<Function>(StackChkFail.
getCallee())->addFnAttr(Attribute::NoReturn);
714 B.CreateCall(StackChkFail, Args);
715 B.CreateUnreachable();
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...
This file provides utility analysis objects describing memory locations.
Module.h This file contains the declarations for the Module class.
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.
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)
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=std::nullopt)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
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...