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

53using namespace llvm;

54

55#define DEBUG_TYPE "stack-protector"

56

57STATISTIC(NumFunProtected, "Number of functions protected");

58STATISTIC(NumAddrTaken, "Number of local variables that have their address"

59 " taken.");

60

65

66

67

68

69

70

71

74 bool &HasIRCheck);

75

76

77

79

83

85 if (Layout.empty())

86 return;

87

90 continue;

91

93 if (!AI)

94 continue;

95

97 if (LI == Layout.end())

98 continue;

99

101 }

102}

103

106

108 Info.RequireStackProtector =

110 Info.SSPBufferSize = F.getFnAttributeAsParsedInteger(

111 "stack-protector-buffer-size", SSPLayoutInfo::DefaultSSPBufferSize);

112 return Info;

113}

114

116

121 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);

122

123 if (!Info.RequireStackProtector)

125

126

127

128 if (F.hasPersonalityFn()) {

132 }

133

134 ++NumFunProtected;

136 Info.HasPrologue, Info.HasIRCheck);

137#ifdef EXPENSIVE_CHECKS

139 DTU.getDomTree().verify(DominatorTree::VerificationLevel::Full)) &&

140 "Failed to maintain validity of domtree!");

141#endif

142

148 return PA;

149}

150

152

156

158 "Insert stack protectors", false, true)

163

165

170

172 F = &Fn;

175 DTU.emplace(DTWP->getDomTree(), DomTreeUpdater::UpdateStrategy::Lazy);

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;

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();

204}

205

206

207

208

210 bool &IsLarge, bool Strong,

211 bool InStruct) {

212 if (!Ty)

213 return false;

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

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

255

256

264

265

268 PhiMap &VisitedPHIs) {

270 for (const User *U : AI->users()) {

272

273

275 if (MemLoc && MemLoc->Size.hasValue() &&

277 return true;

278 switch (I->getOpcode()) {

279 case Instruction::Store:

281 return true;

282 break;

283 case Instruction::AtomicCmpXchg:

284

285

287 return true;

288 break;

289 case Instruction::AtomicRMW:

291 return true;

292 break;

293 case Instruction::PtrToInt:

295 return true;

296 break;

297 case Instruction::Call: {

298

299

301 if (!CI->isDebugOrPseudoInst() && !CI->isLifetimeStartOrEnd())

302 return true;

303 break;

304 }

305 case Instruction::Invoke:

306 return true;

307 case Instruction::GetElementPtr: {

308

309

310

311

313 unsigned IndexSize = DL.getIndexTypeSizeInBits(I->getType());

315 if (GEP->accumulateConstantOffset(DL, Offset))

316 return true;

319 return true;

320

321

322

326 return true;

327 break;

328 }

329 case Instruction::BitCast:

330 case Instruction::Select:

331 case Instruction::AddrSpaceCast:

333 return true;

334 break;

335 case Instruction::PHI: {

336

337

339 auto [It, Inserted] = VisitedPHIs.try_emplace(PN, AllocSize);

340 if (!Inserted) {

342 break;

343

344

346 return true;

347

348 It->second.AllocSize = AllocSize;

349 ++It->second.NumDecreased;

350 }

352 return true;

353 break;

354 }

355 case Instruction::Load:

356 case Instruction::Ret:

357

358

359 break;

360 default:

361

362

363 return true;

364 }

365 }

366 return false;

367}

368

369

370

375 if (II->getIntrinsicID() == Intrinsic::stackprotector)

376 return II;

377 return nullptr;

378}

379

380

381

382

383

384

385

386

387

388

389

390

391

392

394 SSPLayoutMap *Layout) {

395 Module *M = F->getParent();

396 bool Strong = false;

397 bool NeedsProtector = false;

398

399

400

401

403

404 unsigned SSPBufferSize = F->getFnAttributeAsParsedInteger(

405 "stack-protector-buffer-size", SSPLayoutInfo::DefaultSSPBufferSize);

406

407 if (F->hasFnAttribute(Attribute::SafeStack))

408 return false;

409

410

411

412

414

415 if (F->hasFnAttribute(Attribute::StackProtectReq)) {

416 if (!Layout)

417 return true;

418 ORE.emit([&]() {

420 << "Stack protection applied to function "

422 << " due to a function attribute or command-line switch";

423 });

424 NeedsProtector = true;

425 Strong = true;

426 } else if (F->hasFnAttribute(Attribute::StackProtectStrong))

427 Strong = true;

428 else if (F->hasFnAttribute(Attribute::StackProtect))

429 return false;

430

434 if (AI->isArrayAllocation()) {

435 auto RemarkBuilder = [&]() {

437 &I)

438 << "Stack protection applied to function "

440 << " due to a call to alloca or use of a variable length "

441 "array";

442 };

444 if (CI->getLimitedValue(SSPBufferSize) >= SSPBufferSize) {

445

446

447 if (!Layout)

448 return true;

451 ORE.emit(RemarkBuilder);

452 NeedsProtector = true;

453 } else if (Strong) {

454

455 if (!Layout)

456 return true;

459 ORE.emit(RemarkBuilder);

460 NeedsProtector = true;

461 }

462 } else {

463

464 if (!Layout)

465 return true;

468 ORE.emit(RemarkBuilder);

469 NeedsProtector = true;

470 }

