13
13
14
14
#include " AArch64InstrInfo.h"
15
15
#include " AArch64Subtarget.h"
16
- #include " Utils/AArch64BaseInfo.h"
17
16
#include " llvm/CodeGen/IndirectThunks.h"
18
17
#include " llvm/CodeGen/MachineBasicBlock.h"
19
18
#include " llvm/CodeGen/MachineFunction.h"
20
- #include " llvm/CodeGen/MachineFunctionPass.h"
21
19
#include " llvm/CodeGen/MachineInstr.h"
22
20
#include " llvm/CodeGen/MachineInstrBuilder.h"
23
21
#include " llvm/CodeGen/MachineOperand.h"
24
- #include " llvm/CodeGen/MachineRegisterInfo.h"
25
22
#include " llvm/CodeGen/RegisterScavenging.h"
26
23
#include " llvm/IR/DebugLoc.h"
27
24
#include " llvm/Pass.h"
28
- #include " llvm/Support/CodeGen.h"
29
- #include " llvm/Support/Debug.h"
25
+ #include " llvm/Support/ErrorHandling.h"
30
26
#include " llvm/Target/TargetMachine.h"
31
27
#include < cassert>
32
28
@@ -36,38 +32,42 @@ using namespace llvm;
36
32
37
33
#define AARCH64_SLS_HARDENING_NAME " AArch64 sls hardening pass"
38
34
35
+ static const char SLSBLRNamePrefix[] = " __llvm_slsblr_thunk_" ;
36
+
39
37
namespace {
40
38
41
- class AArch64SLSHardening : public MachineFunctionPass {
42
- public:
43
- const TargetInstrInfo *TII;
44
- const TargetRegisterInfo *TRI;
45
- const AArch64Subtarget *ST;
39
+ // Set of inserted thunks: bitmask with bits corresponding to
40
+ // indexes in SLSBLRThunks array.
41
+ typedef uint32_t ThunksSet;
46
42
47
- static char ID;
48
-
49
- AArch64SLSHardening () : MachineFunctionPass(ID) {
50
- initializeAArch64SLSHardeningPass (*PassRegistry::getPassRegistry ());
43
+ struct SLSHardeningInserter : ThunkInserter<SLSHardeningInserter, ThunksSet> {
44
+ public:
45
+ const char *getThunkPrefix () { return SLSBLRNamePrefix; }
46
+ bool mayUseThunk (const MachineFunction &MF) {
47
+ ComdatThunks &= !MF.getSubtarget <AArch64Subtarget>().hardenSlsNoComdat ();
48
+ // We are inserting barriers aside from thunk calls, so
49
+ // check hardenSlsRetBr() as well.
50
+ return MF.getSubtarget <AArch64Subtarget>().hardenSlsBlr () ||
51
+ MF.getSubtarget <AArch64Subtarget>().hardenSlsRetBr ();
51
52
}
53
+ ThunksSet insertThunks (MachineModuleInfo &MMI, MachineFunction &MF,
54
+ ThunksSet ExistingThunks);
55
+ void populateThunk (MachineFunction &MF);
52
56
53
- bool runOnMachineFunction (MachineFunction &Fn) override ;
57
+ private:
58
+ bool ComdatThunks = true ;
54
59
55
- StringRef getPassName () const override { return AARCH64_SLS_HARDENING_NAME; }
60
+ bool hardenReturnsAndBRs (MachineModuleInfo &MMI, MachineBasicBlock &MBB);
61
+ bool hardenBLRs (MachineModuleInfo &MMI, MachineBasicBlock &MBB,
62
+ ThunksSet &Thunks);
56
63
57
- private:
58
- bool hardenReturnsAndBRs (MachineBasicBlock &MBB) const ;
59
- bool hardenBLRs (MachineBasicBlock &MBB) const ;
60
- MachineBasicBlock &ConvertBLRToBL (MachineBasicBlock &MBB,
61
- MachineBasicBlock::instr_iterator) const ;
64
+ void convertBLRToBL (MachineModuleInfo &MMI, MachineBasicBlock &MBB,
65
+ MachineBasicBlock::instr_iterator MBBI,
66
+ ThunksSet &Thunks);
62
67
};
63
68
64
69
} // end anonymous namespace
65
70
66
- char AArch64SLSHardening::ID = 0 ;
67
-
68
- INITIALIZE_PASS (AArch64SLSHardening, " aarch64-sls-hardening" ,
69
- AARCH64_SLS_HARDENING_NAME, false , false )
70
-
71
71
static void insertSpeculationBarrier (const AArch64Subtarget *ST,
72
72
MachineBasicBlock &MBB,
73
73
MachineBasicBlock::iterator MBBI,
@@ -90,18 +90,18 @@ static void insertSpeculationBarrier(const AArch64Subtarget *ST,
90
90
BuildMI (MBB, MBBI, DL, TII->get (BarrierOpc));
91
91
}
92
92
93
- bool AArch64SLSHardening::runOnMachineFunction (MachineFunction &MF) {
94
- ST = &MF. getSubtarget <AArch64Subtarget>();
95
- TII = MF. getSubtarget (). getInstrInfo ();
96
- TRI = MF.getSubtarget (). getRegisterInfo ();
93
+ ThunksSet SLSHardeningInserter::insertThunks (MachineModuleInfo &MMI,
94
+ MachineFunction &MF,
95
+ ThunksSet ExistingThunks) {
96
+ const AArch64Subtarget *ST = & MF.getSubtarget <AArch64Subtarget> ();
97
97
98
- bool Modified = false ;
99
98
for (auto &MBB : MF) {
100
- Modified |= hardenReturnsAndBRs (MBB);
101
- Modified |= hardenBLRs (MBB);
99
+ if (ST->hardenSlsRetBr ())
100
+ hardenReturnsAndBRs (MMI, MBB);
101
+ if (ST->hardenSlsBlr ())
102
+ hardenBLRs (MMI, MBB, ExistingThunks);
102
103
}
103
-
104
- return Modified;
104
+ return ExistingThunks;
105
105
}
106
106
107
107
static bool isBLR (const MachineInstr &MI) {
@@ -120,9 +120,10 @@ static bool isBLR(const MachineInstr &MI) {
120
120
return false ;
121
121
}
122
122
123
- bool AArch64SLSHardening::hardenReturnsAndBRs (MachineBasicBlock &MBB) const {
124
- if (!ST->hardenSlsRetBr ())
125
- return false ;
123
+ bool SLSHardeningInserter::hardenReturnsAndBRs (MachineModuleInfo &MMI,
124
+ MachineBasicBlock &MBB) {
125
+ const AArch64Subtarget *ST =
126
+ &MBB.getParent ()->getSubtarget <AArch64Subtarget>();
126
127
bool Modified = false ;
127
128
MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator (), E = MBB.end ();
128
129
MachineBasicBlock::iterator NextMBBI;
@@ -138,78 +139,55 @@ bool AArch64SLSHardening::hardenReturnsAndBRs(MachineBasicBlock &MBB) const {
138
139
return Modified;
139
140
}
140
141
141
- static const char SLSBLRNamePrefix[] = " __llvm_slsblr_thunk_" ;
142
-
142
+ static const unsigned NumPermittedRegs = 29 ;
143
143
static const struct ThunkNameAndReg {
144
144
const char * Name;
145
145
Register Reg;
146
- } SLSBLRThunks[] = {
147
- { " __llvm_slsblr_thunk_x0" , AArch64::X0},
148
- { " __llvm_slsblr_thunk_x1" , AArch64::X1},
149
- { " __llvm_slsblr_thunk_x2" , AArch64::X2},
150
- { " __llvm_slsblr_thunk_x3" , AArch64::X3},
151
- { " __llvm_slsblr_thunk_x4" , AArch64::X4},
152
- { " __llvm_slsblr_thunk_x5" , AArch64::X5},
153
- { " __llvm_slsblr_thunk_x6" , AArch64::X6},
154
- { " __llvm_slsblr_thunk_x7" , AArch64::X7},
155
- { " __llvm_slsblr_thunk_x8" , AArch64::X8},
156
- { " __llvm_slsblr_thunk_x9" , AArch64::X9},
157
- { " __llvm_slsblr_thunk_x10" , AArch64::X10},
158
- { " __llvm_slsblr_thunk_x11" , AArch64::X11},
159
- { " __llvm_slsblr_thunk_x12" , AArch64::X12},
160
- { " __llvm_slsblr_thunk_x13" , AArch64::X13},
161
- { " __llvm_slsblr_thunk_x14" , AArch64::X14},
162
- { " __llvm_slsblr_thunk_x15" , AArch64::X15},
163
- // X16 and X17 are deliberately missing, as the mitigation requires those
164
- // register to not be used in BLR. See comment in ConvertBLRToBL for more
165
- // details.
166
- { " __llvm_slsblr_thunk_x18" , AArch64::X18},
167
- { " __llvm_slsblr_thunk_x19" , AArch64::X19},
168
- { " __llvm_slsblr_thunk_x20" , AArch64::X20},
169
- { " __llvm_slsblr_thunk_x21" , AArch64::X21},
170
- { " __llvm_slsblr_thunk_x22" , AArch64::X22},
171
- { " __llvm_slsblr_thunk_x23" , AArch64::X23},
172
- { " __llvm_slsblr_thunk_x24" , AArch64::X24},
173
- { " __llvm_slsblr_thunk_x25" , AArch64::X25},
174
- { " __llvm_slsblr_thunk_x26" , AArch64::X26},
175
- { " __llvm_slsblr_thunk_x27" , AArch64::X27},
176
- { " __llvm_slsblr_thunk_x28" , AArch64::X28},
177
- { " __llvm_slsblr_thunk_x29" , AArch64::FP},
178
- // X30 is deliberately missing, for similar reasons as X16 and X17 are
179
- // missing.
180
- { " __llvm_slsblr_thunk_x31" , AArch64::XZR},
146
+ } SLSBLRThunks[NumPermittedRegs ] = {
147
+ { " __llvm_slsblr_thunk_x0" , AArch64::X0},
148
+ { " __llvm_slsblr_thunk_x1" , AArch64::X1},
149
+ { " __llvm_slsblr_thunk_x2" , AArch64::X2},
150
+ { " __llvm_slsblr_thunk_x3" , AArch64::X3},
151
+ { " __llvm_slsblr_thunk_x4" , AArch64::X4},
152
+ { " __llvm_slsblr_thunk_x5" , AArch64::X5},
153
+ { " __llvm_slsblr_thunk_x6" , AArch64::X6},
154
+ { " __llvm_slsblr_thunk_x7" , AArch64::X7},
155
+ { " __llvm_slsblr_thunk_x8" , AArch64::X8},
156
+ { " __llvm_slsblr_thunk_x9" , AArch64::X9},
157
+ { " __llvm_slsblr_thunk_x10" , AArch64::X10},
158
+ { " __llvm_slsblr_thunk_x11" , AArch64::X11},
159
+ { " __llvm_slsblr_thunk_x12" , AArch64::X12},
160
+ { " __llvm_slsblr_thunk_x13" , AArch64::X13},
161
+ { " __llvm_slsblr_thunk_x14" , AArch64::X14},
162
+ { " __llvm_slsblr_thunk_x15" , AArch64::X15},
163
+ // X16 and X17 are deliberately missing, as the mitigation requires those
164
+ // register to not be used in BLR. See comment in ConvertBLRToBL for more
165
+ // details.
166
+ { " __llvm_slsblr_thunk_x18" , AArch64::X18},
167
+ { " __llvm_slsblr_thunk_x19" , AArch64::X19},
168
+ { " __llvm_slsblr_thunk_x20" , AArch64::X20},
169
+ { " __llvm_slsblr_thunk_x21" , AArch64::X21},
170
+ { " __llvm_slsblr_thunk_x22" , AArch64::X22},
171
+ { " __llvm_slsblr_thunk_x23" , AArch64::X23},
172
+ { " __llvm_slsblr_thunk_x24" , AArch64::X24},
173
+ { " __llvm_slsblr_thunk_x25" , AArch64::X25},
174
+ { " __llvm_slsblr_thunk_x26" , AArch64::X26},
175
+ { " __llvm_slsblr_thunk_x27" , AArch64::X27},
176
+ { " __llvm_slsblr_thunk_x28" , AArch64::X28},
177
+ { " __llvm_slsblr_thunk_x29" , AArch64::FP},
178
+ // X30 is deliberately missing, for similar reasons as X16 and X17 are
179
+ // missing.
180
+ { " __llvm_slsblr_thunk_x31" , AArch64::XZR},
181
181
};
182
182
183
- namespace {
184
- struct SLSBLRThunkInserter : ThunkInserter<SLSBLRThunkInserter> {
185
- const char *getThunkPrefix () { return SLSBLRNamePrefix; }
186
- bool mayUseThunk (const MachineFunction &MF) {
187
- ComdatThunks &= !MF.getSubtarget <AArch64Subtarget>().hardenSlsNoComdat ();
188
- return MF.getSubtarget <AArch64Subtarget>().hardenSlsBlr ();
189
- }
190
- bool insertThunks (MachineModuleInfo &MMI, MachineFunction &MF,
191
- bool ExistingThunks);
192
- void populateThunk (MachineFunction &MF);
193
-
194
- private:
195
- bool ComdatThunks = true ;
196
- };
197
- } // namespace
198
-
199
- bool SLSBLRThunkInserter::insertThunks (MachineModuleInfo &MMI,
200
- MachineFunction &MF,
201
- bool ExistingThunks) {
202
- if (ExistingThunks)
203
- return false ;
204
- // FIXME: It probably would be possible to filter which thunks to produce
205
- // based on which registers are actually used in BLR instructions in this
206
- // function. But would that be a worthwhile optimization?
207
- for (auto T : SLSBLRThunks)
208
- createThunkFunction (MMI, T.Name , ComdatThunks);
209
- return true ;
183
+ unsigned getThunkIndex (Register Reg) {
184
+ for (unsigned I = 0 ; I < NumPermittedRegs; ++I)
185
+ if (SLSBLRThunks[I].Reg == Reg)
186
+ return I;
187
+ llvm_unreachable (" Unexpected register" );
210
188
}
211
189
212
- void SLSBLRThunkInserter ::populateThunk (MachineFunction &MF) {
190
+ void SLSHardeningInserter ::populateThunk (MachineFunction &MF) {
213
191
assert (MF.getFunction ().hasComdat () == ComdatThunks &&
214
192
" ComdatThunks value changed since MF creation" );
215
193
// FIXME: How to better communicate Register number, rather than through
@@ -258,8 +236,9 @@ void SLSBLRThunkInserter::populateThunk(MachineFunction &MF) {
258
236
Entry->end (), DebugLoc (), true /* AlwaysUseISBDSB*/ );
259
237
}
260
238
261
- MachineBasicBlock &AArch64SLSHardening::ConvertBLRToBL (
262
- MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator MBBI) const {
239
+ void SLSHardeningInserter::convertBLRToBL (
240
+ MachineModuleInfo &MMI, MachineBasicBlock &MBB,
241
+ MachineBasicBlock::instr_iterator MBBI, ThunksSet &Thunks) {
263
242
// Transform a BLR to a BL as follows:
264
243
// Before:
265
244
// |-----------------------------|
@@ -285,7 +264,6 @@ MachineBasicBlock &AArch64SLSHardening::ConvertBLRToBL(
285
264
// | barrierInsts |
286
265
// |-----------------------------|
287
266
//
288
- // The __llvm_slsblr_thunk_xN thunks are created by the SLSBLRThunkInserter.
289
267
// This function merely needs to transform BLR xN into BL
290
268
// __llvm_slsblr_thunk_xN.
291
269
//
@@ -318,37 +296,16 @@ MachineBasicBlock &AArch64SLSHardening::ConvertBLRToBL(
318
296
}
319
297
DebugLoc DL = BLR.getDebugLoc ();
320
298
321
- // If we'd like to support also BLRAA and BLRAB instructions, we'd need
322
- // a lot more different kind of thunks.
323
- // For example, a
324
- //
325
- // BLRAA xN, xM
326
- //
327
- // instruction probably would need to be transformed to something like:
328
- //
329
- // BL __llvm_slsblraa_thunk_x<N>_x<M>
330
- //
331
- // __llvm_slsblraa_thunk_x<N>_x<M>:
332
- // BRAA x<N>, x<M>
333
- // barrierInsts
334
- //
335
- // Given that about 30 different values of N are possible and about 30
336
- // different values of M are possible in the above, with the current way
337
- // of producing indirect thunks, we'd be producing about 30 times 30, i.e.
338
- // about 900 thunks (where most might not be actually called). This would
339
- // multiply further by two to support both BLRAA and BLRAB variants of those
340
- // instructions.
341
- // If we'd want to support this, we'd probably need to look into a different
342
- // way to produce thunk functions, based on which variants are actually
343
- // needed, rather than producing all possible variants.
344
- // So far, LLVM does never produce BLRA* instructions, so let's leave this
345
- // for the future when LLVM can start producing BLRA* instructions.
346
299
MachineFunction &MF = *MBBI->getMF ();
347
300
MCContext &Context = MBB.getParent ()->getContext ();
348
- auto ThunkIt =
349
- llvm::find_if (SLSBLRThunks, [Reg](auto T) { return T.Reg == Reg; });
350
- assert (ThunkIt != std::end (SLSBLRThunks));
351
- MCSymbol *Sym = Context.getOrCreateSymbol (ThunkIt->Name );
301
+ const TargetInstrInfo *TII = MF.getSubtarget ().getInstrInfo ();
302
+ unsigned ThunkIndex = getThunkIndex (Reg);
303
+ StringRef ThunkName = SLSBLRThunks[ThunkIndex].Name ;
304
+ MCSymbol *Sym = Context.getOrCreateSymbol (ThunkName);
305
+ if (!(Thunks & (1u << ThunkIndex))) {
306
+ Thunks |= 1u << ThunkIndex;
307
+ createThunkFunction (MMI, ThunkName, ComdatThunks);
308
+ }
352
309
353
310
MachineInstr *BL = BuildMI (MBB, MBBI, DL, TII->get (BLOpcode)).addSym (Sym);
354
311
@@ -386,13 +343,11 @@ MachineBasicBlock &AArch64SLSHardening::ConvertBLRToBL(
386
343
RegIsKilled /* isKill*/ ));
387
344
// Remove BLR instruction
388
345
MBB.erase (MBBI);
389
-
390
- return MBB;
391
346
}
392
347
393
- bool AArch64SLSHardening ::hardenBLRs (MachineBasicBlock &MBB) const {
394
- if (!ST-> hardenSlsBlr ())
395
- return false ;
348
+ bool SLSHardeningInserter ::hardenBLRs (MachineModuleInfo &MMI,
349
+ MachineBasicBlock &MBB,
350
+ ThunksSet &Thunks) {
396
351
bool Modified = false ;
397
352
MachineBasicBlock::instr_iterator MBBI = MBB.instr_begin (),
398
353
E = MBB.instr_end ();
@@ -401,31 +356,30 @@ bool AArch64SLSHardening::hardenBLRs(MachineBasicBlock &MBB) const {
401
356
MachineInstr &MI = *MBBI;
402
357
NextMBBI = std::next (MBBI);
403
358
if (isBLR (MI)) {
404
- ConvertBLRToBL ( MBB, MBBI);
359
+ convertBLRToBL (MMI, MBB, MBBI, Thunks );
405
360
Modified = true ;
406
361
}
407
362
}
408
363
return Modified;
409
364
}
410
365
411
- FunctionPass *llvm::createAArch64SLSHardeningPass () {
412
- return new AArch64SLSHardening ();
413
- }
414
-
415
366
namespace {
416
- class AArch64IndirectThunks : public ThunkInserterPass <SLSBLRThunkInserter > {
367
+ class AArch64SLSHardening : public ThunkInserterPass <SLSHardeningInserter > {
417
368
public:
418
369
static char ID;
419
370
420
- AArch64IndirectThunks () : ThunkInserterPass(ID) {}
371
+ AArch64SLSHardening () : ThunkInserterPass(ID) {}
421
372
422
- StringRef getPassName () const override { return " AArch64 Indirect Thunks " ; }
373
+ StringRef getPassName () const override { return AARCH64_SLS_HARDENING_NAME ; }
423
374
};
424
375
425
376
} // end anonymous namespace
426
377
427
- char AArch64IndirectThunks::ID = 0 ;
378
+ char AArch64SLSHardening::ID = 0 ;
379
+
380
+ INITIALIZE_PASS (AArch64SLSHardening, " aarch64-sls-hardening" ,
381
+ AARCH64_SLS_HARDENING_NAME, false , false )
428
382
429
- FunctionPass *llvm::createAArch64IndirectThunks () {
430
- return new AArch64IndirectThunks ();
383
+ FunctionPass *llvm::createAArch64SLSHardeningPass () {
384
+ return new AArch64SLSHardening ();
431
385
}
0 commit comments