Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -234,5 +234,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 @@ -207,6 +207,7 @@ typedef typename llvm::object::ELFFile::Elf_Sym_Range Elf_Sym_Range; std::vector> SymbolBodies; + std::vector Undefs; public: using ELFData::getEMachine; @@ -214,6 +215,8 @@ return SymbolBodies; } + llvm::ArrayRef getUndefinedSymbols() { return Undefs; } + static bool classof(const InputFile *F) { return F->kind() == SharedKind && cast(F)->getELFKind() == getStaticELFKind(); Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -322,14 +322,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(Name, Sym); + if (Sym.isUndefined()) + Undefs.push_back(Name); + else + SymbolBodies.emplace_back(Name, Sym); } } Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -60,6 +60,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); @@ -68,6 +69,7 @@ void addMemberFile(Lazy *Body); 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 @@ -189,6 +189,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) @@ -224,6 +231,18 @@ addFile(std::move(File)); } +template void SymbolTable::finalize() { + // This code fixes an issue related to BSD's __progname symbol. + // The symbol is undefined in shared libraries, expecting that user + // programs (actually crt1.o) define that. We need to put such + // symbols to .dynsym so that the dynamic linker can fix shared libraries. + 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