From f78eb7279ebfec8845e1aa3b0052be9d66a1f2c8 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Fri, 3 May 2024 14:48:23 +0300 Subject: [PATCH 1/3] [PAC][llvm-readobj][ELF][AArch64] Define static AUTH TLSDESC relocations --- llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def | 3 +++ llvm/test/tools/llvm-readobj/ELF/reloc-types-aarch64.test | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def index ece8577fe219..53a3952f278e 100644 --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def @@ -158,6 +158,9 @@ ELF_RELOC(R_AARCH64_AUTH_GOT_LO12_NC, 0x811a) ELF_RELOC(R_AARCH64_AUTH_LD64_GOTPAGE_LO15, 0x811b) ELF_RELOC(R_AARCH64_AUTH_GOT_ADD_LO12_NC, 0x811c) ELF_RELOC(R_AARCH64_AUTH_GOT_ADR_PREL21, 0x811d) +ELF_RELOC(R_AARCH64_AUTH_TLSDESC_ADR_PAGE21, 0x811e) +ELF_RELOC(R_AARCH64_AUTH_TLSDESC_LD64_LO12, 0x811f) +ELF_RELOC(R_AARCH64_AUTH_TLSDESC_ADD_LO12, 0x8120) ELF_RELOC(R_AARCH64_AUTH_GLOB_DAT, 0xe201) ELF_RELOC(R_AARCH64_AUTH_TLSDESC, 0xe202) ELF_RELOC(R_AARCH64_AUTH_IRELATIVE, 0xe203) diff --git a/llvm/test/tools/llvm-readobj/ELF/reloc-types-aarch64.test b/llvm/test/tools/llvm-readobj/ELF/reloc-types-aarch64.test index 8111bfe71c10..0d11adf6a510 100644 --- a/llvm/test/tools/llvm-readobj/ELF/reloc-types-aarch64.test +++ b/llvm/test/tools/llvm-readobj/ELF/reloc-types-aarch64.test @@ -144,6 +144,9 @@ # CHECK: Type: R_AARCH64_AUTH_LD64_GOTPAGE_LO15 (33051) # CHECK: Type: R_AARCH64_AUTH_GOT_ADD_LO12_NC (33052) # CHECK: Type: R_AARCH64_AUTH_GOT_ADR_PREL21 (33053) +# CHECK: Type: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21 (33054) +# CHECK: Type: R_AARCH64_AUTH_TLSDESC_LD64_LO12 (33055) +# CHECK: Type: R_AARCH64_AUTH_TLSDESC_ADD_LO12 (33056) # CHECK: Type: R_AARCH64_AUTH_GLOB_DAT (57857) # CHECK: Type: R_AARCH64_AUTH_TLSDESC (57858) # CHECK: Type: R_AARCH64_AUTH_IRELATIVE (57859) @@ -298,6 +301,9 @@ Sections: - Type: R_AARCH64_AUTH_LD64_GOTPAGE_LO15 - Type: R_AARCH64_AUTH_GOT_ADD_LO12_NC - Type: R_AARCH64_AUTH_GOT_ADR_PREL21 + - Type: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21 + - Type: R_AARCH64_AUTH_TLSDESC_LD64_LO12 + - Type: R_AARCH64_AUTH_TLSDESC_ADD_LO12 - Type: R_AARCH64_AUTH_GLOB_DAT - Type: R_AARCH64_AUTH_TLSDESC - Type: R_AARCH64_AUTH_IRELATIVE From 80ad0bc774ad4888741f5d6fa70b411ea48d3567 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Fri, 3 May 2024 15:37:32 +0300 Subject: [PATCH 2/3] [PAC][CodeGen][ELF][AArch64] Support signed TLSDESC Support the following relocations and assembly operators: - `R_AARCH64_AUTH_TLSDESC_ADR_PAGE21` (`:tlsdesc_auth:` for `adrp`) - `R_AARCH64_AUTH_TLSDESC_LD64_LO12` (`:tlsdesc_auth_lo12:` for `ldr`) - `R_AARCH64_AUTH_TLSDESC_ADD_LO12` (`:tlsdesc_auth_lo12:` for `add`) `TLSDESC_AUTH_CALLSEQ` pseudo-instruction is introduced which is later expanded to actual instruction sequence like the following. ``` adrp x0, :tlsdesc:var ldr x16, [x0, #:tlsdesc_lo12:var] add x0, x0, #:tlsdesc_lo12:var autia x16, x0 .tlsdesccall var blr x16 (TPIDR_EL0 offset now in x0) ``` FIXME: use BLRAA instead of AUTIA + BLR. BLRAA is currently explicitly unsupported in AArch64SLSHardening pass. Only SelectionDAG ISel is supported. Tests with 'auth' in name have corresponding variants w/o it. --- llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 63 +++++++++ .../Target/AArch64/AArch64ISelLowering.cpp | 8 +- llvm/lib/Target/AArch64/AArch64ISelLowering.h | 1 + llvm/lib/Target/AArch64/AArch64InstrInfo.td | 14 ++ .../lib/Target/AArch64/AArch64MCInstLower.cpp | 12 +- .../AArch64/AsmParser/AArch64AsmParser.cpp | 109 ++++++++------- .../MCTargetDesc/AArch64ELFObjectWriter.cpp | 26 ++++ .../AArch64/MCTargetDesc/AArch64MCExpr.cpp | 3 + .../AArch64/MCTargetDesc/AArch64MCExpr.h | 127 +++++++++--------- .../AArch64/arm64-tls-dynamics-auth.ll | 87 ++++++++++++ llvm/test/MC/AArch64/arm64-elf-relocs.s | 55 +++++--- llvm/test/MC/AArch64/ilp32-diagnostics.s | 12 ++ 12 files changed, 382 insertions(+), 135 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/arm64-tls-dynamics-auth.ll diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index f6ccd0ecfdc8..459ec987a38c 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -1647,6 +1647,69 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) { EmitToStreamer(*OutStreamer, TmpInstSB); return; } + case AArch64::TLSDESC_AUTH_CALLSEQ: { + // FIXME: use BLRAA instead of AUTIA + BLR. BLRAA is currently explicitly + // unsupported in AArch64SLSHardening pass. + /// lower this to: + /// adrp x0, :tlsdesc:var + /// ldr x16, [x0, #:tlsdesc_lo12:var] + /// add x0, x0, #:tlsdesc_lo12:var + /// autia x16, x0 + /// .tlsdesccall var + /// blr x16 + /// (TPIDR_EL0 offset now in x0) + const MachineOperand &MO_Sym = MI->getOperand(0); + MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym); + MCOperand Sym, SymTLSDescLo12, SymTLSDesc; + MO_TLSDESC_LO12.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGEOFF); + MO_TLSDESC.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGE); + MCInstLowering.lowerOperand(MO_Sym, Sym); + MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12); + MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc); + + MCInst Adrp; + Adrp.setOpcode(AArch64::ADRP); + Adrp.addOperand(MCOperand::createReg(AArch64::X0)); + Adrp.addOperand(SymTLSDesc); + EmitToStreamer(*OutStreamer, Adrp); + + MCInst Ldr; + Ldr.setOpcode(AArch64::LDRXui); + Ldr.addOperand(MCOperand::createReg(AArch64::X16)); + Ldr.addOperand(MCOperand::createReg(AArch64::X0)); + Ldr.addOperand(SymTLSDescLo12); + Ldr.addOperand(MCOperand::createImm(0)); + EmitToStreamer(*OutStreamer, Ldr); + + MCInst Add; + Add.setOpcode(AArch64::ADDXri); + Add.addOperand(MCOperand::createReg(AArch64::X0)); + Add.addOperand(MCOperand::createReg(AArch64::X0)); + Add.addOperand(SymTLSDescLo12); + Add.addOperand(MCOperand::createImm(AArch64_AM::getShiftValue(0))); + EmitToStreamer(*OutStreamer, Add); + + MCInst Autia; + Autia.setOpcode(AArch64::AUTIA); + Autia.addOperand(MCOperand::createReg(AArch64::X16)); + Autia.addOperand(MCOperand::createReg(AArch64::X16)); + Autia.addOperand(MCOperand::createReg(AArch64::X0)); + EmitToStreamer(*OutStreamer, Autia); + + // Emit a relocation-annotation. This expands to no code, but requests + // the following instruction gets an R_AARCH64_TLSDESC_CALL. + MCInst TLSDescCall; + TLSDescCall.setOpcode(AArch64::TLSDESCCALL); + TLSDescCall.addOperand(Sym); + EmitToStreamer(*OutStreamer, TLSDescCall); + + MCInst Blr; + Blr.setOpcode(AArch64::BLR); + Blr.addOperand(MCOperand::createReg(AArch64::X16)); + EmitToStreamer(*OutStreamer, Blr); + + return; + } case AArch64::TLSDESC_CALLSEQ: { /// lower this to: /// adrp x0, :tlsdesc:var diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 04e5e84e1f19..2ab186dd4e9f 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -2428,6 +2428,7 @@ const char *AArch64TargetLowering::getTargetNodeName(unsigned Opcode) const { MAKE_CASE(AArch64ISD::CSINC) MAKE_CASE(AArch64ISD::THREAD_POINTER) MAKE_CASE(AArch64ISD::TLSDESC_CALLSEQ) + MAKE_CASE(AArch64ISD::TLSDESC_AUTH_CALLSEQ) MAKE_CASE(AArch64ISD::PROBED_ALLOCA) MAKE_CASE(AArch64ISD::ABDS_PRED) MAKE_CASE(AArch64ISD::ABDU_PRED) @@ -8984,8 +8985,11 @@ SDValue AArch64TargetLowering::LowerELFTLSDescCallSeq(SDValue SymAddr, SDValue Chain = DAG.getEntryNode(); SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); - Chain = - DAG.getNode(AArch64ISD::TLSDESC_CALLSEQ, DL, NodeTys, {Chain, SymAddr}); + unsigned Opcode = + DAG.getMachineFunction().getFunction().getParent()->hasELFSignedGOT() + ? AArch64ISD::TLSDESC_AUTH_CALLSEQ + : AArch64ISD::TLSDESC_CALLSEQ; + Chain = DAG.getNode(Opcode, DL, NodeTys, {Chain, SymAddr}); SDValue Glue = Chain.getValue(1); return DAG.getCopyFromReg(Chain, DL, AArch64::X0, PtrVT, Glue); diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h index db6e8a00d2fb..280e135536d4 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -72,6 +72,7 @@ enum NodeType : unsigned { // Produces the full sequence of instructions for getting the thread pointer // offset of a variable into X0, using the TLSDesc model. TLSDESC_CALLSEQ, + TLSDESC_AUTH_CALLSEQ, ADRP, // Page address of a TargetGlobalAddress operand. ADR, // ADR ADDlow, // Add the low 12 bits of a TargetGlobalAddress operand. diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index 25bf85ffbc14..87b4f2d50acc 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -431,6 +431,8 @@ def SDT_AArch64stnp : SDTypeProfile<0, 3, [SDTCisVT<0, v4i32>, SDTCisSameAs<0, 1 // number of operands (the variable) def SDT_AArch64TLSDescCallSeq : SDTypeProfile<0,1, [SDTCisPtrTy<0>]>; +def SDT_AArch64TLSDescAuthCallSeq : SDTypeProfile<0,1, + [SDTCisPtrTy<0>]>; def SDT_AArch64WrapperLarge : SDTypeProfile<1, 4, [SDTCisVT<0, i64>, SDTCisVT<1, i32>, @@ -785,6 +787,10 @@ def AArch64tlsdesc_callseq : SDNode<"AArch64ISD::TLSDESC_CALLSEQ", [SDNPInGlue, SDNPOutGlue, SDNPHasChain, SDNPVariadic]>; +def AArch64tlsdesc_auth_callseq : SDNode<"AArch64ISD::TLSDESC_AUTH_CALLSEQ", + SDT_AArch64TLSDescAuthCallSeq, + [SDNPInGlue, SDNPOutGlue, SDNPHasChain, + SDNPVariadic]>; def AArch64WrapperLarge : SDNode<"AArch64ISD::WrapperLarge", SDT_AArch64WrapperLarge>; @@ -2920,8 +2926,16 @@ def TLSDESC_CALLSEQ : Pseudo<(outs), (ins i64imm:$sym), [(AArch64tlsdesc_callseq tglobaltlsaddr:$sym)]>, Sched<[WriteI, WriteLD, WriteI, WriteBrReg]>; +let isCall = 1, Defs = [NZCV, LR, X0, X16], hasSideEffects = 1, Size = 20, + isCodeGenOnly = 1 in +def TLSDESC_AUTH_CALLSEQ + : Pseudo<(outs), (ins i64imm:$sym), + [(AArch64tlsdesc_auth_callseq tglobaltlsaddr:$sym)]>, + Sched<[WriteI, WriteLD, WriteI, WriteBrReg]>; def : Pat<(AArch64tlsdesc_callseq texternalsym:$sym), (TLSDESC_CALLSEQ texternalsym:$sym)>; +def : Pat<(AArch64tlsdesc_auth_callseq texternalsym:$sym), + (TLSDESC_AUTH_CALLSEQ texternalsym:$sym)>; //===----------------------------------------------------------------------===// // Conditional branch (immediate) instruction. diff --git a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp index 5870696c7219..7dc970265443 100644 --- a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp +++ b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp @@ -220,10 +220,18 @@ MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO, case TLSModel::LocalDynamic: RefFlags |= AArch64MCExpr::VK_DTPREL; break; - case TLSModel::GeneralDynamic: - RefFlags |= AArch64MCExpr::VK_TLSDESC; + case TLSModel::GeneralDynamic: { + // TODO: it's probably better to introduce MO_TLS_AUTH or smth and avoid + // running M->hasELFSignedGOT() every time, but existing flags already + // cover all 12 bits of SubReg_TargetFlags field in MachineOperand, and + // making the field wider breaks static assertions. + const Module *M = + MO.getParent()->getParent()->getParent()->getFunction().getParent(); + RefFlags |= M->hasELFSignedGOT() ? AArch64MCExpr::VK_TLSDESC_AUTH + : AArch64MCExpr::VK_TLSDESC; break; } + } } else if (MO.getTargetFlags() & AArch64II::MO_PREL) { RefFlags |= AArch64MCExpr::VK_PREL; } else { diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index fd4b98526711..7c12524eddaa 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -880,6 +880,7 @@ class AArch64Operand : public MCParsedAsmOperand { ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC || ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 || + ELFRefKind == AArch64MCExpr::VK_TLSDESC_AUTH_LO12 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12 || ELFRefKind == AArch64MCExpr::VK_GOT_PAGE_LO15) { @@ -997,6 +998,7 @@ class AArch64Operand : public MCParsedAsmOperand { ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 || + ELFRefKind == AArch64MCExpr::VK_TLSDESC_AUTH_LO12 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12; } @@ -3253,7 +3255,8 @@ ParseStatus AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) { ELFRefKind != AArch64MCExpr::VK_GOT_AUTH_PAGE && ELFRefKind != AArch64MCExpr::VK_GOT_PAGE_LO15 && ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE && - ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) { + ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE && + ELFRefKind != AArch64MCExpr::VK_TLSDESC_AUTH_PAGE) { // The operand must be an @page or @gotpage qualified symbolref. return Error(S, "page or gotpage label reference expected"); } @@ -4302,56 +4305,59 @@ bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) { return TokError("expect relocation specifier in operand after ':'"); std::string LowerCase = getTok().getIdentifier().lower(); - RefKind = StringSwitch(LowerCase) - .Case("lo12", AArch64MCExpr::VK_LO12) - .Case("abs_g3", AArch64MCExpr::VK_ABS_G3) - .Case("abs_g2", AArch64MCExpr::VK_ABS_G2) - .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S) - .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC) - .Case("abs_g1", AArch64MCExpr::VK_ABS_G1) - .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S) - .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC) - .Case("abs_g0", AArch64MCExpr::VK_ABS_G0) - .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S) - .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC) - .Case("prel_g3", AArch64MCExpr::VK_PREL_G3) - .Case("prel_g2", AArch64MCExpr::VK_PREL_G2) - .Case("prel_g2_nc", AArch64MCExpr::VK_PREL_G2_NC) - .Case("prel_g1", AArch64MCExpr::VK_PREL_G1) - .Case("prel_g1_nc", AArch64MCExpr::VK_PREL_G1_NC) - .Case("prel_g0", AArch64MCExpr::VK_PREL_G0) - .Case("prel_g0_nc", AArch64MCExpr::VK_PREL_G0_NC) - .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2) - .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1) - .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC) - .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0) - .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC) - .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12) - .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12) - .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC) - .Case("pg_hi21_nc", AArch64MCExpr::VK_ABS_PAGE_NC) - .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2) - .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1) - .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC) - .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0) - .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC) - .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12) - .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12) - .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC) - .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12) - .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) - .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC) - .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE) - .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12) - .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12) - .Default(AArch64MCExpr::VK_INVALID); + RefKind = + StringSwitch(LowerCase) + .Case("lo12", AArch64MCExpr::VK_LO12) + .Case("abs_g3", AArch64MCExpr::VK_ABS_G3) + .Case("abs_g2", AArch64MCExpr::VK_ABS_G2) + .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S) + .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC) + .Case("abs_g1", AArch64MCExpr::VK_ABS_G1) + .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S) + .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC) + .Case("abs_g0", AArch64MCExpr::VK_ABS_G0) + .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S) + .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC) + .Case("prel_g3", AArch64MCExpr::VK_PREL_G3) + .Case("prel_g2", AArch64MCExpr::VK_PREL_G2) + .Case("prel_g2_nc", AArch64MCExpr::VK_PREL_G2_NC) + .Case("prel_g1", AArch64MCExpr::VK_PREL_G1) + .Case("prel_g1_nc", AArch64MCExpr::VK_PREL_G1_NC) + .Case("prel_g0", AArch64MCExpr::VK_PREL_G0) + .Case("prel_g0_nc", AArch64MCExpr::VK_PREL_G0_NC) + .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2) + .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1) + .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC) + .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0) + .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC) + .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12) + .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12) + .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC) + .Case("pg_hi21_nc", AArch64MCExpr::VK_ABS_PAGE_NC) + .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2) + .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1) + .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC) + .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0) + .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC) + .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12) + .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12) + .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC) + .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12) + .Case("tlsdesc_auth_lo12", AArch64MCExpr::VK_TLSDESC_AUTH_LO12) + .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) + .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC) + .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE) + .Case("tlsdesc_auth", AArch64MCExpr::VK_TLSDESC_AUTH_PAGE) + .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12) + .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12) + .Default(AArch64MCExpr::VK_INVALID); if (RefKind == AArch64MCExpr::VK_INVALID) return TokError("expect relocation specifier in operand after ':'"); @@ -5701,6 +5707,7 @@ bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc, ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 || + ELFRefKind == AArch64MCExpr::VK_TLSDESC_AUTH_LO12 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) && (Inst.getOpcode() == AArch64::ADDXri || diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp index 6a583681e7a8..a3dc6a6e64df 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp @@ -190,6 +190,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx, return R_CLS(TLSIE_ADR_GOTTPREL_PAGE21); if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC) return R_CLS(TLSDESC_ADR_PAGE21); + if (SymLoc == AArch64MCExpr::VK_TLSDESC_AUTH && !IsNC) { + if (IsILP32) { + Ctx.reportError(Fixup.getLoc(), + "ILP32 ADRP AUTH relocation not supported " + "(LP64 eqv: AUTH_TLSDESC_ADR_PAGE21)"); + return ELF::R_AARCH64_NONE; + } + return ELF::R_AARCH64_AUTH_TLSDESC_ADR_PAGE21; + } Ctx.reportError(Fixup.getLoc(), "invalid symbol kind for ADRP relocation"); return ELF::R_AARCH64_NONE; @@ -265,6 +274,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_TLSDESC_AUTH_LO12) { + if (IsILP32) { + Ctx.reportError(Fixup.getLoc(), + "ILP32 ADD AUTH relocation not supported " + "(LP64 eqv: AUTH_TLSDESC_ADD_LO12)"); + return ELF::R_AARCH64_NONE; + } + return ELF::R_AARCH64_AUTH_TLSDESC_ADD_LO12; + } if (RefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 && IsNC) { if (IsILP32) { Ctx.reportError(Fixup.getLoc(), @@ -420,6 +438,14 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx, return ELF::R_AARCH64_NONE; } } + if (SymLoc == AArch64MCExpr::VK_TLSDESC_AUTH) { + if (!IsILP32) + return ELF::R_AARCH64_AUTH_TLSDESC_LD64_LO12; + Ctx.reportError(Fixup.getLoc(), "ILP32 64-bit load/store AUTH " + "relocation not supported (LP64 eqv: " + "AUTH_TLSDESC_LD64_LO12)"); + return ELF::R_AARCH64_NONE; + } Ctx.reportError(Fixup.getLoc(), "invalid fixup for 64-bit load/store instruction"); return ELF::R_AARCH64_NONE; diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp index 768170281a05..20bb7fbd23d0 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp @@ -68,6 +68,7 @@ StringRef AArch64MCExpr::getVariantKindName() const { case VK_TPREL_LO12: return ":tprel_lo12:"; case VK_TPREL_LO12_NC: return ":tprel_lo12_nc:"; case VK_TLSDESC_LO12: return ":tlsdesc_lo12:"; + case VK_TLSDESC_AUTH_LO12: return ":tlsdesc_auth_lo12:"; case VK_ABS_PAGE: return ""; case VK_ABS_PAGE_NC: return ":pg_hi21_nc:"; case VK_GOT: return ":got:"; @@ -81,6 +82,8 @@ StringRef AArch64MCExpr::getVariantKindName() const { case VK_GOTTPREL_G0_NC: return ":gottprel_g0_nc:"; case VK_TLSDESC: return ""; case VK_TLSDESC_PAGE: return ":tlsdesc:"; + case VK_TLSDESC_AUTH: return ""; + case VK_TLSDESC_AUTH_PAGE: return ":tlsdesc_auth:"; case VK_SECREL_LO12: return ":secrel_lo12:"; case VK_SECREL_HI12: return ":secrel_hi12:"; case VK_GOT_AUTH: return ":got_auth:"; diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h index 780ae39c15a7..6be2e86139f3 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h @@ -28,19 +28,20 @@ class AArch64MCExpr : public MCTargetExpr { // 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, ... - VK_ABS = 0x001, - VK_SABS = 0x002, - VK_PREL = 0x003, - VK_GOT = 0x004, - VK_DTPREL = 0x005, - VK_GOTTPREL = 0x006, - VK_TPREL = 0x007, - VK_TLSDESC = 0x008, - VK_SECREL = 0x009, - VK_AUTH = 0x00a, - VK_AUTHADDR = 0x00b, - VK_GOT_AUTH = 0x00c, - VK_SymLocBits = 0x00f, + VK_ABS = 0x001, + VK_SABS = 0x002, + VK_PREL = 0x003, + VK_GOT = 0x004, + VK_DTPREL = 0x005, + VK_GOTTPREL = 0x006, + VK_TPREL = 0x007, + VK_TLSDESC = 0x008, + VK_SECREL = 0x009, + VK_AUTH = 0x00a, + VK_AUTHADDR = 0x00b, + VK_GOT_AUTH = 0x00c, + VK_TLSDESC_AUTH = 0x00d, + VK_SymLocBits = 0x00f, // Variants specifying which part of the final address calculation is // used. E.g. the low 12 bits for an ADD/LDR, the middle 16 bits for a @@ -67,55 +68,57 @@ class AArch64MCExpr : public MCTargetExpr { // omitted in line with assembly syntax here (VK_LO12 rather than VK_LO12_NC // since a user would write ":lo12:"). VK_CALL = VK_ABS, - VK_ABS_PAGE = VK_ABS | VK_PAGE, - VK_ABS_PAGE_NC = VK_ABS | VK_PAGE | VK_NC, - VK_ABS_G3 = VK_ABS | VK_G3, - VK_ABS_G2 = VK_ABS | VK_G2, - VK_ABS_G2_S = VK_SABS | VK_G2, - VK_ABS_G2_NC = VK_ABS | VK_G2 | VK_NC, - VK_ABS_G1 = VK_ABS | VK_G1, - VK_ABS_G1_S = VK_SABS | VK_G1, - VK_ABS_G1_NC = VK_ABS | VK_G1 | VK_NC, - VK_ABS_G0 = VK_ABS | VK_G0, - VK_ABS_G0_S = VK_SABS | VK_G0, - VK_ABS_G0_NC = VK_ABS | VK_G0 | VK_NC, - VK_LO12 = VK_ABS | VK_PAGEOFF | VK_NC, - VK_PREL_G3 = VK_PREL | VK_G3, - VK_PREL_G2 = VK_PREL | VK_G2, - VK_PREL_G2_NC = VK_PREL | VK_G2 | VK_NC, - VK_PREL_G1 = VK_PREL | VK_G1, - VK_PREL_G1_NC = VK_PREL | VK_G1 | VK_NC, - VK_PREL_G0 = VK_PREL | VK_G0, - VK_PREL_G0_NC = VK_PREL | VK_G0 | VK_NC, - 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, - VK_DTPREL_G0 = VK_DTPREL | VK_G0, - VK_DTPREL_G0_NC = VK_DTPREL | VK_G0 | VK_NC, - VK_DTPREL_HI12 = VK_DTPREL | VK_HI12, - VK_DTPREL_LO12 = VK_DTPREL | VK_PAGEOFF, - VK_DTPREL_LO12_NC = VK_DTPREL | VK_PAGEOFF | VK_NC, - VK_GOTTPREL_PAGE = VK_GOTTPREL | VK_PAGE, - VK_GOTTPREL_LO12_NC = VK_GOTTPREL | VK_PAGEOFF | VK_NC, - VK_GOTTPREL_G1 = VK_GOTTPREL | VK_G1, - VK_GOTTPREL_G0_NC = VK_GOTTPREL | VK_G0 | VK_NC, - VK_TPREL_G2 = VK_TPREL | VK_G2, - VK_TPREL_G1 = VK_TPREL | VK_G1, - VK_TPREL_G1_NC = VK_TPREL | VK_G1 | VK_NC, - VK_TPREL_G0 = VK_TPREL | VK_G0, - VK_TPREL_G0_NC = VK_TPREL | VK_G0 | VK_NC, - VK_TPREL_HI12 = VK_TPREL | VK_HI12, - VK_TPREL_LO12 = VK_TPREL | VK_PAGEOFF, - VK_TPREL_LO12_NC = VK_TPREL | VK_PAGEOFF | VK_NC, - VK_TLSDESC_LO12 = VK_TLSDESC | VK_PAGEOFF, - VK_TLSDESC_PAGE = VK_TLSDESC | VK_PAGE, - VK_SECREL_LO12 = VK_SECREL | VK_PAGEOFF, - VK_SECREL_HI12 = VK_SECREL | VK_HI12, + VK_ABS_PAGE = VK_ABS | VK_PAGE, + VK_ABS_PAGE_NC = VK_ABS | VK_PAGE | VK_NC, + VK_ABS_G3 = VK_ABS | VK_G3, + VK_ABS_G2 = VK_ABS | VK_G2, + VK_ABS_G2_S = VK_SABS | VK_G2, + VK_ABS_G2_NC = VK_ABS | VK_G2 | VK_NC, + VK_ABS_G1 = VK_ABS | VK_G1, + VK_ABS_G1_S = VK_SABS | VK_G1, + VK_ABS_G1_NC = VK_ABS | VK_G1 | VK_NC, + VK_ABS_G0 = VK_ABS | VK_G0, + VK_ABS_G0_S = VK_SABS | VK_G0, + VK_ABS_G0_NC = VK_ABS | VK_G0 | VK_NC, + VK_LO12 = VK_ABS | VK_PAGEOFF | VK_NC, + VK_PREL_G3 = VK_PREL | VK_G3, + VK_PREL_G2 = VK_PREL | VK_G2, + VK_PREL_G2_NC = VK_PREL | VK_G2 | VK_NC, + VK_PREL_G1 = VK_PREL | VK_G1, + VK_PREL_G1_NC = VK_PREL | VK_G1 | VK_NC, + VK_PREL_G0 = VK_PREL | VK_G0, + VK_PREL_G0_NC = VK_PREL | VK_G0 | VK_NC, + 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, + VK_DTPREL_G0 = VK_DTPREL | VK_G0, + VK_DTPREL_G0_NC = VK_DTPREL | VK_G0 | VK_NC, + VK_DTPREL_HI12 = VK_DTPREL | VK_HI12, + VK_DTPREL_LO12 = VK_DTPREL | VK_PAGEOFF, + VK_DTPREL_LO12_NC = VK_DTPREL | VK_PAGEOFF | VK_NC, + VK_GOTTPREL_PAGE = VK_GOTTPREL | VK_PAGE, + VK_GOTTPREL_LO12_NC = VK_GOTTPREL | VK_PAGEOFF | VK_NC, + VK_GOTTPREL_G1 = VK_GOTTPREL | VK_G1, + VK_GOTTPREL_G0_NC = VK_GOTTPREL | VK_G0 | VK_NC, + VK_TPREL_G2 = VK_TPREL | VK_G2, + VK_TPREL_G1 = VK_TPREL | VK_G1, + VK_TPREL_G1_NC = VK_TPREL | VK_G1 | VK_NC, + VK_TPREL_G0 = VK_TPREL | VK_G0, + VK_TPREL_G0_NC = VK_TPREL | VK_G0 | VK_NC, + VK_TPREL_HI12 = VK_TPREL | VK_HI12, + VK_TPREL_LO12 = VK_TPREL | VK_PAGEOFF, + VK_TPREL_LO12_NC = VK_TPREL | VK_PAGEOFF | VK_NC, + VK_TLSDESC_LO12 = VK_TLSDESC | VK_PAGEOFF, + VK_TLSDESC_PAGE = VK_TLSDESC | VK_PAGE, + VK_TLSDESC_AUTH_LO12 = VK_TLSDESC_AUTH | VK_PAGEOFF, + VK_TLSDESC_AUTH_PAGE = VK_TLSDESC_AUTH | VK_PAGE, + VK_SECREL_LO12 = VK_SECREL | VK_PAGEOFF, + VK_SECREL_HI12 = VK_SECREL | VK_HI12, VK_INVALID = 0xfff // clang-format on diff --git a/llvm/test/CodeGen/AArch64/arm64-tls-dynamics-auth.ll b/llvm/test/CodeGen/AArch64/arm64-tls-dynamics-auth.ll new file mode 100644 index 000000000000..d3bb026b0869 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/arm64-tls-dynamics-auth.ll @@ -0,0 +1,87 @@ +; RUN: llc -mtriple=arm64-none-linux-gnu -mattr=+pauth -relocation-model=pic \ +; RUN: -verify-machineinstrs < %s | FileCheck %s +; RUN: llc -mtriple=arm64-none-linux-gnu -mattr=+pauth -relocation-model=pic \ +; RUN: -filetype=obj < %s | llvm-objdump -r - | FileCheck --check-prefix=CHECK-RELOC %s +; RUN: not --crash llc -mtriple=arm64-none-linux-gnu -mattr=+pauth -relocation-model=pic \ +; RUN: -global-isel=1 < %s 2>&1 | FileCheck --check-prefix=CHECK-ERR %s + +@general_dynamic_var = external thread_local global i32 + +define i32 @test_generaldynamic() { +; CHECK-LABEL: test_generaldynamic: + + %val = load i32, ptr @general_dynamic_var + ret i32 %val + +; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc_auth:general_dynamic_var +; CHECK-NEXT: ldr x16, [x[[TLSDESC_HI]], :tlsdesc_auth_lo12:general_dynamic_var] +; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_auth_lo12:general_dynamic_var +; CHECK-NEXT: autia x16, x0 +; CHECK-NEXT: .tlsdesccall general_dynamic_var +; CHECK-NEXT: blr x16 + +; CHECK-RELOC: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21 +; CHECK-RELOC: R_AARCH64_AUTH_TLSDESC_LD64_LO12 +; CHECK-RELOC: R_AARCH64_AUTH_TLSDESC_ADD_LO12 +; CHECK-RELOC: R_AARCH64_TLSDESC_CALL + +; CHECK-ERR: LLVM ERROR: cannot select: %1:gpr64sp(p0) = G_GLOBAL_VALUE @general_dynamic_var (in function: test_generaldynamic) +} + +define ptr @test_generaldynamic_addr() { +; CHECK-LABEL: test_generaldynamic_addr: + + ret ptr @general_dynamic_var + +; CHECK-RELOC: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21 +; CHECK-RELOC: R_AARCH64_AUTH_TLSDESC_LD64_LO12 +; CHECK-RELOC: R_AARCH64_AUTH_TLSDESC_ADD_LO12 +; CHECK-RELOC: R_AARCH64_TLSDESC_CALL +} + +@local_dynamic_var = external thread_local(localdynamic) global i32 + +define i32 @test_localdynamic() { +; CHECK-LABEL: test_localdynamic: + + %val = load i32, ptr @local_dynamic_var + ret i32 %val + +; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc_auth:local_dynamic_var +; CHECK-NEXT: ldr x16, [x[[TLSDESC_HI]], :tlsdesc_auth_lo12:local_dynamic_var] +; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_auth_lo12:local_dynamic_var +; CHECK-NEXT: autia x16, x0 +; CHECK-NEXT: .tlsdesccall local_dynamic_var +; CHECK-NEXT: blr x16 +; CHECK: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0 +; CHECK: ldr w0, [x[[TPIDR]], x0] + +; CHECK-RELOC: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21 +; CHECK-RELOC: R_AARCH64_AUTH_TLSDESC_LD64_LO12 +; CHECK-RELOC: R_AARCH64_AUTH_TLSDESC_ADD_LO12 +; CHECK-RELOC: R_AARCH64_TLSDESC_CALL +} + +define ptr @test_localdynamic_addr() { +; CHECK-LABEL: test_localdynamic_addr: + + ret ptr @local_dynamic_var + +; CHECK: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc_auth:local_dynamic_var +; CHECK-NEXT: ldr x16, [x[[TLSDESC_HI]], :tlsdesc_auth_lo12:local_dynamic_var] +; CHECK-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_auth_lo12:local_dynamic_var +; CHECK-NEXT: autia x16, x0 +; CHECK-NEXT: .tlsdesccall local_dynamic_var +; CHECK-NEXT: blr x16 +; CHECK: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0 +; CHECK: add x0, x[[TPIDR]], x0 + +; CHECK-RELOC: R_AARCH64_AUTH_TLSDESC_ADR_PAGE21 +; CHECK-RELOC: R_AARCH64_AUTH_TLSDESC_LD64_LO12 +; CHECK-RELOC: R_AARCH64_AUTH_TLSDESC_ADD_LO12 +; CHECK-RELOC: R_AARCH64_TLSDESC_CALL +} + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 128} diff --git a/llvm/test/MC/AArch64/arm64-elf-relocs.s b/llvm/test/MC/AArch64/arm64-elf-relocs.s index 3e7bd1492016..6ab4b5bacb83 100644 --- a/llvm/test/MC/AArch64/arm64-elf-relocs.s +++ b/llvm/test/MC/AArch64/arm64-elf-relocs.s @@ -35,63 +35,75 @@ // CHECK: add x5, x0, :tlsdesc_lo12:sym // CHECK-OBJ-LP64: 1c R_AARCH64_TLSDESC_ADD_LO12 sym + add x5, x0, #:tlsdesc_auth_lo12:sym +// CHECK: add x5, x0, :tlsdesc_auth_lo12:sym +// CHECK-OBJ-LP64: 20 R_AARCH64_AUTH_TLSDESC_ADD_LO12 sym + add x0, x2, #:lo12:sym+8 // CHECK: add x0, x2, :lo12:sym -// CHECK-OBJ-LP64: 20 R_AARCH64_ADD_ABS_LO12_NC sym+0x8 +// CHECK-OBJ-LP64: 24 R_AARCH64_ADD_ABS_LO12_NC sym+0x8 add x5, x7, #:dtprel_lo12:sym+1 // CHECK: add x5, x7, :dtprel_lo12:sym+1 -// CHECK-OBJ-LP64: 24 R_AARCH64_TLSLD_ADD_DTPREL_LO12 sym+0x1 +// CHECK-OBJ-LP64: 28 R_AARCH64_TLSLD_ADD_DTPREL_LO12 sym+0x1 add x9, x12, #:dtprel_lo12_nc:sym+2 // CHECK: add x9, x12, :dtprel_lo12_nc:sym+2 -// CHECK-OBJ-LP64: 28 R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC sym+0x2 +// CHECK-OBJ-LP64: 2c R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC sym+0x2 add x20, x30, #:tprel_lo12:sym+12 // CHECK: add x20, x30, :tprel_lo12:sym+12 -// CHECK-OBJ-LP64: 2c R_AARCH64_TLSLE_ADD_TPREL_LO12 sym+0xc +// CHECK-OBJ-LP64: 30 R_AARCH64_TLSLE_ADD_TPREL_LO12 sym+0xc add x9, x12, #:tprel_lo12_nc:sym+54 // CHECK: add x9, x12, :tprel_lo12_nc:sym+54 -// CHECK-OBJ-LP64: 30 R_AARCH64_TLSLE_ADD_TPREL_LO12_NC sym+0x36 +// CHECK-OBJ-LP64: 34 R_AARCH64_TLSLE_ADD_TPREL_LO12_NC sym+0x36 add x5, x0, #:tlsdesc_lo12:sym+70 // CHECK: add x5, x0, :tlsdesc_lo12:sym+70 -// CHECK-OBJ-LP64: 34 R_AARCH64_TLSDESC_ADD_LO12 sym+0x46 +// CHECK-OBJ-LP64: 38 R_AARCH64_TLSDESC_ADD_LO12 sym+0x46 + + add x5, x0, #:tlsdesc_auth_lo12:sym+70 +// CHECK: add x5, x0, :tlsdesc_auth_lo12:sym+70 +// CHECK-OBJ-LP64: 3c R_AARCH64_AUTH_TLSDESC_ADD_LO12 sym+0x46 .hword sym + 4 - . -// CHECK-OBJ-LP64: 38 R_AARCH64_PREL16 sym+0x4 +// CHECK-OBJ-LP64: 40 R_AARCH64_PREL16 sym+0x4 .word sym - . + 8 -// CHECK-OBJ-LP64: 3a R_AARCH64_PREL32 sym+0x8 +// CHECK-OBJ-LP64: 42 R_AARCH64_PREL32 sym+0x8 .xword sym-. -// CHECK-OBJ-LP64: 3e R_AARCH64_PREL64 sym{{$}} +// CHECK-OBJ-LP64: 46 R_AARCH64_PREL64 sym{{$}} .hword sym -// CHECK-OBJ-LP64: 46 R_AARCH64_ABS16 sym +// CHECK-OBJ-LP64: 4e R_AARCH64_ABS16 sym .word sym+1 -// CHECK-OBJ-LP64: 48 R_AARCH64_ABS32 sym+0x1 +// CHECK-OBJ-LP64: 50 R_AARCH64_ABS32 sym+0x1 .xword sym+16 -// CHECK-OBJ-LP64: 4c R_AARCH64_ABS64 sym+0x10 +// CHECK-OBJ-LP64: 54 R_AARCH64_ABS64 sym+0x10 adrp x0, sym // CHECK: adrp x0, sym -// CHECK-OBJ-LP64: 54 R_AARCH64_ADR_PREL_PG_HI21 sym +// CHECK-OBJ-LP64: 5c R_AARCH64_ADR_PREL_PG_HI21 sym adrp x15, :got:sym // CHECK: adrp x15, :got:sym -// CHECK-OBJ-LP64: 58 R_AARCH64_ADR_GOT_PAGE sym +// CHECK-OBJ-LP64: 60 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 +// CHECK-OBJ-LP64: 64 R_AARCH64_AUTH_ADR_GOT_PAGE sym adrp x29, :gottprel:sym // CHECK: adrp x29, :gottprel:sym -// CHECK-OBJ-LP64: 60 R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 sym +// CHECK-OBJ-LP64: 68 R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 sym adrp x2, :tlsdesc:sym // CHECK: adrp x2, :tlsdesc:sym -// CHECK-OBJ-LP64: 64 R_AARCH64_TLSDESC_ADR_PAGE21 sym +// CHECK-OBJ-LP64: 6c R_AARCH64_TLSDESC_ADR_PAGE21 sym + + adrp x2, :tlsdesc_auth:sym +// CHECK: adrp x2, :tlsdesc_auth:sym +// CHECK-OBJ-LP64: 70 R_AARCH64_AUTH_TLSDESC_ADR_PAGE21 sym // LLVM is not competent enough to do this relocation because the // page boundary could occur anywhere after linking. A relocation @@ -100,7 +112,7 @@ .global trickQuestion trickQuestion: // CHECK: adrp x3, trickQuestion -// CHECK-OBJ-LP64: 68 R_AARCH64_ADR_PREL_PG_HI21 trickQuestion +// CHECK-OBJ-LP64: 74 R_AARCH64_ADR_PREL_PG_HI21 trickQuestion ldrb w2, [x3, :lo12:sym] ldrsb w5, [x7, #:lo12:sym] @@ -311,6 +323,13 @@ trickQuestion: // CHECK-OBJ-LP64: R_AARCH64_TLSDESC_LD64_LO12 sym // CHECK-OBJ-LP64: R_AARCH64_TLSDESC_LD64_LO12 sym + ldr x24, [x23, #:tlsdesc_auth_lo12:sym] + ldr d22, [x21, :tlsdesc_auth_lo12:sym] +// CHECK: ldr x24, [x23, :tlsdesc_auth_lo12:sym] +// CHECK: ldr d22, [x21, :tlsdesc_auth_lo12:sym] +// CHECK-OBJ-LP64: R_AARCH64_AUTH_TLSDESC_LD64_LO12 sym +// CHECK-OBJ-LP64: R_AARCH64_AUTH_TLSDESC_LD64_LO12 sym + ldr q20, [x19, #:lo12:sym] // CHECK: ldr q20, [x19, :lo12:sym] // CHECK-OBJ-LP64: R_AARCH64_LDST128_ABS_LO12_NC sym diff --git a/llvm/test/MC/AArch64/ilp32-diagnostics.s b/llvm/test/MC/AArch64/ilp32-diagnostics.s index 472c140ea36a..2926a332220f 100644 --- a/llvm/test/MC/AArch64/ilp32-diagnostics.s +++ b/llvm/test/MC/AArch64/ilp32-diagnostics.s @@ -118,4 +118,16 @@ adr x24, :got_auth:sym // CHECK-ERROR: error: ILP32 ADR AUTH relocation not supported (LP64 eqv: AUTH_GOT_ADR_PREL21) +// CHECK-ERROR: ^ + + adrp x24, :tlsdesc_auth:sym +// CHECK-ERROR: error: ILP32 ADRP AUTH relocation not supported (LP64 eqv: AUTH_TLSDESC_ADR_PAGE21) +// CHECK-ERROR: ^ + + ldr x24, [x23, :tlsdesc_auth_lo12:sym] +// CHECK-ERROR: error: ILP32 64-bit load/store AUTH relocation not supported (LP64 eqv: AUTH_TLSDESC_LD64_LO12) +// CHECK-ERROR: ^ + + add x24, x23, :tlsdesc_auth_lo12:sym +// CHECK-ERROR: error: ILP32 ADD AUTH relocation not supported (LP64 eqv: AUTH_TLSDESC_ADD_LO12) // CHECK-ERROR: ^ From 7c1225eed3f6a20b0e9ccf8f2f645676b3e0231d Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Fri, 3 May 2024 15:19:25 +0300 Subject: [PATCH 3/3] [PAC][lld][AArch64][ELF] Support signed TLSDESC Support `R_AARCH64_AUTH_TLSDESC_ADR_PAGE21`, `R_AARCH64_AUTH_TLSDESC_LD64_LO12` and `R_AARCH64_AUTH_TLSDESC_LD64_LO12` static TLSDESC relocations. --- lld/ELF/Arch/AArch64.cpp | 8 +++ lld/ELF/InputSection.cpp | 2 + lld/ELF/Relocations.cpp | 25 +++++-- lld/ELF/Relocations.h | 4 ++ lld/ELF/Symbols.h | 1 + lld/ELF/SyntheticSections.cpp | 5 ++ lld/test/ELF/aarch64-tlsdesc-auth.s | 106 ++++++++++++++++++++++++++++ 7 files changed, 146 insertions(+), 5 deletions(-) create mode 100644 lld/test/ELF/aarch64-tlsdesc-auth.s diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index d10f8177c60d..1310a0f3b91e 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -124,9 +124,14 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s, return R_AARCH64_AUTH; case R_AARCH64_TLSDESC_ADR_PAGE21: return R_AARCH64_TLSDESC_PAGE; + case R_AARCH64_AUTH_TLSDESC_ADR_PAGE21: + return R_AARCH64_AUTH_TLSDESC_PAGE; case R_AARCH64_TLSDESC_LD64_LO12: case R_AARCH64_TLSDESC_ADD_LO12: return R_TLSDESC; + case R_AARCH64_AUTH_TLSDESC_LD64_LO12: + case R_AARCH64_AUTH_TLSDESC_ADD_LO12: + return RelExpr::R_AARCH64_AUTH_TLSDESC; case R_AARCH64_TLSDESC_CALL: return R_TLSDESC_CALL; case R_AARCH64_TLSLE_ADD_TPREL_HI12: @@ -446,6 +451,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, case R_AARCH64_ADR_PREL_PG_HI21: case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: case R_AARCH64_TLSDESC_ADR_PAGE21: + case R_AARCH64_AUTH_TLSDESC_ADR_PAGE21: checkInt(loc, val, 33, rel); [[fallthrough]]; case R_AARCH64_ADR_PREL_PG_HI21_NC: @@ -497,6 +503,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: case R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC: case R_AARCH64_TLSDESC_LD64_LO12: + case R_AARCH64_AUTH_TLSDESC_LD64_LO12: checkAlignment(loc, val, 8, rel); or32AArch64Imm(loc, getBits(val, 3, 11)); break; @@ -569,6 +576,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, break; case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: case R_AARCH64_TLSDESC_ADD_LO12: + case R_AARCH64_AUTH_TLSDESC_ADD_LO12: or32AArch64Imm(loc, val); break; case R_AARCH64_TLSDESC: diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 0ecbc928bff8..c1c6fa64355e 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -870,12 +870,14 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type, case R_SIZE: return sym.getSize() + a; case R_TLSDESC: + case RelExpr::R_AARCH64_AUTH_TLSDESC: return in.got->getTlsDescAddr(sym) + a; case R_TLSDESC_PC: return in.got->getTlsDescAddr(sym) + a - p; case R_TLSDESC_GOTPLT: return in.got->getTlsDescAddr(sym) + a - in.gotPlt->getVA(); case R_AARCH64_TLSDESC_PAGE: + case R_AARCH64_AUTH_TLSDESC_PAGE: return getAArch64Page(in.got->getTlsDescAddr(sym) + a) - getAArch64Page(p); case R_TLSGD_GOT: return in.got->getGlobalDynOffset(sym) + a; diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 550d1a538281..d32da4df10de 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1324,14 +1324,25 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym, return handleMipsTlsRelocation(type, sym, c, offset, addend, expr); bool isRISCV = config->emachine == EM_RISCV; - if (oneof(expr) && config->shared) { // R_RISCV_TLSDESC_{LOAD_LO12,ADD_LO12_I,CALL} reference a label. Do not // set NEEDS_TLSDESC on the label. if (expr != R_TLSDESC_CALL) { - if (!isRISCV || type == R_RISCV_TLSDESC_HI20) - sym.setFlags(NEEDS_TLSDESC); + bool needsTlsDescAuth = + (expr == R_AARCH64_AUTH_TLSDESC_PAGE || expr == RelExpr::R_AARCH64_AUTH_TLSDESC); + if (!sym.hasFlag(NEEDS_TLSDESC)) { + if (!isRISCV || type == R_RISCV_TLSDESC_HI20) + sym.setFlags(NEEDS_TLSDESC); + if (needsTlsDescAuth) + sym.setFlags(NEEDS_TLSDESC_AUTH); + } else if (needsTlsDescAuth != sym.hasFlag(NEEDS_TLSDESC_AUTH)) { + fatal("both AUTH and non-AUTH TLSDESC entries for '" + sym.getName() + + "' requested, but only one type of TLSDESC entry per symbol is " + "supported"); + } c.addReloc({expr, type, offset, addend, &sym}); } return 1; @@ -1788,9 +1799,13 @@ void elf::postScanRelocations() { if (flags & NEEDS_TLSDESC) { got->addTlsDescEntry(sym); + RelType tlsDescRel = target->tlsDescRel; + if (flags & NEEDS_TLSDESC_AUTH) { + assert(config->emachine == EM_AARCH64); + tlsDescRel = ELF::R_AARCH64_AUTH_TLSDESC; + } mainPart->relaDyn->addAddendOnlyRelocIfNonPreemptible( - target->tlsDescRel, *got, got->getTlsDescOffset(sym), sym, - target->tlsDescRel); + tlsDescRel, *got, got->getTlsDescOffset(sym), sym, tlsDescRel); } if (flags & NEEDS_TLSGD) { got->addDynTlsEntry(sym); diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h index 692476a98d78..dc0784f9288b 100644 --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -90,6 +90,10 @@ enum RelExpr { R_AARCH64_PAGE_PC, R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC, R_AARCH64_TLSDESC_PAGE, + R_AARCH64_AUTH_TLSDESC_PAGE, + // TODO: maybe it's better to rename this expression + // to avoid name conflict with dynamic reloc + R_AARCH64_AUTH_TLSDESC, R_AARCH64_AUTH, R_ARM_PCA, R_ARM_SBREL, diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index c8aa3d937af0..67affa3cdf9a 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -55,6 +55,7 @@ enum { NEEDS_GOT_DTPREL = 1 << 7, NEEDS_TLSIE = 1 << 8, NEEDS_GOT_AUTH = 1 << 9, + NEEDS_TLSDESC_AUTH = 1 << 10, }; // Some index properties of a symbol are stored separately in this auxiliary diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 2b4219344081..3f1573ca3ecd 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -665,6 +665,11 @@ bool GotSection::addTlsDescEntry(const Symbol &sym) { assert(sym.auxIdx == symAux.size() - 1); symAux.back().tlsDescIdx = numEntries; numEntries += 2; + if (sym.hasFlag(NEEDS_TLSDESC_AUTH)) { + assert(config->emachine == EM_AARCH64); + authEntries.push_back({(numEntries - 2) * config->wordsize, true}); + authEntries.push_back({(numEntries - 1) * config->wordsize, false}); + } return true; } diff --git a/lld/test/ELF/aarch64-tlsdesc-auth.s b/lld/test/ELF/aarch64-tlsdesc-auth.s new file mode 100644 index 000000000000..34c1bd2e86b5 --- /dev/null +++ b/lld/test/ELF/aarch64-tlsdesc-auth.s @@ -0,0 +1,106 @@ +// REQUIRES: aarch64 +// RUN: rm -rf %t && split-file %s %t && cd %t + +//--- ok.s + +// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-linux -mattr=+pauth ok.s -o ok.o +// RUN: ld.lld --hash-style=sysv -shared ok.o -o ok.so +// RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn ok.so | FileCheck %s +// RUN: llvm-readobj -r -x .got ok.so | FileCheck --check-prefix=REL %s + + .text + adrp x0, :tlsdesc_auth:a + ldr x16, [x0, :tlsdesc_auth_lo12:a] + add x0, x0, :tlsdesc_auth_lo12:a + autia x16, x0 + .tlsdesccall a + blr x16 + +// CHECK: 10298: adrp x0, 0x20000 +// CHECK-NEXT: 1029c: ldr x16, [x0, #872] +// CHECK-NEXT: 102a0: add x0, x0, #872 +// CHECK-NEXT: 102a4: autia x16, x0 +// CHECK-NEXT: 102a8: blr x16 + +// Create relocation against local TLS symbols where linker should +// create target specific dynamic TLSDESC relocation where addend is +// the symbol VMA in tls block. + + adrp x0, :tlsdesc_auth:local1 + ldr x16, [x0, :tlsdesc_auth_lo12:local1] + add x0, x0, :tlsdesc_auth_lo12:local1 + autia x16, x0 + .tlsdesccall a + blr x16 + +// CHECK: 102ac: adrp x0, 0x20000 +// CHECK-NEXT: 102b0: ldr x16, [x0, #888] +// CHECK-NEXT: 102b4: add x0, x0, #888 +// CHECK-NEXT: 102b8: autia x16, x0 +// CHECK-NEXT: 102bc: blr x16 + + adrp x0, :tlsdesc_auth:local2 + ldr x16, [x0, :tlsdesc_auth_lo12:local2] + add x0, x0, :tlsdesc_auth_lo12:local2 + autia x16, x0 + .tlsdesccall a + blr x16 + +// CHECK: 102c0: adrp x0, 0x20000 +// CHECK-NEXT: 102c4: ldr x16, [x0, #904] +// CHECK-NEXT: 102c8: add x0, x0, #904 +// CHECK-NEXT: 102cc: autia x16, x0 +// CHECK-NEXT: 102d0: blr x16 + + .section .tbss,"awT",@nobits + .type local1,@object + .p2align 2 +local1: + .word 0 + .size local1, 4 + + .type local2,@object + .p2align 3 +local2: + .xword 0 + .size local2, 8 + + +// R_AARCH64_AUTH_TLSDESC - 0x0 -> start of tls block +// R_AARCH64_AUTH_TLSDESC - 0x8 -> align (sizeof (local1), 8) + +// REL: Relocations [ +// REL-NEXT: Section (4) .rela.dyn { +// REL-NEXT: 0x20378 R_AARCH64_AUTH_TLSDESC - 0x0 +// REL-NEXT: 0x20388 R_AARCH64_AUTH_TLSDESC - 0x8 +// REL-NEXT: 0x20368 R_AARCH64_AUTH_TLSDESC a 0x0 +// REL-NEXT: } +// REL-NEXT: ] + +// REL: Hex dump of section '.got': +// REL-NEXT: 0x00020368 00000000 00000080 00000000 000000a0 +// REL-NEXT: 0x00020378 00000000 00000080 00000000 000000a0 +// REL-NEXT: 0x00020388 00000000 00000080 00000000 000000a0 +// ^^ +// 0b10000000 bit 63 address diversity = true, bits 61..60 key = IA +// ^^ +// 0b10100000 bit 63 address diversity = true, bits 61..60 key = DA + +//--- err.s + +// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-linux -mattr=+pauth err.s -o err.o +// RUN: not ld.lld --hash-style=sysv -shared err.o -o err.so 2>&1 | FileCheck --check-prefix=ERR %s +// ERR: error: both AUTH and non-AUTH TLSDESC entries for 'a' requested, but only one type of TLSDESC entry per symbol is supported + .text + adrp x0, :tlsdesc_auth:a + ldr x16, [x0, :tlsdesc_auth_lo12:a] + add x0, x0, :tlsdesc_auth_lo12:a + autia x16, x0 + .tlsdesccall a + blr x16 + + adrp x0, :tlsdesc:a + ldr x1, [x0, :tlsdesc_lo12:a] + add x0, x0, :tlsdesc_lo12:a + .tlsdesccall a + blr x1