Go to the documentation of this file.
55 #define DEBUG_TYPE "stack-protector"
57 STATISTIC(NumFunProtected,
"Number of functions protected");
58 STATISTIC(NumAddrTaken,
"Number of local variables that have their address"
71 "Insert stack protectors",
false,
true)
88 getAnalysisIfAvailable<DominatorTreeWrapperPass>();
101 if (!RequiresStackProtector())
113 return InsertStackProtectors();
119 bool StackProtector::ContainsProtectableArray(
Type *Ty,
bool &IsLarge,
121 bool InStruct)
const {
124 if (
ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
125 if (!AT->getElementType()->isIntegerTy(8)) {
130 if (!Strong && (InStruct || !Trip.
isOSDarwin()))
136 if (SSPBufferSize <= M->getDataLayout().getTypeAllocSize(AT)) {
150 bool NeedsProtector =
false;
152 E =
ST->element_end();
154 if (ContainsProtectableArray(*
I, IsLarge, Strong,
true)) {
160 NeedsProtector =
true;
163 return NeedsProtector;
166 bool StackProtector::HasAddressTaken(
const Instruction *AI,
167 uint64_t AllocSize) {
170 const auto *
I = cast<Instruction>(U);
177 switch (
I->getOpcode()) {
179 if (AI == cast<StoreInst>(
I)->getValueOperand())
182 case Instruction::AtomicCmpXchg:
185 if (AI == cast<AtomicCmpXchgInst>(
I)->getNewValOperand())
188 case Instruction::PtrToInt:
189 if (AI == cast<PtrToIntInst>(
I)->getOperand(0))
195 const auto *CI = cast<CallInst>(
I);
196 if (!CI->isDebugOrPseudoInst() && !CI->isLifetimeStartOrEnd())
200 case Instruction::Invoke:
202 case Instruction::GetElementPtr: {
208 unsigned TypeSize =
DL.getIndexTypeSizeInBits(
I->getType());
214 if (HasAddressTaken(
I, AllocSize -
Offset.getLimitedValue()))
218 case Instruction::BitCast:
220 case Instruction::AddrSpaceCast:
221 if (HasAddressTaken(
I, AllocSize))
224 case Instruction::PHI: {
227 const auto *PN = cast<PHINode>(
I);
228 if (VisitedPHIs.insert(PN).second)
229 if (HasAddressTaken(PN, AllocSize))
234 case Instruction::AtomicRMW:
256 if (
const auto *II = dyn_cast<IntrinsicInst>(&
I))
257 if (II->getIntrinsicID() == Intrinsic::stackprotector)
275 bool StackProtector::RequiresStackProtector() {
277 bool NeedsProtector =
false;
290 <<
"Stack protection applied to function "
292 <<
" due to a function attribute or command-line switch";
294 NeedsProtector =
true;
303 if (
const AllocaInst *AI = dyn_cast<AllocaInst>(&
I)) {
304 if (AI->isArrayAllocation()) {
305 auto RemarkBuilder = [&]() {
308 <<
"Stack protection applied to function "
310 <<
" due to a call to alloca or use of a variable length "
313 if (
const auto *CI = dyn_cast<ConstantInt>(AI->getArraySize())) {
314 if (CI->getLimitedValue(SSPBufferSize) >= SSPBufferSize) {
317 Layout.
insert(std::make_pair(AI,
319 ORE.emit(RemarkBuilder);
320 NeedsProtector =
true;
323 Layout.
insert(std::make_pair(AI,
325 ORE.emit(RemarkBuilder);
326 NeedsProtector =
true;
330 Layout.
insert(std::make_pair(AI,
332 ORE.emit(RemarkBuilder);
333 NeedsProtector =
true;
338 bool IsLarge =
false;
339 if (ContainsProtectableArray(AI->getAllocatedType(), IsLarge, Strong)) {
340 Layout.
insert(std::make_pair(AI, IsLarge
345 <<
"Stack protection applied to function "
347 <<
" due to a stack allocated buffer or struct containing a "
350 NeedsProtector =
true;
355 AI->getAllocatedType()))) {
361 <<
"Stack protection applied to function "
363 <<
" due to the address of a local variable being taken";
365 NeedsProtector =
true;
374 return NeedsProtector;
381 bool *SupportsSelectionDAGSP =
nullptr) {
386 return B.CreateLoad(
B.getInt8PtrTy(), Guard,
true,
"StackGuard");
399 if (SupportsSelectionDAGSP)
400 *SupportsSelectionDAGSP =
true;
417 bool SupportsSelectionDAGSP =
false;
420 AI =
B.CreateAlloca(PtrTy,
nullptr,
"StackGuardSlot");
425 return SupportsSelectionDAGSP;
434 bool StackProtector::InsertStackProtectors() {
438 bool SupportsSelectionDAGSP =
446 ReturnInst *RI = dyn_cast<ReturnInst>(
BB->getTerminator());
458 if (SupportsSelectionDAGSP)
465 assert(SPCall &&
"Call to llvm.stackprotector is missing");
481 if (Prev && isa<CallInst>(Prev) && cast<CallInst>(Prev)->
isMustTailCall())
485 if (Prev && isa<CallInst>(Prev) && cast<CallInst>(Prev)->
isMustTailCall())
496 LoadInst *Guard =
B.CreateLoad(
B.getInt8PtrTy(), AI,
true,
"Guard");
498 Call->setAttributes(GuardCheck->getAttributes());
499 Call->setCallingConv(GuardCheck->getCallingConv());
543 BB->getTerminator()->eraseFromParent();
552 LoadInst *LI2 =
B.CreateLoad(
B.getInt8PtrTy(), AI,
true);
560 FailureProb.getNumerator());
561 B.CreateCondBr(Cmp, NewBB, FailBB, Weights);
576 if (
F->getSubprogram())
577 B.SetCurrentDebugLocation(
584 B.CreateCall(StackChkFail,
B.CreateGlobalStringPtr(
F->getName(),
"SSH"));
589 B.CreateCall(StackChkFail, {});
591 B.CreateUnreachable();
596 return HasPrologue && !HasIRCheck && isa<ReturnInst>(
BB.getTerminator());
612 if (LI == Layout.
end())
const Instruction * getPrevNonDebugInstruction(bool SkipPseudoOp=false) const
Return a pointer to the previous non-debug instruction in the same basic block as 'this',...
This base class for TargetLowering contains the SelectionDAG-independent parts that can be used from ...
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Return a value (possibly void), from a function.
A parsed version of the target data layout string in and methods for querying it.
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=None)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
void copyToMachineFrameInfo(MachineFrameInfo &MFI) const
Type::subtype_iterator element_iterator
bool runOnFunction(Function &Fn) override
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
INITIALIZE_PASS_BEGIN(StackProtector, DEBUG_TYPE, "Insert stack protectors", false, true) INITIALIZE_PASS_END(StackProtector
LocationSize Size
The maximum size of the location, in address-units, or UnknownSize if the size is not known.
static cl::opt< bool > EnableSelectionDAGSP("enable-selectiondag-sp", cl::init(true), cl::Hidden)
The instances of the Type class are immutable: once they are created, they are never changed.
@ SSPLK_LargeArray
Array or nested array >= SSP-buffer-size.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T, AttributeList AttributeList)
Look up the specified function in the module symbol table.
DiagnosticInfoOptimizationBase::Argument NV
static bool isMustTailCall(Value *V)
Class to represent array types.
int getObjectIndexEnd() const
Return one past the maximum frame object index.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
LLVM Basic Block Representation.
constexpr bool hasValue() const
EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
bool isOSDarwin() const
isOSDarwin - Is this a "Darwin" OS (macOS, iOS, tvOS or watchOS).
void setObjectSSPLayout(int ObjectIdx, SSPLayoutKind Kind)
MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight)
Return metadata containing two branch weights.
Represent the analysis usage information of a pass.
uint64_t getValue() const
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Legacy analysis pass which computes a DominatorTree.
STATISTIC(NumFunctions, "Total number of functions")
bool hasPersonalityFn() const
Check whether this function has a personality function.
bool isStringAttribute() const
Return true if the attribute is a string (target-dependent) attribute.
virtual void insertSSPDeclarations(Module &M) const
Inserts necessary declarations for SSP (stack protection) purpose.
StringRef getValueAsString() const
Return the attribute's value as a string.
std::enable_if_t< std::numeric_limits< T >::is_signed, bool > getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
static BranchProbability getBranchProbStackProtector(bool IsLikely)
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
Target-Independent Code Generator Pass Configuration Options.
unsigned EnableGlobalISel
EnableGlobalISel - This flag enables global instruction selection.
static Optional< MemoryLocation > getOrNone(const Instruction *Inst)
Module * getParent()
Get the module that this global value is contained inside of...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
This is an important class for using LLVM in a threaded context.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
initializer< Ty > init(const Ty &Val)
Class to represent pointers.
iterator find(const_arg_type_t< KeyT > Val)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Primary interface to the complete machine description for the target machine.
bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
A Module instance is used to store all the information related to an LLVM module.
unsigned EnableFastISel
EnableFastISel - This flag enables fast-path instruction selection which trades away generated code q...
virtual bool useStackGuardXorFP() const
If this function returns true, stack protection checks should XOR the frame pointer (or whichever poi...
Class for arbitrary precision integers.
bool shouldEmitSDCheck(const BasicBlock &BB) const
void moveAfter(BasicBlock *MovePos)
Unlink this basic block from its current function and insert it right after MovePos in the function M...
Class to represent struct types.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVMContext & getContext() const
All values hold a context through their type.
self_iterator getIterator()
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static bool CreatePrologue(Function *F, Module *M, ReturnInst *RI, const TargetLoweringBase *TLI, AllocaInst *&AI)
Insert code into the entry block that stores the stack guard variable onto the stack:
An instruction for reading from memory.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
LLVM_NODISCARD bool empty() const
const TargetMachine & getTargetMachine() const
virtual Function * getSSPStackGuardCheck(const Module &M) const
If the target has a standard stack protection check function that performs validation and error handl...
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
DominatorTree & getDomTree()
Constant * getPersonalityFn() const
Get the personality function associated with this function.
static Type * getVoidTy(LLVMContext &C)
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
virtual const TargetLowering * getTargetLowering() const
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
@ SSPLK_AddrOf
The address of this allocation is exposed and triggered protection.
Value * getArgOperand(unsigned i) const
const Triple & getTargetTriple() const
@ SSPLK_SmallArray
Array or nested array < SSP-buffer-size.
S is passed via registers r2 But gcc stores them to the stack
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
FunctionPass class - This class is used to implement most global optimizations.
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.
This class represents a function call, abstracting a target machine's calling convention.
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
AnalysisUsage & addRequired()
void initializeStackProtectorPass(PassRegistry &)
an instruction to allocate memory on the stack
static const CallInst * findStackProtectorIntrinsic(Function &F)
Search for the first call to the llvm.stackprotector intrinsic and return it if present.
LLVM Value Representation.
iterator_range< user_iterator > users()
StackProtectorGuards StackProtectorGuard
Stack protector guard mode to use, e.g. tls, global.
bool isFuncletEHPersonality(EHPersonality Pers)
Returns true if this is a personality function that invokes handler funclets (which must return to it...
FunctionPass * createStackProtectorPass()
createStackProtectorPass - This pass adds stack protectors to functions.
BasicBlockListType::iterator iterator
virtual Value * getIRStackGuard(IRBuilder<> &IRB) const
If the target has a standard location for the stack protector guard, returns the address of that loca...
const AllocaInst * getObjectAllocation(int ObjectIdx) const
Return the underlying Alloca of the specified stack object if it exists.
TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...