[lld] r219349 - [ELF] Fix inclusion of weak symbols in the dynamic symbol table
Rafael Auler
rafaelauler at gmail.com
Wed Oct 8 15:38:11 PDT 2014
Author: rafauler
Date: Wed Oct 8 17:38:10 2014
New Revision: 219349
URL: http://llvm.org/viewvc/llvm-project?rev=219349&view=rev
Log:
[ELF] Fix inclusion of weak symbols in the dynamic symbol table
This commit implements in the X86_64 ELF lld backend yet another feature that
was only available in the MIPS backend. However, this patch changes generic ELF
classes to make it trivial for other ELF backends to use this logic too. When
creating a dynamic executable that has dynamic relocations against weak
undefined symbols, these symbols must be exported to the dynamic symbol table
to seek a possible resolution at run time.
A common use case is the __gmon_start__ weak glibc undefined symbol.
Reviewer: shankarke
http://reviews.llvm.org/D5571
Added:
lld/trunk/test/elf/X86_64/weaksym.test
Modified:
lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h
lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h
lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp
Modified: lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h?rev=219349&r1=219348&r2=219349&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h Wed Oct 8 17:38:10 2014
@@ -170,6 +170,8 @@ public:
typedef typename std::vector<lld::AtomLayout *>::iterator AbsoluteAtomIterT;
+ typedef llvm::DenseSet<const Atom *> AtomSetT;
+
DefaultLayout(const ELFLinkingContext &context) : _context(context) {}
/// \brief Return the section order for a input section
@@ -297,8 +299,8 @@ public:
return 0;
}
- bool isReferencedByDefinedAtom(const SharedLibraryAtom *sla) const {
- return _referencedDynAtoms.count(sla);
+ bool isReferencedByDefinedAtom(const Atom *a) const {
+ return _referencedDynAtoms.count(a);
}
protected:
@@ -322,7 +324,7 @@ protected:
LLD_UNIQUE_BUMP_PTR(RelocationTable<ELFT>) _dynamicRelocationTable;
LLD_UNIQUE_BUMP_PTR(RelocationTable<ELFT>) _pltRelocationTable;
std::vector<lld::AtomLayout *> _absoluteAtoms;
- llvm::DenseSet<const SharedLibraryAtom *> _referencedDynAtoms;
+ AtomSetT _referencedDynAtoms;
const ELFLinkingContext &_context;
};
@@ -561,15 +563,28 @@ ErrorOr<const lld::AtomLayout &> Default
StringRef sectionName = getSectionName(definedAtom);
AtomSection<ELFT> *section =
getSection(sectionName, contentType, permissions);
+
// Add runtime relocations to the .rela section.
for (const auto &reloc : *definedAtom) {
- if (_context.isDynamicRelocation(*definedAtom, *reloc))
+ bool isLocalReloc = true;
+ if (_context.isDynamicRelocation(*definedAtom, *reloc)) {
getDynamicRelocationTable()->addRelocation(*definedAtom, *reloc);
- else if (_context.isPLTRelocation(*definedAtom, *reloc))
+ isLocalReloc = false;
+ } else if (_context.isPLTRelocation(*definedAtom, *reloc)) {
getPLTRelocationTable()->addRelocation(*definedAtom, *reloc);
- if (const auto *sla = dyn_cast<SharedLibraryAtom>(reloc->target()))
- _referencedDynAtoms.insert(sla);
+ isLocalReloc = false;
+ }
+
+ if (!reloc->target())
+ continue;
+
+ //Ignore undefined atoms that are not target of dynamic relocations
+ if (isa<UndefinedAtom>(reloc->target()) && isLocalReloc)
+ continue;
+
+ _referencedDynAtoms.insert(reloc->target());
}
+
return section->appendAtom(atom);
} else if (const AbsoluteAtom *absoluteAtom = dyn_cast<AbsoluteAtom>(atom)) {
// Absolute atoms are not part of any section, they are global for the whole
Modified: lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h?rev=219349&r1=219348&r2=219349&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ExecutableWriter.h Wed Oct 8 17:38:10 2014
@@ -59,6 +59,15 @@ void ExecutableWriter<ELFT>::buildDynami
atom->_virtualAddr, atom);
}
+ // Put weak symbols in the dynamic symbol table.
+ if (this->_context.isDynamic()) {
+ for (const UndefinedAtom *a : file.undefined()) {
+ if (this->_layout.isReferencedByDefinedAtom(a) &&
+ a->canBeNull() != UndefinedAtom::canBeNullNever)
+ this->_dynamicSymbolTable->addSymbol(a, ELF::SHN_UNDEF);
+ }
+ }
+
OutputELFWriter<ELFT>::buildDynamicSymbolTable(file);
}
Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h?rev=219349&r1=219348&r2=219349&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h Wed Oct 8 17:38:10 2014
@@ -65,9 +65,24 @@ void MipsExecutableWriter<ELFT>::buildDy
for (auto sec : this->_layout.sections())
if (auto section = dyn_cast<AtomSection<ELFT>>(sec))
for (const auto &atom : section->atoms()) {
- if (_writeHelper.hasGlobalGOTEntry(atom->_atom))
+ if (_writeHelper.hasGlobalGOTEntry(atom->_atom)) {
this->_dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(),
atom->_virtualAddr, atom);
+ continue;
+ }
+
+ const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom->_atom);
+ if (!da)
+ continue;
+
+ if (da->dynamicExport() != DefinedAtom::dynamicExportAlways &&
+ !this->_context.isDynamicallyExportedSymbol(da->name()) &&
+ !(this->_context.shouldExportDynamic() &&
+ da->scope() == Atom::Scope::scopeGlobal))
+ continue;
+
+ this->_dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(),
+ atom->_virtualAddr, atom);
}
for (const UndefinedAtom *a : file.undefined())
@@ -77,7 +92,10 @@ void MipsExecutableWriter<ELFT>::buildDy
if (_writeHelper.hasGlobalGOTEntry(a))
this->_dynamicSymbolTable->addSymbol(a, ELF::SHN_UNDEF);
- ExecutableWriter<ELFT>::buildDynamicSymbolTable(file);
+ // Skip our immediate parent class method
+ // ExecutableWriter<ELFT>::buildDynamicSymbolTable because we replaced it
+ // with our own version. Call OutputELFWriter directly.
+ OutputELFWriter<ELFT>::buildDynamicSymbolTable(file);
}
template <class ELFT>
Modified: lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp?rev=219349&r1=219348&r2=219349&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp Wed Oct 8 17:38:10 2014
@@ -471,16 +471,16 @@ public:
return std::error_code();
}
- const GOTAtom *getSharedGOT(const SharedLibraryAtom *sla) {
- auto got = _gotMap.find(sla);
+ const GOTAtom *getSharedGOT(const Atom *a) {
+ auto got = _gotMap.find(a);
if (got == _gotMap.end()) {
auto g = new (_file._alloc) X86_64GOTAtom(_file, ".got.dyn");
- g->addReferenceELF_x86_64(R_X86_64_GLOB_DAT, 0, sla, 0);
+ g->addReferenceELF_x86_64(R_X86_64_GLOB_DAT, 0, a, 0);
#ifndef NDEBUG
g->_name = "__got_";
- g->_name += sla->name();
+ g->_name += a->name();
#endif
- _gotMap[sla] = g;
+ _gotMap[a] = g;
_gotVector.push_back(g);
return g;
}
@@ -488,12 +488,13 @@ public:
}
std::error_code handleGOT(const Reference &ref) {
- if (isa<UndefinedAtom>(ref.target()))
- const_cast<Reference &>(ref).setTarget(getNullGOT());
- else if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(ref.target()))
+ if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(ref.target()))
const_cast<Reference &>(ref).setTarget(getGOT(da));
- else if (const auto sla = dyn_cast<const SharedLibraryAtom>(ref.target()))
- const_cast<Reference &>(ref).setTarget(getSharedGOT(sla));
+ // Handle undefined atoms in the same way as shared lib atoms: to be
+ // resolved at run time.
+ else if (isa<SharedLibraryAtom>(ref.target()) ||
+ isa<UndefinedAtom>(ref.target()))
+ const_cast<Reference &>(ref).setTarget(getSharedGOT(ref.target()));
return std::error_code();
}
};
Added: lld/trunk/test/elf/X86_64/weaksym.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/weaksym.test?rev=219349&view=auto
==============================================================================
--- lld/trunk/test/elf/X86_64/weaksym.test (added)
+++ lld/trunk/test/elf/X86_64/weaksym.test Wed Oct 8 17:38:10 2014
@@ -0,0 +1,78 @@
+# Tests that an executable with a weak undefine will put this symbol in the
+# dynamic symbol table if the executable has a dynamic relocation against this
+# symbol.
+
+#RUN: yaml2obj --format elf %s -o %t.o
+#RUN: lld -flavor gnu -target x86_64 -e main %t.o -o %t1
+#RUN: llvm-readobj -dt %t1 | FileCheck -check-prefix CHECKSYMS %s
+
+#CHECKSYMS: Name: x@
+#CHECKSYMS-NEXT: Value: 0x0
+#CHECKSYMS-NEXT: Size: 0
+#CHECKSYMS-NEXT: Binding: Weak (0x2)
+#CHECKSYMS-NEXT: Type: None (0x0)
+#CHECKSYMS-NEXT: Other: 0
+#CHECKSYMS-NEXT: Section: Undefined (0x0)
+
+# The object file above corresponds to the following C program compiled with
+# -fPIC:
+# extern int *x __attribute__((weak));
+#
+# int main() {
+# if (x)
+# return 1;
+# return 0;
+# }
+
+---
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_GNU
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x0000000000000010
+ Content: 554889E5488B0500000000C745FC00000000488138000000000F840C000000C745FC01000000E907000000C745FC000000008B45FC5DC3
+ - Name: .rela.text
+ Type: SHT_RELA
+ Link: .symtab
+ AddressAlign: 0x0000000000000008
+ Info: .text
+ Relocations:
+ - Offset: 0x0000000000000007
+ Symbol: x
+ Type: R_X86_64_GOTPCREL
+ Addend: -4
+ - Name: .data
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ AddressAlign: 0x0000000000000004
+ Content: ''
+ - Name: .bss
+ Type: SHT_NOBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ AddressAlign: 0x0000000000000004
+ Content: ''
+Symbols:
+ Local:
+ - Name: .text
+ Type: STT_SECTION
+ Section: .text
+ - Name: .data
+ Type: STT_SECTION
+ Section: .data
+ - Name: .bss
+ Type: STT_SECTION
+ Section: .bss
+ Global:
+ - Name: main
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x0000000000000037
+ - Name: _GLOBAL_OFFSET_TABLE_
+ Weak:
+ - Name: x
More information about the llvm-commits
mailing list