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),
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
|| (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:
// don't create GOT atoms during this loop because that could invalidate the sections iterator
std::vector<const ld::Atom*> atomsReferencingGOT;
std::map<const ld::Atom*,bool> weakImportMap;
+ std::map<const ld::Atom*,bool> weakDefMap;
atomsReferencingGOT.reserve(128);
for (std::vector<ld::Internal::FinalSection*>::iterator sit=internal.sections.begin(); sit != internal.sections.end(); ++sit) {
ld::Internal::FinalSection* sect = *sit;
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
}
if ( gotMap.count(targetOfGOT) == 0 )
gotMap[targetOfGOT] = NULL;
+ // record if target is weak def
+ weakDefMap[targetOfGOT] = targetIsExternalWeakDef;
// record weak_import attribute
std::map<const ld::Atom*,bool>::iterator pos = weakImportMap.find(targetOfGOT);
if ( pos == weakImportMap.end() ) {
// 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);
}
}
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