1*4ba319b5SDimitry Andric //===------- ShadowCallStack.cpp - Shadow Call Stack pass -----------------===//
2*4ba319b5SDimitry Andric //
3*4ba319b5SDimitry Andric // The LLVM Compiler Infrastructure
4*4ba319b5SDimitry Andric //
5*4ba319b5SDimitry Andric // This file is distributed under the University of Illinois Open Source
6*4ba319b5SDimitry Andric // License. See LICENSE.TXT for details.
7*4ba319b5SDimitry Andric //
8*4ba319b5SDimitry Andric //===----------------------------------------------------------------------===//
9*4ba319b5SDimitry Andric //
10*4ba319b5SDimitry Andric // The ShadowCallStack pass instruments function prologs/epilogs to check that
11*4ba319b5SDimitry Andric // the return address has not been corrupted during the execution of the
12*4ba319b5SDimitry Andric // function. The return address is stored in a 'shadow call stack' addressed
13*4ba319b5SDimitry Andric // using the %gs segment register.
14*4ba319b5SDimitry Andric //
15*4ba319b5SDimitry Andric //===----------------------------------------------------------------------===//
16*4ba319b5SDimitry Andric
17*4ba319b5SDimitry Andric #include "X86.h"
18*4ba319b5SDimitry Andric #include "X86InstrBuilder.h"
19*4ba319b5SDimitry Andric #include "X86InstrInfo.h"
20*4ba319b5SDimitry Andric #include "X86Subtarget.h"
21*4ba319b5SDimitry Andric
22*4ba319b5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
23*4ba319b5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
24*4ba319b5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
25*4ba319b5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
26*4ba319b5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
27*4ba319b5SDimitry Andric #include "llvm/CodeGen/Passes.h"
28*4ba319b5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
29*4ba319b5SDimitry Andric #include "llvm/Pass.h"
30*4ba319b5SDimitry Andric #include "llvm/Support/raw_ostream.h"
31*4ba319b5SDimitry Andric
32*4ba319b5SDimitry Andric using namespace llvm;
33*4ba319b5SDimitry Andric
34*4ba319b5SDimitry Andric namespace {
35*4ba319b5SDimitry Andric
36*4ba319b5SDimitry Andric class ShadowCallStack : public MachineFunctionPass {
37*4ba319b5SDimitry Andric public:
38*4ba319b5SDimitry Andric static char ID;
39*4ba319b5SDimitry Andric
ShadowCallStack()40*4ba319b5SDimitry Andric ShadowCallStack() : MachineFunctionPass(ID) {
41*4ba319b5SDimitry Andric initializeShadowCallStackPass(*PassRegistry::getPassRegistry());
42*4ba319b5SDimitry Andric }
43*4ba319b5SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const44*4ba319b5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
45*4ba319b5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
46*4ba319b5SDimitry Andric }
47*4ba319b5SDimitry Andric
48*4ba319b5SDimitry Andric bool runOnMachineFunction(MachineFunction &Fn) override;
49*4ba319b5SDimitry Andric
50*4ba319b5SDimitry Andric private:
51*4ba319b5SDimitry Andric // Do not instrument leaf functions with this many or fewer instructions. The
52*4ba319b5SDimitry Andric // shadow call stack instrumented prolog/epilog are slightly race-y reading
53*4ba319b5SDimitry Andric // and checking the saved return address, so it is better to not instrument
54*4ba319b5SDimitry Andric // functions that have fewer instructions than the instrumented prolog/epilog
55*4ba319b5SDimitry Andric // race.
56*4ba319b5SDimitry Andric static const size_t SkipLeafInstructions = 3;
57*4ba319b5SDimitry Andric };
58*4ba319b5SDimitry Andric
59*4ba319b5SDimitry Andric char ShadowCallStack::ID = 0;
60*4ba319b5SDimitry Andric } // end anonymous namespace.
61*4ba319b5SDimitry Andric
62*4ba319b5SDimitry Andric static void addProlog(MachineFunction &Fn, const TargetInstrInfo *TII,
63*4ba319b5SDimitry Andric MachineBasicBlock &MBB, const DebugLoc &DL);
64*4ba319b5SDimitry Andric static void addPrologLeaf(MachineFunction &Fn, const TargetInstrInfo *TII,
65*4ba319b5SDimitry Andric MachineBasicBlock &MBB, const DebugLoc &DL,
66*4ba319b5SDimitry Andric MCPhysReg FreeRegister);
67*4ba319b5SDimitry Andric
68*4ba319b5SDimitry Andric static void addEpilog(const TargetInstrInfo *TII, MachineBasicBlock &MBB,
69*4ba319b5SDimitry Andric MachineInstr &MI, MachineBasicBlock &TrapBB);
70*4ba319b5SDimitry Andric static void addEpilogLeaf(const TargetInstrInfo *TII, MachineBasicBlock &MBB,
71*4ba319b5SDimitry Andric MachineInstr &MI, MachineBasicBlock &TrapBB,
72*4ba319b5SDimitry Andric MCPhysReg FreeRegister);
73*4ba319b5SDimitry Andric // Generate a longer epilog that only uses r10 when a tailcall branches to r11.
74*4ba319b5SDimitry Andric static void addEpilogOnlyR10(const TargetInstrInfo *TII, MachineBasicBlock &MBB,
75*4ba319b5SDimitry Andric MachineInstr &MI, MachineBasicBlock &TrapBB);
76*4ba319b5SDimitry Andric
77*4ba319b5SDimitry Andric // Helper function to add ModR/M references for [Seg: Reg + Offset] memory
78*4ba319b5SDimitry Andric // accesses
79*4ba319b5SDimitry Andric static inline const MachineInstrBuilder &
addSegmentedMem(const MachineInstrBuilder & MIB,MCPhysReg Seg,MCPhysReg Reg,int Offset=0)80*4ba319b5SDimitry Andric addSegmentedMem(const MachineInstrBuilder &MIB, MCPhysReg Seg, MCPhysReg Reg,
81*4ba319b5SDimitry Andric int Offset = 0) {
82*4ba319b5SDimitry Andric return MIB.addReg(Reg).addImm(1).addReg(0).addImm(Offset).addReg(Seg);
83*4ba319b5SDimitry Andric }
84*4ba319b5SDimitry Andric
addProlog(MachineFunction & Fn,const TargetInstrInfo * TII,MachineBasicBlock & MBB,const DebugLoc & DL)85*4ba319b5SDimitry Andric static void addProlog(MachineFunction &Fn, const TargetInstrInfo *TII,
86*4ba319b5SDimitry Andric MachineBasicBlock &MBB, const DebugLoc &DL) {
87*4ba319b5SDimitry Andric const MCPhysReg ReturnReg = X86::R10;
88*4ba319b5SDimitry Andric const MCPhysReg OffsetReg = X86::R11;
89*4ba319b5SDimitry Andric
90*4ba319b5SDimitry Andric auto MBBI = MBB.begin();
91*4ba319b5SDimitry Andric // mov r10, [rsp]
92*4ba319b5SDimitry Andric addDirectMem(BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm)).addDef(ReturnReg),
93*4ba319b5SDimitry Andric X86::RSP);
94*4ba319b5SDimitry Andric // xor r11, r11
95*4ba319b5SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(X86::XOR64rr))
96*4ba319b5SDimitry Andric .addDef(OffsetReg)
97*4ba319b5SDimitry Andric .addReg(OffsetReg, RegState::Undef)
98*4ba319b5SDimitry Andric .addReg(OffsetReg, RegState::Undef);
99*4ba319b5SDimitry Andric // add QWORD [gs:r11], 8
100*4ba319b5SDimitry Andric addSegmentedMem(BuildMI(MBB, MBBI, DL, TII->get(X86::ADD64mi8)), X86::GS,
101*4ba319b5SDimitry Andric OffsetReg)
102*4ba319b5SDimitry Andric .addImm(8);
103*4ba319b5SDimitry Andric // mov r11, [gs:r11]
104*4ba319b5SDimitry Andric addSegmentedMem(
105*4ba319b5SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64rm)).addDef(OffsetReg), X86::GS,
106*4ba319b5SDimitry Andric OffsetReg);
107*4ba319b5SDimitry Andric // mov [gs:r11], r10
108*4ba319b5SDimitry Andric addSegmentedMem(BuildMI(MBB, MBBI, DL, TII->get(X86::MOV64mr)), X86::GS,
109*4ba319b5SDimitry Andric OffsetReg)
110*4ba319b5SDimitry Andric .addReg(ReturnReg);
111*4ba319b5SDimitry Andric }
112*4ba319b5SDimitry Andric
addPrologLeaf(MachineFunction & Fn,const TargetInstrInfo * TII,MachineBasicBlock & MBB,const DebugLoc & DL,MCPhysReg FreeRegister)113*4ba319b5SDimitry Andric static void addPrologLeaf(MachineFunction &Fn, const TargetInstrInfo *TII,
114*4ba319b5SDimitry Andric MachineBasicBlock &MBB, const DebugLoc &DL,
115*4ba319b5SDimitry Andric MCPhysReg FreeRegister) {
116*4ba319b5SDimitry Andric // mov REG, [rsp]
117*4ba319b5SDimitry Andric addDirectMem(BuildMI(MBB, MBB.begin(), DL, TII->get(X86::MOV64rm))
118*4ba319b5SDimitry Andric .addDef(FreeRegister),
119*4ba319b5SDimitry Andric X86::RSP);
120*4ba319b5SDimitry Andric }
121*4ba319b5SDimitry Andric
addEpilog(const TargetInstrInfo * TII,MachineBasicBlock & MBB,MachineInstr & MI,MachineBasicBlock & TrapBB)122*4ba319b5SDimitry Andric static void addEpilog(const TargetInstrInfo *TII, MachineBasicBlock &MBB,
123*4ba319b5SDimitry Andric MachineInstr &MI, MachineBasicBlock &TrapBB) {
124*4ba319b5SDimitry Andric const DebugLoc &DL = MI.getDebugLoc();
125*4ba319b5SDimitry Andric
126*4ba319b5SDimitry Andric // xor r11, r11
127*4ba319b5SDimitry Andric BuildMI(MBB, MI, DL, TII->get(X86::XOR64rr))
128*4ba319b5SDimitry Andric .addDef(X86::R11)
129*4ba319b5SDimitry Andric .addReg(X86::R11, RegState::Undef)
130*4ba319b5SDimitry Andric .addReg(X86::R11, RegState::Undef);
131*4ba319b5SDimitry Andric // mov r10, [gs:r11]
132*4ba319b5SDimitry Andric addSegmentedMem(BuildMI(MBB, MI, DL, TII->get(X86::MOV64rm)).addDef(X86::R10),
133*4ba319b5SDimitry Andric X86::GS, X86::R11);
134*4ba319b5SDimitry Andric // mov r10, [gs:r10]
135*4ba319b5SDimitry Andric addSegmentedMem(BuildMI(MBB, MI, DL, TII->get(X86::MOV64rm)).addDef(X86::R10),
136*4ba319b5SDimitry Andric X86::GS, X86::R10);
137*4ba319b5SDimitry Andric // sub QWORD [gs:r11], 8
138*4ba319b5SDimitry Andric // This instruction should not be moved up to avoid a signal race.
139*4ba319b5SDimitry Andric addSegmentedMem(BuildMI(MBB, MI, DL, TII->get(X86::SUB64mi8)),
140*4ba319b5SDimitry Andric X86::GS, X86::R11)
141*4ba319b5SDimitry Andric .addImm(8);
142*4ba319b5SDimitry Andric // cmp [rsp], r10
143*4ba319b5SDimitry Andric addDirectMem(BuildMI(MBB, MI, DL, TII->get(X86::CMP64mr)), X86::RSP)
144*4ba319b5SDimitry Andric .addReg(X86::R10);
145*4ba319b5SDimitry Andric // jne trap
146*4ba319b5SDimitry Andric BuildMI(MBB, MI, DL, TII->get(X86::JNE_1)).addMBB(&TrapBB);
147*4ba319b5SDimitry Andric MBB.addSuccessor(&TrapBB);
148*4ba319b5SDimitry Andric }
149*4ba319b5SDimitry Andric
addEpilogLeaf(const TargetInstrInfo * TII,MachineBasicBlock & MBB,MachineInstr & MI,MachineBasicBlock & TrapBB,MCPhysReg FreeRegister)150*4ba319b5SDimitry Andric static void addEpilogLeaf(const TargetInstrInfo *TII, MachineBasicBlock &MBB,
151*4ba319b5SDimitry Andric MachineInstr &MI, MachineBasicBlock &TrapBB,
152*4ba319b5SDimitry Andric MCPhysReg FreeRegister) {
153*4ba319b5SDimitry Andric const DebugLoc &DL = MI.getDebugLoc();
154*4ba319b5SDimitry Andric
155*4ba319b5SDimitry Andric // cmp [rsp], REG
156*4ba319b5SDimitry Andric addDirectMem(BuildMI(MBB, MI, DL, TII->get(X86::CMP64mr)), X86::RSP)
157*4ba319b5SDimitry Andric .addReg(FreeRegister);
158*4ba319b5SDimitry Andric // jne trap
159*4ba319b5SDimitry Andric BuildMI(MBB, MI, DL, TII->get(X86::JNE_1)).addMBB(&TrapBB);
160*4ba319b5SDimitry Andric MBB.addSuccessor(&TrapBB);
161*4ba319b5SDimitry Andric }
162*4ba319b5SDimitry Andric
addEpilogOnlyR10(const TargetInstrInfo * TII,MachineBasicBlock & MBB,MachineInstr & MI,MachineBasicBlock & TrapBB)163*4ba319b5SDimitry Andric static void addEpilogOnlyR10(const TargetInstrInfo *TII, MachineBasicBlock &MBB,
164*4ba319b5SDimitry Andric MachineInstr &MI, MachineBasicBlock &TrapBB) {
165*4ba319b5SDimitry Andric const DebugLoc &DL = MI.getDebugLoc();
166*4ba319b5SDimitry Andric
167*4ba319b5SDimitry Andric // xor r10, r10
168*4ba319b5SDimitry Andric BuildMI(MBB, MI, DL, TII->get(X86::XOR64rr))
169*4ba319b5SDimitry Andric .addDef(X86::R10)
170*4ba319b5SDimitry Andric .addReg(X86::R10, RegState::Undef)
171*4ba319b5SDimitry Andric .addReg(X86::R10, RegState::Undef);
172*4ba319b5SDimitry Andric // mov r10, [gs:r10]
173*4ba319b5SDimitry Andric addSegmentedMem(BuildMI(MBB, MI, DL, TII->get(X86::MOV64rm)).addDef(X86::R10),
174*4ba319b5SDimitry Andric X86::GS, X86::R10);
175*4ba319b5SDimitry Andric // mov r10, [gs:r10]
176*4ba319b5SDimitry Andric addSegmentedMem(BuildMI(MBB, MI, DL, TII->get(X86::MOV64rm)).addDef(X86::R10),
177*4ba319b5SDimitry Andric X86::GS, X86::R10);
178*4ba319b5SDimitry Andric // sub QWORD [gs:0], 8
179*4ba319b5SDimitry Andric // This instruction should not be moved up to avoid a signal race.
180*4ba319b5SDimitry Andric addSegmentedMem(BuildMI(MBB, MI, DL, TII->get(X86::SUB64mi8)), X86::GS, 0)
181*4ba319b5SDimitry Andric .addImm(8);
182*4ba319b5SDimitry Andric // cmp [rsp], r10
183*4ba319b5SDimitry Andric addDirectMem(BuildMI(MBB, MI, DL, TII->get(X86::CMP64mr)), X86::RSP)
184*4ba319b5SDimitry Andric .addReg(X86::R10);
185*4ba319b5SDimitry Andric // jne trap
186*4ba319b5SDimitry Andric BuildMI(MBB, MI, DL, TII->get(X86::JNE_1)).addMBB(&TrapBB);
187*4ba319b5SDimitry Andric MBB.addSuccessor(&TrapBB);
188*4ba319b5SDimitry Andric }
189*4ba319b5SDimitry Andric
runOnMachineFunction(MachineFunction & Fn)190*4ba319b5SDimitry Andric bool ShadowCallStack::runOnMachineFunction(MachineFunction &Fn) {
191*4ba319b5SDimitry Andric if (!Fn.getFunction().hasFnAttribute(Attribute::ShadowCallStack) ||
192*4ba319b5SDimitry Andric Fn.getFunction().hasFnAttribute(Attribute::Naked))
193*4ba319b5SDimitry Andric return false;
194*4ba319b5SDimitry Andric
195*4ba319b5SDimitry Andric if (Fn.empty() || !Fn.getRegInfo().tracksLiveness())
196*4ba319b5SDimitry Andric return false;
197*4ba319b5SDimitry Andric
198*4ba319b5SDimitry Andric // FIXME: Skip functions that have r10 or r11 live on entry (r10 can be live
199*4ba319b5SDimitry Andric // on entry for parameters with the nest attribute.)
200*4ba319b5SDimitry Andric if (Fn.front().isLiveIn(X86::R10) || Fn.front().isLiveIn(X86::R11))
201*4ba319b5SDimitry Andric return false;
202*4ba319b5SDimitry Andric
203*4ba319b5SDimitry Andric // FIXME: Skip functions with conditional and r10 tail calls for now.
204*4ba319b5SDimitry Andric bool HasReturn = false;
205*4ba319b5SDimitry Andric for (auto &MBB : Fn) {
206*4ba319b5SDimitry Andric if (MBB.empty())
207*4ba319b5SDimitry Andric continue;
208*4ba319b5SDimitry Andric
209*4ba319b5SDimitry Andric const MachineInstr &MI = MBB.instr_back();
210*4ba319b5SDimitry Andric if (MI.isReturn())
211*4ba319b5SDimitry Andric HasReturn = true;
212*4ba319b5SDimitry Andric
213*4ba319b5SDimitry Andric if (MI.isReturn() && MI.isCall()) {
214*4ba319b5SDimitry Andric if (MI.findRegisterUseOperand(X86::EFLAGS))
215*4ba319b5SDimitry Andric return false;
216*4ba319b5SDimitry Andric // This should only be possible on Windows 64 (see GR64_TC versus
217*4ba319b5SDimitry Andric // GR64_TCW64.)
218*4ba319b5SDimitry Andric if (MI.findRegisterUseOperand(X86::R10) ||
219*4ba319b5SDimitry Andric MI.hasRegisterImplicitUseOperand(X86::R10))
220*4ba319b5SDimitry Andric return false;
221*4ba319b5SDimitry Andric }
222*4ba319b5SDimitry Andric }
223*4ba319b5SDimitry Andric
224*4ba319b5SDimitry Andric if (!HasReturn)
225*4ba319b5SDimitry Andric return false;
226*4ba319b5SDimitry Andric
227*4ba319b5SDimitry Andric // For leaf functions:
228*4ba319b5SDimitry Andric // 1. Do not instrument very short functions where it would not improve that
229*4ba319b5SDimitry Andric // function's security.
230*4ba319b5SDimitry Andric // 2. Detect if there is an unused caller-saved register we can reserve to
231*4ba319b5SDimitry Andric // hold the return address instead of writing/reading it from the shadow
232*4ba319b5SDimitry Andric // call stack.
233*4ba319b5SDimitry Andric MCPhysReg LeafFuncRegister = X86::NoRegister;
234*4ba319b5SDimitry Andric if (!Fn.getFrameInfo().adjustsStack()) {
235*4ba319b5SDimitry Andric size_t InstructionCount = 0;
236*4ba319b5SDimitry Andric std::bitset<X86::NUM_TARGET_REGS> UsedRegs;
237*4ba319b5SDimitry Andric for (auto &MBB : Fn) {
238*4ba319b5SDimitry Andric for (auto &LiveIn : MBB.liveins())
239*4ba319b5SDimitry Andric UsedRegs.set(LiveIn.PhysReg);
240*4ba319b5SDimitry Andric for (auto &MI : MBB) {
241*4ba319b5SDimitry Andric if (!MI.isDebugValue() && !MI.isCFIInstruction() && !MI.isLabel())
242*4ba319b5SDimitry Andric InstructionCount++;
243*4ba319b5SDimitry Andric for (auto &Op : MI.operands())
244*4ba319b5SDimitry Andric if (Op.isReg() && Op.isDef())
245*4ba319b5SDimitry Andric UsedRegs.set(Op.getReg());
246*4ba319b5SDimitry Andric }
247*4ba319b5SDimitry Andric }
248*4ba319b5SDimitry Andric
249*4ba319b5SDimitry Andric if (InstructionCount <= SkipLeafInstructions)
250*4ba319b5SDimitry Andric return false;
251*4ba319b5SDimitry Andric
252*4ba319b5SDimitry Andric std::bitset<X86::NUM_TARGET_REGS> CalleeSavedRegs;
253*4ba319b5SDimitry Andric const MCPhysReg *CSRegs = Fn.getRegInfo().getCalleeSavedRegs();
254*4ba319b5SDimitry Andric for (size_t i = 0; CSRegs[i]; i++)
255*4ba319b5SDimitry Andric CalleeSavedRegs.set(CSRegs[i]);
256*4ba319b5SDimitry Andric
257*4ba319b5SDimitry Andric const TargetRegisterInfo *TRI = Fn.getSubtarget().getRegisterInfo();
258*4ba319b5SDimitry Andric for (auto &Reg : X86::GR64_NOSPRegClass.getRegisters()) {
259*4ba319b5SDimitry Andric // FIXME: Optimization opportunity: spill/restore a callee-saved register
260*4ba319b5SDimitry Andric // if a caller-saved register is unavailable.
261*4ba319b5SDimitry Andric if (CalleeSavedRegs.test(Reg))
262*4ba319b5SDimitry Andric continue;
263*4ba319b5SDimitry Andric
264*4ba319b5SDimitry Andric bool Used = false;
265*4ba319b5SDimitry Andric for (MCSubRegIterator SR(Reg, TRI, true); SR.isValid(); ++SR)
266*4ba319b5SDimitry Andric if ((Used = UsedRegs.test(*SR)))
267*4ba319b5SDimitry Andric break;
268*4ba319b5SDimitry Andric
269*4ba319b5SDimitry Andric if (!Used) {
270*4ba319b5SDimitry Andric LeafFuncRegister = Reg;
271*4ba319b5SDimitry Andric break;
272*4ba319b5SDimitry Andric }
273*4ba319b5SDimitry Andric }
274*4ba319b5SDimitry Andric }
275*4ba319b5SDimitry Andric
276*4ba319b5SDimitry Andric const bool LeafFuncOptimization = LeafFuncRegister != X86::NoRegister;
277*4ba319b5SDimitry Andric if (LeafFuncOptimization)
278*4ba319b5SDimitry Andric // Mark the leaf function register live-in for all MBBs except the entry MBB
279*4ba319b5SDimitry Andric for (auto I = ++Fn.begin(), E = Fn.end(); I != E; ++I)
280*4ba319b5SDimitry Andric I->addLiveIn(LeafFuncRegister);
281*4ba319b5SDimitry Andric
282*4ba319b5SDimitry Andric MachineBasicBlock &MBB = Fn.front();
283*4ba319b5SDimitry Andric const MachineBasicBlock *NonEmpty = MBB.empty() ? MBB.getFallThrough() : &MBB;
284*4ba319b5SDimitry Andric const DebugLoc &DL = NonEmpty->front().getDebugLoc();
285*4ba319b5SDimitry Andric
286*4ba319b5SDimitry Andric const TargetInstrInfo *TII = Fn.getSubtarget().getInstrInfo();
287*4ba319b5SDimitry Andric if (LeafFuncOptimization)
288*4ba319b5SDimitry Andric addPrologLeaf(Fn, TII, MBB, DL, LeafFuncRegister);
289*4ba319b5SDimitry Andric else
290*4ba319b5SDimitry Andric addProlog(Fn, TII, MBB, DL);
291*4ba319b5SDimitry Andric
292*4ba319b5SDimitry Andric MachineBasicBlock *Trap = nullptr;
293*4ba319b5SDimitry Andric for (auto &MBB : Fn) {
294*4ba319b5SDimitry Andric if (MBB.empty())
295*4ba319b5SDimitry Andric continue;
296*4ba319b5SDimitry Andric
297*4ba319b5SDimitry Andric MachineInstr &MI = MBB.instr_back();
298*4ba319b5SDimitry Andric if (MI.isReturn()) {
299*4ba319b5SDimitry Andric if (!Trap) {
300*4ba319b5SDimitry Andric Trap = Fn.CreateMachineBasicBlock();
301*4ba319b5SDimitry Andric BuildMI(Trap, MI.getDebugLoc(), TII->get(X86::TRAP));
302*4ba319b5SDimitry Andric Fn.push_back(Trap);
303*4ba319b5SDimitry Andric }
304*4ba319b5SDimitry Andric
305*4ba319b5SDimitry Andric if (LeafFuncOptimization)
306*4ba319b5SDimitry Andric addEpilogLeaf(TII, MBB, MI, *Trap, LeafFuncRegister);
307*4ba319b5SDimitry Andric else if (MI.findRegisterUseOperand(X86::R11))
308*4ba319b5SDimitry Andric addEpilogOnlyR10(TII, MBB, MI, *Trap);
309*4ba319b5SDimitry Andric else
310*4ba319b5SDimitry Andric addEpilog(TII, MBB, MI, *Trap);
311*4ba319b5SDimitry Andric }
312*4ba319b5SDimitry Andric }
313*4ba319b5SDimitry Andric
314*4ba319b5SDimitry Andric return true;
315*4ba319b5SDimitry Andric }
316*4ba319b5SDimitry Andric
317*4ba319b5SDimitry Andric INITIALIZE_PASS(ShadowCallStack, "shadow-call-stack", "Shadow Call Stack",
318*4ba319b5SDimitry Andric false, false)
319*4ba319b5SDimitry Andric
createShadowCallStackPass()320*4ba319b5SDimitry Andric FunctionPass *llvm::createShadowCallStackPass() {
321*4ba319b5SDimitry Andric return new ShadowCallStack();
322*4ba319b5SDimitry Andric }
323