@@ -160,6 +160,9 @@ class AArch64AsmPrinter : public AsmPrinter {
160160 // adrp-add followed by PAC sign)
161161 void LowerMOVaddrPAC (const MachineInstr &MI);
162162
163+ // Emit the sequence for LOADgotAUTH (load+auth pointer from signed ELF GOT)
164+ void LowerLOADgotAUTH (const MachineInstr &MI);
165+
163166 // / tblgen'erated driver function for lowering simple MI->MC
164167 // / pseudo instructions.
165168 bool lowerPseudoInstExpansion (const MachineInstr *MI, MCInst &Inst);
@@ -2168,6 +2171,10 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
21682171 };
21692172
21702173 const bool IsGOTLoad = MI.getOpcode () == AArch64::LOADgotPAC;
2174+ const bool IsELFSignedGOT = MI.getParent ()
2175+ ->getParent ()
2176+ ->getInfo <AArch64FunctionInfo>()
2177+ ->hasELFSignedGOT ();
21712178 MachineOperand GAOp = MI.getOperand (0 );
21722179 const uint64_t KeyC = MI.getOperand (1 ).getImm ();
21732180 assert (KeyC <= AArch64PACKey::LAST &&
@@ -2184,9 +2191,17 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
21842191 // Emit:
21852192 // target materialization:
21862193 // - 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
21902205 //
21912206 // - direct:
21922207 // adrp x16, target
@@ -2229,13 +2244,81 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
22292244 MCInstLowering.lowerOperand (GAMOLo, GAMCLo);
22302245
22312246 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));
22332250
22342251 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+ }
22392322 } else {
22402323 EmitAndIncrement (MCInstBuilder (AArch64::ADDXri)
22412324 .addReg (AArch64::X16)
@@ -2320,6 +2403,53 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
23202403 assert (STI->getInstrInfo ()->getInstSizeInBytes (MI) >= InstsEmitted * 4 );
23212404}
23222405
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+
23232453const MCExpr *
23242454AArch64AsmPrinter::lowerBlockAddressConstant (const BlockAddress &BA) {
23252455 const MCExpr *BAE = AsmPrinter::lowerBlockAddressConstant (BA);
@@ -2484,6 +2614,10 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
24842614 LowerMOVaddrPAC (*MI);
24852615 return ;
24862616
2617+ case AArch64::LOADgotAUTH:
2618+ LowerLOADgotAUTH (*MI);
2619+ return ;
2620+
24872621 case AArch64::BRA:
24882622 case AArch64::BLRA:
24892623 emitPtrauthBranch (MI);
0 commit comments