55#define DEBUG_TYPE "stack-protector"
57STATISTIC(NumFunProtected,
"Number of functions protected");
58STATISTIC(NumAddrTaken,
"Number of local variables that have their address"
73 "Insert stack protectors",
false,
true)
89 if (
auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>())
98 "stack-protector-buffer-size", DefaultSSPBufferSize);
99 if (!RequiresStackProtector())
111 bool Changed = InsertStackProtectors();
112#ifdef EXPENSIVE_CHECKS
114 DTU->getDomTree().verify(DominatorTree::VerificationLevel::Full)) &&
115 "Failed to maintain validity of domtree!");
124bool StackProtector::ContainsProtectableArray(
Type *Ty,
bool &IsLarge,
126 bool InStruct)
const {
129 if (
ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
130 if (!AT->getElementType()->isIntegerTy(8)) {
135 if (!Strong && (InStruct || !Trip.
isOSDarwin()))
141 if (SSPBufferSize <= M->getDataLayout().getTypeAllocSize(AT)) {
155 bool NeedsProtector =
false;
156 for (
Type *ET :
ST->elements())
157 if (ContainsProtectableArray(ET, IsLarge, Strong,
true)) {
163 NeedsProtector =
true;
166 return NeedsProtector;
169bool StackProtector::HasAddressTaken(
const Instruction *AI,
173 const auto *
I = cast<Instruction>(U);
177 if (MemLoc && MemLoc->Size.hasValue() &&
181 switch (
I->getOpcode()) {
182 case Instruction::Store:
183 if (AI == cast<StoreInst>(
I)->getValueOperand())
186 case Instruction::AtomicCmpXchg:
189 if (AI == cast<AtomicCmpXchgInst>(
I)->getNewValOperand())
192 case Instruction::PtrToInt:
193 if (AI == cast<PtrToIntInst>(
I)->getOperand(0))
196 case Instruction::Call: {
199 const auto *CI = cast<CallInst>(
I);
200 if (!CI->isDebugOrPseudoInst() && !CI->isLifetimeStartOrEnd())
204 case Instruction::Invoke:
206 case Instruction::GetElementPtr: {
212 unsigned IndexSize =
DL.getIndexTypeSizeInBits(
I->getType());
224 if (HasAddressTaken(
I, NewAllocSize))
228 case Instruction::BitCast:
229 case Instruction::Select:
230 case Instruction::AddrSpaceCast:
231 if (HasAddressTaken(
I, AllocSize))
234 case Instruction::PHI: {
237 const auto *PN = cast<PHINode>(
I);
238 if (VisitedPHIs.insert(PN).second)
239 if (HasAddressTaken(PN, AllocSize))
243 case Instruction::Load:
244 case Instruction::AtomicRMW:
245 case Instruction::Ret:
266 if (
const auto *II = dyn_cast<IntrinsicInst>(&
I))
267 if (II->getIntrinsicID() == Intrinsic::stackprotector)
285bool StackProtector::RequiresStackProtector() {
287 bool NeedsProtector =
false;
300 <<
"Stack protection applied to function "
302 <<
" due to a function attribute or command-line switch";
304 NeedsProtector =
true;
313 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(&
I)) {
314 if (AI->isArrayAllocation()) {
315 auto RemarkBuilder = [&]() {
318 <<
"Stack protection applied to function "
320 <<
" due to a call to alloca or use of a variable length "
323 if (
const auto *CI = dyn_cast<ConstantInt>(AI->getArraySize())) {
324 if (CI->getLimitedValue(SSPBufferSize) >= SSPBufferSize) {
327 Layout.
insert(std::make_pair(AI,
329 ORE.emit(RemarkBuilder);
330 NeedsProtector =
true;
333 Layout.
insert(std::make_pair(AI,
335 ORE.emit(RemarkBuilder);
336 NeedsProtector =
true;
340 Layout.
insert(std::make_pair(AI,
342 ORE.emit(RemarkBuilder);
343 NeedsProtector =
true;
348 bool IsLarge =
false;
349 if (ContainsProtectableArray(AI->getAllocatedType(), IsLarge, Strong)) {
350 Layout.
insert(std::make_pair(AI, IsLarge
355 <<
"Stack protection applied to function "
357 <<
" due to a stack allocated buffer or struct containing a "
360 NeedsProtector =
true;
365 AI->getAllocatedType()))) {
371 <<
"Stack protection applied to function "
373 <<
" due to the address of a local variable being taken";
375 NeedsProtector =
true;
384 return NeedsProtector;
391 bool *SupportsSelectionDAGSP =
nullptr) {
393 StringRef GuardMode = M->getStackProtectorGuard();
394 if ((GuardMode ==
"tls" || GuardMode.
empty()) && Guard)
395 return B.CreateLoad(
B.getInt8PtrTy(), Guard,
true,
"StackGuard");
408 if (SupportsSelectionDAGSP)
409 *SupportsSelectionDAGSP =
true;
426 bool SupportsSelectionDAGSP =
false;
429 AI =
B.CreateAlloca(PtrTy,
nullptr,
"StackGuardSlot");
434 return SupportsSelectionDAGSP;
443bool StackProtector::InsertStackProtectors() {
447 bool SupportsSelectionDAGSP =
457 Instruction *CheckLoc = dyn_cast<ReturnInst>(BB.getTerminator());
459 for (
auto &Inst : BB) {
460 auto *CB = dyn_cast<CallBase>(&Inst);
463 if (!CB->doesNotReturn())
477 SupportsSelectionDAGSP &=
CreatePrologue(F, M, CheckLoc, TLI, AI);
482 if (SupportsSelectionDAGSP)
489 assert(SPCall &&
"Call to llvm.stackprotector is missing");
504 if (Prev && isa<CallInst>(Prev) && cast<CallInst>(Prev)->isTailCall())
508 if (Prev && isa<CallInst>(Prev) && cast<CallInst>(Prev)->isTailCall())
519 LoadInst *Guard =
B.CreateLoad(
B.getInt8PtrTy(), AI,
true,
"Guard");
521 Call->setAttributes(GuardCheck->getAttributes());
522 Call->setCallingConv(GuardCheck->getCallingConv());
554 FailBB = CreateFailBB();
558 LoadInst *LI2 =
B.CreateLoad(
B.getInt8PtrTy(), AI,
true);
559 auto *
Cmp = cast<ICmpInst>(
B.CreateICmpNE(Guard, LI2));
566 SuccessProb.getNumerator());
570 DTU ? &*DTU :
nullptr,
573 auto *BI = cast<BranchInst>(
Cmp->getParent()->getTerminator());
578 Cmp->setPredicate(
Cmp->getInversePredicate());
579 BI->swapSuccessors();
594 if (
F->getSubprogram())
595 B.SetCurrentDebugLocation(
602 B.CreateCall(StackChkFail,
B.CreateGlobalStringPtr(
F->getName(),
"SSH"));
607 B.CreateCall(StackChkFail, {});
609 B.CreateUnreachable();
614 return HasPrologue && !HasIRCheck && isa<ReturnInst>(BB.
getTerminator());
630 if (LI == Layout.
end())
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")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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.
#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.
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 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 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.
Class to represent array types.
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.
TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
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.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
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)
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.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T, AttributeList AttributeList)
Look up the specified function in the module symbol table.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
bool shouldEmitSDCheck(const BasicBlock &BB) const
void copyToMachineFrameInfo(MachineFrameInfo &MFI) const
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 bool useStackGuardXorFP() const
If this function returns true, stack protection checks should XOR the frame pointer (or whichever poi...
virtual Function * getSSPStackGuardCheck(const Module &M) const
If the target has a standard stack protection check function that performs validation and error handl...
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.
const Triple & getTargetTriple() const
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
unsigned EnableFastISel
EnableFastISel - This flag enables fast-path instruction selection which trades away generated code q...
Target-Independent Code Generator Pass Configuration Options.
virtual const TargetLowering * getTargetLowering() const
bool isOSDarwin() const
Is this a "Darwin" OS (macOS, iOS, tvOS, watchOS, or DriverKit).
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static constexpr TypeSize Fixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static Type * getVoidTy(LLVMContext &C)
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
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, Instruction *SplitBefore, bool Unreachable, MDNode *BranchWeights, DominatorTree *DT, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...