471 continue;

472 }

473

474 bool IsLarge = false;

476 IsLarge, Strong, false)) {

477 if (!Layout)

478 return true;

479 Layout->insert(std::make_pair(

482 ORE.emit([&]() {

484 << "Stack protection applied to function "

486 << " due to a stack allocated buffer or struct containing a "

487 "buffer";

488 });

489 NeedsProtector = true;

490 continue;

491 }

492

493 if (Strong &&

495 AI, M->getDataLayout().getTypeAllocSize(AI->getAllocatedType()),

496 M, VisitedPHIs)) {

497 ++NumAddrTaken;

498 if (!Layout)

499 return true;

501 ORE.emit([&]() {

503 &I)

504 << "Stack protection applied to function "

506 << " due to the address of a local variable being taken";

507 });

508 NeedsProtector = true;

509 }

510

511

512 VisitedPHIs.clear();

513 }

514 }

515 }

516

517 return NeedsProtector;

518}

519

520

521

524 bool *SupportsSelectionDAGSP = nullptr) {

526 StringRef GuardMode = M->getStackProtectorGuard();

527 if ((GuardMode == "tls" || GuardMode.empty()) && Guard)

528 return B.CreateLoad(B.getPtrTy(), Guard, true, "StackGuard");

529

530

531

532

533

534

535

536

537

538

539

540

541 if (SupportsSelectionDAGSP)

542 *SupportsSelectionDAGSP = true;

544 return B.CreateIntrinsic(Intrinsic::stackguard, {});

545}

546

547

548

549

550

551

552

553

554

555

556

559 bool SupportsSelectionDAGSP = false;

562 AI = B.CreateAlloca(PtrTy, nullptr, "StackGuardSlot");

563

565 B.CreateIntrinsic(Intrinsic::stackprotector, {GuardSlot, AI});

566 return SupportsSelectionDAGSP;

567}

568

571 bool &HasIRCheck) {

572 auto *M = F->getParent();

574

575

576

577

578 bool SupportsSelectionDAGSP =

581 AllocaInst *AI = nullptr;

583

585

586 if (&BB == FailBB)

587 continue;

590 for (auto &Inst : BB) {

592 IB && (IB->getIntrinsicID() == Intrinsic::eh_sjlj_callsite)) {

593

594

595 CheckLoc = IB;

596 break;

597 }

599

600

601 if (CB->doesNotReturn() && !CB->doesNotThrow()) {

602 CheckLoc = CB;

603 break;

604 }

605 }

606

607 if (!CheckLoc)

608 continue;

609

610

611 if (!HasPrologue) {

612 HasPrologue = true;

613 SupportsSelectionDAGSP &= CreatePrologue(F, M, CheckLoc, TLI, AI);

614 }

615

616

617

618 if (SupportsSelectionDAGSP)

619 break;

620

621

622

623 if (!AI) {

625 assert(SPCall && "Call to llvm.stackprotector is missing");

627 }

628

629

630

631

632 HasIRCheck = true;

633

634

635

639 CheckLoc = Prev;

640

641

642

643

644 if (Function *GuardCheck = TLI->getSSPStackGuardCheck(*M)) {

645

646

648 LoadInst *Guard = B.CreateLoad(B.getPtrTy(), AI, true, "Guard");

649 CallInst *Call = B.CreateCall(GuardCheck, {Guard});

650 Call->setAttributes(GuardCheck->getAttributes());

651 Call->setCallingConv(GuardCheck->getCallingConv());

652 } else {

653

654

655

656

657

658

659

660

661

662

663

664

665

666

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682 if (!FailBB)

684

687 LoadInst *LI2 = B.CreateLoad(B.getPtrTy(), AI, true);

689 auto SuccessProb =

691 auto FailureProb =

695 SuccessProb.getNumerator());

