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: