1 //===------- ShadowCallStack.cpp - Shadow Call Stack pass -----------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // The ShadowCallStack pass instruments function prologs/epilogs to check that
10 // the return address has not been corrupted during the execution of the
11 // function. The return address is stored in a 'shadow call stack' addressed
12 // using the %gs segment register.
14 //===----------------------------------------------------------------------===//
17 #include "X86InstrBuilder.h"
18 #include "X86InstrInfo.h"
19 #include "X86Subtarget.h"
21 #include "llvm/CodeGen/MachineFunction.h"
22 #include "llvm/CodeGen/MachineFunctionPass.h"
23 #include "llvm/CodeGen/MachineInstrBuilder.h"
24 #include "llvm/CodeGen/MachineModuleInfo.h"
25 #include "llvm/CodeGen/MachineRegisterInfo.h"
26 #include "llvm/CodeGen/Passes.h"
27 #include "llvm/CodeGen/TargetInstrInfo.h"
28 #include "llvm/Pass.h"
29 #include "llvm/Support/raw_ostream.h"
35 class ShadowCallStack
: public MachineFunctionPass
{
39 ShadowCallStack() : MachineFunctionPass(ID
) {
40 initializeShadowCallStackPass(*PassRegistry::getPassRegistry());
43 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
44 MachineFunctionPass::getAnalysisUsage(AU
);
47 bool runOnMachineFunction(MachineFunction
&Fn
) override
;
50 // Do not instrument leaf functions with this many or fewer instructions. The
51 // shadow call stack instrumented prolog/epilog are slightly race-y reading
52 // and checking the saved return address, so it is better to not instrument
53 // functions that have fewer instructions than the instrumented prolog/epilog
55 static const size_t SkipLeafInstructions
= 3;
58 char ShadowCallStack::ID
= 0;
59 } // end anonymous namespace.
61 static void addProlog(MachineFunction
&Fn
, const TargetInstrInfo
*TII
,
62 MachineBasicBlock
&MBB
, const DebugLoc
&DL
);
63 static void addPrologLeaf(MachineFunction
&Fn
, const TargetInstrInfo
*TII
,
64 MachineBasicBlock
&MBB
, const DebugLoc
&DL
,
65 MCPhysReg FreeRegister
);
67 static void addEpilog(const TargetInstrInfo
*TII
, MachineBasicBlock
&MBB
,
68 MachineInstr
&MI
, MachineBasicBlock
&TrapBB
);
69 static void addEpilogLeaf(const TargetInstrInfo
*TII
, MachineBasicBlock
&MBB
,
70 MachineInstr
&MI
, MachineBasicBlock
&TrapBB
,
71 MCPhysReg FreeRegister
);
72 // Generate a longer epilog that only uses r10 when a tailcall branches to r11.
73 static void addEpilogOnlyR10(const TargetInstrInfo
*TII
, MachineBasicBlock
&MBB
,
74 MachineInstr
&MI
, MachineBasicBlock
&TrapBB
);
76 // Helper function to add ModR/M references for [Seg: Reg + Offset] memory
78 static inline const MachineInstrBuilder
&
79 addSegmentedMem(const MachineInstrBuilder
&MIB
, MCPhysReg Seg
, MCPhysReg Reg
,
81 return MIB
.addReg(Reg
).addImm(1).addReg(0).addImm(Offset
).addReg(Seg
);
84 static void addProlog(MachineFunction
&Fn
, const TargetInstrInfo
*TII
,
85 MachineBasicBlock
&MBB
, const DebugLoc
&DL
) {
86 const MCPhysReg ReturnReg
= X86::R10
;
87 const MCPhysReg OffsetReg
= X86::R11
;
89 auto MBBI
= MBB
.begin();
91 addDirectMem(BuildMI(MBB
, MBBI
, DL
, TII
->get(X86::MOV64rm
)).addDef(ReturnReg
),
94 BuildMI(MBB
, MBBI
, DL
, TII
->get(X86::XOR64rr
))
96 .addReg(OffsetReg
, RegState::Undef
)
97 .addReg(OffsetReg
, RegState::Undef
);
98 // add QWORD [gs:r11], 8
99 addSegmentedMem(BuildMI(MBB
, MBBI
, DL
, TII
->get(X86::ADD64mi8
)), X86::GS
,
104 BuildMI(MBB
, MBBI
, DL
, TII
->get(X86::MOV64rm
)).addDef(OffsetReg
), X86::GS
,
107 addSegmentedMem(BuildMI(MBB
, MBBI
, DL
, TII
->get(X86::MOV64mr
)), X86::GS
,
112 static void addPrologLeaf(MachineFunction
&Fn
, const TargetInstrInfo
*TII
,
113 MachineBasicBlock
&MBB
, const DebugLoc
&DL
,
114 MCPhysReg FreeRegister
) {
116 addDirectMem(BuildMI(MBB
, MBB
.begin(), DL
, TII
->get(X86::MOV64rm
))
117 .addDef(FreeRegister
),
121 static void addEpilog(const TargetInstrInfo
*TII
, MachineBasicBlock
&MBB
,
122 MachineInstr
&MI
, MachineBasicBlock
&TrapBB
) {
123 const DebugLoc
&DL
= MI
.getDebugLoc();
126 BuildMI(MBB
, MI
, DL
, TII
->get(X86::XOR64rr
))
128 .addReg(X86::R11
, RegState::Undef
)
129 .addReg(X86::R11
, RegState::Undef
);
131 addSegmentedMem(BuildMI(MBB
, MI
, DL
, TII
->get(X86::MOV64rm
)).addDef(X86::R10
),
134 addSegmentedMem(BuildMI(MBB
, MI
, DL
, TII
->get(X86::MOV64rm
)).addDef(X86::R10
),
136 // sub QWORD [gs:r11], 8
137 // This instruction should not be moved up to avoid a signal race.
138 addSegmentedMem(BuildMI(MBB
, MI
, DL
, TII
->get(X86::SUB64mi8
)),
142 addDirectMem(BuildMI(MBB
, MI
, DL
, TII
->get(X86::CMP64mr
)), X86::RSP
)
145 BuildMI(MBB
, MI
, DL
, TII
->get(X86::JNE_1
)).addMBB(&TrapBB
);
146 MBB
.addSuccessor(&TrapBB
);
149 static void addEpilogLeaf(const TargetInstrInfo
*TII
, MachineBasicBlock
&MBB
,
150 MachineInstr
&MI
, MachineBasicBlock
&TrapBB
,
151 MCPhysReg FreeRegister
) {
152 const DebugLoc
&DL
= MI
.getDebugLoc();
155 addDirectMem(BuildMI(MBB
, MI
, DL
, TII
->get(X86::CMP64mr
)), X86::RSP
)
156 .addReg(FreeRegister
);
158 BuildMI(MBB
, MI
, DL
, TII
->get(X86::JNE_1
)).addMBB(&TrapBB
);
159 MBB
.addSuccessor(&TrapBB
);
162 static void addEpilogOnlyR10(const TargetInstrInfo
*TII
, MachineBasicBlock
&MBB
,
163 MachineInstr
&MI
, MachineBasicBlock
&TrapBB
) {
164 const DebugLoc
&DL
= MI
.getDebugLoc();
167 BuildMI(MBB
, MI
, DL
, TII
->get(X86::XOR64rr
))
169 .addReg(X86::R10
, RegState::Undef
)
170 .addReg(X86::R10
, RegState::Undef
);
172 addSegmentedMem(BuildMI(MBB
, MI
, DL
, TII
->get(X86::MOV64rm
)).addDef(X86::R10
),
175 addSegmentedMem(BuildMI(MBB
, MI
, DL
, TII
->get(X86::MOV64rm
)).addDef(X86::R10
),
177 // sub QWORD [gs:0], 8
178 // This instruction should not be moved up to avoid a signal race.
179 addSegmentedMem(BuildMI(MBB
, MI
, DL
, TII
->get(X86::SUB64mi8
)), X86::GS
, 0)
182 addDirectMem(BuildMI(MBB
, MI
, DL
, TII
->get(X86::CMP64mr
)), X86::RSP
)
185 BuildMI(MBB
, MI
, DL
, TII
->get(X86::JNE_1
)).addMBB(&TrapBB
);
186 MBB
.addSuccessor(&TrapBB
);
189 bool ShadowCallStack::runOnMachineFunction(MachineFunction
&Fn
) {
190 if (!Fn
.getFunction().hasFnAttribute(Attribute::ShadowCallStack
) ||
191 Fn
.getFunction().hasFnAttribute(Attribute::Naked
))
194 if (Fn
.empty() || !Fn
.getRegInfo().tracksLiveness())
197 // FIXME: Skip functions that have r10 or r11 live on entry (r10 can be live
198 // on entry for parameters with the nest attribute.)
199 if (Fn
.front().isLiveIn(X86::R10
) || Fn
.front().isLiveIn(X86::R11
))
202 // FIXME: Skip functions with conditional and r10 tail calls for now.
203 bool HasReturn
= false;
204 for (auto &MBB
: Fn
) {
208 const MachineInstr
&MI
= MBB
.instr_back();
212 if (MI
.isReturn() && MI
.isCall()) {
213 if (MI
.findRegisterUseOperand(X86::EFLAGS
))
215 // This should only be possible on Windows 64 (see GR64_TC versus
217 if (MI
.findRegisterUseOperand(X86::R10
) ||
218 MI
.hasRegisterImplicitUseOperand(X86::R10
))
226 // For leaf functions:
227 // 1. Do not instrument very short functions where it would not improve that
228 // function's security.
229 // 2. Detect if there is an unused caller-saved register we can reserve to
230 // hold the return address instead of writing/reading it from the shadow
232 MCPhysReg LeafFuncRegister
= X86::NoRegister
;
233 if (!Fn
.getFrameInfo().adjustsStack()) {
234 size_t InstructionCount
= 0;
235 std::bitset
<X86::NUM_TARGET_REGS
> UsedRegs
;
236 for (auto &MBB
: Fn
) {
237 for (auto &LiveIn
: MBB
.liveins())
238 UsedRegs
.set(LiveIn
.PhysReg
);
239 for (auto &MI
: MBB
) {
240 if (!MI
.isDebugValue() && !MI
.isCFIInstruction() && !MI
.isLabel())
242 for (auto &Op
: MI
.operands())
243 if (Op
.isReg() && Op
.isDef())
244 UsedRegs
.set(Op
.getReg());
248 if (InstructionCount
<= SkipLeafInstructions
)
251 std::bitset
<X86::NUM_TARGET_REGS
> CalleeSavedRegs
;
252 const MCPhysReg
*CSRegs
= Fn
.getRegInfo().getCalleeSavedRegs();
253 for (size_t i
= 0; CSRegs
[i
]; i
++)
254 CalleeSavedRegs
.set(CSRegs
[i
]);
256 const TargetRegisterInfo
*TRI
= Fn
.getSubtarget().getRegisterInfo();
257 for (auto &Reg
: X86::GR64_NOSPRegClass
.getRegisters()) {
258 // FIXME: Optimization opportunity: spill/restore a callee-saved register
259 // if a caller-saved register is unavailable.
260 if (CalleeSavedRegs
.test(Reg
))
264 for (MCSubRegIterator
SR(Reg
, TRI
, true); SR
.isValid(); ++SR
)
265 if ((Used
= UsedRegs
.test(*SR
)))
269 LeafFuncRegister
= Reg
;
275 const bool LeafFuncOptimization
= LeafFuncRegister
!= X86::NoRegister
;
276 if (LeafFuncOptimization
)
277 // Mark the leaf function register live-in for all MBBs except the entry MBB
278 for (auto I
= ++Fn
.begin(), E
= Fn
.end(); I
!= E
; ++I
)
279 I
->addLiveIn(LeafFuncRegister
);
281 MachineBasicBlock
&MBB
= Fn
.front();
282 const MachineBasicBlock
*NonEmpty
= MBB
.empty() ? MBB
.getFallThrough() : &MBB
;
283 const DebugLoc
&DL
= NonEmpty
->front().getDebugLoc();
285 const TargetInstrInfo
*TII
= Fn
.getSubtarget().getInstrInfo();
286 if (LeafFuncOptimization
)
287 addPrologLeaf(Fn
, TII
, MBB
, DL
, LeafFuncRegister
);
289 addProlog(Fn
, TII
, MBB
, DL
);
291 MachineBasicBlock
*Trap
= nullptr;
292 for (auto &MBB
: Fn
) {
296 MachineInstr
&MI
= MBB
.instr_back();
299 Trap
= Fn
.CreateMachineBasicBlock();
300 BuildMI(Trap
, MI
.getDebugLoc(), TII
->get(X86::TRAP
));
304 if (LeafFuncOptimization
)
305 addEpilogLeaf(TII
, MBB
, MI
, *Trap
, LeafFuncRegister
);
306 else if (MI
.findRegisterUseOperand(X86::R11
))
307 addEpilogOnlyR10(TII
, MBB
, MI
, *Trap
);
309 addEpilog(TII
, MBB
, MI
, *Trap
);
316 INITIALIZE_PASS(ShadowCallStack
, "shadow-call-stack", "Shadow Call Stack",
319 FunctionPass
*llvm::createShadowCallStackPass() {
320 return new ShadowCallStack();