X-Git-Url: https://git.saurik.com/apple/ld64.git/blobdiff_plain/e667b16e39593d19d0e25a8440a563eac3572653..7f09b9353af9897bf18933788d6a59c152c29edd:/src/ld/passes/got.cpp diff --git a/src/ld/passes/got.cpp b/src/ld/passes/got.cpp index 66caf34..01c2e30 100644 --- a/src/ld/passes/got.cpp +++ b/src/ld/passes/got.cpp @@ -44,8 +44,8 @@ class File; // forward reference class GOTEntryAtom : public ld::Atom { public: - GOTEntryAtom(ld::Internal& internal, const ld::Atom* target, bool weakImport, bool is64) - : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, + GOTEntryAtom(ld::Internal& internal, const ld::Atom* target, bool weakImport, bool weakDef, bool is64) + : ld::Atom(weakDef ? _s_sectionWeak : _s_section, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeLinkageUnit, ld::Atom::typeNonLazyPointer, symbolTableNotIn, false, false, false, (is64 ? ld::Atom::Alignment(3) : ld::Atom::Alignment(2))), _fixup(0, ld::Fixup::k1of1, (is64 ? ld::Fixup::kindStoreTargetAddressLittleEndian64 : ld::Fixup::kindStoreTargetAddressLittleEndian32), target), @@ -68,13 +68,16 @@ private: bool _is64; static ld::Section _s_section; + static ld::Section _s_sectionWeak; }; ld::Section GOTEntryAtom::_s_section("__DATA", "__got", ld::Section::typeNonLazyPointer); +ld::Section GOTEntryAtom::_s_sectionWeak("__DATA", "__got_weak", ld::Section::typeNonLazyPointer); -static bool gotFixup(const Options& opts, ld::Internal& internal, const ld::Atom* targetOfGOT, const ld::Fixup* fixup, bool* optimizable) +static bool gotFixup(const Options& opts, ld::Internal& internal, const ld::Atom* targetOfGOT, const ld::Fixup* fixup, bool* optimizable, bool* targetIsExternalWeakDef) { + *targetIsExternalWeakDef = false; switch (fixup->kind) { case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad: #if SUPPORT_ARCH_arm64 @@ -92,14 +95,15 @@ static bool gotFixup(const Options& opts, ld::Internal& internal, const ld::Atom || (targetOfGOT->section().type() == ld::Section::typeTentativeDefs)) ) { *optimizable = false; } - if ( targetOfGOT->scope() == ld::Atom::scopeGlobal ) { + if ( targetOfGOT->scope() == ld::Atom::scopeGlobal ) { // cannot do LEA optimization if target is weak exported symbol - if ( (targetOfGOT->definition() == ld::Atom::definitionRegular) && (targetOfGOT->combine() == ld::Atom::combineByName) ) { + if ( ((targetOfGOT->definition() == ld::Atom::definitionRegular) || (targetOfGOT->definition() == ld::Atom::definitionProxy)) && (targetOfGOT->combine() == ld::Atom::combineByName) ) { switch ( opts.outputKind() ) { case Options::kDynamicExecutable: case Options::kDynamicLibrary: case Options::kDynamicBundle: case Options::kKextBundle: + *targetIsExternalWeakDef = true; *optimizable = false; break; case Options::kStaticExecutable: @@ -199,6 +203,7 @@ void doPass(const Options& opts, ld::Internal& internal) // don't create GOT atoms during this loop because that could invalidate the sections iterator std::vector atomsReferencingGOT; std::map weakImportMap; + std::map weakDefMap; atomsReferencingGOT.reserve(128); for (std::vector::iterator sit=internal.sections.begin(); sit != internal.sections.end(); ++sit) { ld::Internal::FinalSection* sect = *sit; @@ -223,7 +228,8 @@ void doPass(const Options& opts, ld::Internal& internal) break; } bool optimizable; - if ( !gotFixup(opts, internal, targetOfGOT, fit, &optimizable) ) + bool targetIsExternalWeakDef; + if ( !gotFixup(opts, internal, targetOfGOT, fit, &optimizable, &targetIsExternalWeakDef) ) continue; if ( optimizable ) { // change from load of GOT entry to lea of target @@ -264,6 +270,8 @@ void doPass(const Options& opts, ld::Internal& internal) } if ( gotMap.count(targetOfGOT) == 0 ) gotMap[targetOfGOT] = NULL; + // record if target is weak def + weakDefMap[targetOfGOT] = targetIsExternalWeakDef; // record weak_import attribute std::map::iterator pos = weakImportMap.find(targetOfGOT); if ( pos == weakImportMap.end() ) { @@ -319,7 +327,7 @@ void doPass(const Options& opts, ld::Internal& internal) // make GOT entries for (auto& entry : gotMap) { if ( entry.second == NULL ) { - entry.second = new GOTEntryAtom(internal, entry.first, weakImportMap[entry.first], is64); + entry.second = new GOTEntryAtom(internal, entry.first, weakImportMap[entry.first], opts.useDataConstSegment() && weakDefMap[entry.first], is64); if (log) fprintf(stderr, "making new GOT slot for %s, gotMap[%p] = %p\n", entry.first->name(), entry.first, entry.second); } } @@ -348,7 +356,8 @@ void doPass(const Options& opts, ld::Internal& internal) break; } bool optimizable; - if ( (targetOfGOT == NULL) || !gotFixup(opts, internal, targetOfGOT, fit, &optimizable) ) + bool targetIsExternalWeakDef; + if ( (targetOfGOT == NULL) || !gotFixup(opts, internal, targetOfGOT, fit, &optimizable, &targetIsExternalWeakDef) ) continue; if ( !optimizable ) { // GOT use not optimized away, update to bind to GOT entry