aboutsummaryrefslogtreecommitdiff
path: root/lld/ELF/SymbolTable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/SymbolTable.cpp')
-rw-r--r--lld/ELF/SymbolTable.cpp52
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