Skip to content

Commit 9cf982a

Browse files
committed
StackProtector: Use LibcallLoweringInfo analysis
1 parent 17769e5 commit 9cf982a

File tree

6 files changed

+67
-32
lines changed

6 files changed

+67
-32
lines changed

llvm/lib/CodeGen/StackProtector.cpp

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,15 @@ static cl::opt<bool> DisableCheckNoReturn("disable-check-noreturn-call",
6969
/// - The prologue code loads and stores the stack guard onto the stack.
7070
/// - The epilogue checks the value stored in the prologue against the original
7171
/// value. It calls __stack_chk_fail if they differ.
72-
static bool InsertStackProtectors(const TargetMachine *TM, Function *F,
73-
DomTreeUpdater *DTU, bool &HasPrologue,
74-
bool &HasIRCheck);
72+
static bool InsertStackProtectors(const TargetLowering &TLI,
73+
const LibcallLoweringInfo &Libcalls,
74+
Function *F, DomTreeUpdater *DTU,
75+
bool &HasPrologue, bool &HasIRCheck);
7576

7677
/// CreateFailBB - Create a basic block to jump to when the stack protector
7778
/// check fails.
78-
static BasicBlock *CreateFailBB(Function *F, const TargetLowering &TLI);
79+
static BasicBlock *CreateFailBB(Function *F,
80+
const LibcallLoweringInfo &Libcalls);
7981

8082
bool SSPLayoutInfo::shouldEmitSDCheck(const BasicBlock &BB) const {
8183
return HasPrologue && !HasIRCheck && isa<ReturnInst>(BB.getTerminator());
@@ -131,8 +133,23 @@ PreservedAnalyses StackProtectorPass::run(Function &F,
131133
return PreservedAnalyses::all();
132134
}
133135

136+
auto &MAMProxy = FAM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
137+
const LibcallLoweringModuleAnalysisResult *LibcallLowering =
138+
MAMProxy.getCachedResult<LibcallLoweringModuleAnalysis>(*F.getParent());
139+
140+
if (!LibcallLowering) {
141+
F.getContext().emitError("'" + LibcallLoweringModuleAnalysis::name() +
142+
"' analysis required");
143+
return PreservedAnalyses::all();
144+
}
145+
146+
const TargetSubtargetInfo *STI = TM->getSubtargetImpl(F);
147+
const TargetLowering *TLI = STI->getTargetLowering();
148+
const LibcallLoweringInfo &Libcalls =
149+
LibcallLowering->getLibcallLowering(*STI);
150+
134151
++NumFunProtected;
135-
bool Changed = InsertStackProtectors(TM, &F, DT ? &DTU : nullptr,
152+
bool Changed = InsertStackProtectors(*TLI, Libcalls, &F, DT ? &DTU : nullptr,
136153
Info.HasPrologue, Info.HasIRCheck);
137154
#ifdef EXPENSIVE_CHECKS
138155
assert((!DT ||
@@ -156,6 +173,7 @@ StackProtector::StackProtector() : FunctionPass(ID) {
156173

157174
INITIALIZE_PASS_BEGIN(StackProtector, DEBUG_TYPE,
158175
"Insert stack protectors", false, true)
176+
INITIALIZE_PASS_DEPENDENCY(LibcallLoweringInfoWrapper)
159177
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
160178
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
161179
INITIALIZE_PASS_END(StackProtector, DEBUG_TYPE,
@@ -164,6 +182,7 @@ INITIALIZE_PASS_END(StackProtector, DEBUG_TYPE,
164182
FunctionPass *llvm::createStackProtectorPass() { return new StackProtector(); }
165183

166184
void StackProtector::getAnalysisUsage(AnalysisUsage &AU) const {
185+
AU.addRequired<LibcallLoweringInfoWrapper>();
167186
AU.addRequired<TargetPassConfig>();
168187
AU.addPreserved<DominatorTreeWrapperPass>();
169188
}
@@ -190,9 +209,16 @@ bool StackProtector::runOnFunction(Function &Fn) {
190209
return false;
191210
}
192211

212+
const TargetSubtargetInfo *Subtarget = TM->getSubtargetImpl(Fn);
213+
const LibcallLoweringInfo &Libcalls =
214+
getAnalysis<LibcallLoweringInfoWrapper>().getLibcallLowering(*M,
215+
*Subtarget);
216+
217+
const TargetLowering *TLI = Subtarget->getTargetLowering();
218+
193219
++NumFunProtected;
194220
bool Changed =
195-
InsertStackProtectors(TM, F, DTU ? &*DTU : nullptr,
221+
InsertStackProtectors(*TLI, Libcalls, F, DTU ? &*DTU : nullptr,
196222
LayoutInfo.HasPrologue, LayoutInfo.HasIRCheck);
197223
#ifdef EXPENSIVE_CHECKS
198224
assert((!DTU ||
@@ -519,10 +545,10 @@ bool SSPLayoutAnalysis::requiresStackProtector(Function *F,
519545

520546
/// Create a stack guard loading and populate whether SelectionDAG SSP is
521547
/// supported.
522-
static Value *getStackGuard(const TargetLoweringBase *TLI, Module *M,
548+
static Value *getStackGuard(const TargetLoweringBase &TLI, Module *M,
523549
IRBuilder<> &B,
524550
bool *SupportsSelectionDAGSP = nullptr) {
525-
Value *Guard = TLI->getIRStackGuard(B);
551+
Value *Guard = TLI.getIRStackGuard(B);
526552
StringRef GuardMode = M->getStackProtectorGuard();
527553
if ((GuardMode == "tls" || GuardMode.empty()) && Guard)
528554
return B.CreateLoad(B.getPtrTy(), Guard, true, "StackGuard");
@@ -540,7 +566,7 @@ static Value *getStackGuard(const TargetLoweringBase *TLI, Module *M,
540566
// actually conveys the same information getIRStackGuard() already gives.
541567
if (SupportsSelectionDAGSP)
542568
*SupportsSelectionDAGSP = true;
543-
TLI->insertSSPDeclarations(*M);
569+
TLI.insertSSPDeclarations(*M);
544570
return B.CreateIntrinsic(Intrinsic::stackguard, {});
545571
}
546572

@@ -561,23 +587,23 @@ static bool CreatePrologue(Function *F, Module *M, Instruction *CheckLoc,
561587
PointerType *PtrTy = PointerType::getUnqual(CheckLoc->getContext());
562588
AI = B.CreateAlloca(PtrTy, nullptr, "StackGuardSlot");
563589

564-
Value *GuardSlot = getStackGuard(TLI, M, B, &SupportsSelectionDAGSP);
590+
Value *GuardSlot = getStackGuard(*TLI, M, B, &SupportsSelectionDAGSP);
565591
B.CreateIntrinsic(Intrinsic::stackprotector, {GuardSlot, AI});
566592
return SupportsSelectionDAGSP;
567593
}
568594

569-
bool InsertStackProtectors(const TargetMachine *TM, Function *F,
595+
bool InsertStackProtectors(const TargetLowering &TLI,
596+
const LibcallLoweringInfo &Libcalls, Function *F,
570597
DomTreeUpdater *DTU, bool &HasPrologue,
571598
bool &HasIRCheck) {
572599
auto *M = F->getParent();
573-
auto *TLI = TM->getSubtargetImpl(*F)->getTargetLowering();
574600

575601
// If the target wants to XOR the frame pointer into the guard value, it's
576602
// impossible to emit the check in IR, so the target *must* support stack
577603
// protection in SDAG.
578604
bool SupportsSelectionDAGSP =
579-
TLI->useStackGuardXorFP() ||
580-
(EnableSelectionDAGSP && !TM->Options.EnableFastISel);
605+
TLI.useStackGuardXorFP() ||
606+
(EnableSelectionDAGSP && !TLI.getTargetMachine().Options.EnableFastISel);
581607
AllocaInst *AI = nullptr; // Place on stack that stores the stack guard.
582608
BasicBlock *FailBB = nullptr;
583609

@@ -610,7 +636,7 @@ bool InsertStackProtectors(const TargetMachine *TM, Function *F,
610636
// Generate prologue instrumentation if not already generated.
611637
if (!HasPrologue) {
612638
HasPrologue = true;
613-
SupportsSelectionDAGSP &= CreatePrologue(F, M, CheckLoc, TLI, AI);
639+
SupportsSelectionDAGSP &= CreatePrologue(F, M, CheckLoc, &TLI, AI);
614640
}
615641

616642
// SelectionDAG based code generation. Nothing else needs to be done here.
@@ -635,13 +661,13 @@ bool InsertStackProtectors(const TargetMachine *TM, Function *F,
635661
// inserted before the call rather than between it and the return.
636662
Instruction *Prev = CheckLoc->getPrevNode();
637663
if (auto *CI = dyn_cast_if_present<CallInst>(Prev))
638-
if (CI->isTailCall() && isInTailCallPosition(*CI, *TM))
664+
if (CI->isTailCall() && isInTailCallPosition(*CI, TLI.getTargetMachine()))
639665
CheckLoc = Prev;
640666

641667
// Generate epilogue instrumentation. The epilogue intrumentation can be
642668
// function-based or inlined depending on which mechanism the target is
643669
// providing.
644-
if (Function *GuardCheck = TLI->getSSPStackGuardCheck(*M)) {
670+
if (Function *GuardCheck = TLI.getSSPStackGuardCheck(*M)) {
645671
// Generate the function-based epilogue instrumentation.
646672
// The target provides a guard check function, generate a call to it.
647673
IRBuilder<> B(CheckLoc);
@@ -680,7 +706,7 @@ bool InsertStackProtectors(const TargetMachine *TM, Function *F,
680706
// merge pass will merge together all of the various BB into one including
681707
// fail BB generated by the stack protector pseudo instruction.
682708
if (!FailBB)
683-
FailBB = CreateFailBB(F, *TLI);
709+
FailBB = CreateFailBB(F, Libcalls);
684710

685711
IRBuilder<> B(CheckLoc);
686712
Value *Guard = getStackGuard(TLI, M, B);
@@ -713,7 +739,7 @@ bool InsertStackProtectors(const TargetMachine *TM, Function *F,
713739
return HasPrologue;
714740
}
715741

716-
BasicBlock *CreateFailBB(Function *F, const TargetLowering &TLI) {
742+
BasicBlock *CreateFailBB(Function *F, const LibcallLoweringInfo &Libcalls) {
717743
auto *M = F->getParent();
718744
LLVMContext &Context = F->getContext();
719745
BasicBlock *FailBB = BasicBlock::Create(Context, "CallStackCheckFailBlk", F);
@@ -724,14 +750,16 @@ BasicBlock *CreateFailBB(Function *F, const TargetLowering &TLI) {
724750
FunctionCallee StackChkFail;
725751
SmallVector<Value *, 1> Args;
726752

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 =
732-
TLI.getLibcallName(RTLIB::STACK_SMASH_HANDLER)) {
733-
StackChkFail = M->getOrInsertFunction(SSHName, Type::getVoidTy(Context),
734-
PointerType::getUnqual(Context));
753+
if (RTLIB::LibcallImpl ChkFailImpl =
754+
Libcalls.getLibcallImpl(RTLIB::STACKPROTECTOR_CHECK_FAIL)) {
755+
StackChkFail = M->getOrInsertFunction(
756+
RTLIB::RuntimeLibcallsInfo::getLibcallImplName(ChkFailImpl),
757+
Type::getVoidTy(Context));
758+
} else if (RTLIB::LibcallImpl SSHImpl =
759+
Libcalls.getLibcallImpl(RTLIB::STACK_SMASH_HANDLER)) {
760+
StackChkFail = M->getOrInsertFunction(
761+
RTLIB::RuntimeLibcallsInfo::getLibcallImplName(SSHImpl),
762+
Type::getVoidTy(Context), PointerType::getUnqual(Context));
735763
Args.push_back(B.CreateGlobalString(F->getName(), "SSH"));
736764
} else {
737765
Context.emitError("no libcall available for stack protector");

llvm/test/CodeGen/NVPTX/no-stack-protector-libcall-error.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: not opt -disable-output -mtriple=nvptx64-- -enable-selectiondag-sp=0 -passes=stack-protector %s 2>&1 | FileCheck %s
1+
; RUN: not opt -disable-output -mtriple=nvptx64-- -enable-selectiondag-sp=0 -passes='require<libcall-lowering-info>,stack-protector' %s 2>&1 | FileCheck %s
22

33
; CHECK: error: no libcall available for stack protector
44
define void @func() sspreq nounwind {

llvm/test/CodeGen/X86/stack-protector-atomicrmw-xchg.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2-
; RUN: opt -S -mtriple=x86_64-unknown-linux-gnu -passes=stack-protector < %s | FileCheck %s
3-
; RUN: opt -S -mtriple=x86_64-unknown-linux-gnu -passes='require<domtree>,stack-protector' < %s | FileCheck %s
2+
; RUN: opt -S -mtriple=x86_64-unknown-linux-gnu -passes='require<libcall-lowering-info>,stack-protector' < %s | FileCheck %s
3+
; RUN: opt -S -mtriple=x86_64-unknown-linux-gnu -passes='require<libcall-lowering-info>,function(require<domtree>,stack-protector)' < %s | FileCheck %s
44

55
define void @atomicrmw_xchg(ptr %p) sspstrong {
66
; CHECK-LABEL: define void @atomicrmw_xchg(

llvm/test/Transforms/StackProtector/cross-dso-cfi-stack-chk-fail.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
;; This is a minimal reproducer that caused StackProtector to crash with a bad cast when
22
;; CrossDSOCFI is used. This test just needs to not crash.
33
; REQUIRES: x86-registered-target
4-
; RUN: opt -mtriple=x86_64-pc-linux-gnu %s -passes=lowertypetests,cross-dso-cfi,stack-protector
4+
; RUN: opt -mtriple=x86_64-pc-linux-gnu %s -passes='require<libcall-lowering-info>,lowertypetests,cross-dso-cfi,stack-protector'
55

66
define hidden void @__stack_chk_fail() !type !1{
77
unreachable
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
; REQUIRES: x86-registered-target
2+
; RUN: not opt -mtriple=x86_64-- -passes=expand-fp -disable-output %s 2>&1 | FileCheck %s
3+
4+
; CHECK: 'LibcallLoweringModuleAnalysis' analysis required
5+
define void @empty() {
6+
ret void
7+
}

llvm/test/Transforms/StackProtector/stack-chk-fail-alias.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
;; __stack_chk_fail should have the noreturn attr even if it is an alias
22
; REQUIRES: x86-registered-target
3-
; RUN: opt -mtriple=x86_64-pc-linux-gnu %s -passes=stack-protector -S | FileCheck %s
3+
; RUN: opt -mtriple=x86_64-pc-linux-gnu %s -passes='require<libcall-lowering-info>,stack-protector' -S | FileCheck %s
44

55
define hidden void @__stack_chk_fail_impl() {
66
unreachable

0 commit comments

Comments
 (0)