summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Driver.cpp9
-rw-r--r--lld/ELF/InputFiles.cpp2
-rw-r--r--lld/ELF/InputFiles.h11
-rw-r--r--lld/ELF/LinkerScript.cpp10
-rw-r--r--lld/ELF/SymbolTable.cpp2
-rw-r--r--lld/test/ELF/linkerscript/Inputs/provide-shared2.s3
-rw-r--r--lld/test/ELF/linkerscript/provide-shared2.s13
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
OpenPOWER on IntegriCloud