@@ -160,6 +160,11 @@ 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 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+
163168 // / tblgen'erated driver function for lowering simple MI->MC
164169 // / pseudo instructions.
165170 bool lowerPseudoInstExpansion (const MachineInstr *MI, MCInst &Inst);
@@ -923,6 +928,22 @@ void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) {
923928
924929 OutStreamer->addBlankLine ();
925930 }
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);
926947 }
927948
928949 // Emit stack and fault map information.
@@ -2168,6 +2189,10 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
21682189 };
21692190
21702191 const bool IsGOTLoad = MI.getOpcode () == AArch64::LOADgotPAC;
2192+ const bool IsELFSignedGOT = MI.getParent ()
2193+ ->getParent ()
2194+ ->getInfo <AArch64FunctionInfo>()
2195+ ->hasELFSignedGOT ();
21712196 MachineOperand GAOp = MI.getOperand (0 );
21722197 const uint64_t KeyC = MI.getOperand (1 ).getImm ();
21732198 assert (KeyC <= AArch64PACKey::LAST &&
@@ -2184,9 +2209,17 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
21842209 // Emit:
21852210 // target materialization:
21862211 // - 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
21902223 //
21912224 // - direct:
21922225 // adrp x16, target
@@ -2229,13 +2262,79 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
22292262 MCInstLowering.lowerOperand (GAMOLo, GAMCLo);
22302263
22312264 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));
22332268
22342269 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+ }
22392338 } else {
22402339 EmitAndIncrement (MCInstBuilder (AArch64::ADDXri)
22412340 .addReg (AArch64::X16)
@@ -2320,6 +2419,53 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) {
23202419 assert (STI->getInstrInfo ()->getInstSizeInBytes (MI) >= InstsEmitted * 4 );
23212420}
23222421
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+
23232469const MCExpr *
23242470AArch64AsmPrinter::lowerBlockAddressConstant (const BlockAddress &BA) {
23252471 const MCExpr *BAE = AsmPrinter::lowerBlockAddressConstant (BA);
@@ -2484,6 +2630,10 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
24842630 LowerMOVaddrPAC (*MI);
24852631 return ;
24862632
2633+ case AArch64::LOADgotAUTH:
2634+ LowerLOADgotAUTH (*MI);
2635+ return ;
2636+
24872637 case AArch64::BRA:
24882638 case AArch64::BLRA:
24892639 emitPtrauthBranch (MI);
0 commit comments