diff options
-rw-r--r-- | lld/ELF/SymbolTable.cpp | 61 | ||||
-rw-r--r-- | lld/ELF/SymbolTable.h | 6 |
2 files changed, 31 insertions, 36 deletions
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 08d9d0ac752..3284dd2dcce 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -154,19 +154,12 @@ template <class ELFT> void SymbolTable<ELFT>::resolve(SymbolBody *New) { SymbolBody *Existing = Sym->Body; if (Lazy *L = dyn_cast<Lazy>(Existing)) { - if (New->isUndefined()) { - if (New->isWeak()) { - // See the explanation in SymbolTable::addLazy - L->setUsedInRegularObj(); - L->setWeak(); - return; - } - addMemberFile(L); + if (auto *Undef = dyn_cast<Undefined<ELFT>>(New)) { + addMemberFile(Undef, L); return; } - - // Found a definition for something also in an archive. Ignore the archive - // definition. + // Found a definition for something also in an archive. + // Ignore the archive definition. Sym->Body = New; return; } @@ -208,29 +201,14 @@ template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) { return It->second->Body; } -template <class ELFT> void SymbolTable<ELFT>::addLazy(Lazy *New) { - Symbol *Sym = insert(New); - if (Sym->Body == New) - return; - SymbolBody *Existing = Sym->Body; - if (Existing->isDefined() || Existing->isLazy()) - return; - Sym->Body = New; - assert(Existing->isUndefined() && "Unexpected symbol kind."); - - // Weak undefined symbols should not fetch members from archives. - // If we were to keep old symbol we would not know that an archive member was - // available if a strong undefined symbol shows up afterwards in the link. - // If a strong undefined symbol never shows up, this lazy symbol will - // get to the end of the link and must be treated as the weak undefined one. - // We set UsedInRegularObj in a similar way to what is done with shared - // symbols and mark it as weak to reduce how many special cases are needed. - if (Existing->isWeak()) { - New->setUsedInRegularObj(); - New->setWeak(); +template <class ELFT> void SymbolTable<ELFT>::addLazy(Lazy *L) { + Symbol *Sym = insert(L); + if (Sym->Body == L) return; + if (auto *Undef = dyn_cast<Undefined<ELFT>>(Sym->Body)) { + Sym->Body = L; + addMemberFile(Undef, L); } - addMemberFile(New); } template <class ELFT> @@ -247,9 +225,24 @@ void SymbolTable<ELFT>::checkCompatibility(std::unique_ptr<InputFile> &File) { error(A + " is incompatible with " + B); } -template <class ELFT> void SymbolTable<ELFT>::addMemberFile(Lazy *Body) { +template <class ELFT> +void SymbolTable<ELFT>::addMemberFile(Undefined<ELFT> *Undef, Lazy *L) { + // Weak undefined symbols should not fetch members from archives. + // If we were to keep old symbol we would not know that an archive member was + // available if a strong undefined symbol shows up afterwards in the link. + // If a strong undefined symbol never shows up, this lazy symbol will + // get to the end of the link and must be treated as the weak undefined one. + // We set UsedInRegularObj in a similar way to what is done with shared + // symbols and mark it as weak to reduce how many special cases are needed. + if (Undef->isWeak()) { + L->setUsedInRegularObj(); + L->setWeak(); + return; + } + + // Fetch a member file that has the definition for L. // getMember returns nullptr if the member was already read from the library. - if (std::unique_ptr<InputFile> File = Body->getMember()) + if (std::unique_ptr<InputFile> File = L->getMember()) addFile(std::move(File)); } diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h index 81503866a13..a6b478a75d1 100644 --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -15,8 +15,10 @@ namespace lld { namespace elf2 { -template <class ELFT> class OutputSectionBase; +class Lazy; struct Symbol; +template <class ELFT> class OutputSectionBase; +template <class ELFT> class Undefined; // SymbolTable is a bucket of all known symbols, including defined, // undefined, or lazy symbols (the last one is symbols in archive @@ -62,7 +64,7 @@ public: private: Symbol *insert(SymbolBody *New); void addLazy(Lazy *New); - void addMemberFile(Lazy *Body); + void addMemberFile(Undefined<ELFT> *Undef, Lazy *L); void checkCompatibility(std::unique_ptr<InputFile> &File); void resolve(SymbolBody *Body); std::string conflictMsg(SymbolBody *Old, SymbolBody *New); |