aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/StackProtector.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/StackProtector.cpp')
-rw-r--r--llvm/lib/CodeGen/StackProtector.cpp134
1 files changed, 85 insertions, 49 deletions
diff --git a/llvm/lib/CodeGen/StackProtector.cpp b/llvm/lib/CodeGen/StackProtector.cpp
index 2a8234a..cf6ed09 100644
--- a/llvm/lib/CodeGen/StackProtector.cpp
+++ b/llvm/lib/CodeGen/StackProtector.cpp
@@ -49,7 +49,6 @@
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include <optional>
-#include <utility>
using namespace llvm;
@@ -70,13 +69,15 @@ static cl::opt<bool> DisableCheckNoReturn("disable-check-noreturn-call",
/// - The prologue code loads and stores the stack guard onto the stack.
/// - The epilogue checks the value stored in the prologue against the original
/// value. It calls __stack_chk_fail if they differ.
-static bool InsertStackProtectors(const TargetMachine *TM, Function *F,
- DomTreeUpdater *DTU, bool &HasPrologue,
- bool &HasIRCheck);
+static bool InsertStackProtectors(const TargetLowering &TLI,
+ const LibcallLoweringInfo &Libcalls,
+ Function *F, DomTreeUpdater *DTU,
+ bool &HasPrologue, bool &HasIRCheck);
/// CreateFailBB - Create a basic block to jump to when the stack protector
/// check fails.
-static BasicBlock *CreateFailBB(Function *F, const TargetLowering &TLI);
+static BasicBlock *CreateFailBB(Function *F,
+ const LibcallLoweringInfo &Libcalls);
bool SSPLayoutInfo::shouldEmitSDCheck(const BasicBlock &BB) const {
return HasPrologue && !HasIRCheck && isa<ReturnInst>(BB.getTerminator());
@@ -132,8 +133,23 @@ PreservedAnalyses StackProtectorPass::run(Function &F,
return PreservedAnalyses::all();
}
+ auto &MAMProxy = FAM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
+ const LibcallLoweringModuleAnalysisResult *LibcallLowering =
+ MAMProxy.getCachedResult<LibcallLoweringModuleAnalysis>(*F.getParent());
+
+ if (!LibcallLowering) {
+ F.getContext().emitError("'" + LibcallLoweringModuleAnalysis::name() +
+ "' analysis required");
+ return PreservedAnalyses::all();
+ }
+
+ const TargetSubtargetInfo *STI = TM->getSubtargetImpl(F);
+ const TargetLowering *TLI = STI->getTargetLowering();
+ const LibcallLoweringInfo &Libcalls =
+ LibcallLowering->getLibcallLowering(*STI);
+
++NumFunProtected;
- bool Changed = InsertStackProtectors(TM, &F, DT ? &DTU : nullptr,
+ bool Changed = InsertStackProtectors(*TLI, Libcalls, &F, DT ? &DTU : nullptr,
Info.HasPrologue, Info.HasIRCheck);
#ifdef EXPENSIVE_CHECKS
assert((!DT ||
@@ -151,12 +167,11 @@ PreservedAnalyses StackProtectorPass::run(Function &F,
char StackProtector::ID = 0;
-StackProtector::StackProtector() : FunctionPass(ID) {
- initializeStackProtectorPass(*PassRegistry::getPassRegistry());
-}
+StackProtector::StackProtector() : FunctionPass(ID) {}
INITIALIZE_PASS_BEGIN(StackProtector, DEBUG_TYPE,
"Insert stack protectors", false, true)
+INITIALIZE_PASS_DEPENDENCY(LibcallLoweringInfoWrapper)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_END(StackProtector, DEBUG_TYPE,
@@ -165,6 +180,7 @@ INITIALIZE_PASS_END(StackProtector, DEBUG_TYPE,
FunctionPass *llvm::createStackProtectorPass() { return new StackProtector(); }
void StackProtector::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<LibcallLoweringInfoWrapper>();
AU.addRequired<TargetPassConfig>();
AU.addPreserved<DominatorTreeWrapperPass>();
}
@@ -191,9 +207,16 @@ bool StackProtector::runOnFunction(Function &Fn) {
return false;
}
+ const TargetSubtargetInfo *Subtarget = TM->getSubtargetImpl(Fn);
+ const LibcallLoweringInfo &Libcalls =
+ getAnalysis<LibcallLoweringInfoWrapper>().getLibcallLowering(*M,
+ *Subtarget);
+
+ const TargetLowering *TLI = Subtarget->getTargetLowering();
+
++NumFunProtected;
bool Changed =
- InsertStackProtectors(TM, F, DTU ? &*DTU : nullptr,
+ InsertStackProtectors(*TLI, Libcalls, F, DTU ? &*DTU : nullptr,
LayoutInfo.HasPrologue, LayoutInfo.HasIRCheck);
#ifdef EXPENSIVE_CHECKS
assert((!DTU ||
@@ -432,6 +455,11 @@ bool SSPLayoutAnalysis::requiresStackProtector(Function *F,
for (const BasicBlock &BB : *F) {
for (const Instruction &I : BB) {
if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
+ if (const MDNode *MD = AI->getMetadata("stack-protector")) {
+ const auto *CI = mdconst::dyn_extract<ConstantInt>(MD->getOperand(0));
+ if (CI->isZero())
+ continue;
+ }
if (AI->isArrayAllocation()) {
auto RemarkBuilder = [&]() {
return OptimizationRemark(DEBUG_TYPE, "StackProtectorAllocaOrArray",
@@ -491,22 +519,23 @@ bool SSPLayoutAnalysis::requiresStackProtector(Function *F,
continue;
}
- if (Strong &&
- HasAddressTaken(
- AI, M->getDataLayout().getTypeAllocSize(AI->getAllocatedType()),
- M, VisitedPHIs)) {
- ++NumAddrTaken;
- if (!Layout)
- return true;
- Layout->insert(std::make_pair(AI, MachineFrameInfo::SSPLK_AddrOf));
- ORE.emit([&]() {
- return OptimizationRemark(DEBUG_TYPE, "StackProtectorAddressTaken",
- &I)
- << "Stack protection applied to function "
- << ore::NV("Function", F)
- << " due to the address of a local variable being taken";
- });
- NeedsProtector = true;
+ if (Strong) {
+ std::optional<TypeSize> AllocSize =
+ AI->getAllocationSize(M->getDataLayout());
+ if (!AllocSize || HasAddressTaken(AI, *AllocSize, M, VisitedPHIs)) {
+ ++NumAddrTaken;
+ if (!Layout)
+ return true;
+ Layout->insert(std::make_pair(AI, MachineFrameInfo::SSPLK_AddrOf));
+ ORE.emit([&]() {
+ return OptimizationRemark(DEBUG_TYPE,
+ "StackProtectorAddressTaken", &I)
+ << "Stack protection applied to function "
+ << ore::NV("Function", F)
+ << " due to the address of a local variable being taken";
+ });
+ NeedsProtector = true;
+ }
}
// Clear any PHIs that we visited, to make sure we examine all uses of
// any subsequent allocas that we look at.
@@ -520,10 +549,11 @@ bool SSPLayoutAnalysis::requiresStackProtector(Function *F,
/// Create a stack guard loading and populate whether SelectionDAG SSP is
/// supported.
-static Value *getStackGuard(const TargetLoweringBase *TLI, Module *M,
+static Value *getStackGuard(const TargetLoweringBase &TLI,
+ const LibcallLoweringInfo &Libcalls, Module *M,
IRBuilder<> &B,
bool *SupportsSelectionDAGSP = nullptr) {
- Value *Guard = TLI->getIRStackGuard(B);
+ Value *Guard = TLI.getIRStackGuard(B, Libcalls);
StringRef GuardMode = M->getStackProtectorGuard();
if ((GuardMode == "tls" || GuardMode.empty()) && Guard)
return B.CreateLoad(B.getPtrTy(), Guard, true, "StackGuard");
@@ -541,7 +571,7 @@ static Value *getStackGuard(const TargetLoweringBase *TLI, Module *M,
// actually conveys the same information getIRStackGuard() already gives.
if (SupportsSelectionDAGSP)
*SupportsSelectionDAGSP = true;
- TLI->insertSSPDeclarations(*M);
+ TLI.insertSSPDeclarations(*M, Libcalls);
return B.CreateIntrinsic(Intrinsic::stackguard, {});
}
@@ -556,29 +586,32 @@ static Value *getStackGuard(const TargetLoweringBase *TLI, Module *M,
/// Returns true if the platform/triple supports the stackprotectorcreate pseudo
/// node.
static bool CreatePrologue(Function *F, Module *M, Instruction *CheckLoc,
- const TargetLoweringBase *TLI, AllocaInst *&AI) {
+ const TargetLoweringBase *TLI,
+ const LibcallLoweringInfo &Libcalls,
+ AllocaInst *&AI) {
bool SupportsSelectionDAGSP = false;
IRBuilder<> B(&F->getEntryBlock().front());
PointerType *PtrTy = PointerType::getUnqual(CheckLoc->getContext());
AI = B.CreateAlloca(PtrTy, nullptr, "StackGuardSlot");
- Value *GuardSlot = getStackGuard(TLI, M, B, &SupportsSelectionDAGSP);
+ Value *GuardSlot =
+ getStackGuard(*TLI, Libcalls, M, B, &SupportsSelectionDAGSP);
B.CreateIntrinsic(Intrinsic::stackprotector, {GuardSlot, AI});
return SupportsSelectionDAGSP;
}
-bool InsertStackProtectors(const TargetMachine *TM, Function *F,
+bool InsertStackProtectors(const TargetLowering &TLI,
+ const LibcallLoweringInfo &Libcalls, Function *F,
DomTreeUpdater *DTU, bool &HasPrologue,
bool &HasIRCheck) {
auto *M = F->getParent();
- auto *TLI = TM->getSubtargetImpl(*F)->getTargetLowering();
// If the target wants to XOR the frame pointer into the guard value, it's
// impossible to emit the check in IR, so the target *must* support stack
// protection in SDAG.
bool SupportsSelectionDAGSP =
- TLI->useStackGuardXorFP() ||
- (EnableSelectionDAGSP && !TM->Options.EnableFastISel);
+ TLI.useStackGuardXorFP() ||
+ (EnableSelectionDAGSP && !TLI.getTargetMachine().Options.EnableFastISel);
AllocaInst *AI = nullptr; // Place on stack that stores the stack guard.
BasicBlock *FailBB = nullptr;
@@ -611,7 +644,8 @@ bool InsertStackProtectors(const TargetMachine *TM, Function *F,
// Generate prologue instrumentation if not already generated.
if (!HasPrologue) {
HasPrologue = true;
- SupportsSelectionDAGSP &= CreatePrologue(F, M, CheckLoc, TLI, AI);
+ SupportsSelectionDAGSP &=
+ CreatePrologue(F, M, CheckLoc, &TLI, Libcalls, AI);
}
// SelectionDAG based code generation. Nothing else needs to be done here.
@@ -636,13 +670,13 @@ bool InsertStackProtectors(const TargetMachine *TM, Function *F,
// inserted before the call rather than between it and the return.
Instruction *Prev = CheckLoc->getPrevNode();
if (auto *CI = dyn_cast_if_present<CallInst>(Prev))
- if (CI->isTailCall() && isInTailCallPosition(*CI, *TM))
+ if (CI->isTailCall() && isInTailCallPosition(*CI, TLI.getTargetMachine()))
CheckLoc = Prev;
// Generate epilogue instrumentation. The epilogue intrumentation can be
// function-based or inlined depending on which mechanism the target is
// providing.
- if (Function *GuardCheck = TLI->getSSPStackGuardCheck(*M)) {
+ if (Function *GuardCheck = TLI.getSSPStackGuardCheck(*M, Libcalls)) {
// Generate the function-based epilogue instrumentation.
// The target provides a guard check function, generate a call to it.
IRBuilder<> B(CheckLoc);
@@ -681,10 +715,10 @@ bool InsertStackProtectors(const TargetMachine *TM, Function *F,
// merge pass will merge together all of the various BB into one including
// fail BB generated by the stack protector pseudo instruction.
if (!FailBB)
- FailBB = CreateFailBB(F, *TLI);
+ FailBB = CreateFailBB(F, Libcalls);
IRBuilder<> B(CheckLoc);
- Value *Guard = getStackGuard(TLI, M, B);
+ Value *Guard = getStackGuard(TLI, Libcalls, M, B);
LoadInst *LI2 = B.CreateLoad(B.getPtrTy(), AI, true);
auto *Cmp = cast<ICmpInst>(B.CreateICmpNE(Guard, LI2));
auto SuccessProb =
@@ -714,7 +748,7 @@ bool InsertStackProtectors(const TargetMachine *TM, Function *F,
return HasPrologue;
}
-BasicBlock *CreateFailBB(Function *F, const TargetLowering &TLI) {
+BasicBlock *CreateFailBB(Function *F, const LibcallLoweringInfo &Libcalls) {
auto *M = F->getParent();
LLVMContext &Context = F->getContext();
BasicBlock *FailBB = BasicBlock::Create(Context, "CallStackCheckFailBlk", F);
@@ -725,14 +759,16 @@ BasicBlock *CreateFailBB(Function *F, const TargetLowering &TLI) {
FunctionCallee StackChkFail;
SmallVector<Value *, 1> Args;
- if (const char *ChkFailName =
- TLI.getLibcallName(RTLIB::STACKPROTECTOR_CHECK_FAIL)) {
- StackChkFail =
- M->getOrInsertFunction(ChkFailName, Type::getVoidTy(Context));
- } else if (const char *SSHName =
- TLI.getLibcallName(RTLIB::STACK_SMASH_HANDLER)) {
- StackChkFail = M->getOrInsertFunction(SSHName, Type::getVoidTy(Context),
- PointerType::getUnqual(Context));
+ if (RTLIB::LibcallImpl ChkFailImpl =
+ Libcalls.getLibcallImpl(RTLIB::STACKPROTECTOR_CHECK_FAIL)) {
+ StackChkFail = M->getOrInsertFunction(
+ RTLIB::RuntimeLibcallsInfo::getLibcallImplName(ChkFailImpl),
+ Type::getVoidTy(Context));
+ } else if (RTLIB::LibcallImpl SSHImpl =
+ Libcalls.getLibcallImpl(RTLIB::STACK_SMASH_HANDLER)) {
+ StackChkFail = M->getOrInsertFunction(
+ RTLIB::RuntimeLibcallsInfo::getLibcallImplName(SSHImpl),
+ Type::getVoidTy(Context), PointerType::getUnqual(Context));
Args.push_back(B.CreateGlobalString(F->getName(), "SSH"));
} else {
Context.emitError("no libcall available for stack protector");