@@ -160,6 +160,11 @@ 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 signed pointer from signed ELF GOT
164
+ // and authenticate it with, if FPAC bit is not set, check+trap sequence after
165
+ // authenticating)
166
+ void LowerLOADgotAUTH (const MachineInstr &MI);
167
+
163
168
// / tblgen'erated driver function for lowering simple MI->MC
164
169
// / pseudo instructions.
165
170
bool lowerPseudoInstExpansion (const MachineInstr *MI, MCInst &Inst);
@@ -923,6 +928,22 @@ void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) {
923
928
924
929
OutStreamer->addBlankLine ();
925
930
}
931
+
932
+ // With signed ELF GOT enabled, the linker looks at the symbol type to
933
+ // choose between keys IA (for STT_FUNC) and DA (for other types). Symbols
934
+ // for functions not defined in the module have STT_NOTYPE type by default.
935
+ // This makes linker to emit signing schema with DA key (instead of IA) for
936
+ // corresponding R_AARCH64_AUTH_GLOB_DAT dynamic reloc. To avoid that, force
937
+ // all function symbols used in the module to have STT_FUNC type. See
938
+ // https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#default-signing-schema
939
+ const auto *PtrAuthELFGOTFlag = mdconst::extract_or_null<ConstantInt>(
940
+ M.getModuleFlag (" ptrauth-elf-got" ));
941
+ if (PtrAuthELFGOTFlag && PtrAuthELFGOTFlag->getZExtValue () == 1 )
942
+ for (const GlobalValue &GV : M.global_values ())
943
+ if (!GV.use_empty () && GV.getValueType ()->isFunctionTy () &&
944
+ !GV.getName ().starts_with (" llvm." ))
945
+ OutStreamer->emitSymbolAttribute (getSymbol (&GV),
946
+ MCSA_ELF_TypeFunction);
926
947
}
927
948
928
949
// Emit stack and fault map information.
@@ -2168,6 +2189,10 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
2168
2189
};
2169
2190
2170
2191
const bool IsGOTLoad = MI.getOpcode () == AArch64::LOADgotPAC;
2192
+ const bool IsELFSignedGOT = MI.getParent ()
2193
+ ->getParent ()
2194
+ ->getInfo <AArch64FunctionInfo>()
2195
+ ->hasELFSignedGOT ();
2171
2196
MachineOperand GAOp = MI.getOperand (0 );
2172
2197
const uint64_t KeyC = MI.getOperand (1 ).getImm ();
2173
2198
assert (KeyC <= AArch64PACKey::LAST &&
@@ -2184,9 +2209,17 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
2184
2209
// Emit:
2185
2210
// target materialization:
2186
2211
// - via GOT:
2187
- // adrp x16, :got:target
2188
- // ldr x16, [x16, :got_lo12:target]
2189
- // add offset to x16 if offset != 0
2212
+ // - unsigned GOT:
2213
+ // adrp x16, :got:target
2214
+ // ldr x16, [x16, :got_lo12:target]
2215
+ // add offset to x16 if offset != 0
2216
+ // - ELF signed GOT:
2217
+ // adrp x17, :got:target
2218
+ // add x17, x17, :got_auth_lo12:target
2219
+ // ldr x16, [x17]
2220
+ // aut{i|d}a x16, x17
2221
+ // check+trap sequence (if no FPAC)
2222
+ // add offset to x16 if offset != 0
2190
2223
//
2191
2224
// - direct:
2192
2225
// adrp x16, target
@@ -2229,13 +2262,79 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
2229
2262
MCInstLowering.lowerOperand (GAMOLo, GAMCLo);
2230
2263
2231
2264
EmitAndIncrement (
2232
- MCInstBuilder (AArch64::ADRP).addReg (AArch64::X16).addOperand (GAMCHi));
2265
+ MCInstBuilder (AArch64::ADRP)
2266
+ .addReg (IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16)
2267
+ .addOperand (GAMCHi));
2233
2268
2234
2269
if (IsGOTLoad) {
2235
- EmitAndIncrement (MCInstBuilder (AArch64::LDRXui)
2236
- .addReg (AArch64::X16)
2237
- .addReg (AArch64::X16)
2238
- .addOperand (GAMCLo));
2270
+ if (IsELFSignedGOT) {
2271
+ EmitAndIncrement (MCInstBuilder (AArch64::ADDXri)
2272
+ .addReg (AArch64::X17)
2273
+ .addReg (AArch64::X17)
2274
+ .addOperand (GAMCLo)
2275
+ .addImm (0 ));
2276
+
2277
+ EmitAndIncrement (MCInstBuilder (AArch64::LDRXui)
2278
+ .addReg (AArch64::X16)
2279
+ .addReg (AArch64::X17)
2280
+ .addImm (0 ));
2281
+
2282
+ assert (GAOp.isGlobal ());
2283
+ assert (GAOp.getGlobal ()->getValueType () != nullptr );
2284
+ unsigned AuthOpcode = GAOp.getGlobal ()->getValueType ()->isFunctionTy ()
2285
+ ? AArch64::AUTIA
2286
+ : AArch64::AUTDA;
2287
+
2288
+ EmitAndIncrement (MCInstBuilder (AuthOpcode)
2289
+ .addReg (AArch64::X16)
2290
+ .addReg (AArch64::X16)
2291
+ .addReg (AArch64::X17));
2292
+
2293
+ if (!STI->hasFPAC ()) {
2294
+ auto AuthKey = (AuthOpcode == AArch64::AUTIA ? AArch64PACKey::IA
2295
+ : AArch64PACKey::DA);
2296
+ unsigned XPACOpc = getXPACOpcodeForKey (AuthKey);
2297
+ MCSymbol *SuccessSym = createTempSymbol (" auth_success_" );
2298
+
2299
+ // XPAC has tied src/dst: use x17 as a temporary copy.
2300
+ // mov x17, x16
2301
+ EmitAndIncrement (MCInstBuilder (AArch64::ORRXrs)
2302
+ .addReg (AArch64::X17)
2303
+ .addReg (AArch64::XZR)
2304
+ .addReg (AArch64::X16)
2305
+ .addImm (0 ));
2306
+
2307
+ // xpaci x17
2308
+ EmitAndIncrement (
2309
+ MCInstBuilder (XPACOpc).addReg (AArch64::X17).addReg (AArch64::X17));
2310
+
2311
+ // cmp x16, x17
2312
+ EmitAndIncrement (MCInstBuilder (AArch64::SUBSXrs)
2313
+ .addReg (AArch64::XZR)
2314
+ .addReg (AArch64::X16)
2315
+ .addReg (AArch64::X17)
2316
+ .addImm (0 ));
2317
+
2318
+ // b.eq Lsuccess
2319
+ EmitAndIncrement (
2320
+ MCInstBuilder (AArch64::Bcc)
2321
+ .addImm (AArch64CC::EQ)
2322
+ .addExpr (MCSymbolRefExpr::create (SuccessSym, OutContext)));
2323
+
2324
+ // Trapping sequences do a 'brk'.
2325
+ // brk #<0xc470 + aut key>
2326
+ EmitAndIncrement (MCInstBuilder (AArch64::BRK).addImm (0xc470 | AuthKey));
2327
+
2328
+ // If the auth check succeeds, we can continue.
2329
+ // Lsuccess:
2330
+ OutStreamer->emitLabel (SuccessSym);
2331
+ }
2332
+ } else {
2333
+ EmitAndIncrement (MCInstBuilder (AArch64::LDRXui)
2334
+ .addReg (AArch64::X16)
2335
+ .addReg (AArch64::X16)
2336
+ .addOperand (GAMCLo));
2337
+ }
2239
2338
} else {
2240
2339
EmitAndIncrement (MCInstBuilder (AArch64::ADDXri)
2241
2340
.addReg (AArch64::X16)
@@ -2320,6 +2419,53 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
2320
2419
assert (STI->getInstrInfo ()->getInstSizeInBytes (MI) >= InstsEmitted * 4 );
2321
2420
}
2322
2421
2422
+ void AArch64AsmPrinter::LowerLOADgotAUTH (const MachineInstr &MI) {
2423
+ unsigned InstsEmitted = 0 ;
2424
+ auto EmitAndIncrement = [this , &InstsEmitted](const MCInst &Inst) {
2425
+ EmitToStreamer (*OutStreamer, Inst);
2426
+ ++InstsEmitted;
2427
+ };
2428
+
2429
+ Register DstReg = MI.getOperand (0 ).getReg ();
2430
+ const MachineOperand &GAMO = MI.getOperand (1 );
2431
+ assert (GAMO.getOffset () == 0 );
2432
+
2433
+ MachineOperand GAHiOp (GAMO);
2434
+ MachineOperand GALoOp (GAMO);
2435
+ GAHiOp.addTargetFlag (AArch64II::MO_PAGE);
2436
+ GALoOp.addTargetFlag (AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
2437
+
2438
+ MCOperand GAMCHi, GAMCLo;
2439
+ MCInstLowering.lowerOperand (GAHiOp, GAMCHi);
2440
+ MCInstLowering.lowerOperand (GALoOp, GAMCLo);
2441
+
2442
+ EmitAndIncrement (
2443
+ MCInstBuilder (AArch64::ADRP).addReg (AArch64::X16).addOperand (GAMCHi));
2444
+
2445
+ EmitAndIncrement (MCInstBuilder (AArch64::ADDXri)
2446
+ .addReg (AArch64::X16)
2447
+ .addReg (AArch64::X16)
2448
+ .addOperand (GAMCLo)
2449
+ .addImm (0 ));
2450
+
2451
+ EmitAndIncrement (MCInstBuilder (AArch64::LDRXui)
2452
+ .addReg (DstReg)
2453
+ .addReg (AArch64::X16)
2454
+ .addImm (0 ));
2455
+
2456
+ assert (GAMO.isGlobal ());
2457
+ assert (GAMO.getGlobal ()->getValueType () != nullptr );
2458
+ unsigned AuthOpcode = GAMO.getGlobal ()->getValueType ()->isFunctionTy ()
2459
+ ? AArch64::AUTIA
2460
+ : AArch64::AUTDA;
2461
+ EmitAndIncrement (MCInstBuilder (AuthOpcode)
2462
+ .addReg (DstReg)
2463
+ .addReg (DstReg)
2464
+ .addReg (AArch64::X16));
2465
+
2466
+ assert (STI->getInstrInfo ()->getInstSizeInBytes (MI) >= InstsEmitted * 4 );
2467
+ }
2468
+
2323
2469
const MCExpr *
2324
2470
AArch64AsmPrinter::lowerBlockAddressConstant (const BlockAddress &BA) {
2325
2471
const MCExpr *BAE = AsmPrinter::lowerBlockAddressConstant (BA);
@@ -2484,6 +2630,10 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
2484
2630
LowerMOVaddrPAC (*MI);
2485
2631
return ;
2486
2632
2633
+ case AArch64::LOADgotAUTH:
2634
+ LowerLOADgotAUTH (*MI);
2635
+ return ;
2636
+
2487
2637
case AArch64::BRA:
2488
2638
case AArch64::BLRA:
2489
2639
emitPtrauthBranch (MI);
0 commit comments