]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/passes/stubs/stubs.cpp
ld64-242.2.tar.gz
[apple/ld64.git] / src / ld / passes / stubs / stubs.cpp
index 274878bdc8ee9da4758c337c0726184da7b7b43b..c01f3f9cc86adebc28a1eabdd7bf1181d75c4c33 100644 (file)
@@ -35,6 +35,7 @@
 #include <map>
 
 #include "Options.h"
+#include "MachOFileAbstraction.hpp"
 #include "ld.hpp"
 
 #include "make_stubs.h"
@@ -89,9 +90,9 @@ private:
 #include "stub_x86_classic.hpp"
 #include "stub_arm.hpp"
 #include "stub_arm_classic.hpp"
-#include "stub_ppc_classic.hpp"
-
-
+#if SUPPORT_ARCH_arm64
+#include "stub_arm64.hpp"
+#endif
 
 Pass::Pass(const Options& opts) 
        :       compressedHelperHelper(NULL), 
@@ -116,10 +117,13 @@ const ld::Atom* Pass::stubableFixup(const ld::Fixup* fixup, ld::Internal& state)
        if ( fixup->binding == ld::Fixup::bindingsIndirectlyBound ) {
                const ld::Atom* target = state.indirectBindingTable[fixup->u.bindingIndex];
                switch ( fixup->kind ) {
-                       case ld::Fixup::kindStoreTargetAddressPPCBranch24:
                        case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
                        case ld::Fixup::kindStoreTargetAddressARMBranch24:
                        case ld::Fixup::kindStoreTargetAddressThumbBranch22:
+#if SUPPORT_ARCH_arm64
+                       case ld::Fixup::kindStoreTargetAddressARM64Branch26:
+#endif
+                assert(target != NULL);
                                // create stub if target is in a dylib
                                if ( target->definition() == ld::Atom::definitionProxy ) 
                                        return target;
@@ -177,29 +181,31 @@ ld::Atom* Pass::makeStub(const ld::Atom& target, bool weakImport)
        }
 
        switch ( _architecture ) {
-               case CPU_TYPE_POWERPC: 
-                       if ( _pic )
-                               return new ld::passes::stubs::ppc::classic::StubPICAtom(*this, target, forLazyDylib, false, weakImport);
-                       else
-                               return new ld::passes::stubs::ppc::classic::StubNoPICAtom(*this, target, forLazyDylib, false, weakImport);
-                       break;
-               case CPU_TYPE_POWERPC64: 
-                       return new ld::passes::stubs::ppc::classic::StubPICAtom(*this, target, forLazyDylib, true, weakImport);
-                       break;
+#if SUPPORT_ARCH_i386
                case CPU_TYPE_I386:
                        if ( usingCompressedLINKEDIT() && !forLazyDylib )
                                return new ld::passes::stubs::x86::StubAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport);
                        else
                                return new ld::passes::stubs::x86::classic::StubAtom(*this, target, forLazyDylib, weakImport);
                        break;
+#endif
+#if SUPPORT_ARCH_x86_64
                case CPU_TYPE_X86_64:
-                       if ( usingCompressedLINKEDIT() && !forLazyDylib )
+                       if ( (_options.outputKind() == Options::kKextBundle) && _options.kextsUseStubs() ) 
+                               return new ld::passes::stubs::x86_64::KextStubAtom(*this, target);
+                       else if ( usingCompressedLINKEDIT() && !forLazyDylib )
                                return new ld::passes::stubs::x86_64::StubAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport);
                        else
                                return new ld::passes::stubs::x86_64::classic::StubAtom(*this, target, forLazyDylib, weakImport);
                        break;
+#endif
+#if SUPPORT_ARCH_arm_any
                case CPU_TYPE_ARM: 
-                       if ( usingCompressedLINKEDIT() && !forLazyDylib ) {
+                       if ( (_options.outputKind() == Options::kKextBundle) && _options.kextsUseStubs() ) {
+                               // if text relocs are not allows in kext bundles, then linker must create a stub 
+                               return new ld::passes::stubs::arm::StubPICKextAtom(*this, target);
+                       }
+                       else if ( usingCompressedLINKEDIT() && !forLazyDylib ) {
                                if ( (_stubCount < 900) && !_mightBeInSharedRegion && !_largeText )
                                        return new ld::passes::stubs::arm::StubCloseAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport);
                                else if ( _pic )
@@ -214,6 +220,15 @@ ld::Atom* Pass::makeStub(const ld::Atom& target, bool weakImport)
                                        return new ld::passes::stubs::arm::classic::StubNoPICAtom(*this, target, forLazyDylib, weakImport);
                        }
                        break;
