X-Git-Url: https://git.saurik.com/apple/ld64.git/blobdiff_plain/b2fa67a80bc53211e4d1ea81f23e9f953ee1dd6c..e667b16e39593d19d0e25a8440a563eac3572653:/src/ld/passes/stubs/stubs.cpp diff --git a/src/ld/passes/stubs/stubs.cpp b/src/ld/passes/stubs/stubs.cpp index aa4aaf1..c01f3f9 100644 --- a/src/ld/passes/stubs/stubs.cpp +++ b/src/ld/passes/stubs/stubs.cpp @@ -35,6 +35,7 @@ #include #include "Options.h" +#include "MachOFileAbstraction.hpp" #include "ld.hpp" #include "make_stubs.h" @@ -89,8 +90,9 @@ private: #include "stub_x86_classic.hpp" #include "stub_arm.hpp" #include "stub_arm_classic.hpp" - - +#if SUPPORT_ARCH_arm64 +#include "stub_arm64.hpp" +#endif Pass::Pass(const Options& opts) : compressedHelperHelper(NULL), @@ -118,6 +120,10 @@ const ld::Atom* Pass::stubableFixup(const ld::Fixup* fixup, ld::Internal& state) 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; @@ -175,20 +181,31 @@ ld::Atom* Pass::makeStub(const ld::Atom& target, bool weakImport) } switch ( _architecture ) { +#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 ) @@ -203,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"; } @@ -226,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: @@ -236,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 @@ -302,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; @@ -310,7 +350,7 @@ void Pass::process(ld::Internal& state) return; // 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 @@ -357,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::iterator sit=state.sections.begin(); sit != state.sections.end(); ++sit) { ld::Internal::FinalSection* sect = *sit;