1212// ===----------------------------------------------------------------------===//
1313
1414#include " AArch64.h"
15+ #include " AArch64ExpandImm.h"
1516#include " AArch64MCInstLower.h"
1617#include " AArch64MachineFunctionInfo.h"
1718#include " AArch64RegisterInfo.h"
@@ -160,6 +161,11 @@ class AArch64AsmPrinter : public AsmPrinter {
160161 // adrp-add followed by PAC sign)
161162 void LowerMOVaddrPAC (const MachineInstr &MI);
162163
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+
163169 // / tblgen'erated driver function for lowering simple MI->MC
164170 // / pseudo instructions.
165171 bool lowerPseudoInstExpansion (const MachineInstr *MI, MCInst &Inst);
@@ -2168,6 +2174,10 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
21682174 };
21692175
21702176 const bool IsGOTLoad = MI.getOpcode () == AArch64::LOADgotPAC;
2177+ const bool IsELFSignedGOT = MI.getParent ()
2178+ ->getParent ()
2179+ ->getInfo <AArch64FunctionInfo>()
2180+ ->hasELFSignedGOT ();
21712181 MachineOperand GAOp = MI.getOperand (0 );
21722182 const uint64_t KeyC = MI.getOperand (1 ).getImm ();
21732183 assert (KeyC <= AArch64PACKey::LAST &&
@@ -2184,9 +2194,17 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
21842194 // Emit:
21852195 // target materialization:
21862196 // - 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
21902208 //
21912209 // - direct:
21922210 // adrp x16, target
@@ -2229,13 +2247,79 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
22292247 MCInstLowering.lowerOperand (GAMOLo, GAMCLo);
22302248
22312249 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));
22332253
22342254 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+ }
22392323 } else {
22402324 EmitAndIncrement (MCInstBuilder (AArch64::ADDXri)
22412325 .addReg (AArch64::X16)
@@ -2320,6 +2404,53 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
23202404 assert (STI->getInstrInfo ()->getInstSizeInBytes (MI) >= InstsEmitted * 4 );
23212405}
23222406
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+
23232454const MCExpr *
23242455AArch64AsmPrinter::lowerBlockAddressConstant (const BlockAddress &BA) {
23252456 const MCExpr *BAE = AsmPrinter::lowerBlockAddressConstant (BA);
@@ -2484,6 +2615,10 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
24842615 LowerMOVaddrPAC (*MI);
24852616 return ;
24862617
2618+ case AArch64::LOADgotAUTH:
2619+ LowerLOADgotAUTH (*MI);
2620+ return ;
2621+
24872622 case AArch64::BRA:
24882623 case AArch64::BLRA:
24892624 emitPtrauthBranch (MI);
0 commit comments