diff options
Diffstat (limited to 'lld/lib/Core')
| -rw-r--r-- | lld/lib/Core/Resolver.cpp | 9 | ||||
| -rw-r--r-- | lld/lib/Core/SymbolTable.cpp | 11 |
2 files changed, 18 insertions, 2 deletions
diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp index d56f7d1067f..716f0d48d53 100644 --- a/lld/lib/Core/Resolver.cpp +++ b/lld/lib/Core/Resolver.cpp @@ -198,7 +198,7 @@ void Resolver::resolveUndefines() { undefineGenCount = _symbolTable.size(); std::vector<const UndefinedAtom *> undefines; _symbolTable.undefines(undefines); - for ( const Atom *undefAtom : undefines ) { + for (const UndefinedAtom *undefAtom : undefines) { StringRef undefName = undefAtom->name(); // load for previous undefine may also have loaded this undefine if (!_symbolTable.isDefined(undefName)) { @@ -208,6 +208,13 @@ void Resolver::resolveUndefines() { false, // dataSymbolOnly *this); } + // If the undefined symbol has an alternative name, try to resolve the + // symbol with the name to give it a second chance. This feature is used + // for COFF "weak external" symbol. + if (const UndefinedAtom *fallbackUndefAtom = undefAtom->fallback()) { + _symbolTable.addReplacement(undefAtom, fallbackUndefAtom); + _symbolTable.add(*fallbackUndefAtom); + } } // search libraries for overrides of common symbols if (searchArchives || searchSharedLibs) { diff --git a/lld/lib/Core/SymbolTable.cpp b/lld/lib/Core/SymbolTable.cpp index 3b43c2effa8..8fee4bb41e3 100644 --- a/lld/lib/Core/SymbolTable.cpp +++ b/lld/lib/Core/SymbolTable.cpp @@ -311,6 +311,11 @@ bool SymbolTable::isDefined(StringRef sym) { return true; } +void SymbolTable::addReplacement(const Atom *replaced, + const Atom *replacement) { + _replacedAtoms[replaced] = replacement; +} + const Atom *SymbolTable::replacement(const Atom *atom) { AtomToAtom::iterator pos = _replacedAtoms.find(atom); if (pos == _replacedAtoms.end()) @@ -328,8 +333,12 @@ void SymbolTable::undefines(std::vector<const UndefinedAtom *> &undefs) { end = _nameTable.end(); it != end; ++it) { const Atom *atom = it->second; assert(atom != nullptr); - if (const auto undef = dyn_cast<const UndefinedAtom>(atom)) + if (const auto undef = dyn_cast<const UndefinedAtom>(atom)) { + AtomToAtom::iterator pos = _replacedAtoms.find(undef); + if (pos != _replacedAtoms.end()) + continue; undefs.push_back(undef); + } } } |

