diff options
| author | Rui Ueyama <ruiu@google.com> | 2019-05-16 03:29:03 +0000 |
|---|---|---|
| committer | Rui Ueyama <ruiu@google.com> | 2019-05-16 03:29:03 +0000 |
| commit | 5c073a94f9c25e73d78dbeb8eb7b1b3a60d7dd1f (patch) | |
| tree | 5b4926869d3408f072134ca8ba057d4e1fc964a8 /lld/ELF/SymbolTable.cpp | |
| parent | d5529629fb18ae184ef8db8358263031e19aeba9 (diff) | |
| download | bcm5719-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.cpp | 196 |
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; } |

