Skip to content

Commit 22b8ba2

Browse files
author
Josh Magee
committed
[stackprotector] Use analysis from the StackProtector pass for stack layout in PEI a nd LocalStackSlot passes.
This changes the MachineFrameInfo API to use the new SSPLayoutKind information produced by the StackProtector pass (instead of a boolean flag) and updates a few pass dependencies (to preserve the SSP analysis). The stack layout follows the same approach used prior to this change - i.e., only LargeArray stack objects will be placed near the canary and everything else will be laid out normally. After this change, structures containing large arrays will also be placed near the canary - a case previously missed by the old implementation. Out of tree targets will need to update their usage of MachineFrameInfo::CreateStackObject to remove the MayNeedSP argument. The next patch will implement the rules for sspstrong and sspreq. The end goal is to support ssp-strong stack layout rules. WIP. Differential Revision: http://llvm-reviews.chandlerc.com/D2158 llvm-svn: 197653
1 parent c432799 commit 22b8ba2

18 files changed

+559
-54
lines changed

llvm/include/llvm/CodeGen/MachineFrameInfo.h

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,6 @@ class MachineFrameInfo {
101101
// cannot alias any other memory objects.
102102
bool isSpillSlot;
103103

104-
// MayNeedSP - If true the stack object triggered the creation of the stack
105-
// protector. We should allocate this object right after the stack
106-
// protector.
107-
bool MayNeedSP;
108-
109104
/// Alloca - If this stack object is originated from an Alloca instruction
110105
/// this value saves the original IR allocation. Can be NULL.
111106
const AllocaInst *Alloca;
@@ -115,9 +110,9 @@ class MachineFrameInfo {
115110
bool PreAllocated;
116111

117112
StackObject(uint64_t Sz, unsigned Al, int64_t SP, bool IM,
118-
bool isSS, bool NSP, const AllocaInst *Val)
113+
bool isSS, const AllocaInst *Val)
119114
: SPOffset(SP), Size(Sz), Alignment(Al), isImmutable(IM),
120-
isSpillSlot(isSS), MayNeedSP(NSP), Alloca(Val), PreAllocated(false) {}
115+
isSpillSlot(isSS), Alloca(Val), PreAllocated(false) {}
121116
};
122117

123118
const TargetMachine &TM;
@@ -406,14 +401,6 @@ class MachineFrameInfo {
406401
return Objects[ObjectIdx+NumFixedObjects].Alloca;
407402
}
408403

409-
/// NeedsStackProtector - Returns true if the object may need stack
410-
/// protectors.
411-
bool MayNeedStackProtector(int ObjectIdx) const {
412-
assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
413-
"Invalid Object Idx!");
414-
return Objects[ObjectIdx+NumFixedObjects].MayNeedSP;
415-
}
416-
417404
/// getObjectOffset - Return the assigned stack offset of the specified object
418405
/// from the incoming stack pointer.
419406
///
@@ -531,7 +518,7 @@ class MachineFrameInfo {
531518
/// a nonnegative identifier to represent it.
532519
///
533520
int CreateStackObject(uint64_t Size, unsigned Alignment, bool isSS,
534-
bool MayNeedSP = false, const AllocaInst *Alloca = 0);
521+
const AllocaInst *Alloca = 0);
535522

