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