diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index 0391d51832431..040a47f2f6d7f 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -2161,6 +2161,10 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) { }; const bool IsGOTLoad = MI.getOpcode() == AArch64::LOADgotPAC; + const bool IsELFSignedGOT = MI.getParent() + ->getParent() + ->getInfo() + ->hasELFSignedGOT(); MachineOperand GAOp = MI.getOperand(0); const uint64_t KeyC = MI.getOperand(1).getImm(); assert(KeyC <= AArch64PACKey::LAST && @@ -2177,9 +2181,16 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) { // Emit: // target materialization: // - via GOT: - // adrp x16, :got:target - // ldr x16, [x16, :got_lo12:target] - // add offset to x16 if offset != 0 + // - unsigned GOT: + // adrp x16, :got:target + // ldr x16, [x16, :got_lo12:target] + // add offset to x16 if offset != 0 + // - ELF signed GOT: + // adrp x17, :got:target + // add x17, x17, :got_auth_lo12:target + // ldr x16, [x17] + // aut{i|d}a x16, x17 + // add offset to x16 if offset != 0 // // - direct: // adrp x16, target @@ -2222,13 +2233,40 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) { MCInstLowering.lowerOperand(GAMOLo, GAMCLo); EmitAndIncrement( - MCInstBuilder(AArch64::ADRP).addReg(AArch64::X16).addOperand(GAMCHi)); + MCInstBuilder(AArch64::ADRP) + .addReg(IsGOTLoad && IsELFSignedGOT ? AArch64::X17 : AArch64::X16) + .addOperand(GAMCHi)); if (IsGOTLoad) { - EmitAndIncrement(MCInstBuilder(AArch64::LDRXui) - .addReg(AArch64::X16) - .addReg(AArch64::X16) - .addOperand(GAMCLo)); + if (IsELFSignedGOT) { + EmitAndIncrement(MCInstBuilder(AArch64::ADDXri) + .addReg(AArch64::X17) + .addReg(AArch64::X17) + .addOperand(GAMCLo) + .addImm(0)); + + EmitAndIncrement(MCInstBuilder(AArch64::LDRXui) + .addReg(AArch64::X16) + .addReg(AArch64::X17) + .addImm(0)); + + assert(GAOp.isGlobal()); + assert(GAOp.getGlobal()->getValueType() != nullptr); + unsigned AuthOpcode = GAOp.getGlobal()->getValueType()->isFunctionTy() + ? AArch64::AUTIA + : AArch64::AUTDA; + + EmitAndIncrement(MCInstBuilder(AuthOpcode) + .addReg(AArch64::X16) + .addReg(AArch64::X16) + .addReg(AArch64::X17)); + + } else { + EmitAndIncrement(MCInstBuilder(AArch64::LDRXui) + .addReg(AArch64::X16) + .addReg(AArch64::X16) + .addOperand(GAMCLo)); + } } else { EmitAndIncrement(MCInstBuilder(AArch64::ADDXri) .addReg(AArch64::X16) diff --git a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp index 9b7fc228d5de8..72c767200b380 100644 --- a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp +++ b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp @@ -1291,7 +1291,40 @@ bool AArch64ExpandPseudo::expandMI(MachineBasicBlock &MBB, MI.eraseFromParent(); return true; } + case AArch64::LOADgotAUTH: { + Register DstReg = MI.getOperand(0).getReg(); + const MachineOperand &MO1 = MI.getOperand(1); + + MachineOperand GAHiOp(MO1); + MachineOperand GALoOp(MO1); + GAHiOp.addTargetFlag(AArch64II::MO_PAGE); + GALoOp.addTargetFlag(AArch64II::MO_PAGEOFF | AArch64II::MO_NC); + + DebugLoc DL = MI.getDebugLoc(); + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), AArch64::X16) + .add(GAHiOp); + BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXri), AArch64::X16) + .addReg(AArch64::X16) + .add(GALoOp) + .addImm(0); + + BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXui), DstReg) + .addReg(AArch64::X16) + .addImm(0); + + assert(MO1.isGlobal()); + assert(MO1.getGlobal()->getValueType() != nullptr); + unsigned AuthOpcode = MO1.getGlobal()->getValueType()->isFunctionTy() + ? AArch64::AUTIA + : AArch64::AUTDA; + BuildMI(MBB, MBBI, DL, TII->get(AuthOpcode), DstReg) + .addReg(DstReg) + .addReg(AArch64::X16); + + MI.eraseFromParent(); + return true; + } case AArch64::LOADgot: { MachineFunction *MF = MBB.getParent(); Register DstReg = MI.getOperand(0).getReg(); diff --git a/llvm/lib/Target/AArch64/AArch64FastISel.cpp b/llvm/lib/Target/AArch64/AArch64FastISel.cpp index cbf38f2c57a35..4487d34a936c4 100644 --- a/llvm/lib/Target/AArch64/AArch64FastISel.cpp +++ b/llvm/lib/Target/AArch64/AArch64FastISel.cpp @@ -453,6 +453,9 @@ unsigned AArch64FastISel::materializeGV(const GlobalValue *GV) { if (!Subtarget->useSmallAddressing() && !Subtarget->isTargetMachO()) return 0; + if (FuncInfo.MF->getInfo()->hasELFSignedGOT()) + return 0; + unsigned OpFlags = Subtarget->ClassifyGlobalReference(GV, TM); EVT DestEVT = TLI.getValueType(DL, GV->getType(), true); diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index f0c3afc4f9b5d..94130736c3986 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -9225,6 +9225,11 @@ SDValue AArch64TargetLowering::getGOT(NodeTy *N, SelectionDAG &DAG, SDValue GotAddr = getTargetNode(N, Ty, DAG, AArch64II::MO_GOT | Flags); // FIXME: Once remat is capable of dealing with instructions with register // operands, expand this into two nodes instead of using a wrapper node. + if (DAG.getMachineFunction() + .getInfo() + ->hasELFSignedGOT()) + return SDValue(DAG.getMachineNode(AArch64::LOADgotAUTH, DL, Ty, GotAddr), + 0); return DAG.getNode(AArch64ISD::LOADgot, DL, Ty, GotAddr); } diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index e720c6b21a97b..93d2c0b2c9f42 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -1872,7 +1872,7 @@ let Predicates = [HasPAuth] in { Sched<[WriteI, ReadI]> { let isReMaterializable = 1; let isCodeGenOnly = 1; - let Size = 40; // 12 fixed + 28 variable, for pointer offset, and discriminator + let Size = 48; // 12 fixed + 36 variable, for pointer offset, and discriminator let Defs = [X16,X17]; } @@ -1911,6 +1911,11 @@ let Predicates = [HasPAuth] in { tcGPR64:$AddrDisc), (AUTH_TCRETURN_BTI tcGPRx16x17:$dst, imm:$FPDiff, imm:$Key, imm:$Disc, tcGPR64:$AddrDisc)>; + + def LOADgotAUTH : Pseudo<(outs GPR64common:$dst), (ins i64imm:$addr), []>, + Sched<[WriteI, ReadI]> { + let Defs = [X16]; + } } // v9.5-A pointer authentication extensions diff --git a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp index 48672241f905d..9f234b0f91705 100644 --- a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp +++ b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "AArch64MCInstLower.h" +#include "AArch64MachineFunctionInfo.h" #include "MCTargetDesc/AArch64MCExpr.h" #include "Utils/AArch64BaseInfo.h" #include "llvm/CodeGen/AsmPrinter.h" @@ -185,9 +186,12 @@ MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO, MCSymbol *Sym) const { uint32_t RefFlags = 0; - if (MO.getTargetFlags() & AArch64II::MO_GOT) - RefFlags |= AArch64MCExpr::VK_GOT; - else if (MO.getTargetFlags() & AArch64II::MO_TLS) { + if (MO.getTargetFlags() & AArch64II::MO_GOT) { + const MachineFunction *MF = MO.getParent()->getParent()->getParent(); + RefFlags |= (MF->getInfo()->hasELFSignedGOT() + ? AArch64MCExpr::VK_GOT_AUTH + : AArch64MCExpr::VK_GOT); + } else if (MO.getTargetFlags() & AArch64II::MO_TLS) { TLSModel::Model Model; if (MO.isGlobal()) { const GlobalValue *GV = MO.getGlobal(); diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp index e96c5a953ff2b..a0f0a489816c4 100644 --- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp @@ -16,6 +16,7 @@ #include "AArch64MachineFunctionInfo.h" #include "AArch64InstrInfo.h" #include "AArch64Subtarget.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" @@ -72,6 +73,29 @@ static bool ShouldSignWithBKey(const Function &F, const AArch64Subtarget &STI) { return Key == "b_key"; } +// Determine if we need to treat pointers in GOT as signed (as described in +// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#appendix-signed-got) +// based on PAuth core info encoded as "aarch64-elf-pauthabi-platform" and +// "aarch64-elf-pauthabi-version" module flags. Currently, only +// AARCH64_PAUTH_PLATFORM_LLVM_LINUX platform supports signed GOT with +// AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT bit in version value set. +static bool hasELFSignedGOTHelper(const Function &F, + const AArch64Subtarget *STI) { + if (!Triple(STI->getTargetTriple()).isOSBinFormatELF()) + return false; + const Module *M = F.getParent(); + const auto *PAP = mdconst::extract_or_null( + M->getModuleFlag("aarch64-elf-pauthabi-platform")); + if (!PAP || PAP->getZExtValue() != ELF::AARCH64_PAUTH_PLATFORM_LLVM_LINUX) + return false; + const auto *PAV = mdconst::extract_or_null( + M->getModuleFlag("aarch64-elf-pauthabi-version")); + if (!PAV) + return false; + return PAV->getZExtValue() & + (1 << ELF::AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT); +} + AArch64FunctionInfo::AArch64FunctionInfo(const Function &F, const AArch64Subtarget *STI) { // If we already know that the function doesn't have a redzone, set @@ -80,6 +104,7 @@ AArch64FunctionInfo::AArch64FunctionInfo(const Function &F, HasRedZone = false; std::tie(SignReturnAddress, SignReturnAddressAll) = GetSignReturnAddress(F); SignWithBKey = ShouldSignWithBKey(F, *STI); + HasELFSignedGOT = hasELFSignedGOTHelper(F, STI); // TODO: skip functions that have no instrumented allocas for optimization IsMTETagged = F.hasFnAttribute(Attribute::SanitizeMemTag); diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h index 72f110cebbdc8..9ae4584883437 100644 --- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h +++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h @@ -177,6 +177,14 @@ class AArch64FunctionInfo final : public MachineFunctionInfo { /// SignWithBKey modifies the default PAC-RET mode to signing with the B key. bool SignWithBKey = false; + /// HasELFSignedGOT is true if the target binary format is ELF and the IR + /// module containing the corresponding function has the following flags: + /// - aarch64-elf-pauthabi-platform flag equal to + /// AARCH64_PAUTH_PLATFORM_LLVM_LINUX; + /// - aarch64-elf-pauthabi-version flag with + /// AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT bit set. + bool HasELFSignedGOT = false; + /// SigningInstrOffset captures the offset of the PAC-RET signing instruction /// within the prologue, so it can be re-used for authentication in the /// epilogue when using PC as a second salt (FEAT_PAuth_LR) @@ -509,6 +517,8 @@ class AArch64FunctionInfo final : public MachineFunctionInfo { bool shouldSignWithBKey() const { return SignWithBKey; } + bool hasELFSignedGOT() const { return HasELFSignedGOT; } + MCSymbol *getSigningInstrLabel() const { return SignInstrLabel; } void setSigningInstrLabel(MCSymbol *Label) { SignInstrLabel = Label; } diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index 5e17ed40df8ab..8d4fc4ec5b007 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -875,6 +875,7 @@ class AArch64Operand : public MCParsedAsmOperand { if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF || ELFRefKind == AArch64MCExpr::VK_LO12 || ELFRefKind == AArch64MCExpr::VK_GOT_LO12 || + ELFRefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 || @@ -986,19 +987,20 @@ class AArch64Operand : public MCParsedAsmOperand { int64_t Addend; if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) { - return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF - || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF - || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0) - || ELFRefKind == AArch64MCExpr::VK_LO12 - || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 - || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 - || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC - || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 - || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 - || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC - || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 - || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12 - || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12; + return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF || + DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF || + (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0) || + ELFRefKind == AArch64MCExpr::VK_LO12 || + ELFRefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 || + ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 || + ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 || + ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC || + ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 || + ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 || + ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC || + ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 || + ELFRefKind == AArch64MCExpr::VK_SECREL_HI12 || + ELFRefKind == AArch64MCExpr::VK_SECREL_LO12; } // If it's a constant, it should be a real immediate in range. @@ -3250,6 +3252,7 @@ ParseStatus AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) { DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE && ELFRefKind != AArch64MCExpr::VK_ABS_PAGE_NC && ELFRefKind != AArch64MCExpr::VK_GOT_PAGE && + ELFRefKind != AArch64MCExpr::VK_GOT_AUTH_PAGE && ELFRefKind != AArch64MCExpr::VK_GOT_PAGE_LO15 && ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE && ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) { @@ -4334,6 +4337,8 @@ bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) { .Case("got", AArch64MCExpr::VK_GOT_PAGE) .Case("gotpage_lo15", AArch64MCExpr::VK_GOT_PAGE_LO15) .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12) + .Case("got_auth", AArch64MCExpr::VK_GOT_AUTH_PAGE) + .Case("got_auth_lo12", AArch64MCExpr::VK_GOT_AUTH_LO12) .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE) .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC) .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1) @@ -5708,6 +5713,7 @@ bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc, // Only allow these with ADDXri/ADDWri if ((ELFRefKind == AArch64MCExpr::VK_LO12 || + ELFRefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC || diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp index e9e6b6cb68d0d..ef8fcc0741701 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -2845,7 +2845,9 @@ bool AArch64InstructionSelector::select(MachineInstr &I) { } if (OpFlags & AArch64II::MO_GOT) { - I.setDesc(TII.get(AArch64::LOADgot)); + I.setDesc(TII.get(MF.getInfo()->hasELFSignedGOT() + ? AArch64::LOADgotAUTH + : AArch64::LOADgot)); I.getOperand(1).setTargetFlags(OpFlags); } else if (TM.getCodeModel() == CodeModel::Large && !TM.isPositionIndependent()) { diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp index b4c5cde5fd888..72671b0715f6e 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp @@ -167,6 +167,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx, } if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC) return R_CLS(ADR_GOT_PAGE); + if (SymLoc == AArch64MCExpr::VK_GOT_AUTH && !IsNC) { + if (IsILP32) { + Ctx.reportError(Fixup.getLoc(), + "ILP32 ADRP AUTH relocation not supported " + "(LP64 eqv: AUTH_ADR_GOT_PAGE)"); + return ELF::R_AARCH64_NONE; + } + return ELF::R_AARCH64_AUTH_ADR_GOT_PAGE; + } if (SymLoc == AArch64MCExpr::VK_GOTTPREL && !IsNC) return R_CLS(TLSIE_ADR_GOTTPREL_PAGE21); if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC) @@ -237,6 +246,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx, return R_CLS(TLSLE_ADD_TPREL_LO12); if (RefKind == AArch64MCExpr::VK_TLSDESC_LO12) return R_CLS(TLSDESC_ADD_LO12); + if (RefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 && IsNC) { + if (IsILP32) { + Ctx.reportError(Fixup.getLoc(), + "ILP32 ADD AUTH relocation not supported " + "(LP64 eqv: AUTH_GOT_ADD_LO12_NC)"); + return ELF::R_AARCH64_NONE; + } + return ELF::R_AARCH64_AUTH_GOT_ADD_LO12_NC; + } if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) return R_CLS(ADD_ABS_LO12_NC); @@ -329,17 +347,23 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx, case AArch64::fixup_aarch64_ldst_imm12_scale8: if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) return R_CLS(LDST64_ABS_LO12_NC); - if (SymLoc == AArch64MCExpr::VK_GOT && IsNC) { + if ((SymLoc == AArch64MCExpr::VK_GOT || + SymLoc == AArch64MCExpr::VK_GOT_AUTH) && + IsNC) { AArch64MCExpr::VariantKind AddressLoc = AArch64MCExpr::getAddressFrag(RefKind); + bool IsAuth = (SymLoc == AArch64MCExpr::VK_GOT_AUTH); if (!IsILP32) { if (AddressLoc == AArch64MCExpr::VK_LO15) return ELF::R_AARCH64_LD64_GOTPAGE_LO15; - return ELF::R_AARCH64_LD64_GOT_LO12_NC; + return (IsAuth ? ELF::R_AARCH64_AUTH_LD64_GOT_LO12_NC + : ELF::R_AARCH64_LD64_GOT_LO12_NC); } - Ctx.reportError(Fixup.getLoc(), "ILP32 64-bit load/store " - "relocation not supported (LP64 eqv: " - "LD64_GOT_LO12_NC)"); + Ctx.reportError(Fixup.getLoc(), + Twine("ILP32 64-bit load/store " + "relocation not supported (LP64 eqv: ") + + (IsAuth ? "AUTH_GOT_LO12_NC" : "LD64_GOT_LO12_NC") + + Twine(')')); return ELF::R_AARCH64_NONE; } if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC) diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp index fb8eb9f47da17..3430b9002894f 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp @@ -30,6 +30,7 @@ const AArch64MCExpr *AArch64MCExpr::create(const MCExpr *Expr, VariantKind Kind, } StringRef AArch64MCExpr::getVariantKindName() const { + // clang-format off switch (static_cast(getKind())) { case VK_CALL: return ""; case VK_LO12: return ":lo12:"; @@ -82,9 +83,13 @@ StringRef AArch64MCExpr::getVariantKindName() const { case VK_TLSDESC_PAGE: return ":tlsdesc:"; case VK_SECREL_LO12: return ":secrel_lo12:"; case VK_SECREL_HI12: return ":secrel_hi12:"; + case VK_GOT_AUTH: return ":got_auth:"; + case VK_GOT_AUTH_PAGE: return ":got_auth:"; + case VK_GOT_AUTH_LO12: return ":got_auth_lo12:"; default: llvm_unreachable("Invalid ELF symbol kind"); } + // clang-format on } void AArch64MCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h index cf3a90f95a2c1..699992782f67b 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h @@ -24,6 +24,7 @@ namespace llvm { class AArch64MCExpr : public MCTargetExpr { public: enum VariantKind { + // clang-format off // Symbol locations specifying (roughly speaking) what calculation should be // performed to construct the final address for the relocated // symbol. E.g. direct, via the GOT, ... @@ -38,6 +39,7 @@ class AArch64MCExpr : public MCTargetExpr { VK_SECREL = 0x009, VK_AUTH = 0x00a, VK_AUTHADDR = 0x00b, + VK_GOT_AUTH = 0x00c, VK_SymLocBits = 0x00f, // Variants specifying which part of the final address calculation is @@ -88,6 +90,8 @@ class AArch64MCExpr : public MCTargetExpr { VK_GOT_LO12 = VK_GOT | VK_PAGEOFF | VK_NC, VK_GOT_PAGE = VK_GOT | VK_PAGE, VK_GOT_PAGE_LO15 = VK_GOT | VK_LO15 | VK_NC, + VK_GOT_AUTH_LO12 = VK_GOT_AUTH | VK_PAGEOFF | VK_NC, + VK_GOT_AUTH_PAGE = VK_GOT_AUTH | VK_PAGE, VK_DTPREL_G2 = VK_DTPREL | VK_G2, VK_DTPREL_G1 = VK_DTPREL | VK_G1, VK_DTPREL_G1_NC = VK_DTPREL | VK_G1 | VK_NC, @@ -114,6 +118,7 @@ class AArch64MCExpr : public MCTargetExpr { VK_SECREL_HI12 = VK_SECREL | VK_HI12, VK_INVALID = 0xfff + // clang-format on }; private: diff --git a/llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll new file mode 100644 index 0000000000000..de6901f107617 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll @@ -0,0 +1,82 @@ +; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=0 -verify-machineinstrs \ +; RUN: -relocation-model=pic -mattr=+pauth %s -o - | FileCheck %s +; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=1 -verify-machineinstrs \ +; RUN: -relocation-model=pic -mattr=+pauth %s -o - | FileCheck %s +; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=1 -global-isel-abort=1 -verify-machineinstrs \ +; RUN: -relocation-model=pic -mattr=+pauth %s -o - | FileCheck %s + +;; Note: for FastISel, we fall back to SelectionDAG + +@var = global i32 0 + +define i32 @get_globalvar() { +; CHECK-LABEL: get_globalvar: +; CHECK: adrp x[[GOT:[0-9]+]], :got_auth:var +; CHECK-NEXT: add x[[GOT]], x[[GOT]], :got_auth_lo12:var +; CHECK-NEXT: ldr x[[SYM:[0-9]+]], [x[[GOT]]] +; CHECK-NEXT: autda x[[SYM]], x[[GOT]] +; CHECK-NEXT: ldr w0, [x[[SYM]]] + + %val = load i32, ptr @var + ret i32 %val +} + +define ptr @get_globalvaraddr() { +; CHECK-LABEL: get_globalvaraddr: +; CHECK: adrp x[[GOT:[0-9]+]], :got_auth:var +; CHECK-NEXT: add x[[GOT]], x[[GOT]], :got_auth_lo12:var +; CHECK-NEXT: ldr x0, [x[[GOT]]] +; CHECK-NEXT: autda x0, x[[GOT]] + + %val = load i32, ptr @var + ret ptr @var +} + +declare i32 @foo() + +define ptr @resign_globalfunc() { +; CHECK-LABEL: resign_globalfunc: +; CHECK: adrp x17, :got_auth:foo +; CHECK-NEXT: add x17, x17, :got_auth_lo12:foo +; CHECK-NEXT: ldr x16, [x17] +; CHECK-NEXT: autia x16, x17 +; CHECK-NEXT: mov x17, #42 +; CHECK-NEXT: pacia x16, x17 +; CHECK-NEXT: mov x0, x16 +; CHECK-NEXT: ret + + ret ptr ptrauth (ptr @foo, i32 0, i64 42) +} + +define ptr @resign_globalvar() { +; CHECK-LABEL: resign_globalvar: +; CHECK: adrp x17, :got_auth:var +; CHECK-NEXT: add x17, x17, :got_auth_lo12:var +; CHECK-NEXT: ldr x16, [x17] +; CHECK-NEXT: autda x16, x17 +; CHECK-NEXT: mov x17, #43 +; CHECK-NEXT: pacdb x16, x17 +; CHECK-NEXT: mov x0, x16 +; CHECK-NEXT: ret + + ret ptr ptrauth (ptr @var, i32 3, i64 43) +} + +define ptr @resign_globalvar_offset() { +; CHECK-LABEL: resign_globalvar_offset: +; CHECK: adrp x17, :got_auth:var +; CHECK-NEXT: add x17, x17, :got_auth_lo12:var +; CHECK-NEXT: ldr x16, [x17] +; CHECK-NEXT: autda x16, x17 +; CHECK-NEXT: add x16, x16, #16 +; CHECK-NEXT: mov x17, #44 +; CHECK-NEXT: pacda x16, x17 +; CHECK-NEXT: mov x0, x16 +; CHECK-NEXT: ret + + ret ptr ptrauth (ptr getelementptr (i8, ptr @var, i64 16), i32 2, i64 44) +} + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 256} diff --git a/llvm/test/CodeGen/AArch64/ptrauth-elf-globals-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-elf-globals-pic.ll new file mode 100644 index 0000000000000..2b7d8637b432a --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-elf-globals-pic.ll @@ -0,0 +1,23 @@ +; RUN: llc -mtriple=arm64 -global-isel=0 -fast-isel=0 -relocation-model=pic -o - %s -mcpu=cyclone -mattr=+pauth | FileCheck %s +; RUN: llc -mtriple=arm64 -global-isel=0 -fast-isel=1 -relocation-model=pic -o - %s -mcpu=cyclone -mattr=+pauth | FileCheck %s +; RUN: llc -mtriple=arm64 -global-isel=1 -global-isel-abort=1 -relocation-model=pic -o - %s -mcpu=cyclone -mattr=+pauth | FileCheck %s + +;; Note: for FastISel, we fall back to SelectionDAG + +@var8 = external global i8, align 1 + +define i8 @test_i8(i8 %new) { + %val = load i8, ptr @var8, align 1 + store i8 %new, ptr @var8 + ret i8 %val + +; CHECK: adrp x[[HIREG:[0-9]+]], :got_auth:var8 +; CHECK-NEXT: add x[[HIREG]], x[[HIREG]], :got_auth_lo12:var8 +; CHECK-NEXT: ldr x[[VAR_ADDR:[0-9]+]], [x[[HIREG]]] +; CHECK-NEXT: autda x[[VAR_ADDR]], x[[HIREG]] +; CHECK-NEXT: ldrb {{w[0-9]+}}, [x[[VAR_ADDR]]] +} + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 256} diff --git a/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll b/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll new file mode 100644 index 0000000000000..88b611141c041 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll @@ -0,0 +1,36 @@ +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=0 -fast-isel=0 -relocation-model=pic -mattr=+pauth -o - %s | FileCheck %s +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=0 -fast-isel=1 -relocation-model=pic -mattr=+pauth -o - %s | FileCheck %s +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=1 -global-isel-abort=1 -relocation-model=pic -mattr=+pauth -o - %s | FileCheck %s + +;; Note: for FastISel, we fall back to SelectionDAG + +declare extern_weak dso_local i32 @var() + +define ptr @foo() { +; The usual ADRP/ADD pair can't be used for a weak reference because it must +; evaluate to 0 if the symbol is undefined. We use a GOT entry for PIC +; otherwise a litpool entry. + ret ptr @var + +; CHECK: adrp x[[ADDRHI:[0-9]+]], :got_auth:var +; CHECK-NEXT: add x[[ADDRHI]], x[[ADDRHI]], :got_auth_lo12:var +; CHECK-NEXT: ldr x0, [x[[ADDRHI]]] +; CHECK-NEXT: autia x0, x[[ADDRHI]] +} + +@arr_var = extern_weak global [10 x i32] + +define ptr @bar() { + %addr = getelementptr [10 x i32], ptr @arr_var, i32 0, i32 5 + +; CHECK: adrp x[[ADDRHI:[0-9]+]], :got_auth:arr_var +; CHECK-NEXT: add x[[ADDRHI]], x[[ADDRHI]], :got_auth_lo12:arr_var +; CHECK-NEXT: ldr [[BASE:x[0-9]+]], [x[[ADDRHI]]] +; CHECK-NEXT: autda [[BASE]], x[[ADDRHI]] +; CHECK-NEXT: add x0, [[BASE]], #20 + ret ptr %addr +} + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 256} diff --git a/llvm/test/CodeGen/AArch64/ptrauth-got-abuse.ll b/llvm/test/CodeGen/AArch64/ptrauth-got-abuse.ll new file mode 100644 index 0000000000000..c1580534b62cb --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-got-abuse.ll @@ -0,0 +1,44 @@ +; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=0 -fast-isel=0 -relocation-model=pic -mattr=+pauth -o - %s | FileCheck %s +; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=0 -fast-isel=1 -relocation-model=pic -mattr=+pauth -o - %s | FileCheck %s +; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=1 -global-isel-abort=1 -relocation-model=pic -mattr=+pauth -o - %s | FileCheck %s +; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=0 -fast-isel=0 -relocation-model=pic -filetype=obj -mattr=+pauth -o /dev/null %s +; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=0 -fast-isel=1 -relocation-model=pic -filetype=obj -mattr=+pauth -o /dev/null %s +; RUN: llc -mtriple=aarch64-none-linux-gnu -asm-verbose=false -global-isel=1 -global-isel-abort=1 -relocation-model=pic -filetype=obj -mattr=+pauth -o /dev/null %s + +;; Note: for FastISel, we fall back to SelectionDAG + +declare void @consume(i32) +declare void @func() + +define void @aliasee_func() { + ret void +} +@alias_func = alias void (), ptr @aliasee_func + +@aliasee_global = global i32 42 +@alias_global = alias i32, ptr @aliasee_global + +define void @foo() nounwind { +; CHECK-LABEL: foo: +entry: + call void @consume(i32 ptrtoint (ptr @func to i32)) +; CHECK: adrp x[[ADDRHI:[0-9]+]], :got_auth:func +; CHECK-NEXT: add x[[ADDRHI]], x[[ADDRHI]], :got_auth_lo12:func +; CHECK-NEXT: ldr x[[SYM:[0-9]+]], [x[[ADDRHI]]] +; CHECK-NEXT: autia x[[SYM:[0-9]+]], x[[ADDRHI]] + call void @consume(i32 ptrtoint (ptr @alias_func to i32)) +; CHECK: adrp x[[ADDRHI:[0-9]+]], :got_auth:alias_func +; CHECK-NEXT: add x[[ADDRHI]], x[[ADDRHI]], :got_auth_lo12:alias_func +; CHECK-NEXT: ldr x[[SYM:[0-9]+]], [x[[ADDRHI]]] +; CHECK-NEXT: autia x[[SYM:[0-9]+]], x[[ADDRHI]] + call void @consume(i32 ptrtoint (ptr @alias_global to i32)) +; CHECK: adrp x[[ADDRHI:[0-9]+]], :got_auth:alias_global +; CHECK-NEXT: add x[[ADDRHI]], x[[ADDRHI]], :got_auth_lo12:alias_global +; CHECK-NEXT: ldr x[[SYM:[0-9]+]], [x[[ADDRHI]]] +; CHECK-NEXT: autda x[[SYM:[0-9]+]], x[[ADDRHI]] + ret void +} + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 256} diff --git a/llvm/test/CodeGen/AArch64/ptrauth-tagged-globals-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-tagged-globals-pic.ll new file mode 100644 index 0000000000000..c9a6722505bda --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-tagged-globals-pic.ll @@ -0,0 +1,66 @@ +; RUN: llc --relocation-model=pic -mattr=+pauth < %s | FileCheck %s --check-prefixes=CHECK,GISEL + +; RUN: llc -global-isel=0 -fast-isel=0 -O0 --relocation-model=pic < %s -mattr=+pauth | FileCheck %s --check-prefixes=CHECK,DAGISEL +; RUN: llc -global-isel=0 -fast-isel=1 -O0 --relocation-model=pic < %s -mattr=+pauth | FileCheck %s --check-prefixes=CHECK,DAGISEL +; RUN: llc -global-isel=1 -global-isel-abort=1 -O0 --relocation-model=pic < %s -mattr=+pauth | FileCheck %s --check-prefixes=CHECK,GISEL + +;; Note: for FastISel, we fall back to SelectionDAG + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64-unknown-linux-android" + +@global = external global i32 +declare void @func() + +define ptr @global_addr() #0 { + ; CHECK-LABEL: global_addr: + ; CHECK: adrp [[REG:x[0-9]+]], :got_auth:global + ; CHECK-NEXT: add [[REG]], [[REG]], :got_auth_lo12:global + ; CHECK-NEXT: ldr x0, [[[REG]]] + ; CHECK-NEXT: autda x0, [[REG]] + ; CHECK-NEXT: ret + + ret ptr @global +} + +define i32 @global_load() #0 { + ; CHECK-LABEL: global_load: + ; CHECK: adrp [[REG0:x[0-9]+]], :got_auth:global + ; CHECK-NEXT: add [[REG0]], [[REG0]], :got_auth_lo12:global + ; CHECK-NEXT: ldr [[REG1:x[0-9]+]], [[[REG0]]] + ; CHECK-NEXT: autda [[REG1]], [[REG0]] + ; CHECK-NEXT: ldr w0, [[[REG1]]] + ; CHECK-NEXT: ret + %load = load i32, ptr @global + ret i32 %load +} + +define void @global_store() #0 { + ; CHECK-LABEL: global_store: + ; CHECK: adrp [[REG0:x[0-9]+]], :got_auth:global + ; CHECK-NEXT: add [[REG0]], [[REG0]], :got_auth_lo12:global + ; CHECK-NEXT: ldr [[REG1:x[0-9]+]], [[[REG0]]] + ; CHECK-NEXT: autda [[REG1]], [[REG0]] + ; GISEL-NEXT: str wzr, [[[REG1]]] + ; DAGISEL-NEXT: mov w8, wzr + ; DAGISEL-NEXT: str w8, [[[REG1]]] + ; CHECK-NEXT: ret + store i32 0, ptr @global + ret void +} + +define ptr @func_addr() #0 { + ; CHECK-LABEL: func_addr: + ; CHECK: adrp [[REG:x[0-9]+]], :got_auth:func + ; CHECK-NEXT: add [[REG]], [[REG]], :got_auth_lo12:func + ; CHECK-NEXT: ldr x0, [[[REG]]] + ; CHECK-NEXT: autia x0, [[REG]] + ; CHECK-NEXT: ret + ret ptr @func +} + +attributes #0 = { "target-features"="+tagged-globals" } + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 256} diff --git a/llvm/test/MC/AArch64/adrp-auth-relocation.s b/llvm/test/MC/AArch64/adrp-auth-relocation.s new file mode 100644 index 0000000000000..57021c71632ff --- /dev/null +++ b/llvm/test/MC/AArch64/adrp-auth-relocation.s @@ -0,0 +1,12 @@ +// RUN: llvm-mc -triple=aarch64-linux-gnu -filetype=obj -o - %s | llvm-readobj -r - | FileCheck %s +// RUN: not llvm-mc -triple=aarch64-linux-gnu_ilp32 -filetype=obj \ +// RUN: -o /dev/null %s 2>&1 | FileCheck -check-prefix=CHECK-ILP32 %s + +.text +adrp x0, :got_auth:sym + +.global sym +sym: + +// CHECK: R_AARCH64_AUTH_ADR_GOT_PAGE sym +// CHECK-ILP32: error: ILP32 ADRP AUTH relocation not supported (LP64 eqv: AUTH_ADR_GOT_PAGE) diff --git a/llvm/test/MC/AArch64/arm64-elf-relocs.s b/llvm/test/MC/AArch64/arm64-elf-relocs.s index 8813c4bd7d1aa..f679bb4c82827 100644 --- a/llvm/test/MC/AArch64/arm64-elf-relocs.s +++ b/llvm/test/MC/AArch64/arm64-elf-relocs.s @@ -81,13 +81,17 @@ // CHECK: adrp x15, :got:sym // CHECK-OBJ-LP64: 58 R_AARCH64_ADR_GOT_PAGE sym + adrp x15, :got_auth:sym +// CHECK: adrp x15, :got_auth:sym +// CHECK-OBJ-LP64: 5c R_AARCH64_AUTH_ADR_GOT_PAGE sym + adrp x29, :gottprel:sym // CHECK: adrp x29, :gottprel:sym -// CHECK-OBJ-LP64: 5c R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 sym +// CHECK-OBJ-LP64: 60 R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 sym adrp x2, :tlsdesc:sym // CHECK: adrp x2, :tlsdesc:sym -// CHECK-OBJ-LP64: 60 R_AARCH64_TLSDESC_ADR_PAGE21 sym +// CHECK-OBJ-LP64: 64 R_AARCH64_TLSDESC_ADR_PAGE21 sym // LLVM is not competent enough to do this relocation because the // page boundary could occur anywhere after linking. A relocation @@ -96,7 +100,7 @@ .global trickQuestion trickQuestion: // CHECK: adrp x3, trickQuestion -// CHECK-OBJ-LP64: 64 R_AARCH64_ADR_PREL_PG_HI21 trickQuestion +// CHECK-OBJ-LP64: 68 R_AARCH64_ADR_PREL_PG_HI21 trickQuestion ldrb w2, [x3, :lo12:sym] ldrsb w5, [x7, #:lo12:sym] @@ -245,6 +249,16 @@ trickQuestion: // CHECK-OBJ-LP64: R_AARCH64_LD64_GOT_LO12_NC sym // CHECK-OBJ-LP64: R_AARCH64_LD64_GOT_LO12_NC sym+0x7 + ldr x24, [x23, #:got_auth_lo12:sym] + ldr d22, [x21, :got_auth_lo12:sym] + ldr x24, [x23, :got_auth_lo12:sym+7] +// CHECK: ldr x24, [x23, :got_auth_lo12:sym] +// CHECK: ldr d22, [x21, :got_auth_lo12:sym] +// CHECK: ldr x24, [x23, :got_auth_lo12:sym+7] +// CHECK-OBJ-LP64: R_AARCH64_AUTH_LD64_GOT_LO12_NC sym +// CHECK-OBJ-LP64: R_AARCH64_AUTH_LD64_GOT_LO12_NC sym +// CHECK-OBJ-LP64: R_AARCH64_AUTH_LD64_GOT_LO12_NC sym+0x7 + ldr x24, [x23, #:gotpage_lo15:sym] ldr d22, [x21, :gotpage_lo15:sym] ldr d22, [x23, :gotpage_lo15:sym+7] diff --git a/llvm/test/MC/AArch64/ilp32-diagnostics.s b/llvm/test/MC/AArch64/ilp32-diagnostics.s index 8a3bc1398e042..5d9c6e5626b2b 100644 --- a/llvm/test/MC/AArch64/ilp32-diagnostics.s +++ b/llvm/test/MC/AArch64/ilp32-diagnostics.s @@ -69,6 +69,12 @@ ldr x10, [x0, #:gottprel_lo12:var] ldr x24, [x23, #:got_lo12:sym] // ERROR: [[#@LINE-1]]:1: error: ILP32 64-bit load/store relocation not supported (LP64 eqv: LD64_GOT_LO12_NC) +ldr x24, [x23, #:got_auth_lo12:sym] +// ERROR: [[#@LINE-1]]:1: error: ILP32 64-bit load/store relocation not supported (LP64 eqv: AUTH_GOT_LO12_NC) + +add x24, x23, #:got_auth_lo12:sym +// ERROR: [[#@LINE-1]]:1: error: ILP32 ADD AUTH relocation not supported (LP64 eqv: AUTH_GOT_ADD_LO12_NC) + ldr x24, [x23, :gottprel_lo12:sym] // ERROR: [[#@LINE-1]]:1: error: ILP32 64-bit load/store relocation not supported (LP64 eqv: TLSIE_LD64_GOTTPREL_LO12_NC)