summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/CodeGen/StackProtector.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/CodeGen/StackProtector.cpp')
-rw-r--r--contrib/llvm/lib/CodeGen/StackProtector.cpp204
1 files changed, 91 insertions, 113 deletions
diff --git a/contrib/llvm/lib/CodeGen/StackProtector.cpp b/contrib/llvm/lib/CodeGen/StackProtector.cpp
index db3fef5..89868e4 100644
--- a/contrib/llvm/lib/CodeGen/StackProtector.cpp
+++ b/contrib/llvm/lib/CodeGen/StackProtector.cpp
@@ -18,12 +18,13 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
+#include "llvm/Analysis/EHPersonalities.h"
#include "llvm/Analysis/ValueTracking.h"
-#include "llvm/CodeGen/Analysis.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
@@ -89,15 +90,25 @@ bool StackProtector::runOnFunction(Function &Fn) {
getAnalysisIfAvailable<DominatorTreeWrapperPass>();
DT = DTWP ? &DTWP->getDomTree() : nullptr;
TLI = TM->getSubtargetImpl(Fn)->getTargetLowering();
+ HasPrologue = false;
+ HasIRCheck = false;
Attribute Attr = Fn.getFnAttribute("stack-protector-buffer-size");
if (Attr.isStringAttribute() &&
Attr.getValueAsString().getAsInteger(10, SSPBufferSize))
- return false; // Invalid integer string
+ return false; // Invalid integer string
if (!RequiresStackProtector())
return false;
+ // TODO(etienneb): Functions with funclets are not correctly supported now.
+ // Do nothing if this is funclet-based personality.
+ if (Fn.hasPersonalityFn()) {
+ EHPersonality Personality = classifyEHPersonality(Fn.getPersonalityFn());
+ if (isFuncletEHPersonality(Personality))
+ return false;
+ }
+
++NumFunProtected;
return InsertStackProtectors();
}
@@ -200,11 +211,24 @@ bool StackProtector::HasAddressTaken(const Instruction *AI) {
bool StackProtector::RequiresStackProtector() {
bool Strong = false;
bool NeedsProtector = false;
+ for (const BasicBlock &BB : *F)
+ for (const Instruction &I : BB)
+ if (const CallInst *CI = dyn_cast<CallInst>(&I))
+ if (CI->getCalledFunction() ==
+ Intrinsic::getDeclaration(F->getParent(),
+ Intrinsic::stackprotector))
+ HasPrologue = true;
+
+ if (F->hasFnAttribute(Attribute::SafeStack))
+ return false;
+
if (F->hasFnAttribute(Attribute::StackProtectReq)) {
NeedsProtector = true;
Strong = true; // Use the same heuristic as strong to determine SSPLayout
} else if (F->hasFnAttribute(Attribute::StackProtectStrong))
Strong = true;
+ else if (HasPrologue)
+ NeedsProtector = true;
else if (!F->hasFnAttribute(Attribute::StackProtect))
return false;
@@ -256,106 +280,51 @@ bool StackProtector::RequiresStackProtector() {
return NeedsProtector;
}
-static bool InstructionWillNotHaveChain(const Instruction *I) {
- return !I->mayHaveSideEffects() && !I->mayReadFromMemory() &&
- isSafeToSpeculativelyExecute(I);
-}
-
-/// Identify if RI has a previous instruction in the "Tail Position" and return
-/// it. Otherwise return 0.
-///
-/// This is based off of the code in llvm::isInTailCallPosition. The difference
-/// is that it inverts the first part of llvm::isInTailCallPosition since
-/// isInTailCallPosition is checking if a call is in a tail call position, and
-/// we are searching for an unknown tail call that might be in the tail call
-/// position. Once we find the call though, the code uses the same refactored
-/// code, returnTypeIsEligibleForTailCall.
-static CallInst *FindPotentialTailCall(BasicBlock *BB, ReturnInst *RI,
- const TargetLoweringBase *TLI) {
- // Establish a reasonable upper bound on the maximum amount of instructions we
- // will look through to find a tail call.
- unsigned SearchCounter = 0;
- const unsigned MaxSearch = 4;
- bool NoInterposingChain = true;
-
- for (BasicBlock::reverse_iterator I = std::next(BB->rbegin()), E = BB->rend();
- I != E && SearchCounter < MaxSearch; ++I) {
- Instruction *Inst = &*I;
-
- // Skip over debug intrinsics and do not allow them to affect our MaxSearch
- // counter.
- if (isa<DbgInfoIntrinsic>(Inst))
- continue;
-
- // If we find a call and the following conditions are satisifed, then we
- // have found a tail call that satisfies at least the target independent
- // requirements of a tail call:
- //
- // 1. The call site has the tail marker.
- //
- // 2. The call site either will not cause the creation of a chain or if a
- // chain is necessary there are no instructions in between the callsite and
- // the call which would create an interposing chain.
- //
- // 3. The return type of the function does not impede tail call
- // optimization.
- if (CallInst *CI = dyn_cast<CallInst>(Inst)) {
- if (CI->isTailCall() &&
- (InstructionWillNotHaveChain(CI) || NoInterposingChain) &&
- returnTypeIsEligibleForTailCall(BB->getParent(), CI, RI, *TLI))
- return CI;
- }
-
- // If we did not find a call see if we have an instruction that may create
- // an interposing chain.
- NoInterposingChain =
- NoInterposingChain && InstructionWillNotHaveChain(Inst);
-
- // Increment max search.
- SearchCounter++;
- }
-
- return nullptr;
+/// Create a stack guard loading and populate whether SelectionDAG SSP is
+/// supported.
+static Value *getStackGuard(const TargetLoweringBase *TLI, Module *M,
+ IRBuilder<> &B,
+ bool *SupportsSelectionDAGSP = nullptr) {
+ if (Value *Guard = TLI->getIRStackGuard(B))
+ return B.CreateLoad(Guard, true, "StackGuard");
+
+ // Use SelectionDAG SSP handling, since there isn't an IR guard.
+ //
+ // This is more or less weird, since we optionally output whether we
+ // should perform a SelectionDAG SP here. The reason is that it's strictly
+ // defined as !TLI->getIRStackGuard(B), where getIRStackGuard is also
+ // mutating. There is no way to get this bit without mutating the IR, so
+ // getting this bit has to happen in this right time.
+ //
+ // We could have define a new function TLI::supportsSelectionDAGSP(), but that
+ // will put more burden on the backends' overriding work, especially when it
+ // actually conveys the same information getIRStackGuard() already gives.
+ if (SupportsSelectionDAGSP)
+ *SupportsSelectionDAGSP = true;
+ TLI->insertSSPDeclarations(*M);
+ return B.CreateCall(Intrinsic::getDeclaration(M, Intrinsic::stackguard));
}
-/// Insert code into the entry block that stores the __stack_chk_guard
+/// Insert code into the entry block that stores the stack guard
/// variable onto the stack:
///
/// entry:
/// StackGuardSlot = alloca i8*
-/// StackGuard = load __stack_chk_guard
-/// call void @llvm.stackprotect.create(StackGuard, StackGuardSlot)
+/// StackGuard = <stack guard>
+/// call void @llvm.stackprotector(StackGuard, StackGuardSlot)
///
/// Returns true if the platform/triple supports the stackprotectorcreate pseudo
/// node.
static bool CreatePrologue(Function *F, Module *M, ReturnInst *RI,
- const TargetLoweringBase *TLI, const Triple &TT,
- AllocaInst *&AI, Value *&StackGuardVar) {
+ const TargetLoweringBase *TLI, AllocaInst *&AI) {
bool SupportsSelectionDAGSP = false;
- PointerType *PtrTy = Type::getInt8PtrTy(RI->getContext());
- unsigned AddressSpace, Offset;
- if (TLI->getStackCookieLocation(AddressSpace, Offset)) {
- Constant *OffsetVal =
- ConstantInt::get(Type::getInt32Ty(RI->getContext()), Offset);
-
- StackGuardVar =
- ConstantExpr::getIntToPtr(OffsetVal, PointerType::get(PtrTy,
- AddressSpace));
- } else if (TT.isOSOpenBSD()) {
- StackGuardVar = M->getOrInsertGlobal("__guard_local", PtrTy);
- cast<GlobalValue>(StackGuardVar)
- ->setVisibility(GlobalValue::HiddenVisibility);
- } else {
- SupportsSelectionDAGSP = true;
- StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard", PtrTy);
- }
-
IRBuilder<> B(&F->getEntryBlock().front());
+ PointerType *PtrTy = Type::getInt8PtrTy(RI->getContext());
AI = B.CreateAlloca(PtrTy, nullptr, "StackGuardSlot");
- LoadInst *LI = B.CreateLoad(StackGuardVar, "StackGuard");
- B.CreateCall(Intrinsic::getDeclaration(M, Intrinsic::stackprotector),
- {LI, AI});
+ Value *GuardSlot = getStackGuard(TLI, M, B, &SupportsSelectionDAGSP);
+ B.CreateCall(Intrinsic::getDeclaration(M, Intrinsic::stackprotector),
+ {GuardSlot, AI});
return SupportsSelectionDAGSP;
}
@@ -366,11 +335,9 @@ static bool CreatePrologue(Function *F, Module *M, ReturnInst *RI,
/// - The epilogue checks the value stored in the prologue against the original
/// value. It calls __stack_chk_fail if they differ.
bool StackProtector::InsertStackProtectors() {
- bool HasPrologue = false;
bool SupportsSelectionDAGSP =
EnableSelectionDAGSP && !TM->Options.EnableFastISel;
AllocaInst *AI = nullptr; // Place on stack that stores the stack guard.
- Value *StackGuardVar = nullptr; // The stack guard variable.
for (Function::iterator I = F->begin(), E = F->end(); I != E;) {
BasicBlock *BB = &*I++;
@@ -378,30 +345,36 @@ bool StackProtector::InsertStackProtectors() {
if (!RI)
continue;
+ // Generate prologue instrumentation if not already generated.
if (!HasPrologue) {
HasPrologue = true;
- SupportsSelectionDAGSP &=
- CreatePrologue(F, M, RI, TLI, Trip, AI, StackGuardVar);
+ SupportsSelectionDAGSP &= CreatePrologue(F, M, RI, TLI, AI);
}
- if (SupportsSelectionDAGSP) {
- // Since we have a potential tail call, insert the special stack check
- // intrinsic.
- Instruction *InsertionPt = nullptr;
- if (CallInst *CI = FindPotentialTailCall(BB, RI, TLI)) {
- InsertionPt = CI;
- } else {
- InsertionPt = RI;
- // At this point we know that BB has a return statement so it *DOES*
- // have a terminator.
- assert(InsertionPt != nullptr &&
- "BB must have a terminator instruction at this point.");
- }
-
- Function *Intrinsic =
- Intrinsic::getDeclaration(M, Intrinsic::stackprotectorcheck);
- CallInst::Create(Intrinsic, StackGuardVar, "", InsertionPt);
+ // SelectionDAG based code generation. Nothing else needs to be done here.
+ // The epilogue instrumentation is postponed to SelectionDAG.
+ if (SupportsSelectionDAGSP)
+ break;
+
+ // Set HasIRCheck to true, so that SelectionDAG will not generate its own
+ // version. SelectionDAG called 'shouldEmitSDCheck' to check whether
+ // instrumentation has already been generated.
+ HasIRCheck = true;
+
+ // Generate epilogue instrumentation. The epilogue intrumentation can be
+ // function-based or inlined depending on which mechanism the target is
+ // providing.
+ if (Value* GuardCheck = TLI->getSSPStackGuardCheck(*M)) {
+ // Generate the function-based epilogue instrumentation.
+ // The target provides a guard check function, generate a call to it.
+ IRBuilder<> B(RI);
+ LoadInst *Guard = B.CreateLoad(AI, true, "Guard");
+ CallInst *Call = B.CreateCall(GuardCheck, {Guard});
+ llvm::Function *Function = cast<llvm::Function>(GuardCheck);
+ Call->setAttributes(Function->getAttributes());
+ Call->setCallingConv(Function->getCallingConv());
} else {
+ // Generate the epilogue with inline instrumentation.
// If we do not support SelectionDAG based tail calls, generate IR level
// tail calls.
//
@@ -415,7 +388,7 @@ bool StackProtector::InsertStackProtectors() {
//
// return:
// ...
- // %1 = load __stack_chk_guard
+ // %1 = <stack guard>
// %2 = load StackGuardSlot
// %3 = cmp i1 %1, %2
// br i1 %3, label %SP_return, label %CallStackCheckFailBlk
@@ -450,9 +423,9 @@ bool StackProtector::InsertStackProtectors() {
// Generate the stack protector instructions in the old basic block.
IRBuilder<> B(BB);
- LoadInst *LI1 = B.CreateLoad(StackGuardVar);
- LoadInst *LI2 = B.CreateLoad(AI);
- Value *Cmp = B.CreateICmpEQ(LI1, LI2);
+ Value *Guard = getStackGuard(TLI, M, B);
+ LoadInst *LI2 = B.CreateLoad(AI, true);
+ Value *Cmp = B.CreateICmpEQ(Guard, LI2);
auto SuccessProb =
BranchProbabilityInfo::getBranchProbStackProtector(true);
auto FailureProb =
@@ -475,6 +448,7 @@ BasicBlock *StackProtector::CreateFailBB() {
LLVMContext &Context = F->getContext();
BasicBlock *FailBB = BasicBlock::Create(Context, "CallStackCheckFailBlk", F);
IRBuilder<> B(FailBB);
+ B.SetCurrentDebugLocation(DebugLoc::get(0, 0, F->getSubprogram()));
if (Trip.isOSOpenBSD()) {
Constant *StackChkFail =
M->getOrInsertFunction("__stack_smash_handler",
@@ -491,3 +465,7 @@ BasicBlock *StackProtector::CreateFailBB() {
B.CreateUnreachable();
return FailBB;
}
+
+bool StackProtector::shouldEmitSDCheck(const BasicBlock &BB) const {
+ return HasPrologue && !HasIRCheck && dyn_cast<ReturnInst>(BB.getTerminator());
+}
OpenPOWER on IntegriCloud