696

698 false, Weights, DTU,

699 nullptr, FailBB);

700

701 auto *BI = cast(Cmp->getParent()->getTerminator());

702 BasicBlock *NewBB = BI->getSuccessor(1);

703 NewBB->setName("SP_return");

705

706 Cmp->setPredicate(Cmp->getInversePredicate());

707 BI->swapSuccessors();

708 }

709 }

710

711

712

713 return HasPrologue;

714}

715

717 auto *M = F->getParent();

721 if (F->getSubprogram())

722 B.SetCurrentDebugLocation(

726

727 if (const char *ChkFailName =

728 TLI.getLibcallName(RTLIB::STACKPROTECTOR_CHECK_FAIL)) {

729 StackChkFail =

730 M->getOrInsertFunction(ChkFailName, Type::getVoidTy(Context));

731 } else if (const char *SSHName =

733 StackChkFail = M->getOrInsertFunction(SSHName, Type::getVoidTy(Context),

735 Args.push_back(B.CreateGlobalString(F->getName(), "SSH"));

736 } else {

737 Context.emitError("no libcall available for stack protector");

738 }

739

740 if (StackChkFail) {

741 CallInst *Call = B.CreateCall(StackChkFail, Args);

742 Call->addFnAttr(Attribute::NoReturn);

743 }

744

745 B.CreateUnreachable();

746 return FailBB;

747}

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 Value * getStackGuard(const TargetLoweringBase *TLI, Module *M, IRBuilder<> &B, bool *SupportsSelectionDAGSP=nullptr)

Create a stack guard loading and populate whether SelectionDAG SSP is supported.

Definition StackProtector.cpp:522

static BasicBlock * CreateFailBB(Function *F, const TargetLowering &TLI)

CreateFailBB - Create a basic block to jump to when the stack protector check fails.

Definition StackProtector.cpp:716

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.

Definition StackProtector.cpp:569

static bool HasAddressTaken(const Instruction *AI, TypeSize AllocSize, Module *M, PhiMap &VisitedPHIs)

Check whether a stack allocation has its address taken.

Definition StackProtector.cpp:266

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:

Definition StackProtector.cpp:557

SmallDenseMap< const PHINode *, PhiInfo, 16 > PhiMap

Definition StackProtector.cpp:263

static bool ContainsProtectableArray(Type *Ty, Module *M, unsigned SSPBufferSize, bool &IsLarge, bool Strong, bool InStruct)

Definition StackProtector.cpp:209

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.

Definition StackProtector.cpp:371

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.

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.

static LLVM_ABI PassRegistry * getPassRegistry()

getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...

AnalysisType & getAnalysis() const

getAnalysis() - This function is used by subclasses to get to the analysis information ...

AnalysisType * getAnalysisIfAvailable() const

getAnalysisIfAvailable() - 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.

Definition StackProtector.cpp:393

Result run(Function &F, FunctionAnalysisManager &FAM)

Definition StackProtector.cpp:104

void copyToMachineFrameInfo(MachineFrameInfo &MFI) const

Definition StackProtector.cpp:84

bool shouldEmitSDCheck(const BasicBlock &BB) const

Definition StackProtector.cpp:80

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)

Definition StackProtector.cpp:117

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...

Definition StackProtector.cpp:166

StackProtector()

Definition StackProtector.cpp:153

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.

Definition StackProtector.cpp:171

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 Value * getIRStackGuard(IRBuilderBase &IRB) const

If the target has a standard location for the stack protector guard, returns the address of that loca...

const char * getLibcallName(RTLIB::Libcall Call) const

Get the libcall routine name for the specified libcall.

virtual void insertSSPDeclarations(Module &M) 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.

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

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)

DiagnosticInfoOptimizationBase::Argument NV

This is an optimization pass for GlobalISel generic memory operations.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

auto dyn_cast_if_present(const Y &Val)

dyn_cast_if_present - 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.

Definition StackProtector.cpp:164

LLVM_ABI void initializeStackProtectorPass(PassRegistry &)

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 - 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 - 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)

Definition StackProtector.cpp:261

unsigned NumDecreased

Definition StackProtector.cpp:259

static constexpr unsigned MaxNumDecreased

Definition StackProtector.cpp:260

TypeSize AllocSize

Definition StackProtector.cpp:258

A special type used by analysis passes to provide an address that identifies that particular analysis...