Index: include/llvm/CodeGen/MachineFrameInfo.h =================================================================== --- include/llvm/CodeGen/MachineFrameInfo.h +++ include/llvm/CodeGen/MachineFrameInfo.h @@ -87,7 +87,21 @@ /// /// @brief Abstract Stack Frame Information class MachineFrameInfo { +public: + /// SSPLayoutKind. Stack Smashing Protection (SSP) rules require that + /// vulnerable stack allocations are located close the stack protector. + enum SSPLayoutKind { + SSPLK_None, ///< Did not trigger a stack protector. No effect on data + ///< layout. + SSPLK_LargeArray, ///< Array or nested array >= SSP-buffer-size. Closest + ///< to the stack protector. + SSPLK_SmallArray, ///< Array or nested array < SSP-buffer-size. 2nd closest + ///< to the stack protector. + SSPLK_AddrOf ///< The address of this allocation is exposed and + ///< triggered protection. 3rd closest to the protector. + }; +private: // Represent a single object allocated on the stack. struct StackObject { // The offset of this object from the stack pointer on entry to @@ -145,12 +159,15 @@ /// If true, the object has been zero-extended. bool isSExt; + MachineFrameInfo::SSPLayoutKind SSPLayout; + StackObject(uint64_t Sz, unsigned Al, int64_t SP, bool IM, bool isSS, const AllocaInst *Val, bool Aliased, uint8_t ID = 0) : SPOffset(SP), Size(Sz), Alignment(Al), isImmutable(IM), isSpillSlot(isSS), isStatepointSpillSlot(false), StackID(ID), Alloca(Val), - PreAllocated(false), isAliased(Aliased), isZExt(false), isSExt(false) {} + PreAllocated(false), isAliased(Aliased), isZExt(false), isSExt(false), + SSPLayout(SSPLK_None) {} }; /// The alignment of the stack. @@ -485,6 +502,20 @@ Objects[ObjectIdx+NumFixedObjects].SPOffset = SPOffset; } + SSPLayoutKind getObjectSSPLayout(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].SSPLayout; + } + + void setObjectSSPLayout(int ObjectIdx, SSPLayoutKind Kind) { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + assert(!isDeadObjectIndex(ObjectIdx) && + "Setting SSP layou for a dead object?"); + Objects[ObjectIdx+NumFixedObjects].SSPLayout = Kind; + } + /// Return the number of bytes that must be allocated to hold /// all of the fixed size frame objects. This is only valid after /// Prolog/Epilog code insertion has finalized the stack frame layout. Index: include/llvm/CodeGen/StackProtector.h =================================================================== --- include/llvm/CodeGen/StackProtector.h +++ include/llvm/CodeGen/StackProtector.h @@ -50,7 +50,7 @@ }; /// A mapping of AllocaInsts to their required SSP layout. - using SSPLayoutMap = ValueMap; + using SSPLayoutMap = DenseMap; private: const TargetMachine *TM = nullptr; Index: lib/CodeGen/LocalStackSlotAllocation.cpp =================================================================== --- lib/CodeGen/LocalStackSlotAllocation.cpp +++ lib/CodeGen/LocalStackSlotAllocation.cpp @@ -99,7 +99,6 @@ void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesCFG(); - AU.addRequired(); MachineFunctionPass::getAnalysisUsage(AU); } }; @@ -109,12 +108,8 @@ char LocalStackSlotPass::ID = 0; char &llvm::LocalStackSlotAllocationID = LocalStackSlotPass::ID; - -INITIALIZE_PASS_BEGIN(LocalStackSlotPass, DEBUG_TYPE, - "Local Stack Slot Allocation", false, false) -INITIALIZE_PASS_DEPENDENCY(StackProtector) -INITIALIZE_PASS_END(LocalStackSlotPass, DEBUG_TYPE, - "Local Stack Slot Allocation", false, false) +INITIALIZE_PASS(LocalStackSlotPass, DEBUG_TYPE, + "Local Stack Slot Allocation", false, false) bool LocalStackSlotPass::runOnMachineFunction(MachineFunction &MF) { MachineFrameInfo &MFI = MF.getFrameInfo(); @@ -202,7 +197,6 @@ TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown; int64_t Offset = 0; unsigned MaxAlign = 0; - StackProtector *SP = &getAnalysis(); // Make sure that the stack protector comes before the local variables on the // stack. @@ -222,16 +216,16 @@ if (MFI.getStackProtectorIndex() == (int)i) continue; - switch (SP->getSSPLayout(MFI.getObjectAllocation(i))) { - case StackProtector::SSPLK_None: + switch (MFI.getObjectSSPLayout(i)) { + case MachineFrameInfo::SSPLK_None: continue; - case StackProtector::SSPLK_SmallArray: + case MachineFrameInfo::SSPLK_SmallArray: SmallArrayObjs.insert(i); continue; - case StackProtector::SSPLK_AddrOf: + case MachineFrameInfo::SSPLK_AddrOf: AddrOfObjs.insert(i); continue; - case StackProtector::SSPLK_LargeArray: + case MachineFrameInfo::SSPLK_LargeArray: LargeArrayObjs.insert(i); continue; } Index: lib/CodeGen/PrologEpilogInserter.cpp =================================================================== --- lib/CodeGen/PrologEpilogInserter.cpp +++ lib/CodeGen/PrologEpilogInserter.cpp @@ -38,7 +38,6 @@ #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" -#include "llvm/CodeGen/StackProtector.h" #include "llvm/CodeGen/WinEHFuncInfo.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/CallingConv.h" @@ -148,7 +147,6 @@ false) INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) -INITIALIZE_PASS_DEPENDENCY(StackProtector) INITIALIZE_PASS_DEPENDENCY(MachineOptimizationRemarkEmitterPass) INITIALIZE_PASS_END(PEI, DEBUG_TYPE, "Prologue/Epilogue Insertion & Frame Finalization", false, @@ -165,7 +163,6 @@ AU.setPreservesCFG(); AU.addPreserved(); AU.addPreserved(); - AU.addRequired(); AU.addRequired(); MachineFunctionPass::getAnalysisUsage(AU); } @@ -697,7 +694,6 @@ /// abstract stack objects. void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering(); - StackProtector *SP = &getAnalysis(); bool StackGrowsDown = TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown; @@ -846,16 +842,16 @@ EHRegNodeFrameIndex == (int)i) continue; - switch (SP->getSSPLayout(MFI.getObjectAllocation(i))) { - case StackProtector::SSPLK_None: + switch (MFI.getObjectSSPLayout(i)) { + case MachineFrameInfo::SSPLK_None: continue; - case StackProtector::SSPLK_SmallArray: + case MachineFrameInfo::SSPLK_SmallArray: SmallArrayObjs.insert(i); continue; - case StackProtector::SSPLK_AddrOf: + case MachineFrameInfo::SSPLK_AddrOf: AddrOfObjs.insert(i); continue; - case StackProtector::SSPLK_LargeArray: + case MachineFrameInfo::SSPLK_LargeArray: LargeArrayObjs.insert(i); continue; } Index: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -1358,6 +1358,28 @@ } } +static void intializeStackProtectorMap(StackProtector &SP, MachineFrameInfo &MFI) { + for (int i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) { + if (MFI.isDeadObjectIndex(i)) + continue; + + switch (SP.getSSPLayout(MFI.getObjectAllocation(i))) { + case StackProtector::SSPLK_None: + continue; + case StackProtector::SSPLK_SmallArray: + MFI.setObjectSSPLayout(i, MachineFrameInfo::SSPLK_SmallArray); + continue; + case StackProtector::SSPLK_AddrOf: + MFI.setObjectSSPLayout(i, MachineFrameInfo::SSPLK_AddrOf); + continue; + case StackProtector::SSPLK_LargeArray: + MFI.setObjectSSPLayout(i, MachineFrameInfo::SSPLK_LargeArray); + continue; + } + llvm_unreachable("Unexpected SSPLayoutKind."); + } +} + void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { FastISelFailed = false; // Initialize the Fast-ISel state, if needed. @@ -1586,11 +1608,14 @@ FastIS->recomputeInsertPt(); } - if (getAnalysis().shouldEmitSDCheck(*LLVMBB)) { + StackProtector &SP = getAnalysis(); + if (SP.shouldEmitSDCheck(*LLVMBB)) { bool FunctionBasedInstrumentation = TLI->getSSPStackGuardCheck(*Fn.getParent()); SDB->SPDescriptor.initialize(LLVMBB, FuncInfo->MBBMap[LLVMBB], FunctionBasedInstrumentation); + + intializeStackProtectorMap(SP, MF->getFrameInfo()); } if (Begin != BI) Index: lib/CodeGen/StackColoring.cpp =================================================================== --- lib/CodeGen/StackColoring.cpp +++ lib/CodeGen/StackColoring.cpp @@ -39,7 +39,6 @@ #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/SlotIndexes.h" -#include "llvm/CodeGen/StackProtector.h" #include "llvm/CodeGen/WinEHFuncInfo.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DebugInfoMetadata.h" @@ -422,9 +421,6 @@ /// SlotIndex analysis object. SlotIndexes *Indexes; - /// The stack protector object. - StackProtector *SP; - /// The list of lifetime markers found. These markers are to be removed /// once the coloring is done. SmallVector Markers; @@ -523,13 +519,11 @@ INITIALIZE_PASS_BEGIN(StackColoring, DEBUG_TYPE, "Merge disjoint stack slots", false, false) INITIALIZE_PASS_DEPENDENCY(SlotIndexes) -INITIALIZE_PASS_DEPENDENCY(StackProtector) INITIALIZE_PASS_END(StackColoring, DEBUG_TYPE, "Merge disjoint stack slots", false, false) void StackColoring::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); - AU.addRequired(); MachineFunctionPass::getAnalysisUsage(AU); } @@ -930,9 +924,12 @@ MergedAllocas.insert(From); MergedAllocas.insert(To); - // Allow the stack protector to adjust its value map to account for the - // upcoming replacement. - SP->adjustForColoring(From, To); + // Transfer the stack protector layout tag, but make sure that SSPLK_AddrOf + // does not overwrite SSPLK_SmallArray or SSPLK_LargeArray, and make sure + // that SSPLK_SmallArray does not overwrite SSPLK_LargeArray. + if (MFI->getObjectSSPLayout(SI.second) != MachineFrameInfo::SSPLK_LargeArray && + MFI->getObjectSSPLayout(SI.first) != MachineFrameInfo::SSPLK_AddrOf) + MFI->setObjectSSPLayout(SI.second, MFI->getObjectSSPLayout(SI.first)); // The new alloca might not be valid in a llvm.dbg.declare for this // variable, so undef out the use to make the verifier happy. @@ -1134,7 +1131,6 @@ MF = &Func; MFI = &MF->getFrameInfo(); Indexes = &getAnalysis(); - SP = &getAnalysis(); BlockLiveness.clear(); BasicBlocks.clear(); BasicBlockNumbering.clear();