Skip to content

Commit 259a11d

Browse files
authored
StackProtector: Use RuntimeLibcalls to query libcall names (#147913)
The compiler should not introduce calls to arbitrary strings that aren't defined in RuntimeLibcalls. Previously OpenBSD was disabling the default __stack_chk_fail, but there was no record of the alternative __stack_smash_handler function it emits instead. This also avoids a random triple check in the pass.
1 parent a1c61ac commit 259a11d

File tree

4 files changed

+33
-10
lines changed

4 files changed

+33
-10
lines changed

llvm/include/llvm/IR/RuntimeLibcalls.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ defset list<RuntimeLibcall> LibCalls__OutOfLineAtomic = {
357357

358358
// Stack Protector Fail
359359
def STACKPROTECTOR_CHECK_FAIL : RuntimeLibcall;
360+
def STACK_SMASH_HANDLER : RuntimeLibcall;
360361

361362
// Deoptimization
362363
def DEOPTIMIZE : RuntimeLibcall;
@@ -987,6 +988,9 @@ def bzero : RuntimeLibcallImpl<BZERO>;
987988
def __bzero : RuntimeLibcallImpl<BZERO>;
988989
def _Unwind_SjLj_Resume : RuntimeLibcallImpl<UNWIND_RESUME>;
989990

991+
// Used on OpenBSD
992+
def __stack_smash_handler : RuntimeLibcallImpl<STACK_SMASH_HANDLER>;
993+
990994
def __riscv_flush_icache : RuntimeLibcallImpl<RISCV_FLUSH_ICACHE>;
991995

992996
//===----------------------------------------------------------------------===//

llvm/lib/CodeGen/StackProtector.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ static bool InsertStackProtectors(const TargetMachine *TM, Function *F,
7676

7777
/// CreateFailBB - Create a basic block to jump to when the stack protector
7878
/// check fails.
79-
static BasicBlock *CreateFailBB(Function *F, const Triple &Trip);
79+
static BasicBlock *CreateFailBB(Function *F, const TargetLowering &TLI);
8080

8181
bool SSPLayoutInfo::shouldEmitSDCheck(const BasicBlock &BB) const {
8282
return HasPrologue && !HasIRCheck && isa<ReturnInst>(BB.getTerminator());
@@ -673,7 +673,7 @@ bool InsertStackProtectors(const TargetMachine *TM, Function *F,
673673
// merge pass will merge together all of the various BB into one including
674674
// fail BB generated by the stack protector pseudo instruction.
675675
if (!FailBB)
676-
FailBB = CreateFailBB(F, TM->getTargetTriple());
676+
FailBB = CreateFailBB(F, *TLI);
677677

678678
IRBuilder<> B(CheckLoc);
679679
Value *Guard = getStackGuard(TLI, M, B);
@@ -706,7 +706,7 @@ bool InsertStackProtectors(const TargetMachine *TM, Function *F,
706706
return HasPrologue;
707707
}
708708

709-
BasicBlock *CreateFailBB(Function *F, const Triple &Trip) {
709+
BasicBlock *CreateFailBB(Function *F, const TargetLowering &TLI) {
710710
auto *M = F->getParent();
711711
LLVMContext &Context = F->getContext();
712712
BasicBlock *FailBB = BasicBlock::Create(Context, "CallStackCheckFailBlk", F);
@@ -716,17 +716,25 @@ BasicBlock *CreateFailBB(Function *F, const Triple &Trip) {
716716
DILocation::get(Context, 0, 0, F->getSubprogram()));
717717
FunctionCallee StackChkFail;
718718
SmallVector<Value *, 1> Args;
719-
if (Trip.isOSOpenBSD()) {
720-
StackChkFail = M->getOrInsertFunction("__stack_smash_handler",
721-
Type::getVoidTy(Context),
719+
720+
if (const char *ChkFailName =
721+
TLI.getLibcallName(RTLIB::STACKPROTECTOR_CHECK_FAIL)) {
722+
StackChkFail =
723+
M->getOrInsertFunction(ChkFailName, Type::getVoidTy(Context));
724+
} else if (const char *SSHName =
725+
TLI.getLibcallName(RTLIB::STACK_SMASH_HANDLER)) {
726+
StackChkFail = M->getOrInsertFunction(SSHName, Type::getVoidTy(Context),
722727
PointerType::getUnqual(Context));
723728
Args.push_back(B.CreateGlobalString(F->getName(), "SSH"));
724729
} else {
725-
StackChkFail =
726-
M->getOrInsertFunction("__stack_chk_fail", Type::getVoidTy(Context));
730+
Context.emitError("no libcall available for stack protector");
727731
}
728-
cast<Function>(StackChkFail.getCallee())->addFnAttr(Attribute::NoReturn);
729-
B.CreateCall(StackChkFail, Args);
732+
733+
if (StackChkFail) {
734+
cast<Function>(StackChkFail.getCallee())->addFnAttr(Attribute::NoReturn);
735+
B.CreateCall(StackChkFail, Args);
736+
}
737+
730738
B.CreateUnreachable();
731739
return FailBB;
732740
}

llvm/lib/IR/RuntimeLibcalls.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
100100

101101
if (TT.isOSOpenBSD()) {
102102
setLibcallImpl(RTLIB::STACKPROTECTOR_CHECK_FAIL, RTLIB::Unsupported);
103+
setLibcallImpl(RTLIB::STACK_SMASH_HANDLER, RTLIB::__stack_smash_handler);
103104
}
104105

105106
// Skip default manual processing for targets that have been fully ported to
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
; RUN: not opt -disable-output -mtriple=nvptx64-- -enable-selectiondag-sp=0 -passes=stack-protector %s 2>&1 | FileCheck %s
2+
3+
; CHECK: error: no libcall available for stack protector
4+
define void @func() sspreq nounwind {
5+
%alloca = alloca i32, align 4
6+
call void @capture(ptr %alloca)
7+
ret void
8+
}
9+
10+
declare void @capture(ptr)

0 commit comments

Comments
 (0)