diff options
Diffstat (limited to 'lld/ELF/SymbolTable.cpp')
-rw-r--r-- | lld/ELF/SymbolTable.cpp | 52 |
1 files changed, 30 insertions, 22 deletions
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index f7a8a99cf8f9..afc8b05f8767 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -26,10 +26,10 @@ using namespace llvm; using namespace llvm::object; using namespace llvm::ELF; +using namespace lld; +using namespace lld::elf; -namespace lld { -namespace elf { -SymbolTable *symtab; +SymbolTable *elf::symtab; void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) { // Swap symbols as instructed by -wrap. @@ -40,12 +40,18 @@ void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) { idx2 = idx1; idx1 = idx3; - // Now renaming is complete. No one refers Real symbol. We could leave - // Real as-is, but if Real is written to the symbol table, that may - // contain irrelevant values. So, we copy all values from Sym to Real. - StringRef s = real->getName(); + if (real->exportDynamic) + sym->exportDynamic = true; + + // Now renaming is complete, and no one refers to real. We drop real from + // .symtab and .dynsym. If real is undefined, it is important that we don't + // leave it in .dynsym, because otherwise it might lead to an undefined symbol + // error in a subsequent link. If real is defined, we could emit real as an + // alias for sym, but that could degrade the user experience of some tools + // that can print out only one symbol for each location: sym is a preferred + // name than real, but they might print out real instead. memcpy(real, sym, sizeof(SymbolUnion)); - real->setName(s); + real->isUsedInRegularObj = false; } // Find an existing symbol or create a new one. @@ -88,7 +94,7 @@ Symbol *SymbolTable::insert(StringRef name) { } Symbol *SymbolTable::addSymbol(const Symbol &newSym) { - Symbol *sym = symtab->insert(newSym.getName()); + Symbol *sym = insert(newSym.getName()); sym->resolve(newSym); return sym; } @@ -103,6 +109,13 @@ Symbol *SymbolTable::find(StringRef name) { return sym; } +// A version script/dynamic list is only meaningful for a Defined symbol. +// A CommonSymbol will be converted to a Defined in replaceCommonSymbols(). +// A lazy symbol may be made Defined if an LTO libcall fetches it. +static bool canBeVersioned(const Symbol &sym) { + return sym.isDefined() || sym.isCommon() || sym.isLazy(); +} + // Initialize demangledSyms with a map from demangled symbols to symbol // objects. Used to handle "extern C++" directive in version scripts. // @@ -119,11 +132,9 @@ Symbol *SymbolTable::find(StringRef name) { StringMap<std::vector<Symbol *>> &SymbolTable::getDemangledSyms() { if (!demangledSyms) { demangledSyms.emplace(); - for (Symbol *sym : symVector) { - if (!sym->isDefined() && !sym->isCommon()) - continue; - (*demangledSyms)[demangleItanium(sym->getName())].push_back(sym); - } + for (Symbol *sym : symVector) + if (canBeVersioned(*sym)) + (*demangledSyms)[demangleItanium(sym->getName())].push_back(sym); } return *demangledSyms; } @@ -131,15 +142,15 @@ StringMap<std::vector<Symbol *>> &SymbolTable::getDemangledSyms() { std::vector<Symbol *> SymbolTable::findByVersion(SymbolVersion ver) { if (ver.isExternCpp) return getDemangledSyms().lookup(ver.name); - if (Symbol *b = find(ver.name)) - if (b->isDefined() || b->isCommon()) - return {b}; + if (Symbol *sym = find(ver.name)) + if (canBeVersioned(*sym)) + return {sym}; return {}; } std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion ver) { std::vector<Symbol *> res; - StringMatcher m(ver.name); + SingleStringMatcher m(ver.name); if (ver.isExternCpp) { for (auto &p : getDemangledSyms()) @@ -149,7 +160,7 @@ std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion ver) { } for (Symbol *sym : symVector) - if ((sym->isDefined() || sym->isCommon()) && m.match(sym->getName())) + if (canBeVersioned(*sym) && m.match(sym->getName())) res.push_back(sym); return res; } @@ -264,6 +275,3 @@ void SymbolTable::scanVersionScript() { // --dynamic-list. handleDynamicList(); } - -} // namespace elf -} // namespace lld |