diff --git a/llvm/include/llvm/CodeGen/MachineModuleInfo.h b/llvm/include/llvm/CodeGen/MachineModuleInfo.h index 92ea3c902ce95..97b439c726b0a 100644 --- a/llvm/include/llvm/CodeGen/MachineModuleInfo.h +++ b/llvm/include/llvm/CodeGen/MachineModuleInfo.h @@ -58,12 +58,20 @@ class MachineModuleInfoImpl { using StubValueTy = PointerIntPair; using SymbolListTy = std::vector>; + /// A variant of SymbolListTy where the stub is a generalized MCExpr. + using ExprStubListTy = std::vector>; + virtual ~MachineModuleInfoImpl(); protected: /// Return the entries from a DenseMap in a deterministic sorted orer. /// Clears the map. static SymbolListTy getSortedStubs(DenseMap&); + + /// Return the entries from a DenseMap in a deterministic sorted orer. + /// Clears the map. + static ExprStubListTy + getSortedExprStubs(DenseMap &); }; //===----------------------------------------------------------------------===// diff --git a/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h b/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h index 64d841d86c7c4..c1ae3d2d966df 100644 --- a/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h +++ b/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h @@ -36,6 +36,11 @@ class MachineModuleInfoMachO : public MachineModuleInfoImpl { /// bit is true if this GV is external. DenseMap ThreadLocalGVStubs; + /// Darwin '$auth_ptr' stubs. The key is the stub symbol, like + /// "Lfoo$auth_ptr$ib$12". The value is the MCExpr representing that + /// signed pointer, something like "_foo@AUTH(ib, 12)". + DenseMap AuthPtrStubs; + virtual void anchor(); // Out of line virtual method. public: @@ -51,29 +56,32 @@ class MachineModuleInfoMachO : public MachineModuleInfoImpl { return ThreadLocalGVStubs[Sym]; } + const MCExpr *&getAuthPtrStubEntry(MCSymbol *Sym) { + assert(Sym && "Key cannot be null"); + return AuthPtrStubs[Sym]; + } + /// Accessor methods to return the set of stubs in sorted order. SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); } SymbolListTy GetThreadLocalGVStubList() { return getSortedStubs(ThreadLocalGVStubs); } + + ExprStubListTy getAuthGVStubList() { + return getSortedExprStubs(AuthPtrStubs); + } }; /// MachineModuleInfoELF - This is a MachineModuleInfoImpl implementation /// for ELF targets. class MachineModuleInfoELF : public MachineModuleInfoImpl { -public: - struct AuthStubInfo { - const MCExpr *AuthPtrRef; - }; - -private: /// GVStubs - These stubs are used to materialize global addresses in PIC /// mode. DenseMap GVStubs; /// AuthPtrStubs - These stubs are used to materialize signed addresses for /// extern_weak symbols. - DenseMap AuthPtrStubs; + DenseMap AuthPtrStubs; virtual void anchor(); // Out of line virtual method. @@ -85,7 +93,7 @@ class MachineModuleInfoELF : public MachineModuleInfoImpl { return GVStubs[Sym]; } - AuthStubInfo &getAuthPtrStubEntry(MCSymbol *Sym) { + const MCExpr *&getAuthPtrStubEntry(MCSymbol *Sym) { assert(Sym && "Key cannot be null"); return AuthPtrStubs[Sym]; } @@ -94,10 +102,9 @@ class MachineModuleInfoELF : public MachineModuleInfoImpl { SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); } - using AuthStubPairTy = std::pair; - typedef std::vector AuthStubListTy; - - AuthStubListTy getAuthGVStubList(); + ExprStubListTy getAuthGVStubList() { + return getSortedExprStubs(AuthPtrStubs); + } }; /// MachineModuleInfoCOFF - This is a MachineModuleInfoImpl implementation diff --git a/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp b/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp index f114f1ecc0bae..956317510dc73 100644 --- a/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp +++ b/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp @@ -43,24 +43,19 @@ MachineModuleInfoImpl::SymbolListTy MachineModuleInfoImpl::getSortedStubs( return List; } -template -static typename MachineModuleInfoTarget::AuthStubListTy getAuthGVStubListHelper( - DenseMap - &AuthPtrStubs) { - typename MachineModuleInfoTarget::AuthStubListTy List(AuthPtrStubs.begin(), - AuthPtrStubs.end()); +using ExprStubPairTy = std::pair; +static int SortAuthStubPair(const ExprStubPairTy *LHS, + const ExprStubPairTy *RHS) { + return LHS->first->getName().compare(RHS->first->getName()); +} - if (!List.empty()) - llvm::sort(List.begin(), List.end(), - [](const typename MachineModuleInfoTarget::AuthStubPairTy &LHS, - const typename MachineModuleInfoTarget::AuthStubPairTy &RHS) { - return LHS.first->getName() < RHS.first->getName(); - }); +MachineModuleInfoImpl::ExprStubListTy MachineModuleInfoImpl::getSortedExprStubs( + DenseMap &ExprStubs) { + MachineModuleInfoImpl::ExprStubListTy List(ExprStubs.begin(), + ExprStubs.end()); - AuthPtrStubs.clear(); - return List; -} + array_pod_sort(List.begin(), List.end(), SortAuthStubPair); -MachineModuleInfoELF::AuthStubListTy MachineModuleInfoELF::getAuthGVStubList() { - return getAuthGVStubListHelper(AuthPtrStubs); + ExprStubs.clear(); + return List; } diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp index 6eb9f44de44fd..06b4dba8b0c65 100644 --- a/llvm/lib/MC/MCMachOStreamer.cpp +++ b/llvm/lib/MC/MCMachOStreamer.cpp @@ -161,6 +161,10 @@ static bool canGoAfterDWARF(const MCSectionMachO &MSec) { return true; if (SegName == "__LLVM" && (SecName == "__cg_profile")) return true; + + if (SegName == "__DATA" && SecName == "__auth_ptr") + return true; + return false; } diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index 64d41d4147644..f61be4e100d3a 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -848,13 +848,12 @@ void AArch64AsmPrinter::emitHwasanMemaccessSymbols(Module &M) { } } -template -static void emitAuthenticatedPointer( - MCStreamer &OutStreamer, MCSymbol *StubLabel, - const typename MachineModuleInfoTarget::AuthStubInfo &StubInfo) { +static void emitAuthenticatedPointer(MCStreamer &OutStreamer, + MCSymbol *StubLabel, + const MCExpr *StubAuthPtrRef) { // sym$auth_ptr$key$disc: OutStreamer.emitLabel(StubLabel); - OutStreamer.emitValue(StubInfo.AuthPtrRef, /*size=*/8); + OutStreamer.emitValue(StubAuthPtrRef, /*size=*/8); } void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) { @@ -862,6 +861,25 @@ void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) { const Triple &TT = TM.getTargetTriple(); if (TT.isOSBinFormatMachO()) { + // Output authenticated pointers as indirect symbols, if we have any. + MachineModuleInfoMachO &MMIMacho = + MMI->getObjFileInfo(); + + auto Stubs = MMIMacho.getAuthGVStubList(); + + if (!Stubs.empty()) { + // Switch to the "__auth_ptr" section. + OutStreamer->switchSection( + OutContext.getMachOSection("__DATA", "__auth_ptr", MachO::S_REGULAR, + SectionKind::getMetadata())); + emitAlignment(Align(8)); + + for (const auto &Stub : Stubs) + emitAuthenticatedPointer(*OutStreamer, Stub.first, Stub.second); + + OutStreamer->addBlankLine(); + } + // Funny Darwin hack: This flag tells the linker that no global symbols // contain code that falls through to other global symbols (e.g. the obvious // implementation of multiple entry points). If this doesn't occur, the @@ -882,8 +900,7 @@ void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) { emitAlignment(Align(8)); for (const auto &Stub : Stubs) - emitAuthenticatedPointer(*OutStreamer, Stub.first, - Stub.second); + emitAuthenticatedPointer(*OutStreamer, Stub.first, Stub.second); OutStreamer->addBlankLine(); } @@ -1676,16 +1693,29 @@ void AArch64AsmPrinter::LowerLOADauthptrstatic(const MachineInstr &MI) { // // Where the $auth_ptr$ symbol is the stub slot containing the signed pointer // to symbol. - assert(TM.getTargetTriple().isOSBinFormatELF() && - "LOADauthptrstatic is implemented only for ELF"); - const auto &TLOF = - static_cast(getObjFileLowering()); - - assert(GAOp.getOffset() == 0 && - "non-zero offset for $auth_ptr$ stub slots is not supported"); - const MCSymbol *GASym = TM.getSymbol(GAOp.getGlobal()); - MCSymbol *AuthPtrStubSym = - TLOF.getAuthPtrSlotSymbol(TM, &MF->getMMI(), GASym, Key, Disc); + MCSymbol *AuthPtrStubSym; + if (TM.getTargetTriple().isOSBinFormatELF()) { + const auto &TLOF = + static_cast(getObjFileLowering()); + + assert(GAOp.getOffset() == 0 && + "non-zero offset for $auth_ptr$ stub slots is not supported"); + const MCSymbol *GASym = TM.getSymbol(GAOp.getGlobal()); + AuthPtrStubSym = + TLOF.getAuthPtrSlotSymbol(TM, &MF->getMMI(), GASym, Key, Disc); + } else { + assert(TM.getTargetTriple().isOSBinFormatMachO() && + "LOADauthptrstatic is implemented only for MachO/ELF"); + + const auto &TLOF = static_cast( + getObjFileLowering()); + + assert(GAOp.getOffset() == 0 && + "non-zero offset for $auth_ptr$ stub slots is not supported"); + const MCSymbol *GASym = TM.getSymbol(GAOp.getGlobal()); + AuthPtrStubSym = + TLOF.getAuthPtrSlotSymbol(TM, &MF->getMMI(), GASym, Key, Disc); + } MachineOperand StubMOHi = MachineOperand::CreateMCSymbol(AuthPtrStubSym, AArch64II::MO_PAGE); diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index e0c3cc5eddb82..dbd9a5430752a 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -9545,8 +9545,7 @@ SDValue AArch64TargetLowering::LowerGlobalTLSAddress(SDValue Op, // Load a signed pointer for symbol 'sym' from a stub slot named // 'sym$auth_ptr$key$disc' filled by dynamic linker during relocation // resolving. This usually lowers to adrp+ldr, but also emits an entry into -// .data with an -// @AUTH relocation. See LowerLOADauthptrstatic. +// .data with an @AUTH relocation. See LowerLOADauthptrstatic. // // All 3 are pseudos that are expand late to longer sequences: this lets us // provide integrity guarantees on the to-be-signed intermediate values. @@ -9599,8 +9598,8 @@ AArch64TargetLowering::LowerPtrAuthGlobalAddress(SDValue Op, "constant discriminator in ptrauth global out of range [0, 0xffff]"); // Choosing between 3 lowering alternatives is target-specific. - if (!Subtarget->isTargetELF()) - report_fatal_error("ptrauth global lowering is only implemented for ELF"); + if (!Subtarget->isTargetELF() && !Subtarget->isTargetMachO()) + report_fatal_error("ptrauth global lowering only supported on MachO/ELF"); int64_t PtrOffsetC = 0; if (Ptr.getOpcode() == ISD::ADD) { diff --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp index 3c0facd586732..d916f644de9b5 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp @@ -105,15 +105,14 @@ static MCSymbol *getAuthPtrSlotSymbolHelper( Twine("$auth_ptr$") + AArch64PACKeyIDToString(Key) + Twine('$') + Twine(Discriminator)); - typename MachineModuleInfoTarget::AuthStubInfo &StubInfo = - TargetMMI.getAuthPtrStubEntry(StubSym); + const MCExpr *&StubAuthPtrRef = TargetMMI.getAuthPtrStubEntry(StubSym); - if (StubInfo.AuthPtrRef) + if (StubAuthPtrRef) return StubSym; const MCExpr *Sym = MCSymbolRefExpr::create(RawSym, Ctx); - StubInfo.AuthPtrRef = + StubAuthPtrRef = AArch64AuthMCExpr::create(Sym, Discriminator, Key, /*HasAddressDiversity=*/false, Ctx); return StubSym; @@ -126,3 +125,11 @@ MCSymbol *AArch64_ELFTargetObjectFile::getAuthPtrSlotSymbol( return getAuthPtrSlotSymbolHelper(getContext(), TM, MMI, ELFMMI, RawSym, Key, Discriminator); } + +MCSymbol *AArch64_MachoTargetObjectFile::getAuthPtrSlotSymbol( + const TargetMachine &TM, MachineModuleInfo *MMI, const MCSymbol *RawSym, + AArch64PACKey::ID Key, uint16_t Discriminator) const { + auto &MachOMMI = MMI->getObjFileInfo(); + return getAuthPtrSlotSymbolHelper(getContext(), TM, MMI, MachOMMI, RawSym, + Key, Discriminator); +} diff --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h index c5ebf03c39c77..2ef8bda2988d4 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h +++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h @@ -60,6 +60,11 @@ class AArch64_MachoTargetObjectFile : public TargetLoweringObjectFileMachO { void getNameWithPrefix(SmallVectorImpl &OutName, const GlobalValue *GV, const TargetMachine &TM) const override; + + MCSymbol *getAuthPtrSlotSymbol(const TargetMachine &TM, + MachineModuleInfo *MMI, const MCSymbol *RawSym, + AArch64PACKey::ID Key, + uint16_t Discriminator) const; }; /// This implementation is used for AArch64 COFF targets. diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp index 9e0860934f777..dc47bdf6b351b 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -6636,8 +6636,8 @@ bool AArch64InstructionSelector::selectPtrAuthGlobalValue( "constant discriminator in ptrauth global out of range [0, 0xffff]"); // Choosing between 3 lowering alternatives is target-specific. - if (!STI.isTargetELF()) - report_fatal_error("ptrauth global lowering is only implemented for ELF"); + if (!STI.isTargetELF() && !STI.isTargetMachO()) + report_fatal_error("ptrauth global lowering only supported on MachO/ELF"); if (!MRI.hasOneDef(Addr)) return false; diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll index 7b85b12bb8952..12a3448111fcb 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll @@ -5,6 +5,9 @@ ; RUN: not --crash llc < err1.ll -mtriple aarch64-elf -mattr=+pauth \ ; RUN: -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \ ; RUN: FileCheck --check-prefix=ERR1 %s +; RUN: not --crash llc < err1.ll -mtriple arm64-apple-ios -mattr=+pauth \ +; RUN: -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \ +; RUN: FileCheck --check-prefix=ERR1 %s @g = external global i32 @@ -18,6 +21,9 @@ define ptr @foo() { ; RUN: not --crash llc < err2.ll -mtriple aarch64-elf -mattr=+pauth \ ; RUN: -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \ ; RUN: FileCheck --check-prefix=ERR2 %s +; RUN: not --crash llc < err2.ll -mtriple arm64-apple-ios -mattr=+pauth \ +; RUN: -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \ +; RUN: FileCheck --check-prefix=ERR2 %s @g = external global i32 @@ -31,6 +37,9 @@ define ptr @foo() { ; RUN: not --crash llc < err3.ll -mtriple aarch64-elf -mattr=+pauth \ ; RUN: -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \ ; RUN: FileCheck --check-prefix=ERR3 %s +; RUN: not --crash llc < err3.ll -mtriple arm64-apple-ios -mattr=+pauth \ +; RUN: -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \ +; RUN: FileCheck --check-prefix=ERR3 %s @g_weak = extern_weak global i32 @@ -44,6 +53,9 @@ define ptr @foo() { ; RUN: not --crash llc < err4.ll -mtriple aarch64-elf -mattr=+pauth \ ; RUN: -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \ ; RUN: FileCheck --check-prefix=ERR4 %s +; RUN: not --crash llc < err4.ll -mtriple arm64-apple-ios -mattr=+pauth \ +; RUN: -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \ +; RUN: FileCheck --check-prefix=ERR4 %s @g_weak = extern_weak global i32 @g_weak.ref.da.42.addr = dso_local constant ptr ptrauth (ptr @g_weak, i32 2, i64 42, ptr @g_weak.ref.da.42.addr) @@ -55,21 +67,28 @@ define ptr @foo() { ;--- err5.ll -; RUN: not --crash llc < err5.ll -mtriple arm64-apple-darwin -mattr=+pauth \ +; RUN: not --crash llc < err5.ll -mtriple aarch64-windows -mattr=+pauth \ ; RUN: -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \ ; RUN: FileCheck --check-prefix=ERR5 %s @g = external global i32 define ptr @foo() { -; ERR5: LLVM ERROR: ptrauth global lowering is only implemented for ELF +; ERR5: LLVM ERROR: ptrauth global lowering only supported on MachO/ELF ret ptr ptrauth (ptr @g, i32 0) } ;--- ok.ll ; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=1 \ -; RUN: -verify-machineinstrs -global-isel-abort=1 | FileCheck %s +; RUN: -verify-machineinstrs -global-isel-abort=1 | \ +; RUN: FileCheck %s --check-prefix=ELF +; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=1 \ +; RUN: -verify-machineinstrs -global-isel-abort=1 -filetype=obj + +; RUN: llc < ok.ll -mtriple arm64-apple-ios -mattr=+pauth -global-isel=1 \ +; RUN: -verify-machineinstrs -global-isel-abort=1 | \ +; RUN: FileCheck %s --check-prefix=MACHO ; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=1 \ ; RUN: -verify-machineinstrs -global-isel-abort=1 -filetype=obj @@ -78,100 +97,171 @@ define ptr @foo() { @g_strong_def = dso_local constant i32 42 define ptr @test_global_zero_disc() { -; CHECK-LABEL: test_global_zero_disc: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: paciza x16 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: paciza x16 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_zero_disc: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: paciza x16 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 0) } define ptr @test_global_offset_zero_disc() { -; CHECK-LABEL: test_global_offset_zero_disc: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: add x16, x16, #16 -; CHECK-NEXT: pacdza x16 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_offset_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: add x16, x16, #16 +; ELF-NEXT: pacdza x16 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_offset_zero_disc: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: add x16, x16, #16 +; MACHO-NEXT: pacdza x16 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 16), i32 2) } define ptr @test_global_neg_offset_zero_disc() { -; CHECK-LABEL: test_global_neg_offset_zero_disc: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: sub x16, x16, #576 -; CHECK-NEXT: sub x16, x16, #30, lsl #12 -; CHECK-NEXT: pacdza x16 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_neg_offset_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: sub x16, x16, #576 +; ELF-NEXT: sub x16, x16, #30, lsl #12 +; ELF-NEXT: pacdza x16 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_neg_offset_zero_disc: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: sub x16, x16, #576 +; MACHO-NEXT: sub x16, x16, #30, lsl #12 +; MACHO-NEXT: pacdza x16 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456), i32 2) } define ptr @test_global_big_offset_zero_disc() { -; CHECK-LABEL: test_global_big_offset_zero_disc: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: mov x17, #1 -; CHECK-NEXT: movk x17, #32769, lsl #16 -; CHECK-NEXT: add x16, x16, x17 -; CHECK-NEXT: pacdza x16 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_big_offset_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: mov x17, #1 +; ELF-NEXT: movk x17, #32769, lsl #16 +; ELF-NEXT: add x16, x16, x17 +; ELF-NEXT: pacdza x16 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_big_offset_zero_disc: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x17, #1 +; MACHO-NEXT: movk x17, #32769, lsl #16 +; MACHO-NEXT: add x16, x16, x17 +; MACHO-NEXT: pacdza x16 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 add (i64 2147483648, i64 65537)), i32 2) } define ptr @test_global_big_neg_offset_zero_disc() { -; CHECK-LABEL: test_global_big_neg_offset_zero_disc: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: mov x17, #-52501 -; CHECK-NEXT: movk x17, #63652, lsl #16 -; CHECK-NEXT: add x16, x16, x17 -; CHECK-NEXT: pacdza x16 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_big_neg_offset_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: mov x17, #-52501 +; ELF-NEXT: movk x17, #63652, lsl #16 +; ELF-NEXT: add x16, x16, x17 +; ELF-NEXT: pacdza x16 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_big_neg_offset_zero_disc: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x17, #-52501 +; MACHO-NEXT: movk x17, #63652, lsl #16 +; MACHO-NEXT: add x16, x16, x17 +; MACHO-NEXT: pacdza x16 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456789), i32 2) } define ptr @test_global_huge_neg_offset_zero_disc() { -; CHECK-LABEL: test_global_huge_neg_offset_zero_disc: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: mov x17, #-65536 -; CHECK-NEXT: movk x17, #0, lsl #16 -; CHECK-NEXT: movk x17, #0, lsl #32 -; CHECK-NEXT: movk x17, #32768, lsl #48 -; CHECK-NEXT: add x16, x16, x17 -; CHECK-NEXT: pacdza x16 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_huge_neg_offset_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: mov x17, #-65536 +; ELF-NEXT: movk x17, #0, lsl #16 +; ELF-NEXT: movk x17, #0, lsl #32 +; ELF-NEXT: movk x17, #32768, lsl #48 +; ELF-NEXT: add x16, x16, x17 +; ELF-NEXT: pacdza x16 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_huge_neg_offset_zero_disc: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x17, #-65536 +; MACHO-NEXT: movk x17, #0, lsl #16 +; MACHO-NEXT: movk x17, #0, lsl #32 +; MACHO-NEXT: movk x17, #32768, lsl #48 +; MACHO-NEXT: add x16, x16, x17 +; MACHO-NEXT: pacdza x16 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -9223372036854775808), i32 2) } define ptr @test_global_disc() { -; CHECK-LABEL: test_global_disc: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: mov x17, #42 // =0x2a -; CHECK-NEXT: pacia x16, x17 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: mov x17, #42 // =0x2a +; ELF-NEXT: pacia x16, x17 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_disc: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x17, #42 ; =0x2a +; MACHO-NEXT: pacia x16, x17 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 0, i64 42) } @@ -179,57 +269,123 @@ define ptr @test_global_disc() { @g.ref.da.42.addr = dso_local constant ptr ptrauth (ptr @g, i32 2, i64 42, ptr @g.ref.da.42.addr) define ptr @test_global_addr_disc() { -; CHECK-LABEL: test_global_addr_disc: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x8, g.ref.da.42.addr -; CHECK-NEXT: add x8, x8, :lo12:g.ref.da.42.addr -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: mov x17, x8 -; CHECK-NEXT: movk x17, #42, lsl #48 -; CHECK-NEXT: pacda x16, x17 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_addr_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x8, g.ref.da.42.addr +; ELF-NEXT: add x8, x8, :lo12:g.ref.da.42.addr +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: mov x17, x8 +; ELF-NEXT: movk x17, #42, lsl #48 +; ELF-NEXT: pacda x16, x17 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_addr_disc: +; MACHO: ; %bb.0: +; MACHO-NEXT: Lloh{{.*}}: +; MACHO-NEXT: adrp x8, _g.ref.da.42.addr@PAGE +; MACHO-NEXT: Lloh{{.*}}: +; MACHO-NEXT: add x8, x8, _g.ref.da.42.addr@PAGEOFF +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x17, x8 +; MACHO-NEXT: movk x17, #42, lsl #48 +; MACHO-NEXT: pacda x16, x17 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 2, i64 42, ptr @g.ref.da.42.addr) } define ptr @test_global_process_specific() { -; CHECK-LABEL: test_global_process_specific: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: pacizb x16 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_process_specific: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: pacizb x16 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_process_specific: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: pacizb x16 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret + ret ptr ptrauth (ptr @g, i32 1) } +; Non-external symbols don't need to be accessed through the GOT. + +define ptr @test_global_strong_def() { +; ELF-LABEL: test_global_strong_def: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, g_strong_def +; ELF-NEXT: add x16, x16, :lo12:g_strong_def +; ELF-NEXT: pacdza x16 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_strong_def: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g_strong_def@PAGE +; MACHO-NEXT: add x16, x16, _g_strong_def@PAGEOFF +; MACHO-NEXT: pacdza x16 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret + + ret ptr ptrauth (ptr @g_strong_def, i32 2) +} + ; weak symbols can't be assumed to be non-nil. Use $auth_ptr$ stub slot always. ; The alternative is to emit a null-check here, but that'd be redundant with ; whatever null-check follows in user code. define ptr @test_global_weak() { -; CHECK-LABEL: test_global_weak: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x0, g_weak$auth_ptr$ia$42 -; CHECK-NEXT: ldr x0, [x0, :lo12:g_weak$auth_ptr$ia$42] -; CHECK-NEXT: ret +; ELF-LABEL: test_global_weak: +; ELF: // %bb.0: +; ELF-NEXT: adrp x0, g_weak$auth_ptr$ia$42 +; ELF-NEXT: ldr x0, [x0, :lo12:g_weak$auth_ptr$ia$42] +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_weak: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x0, l_g_weak$auth_ptr$ia$42@PAGE +; MACHO-NEXT: ldr x0, [x0, l_g_weak$auth_ptr$ia$42@PAGEOFF] +; MACHO-NEXT: ret + ret ptr ptrauth (ptr @g_weak, i32 0, i64 42) } -; Non-external symbols don't need to be accessed through the GOT. +; Test another weak symbol to check that stubs are emitted in a stable order. -define ptr @test_global_strong_def() { -; CHECK-LABEL: test_global_strong_def: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, g_strong_def -; CHECK-NEXT: add x16, x16, :lo12:g_strong_def -; CHECK-NEXT: pacdza x16 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret - ret ptr ptrauth (ptr @g_strong_def, i32 2) +@g_weak_2 = extern_weak global i32 + +define ptr @test_global_weak_2() { +; ELF-LABEL: test_global_weak_2: +; ELF: // %bb.0: +; ELF-NEXT: adrp x0, g_weak_2$auth_ptr$ia$42 +; ELF-NEXT: ldr x0, [x0, :lo12:g_weak_2$auth_ptr$ia$42] +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_weak_2: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x0, l_g_weak_2$auth_ptr$ia$42@PAGE +; MACHO-NEXT: ldr x0, [x0, l_g_weak_2$auth_ptr$ia$42@PAGEOFF] +; MACHO-NEXT: ret + + ret ptr ptrauth (ptr @g_weak_2, i32 0, i64 42) } -; CHECK-LABEL: g_weak$auth_ptr$ia$42: -; CHECK-NEXT: .xword g_weak@AUTH(ia,42) +; ELF-LABEL: g_weak$auth_ptr$ia$42: +; ELF-NEXT: .xword g_weak@AUTH(ia,42) +; ELF-LABEL: g_weak_2$auth_ptr$ia$42: +; ELF-NEXT: .xword g_weak_2@AUTH(ia,42) + +; MACHO-LABEL: l_g_weak$auth_ptr$ia$42: +; MACHO-NEXT: .quad _g_weak@AUTH(ia,42) +; MACHO-LABEL: l_g_weak_2$auth_ptr$ia$42: +; MACHO-NEXT: .quad _g_weak_2@AUTH(ia,42) diff --git a/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll b/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll index 73993fa87bf27..76339a7cc5791 100644 --- a/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll +++ b/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll @@ -4,6 +4,8 @@ ; RUN: not --crash llc < err1.ll -mtriple aarch64-elf -mattr=+pauth \ ; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR1 %s +; RUN: not --crash llc < err1.ll -mtriple arm64-apple-ios -mattr=+pauth \ +; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR1 %s @g = external global i32 @@ -16,6 +18,8 @@ define ptr @foo() { ; RUN: not --crash llc < err2.ll -mtriple aarch64-elf -mattr=+pauth \ ; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR2 %s +; RUN: not --crash llc < err2.ll -mtriple arm64-apple-ios -mattr=+pauth \ +; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR2 %s @g = external global i32 @@ -28,6 +32,8 @@ define ptr @foo() { ; RUN: not --crash llc < err3.ll -mtriple aarch64-elf -mattr=+pauth \ ; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR3 %s +; RUN: not --crash llc < err3.ll -mtriple arm64-apple-ios -mattr=+pauth \ +; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR3 %s @g_weak = extern_weak global i32 @@ -40,6 +46,8 @@ define ptr @foo() { ; RUN: not --crash llc < err4.ll -mtriple aarch64-elf -mattr=+pauth \ ; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR4 %s +; RUN: not --crash llc < err4.ll -mtriple arm64-apple-ios -mattr=+pauth \ +; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR4 %s @g_weak = extern_weak global i32 @g_weak.ref.da.42.addr = dso_local constant ptr ptrauth (ptr @g_weak, i32 2, i64 42, ptr @g_weak.ref.da.42.addr) @@ -51,122 +59,198 @@ define ptr @foo() { ;--- err5.ll -; RUN: not --crash llc < err5.ll -mtriple arm64-apple-darwin -mattr=+pauth \ +; RUN: not --crash llc < err5.ll -mtriple aarch64-windows -mattr=+pauth \ ; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR5 %s @g = external global i32 define ptr @foo() { -; ERR5: LLVM ERROR: ptrauth global lowering is only implemented for ELF +; ERR5: LLVM ERROR: ptrauth global lowering only supported on MachO/ELF ret ptr ptrauth (ptr @g, i32 0) } ;--- ok.ll ; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=0 \ -; RUN: -verify-machineinstrs | FileCheck %s +; RUN: -verify-machineinstrs | FileCheck %s --check-prefix=ELF ; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=0 \ ; RUN: -verify-machineinstrs -filetype=obj +; RUN: llc < ok.ll -mtriple arm64-apple-ios -mattr=+pauth -global-isel=0 \ +; RUN: -verify-machineinstrs | FileCheck %s --check-prefix=MACHO +; RUN: llc < ok.ll -mtriple arm64-apple-ios -mattr=+pauth -global-isel=0 \ +; RUN: -verify-machineinstrs -filetype=obj + @g = external global i32 @g_weak = extern_weak global i32 @g_strong_def = dso_local constant i32 42 define ptr @test_global_zero_disc() { -; CHECK-LABEL: test_global_zero_disc: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: paciza x16 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: paciza x16 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_zero_disc: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: paciza x16 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 0) } define ptr @test_global_offset_zero_disc() { -; CHECK-LABEL: test_global_offset_zero_disc: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: add x16, x16, #16 -; CHECK-NEXT: pacdza x16 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_offset_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: add x16, x16, #16 +; ELF-NEXT: pacdza x16 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_offset_zero_disc: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: add x16, x16, #16 +; MACHO-NEXT: pacdza x16 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 16), i32 2) } define ptr @test_global_neg_offset_zero_disc() { -; CHECK-LABEL: test_global_neg_offset_zero_disc: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: sub x16, x16, #576 -; CHECK-NEXT: sub x16, x16, #30, lsl #12 -; CHECK-NEXT: pacdza x16 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_neg_offset_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: sub x16, x16, #576 +; ELF-NEXT: sub x16, x16, #30, lsl #12 +; ELF-NEXT: pacdza x16 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_neg_offset_zero_disc: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: sub x16, x16, #576 +; MACHO-NEXT: sub x16, x16, #30, lsl #12 +; MACHO-NEXT: pacdza x16 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456), i32 2) } define ptr @test_global_big_offset_zero_disc() { -; CHECK-LABEL: test_global_big_offset_zero_disc: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: mov x17, #1 -; CHECK-NEXT: movk x17, #32769, lsl #16 -; CHECK-NEXT: add x16, x16, x17 -; CHECK-NEXT: pacdza x16 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_big_offset_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: mov x17, #1 +; ELF-NEXT: movk x17, #32769, lsl #16 +; ELF-NEXT: add x16, x16, x17 +; ELF-NEXT: pacdza x16 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_big_offset_zero_disc: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x17, #1 +; MACHO-NEXT: movk x17, #32769, lsl #16 +; MACHO-NEXT: add x16, x16, x17 +; MACHO-NEXT: pacdza x16 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 add (i64 2147483648, i64 65537)), i32 2) } define ptr @test_global_big_neg_offset_zero_disc() { -; CHECK-LABEL: test_global_big_neg_offset_zero_disc: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: mov x17, #-52501 -; CHECK-NEXT: movk x17, #63652, lsl #16 -; CHECK-NEXT: add x16, x16, x17 -; CHECK-NEXT: pacdza x16 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_big_neg_offset_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: mov x17, #-52501 +; ELF-NEXT: movk x17, #63652, lsl #16 +; ELF-NEXT: add x16, x16, x17 +; ELF-NEXT: pacdza x16 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_big_neg_offset_zero_disc: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x17, #-52501 +; MACHO-NEXT: movk x17, #63652, lsl #16 +; MACHO-NEXT: add x16, x16, x17 +; MACHO-NEXT: pacdza x16 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456789), i32 2) } define ptr @test_global_huge_neg_offset_zero_disc() { -; CHECK-LABEL: test_global_huge_neg_offset_zero_disc: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: mov x17, #-65536 -; CHECK-NEXT: movk x17, #0, lsl #16 -; CHECK-NEXT: movk x17, #0, lsl #32 -; CHECK-NEXT: movk x17, #32768, lsl #48 -; CHECK-NEXT: add x16, x16, x17 -; CHECK-NEXT: pacdza x16 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_huge_neg_offset_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: mov x17, #-65536 +; ELF-NEXT: movk x17, #0, lsl #16 +; ELF-NEXT: movk x17, #0, lsl #32 +; ELF-NEXT: movk x17, #32768, lsl #48 +; ELF-NEXT: add x16, x16, x17 +; ELF-NEXT: pacdza x16 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_huge_neg_offset_zero_disc: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x17, #-65536 +; MACHO-NEXT: movk x17, #0, lsl #16 +; MACHO-NEXT: movk x17, #0, lsl #32 +; MACHO-NEXT: movk x17, #32768, lsl #48 +; MACHO-NEXT: add x16, x16, x17 +; MACHO-NEXT: pacdza x16 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -9223372036854775808), i32 2) } define ptr @test_global_disc() { -; CHECK-LABEL: test_global_disc: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: mov x17, #42 // =0x2a -; CHECK-NEXT: pacia x16, x17 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: mov x17, #42 // =0x2a +; ELF-NEXT: pacia x16, x17 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_disc: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x17, #42 ; =0x2a +; MACHO-NEXT: pacia x16, x17 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 0, i64 42) } @@ -174,57 +258,123 @@ define ptr @test_global_disc() { @g.ref.da.42.addr = dso_local constant ptr ptrauth (ptr @g, i32 2, i64 42, ptr @g.ref.da.42.addr) define ptr @test_global_addr_disc() { -; CHECK-LABEL: test_global_addr_disc: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x8, g.ref.da.42.addr -; CHECK-NEXT: add x8, x8, :lo12:g.ref.da.42.addr -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: mov x17, x8 -; CHECK-NEXT: movk x17, #42, lsl #48 -; CHECK-NEXT: pacda x16, x17 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_addr_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x8, g.ref.da.42.addr +; ELF-NEXT: add x8, x8, :lo12:g.ref.da.42.addr +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: mov x17, x8 +; ELF-NEXT: movk x17, #42, lsl #48 +; ELF-NEXT: pacda x16, x17 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_addr_disc: +; MACHO: ; %bb.0: +; MACHO-NEXT: Lloh{{.*}}: +; MACHO-NEXT: adrp x8, _g.ref.da.42.addr@PAGE +; MACHO-NEXT: Lloh{{.*}}: +; MACHO-NEXT: add x8, x8, _g.ref.da.42.addr@PAGEOFF +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x17, x8 +; MACHO-NEXT: movk x17, #42, lsl #48 +; MACHO-NEXT: pacda x16, x17 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 2, i64 42, ptr @g.ref.da.42.addr) } define ptr @test_global_process_specific() { -; CHECK-LABEL: test_global_process_specific: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, :got:g -; CHECK-NEXT: ldr x16, [x16, :got_lo12:g] -; CHECK-NEXT: pacizb x16 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret +; ELF-LABEL: test_global_process_specific: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, :got:g +; ELF-NEXT: ldr x16, [x16, :got_lo12:g] +; ELF-NEXT: pacizb x16 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_process_specific: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g@GOTPAGE +; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] +; MACHO-NEXT: pacizb x16 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret + ret ptr ptrauth (ptr @g, i32 1) } +; Non-external symbols don't need to be accessed through the GOT. + +define ptr @test_global_strong_def() { +; ELF-LABEL: test_global_strong_def: +; ELF: // %bb.0: +; ELF-NEXT: adrp x16, g_strong_def +; ELF-NEXT: add x16, x16, :lo12:g_strong_def +; ELF-NEXT: pacdza x16 +; ELF-NEXT: mov x0, x16 +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_strong_def: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x16, _g_strong_def@PAGE +; MACHO-NEXT: add x16, x16, _g_strong_def@PAGEOFF +; MACHO-NEXT: pacdza x16 +; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: ret + + ret ptr ptrauth (ptr @g_strong_def, i32 2) +} + ; weak symbols can't be assumed to be non-nil. Use $auth_ptr$ stub slot always. ; The alternative is to emit a null-check here, but that'd be redundant with ; whatever null-check follows in user code. define ptr @test_global_weak() { -; CHECK-LABEL: test_global_weak: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x0, g_weak$auth_ptr$ia$42 -; CHECK-NEXT: ldr x0, [x0, :lo12:g_weak$auth_ptr$ia$42] -; CHECK-NEXT: ret +; ELF-LABEL: test_global_weak: +; ELF: // %bb.0: +; ELF-NEXT: adrp x0, g_weak$auth_ptr$ia$42 +; ELF-NEXT: ldr x0, [x0, :lo12:g_weak$auth_ptr$ia$42] +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_weak: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x0, l_g_weak$auth_ptr$ia$42@PAGE +; MACHO-NEXT: ldr x0, [x0, l_g_weak$auth_ptr$ia$42@PAGEOFF] +; MACHO-NEXT: ret + ret ptr ptrauth (ptr @g_weak, i32 0, i64 42) } -; Non-external symbols don't need to be accessed through the GOT. +; Test another weak symbol to check that stubs are emitted in a stable order. -define ptr @test_global_strong_def() { -; CHECK-LABEL: test_global_strong_def: -; CHECK: // %bb.0: -; CHECK-NEXT: adrp x16, g_strong_def -; CHECK-NEXT: add x16, x16, :lo12:g_strong_def -; CHECK-NEXT: pacdza x16 -; CHECK-NEXT: mov x0, x16 -; CHECK-NEXT: ret - ret ptr ptrauth (ptr @g_strong_def, i32 2) +@g_weak_2 = extern_weak global i32 + +define ptr @test_global_weak_2() { +; ELF-LABEL: test_global_weak_2: +; ELF: // %bb.0: +; ELF-NEXT: adrp x0, g_weak_2$auth_ptr$ia$42 +; ELF-NEXT: ldr x0, [x0, :lo12:g_weak_2$auth_ptr$ia$42] +; ELF-NEXT: ret + +; MACHO-LABEL: _test_global_weak_2: +; MACHO: ; %bb.0: +; MACHO-NEXT: adrp x0, l_g_weak_2$auth_ptr$ia$42@PAGE +; MACHO-NEXT: ldr x0, [x0, l_g_weak_2$auth_ptr$ia$42@PAGEOFF] +; MACHO-NEXT: ret + + ret ptr ptrauth (ptr @g_weak_2, i32 0, i64 42) } -; CHECK-LABEL: g_weak$auth_ptr$ia$42: -; CHECK-NEXT: .xword g_weak@AUTH(ia,42) +; ELF-LABEL: g_weak$auth_ptr$ia$42: +; ELF-NEXT: .xword g_weak@AUTH(ia,42) +; ELF-LABEL: g_weak_2$auth_ptr$ia$42: +; ELF-NEXT: .xword g_weak_2@AUTH(ia,42) + +; MACHO-LABEL: l_g_weak$auth_ptr$ia$42: +; MACHO-NEXT: .quad _g_weak@AUTH(ia,42) +; MACHO-LABEL: l_g_weak_2$auth_ptr$ia$42: +; MACHO-NEXT: .quad _g_weak_2@AUTH(ia,42)