forked from OSchip/llvm-project
ELF2: Fix BSD's __progname symbol issue.
BSD's DSO files have undefined symbol "__progname" which is defined in crt1.o. On that system, both user programs and system shared libraries depend on each other. In general, we need to put symbols defined by user programs which are referenced by shared libraries to user program's .dynsym. http://reviews.llvm.org/D13637 llvm-svn: 250176
This commit is contained in:
parent
3014991fcf
commit
f8432d97f3
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue