[llvm] 9dae7fc - [PAC][CodeGen][ELF][AArch64] Support signed GOT (#96164)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 7 01:53:03 PDT 2024
Author: Daniil Kovalev
Date: 2024-08-07T11:53:00+03:00
New Revision: 9dae7fcc927de7ae9878d4c32cb15770271fa8e3
URL: https://github.com/llvm/llvm-project/commit/9dae7fcc927de7ae9878d4c32cb15770271fa8e3
DIFF: https://github.com/llvm/llvm-project/commit/9dae7fcc927de7ae9878d4c32cb15770271fa8e3.diff
LOG: [PAC][CodeGen][ELF][AArch64] Support signed GOT (#96164)
Depends on #96158 and #96159
Support the following relocations and assembly operators:
- `R_AARCH64_AUTH_ADR_GOT_PAGE` (`:got_auth:` for `adrp`)
- `R_AARCH64_AUTH_LD64_GOT_LO12_NC` (`:got_auth_lo12:` for `ldr`)
- `R_AARCH64_AUTH_GOT_ADD_LO12_NC` (`:got_auth_lo12:` for `add`)
`LOADgotAUTH` pseudo-instruction is introduced which is later expanded
to actual instruction sequence like the following.
```
adrp x16, :got_auth:sym
add x16, x16, :got_auth_lo12:sym
ldr x0, [x16]
autia x0, x16
```
If a resign is requested, like below, `LOADgotPAC` pseudo is used, and
GOT load is lowered similarly to `LOADgotAUTH`.
```
@var = global i32 0
define ptr @resign_globalvar() {
ret ptr ptrauth (ptr @var, i32 3, i64 43)
}
```
Both SelectionDAG and GlobalISel are suppported. For FastISel, we fall
back to SelectionDAG.
Tests starting with 'ptrauth-' have corresponding variants w/o this
prefix.
See also specification
https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#appendix-signed-got
Added:
llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll
llvm/test/CodeGen/AArch64/ptrauth-elf-globals-pic.ll
llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll
llvm/test/CodeGen/AArch64/ptrauth-got-abuse.ll
llvm/test/CodeGen/AArch64/ptrauth-tagged-globals-pic.ll
llvm/test/MC/AArch64/adrp-auth-relocation.s
Modified:
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
llvm/lib/Target/AArch64/AArch64FastISel.cpp
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
llvm/lib/Target/AArch64/AArch64InstrInfo.td
llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp
llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h
llvm/test/MC/AArch64/arm64-elf-relocs.s
llvm/test/MC/AArch64/ilp32-diagnostics.s
Removed:
################################################################################
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<AArch64FunctionInfo>()
+ ->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<AArch64FunctionInfo>()->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<AArch64FunctionInfo>()
+ ->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<AArch64FunctionInfo>()->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<ConstantInt>(
+ 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<ConstantInt>(
+ 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<AArch64FunctionInfo>()->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<uint32_t>(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
+
+ at 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
+
+ at 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]]
+}
+
+ at 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
+}
+ at alias_func = alias void (), ptr @aliasee_func
+
+ at aliasee_global = global i32 42
+ at 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"
+
+ at 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)
More information about the llvm-commits
mailing list