summaryrefslogtreecommitdiffstats
path: root/lld/ELF/SymbolTable.cpp
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2019-05-16 03:29:03 +0000
committerRui Ueyama <ruiu@google.com>2019-05-16 03:29:03 +0000
commit5c073a94f9c25e73d78dbeb8eb7b1b3a60d7dd1f (patch)
tree5b4926869d3408f072134ca8ba057d4e1fc964a8 /lld/ELF/SymbolTable.cpp
parentd5529629fb18ae184ef8db8358263031e19aeba9 (diff)
downloadbcm5719-llvm-5c073a94f9c25e73d78dbeb8eb7b1b3a60d7dd1f.tar.gz
bcm5719-llvm-5c073a94f9c25e73d78dbeb8eb7b1b3a60d7dd1f.zip
Introduce CommonSymbol.
Previously, we handled common symbols as a kind of Defined symbol, but what we were doing for common symbols is pretty different from regular defined symbols. Common symbol and defined symbol are probably as different as shared symbol and defined symbols are different. This patch introduces CommonSymbol to represent common symbols. After symbols are resolved, they are converted to Defined symbols residing in a .bss section. Differential Revision: https://reviews.llvm.org/D61895 llvm-svn: 360841
Diffstat (limited to 'lld/ELF/SymbolTable.cpp')
-rw-r--r--lld/ELF/SymbolTable.cpp196
1 files changed, 93 insertions, 103 deletions
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index 9c561788165..387e92cb20b 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -86,11 +86,8 @@ static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
return std::min(VA, VB);
}
-// Find an existing symbol or create and insert a new one, then apply the given
-// attributes.
-std::pair<Symbol *, bool> SymbolTable::insert(const Symbol &New) {
- // Find an existing symbol or create and insert a new one.
-
+// Find an existing symbol or create and insert a new one.
+Symbol *SymbolTable::insert(const Symbol &New) {
// <name>@@<version> means the symbol is the default version. In that
// case <name>@@<version> will be used to resolve references to <name>.
//
@@ -130,26 +127,36 @@ std::pair<Symbol *, bool> SymbolTable::insert(const Symbol &New) {
Old = SymVector[SymIndex];
}
+ return Old;
+}
+
+// Merge symbol properties.
+//
+// When we have many symbols of the same name, we choose one of them,
+// and that's the result of symbol resolution. However, symbols that
+// were not chosen still affect some symbol properteis.
+void SymbolTable::mergeProperties(Symbol *Old, const Symbol &New) {
// Merge symbol properties.
Old->ExportDynamic = Old->ExportDynamic || New.ExportDynamic;
Old->IsUsedInRegularObj = Old->IsUsedInRegularObj || New.IsUsedInRegularObj;
// DSO symbols do not affect visibility in the output.
- if (!isa<SharedSymbol>(&New))
+ if (!isa<SharedSymbol>(New))
Old->Visibility = getMinVisibility(Old->Visibility, New.Visibility);
-
- return {Old, IsNew};
}
template <class ELFT> Symbol *SymbolTable::addUndefined(const Undefined &New) {
- Symbol *Old;
- bool WasInserted;
- std::tie(Old, WasInserted) = insert(New);
+ Symbol *Old = insert(New);
+ mergeProperties(Old, New);
+
+ if (Old->isPlaceholder()) {
+ replaceSymbol(Old, &New);
+ return Old;
+ }
// An undefined symbol with non default visibility must be satisfied
// in the same DSO.
- if (WasInserted ||
- (isa<SharedSymbol>(Old) && New.Visibility != STV_DEFAULT)) {
+ if (Old->isShared() && New.Visibility != STV_DEFAULT) {
replaceSymbol(Old, &New);
return Old;
}
@@ -245,95 +252,80 @@ static int compareVersion(StringRef OldName, StringRef NewName) {
return 0;
}
-// We have a new defined symbol with the specified binding. Return 1 if the new
-// symbol should win, -1 if the new symbol should lose, or 0 if both symbols are
-// strong defined symbols.
-static int compareDefined(const Symbol *Old, const Symbol *New) {
- if (!Old->isDefined())
+// Compare two symbols. Return 1 if the new symbol should win, -1 if
+// the new symbol should lose, or 0 if there is a conflict.
+static int compare(const Symbol *Old, const Symbol *New) {
+ assert(New->isDefined() || New->isCommon());
+
+ if (!Old->isDefined() && !Old->isCommon())
return 1;
+
if (int Cmp = compareVersion(Old->getName(), New->getName()))
return Cmp;
- if (New->Binding == STB_WEAK)
+
+ if (New->isWeak())
return -1;
+
if (Old->isWeak())
return 1;
- return 0;
-}
-// We have a new non-common defined symbol with the specified binding. Return 1
-// if the new symbol should win, -1 if the new symbol should lose, or 0 if there
-// is a conflict. If the new symbol wins, also update the binding.
-static int compareDefinedNonCommon(const Symbol *OldSym, const Defined *New) {
- if (int Cmp = compareDefined(OldSym, New))
- return Cmp;
-
- if (auto *Old = dyn_cast<Defined>(OldSym)) {
- if (Old->Section && isa<BssSection>(Old->Section)) {
- // Non-common symbols take precedence over common symbols.
- if (Config->WarnCommon)
- warn("common " + Old->getName() + " is overridden");
- return 1;
- }
+ if (Old->isCommon() && New->isCommon()) {
+ if (Config->WarnCommon)
+ warn("multiple common of " + Old->getName());
+ return 0;
+ }
- if (New->File && isa<BitcodeFile>(New->File))
- return 0;
+ if (Old->isCommon()) {
+ if (Config->WarnCommon)
+ warn("common " + Old->getName() + " is overridden");
+ return 1;
+ }
- if (Old->Section == nullptr && New->Section == nullptr &&
- Old->Value == New->Value && New->Binding == STB_GLOBAL)
- return -1;
+ if (New->isCommon()) {
+ if (Config->WarnCommon)
+ warn("common " + Old->getName() + " is overridden");
+ return -1;
}
+
+ auto *OldSym = cast<Defined>(Old);
+ auto *NewSym = cast<Defined>(New);
+
+ if (New->File && isa<BitcodeFile>(New->File))
+ return 0;
+
+ if (!OldSym->Section && !NewSym->Section && OldSym->Value == NewSym->Value &&
+ NewSym->Binding == STB_GLOBAL)
+ return -1;
+
return 0;
}
-Symbol *SymbolTable::addCommon(const Defined &New) {
- Symbol *Old;
- bool WasInserted;
- std::tie(Old, WasInserted) = insert(New);
-
- auto Replace = [&] {
- auto *Bss = make<BssSection>("COMMON", New.Size, New.Value);
- Bss->File = New.File;
- Bss->Live = !Config->GcSections;
- InputSections.push_back(Bss);
-
- Defined Sym = New;
- Sym.Value = 0;
- Sym.Section = Bss;
- replaceSymbol(Old, &Sym);
- };
-
- if (WasInserted) {
- Replace();
+Symbol *SymbolTable::addCommon(const CommonSymbol &New) {
+ Symbol *Old = insert(New);
+ mergeProperties(Old, New);
+
+ if (Old->isPlaceholder()) {
+ replaceSymbol(Old, &New);
return Old;
}
- int Cmp = compareDefined(Old, &New);
+ int Cmp = compare(Old, &New);
if (Cmp < 0)
return Old;
if (Cmp > 0) {
- Replace();
- return Old;
- }
-
- auto *D = cast<Defined>(Old);
- auto *Bss = dyn_cast_or_null<BssSection>(D->Section);
- if (!Bss) {
- // Non-common symbols take precedence over common symbols.
- if (Config->WarnCommon)
- warn("common " + Old->getName() + " is overridden");
+ replaceSymbol(Old, &New);
return Old;
}
- if (Config->WarnCommon)
- warn("multiple common of " + D->getName());
+ CommonSymbol *OldSym = cast<CommonSymbol>(Old);
- Bss->Alignment = std::max<uint32_t>(Bss->Alignment, New.Value);
- if (New.Size > Bss->Size) {
- D->File = Bss->File = New.File;
- D->Size = Bss->Size = New.Size;
+ OldSym->Alignment = std::max(OldSym->Alignment, New.Alignment);
+ if (OldSym->Size < New.Size) {
+ OldSym->File = New.File;
+ OldSym->Size = New.Size;
}
- return Old;
+ return OldSym;
}
static void reportDuplicate(Symbol *Sym, InputFile *NewFile,
@@ -371,38 +363,38 @@ static void reportDuplicate(Symbol *Sym, InputFile *NewFile,
error(Msg);
}
-Defined *SymbolTable::addDefined(const Defined &New) {
- Symbol *Old;
- bool WasInserted;
- std::tie(Old, WasInserted) = insert(New);
+Symbol *SymbolTable::addDefined(const Defined &New) {
+ Symbol *Old = insert(New);
+ mergeProperties(Old, New);
- if (WasInserted) {
+ if (Old->isPlaceholder()) {
replaceSymbol(Old, &New);
- return cast<Defined>(Old);
+ return Old;
}
- int Cmp = compareDefinedNonCommon(Old, &New);
+ int Cmp = compare(Old, &New);
if (Cmp > 0)
replaceSymbol(Old, &New);
else if (Cmp == 0)
reportDuplicate(Old, New.File,
dyn_cast_or_null<InputSectionBase>(New.Section), New.Value);
- return cast<Defined>(Old);
+ return Old;
}
void SymbolTable::addShared(const SharedSymbol &New) {
- Symbol *Old;
- bool WasInserted;
- std::tie(Old, WasInserted) = insert(New);
+ Symbol *Old = insert(New);
+ mergeProperties(Old, New);
// Make sure we preempt DSO symbols with default visibility.
if (New.Visibility == STV_DEFAULT)
Old->ExportDynamic = true;
- if (WasInserted) {
+ if (Old->isPlaceholder()) {
replaceSymbol(Old, &New);
- } else if (Old->Visibility == STV_DEFAULT &&
- (Old->isUndefined() || Old->isLazy())) {
+ return;
+ }
+
+ if (Old->Visibility == STV_DEFAULT && (Old->isUndefined() || Old->isLazy())) {
// An undefined symbol with non default visibility must be satisfied
// in the same DSO.
uint8_t Binding = Old->Binding;
@@ -412,16 +404,15 @@ void SymbolTable::addShared(const SharedSymbol &New) {
}
Symbol *SymbolTable::addBitcode(const Defined &New) {
- Symbol *Old;
- bool WasInserted;
- std::tie(Old, WasInserted) = insert(New);
+ Symbol *Old = insert(New);
+ mergeProperties(Old, New);
- if (WasInserted) {
+ if (Old->isPlaceholder()) {
replaceSymbol(Old, &New);
return Old;
}
- int Cmp = compareDefinedNonCommon(Old, &New);
+ int Cmp = compare(Old, &New);
if (Cmp > 0)
replaceSymbol(Old, &New);
else if (Cmp == 0)
@@ -439,11 +430,10 @@ Symbol *SymbolTable::find(StringRef Name) {
}
template <class ELFT, class LazyT> void SymbolTable::addLazy(const LazyT &New) {
- Symbol *Old;
- bool WasInserted;
- std::tie(Old, WasInserted) = insert(New);
+ Symbol *Old = insert(New);
+ mergeProperties(Old, New);
- if (WasInserted) {
+ if (Old->isPlaceholder()) {
replaceSymbol(Old, &New);
return;
}
@@ -502,7 +492,7 @@ StringMap<std::vector<Symbol *>> &SymbolTable::getDemangledSyms() {
if (!DemangledSyms) {
DemangledSyms.emplace();
for (Symbol *Sym : SymVector) {
- if (!Sym->isDefined())
+ if (!Sym->isDefined() && !Sym->isCommon())
continue;
if (Optional<std::string> S = demangleItanium(Sym->getName()))
(*DemangledSyms)[*S].push_back(Sym);
@@ -517,7 +507,7 @@ std::vector<Symbol *> SymbolTable::findByVersion(SymbolVersion Ver) {
if (Ver.IsExternCpp)
return getDemangledSyms().lookup(Ver.Name);
if (Symbol *B = find(Ver.Name))
- if (B->isDefined())
+ if (B->isDefined() || B->isCommon())
return {B};
return {};
}
@@ -534,7 +524,7 @@ std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion Ver) {
}
for (Symbol *Sym : SymVector)
- if (Sym->isDefined() && M.match(Sym->getName()))
+ if ((Sym->isDefined() || Sym->isCommon()) && M.match(Sym->getName()))
Res.push_back(Sym);
return Res;
}
OpenPOWER on IntegriCloud