12
12
// ===----------------------------------------------------------------------===//
13
13
14
14
#include " AArch64.h"
15
+ #include " AArch64ExpandImm.h"
15
16
#include " AArch64MCInstLower.h"
16
17
#include " AArch64MachineFunctionInfo.h"
17
18
#include " AArch64RegisterInfo.h"
@@ -160,6 +161,11 @@ class AArch64AsmPrinter : public AsmPrinter {
160
161
// adrp-add followed by PAC sign)
161
162
void LowerMOVaddrPAC (const MachineInstr &MI);
162
163
164
+ // Emit the sequence for LOADgotAUTH (load signed pointer from signed ELF GOT
165
+ // and authenticate it with, if FPAC bit is not set, check+trap sequence after
166
+ // authenticating)
167
+ void LowerLOADgotAUTH (const MachineInstr &MI);
168
+
163
169
// / tblgen'erated driver function for lowering simple MI->MC
164
170
// / pseudo instructions.
165
171
bool lowerPseudoInstExpansion (const MachineInstr *MI, MCInst &Inst);
@@ -2168,6 +2174,10 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
2168
2174
};
2169
2175
2170
2176
const bool IsGOTLoad = MI.getOpcode () == AArch64::LOADgotPAC;
2177
+ const bool IsELFSignedGOT = MI.getParent ()
2178
+ ->getParent ()
2179
+ ->getInfo <AArch64FunctionInfo>()
2180
+ ->hasELFSignedGOT ();
2171
2181
MachineOperand GAOp = MI.getOperand (0 );
2172
2182
const uint64_t KeyC = MI.getOperand (1 ).getImm ();
2173
2183
assert (KeyC <= AArch64PACKey::LAST &&
@@ -2184,9 +2194,17 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
2184
2194
// Emit:
2185
2195
// target materialization:
2186
2196
// - via GOT:
2187
- // adrp x16, :got:target
2188
- // ldr x16, [x16, :got_lo12:target]
2189
- // add offset to x16 if offset != 0
2197
+ // - unsigned GOT:
2198
+ // adrp x16, :got:target
2199
+ // ldr x16, [x16, :got_lo12:target]
2200
+ // add offset to x16 if offset != 0
2201
+ // - ELF signed GOT:
2202
+ // adrp x17, :got:target
2203
+ // add x17, x17, :got_auth_lo12:target
2204
+ // ldr x16, [x17]
2205
+ // aut{i|d}a x16, x17
2206
+ // check+trap sequence (if no FPAC)
2207
+ // add offset to x16 if offset != 0
2190
2208
//
2191
2209
// - direct:
2192
2210
// adrp x16, target
@@ -2229,13 +2247,79 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
2229
2247
MCInstLowering.lowerOperand (GAMOLo, GAMCLo);
2230
2248
2231
2249
EmitAndIncrement (
2232
- MCInstBuilder (AArch64::ADRP).addReg (AArch64::X16).addOperand (GAMCHi));
2250
+ MCInstBuilder (AArch64::ADRP)
2251
+ .addReg (IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2252
+ .addOperand (GAMCHi));
2233
2253
2234
2254
if (IsGOTLoad) {
2235
- EmitAndIncrement (MCInstBuilder (AArch64::LDRXui)
2236
- .addReg (AArch64::X16)
2237
- .addReg (AArch64::X16)
2238
- .addOperand (GAMCLo));
2255
+ if (IsELFSignedGOT) {
2256
+ EmitAndIncrement (MCInstBuilder (AArch64::ADDXri)
2257
+ .addReg (AArch64::X17)
2258
+ .addReg (AArch64::X17)
2259
+ .addOperand (GAMCLo)
2260
+ .addImm (0 ));
2261
+
2262
+ EmitAndIncrement (MCInstBuilder (AArch64::LDRXui)
2263
+ .addReg (AArch64::X16)
2264
+ .addReg (AArch64::X17)
2265
+ .addImm (0 ));
2266
+
2267
+ assert (GAOp.isGlobal ());
2268
+ assert (GAOp.getGlobal ()->getValueType () != nullptr );
2269
+ unsigned AuthOpcode = GAOp.getGlobal ()->getValueType ()->isFunctionTy ()
2270
+ ? AArch64::AUTIA
2271
+ : AArch64::AUTDA;
2272
+
2273
+ EmitAndIncrement (MCInstBuilder (AuthOpcode)
2274
+ .addReg (AArch64::X16)
2275
+ .addReg (AArch64::X16)
2276
+ .addReg (AArch64::X17));
2277
+
2278
+ if (!STI->hasFPAC ()) {
2279
+ auto AuthKey = (AuthOpcode == AArch64::AUTIA ? AArch64PACKey::IA
2280
+ : AArch64PACKey::DA);
2281
+ unsigned XPACOpc = getXPACOpcodeForKey (AuthKey);
2282
+ MCSymbol *SuccessSym = createTempSymbol (" auth_success_" );
2283
+
2284
+ // XPAC has tied src/dst: use x17 as a temporary copy.
2285
+ // mov x17, x16
2286
+ EmitAndIncrement (MCInstBuilder (AArch64::ORRXrs)
2287
+ .addReg (AArch64::X17)
2288
+ .addReg (AArch64::XZR)
2289
+ .addReg (AArch64::X16)
2290
+ .addImm (0 ));
2291
+
2292
+ // xpaci x17
2293
+ EmitAndIncrement (
2294
+ MCInstBuilder (XPACOpc).addReg (AArch64::X17).addReg (AArch64::X17));
2295
+
2296
+ // cmp x16, x17
2297
+ EmitAndIncrement (MCInstBuilder (AArch64::SUBSXrs)
2298
+ .addReg (AArch64::XZR)
2299
+ .addReg (AArch64::X16)
2300
+ .addReg (AArch64::X17)
2301
+ .addImm (0 ));
2302
+
2303
+ // b.eq Lsuccess
2304
+ EmitAndIncrement (
2305
+ MCInstBuilder (AArch64::Bcc)
2306
+ .addImm (AArch64CC::EQ)
2307
+ .addExpr (MCSymbolRefExpr::create (SuccessSym, OutContext)));
2308
+
2309
+ // Trapping sequences do a 'brk'.
2310
+ // brk #<0xc470 + aut key>
2311
+ EmitAndIncrement (MCInstBuilder (AArch64::BRK).addImm (0xc470 | AuthKey));
2312
+
2313
+ // If the auth check succeeds, we can continue.
2314
+ // Lsuccess:
2315
+ OutStreamer->emitLabel (SuccessSym);
2316
+ }
2317
+ } else {
2318
+ EmitAndIncrement (MCInstBuilder (AArch64::LDRXui)
2319
+ .addReg (AArch64::X16)
2320
+ .addReg (AArch64::X16)
2321
+ .addOperand (GAMCLo));
2322
+ }
2239
2323
} else {
2240
2324
EmitAndIncrement (MCInstBuilder (AArch64::ADDXri)
2241
2325
.addReg (AArch64::X16)
@@ -2320,6 +2404,53 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
2320
2404
assert (STI->getInstrInfo ()->getInstSizeInBytes (MI) >= InstsEmitted * 4 );
2321
2405
}
2322
2406
2407
+ void AArch64AsmPrinter::LowerLOADgotAUTH (const MachineInstr &MI) {
2408
+ unsigned InstsEmitted = 0 ;
2409
+ auto EmitAndIncrement = [this , &InstsEmitted](const MCInst &Inst) {
2410
+ EmitToStreamer (*OutStreamer, Inst);
2411
+ ++InstsEmitted;
2412
+ };
2413
+
2414
+ Register DstReg = MI.getOperand (0 ).getReg ();
2415
+ const MachineOperand &GAMO = MI.getOperand (1 );
2416
+ assert (GAMO.getOffset () == 0 );
2417
+
2418
+ MachineOperand GAHiOp (GAMO);
2419
+ MachineOperand GALoOp (GAMO);
2420
+ GAHiOp.addTargetFlag (AArch64II::MO_PAGE);
2421
+ GALoOp.addTargetFlag (AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
2422
+
2423
+ MCOperand GAMCHi, GAMCLo;
2424
+ MCInstLowering.lowerOperand (GAHiOp, GAMCHi);
2425
+ MCInstLowering.lowerOperand (GALoOp, GAMCLo);
2426
+
2427
+ EmitAndIncrement (
2428
+ MCInstBuilder (AArch64::ADRP).addReg (AArch64::X16).addOperand (GAMCHi));
2429
+
2430
+ EmitAndIncrement (MCInstBuilder (AArch64::ADDXri)
2431
+ .addReg (AArch64::X16)
2432
+ .addReg (AArch64::X16)
2433
+ .addOperand (GAMCLo)
2434
+ .addImm (0 ));
2435
+
2436
+ EmitAndIncrement (MCInstBuilder (AArch64::LDRXui)
2437
+ .addReg (DstReg)
2438
+ .addReg (AArch64::X16)
2439
+ .addImm (0 ));
2440
+
2441
+ assert (GAMO.isGlobal ());
2442
+ assert (GAMO.getGlobal ()->getValueType () != nullptr );
2443
+ unsigned AuthOpcode = GAMO.getGlobal ()->getValueType ()->isFunctionTy ()
2444
+ ? AArch64::AUTIA
2445
+ : AArch64::AUTDA;
2446
+ EmitAndIncrement (MCInstBuilder (AuthOpcode)
2447
+ .addReg (DstReg)
2448
+ .addReg (DstReg)
2449
+ .addReg (AArch64::X16));
2450
+
2451
+ assert (STI->getInstrInfo ()->getInstSizeInBytes (MI) >= InstsEmitted * 4 );
2452
+ }
2453
+
2323
2454
const MCExpr *
2324
2455
AArch64AsmPrinter::lowerBlockAddressConstant (const BlockAddress &BA) {
2325
2456
const MCExpr *BAE = AsmPrinter::lowerBlockAddressConstant (BA);
@@ -2484,6 +2615,10 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
2484
2615
LowerMOVaddrPAC (*MI);
2485
2616
return ;
2486
2617
2618
+ case AArch64::LOADgotAUTH:
2619
+ LowerLOADgotAUTH (*MI);
2620
+ return ;
2621
+
2487
2622
case AArch64::BRA:
2488
2623
case AArch64::BLRA:
2489
2624
emitPtrauthBranch (MI);
0 commit comments