+#endif
+#if SUPPORT_ARCH_arm64
+               case CPU_TYPE_ARM64:
+                       if ( (_options.outputKind() == Options::kKextBundle) && _options.kextsUseStubs() ) 
+                               return new ld::passes::stubs::arm64::KextStubAtom(*this, target);
+                       else
+                               return new ld::passes::stubs::arm64::StubAtom(*this, target, stubToGlobalWeakDef, stubToResolver, weakImport);
+                       break;
+#endif
        }
        throw "unsupported arch for stub";
 }
@@ -237,7 +252,6 @@ void Pass::process(ld::Internal& state)
                case Options::kObjectFile:
                        // these kinds don't use stubs and can have resolver functions
                        return;
-               case Options::kKextBundle:
                case Options::kStaticExecutable:
                case Options::kPreload:
                case Options::kDyld:
@@ -247,6 +261,12 @@ void Pass::process(ld::Internal& state)
                case Options::kDynamicLibrary:
                        // uses stubs and can have resolver functions
                        break;
+               case Options::kKextBundle:
+                       verifyNoResolverFunctions(state);
+                       // if kext don't use stubs, don't do this pass
+                       if ( !_options.kextsUseStubs() )
+                               return;
+                       break;
                case Options::kDynamicExecutable:
                case Options::kDynamicBundle:
                        // these kinds do use stubs and cannot have resolver functions
@@ -304,9 +324,7 @@ void Pass::process(ld::Internal& state)
                                if ( _options.outputKind() != Options::kDynamicLibrary ) 
                                        throwf("resolver functions (%s) can only be used in dylibs", atom->name());
                                if ( !_options.makeCompressedDyldInfo() ) {
-                                       if ( _options.architecture() == CPU_TYPE_POWERPC )
-                                               throwf("resolver functions (%s) not supported for PowerPC", atom->name());
-                                       else if ( _options.architecture() == CPU_TYPE_ARM )
+                                       if ( _options.architecture() == CPU_TYPE_ARM )
                                                throwf("resolver functions (%s) can only be used when targeting iOS 4.2 or later", atom->name());
                                        else
                                                throwf("resolver functions (%s) can only be used when targeting Mac OS X 10.6 or later", atom->name());
@@ -315,6 +333,15 @@ void Pass::process(ld::Internal& state)
                        }
                }
        }
+
+       const bool needStubForMain = _options.needsEntryPointLoadCommand() 
+                                                               && (state.entryPoint != NULL) 
+                                                               && (state.entryPoint->definition() == ld::Atom::definitionProxy);
+       if ( needStubForMain ) {
+               // _main not found in any .o files.  Currently have proxy to dylib 
+               // Add to map, so that a stub will be made
+               stubFor[state.entryPoint] = NULL;       
+       }
        
        // short circuit if no stubs needed
        _internal = &state;
@@ -323,7 +350,7 @@ void Pass::process(ld::Internal& state)
                return;
        
        // <rdar://problem/8553283> lazily check for helper
-       if ( !_options.makeCompressedDyldInfo() && (state.classicBindingHelper == NULL) ) 
+       if ( !_options.makeCompressedDyldInfo() && (state.classicBindingHelper == NULL) && (_options.outputKind() != Options::kKextBundle) 
                throw "symbol dyld_stub_binding_helper not found, normally in crt1.o/dylib1.o/bundle1.o";
 
        // disable arm close stubs in some cases
@@ -370,6 +397,13 @@ void Pass::process(ld::Internal& state)
                }
        }
        
+       // switch entry point from proxy to stub
+       if ( needStubForMain ) {
+               const ld::Atom* mainStub = stubFor[state.entryPoint];   
+               assert(mainStub != NULL);
+               state.entryPoint = mainStub;
+       }
+       
        // sort new atoms so links are consistent
        for (std::vector<ld::Internal::FinalSection*>::iterator sit=state.sections.begin(); sit != state.sections.end(); ++sit) {
                ld::Internal::FinalSection* sect = *sit;