]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/passes/stubs/stub_arm64.hpp
ld64-409.12.tar.gz
[apple/ld64.git] / src / ld / passes / stubs / stub_arm64.hpp
index 815e28a53b1a80184a44e4f3b86d631c1b0ff7b5..e473f06540ca6db289af9fe0580e4e61d33e587d 100644 (file)
@@ -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
+