summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Driver.cpp1
-rw-r--r--lld/ELF/InputFiles.cpp8
-rw-r--r--lld/ELF/InputFiles.h3
-rw-r--r--lld/ELF/SymbolTable.cpp21
-rw-r--r--lld/ELF/SymbolTable.h2
-rw-r--r--lld/test/elf2/progname.s20
6 files changed, 51 insertions, 4 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index e0136d25041..346ab44e097 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -227,5 +227,6 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
Config->OutputFile = "a.out";
// Write the result to the file.
+ Symtab.finalize();
writeResult<ELFT>(&Symtab);
}
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 10f12cd4e9d..b154ac63c2a 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -301,14 +301,14 @@ template <class ELFT> void SharedFile<ELFT>::parse() {
uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
SymbolBodies.reserve(NumSymbols);
for (const Elf_Sym &Sym : Syms) {
- if (Sym.isUndefined())
- continue;
-
ErrorOr<StringRef> NameOrErr = Sym.getName(this->StringTable);
error(NameOrErr.getError());
StringRef Name = *NameOrErr;
- SymbolBodies.emplace_back(this, Name, Sym);
+ if (Sym.isUndefined())
+ Undefs.push_back(Name);
+ else
+ SymbolBodies.emplace_back(this, Name, Sym);
}
}
diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index 86ec5360670..00ab848eddf 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -169,6 +169,7 @@ template <class ELFT> class SharedFile : public ELFFileBase<ELFT> {
typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
std::vector<SharedSymbol<ELFT>> SymbolBodies;
+ std::vector<StringRef> Undefs;
StringRef SoName;
public:
@@ -177,6 +178,8 @@ public:
return SymbolBodies;
}
+ llvm::ArrayRef<StringRef> getUndefinedSymbols() { return Undefs; }
+
static bool classof(const InputFile *F) {
return F->kind() == Base::SharedKind;
}
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index 6818d53db8d..a74913cc5fa 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -181,6 +181,13 @@ template <class ELFT> Symbol *SymbolTable<ELFT>::insert(SymbolBody *New) {
return Sym;
}
+template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) {
+ auto It = Symtab.find(Name);
+ if (It == Symtab.end())
+ return nullptr;
+ return It->second->Body;
+}
+
template <class ELFT> void SymbolTable<ELFT>::addLazy(Lazy *New) {
Symbol *Sym = insert(New);
if (Sym->Body == New)
@@ -230,6 +237,20 @@ template <class ELFT> void SymbolTable<ELFT>::addMemberFile(Lazy *Body) {
addFile(std::move(File));
}
+template <class ELFT> void SymbolTable<ELFT>::finalize() {
+ // This code 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
+ // the definitions for them. An example is BSD's __progname symbol.
+ // We need to put such symbols to the main program's .dynsym so that
+ // shared libraries can find them.
+ for (std::unique_ptr<SharedFile<ELFT>> &File : SharedFiles)
+ for (StringRef U : File->getUndefinedSymbols())
+ if (SymbolBody *Sym = find(U))
+ if (Sym->isDefined())
+ Sym->setUsedInDynamicReloc();
+}
+
template class lld::elf2::SymbolTable<ELF32LE>;
template class lld::elf2::SymbolTable<ELF32BE>;
template class lld::elf2::SymbolTable<ELF64LE>;
diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h
index ddaa9ed842a..a41d8d3b2cd 100644
--- a/lld/ELF/SymbolTable.h
+++ b/lld/ELF/SymbolTable.h
@@ -52,6 +52,7 @@ public:
void addSyntheticSym(StringRef Name, OutputSection<ELFT> &Section,
typename llvm::object::ELFFile<ELFT>::uintX_t Value);
void addIgnoredSym(StringRef Name);
+ void finalize();
private:
Symbol *insert(SymbolBody *New);
@@ -60,6 +61,7 @@ private:
void addMemberFile(Lazy *Body);
void checkCompatibility(std::unique_ptr<InputFile> &File);
void resolve(SymbolBody *Body);
+ SymbolBody *find(StringRef Name);
void reportConflict(const Twine &Message, const SymbolBody &Old,
const SymbolBody &New, bool Warning);
diff --git a/lld/test/elf2/progname.s b/lld/test/elf2/progname.s
new file mode 100644
index 00000000000..18b1ef7ef96
--- /dev/null
+++ b/lld/test/elf2/progname.s
@@ -0,0 +1,20 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
+// RUN: echo '.global __progname' > %t2.s
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %t2.s -o %t2.o
+// RUN: ld.lld2 -shared %t2.o -o %t2.so
+// RUN: ld.lld2 -o %t %t.o %t2.so
+// RUN: llvm-readobj -dyn-symbols %t | FileCheck %s
+
+// CHECK: Name: __progname@
+// CHECK-NEXT: Value: 0x11000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global (0x1)
+// CHECK-NEXT: Type: None (0x0)
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+
+.global _start, __progname
+_start:
+__progname:
+ nop
OpenPOWER on IntegriCloud