aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/CodeGen/StackProtector.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/StackProtector.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/CodeGen/StackProtector.cpp93
1 files changed, 58 insertions, 35 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/StackProtector.cpp b/contrib/llvm-project/llvm/lib/CodeGen/StackProtector.cpp
index fca822a485ca..3ec70083b704 100644
--- a/contrib/llvm-project/llvm/lib/CodeGen/StackProtector.cpp
+++ b/contrib/llvm-project/llvm/lib/CodeGen/StackProtector.cpp
@@ -14,12 +14,12 @@
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/StackProtector.h"
-#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
+#include "llvm/CodeGen/Analysis.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetPassConfig.h"
@@ -76,7 +76,7 @@ static bool InsertStackProtectors(const TargetMachine *TM, Function *F,
/// CreateFailBB - Create a basic block to jump to when the stack protector
/// check fails.
-static BasicBlock *CreateFailBB(Function *F, const Triple &Trip);
+static BasicBlock *CreateFailBB(Function *F, const TargetLowering &TLI);
bool SSPLayoutInfo::shouldEmitSDCheck(const BasicBlock &BB) const {
return HasPrologue && !HasIRCheck && isa<ReturnInst>(BB.getTerminator());
@@ -136,7 +136,8 @@ PreservedAnalyses StackProtectorPass::run(Function &F,
bool Changed = InsertStackProtectors(TM, &F, DT ? &DTU : nullptr,
Info.HasPrologue, Info.HasIRCheck);
#ifdef EXPENSIVE_CHECKS
- assert((!DT || DT->verify(DominatorTree::VerificationLevel::Full)) &&
+ assert((!DT ||
+ DTU.getDomTree().verify(DominatorTree::VerificationLevel::Full)) &&
"Failed to maintain validity of domtree!");
#endif
@@ -217,7 +218,7 @@ static bool ContainsProtectableArray(Type *Ty, Module *M, unsigned SSPBufferSize
// add stack protectors unless the array is a character array.
// However, in strong mode any array, regardless of type and size,
// triggers a protector.
- if (!Strong && (InStruct || !Triple(M->getTargetTriple()).isOSDarwin()))
+ if (!Strong && (InStruct || !M->getTargetTriple().isOSDarwin()))
return false;
}
@@ -251,10 +252,21 @@ static bool ContainsProtectableArray(Type *Ty, Module *M, unsigned SSPBufferSize
return NeedsProtector;
}
+/// Maximum remaining allocation size observed for a phi node, and how often
+/// the allocation size has already been decreased. We only allow a limited
+/// number of decreases.
+struct PhiInfo {
+ TypeSize AllocSize;
+ unsigned NumDecreased = 0;
+ static constexpr unsigned MaxNumDecreased = 3;
+ PhiInfo(TypeSize AllocSize) : AllocSize(AllocSize) {}
+};
+using PhiMap = SmallDenseMap<const PHINode *, PhiInfo, 16>;
+
/// Check whether a stack allocation has its address taken.
static bool HasAddressTaken(const Instruction *AI, TypeSize AllocSize,
Module *M,
- SmallPtrSet<const PHINode *, 16> &VisitedPHIs) {
+ PhiMap &VisitedPHIs) {
const DataLayout &DL = M->getDataLayout();
for (const User *U : AI->users()) {
const auto *I = cast<Instruction>(U);
@@ -275,6 +287,10 @@ static bool HasAddressTaken(const Instruction *AI, TypeSize AllocSize,
if (AI == cast<AtomicCmpXchgInst>(I)->getNewValOperand())
return true;
break;
+ case Instruction::AtomicRMW:
+ if (AI == cast<AtomicRMWInst>(I)->getValOperand())
+ return true;
+ break;
case Instruction::PtrToInt:
if (AI == cast<PtrToIntInst>(I)->getOperand(0))
return true;
@@ -321,19 +337,26 @@ static bool HasAddressTaken(const Instruction *AI, TypeSize AllocSize,
// Keep track of what PHI nodes we have already visited to ensure
// they are only visited once.
const auto *PN = cast<PHINode>(I);
- if (VisitedPHIs.insert(PN).second)
- if (HasAddressTaken(PN, AllocSize, M, VisitedPHIs))
+ auto [It, Inserted] = VisitedPHIs.try_emplace(PN, AllocSize);
+ if (!Inserted) {
+ if (TypeSize::isKnownGE(AllocSize, It->second.AllocSize))
+ break;
+
+ // Check again with smaller size.
+ if (It->second.NumDecreased == PhiInfo::MaxNumDecreased)
return true;
+
+ It->second.AllocSize = AllocSize;
+ ++It->second.NumDecreased;
+ }
+ if (HasAddressTaken(PN, AllocSize, M, VisitedPHIs))
+ return true;
break;
}
case Instruction::Load:
- case Instruction::AtomicRMW:
case Instruction::Ret:
// These instructions take an address operand, but have load-like or
// other innocuous behavior that should not trigger a stack protector.
- // atomicrmw conceptually has both load and store semantics, but the
- // value being stored must be integer; so if a pointer is being stored,
- // we'll catch it in the PtrToInt case above.
break;
default:
// Conservatively return true for any instruction that takes an address
@@ -377,7 +400,7 @@ bool SSPLayoutAnalysis::requiresStackProtector(Function *F,
// The set of PHI nodes visited when determining if a variable's reference has
// been taken. This set is maintained to ensure we don't visit the same PHI
// node multiple times.
- SmallPtrSet<const PHINode *, 16> VisitedPHIs;
+ PhiMap VisitedPHIs;
unsigned SSPBufferSize = F->getFnAttributeAsParsedInteger(
"stack-protector-buffer-size", SSPLayoutInfo::DefaultSSPBufferSize);
@@ -519,7 +542,7 @@ static Value *getStackGuard(const TargetLoweringBase *TLI, Module *M,
if (SupportsSelectionDAGSP)
*SupportsSelectionDAGSP = true;
TLI->insertSSPDeclarations(*M);
- return B.CreateCall(Intrinsic::getDeclaration(M, Intrinsic::stackguard));
+ return B.CreateIntrinsic(Intrinsic::stackguard, {});
}
/// Insert code into the entry block that stores the stack guard
@@ -540,8 +563,7 @@ static bool CreatePrologue(Function *F, Module *M, Instruction *CheckLoc,
AI = B.CreateAlloca(PtrTy, nullptr, "StackGuardSlot");
Value *GuardSlot = getStackGuard(TLI, M, B, &SupportsSelectionDAGSP);
- B.CreateCall(Intrinsic::getDeclaration(M, Intrinsic::stackprotector),
- {GuardSlot, AI});
+ B.CreateIntrinsic(Intrinsic::stackprotector, {GuardSlot, AI});
return SupportsSelectionDAGSP;
}
@@ -603,18 +625,11 @@ bool InsertStackProtectors(const TargetMachine *TM, Function *F,
HasIRCheck = true;
// If we're instrumenting a block with a tail call, the check has to be
- // inserted before the call rather than between it and the return. The
- // verifier guarantees that a tail call is either directly before the
- // return or with a single correct bitcast of the return value in between so
- // we don't need to worry about many situations here.
+ // inserted before the call rather than between it and the return.
Instruction *Prev = CheckLoc->getPrevNonDebugInstruction();
- if (Prev && isa<CallInst>(Prev) && cast<CallInst>(Prev)->isTailCall())
- CheckLoc = Prev;
- else if (Prev) {
- Prev = Prev->getPrevNonDebugInstruction();
- if (Prev && isa<CallInst>(Prev) && cast<CallInst>(Prev)->isTailCall())
+ if (auto *CI = dyn_cast_if_present<CallInst>(Prev))
+ if (CI->isTailCall() && isInTailCallPosition(*CI, *TM))
CheckLoc = Prev;
- }
// Generate epilogue instrumentation. The epilogue intrumentation can be
// function-based or inlined depending on which mechanism the target is
@@ -658,7 +673,7 @@ 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, TM->getTargetTriple());
+ FailBB = CreateFailBB(F, *TLI);
IRBuilder<> B(CheckLoc);
Value *Guard = getStackGuard(TLI, M, B);
@@ -691,7 +706,7 @@ bool InsertStackProtectors(const TargetMachine *TM, Function *F,
return HasPrologue;
}
-BasicBlock *CreateFailBB(Function *F, const Triple &Trip) {
+BasicBlock *CreateFailBB(Function *F, const TargetLowering &TLI) {
auto *M = F->getParent();
LLVMContext &Context = F->getContext();
BasicBlock *FailBB = BasicBlock::Create(Context, "CallStackCheckFailBlk", F);
@@ -701,17 +716,25 @@ BasicBlock *CreateFailBB(Function *F, const Triple &Trip) {
DILocation::get(Context, 0, 0, F->getSubprogram()));
FunctionCallee StackChkFail;
SmallVector<Value *, 1> Args;
- if (Trip.isOSOpenBSD()) {
- StackChkFail = M->getOrInsertFunction("__stack_smash_handler",
- Type::getVoidTy(Context),
+
+ 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));
- Args.push_back(B.CreateGlobalStringPtr(F->getName(), "SSH"));
+ Args.push_back(B.CreateGlobalString(F->getName(), "SSH"));
} else {
- StackChkFail =
- M->getOrInsertFunction("__stack_chk_fail", Type::getVoidTy(Context));
+ Context.emitError("no libcall available for stack protector");
+ }
+
+ if (StackChkFail) {
+ cast<Function>(StackChkFail.getCallee())->addFnAttr(Attribute::NoReturn);
+ B.CreateCall(StackChkFail, Args);
}
- cast<Function>(StackChkFail.getCallee())->addFnAttr(Attribute::NoReturn);
- B.CreateCall(StackChkFail, Args);
+
B.CreateUnreachable();
return FailBB;
}