Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -247,5 +247,6 @@ Config->OutputFile = "a.out"; // Write the result to the file. + Symtab.finalize(); writeResult(&Symtab); } Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -173,6 +173,7 @@ typedef typename llvm::object::ELFFile::Elf_Sym_Range Elf_Sym_Range; std::vector> SymbolBodies; + std::vector Undefs; StringRef SoName; public: @@ -181,6 +182,8 @@ return SymbolBodies; } + llvm::ArrayRef getUndefinedSymbols() { return Undefs; } + static bool classof(const InputFile *F) { return F->kind() == Base::SharedKind && cast>(F)->getELFKind() == Base::getStaticELFKind(); Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -301,14 +301,14 @@ uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end()); SymbolBodies.reserve(NumSymbols); for (const Elf_Sym &Sym : Syms) { - if (Sym.isUndefined()) - continue; - ErrorOr 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); } } Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -52,6 +52,7 @@ void addSyntheticSym(StringRef Name, OutputSection &Section, typename llvm::object::ELFFile::uintX_t Value); void addIgnoredSym(StringRef Name); + void finalize(); private: Symbol *insert(SymbolBody *New); @@ -61,6 +62,7 @@ void checkCompatibility(std::unique_ptr &File); void init(uint16_t EMachine); void resolve(SymbolBody *Body); + SymbolBody *find(StringRef Name); void reportConflict(const Twine &Message, const SymbolBody &Old, const SymbolBody &New, bool Warning); Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -181,6 +181,13 @@ return Sym; } +template SymbolBody *SymbolTable::find(StringRef Name) { + auto It = Symtab.find(Name); + if (It == Symtab.end()) + return nullptr; + return It->second->Body; +} + template void SymbolTable::addLazy(Lazy *New) { Symbol *Sym = insert(New); if (Sym->Body == New) @@ -231,6 +238,20 @@ addFile(std::move(File)); } +template void SymbolTable::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> &File : SharedFiles) + for (StringRef U : File->getUndefinedSymbols()) + if (SymbolBody *Sym = find(U)) + if (Sym->isDefined()) + Sym->setUsedInDynamicReloc(); +} + template class lld::elf2::SymbolTable; template class lld::elf2::SymbolTable; template class lld::elf2::SymbolTable; Index: test/elf2/progname.s =================================================================== --- /dev/null +++ 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@ (58) +// 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 (0x4) +// CHECK-NEXT: } + +.global _start, __progname +_start: +__progname: + nop