536523
/// CreateSpillStackObject - Create a new statically sized stack object that
537524
/// represents a spill slot, returning a nonnegative identifier to represent
@@ -551,7 +538,7 @@ class MachineFrameInfo {
551538
/// variable sized object is created, whether or not the index returned is
552539
/// actually used.
553540
///
554-
int CreateVariableSizedObject(unsigned Alignment);
541+
int CreateVariableSizedObject(unsigned Alignment, const AllocaInst *Alloca);
555542

556543
/// getCalleeSavedInfo - Returns a reference to call saved info vector for the
557544
/// current function.

llvm/include/llvm/CodeGen/StackProtector.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020
#include "llvm/ADT/SmallPtrSet.h"
2121
#include "llvm/ADT/Triple.h"
2222
#include "llvm/ADT/ValueMap.h"
23+
#include "llvm/Analysis/Dominators.h"
2324
#include "llvm/Pass.h"
2425
#include "llvm/Target/TargetLowering.h"
2526

2627
namespace llvm {
27-
class DominatorTree;
2828
class Function;
2929
class Module;
3030
class PHINode;

llvm/lib/CodeGen/LocalStackSlotAllocation.cpp

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@
1717
#define DEBUG_TYPE "localstackalloc"
1818
#include "llvm/CodeGen/Passes.h"
1919
#include "llvm/ADT/STLExtras.h"
20+
#include "llvm/ADT/SetVector.h"
2021
#include "llvm/ADT/SmallSet.h"
2122
#include "llvm/ADT/Statistic.h"
2223
#include "llvm/CodeGen/MachineFrameInfo.h"
2324
#include "llvm/CodeGen/MachineFunction.h"
2425
#include "llvm/CodeGen/MachineFunctionPass.h"
2526
#include "llvm/CodeGen/MachineRegisterInfo.h"
27+
#include "llvm/CodeGen/StackProtector.h"
2628
#include "llvm/IR/Constants.h"
2729
#include "llvm/IR/DerivedTypes.h"
2830
#include "llvm/IR/Instructions.h"
@@ -60,18 +62,27 @@ namespace {
6062

6163
class LocalStackSlotPass: public MachineFunctionPass {
6264
SmallVector<int64_t,16> LocalOffsets;
65+
/// StackObjSet - A set of stack object indexes
66+
typedef SmallSetVector<int, 8> StackObjSet;
6367

6468
void AdjustStackOffset(MachineFrameInfo *MFI, int FrameIdx, int64_t &Offset,
6569
bool StackGrowsDown, unsigned &MaxAlign);
70+
void AssignProtectedObjSet(const StackObjSet &UnassignedObjs,
71+
SmallSet<int, 16> &ProtectedObjs,
72+
MachineFrameInfo *MFI, bool StackGrowsDown,
73+
int64_t &Offset, unsigned &MaxAlign);
6674
void calculateFrameObjectOffsets(MachineFunction &Fn);
6775
bool insertFrameReferenceRegisters(MachineFunction &Fn);
6876
public:
6977
static char ID; // Pass identification, replacement for typeid
70-
explicit LocalStackSlotPass() : MachineFunctionPass(ID) { }
78+
explicit LocalStackSlotPass() : MachineFunctionPass(ID) {
79+
initializeLocalStackSlotPassPass(*PassRegistry::getPassRegistry());
80+
}
7181
bool runOnMachineFunction(MachineFunction &MF);
7282

7383
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
7484
AU.setPreservesCFG();
85+
AU.addRequired<StackProtector>();
7586
MachineFunctionPass::getAnalysisUsage(AU);
7687
}
7788

@@ -81,8 +92,12 @@ namespace {
8192

8293
char LocalStackSlotPass::ID = 0;
8394
char &llvm::LocalStackSlotAllocationID = LocalStackSlotPass::ID;
84-
INITIALIZE_PASS(LocalStackSlotPass, "localstackalloc",
85-
"Local Stack Slot Allocation", false, false)
95+
INITIALIZE_PASS_BEGIN(LocalStackSlotPass, "localstackalloc",
96+
"Local Stack Slot Allocation", false, false)
97+
INITIALIZE_PASS_DEPENDENCY(StackProtector)
98+
INITIALIZE_PASS_END(LocalStackSlotPass, "localstackalloc",
99+
"Local Stack Slot Allocation", false, false)
100+
86101

87102
bool LocalStackSlotPass::runOnMachineFunction(MachineFunction &MF) {
88103
MachineFrameInfo *MFI = MF.getFrameInfo();
@@ -145,6 +160,22 @@ void LocalStackSlotPass::AdjustStackOffset(MachineFrameInfo *MFI,
145160
++NumAllocations;
146161
}
147162

163+
/// AssignProtectedObjSet - Helper function to assign large stack objects (i.e.,
164+
/// those required to be close to the Stack Protector) to stack offsets.
165+
void LocalStackSlotPass::AssignProtectedObjSet(const StackObjSet &UnassignedObjs,
166+
SmallSet<int, 16> &ProtectedObjs,
167+
MachineFrameInfo *MFI,
168+
bool StackGrowsDown, int64_t &Offset,
169+
unsigned &MaxAlign) {
170+
171+
for (StackObjSet::const_iterator I = UnassignedObjs.begin(),
172+
E = UnassignedObjs.end(); I != E; ++I) {
173+
int i = *I;
174+
AdjustStackOffset(MFI, i, Offset, StackGrowsDown, MaxAlign);
175+
ProtectedObjs.insert(i);
176+
}
177+
}
178+
148179
/// calculateFrameObjectOffsets - Calculate actual frame offsets for all of the
149180
/// abstract stack objects.
150181
///
@@ -156,11 +187,13 @@ void LocalStackSlotPass::calculateFrameObjectOffsets(MachineFunction &Fn) {
156187
TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown;
157188
int64_t Offset = 0;
158189
unsigned MaxAlign = 0;
190+
StackProtector *SP = &getAnalysis<StackProtector>();
159191

160192
// Make sure that the stack protector comes before the local variables on the
161193
// stack.
162-
SmallSet<int, 16> LargeStackObjs;
194+
SmallSet<int, 16> ProtectedObjs;
163195
if (MFI->getStackProtectorIndex() >= 0) {
196+
StackObjSet LargeArrayObjs;
164197
AdjustStackOffset(MFI, MFI->getStackProtectorIndex(), Offset,
165198
StackGrowsDown, MaxAlign);
166199

@@ -170,12 +203,21 @@ void LocalStackSlotPass::calculateFrameObjectOffsets(MachineFunction &Fn) {
170203
continue;
171204
if (MFI->getStackProtectorIndex() == (int)i)
172205
continue;
173-
if (!MFI->MayNeedStackProtector(i))
174-
continue;
175206

176-
AdjustStackOffset(MFI, i, Offset, StackGrowsDown, MaxAlign);
177-
LargeStackObjs.insert(i);
207+
switch (SP->getSSPLayout(MFI->getObjectAllocation(i))) {
208+
case StackProtector::SSPLK_None:
209+
case StackProtector::SSPLK_SmallArray:
210+
case StackProtector::SSPLK_AddrOf:
211+
continue;
212+
case StackProtector::SSPLK_LargeArray:
213+
LargeArrayObjs.insert(i);
214+
continue;
215+
}
216+
llvm_unreachable("Unexpected SSPLayoutKind.");
178217
}
218+
219+
AssignProtectedObjSet(LargeArrayObjs, ProtectedObjs, MFI, StackGrowsDown,
220+
Offset, MaxAlign);
179221
}
180222

181223
// Then assign frame offsets to stack objects that are not used to spill
@@ -185,7 +227,7 @@ void LocalStackSlotPass::calculateFrameObjectOffsets(MachineFunction &Fn) {
185227
continue;
186228
if (MFI->getStackProtectorIndex() == (int)i)
187229
continue;
188-
if (LargeStackObjs.count(i))
230+
if (ProtectedObjs.count(i))
189231
continue;
190232

191233
AdjustStackOffset(MFI, i, Offset, StackGrowsDown, MaxAlign);

llvm/lib/CodeGen/MachineFunction.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -499,14 +499,13 @@ static inline unsigned clampStackAlignment(bool ShouldClamp, unsigned Align,
499499
/// a nonnegative identifier to represent it.
500500
///
501501
int MachineFrameInfo::CreateStackObject(uint64_t Size, unsigned Alignment,
502-
bool isSS, bool MayNeedSP, const AllocaInst *Alloca) {
502+
bool isSS, const AllocaInst *Alloca) {
503503
assert(Size != 0 && "Cannot allocate zero size stack objects!");
504504
Alignment =
505505
clampStackAlignment(!getFrameLowering()->isStackRealignable() ||
506506
!RealignOption,
507507
Alignment, getFrameLowering()->getStackAlignment());
508-
Objects.push_back(StackObject(Size, Alignment, 0, false, isSS, MayNeedSP,
509-
Alloca));
508+
Objects.push_back(StackObject(Size, Alignment, 0, false, isSS, Alloca));
510509
int Index = (int)Objects.size() - NumFixedObjects - 1;
511510
assert(Index >= 0 && "Bad frame index!");
512511
ensureMaxAlignment(Alignment);
@@ -523,7 +522,7 @@ int MachineFrameInfo::CreateSpillStackObject(uint64_t Size,
523522
clampStackAlignment(!getFrameLowering()->isStackRealignable() ||
524523
!RealignOption,
525524
Alignment, getFrameLowering()->getStackAlignment());
526-
CreateStackObject(Size, Alignment, true, false);
525+
CreateStackObject(Size, Alignment, true);
527526
int Index = (int)Objects.size() - NumFixedObjects - 1;
528527
ensureMaxAlignment(Alignment);
529528
return Index;
@@ -534,13 +533,14 @@ int MachineFrameInfo::CreateSpillStackObject(uint64_t Size,
534533
/// variable sized object is created, whether or not the index returned is
535534
/// actually used.
536535
///
537-
int MachineFrameInfo::CreateVariableSizedObject(unsigned Alignment) {
536+
int MachineFrameInfo::CreateVariableSizedObject(unsigned Alignment,
537+
const AllocaInst *Alloca) {
538538
HasVarSizedObjects = true;
539539
Alignment =
540540
clampStackAlignment(!getFrameLowering()->isStackRealignable() ||
541541
!RealignOption,
542542
Alignment, getFrameLowering()->getStackAlignment());
543-
Objects.push_back(StackObject(0, Alignment, 0, false, false, true, 0));
543+
Objects.push_back(StackObject(0, Alignment, 0, false, false, Alloca));
544544
ensureMaxAlignment(Alignment);
545545
return (int)Objects.size()-NumFixedObjects-1;
546546
}
@@ -565,7 +565,6 @@ int MachineFrameInfo::CreateFixedObject(uint64_t Size, int64_t SPOffset,
565565
Align, getFrameLowering()->getStackAlignment());
566566
Objects.insert(Objects.begin(), StackObject(Size, Align, SPOffset, Immutable,
567567
/*isSS*/ false,
568-
/*NeedSP*/ false,
569568
/*Alloca*/ 0));
570569
return -++NumFixedObjects;
571570
}

llvm/lib/CodeGen/MachineFunctionPass.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ void MachineFunctionPass::getAnalysisUsage(AnalysisUsage &AU) const {
5151
AU.addPreserved("domfrontier");
5252
AU.addPreserved("loops");
5353
AU.addPreserved("lda");
54+
AU.addPreserved("stack-protector");
5455

5556
FunctionPass::getAnalysisUsage(AU);
5657
}

llvm/lib/CodeGen/Passes.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -427,10 +427,10 @@ void TargetPassConfig::addCodeGenPrepare() {
427427
/// Add common passes that perform LLVM IR to IR transforms in preparation for
428428
/// instruction selection.
429429
void TargetPassConfig::addISelPrepare() {
430-
addPass(createStackProtectorPass(TM));
431-
432430
addPreISel();
433431

432+
addPass(createStackProtectorPass(TM));
433+
434434
if (PrintISelInput)
435435
addPass(createPrintFunctionPass("\n\n"
436436
"*** Final LLVM Code input to ISel ***\n",

llvm/lib/CodeGen/PrologEpilogInserter.cpp

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "PrologEpilogInserter.h"
2121
#include "llvm/ADT/IndexedMap.h"
2222
#include "llvm/ADT/STLExtras.h"
23+
#include "llvm/ADT/SetVector.h"
2324
#include "llvm/ADT/SmallSet.h"
2425
#include "llvm/ADT/Statistic.h"
2526
#include "llvm/CodeGen/MachineDominators.h"
@@ -30,6 +31,7 @@
3031
#include "llvm/CodeGen/MachineRegisterInfo.h"
3132
#include "llvm/CodeGen/RegisterScavenging.h"
3233
#include "llvm/IR/DiagnosticInfo.h"
34+
#include "llvm/CodeGen/StackProtector.h"
3335
#include "llvm/IR/InlineAsm.h"
3436
#include "llvm/IR/LLVMContext.h"
3537
#include "llvm/Support/CommandLine.h"
@@ -56,6 +58,7 @@ INITIALIZE_PASS_BEGIN(PEI, "prologepilog",
5658
"Prologue/Epilogue Insertion", false, false)
5759
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
5860
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
61+
INITIALIZE_PASS_DEPENDENCY(StackProtector)
5962
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
6063
INITIALIZE_PASS_END(PEI, "prologepilog",
6164
"Prologue/Epilogue Insertion & Frame Finalization",
@@ -69,6 +72,7 @@ void PEI::getAnalysisUsage(AnalysisUsage &AU) const {
6972
AU.setPreservesCFG();
7073
AU.addPreserved<MachineLoopInfo>();
7174
AU.addPreserved<MachineDominatorTree>();
75+
AU.addRequired<StackProtector>();
7276
AU.addRequired<TargetPassConfig>();
7377
MachineFunctionPass::getAnalysisUsage(AU);
7478
}
@@ -97,6 +101,9 @@ void PEI::calculateSets(MachineFunction &Fn) {
97101
return;
98102
}
99103

104+
/// StackObjSet - A set of stack object indexes
105+
typedef SmallSetVector<int, 8> StackObjSet;
106+
100107
/// runOnMachineFunction - Insert prolog/epilog code and replace abstract
101108
/// frame indexes with appropriate references.
102109
///
@@ -412,11 +419,28 @@ AdjustStackOffset(MachineFrameInfo *MFI, int FrameIdx,
412419
}
413420
}
414421

422+
/// AssignProtectedObjSet - Helper function to assign large stack objects (i.e.,
423+
/// those required to be close to the Stack Protector) to stack offsets.
424+
static void
425+
AssignProtectedObjSet(const StackObjSet &UnassignedObjs,
426+
SmallSet<int, 16> &ProtectedObjs,
427+
MachineFrameInfo *MFI, bool StackGrowsDown,
428+
int64_t &Offset, unsigned &MaxAlign) {
429+
430+
for (StackObjSet::const_iterator I = UnassignedObjs.begin(),
431+
E = UnassignedObjs.end(); I != E; ++I) {
432+
int i = *I;
433+
AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign);
434+
ProtectedObjs.insert(i);
435+
}
436+
}
437+
415438
/// calculateFrameObjectOffsets - Calculate actual frame offsets for all of the
416439
/// abstract stack objects.
417440
///
418441
void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
419442
const TargetFrameLowering &TFI = *Fn.getTarget().getFrameLowering();
443+
StackProtector *SP = &getAnalysis<StackProtector>();
420444

421445
bool StackGrowsDown =
422446
TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown;
@@ -526,8 +550,9 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
526550

527551
// Make sure that the stack protector comes before the local variables on the
528552
// stack.
529-
SmallSet<int, 16> LargeStackObjs;
553+
SmallSet<int, 16> ProtectedObjs;
530554
if (MFI->getStackProtectorIndex() >= 0) {
555+
StackObjSet LargeArrayObjs;
531556
AdjustStackOffset(MFI, MFI->getStackProtectorIndex(), StackGrowsDown,
532557
Offset, MaxAlign);
533558

@@ -544,12 +569,21 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
544569
continue;
545570
if (MFI->getStackProtectorIndex() == (int)i)
546571
continue;
547-
if (!MFI->MayNeedStackProtector(i))
548-
continue;
549572

550-
AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign);
551-
LargeStackObjs.insert(i);
573+
switch (SP->getSSPLayout(MFI->getObjectAllocation(i))) {
574+
case StackProtector::SSPLK_None:
575+
case StackProtector::SSPLK_SmallArray:
576+
case StackProtector::SSPLK_AddrOf:
577+
continue;
578+
case StackProtector::SSPLK_LargeArray:
579+
LargeArrayObjs.insert(i);
580+
continue;
581+
}
582+
llvm_unreachable("Unexpected SSPLayoutKind.");
552583
}
584+
585+
AssignProtectedObjSet(LargeArrayObjs, ProtectedObjs, MFI, StackGrowsDown,
586+
Offset, MaxAlign);
553587
}
554588

555589
// Then assign frame offsets to stack objects that are not used to spill
@@ -566,7 +600,7 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
566600
continue;
567601
if (MFI->getStackProtectorIndex() == (int)i)
568602
continue;
569-
if (LargeStackObjs.count(i))
603+
if (ProtectedObjs.count(i))
570604
continue;
571605

572606
AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign);

0 commit comments

Comments
 (0)