diff options
-rw-r--r-- | lld/ELF/Driver.cpp | 9 | ||||
-rw-r--r-- | lld/ELF/InputFiles.cpp | 2 | ||||
-rw-r--r-- | lld/ELF/InputFiles.h | 11 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 10 | ||||
-rw-r--r-- | lld/ELF/SymbolTable.cpp | 2 | ||||
-rw-r--r-- | lld/test/ELF/linkerscript/Inputs/provide-shared2.s | 3 | ||||
-rw-r--r-- | lld/test/ELF/linkerscript/provide-shared2.s | 13 |
7 files changed, 38 insertions, 12 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 5c561610ad0..244e8e1f8a8 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1080,6 +1080,11 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { 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<ELFT>(); @@ -1097,10 +1102,6 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { 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 diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 1f7233b59bc..daba3bce45c 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -851,7 +851,7 @@ template <class ELFT> void SharedFile<ELFT>::parseRest() { StringRef Name = CHECK(Sym.getName(this->StringTable), this); if (Sym.isUndefined()) { - Undefs.push_back(Name); + this->Undefs.insert(Name); continue; } diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index e21862389ae..7a4004657a1 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -93,6 +93,13 @@ public: 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<StringRef> &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 @@ protected: InputFile(Kind K, MemoryBufferRef M); std::vector<InputSectionBase *> Sections; std::vector<Symbol *> Symbols; + llvm::DenseSet<StringRef> Undefs; private: const Kind FileKind; @@ -288,7 +296,6 @@ template <class ELFT> class SharedFile : public ELFFileBase<ELFT> { typedef typename ELFT::Verdef Elf_Verdef; typedef typename ELFT::Versym Elf_Versym; - std::vector<StringRef> Undefs; const Elf_Shdr *VersymSec = nullptr; const Elf_Shdr *VerdefSec = nullptr; @@ -296,8 +303,6 @@ public: std::vector<const Elf_Verdef *> Verdefs; std::string SoName; - llvm::ArrayRef<StringRef> getUndefinedSymbols() { return Undefs; } - static bool classof(const InputFile *F) { return F->kind() == Base::SharedKind; } diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index f1f4ca4782a..c0c2b8434cc 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -127,9 +127,13 @@ static bool shouldDefineSym(SymbolAssignment *Cmd) { // 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, diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 2f5630ee080..54febf59a25 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -597,7 +597,7 @@ template <class ELFT> void SymbolTable::fetchIfLazy(StringRef Name) { // Except this, we ignore undefined symbols in DSOs. template <class ELFT> void SymbolTable::scanShlibUndefined() { for (InputFile *F : SharedFiles) { - for (StringRef U : cast<SharedFile<ELFT>>(F)->getUndefinedSymbols()) { + for (StringRef U : F->getUndefinedSymbols()) { Symbol *Sym = find(U); if (!Sym) continue; diff --git a/lld/test/ELF/linkerscript/Inputs/provide-shared2.s b/lld/test/ELF/linkerscript/Inputs/provide-shared2.s new file mode 100644 index 00000000000..f02fd650106 --- /dev/null +++ b/lld/test/ELF/linkerscript/Inputs/provide-shared2.s @@ -0,0 +1,3 @@ +.global foo +.data +.dc.a foo diff --git a/lld/test/ELF/linkerscript/provide-shared2.s b/lld/test/ELF/linkerscript/provide-shared2.s new file mode 100644 index 00000000000..8a3200b6f54 --- /dev/null +++ b/lld/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 |