Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -496,9 +496,7 @@ 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(); Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -59,6 +59,7 @@ DefinedRegular *addIgnored(StringRef Name, uint8_t Visibility = llvm::ELF::STV_HIDDEN); + void scanUndefinedFlags(); void scanShlibUndefined(); void scanDynamicList(); void scanVersionScript(); Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -151,17 +151,7 @@ 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 @@ 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 Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -177,8 +177,6 @@ // 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 @@ 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; Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -104,7 +104,6 @@ } void SymbolBody::init() { - CanKeepUndefined = false; NeedsCopyOrPltAddr = false; CanOmitFromDynSym = false; } @@ -245,11 +244,8 @@ 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) Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1343,11 +1343,8 @@ 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); Index: test/ELF/undefined-opt.s =================================================================== --- test/ELF/undefined-opt.s +++ 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: