X-Git-Url: https://git.saurik.com/apple/ld64.git/blobdiff_plain/f410558f5d60087e4c310119a1751b437121c3b9..e456bf1059cf7e6b8b71545d1b2f2092b55a9684:/src/ld/passes/stubs/stub_arm64.hpp diff --git a/src/ld/passes/stubs/stub_arm64.hpp b/src/ld/passes/stubs/stub_arm64.hpp index 815e28a..e473f06 100644 --- a/src/ld/passes/stubs/stub_arm64.hpp +++ b/src/ld/passes/stubs/stub_arm64.hpp @@ -148,7 +148,7 @@ public: const ld::Atom& stubTo) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, - symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)), + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), _stubTo(stubTo), _fixup1(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Branch26, helperHelper(pass)), _fixup2(8, ld::Fixup::k1of2, ld::Fixup::kindSetLazyOffset, lazyPointer), @@ -191,7 +191,7 @@ public: const ld::Atom& stubTo) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, - symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)), + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), _stubTo(stubTo), _fixup1(24, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Branch26, &stubTo), _fixup2(28, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, lazyPointer), @@ -301,7 +301,7 @@ public: bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport, bool dataConstUsed) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, - symbolTableNotIn, false, false, false, ld::Atom::Alignment(1)), + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), _stubTo(stubTo), _lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport, dataConstUsed), _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, &_lazyPointer), @@ -338,12 +338,14 @@ ld::Section StubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeStub); class NonLazyPointerAtom : public ld::Atom { public: - NonLazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo) + NonLazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool weakImport) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), _stubTo(stubTo), _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64, &stubTo) { + _fixup1.weakImport = weakImport; pass.addAtom(*this); } @@ -366,18 +368,19 @@ private: ld::Section NonLazyPointerAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); -class KextStubAtom : public ld::Atom { +class NonLazyStubAtom : public ld::Atom { public: - KextStubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo) + NonLazyStubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool weakImport) : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, - symbolTableIn, false, false, false, ld::Atom::Alignment(1)), + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), _stubTo(stubTo), - _nonLazyPointer(pass, stubTo), + _nonLazyPointer(pass, stubTo, weakImport), _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, &_nonLazyPointer), - _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, &_nonLazyPointer) { - pass.addAtom(*this); + _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, &_nonLazyPointer) { asprintf((char**)&_name, "%s.stub", _stubTo.name()); + pass.addAtom(*this); } virtual const ld::File* file() const { return _stubTo.file(); } @@ -403,8 +406,404 @@ private: static ld::Section _s_section; }; -ld::Section KextStubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeCode); +ld::Section NonLazyStubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeStub); } // namespace arm64 +#if SUPPORT_ARCH_arm64e + +// already in ld::passes::stubs namespace +namespace arm64e { + + + +class FastBindingPointerAtom : public ld::Atom { +public: + FastBindingPointerAtom(ld::passes::stubs::Pass& pass) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), + _fixup(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressLittleEndian64, + pass.internal()->compressedFastBinderProxy) + { pass.addAtom(*this); } + + virtual const ld::File* file() const { return NULL; } + virtual const char* name() const { return "fast binder pointer"; } + virtual uint64_t size() const { return 8; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup)[1]; } + +private: + mutable ld::Fixup _fixup; + + static ld::Section _s_section; +}; + +ld::Section FastBindingPointerAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); + + +class ImageCachePointerAtom : public ld::Atom { +public: + ImageCachePointerAtom(ld::passes::stubs::Pass& pass) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)) { pass.addAtom(*this); } + + virtual const ld::File* file() const { return NULL; } + virtual const char* name() const { return "image cache pointer"; } + virtual uint64_t size() const { return 8; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { } + virtual void setScope(Scope) { } + +private: + + static ld::Section _s_section; +}; + +ld::Section ImageCachePointerAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); + + + + + +// +// The stub-helper-helper is the common code factored out of each helper function. +// It is in the same section as the stub-helpers. +// Similar to the PLT0 entry in ELF. +// +class StubHelperHelperAtom : public ld::Atom { +public: + StubHelperHelperAtom(ld::passes::stubs::Pass& pass) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, compressedImageCache(pass)), + _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, compressedImageCache(pass)), + _fixup3(12, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, compressedFastBinder(pass)), + _fixup4(16, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, compressedFastBinder(pass)), + _fixup5(ld::Fixup::kindLinkerOptimizationHint, LOH_ARM64_ADRP_ADD, 0, 4), + _fixup6(ld::Fixup::kindLinkerOptimizationHint, LOH_ARM64_ADRP_LDR, 12, 16) + { pass.addAtom(*this); } + + virtual ld::File* file() const { return NULL; } + virtual const char* name() const { return "helper helper"; } + virtual uint64_t size() const { return 24; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + OSWriteLittleInt32(&buffer[ 0], 0, 0x90000011); // ADRP X17, dyld_mageLoaderCache@page + OSWriteLittleInt32(&buffer[ 4], 0, 0x91000231); // ADD X17, X17, dyld_mageLoaderCache@pageoff + OSWriteLittleInt32(&buffer[ 8], 0, 0xA9BF47F0); // STP X16/X17, [SP, #-16]! + OSWriteLittleInt32(&buffer[12], 0, 0x90000010); // ADRP X16, _fast_lazy_bind@page + OSWriteLittleInt32(&buffer[16], 0, 0xF9400210); // LDR X16, [X16,_fast_lazy_bind@pageoff] + OSWriteLittleInt32(&buffer[20], 0, 0xD61F0200); // BR X16 + } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup6)[1]; } + +private: + static ld::Atom* compressedImageCache(ld::passes::stubs::Pass& pass) { + if ( pass.compressedImageCache == NULL ) + pass.compressedImageCache = new ImageCachePointerAtom(pass); + return pass.compressedImageCache; + } + static ld::Atom* compressedFastBinder(ld::passes::stubs::Pass& pass) { + if ( pass.compressedFastBinderPointer == NULL ) + pass.compressedFastBinderPointer = new FastBindingPointerAtom(pass); + return pass.compressedFastBinderPointer; + } + + mutable ld::Fixup _fixup1; + ld::Fixup _fixup2; + ld::Fixup _fixup3; + ld::Fixup _fixup4; + ld::Fixup _fixup5; + ld::Fixup _fixup6; + + static ld::Section _s_section; +}; + +ld::Section StubHelperHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper); + + + +class StubHelperAtom : public ld::Atom { +public: + StubHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom* lazyPointer, + const ld::Atom& stubTo) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _stubTo(stubTo), + _fixup1(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Branch26, helperHelper(pass)), + _fixup2(8, ld::Fixup::k1of2, ld::Fixup::kindSetLazyOffset, lazyPointer), + _fixup3(8, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32) { } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _stubTo.name(); } + virtual uint64_t size() const { return 12; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + OSWriteLittleInt32(&buffer[0], 0, 0x18000050); // LDR W16, L0 + OSWriteLittleInt32(&buffer[4], 0, 0x14000000); // B helperhelper + OSWriteLittleInt32(&buffer[8], 0, 0x00000000); // L0: .long 0 + } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } + +private: + static ld::Atom* helperHelper(ld::passes::stubs::Pass& pass) { + if ( pass.compressedHelperHelper == NULL ) + pass.compressedHelperHelper = new StubHelperHelperAtom(pass); + return pass.compressedHelperHelper; + } + + const ld::Atom& _stubTo; + mutable ld::Fixup _fixup1; + ld::Fixup _fixup2; + ld::Fixup _fixup3; + + static ld::Section _s_section; +}; + +ld::Section StubHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper); + + +class ResolverHelperAtom : public ld::Atom { +public: + ResolverHelperAtom(ld::passes::stubs::Pass& pass, const ld::Atom* lazyPointer, + const ld::Atom& stubTo) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeStubHelper, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _stubTo(stubTo), + _fixup1(24, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Branch26, &stubTo), + _fixup2(28, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, lazyPointer), + _fixup3(32, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, lazyPointer) { } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _stubTo.name(); } + virtual uint64_t size() const { return 68; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + OSWriteLittleInt32(&buffer[ 0], 0, 0xa9bf7bfd); // stp fp, lr, [sp, #-16]! + OSWriteLittleInt32(&buffer[ 4], 0, 0x910003fd); // mov fp, sp + OSWriteLittleInt32(&buffer[ 8], 0, 0xa9bf03e1); // stp x1, x0, [sp, #-16]! + OSWriteLittleInt32(&buffer[12], 0, 0xa9bf0be3); // stp x3, x2, [sp, #-16]! + OSWriteLittleInt32(&buffer[16], 0, 0xa9bf13e5); // stp x5, x4, [sp, #-16]! + OSWriteLittleInt32(&buffer[20], 0, 0xa9bf1be7); // stp x7, x6, [sp, #-16]! + OSWriteLittleInt32(&buffer[24], 0, 0x94000000); // bl _foo + OSWriteLittleInt32(&buffer[28], 0, 0x90000010); // adrp x16, lazy_pointer@PAGE + OSWriteLittleInt32(&buffer[32], 0, 0x91000210); // add x16, x16, lazy_pointer@PAGEOFF + OSWriteLittleInt32(&buffer[36], 0, 0xf9000200); // str x0, [x16] + OSWriteLittleInt32(&buffer[40], 0, 0xaa0003f0); // mov x16, x0 + OSWriteLittleInt32(&buffer[44], 0, 0xa8c11be7); // ldp x7, x6, [sp], #16 + OSWriteLittleInt32(&buffer[48], 0, 0xa8c113e5); // ldp x5, x4, [sp], #16 + OSWriteLittleInt32(&buffer[52], 0, 0xa8c10be3); // ldp x3, x2, [sp], #16 + OSWriteLittleInt32(&buffer[56], 0, 0xa8c103e1); // ldp x1, x0, [sp], #16 + OSWriteLittleInt32(&buffer[60], 0, 0xa8c17bfd); // ldp fp, lr, [sp], #16 + OSWriteLittleInt32(&buffer[64], 0, 0xD61F0A1F); // braaz x16 + } + + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } + +private: + + const ld::Atom& _stubTo; + mutable ld::Fixup _fixup1; + ld::Fixup _fixup2; + ld::Fixup _fixup3; + + static ld::Section _s_section; +}; + +ld::Section ResolverHelperAtom::_s_section("__TEXT", "__stub_helper", ld::Section::typeStubHelper); + + + +class LazyPointerAtom : public ld::Atom { +public: + LazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport, bool dataConstUsed) + : ld::Atom(selectSection(stubToGlobalWeakDef, stubToResolver, dataConstUsed), + ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeTranslationUnit, ld::Atom::typeLazyPointer, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), + _stubTo(stubTo), + _helper(pass, this, stubTo), + _resolverHelper(pass, this, stubTo), + _fixup1(0, ld::Fixup::k1of2, ld::Fixup::kindSetAuthData, (ld::Fixup::AuthData){ 0, false, ld::Fixup::AuthData::ptrauth_key_asia }), + _fixup2(0, ld::Fixup::k2of2, ld::Fixup::kindStoreTargetAddressLittleEndianAuth64, + stubToResolver ? &_resolverHelper : (stubToGlobalWeakDef ? &stubTo : &_helper)), + _fixup3(0, ld::Fixup::k1of1, ld::Fixup::kindLazyTarget, &stubTo) { + _fixup2.weakImport = weakImport; pass.addAtom(*this); + if ( stubToResolver ) + pass.addAtom(_resolverHelper); + else if ( !stubToGlobalWeakDef ) + pass.addAtom(_helper); + } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _stubTo.name(); } + virtual uint64_t size() const { return 8; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } + +private: + static ld::Section& selectSection(bool stubToGlobalWeakDef, bool stubToResolver, bool dataConstUsed) { + if ( stubToGlobalWeakDef && dataConstUsed ) + return _s_sectionWeak; + else if ( stubToResolver && dataConstUsed ) + return _s_sectionResolver; + else + return _s_section; + } + + const ld::Atom& _stubTo; + StubHelperAtom _helper; + ResolverHelperAtom _resolverHelper; + mutable ld::Fixup _fixup1; + ld::Fixup _fixup2; + ld::Fixup _fixup3; + + static ld::Section _s_section; + static ld::Section _s_sectionResolver; + static ld::Section _s_sectionWeak; +}; + +ld::Section LazyPointerAtom::_s_section("__DATA", "__la_symbol_ptr", ld::Section::typeLazyPointer); +ld::Section LazyPointerAtom::_s_sectionResolver("__DATA_DIRTY", "__la_resolver", ld::Section::typeLazyPointer); +ld::Section LazyPointerAtom::_s_sectionWeak("__DATA", "__la_weak_ptr", ld::Section::typeLazyPointer); + + +class StubAtom : public ld::Atom { +public: + StubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool stubToGlobalWeakDef, bool stubToResolver, bool weakImport, bool dataConstUsed) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _stubTo(stubTo), + _lazyPointer(pass, stubTo, stubToGlobalWeakDef, stubToResolver, weakImport, dataConstUsed), + _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, &_lazyPointer), + _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, &_lazyPointer), + _fixup3(ld::Fixup::kindLinkerOptimizationHint, LOH_ARM64_ADRP_LDR, 0, 4) + { pass.addAtom(*this); } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _stubTo.name(); } + virtual uint64_t size() const { return 12; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + OSWriteLittleInt32(&buffer[0], 0, 0x90000010); // ADRP X16, lazy_pointer@page + OSWriteLittleInt32(&buffer[4], 0, 0xF9400210); // LDR X16, [X16, lazy_pointer@pageoff] + OSWriteLittleInt32(&buffer[8], 0, 0xD61F0A1F); // BRAAZ X16 + } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup3)[1]; } + +private: + const ld::Atom& _stubTo; + LazyPointerAtom _lazyPointer; + mutable ld::Fixup _fixup1; + mutable ld::Fixup _fixup2; + mutable ld::Fixup _fixup3; + + static ld::Section _s_section; +}; + +ld::Section StubAtom::_s_section("__TEXT", "__stubs", ld::Section::typeStub); + + + +class NonLazyPointerAtom : public ld::Atom { +public: + NonLazyPointerAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool weakImport) + : ld::Atom(_s_section, ld::Atom::definitionRegular, + ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(3)), + _stubTo(stubTo), + _fixup1(0, ld::Fixup::k1of2, ld::Fixup::kindSetAuthData, (ld::Fixup::AuthData){ 0, true, ld::Fixup::AuthData::ptrauth_key_asia }), + _fixup2(0, ld::Fixup::k2of2, ld::Fixup::kindStoreTargetAddressLittleEndianAuth64, &stubTo) { + _fixup2.weakImport = weakImport; + pass.addAtom(*this); + } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _stubTo.name(); } + virtual uint64_t size() const { return 8; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; } + +private: + const ld::Atom& _stubTo; + ld::Fixup _fixup1; + ld::Fixup _fixup2; + + static ld::Section _s_section; +}; + +ld::Section NonLazyPointerAtom::_s_section("__DATA", "__auth_got", ld::Section::typeNonLazyPointer); + + +class NonLazyStubAtom : public ld::Atom { +public: + NonLazyStubAtom(ld::passes::stubs::Pass& pass, const ld::Atom& stubTo, + bool weakImport) + : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + ld::Atom::scopeLinkageUnit, ld::Atom::typeStub, + symbolTableNotIn, false, false, false, ld::Atom::Alignment(2)), + _stubTo(stubTo), + _nonLazyPointer(pass, stubTo, weakImport), + _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Page21, &_nonLazyPointer), + _fixup2(4, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64PageOff12, &_nonLazyPointer) { + asprintf((char**)&_name, "%s.stub", _stubTo.name()); + pass.addAtom(*this); + } + + virtual const ld::File* file() const { return _stubTo.file(); } + virtual const char* name() const { return _name; } + virtual uint64_t size() const { return 16; } + virtual uint64_t objectAddress() const { return 0; } + virtual void copyRawContent(uint8_t buffer[]) const { + OSWriteLittleInt32(&buffer[ 0], 0, 0x90000011); // ADRP X17, dyld_mageLoaderCache@page + OSWriteLittleInt32(&buffer[ 4], 0, 0x91000231); // ADD X17, X17, dyld_mageLoaderCache@pageoff + OSWriteLittleInt32(&buffer[ 8], 0, 0xF9400230); // LDR X16, [X17] + OSWriteLittleInt32(&buffer[12], 0, 0xD71F0A11); // BRAA X16, X17 + } + virtual void setScope(Scope) { } + virtual ld::Fixup::iterator fixupsBegin() const { return &_fixup1; } + virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup2)[1]; } + +private: + const ld::Atom& _stubTo; + const char* _name; + NonLazyPointerAtom _nonLazyPointer; + mutable ld::Fixup _fixup1; + mutable ld::Fixup _fixup2; + + static ld::Section _s_section; +}; + +ld::Section NonLazyStubAtom::_s_section("__TEXT", "__auth_stubs", ld::Section::typeStub); + + +} // namespace arm64e +#endif +