From 892d4980171333c96e50859c716f9dd5ea313ae3 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 27 Apr 2016 00:05:03 +0000 Subject: [PATCH] ELF: Re-implement -u directly and remove CanKeepUndefined flag. The semantics of the -u flag are to load the lazy symbol named by the flag. We were previously relying on this behavior falling out of symbol resolution against a synthetic undefined symbol, but that didn't quite give us the correct behavior, so we needed a flag to mark symbols created with -u so we could treat them specially in the writer. However, it's simpler and less error prone to implement the required behavior directly and remove the flag. This fixes an issue where symbols loaded with -u would receive hidden visibility even when the definition in an object file had wider visibility. Differential Revision: http://reviews.llvm.org/D19560 llvm-svn: 267639 --- lld/ELF/Driver.cpp | 4 +--- lld/ELF/SymbolTable.cpp | 22 +++++++++++----------- lld/ELF/SymbolTable.h | 1 + lld/ELF/Symbols.cpp | 8 ++------ lld/ELF/Symbols.h | 7 +------ lld/ELF/Writer.cpp | 7 ++----- lld/test/ELF/undefined-opt.s | 11 +++++++++++ 7 files changed, 29 insertions(+), 31 deletions(-) diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index d3cd994773ed..a88d8041d930 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -483,9 +483,7 @@ template void LinkerDriver::link(opt::InputArgList &Args) { if (HasError) return; // There were duplicate symbols or incompatible files - for (StringRef S : Config->Undefined) - Symtab.addUndefinedOpt(S); - + Symtab.scanUndefinedFlags(); Symtab.scanShlibUndefined(); Symtab.scanDynamicList(); Symtab.scanVersionScript(); diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index d67ad8699f3c..89275cdb0c78 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -151,17 +151,7 @@ template void SymbolTable::addCombinedLtoObject() { template SymbolBody *SymbolTable::addUndefined(StringRef Name) { auto *Sym = new (Alloc) - UndefinedElf(Name, STB_GLOBAL, STV_DEFAULT, /*Type*/ 0, false); - resolve(Sym); - return Sym; -} - -// Add an undefined symbol. Unlike addUndefined, that symbol -// doesn't have to be resolved, thus "opt" (optional). -template -SymbolBody *SymbolTable::addUndefinedOpt(StringRef Name) { - auto *Sym = new (Alloc) - UndefinedElf(Name, STB_GLOBAL, STV_HIDDEN, /*Type*/ 0, true); + UndefinedElf(Name, STB_GLOBAL, STV_DEFAULT, /*Type*/ 0); resolve(Sym); return Sym; } @@ -368,6 +358,16 @@ void SymbolTable::addMemberFile(SymbolBody *Undef, Lazy *L) { addFile(std::move(File)); } +// Process undefined (-u) flags by loading lazy symbols named by those flags. +template +void SymbolTable::scanUndefinedFlags() { + for (StringRef S : Config->Undefined) + if (SymbolBody *Sym = find(S)) + if (auto *L = dyn_cast(Sym)) + if (std::unique_ptr File = L->getFile()) + addFile(std::move(File)); +} + // This function takes care of the case in which shared libraries depend on // the user program (not the other way, which is usual). Shared libraries // may have undefined symbols, expecting that the user program provides diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h index e67bd329fe79..e2b410489127 100644 --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -59,6 +59,7 @@ public: DefinedRegular *addIgnored(StringRef Name, uint8_t Visibility = llvm::ELF::STV_HIDDEN); + void scanUndefinedFlags(); void scanShlibUndefined(); void scanDynamicList(); void scanVersionScript(); diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index f75f310f7f78..44cc83991fac 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -104,7 +104,6 @@ SymbolBody::SymbolBody(Kind K, StringRef Name, uint8_t Binding, uint8_t StOther, } void SymbolBody::init() { - CanKeepUndefined = false; NeedsCopyOrPltAddr = false; CanOmitFromDynSym = false; } @@ -245,11 +244,8 @@ UndefinedElf::UndefinedElf(StringRef N, const Elf_Sym &Sym) template UndefinedElf::UndefinedElf(StringRef Name, uint8_t Binding, - uint8_t StOther, uint8_t Type, - bool CanKeepUndefined) - : SymbolBody(SymbolBody::UndefinedElfKind, Name, Binding, StOther, Type) { - this->CanKeepUndefined = CanKeepUndefined; -} + uint8_t StOther, uint8_t Type) + : SymbolBody(SymbolBody::UndefinedElfKind, Name, Binding, StOther, Type) {} template UndefinedElf::UndefinedElf(const Elf_Sym &Sym) diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index cd0232b339c7..1ee1ca9b2474 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -177,8 +177,6 @@ public: // symbol or if the symbol should point to its plt entry. unsigned NeedsCopyOrPltAddr : 1; - unsigned CanKeepUndefined : 1; - // The following fields have the same meaning as the ELF symbol attributes. uint8_t Type; // symbol type uint8_t Binding; // symbol binding @@ -325,10 +323,7 @@ template class UndefinedElf : public SymbolBody { public: UndefinedElf(StringRef N, const Elf_Sym &Sym); UndefinedElf(const Elf_Sym &Sym); - UndefinedElf(StringRef Name, uint8_t Binding, uint8_t StOther, uint8_t Type, - bool CanKeepUndefined); - - bool canKeepUndefined() const { return CanKeepUndefined; } + UndefinedElf(StringRef Name, uint8_t Binding, uint8_t StOther, uint8_t Type); uintX_t Size; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 41ec89f7844e..dd9710523bab 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1339,11 +1339,8 @@ template void Writer::createSections() { if (auto *SS = dyn_cast>(Body)) SS->File->IsUsed = true; - if (Body->isUndefined() && !S->isWeak()) { - auto *U = dyn_cast>(Body); - if (!U || !U->canKeepUndefined()) - reportUndefined(Symtab, Body); - } + if (Body->isUndefined() && !S->isWeak()) + reportUndefined(Symtab, Body); if (auto *C = dyn_cast(Body)) CommonSymbols.push_back(C); diff --git a/lld/test/ELF/undefined-opt.s b/lld/test/ELF/undefined-opt.s index 97ab5a63490a..cdd190fc1bbe 100644 --- a/lld/test/ELF/undefined-opt.s +++ b/lld/test/ELF/undefined-opt.s @@ -51,5 +51,16 @@ # UNK-UNDEFINED-SO-NOT: Name: unknown # UNK-UNDEFINED-SO: ] +# Added undefined symbols should appear in the dynamic table if necessary. +# RUN: ld.lld -shared -o %t5 %t.o -u export +# RUN: llvm-readobj --dyn-symbols %t5 | \ +# RUN: FileCheck --check-prefix=EXPORT-SO %s +# EXPORT-SO: DynamicSymbols [ +# EXPORT-SO: Name: export +# EXPORT-SO: ] + .globl _start; _start: + +.globl export +export: