Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -1080,6 +1080,11 @@ if (errorCount()) return; + // We want to declare linker script's symbols early, + // so that we can version them. + // They also might be exported if referenced by DSOs. + Script->declareSymbols(); + // Handle undefined symbols in DSOs. if (!Config->Shared) Symtab->scanShlibUndefined(); @@ -1097,10 +1102,6 @@ if (!Config->Relocatable) addReservedSymbols(); - // We want to declare linker script's symbols early, - // so that we can version them. - Script->declareSymbols(); - // Apply version scripts. // // For a relocatable output, version scripts don't make sense, and Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -93,6 +93,13 @@ return Symbols; } + // Returns undefined symbols of a shared library. + // It is a runtime error to call this function on files of other types. + const llvm::DenseSet &getUndefinedSymbols() { + assert(FileKind == SharedKind); + return Undefs; + } + // Filename of .a which contained this file. If this file was // not in an archive file, it is the empty string. We use this // string for creating error messages. @@ -114,6 +121,7 @@ InputFile(Kind K, MemoryBufferRef M); std::vector Sections; std::vector Symbols; + llvm::DenseSet Undefs; private: const Kind FileKind; @@ -288,7 +296,6 @@ typedef typename ELFT::Verdef Elf_Verdef; typedef typename ELFT::Versym Elf_Versym; - std::vector Undefs; const Elf_Shdr *VersymSec = nullptr; const Elf_Shdr *VerdefSec = nullptr; @@ -296,8 +303,6 @@ std::vector Verdefs; std::string SoName; - llvm::ArrayRef getUndefinedSymbols() { return Undefs; } - static bool classof(const InputFile *F) { return F->kind() == Base::SharedKind; } Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -851,7 +851,7 @@ StringRef Name = CHECK(Sym.getName(this->StringTable), this); if (Sym.isUndefined()) { - Undefs.push_back(Name); + this->Undefs.insert(Name); continue; } Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -127,9 +127,13 @@ // If a symbol was in PROVIDE(), we need to define it only // when it is a referenced undefined symbol. Symbol *B = Symtab->find(Cmd->Name); - if (!B || B->isDefined()) - return false; - return true; + if (B && !B->isDefined()) + return true; + // It might also be referenced by a DSO. + for (InputFile *F : SharedFiles) + if (F->getUndefinedSymbols().count(Cmd->Name)) + return true; + return false; } // This function is called from processSectionCommands, Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -597,7 +597,7 @@ // Except this, we ignore undefined symbols in DSOs. template void SymbolTable::scanShlibUndefined() { for (InputFile *F : SharedFiles) { - for (StringRef U : cast>(F)->getUndefinedSymbols()) { + for (StringRef U : F->getUndefinedSymbols()) { Symbol *Sym = find(U); if (!Sym) continue; Index: test/ELF/linkerscript/Inputs/provide-shared2.s =================================================================== --- test/ELF/linkerscript/Inputs/provide-shared2.s +++ test/ELF/linkerscript/Inputs/provide-shared2.s @@ -0,0 +1,3 @@ +.global foo +.data +.dc.a foo Index: test/ELF/linkerscript/provide-shared2.s =================================================================== --- test/ELF/linkerscript/provide-shared2.s +++ test/ELF/linkerscript/provide-shared2.s @@ -0,0 +1,13 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/provide-shared2.s -o %t2.o +# RUN: ld.lld %t2.o -o %t2.so -shared +# RUN: echo "SECTIONS { . = . + SIZEOF_HEADERS; PROVIDE(foo = 42); }" > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o %t2.so +# RUN: llvm-readelf --dyn-symbols %t | FileCheck %s + +# CHECK: 1 1: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS foo@ + +.global _start +_start: + nop