1
- // ======- X86RetpolineThunks .cpp - Construct retpoline thunks for x86 --==== =//
1
+ // ==- X86IndirectThunks .cpp - Construct indirect call/jump thunks for x86 --=//
2
2
//
3
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
4
// See https://llvm.org/LICENSE.txt for license information.
7
7
// ===----------------------------------------------------------------------===//
8
8
// / \file
9
9
// /
10
- // / Pass that injects an MI thunk implementing a "retpoline". This is
11
- // / a RET-implemented trampoline that is used to lower indirect calls in a way
10
+ // / Pass that injects an MI thunk that is used to lower indirect calls in a way
12
11
// / that prevents speculation on some x86 processors and can be used to mitigate
13
12
// / security vulnerabilities due to targeted speculative execution and side
14
13
// / channels such as CVE-2017-5715.
15
14
// /
15
+ // / Currently supported thunks include:
16
+ // / - Retpoline -- A RET-implemented trampoline that lowers indirect calls
17
+ // /
18
+ // / Note that the reason that this is implemented as a MachineFunctionPass and
19
+ // / not a ModulePass is that ModulePasses at this point in the LLVM X86 pipeline
20
+ // / serialize all transformations, which can consume lots of memory.
21
+ // /
16
22
// / TODO(chandlerc): All of this code could use better comments and
17
23
// / documentation.
18
24
// /
@@ -37,21 +43,21 @@ using namespace llvm;
37
43
38
44
#define DEBUG_TYPE " x86-retpoline-thunks"
39
45
40
- static const char ThunkNamePrefix [] = " __llvm_retpoline_" ;
41
- static const char R11ThunkName [] = " __llvm_retpoline_r11" ;
42
- static const char EAXThunkName [] = " __llvm_retpoline_eax" ;
43
- static const char ECXThunkName [] = " __llvm_retpoline_ecx" ;
44
- static const char EDXThunkName [] = " __llvm_retpoline_edx" ;
45
- static const char EDIThunkName [] = " __llvm_retpoline_edi" ;
46
+ static const char RetpolineNamePrefix [] = " __llvm_retpoline_" ;
47
+ static const char R11RetpolineName [] = " __llvm_retpoline_r11" ;
48
+ static const char EAXRetpolineName [] = " __llvm_retpoline_eax" ;
49
+ static const char ECXRetpolineName [] = " __llvm_retpoline_ecx" ;
50
+ static const char EDXRetpolineName [] = " __llvm_retpoline_edx" ;
51
+ static const char EDIRetpolineName [] = " __llvm_retpoline_edi" ;
46
52
47
53
namespace {
48
- class X86RetpolineThunks : public MachineFunctionPass {
54
+ class X86IndirectThunks : public MachineFunctionPass {
49
55
public:
50
56
static char ID;
51
57
52
- X86RetpolineThunks () : MachineFunctionPass(ID) {}
58
+ X86IndirectThunks () : MachineFunctionPass(ID) {}
53
59
54
- StringRef getPassName () const override { return " X86 Retpoline Thunks" ; }
60
+ StringRef getPassName () const override { return " X86 Indirect Thunks" ; }
55
61
56
62
bool doInitialization (Module &M) override ;
57
63
bool runOnMachineFunction (MachineFunction &F) override ;
@@ -72,24 +78,24 @@ class X86RetpolineThunks : public MachineFunctionPass {
72
78
bool InsertedThunks = false ;
73
79
74
80
void createThunkFunction (Module &M, StringRef Name);
75
- void insertRegReturnAddrClobber (MachineBasicBlock &MBB, unsigned Reg);
76
- void populateThunk (MachineFunction &MF, unsigned Reg);
81
+ void insertRegReturnAddrClobber (MachineBasicBlock &MBB, Register Reg);
82
+ void populateThunk (MachineFunction &MF, Register Reg);
77
83
};
78
84
79
85
} // end anonymous namespace
80
86
81
- FunctionPass *llvm::createX86RetpolineThunksPass () {
82
- return new X86RetpolineThunks ();
87
+ FunctionPass *llvm::createX86IndirectThunksPass () {
88
+ return new X86IndirectThunks ();
83
89
}
84
90
85
- char X86RetpolineThunks ::ID = 0 ;
91
+ char X86IndirectThunks ::ID = 0 ;
86
92
87
- bool X86RetpolineThunks ::doInitialization (Module &M) {
93
+ bool X86IndirectThunks ::doInitialization (Module &M) {
88
94
InsertedThunks = false ;
89
95
return false ;
90
96
}
91
97
92
- bool X86RetpolineThunks ::runOnMachineFunction (MachineFunction &MF) {
98
+ bool X86IndirectThunks ::runOnMachineFunction (MachineFunction &MF) {
93
99
LLVM_DEBUG (dbgs () << getPassName () << ' \n ' );
94
100
95
101
TM = &MF.getTarget ();;
@@ -102,7 +108,7 @@ bool X86RetpolineThunks::runOnMachineFunction(MachineFunction &MF) {
102
108
103
109
// If this function is not a thunk, check to see if we need to insert
104
110
// a thunk.
105
- if (!MF.getName ().startswith (ThunkNamePrefix )) {
111
+ if (!MF.getName ().startswith (RetpolineNamePrefix )) {
106
112
// If we've already inserted a thunk, nothing else to do.
107
113
if (InsertedThunks)
108
114
return false ;
@@ -124,10 +130,11 @@ bool X86RetpolineThunks::runOnMachineFunction(MachineFunction &MF) {
124
130
// pass. We extract the module and insert a new function (and machine
125
131
// function) directly into the module.
126
132
if (Is64Bit)
127
- createThunkFunction (M, R11ThunkName );
133
+ createThunkFunction (M, R11RetpolineName );
128
134
else
129
135
for (StringRef Name :
130
- {EAXThunkName, ECXThunkName, EDXThunkName, EDIThunkName})
136
+ {EAXRetpolineName, ECXRetpolineName, EDXRetpolineName,
137
+ EDIRetpolineName})
131
138
createThunkFunction (M, Name);
132
139
InsertedThunks = true ;
133
140
return true ;
@@ -177,13 +184,13 @@ bool X86RetpolineThunks::runOnMachineFunction(MachineFunction &MF) {
177
184
// ... # Same setup
178
185
// movl %edi, (%esp)
179
186
// retl
180
- if (MF.getName () == EAXThunkName )
187
+ if (MF.getName () == EAXRetpolineName )
181
188
populateThunk (MF, X86::EAX);
182
- else if (MF.getName () == ECXThunkName )
189
+ else if (MF.getName () == ECXRetpolineName )
183
190
populateThunk (MF, X86::ECX);
184
- else if (MF.getName () == EDXThunkName )
191
+ else if (MF.getName () == EDXRetpolineName )
185
192
populateThunk (MF, X86::EDX);
186
- else if (MF.getName () == EDIThunkName )
193
+ else if (MF.getName () == EDIRetpolineName )
187
194
populateThunk (MF, X86::EDI);
188
195
else
189
196
llvm_unreachable (" Invalid thunk name on x86-32!" );
@@ -192,8 +199,8 @@ bool X86RetpolineThunks::runOnMachineFunction(MachineFunction &MF) {
192
199
return true ;
193
200
}
194
201
195
- void X86RetpolineThunks ::createThunkFunction (Module &M, StringRef Name) {
196
- assert (Name.startswith (ThunkNamePrefix ) &&
202
+ void X86IndirectThunks ::createThunkFunction (Module &M, StringRef Name) {
203
+ assert (Name.startswith (RetpolineNamePrefix ) &&
197
204
" Created a thunk with an unexpected prefix!" );
198
205
199
206
LLVMContext &Ctx = M.getContext ();
@@ -226,16 +233,16 @@ void X86RetpolineThunks::createThunkFunction(Module &M, StringRef Name) {
226
233
MF.insert (MF.end (), EntryMBB);
227
234
}
228
235
229
- void X86RetpolineThunks ::insertRegReturnAddrClobber (MachineBasicBlock &MBB,
230
- unsigned Reg) {
236
+ void X86IndirectThunks ::insertRegReturnAddrClobber (MachineBasicBlock &MBB,
237
+ Register Reg) {
231
238
const unsigned MovOpc = Is64Bit ? X86::MOV64mr : X86::MOV32mr;
232
- const unsigned SPReg = Is64Bit ? X86::RSP : X86::ESP;
239
+ const Register SPReg = Is64Bit ? X86::RSP : X86::ESP;
233
240
addRegOffset (BuildMI (&MBB, DebugLoc (), TII->get (MovOpc)), SPReg, false , 0 )
234
241
.addReg (Reg);
235
242
}
236
243
237
- void X86RetpolineThunks ::populateThunk (MachineFunction &MF,
238
- unsigned Reg) {
244
+ void X86IndirectThunks ::populateThunk (MachineFunction &MF,
245
+ Register Reg) {
239
246
// Set MF properties. We never use vregs...
240
247
MF.getProperties ().set (MachineFunctionProperties::Property::NoVRegs);
241
248
@@ -246,8 +253,10 @@ void X86RetpolineThunks::populateThunk(MachineFunction &MF,
246
253
while (MF.size () > 1 )
247
254
MF.erase (std::next (MF.begin ()));
248
255
249
- MachineBasicBlock *CaptureSpec = MF.CreateMachineBasicBlock (Entry->getBasicBlock ());
250
- MachineBasicBlock *CallTarget = MF.CreateMachineBasicBlock (Entry->getBasicBlock ());
256
+ MachineBasicBlock *CaptureSpec =
257
+ MF.CreateMachineBasicBlock (Entry->getBasicBlock ());
258
+ MachineBasicBlock *CallTarget =
259
+ MF.CreateMachineBasicBlock (Entry->getBasicBlock ());
251
260
MCSymbol *TargetSym = MF.getContext ().createTempSymbol ();
252
261
MF.push_back (CaptureSpec);
253
262
MF.push_back (CallTarget);
0 commit comments