[lld] r176150 - [ELF][Writer] Add dynamic relocation tables.
Michael J. Spencer
bigcheesegs at gmail.com
Tue Feb 26 17:30:28 PST 2013
Author: mspencer
Date: Tue Feb 26 19:30:27 2013
New Revision: 176150
URL: http://llvm.org/viewvc/llvm-project?rev=176150&view=rev
Log:
[ELF][Writer] Add dynamic relocation tables.
This adds separate PLT and dynamic relocation tables. It also fills in the dynamic table
entries for them.
Modified:
lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h
lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h
lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
lld/trunk/lib/ReaderWriter/ELF/Writer.cpp
Modified: lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h?rev=176150&r1=176149&r2=176150&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h (original)
+++ lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h Tue Feb 26 19:30:27 2013
@@ -44,11 +44,28 @@ public:
virtual StringRef getEntry() const;
virtual uint64_t getBaseAddress() const { return _options._baseAddress; }
- virtual bool isRuntimeRelocation(const DefinedAtom &,
+ /// \brief Does this relocation belong in the dynamic relocation table?
+ ///
+ /// This table is evaluated at loadtime by the dynamic loader and is
+ /// referenced by the DT_RELA{,ENT,SZ} entries in the dynamic table.
+ /// Relocations that return true will be added to the dynamic relocation
+ /// table.
+ virtual bool isDynamicRelocation(const DefinedAtom &,
const Reference &) const {
return false;
}
+ /// \brief Does this relocation belong in the dynamic plt relocation table?
+ ///
+ /// This table holds all of the relocations used for delayed symbol binding.
+ /// It will be evaluated at load time if LD_BIND_NOW is set. It is referenced
+ /// by the DT_{JMPREL,PLTRELSZ} entries in the dynamic table.
+ /// Relocations that return true will be added to the dynamic plt relocation
+ /// table.
+ virtual bool isPLTRelocation(const DefinedAtom &, const Reference &) const {
+ return false;
+ }
+
virtual StringRef getInterpreter() const {
return "/lib64/ld-linux-x86-64.so.2";
}
Modified: lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h?rev=176150&r1=176149&r2=176150&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h Tue Feb 26 19:30:27 2013
@@ -144,9 +144,7 @@ public:
typedef typename std::vector<AtomLayout *>::iterator AbsoluteAtomIterT;
- DefaultLayout(const ELFTargetInfo &ti)
- : _relocationTable(nullptr), _targetInfo(ti) {
- }
+ DefaultLayout(const ELFTargetInfo &ti) : _targetInfo(ti) {}
/// \brief Return the section order for a input section
virtual SectionOrder getSectionOrder(StringRef name, int32_t contentType,
@@ -243,14 +241,29 @@ public:
return _programHeader;
}
- RelocationTable<ELFT> *getRelocationTable() {
- // Only create the relocation table if it is needed.
- if (!_relocationTable) {
- _relocationTable.reset(new (_allocator)
- RelocationTable<ELFT>(_targetInfo, ".rela.plt", ORDER_REL));
- addSection(_relocationTable.get());
+ bool hasDynamicRelocationTable() const { return !!_dynamicRelocationTable; }
+
+ bool hasPLTRelocationTable() const { return !!_pltRelocationTable; }
+
+ /// \brief Get or create the dynamic relocation table. All relocations in this
+ /// table are processed at startup.
+ RelocationTable<ELFT> *getDynamicRelocationTable() {
+ if (!_dynamicRelocationTable) {
+ _dynamicRelocationTable.reset(new (_allocator) RelocationTable<ELFT>(
+ _targetInfo, ".rela.dyn", ORDER_REL));
+ addSection(_dynamicRelocationTable.get());
+ }
+ return _dynamicRelocationTable.get();
+ }
+
+ /// \brief Get or create the PLT relocation table. Referenced by DT_JMPREL.
+ RelocationTable<ELFT> *getPLTRelocationTable() {
+ if (!_pltRelocationTable) {
+ _pltRelocationTable.reset(new (_allocator) RelocationTable<ELFT>(
+ _targetInfo, ".rela.plt", ORDER_REL));
+ addSection(_pltRelocationTable.get());
}
- return _relocationTable.get();
+ return _pltRelocationTable.get();
}
uint64_t getTLSSize() const {
@@ -277,7 +290,8 @@ private:
std::vector<MergedSections<ELFT> *> _mergedSections;
Header<ELFT> *_header;
ProgramHeader<ELFT> *_programHeader;
- LLD_UNIQUE_BUMP_PTR(RelocationTable<ELFT>) _relocationTable;
+ LLD_UNIQUE_BUMP_PTR(RelocationTable<ELFT>) _dynamicRelocationTable;
+ LLD_UNIQUE_BUMP_PTR(RelocationTable<ELFT>) _pltRelocationTable;
std::vector<AtomLayout *> _absoluteAtoms;
const ELFTargetInfo &_targetInfo;
};
@@ -472,8 +486,10 @@ ErrorOr<const AtomLayout &> DefaultLayou
getSection(sectionName, contentType, permissions);
// Add runtime relocations to the .rela section.
for (const auto &reloc : *definedAtom)
- if (_targetInfo.isRuntimeRelocation(*definedAtom, *reloc))
- getRelocationTable()->addRelocation(*definedAtom, *reloc);
+ if (_targetInfo.isDynamicRelocation(*definedAtom, *reloc))
+ getDynamicRelocationTable()->addRelocation(*definedAtom, *reloc);
+ else if (_targetInfo.isPLTRelocation(*definedAtom, *reloc))
+ getPLTRelocationTable()->addRelocation(*definedAtom, *reloc);
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/SectionChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h?rev=176150&r1=176149&r2=176150&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h Tue Feb 26 19:30:27 2013
@@ -29,6 +29,14 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileOutputBuffer.h"
+namespace {
+LLVM_ATTRIBUTE_UNUSED std::string kindOrUnknown(llvm::ErrorOr<std::string> k) {
+ if (k)
+ return *k;
+ return "<unknown>";
+}
+}
+
namespace lld {
namespace elf {
template <class> class MergedSections;
@@ -587,6 +595,18 @@ public:
void addSymbol(const Atom *atom, int32_t sectionIndex, uint64_t addr = 0);
+ /// \brief Get the symbol table index for an Atom. If it's not in the symbol
+ /// table, return STN_UNDEF.
+ uint32_t getSymbolTableIndex(const Atom *a) const {
+ auto se = std::find_if(_symbolTable.begin(), _symbolTable.end(),
+ [=](const SymbolEntry &se) {
+ return se._atom == a;
+ });
+ if (se == _symbolTable.end())
+ return STN_UNDEF;
+ return std::distance(_symbolTable.begin(), se);
+ }
+
virtual void finalize();
virtual void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer);
@@ -740,7 +760,7 @@ public:
typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
RelocationTable(const ELFTargetInfo &ti, StringRef str, int32_t order)
- : Section<ELFT>(ti, str) {
+ : Section<ELFT>(ti, str), _symbolTable(nullptr) {
this->setOrder(order);
this->_entSize = sizeof(Elf_Rela);
this->_align2 = llvm::alignOf<Elf_Rela>();
@@ -748,10 +768,36 @@ public:
this->_flags = SHF_ALLOC;
}
- void addRelocation(const DefinedAtom &da, const Reference &r) {
+ /// \returns the index of the relocation added.
+ uint32_t addRelocation(const DefinedAtom &da, const Reference &r) {
_relocs.emplace_back(&da, &r);
this->_fsize = _relocs.size() * sizeof(Elf_Rela);
this->_msize = this->_fsize;
+ return _relocs.size() - 1;
+ }
+
+ bool getRelocationIndex(const Reference &r, uint32_t &res) {
+ auto rel = std::find_if(
+ _relocs.begin(), _relocs.end(),
+ [&](const std::pair<const DefinedAtom *, const Reference *> &p) {
+ if (p.second == &r)
+ return true;
+ return false;
+ });
+ if (rel == _relocs.end())
+ return false;
+ res = std::distance(_relocs.begin(), rel);
+ return true;
+ }
+
+ void setSymbolTable(const SymbolTable<ELFT> *symbolTable) {
+ _symbolTable = symbolTable;
+ }
+
+ virtual void finalize() {
+ this->_link = _symbolTable ? _symbolTable->ordinal() : 0;
+ if (this->_parent)
+ this->_parent->setLink(this->_link);
}
virtual void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) {
@@ -759,21 +805,28 @@ public:
uint8_t *dest = chunkBuffer + this->fileOffset();
for (const auto &rel : _relocs) {
Elf_Rela *r = reinterpret_cast<Elf_Rela *>(dest);
- r->setSymbolAndType(0, rel.second->kind());
+ uint32_t index =
+ _symbolTable ? _symbolTable->getSymbolTableIndex(rel.second->target())
+ : STN_UNDEF;
+ r->setSymbolAndType(index, rel.second->kind());
r->r_offset =
writer->addressOfAtom(rel.first) + rel.second->offsetInAtom();
r->r_addend =
writer->addressOfAtom(rel.second->target()) + rel.second->addend();
dest += sizeof(Elf_Rela);
- DEBUG_WITH_TYPE("ELFRelocationTable", llvm::dbgs()
- << "IRELATIVE relocation at " << rel.first->name() << "@"
- << r->r_offset << " to " << rel.second->target()->name()
- << "@" << r->r_addend << "\n");
+ DEBUG_WITH_TYPE("ELFRelocationTable",
+ llvm::dbgs()
+ << kindOrUnknown(this->_targetInfo.stringFromRelocKind(
+ rel.second->kind())) << " relocation at "
+ << rel.first->name() << "@" << r->r_offset << " to "
+ << rel.second->target()->name() << "@" << r->r_addend
+ << "\n");
}
}
private:
std::vector<std::pair<const DefinedAtom *, const Reference *>> _relocs;
+ const SymbolTable<ELFT> *_symbolTable;
};
template <class ELFT> class DynamicTable : public Section<ELFT> {
Modified: lld/trunk/lib/ReaderWriter/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Writer.cpp?rev=176150&r1=176149&r2=176150&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Writer.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Writer.cpp Tue Feb 26 19:30:27 2013
@@ -69,6 +69,26 @@ private:
_dt_strsz = _dynamicTable->addEntry(dyn);
dyn.d_tag = DT_SYMENT;
_dt_syment = _dynamicTable->addEntry(dyn);
+ if (_layout->hasDynamicRelocationTable()) {
+ dyn.d_tag = DT_RELA;
+ _dt_rela = _dynamicTable->addEntry(dyn);
+ dyn.d_tag = DT_RELASZ;
+ _dt_relasz = _dynamicTable->addEntry(dyn);
+ dyn.d_tag = DT_RELAENT;
+ _dt_relaent = _dynamicTable->addEntry(dyn);
+ }
+ if (_layout->hasPLTRelocationTable()) {
+ dyn.d_tag = DT_PLTRELSZ;
+ _dt_pltrelsz = _dynamicTable->addEntry(dyn);
+ dyn.d_tag = DT_PLTGOT;
+ _dt_pltgot = _dynamicTable->addEntry(dyn);
+ dyn.d_tag = DT_PLTREL;
+ dyn.d_un.d_val = DT_RELA;
+ _dt_pltrel = _dynamicTable->addEntry(dyn);
+ dyn.d_un.d_val = 0;
+ dyn.d_tag = DT_JMPREL;
+ _dt_jmprel = _dynamicTable->addEntry(dyn);
+ }
}
void updateDynamicTable() {
@@ -78,6 +98,19 @@ private:
tbl[_dt_symtab].d_un.d_val = _dynamicSymbolTable->virtualAddr();
tbl[_dt_strsz].d_un.d_val = _dynamicStringTable->memSize();
tbl[_dt_syment].d_un.d_val = _dynamicSymbolTable->getEntSize();
+ if (_layout->hasDynamicRelocationTable()) {
+ auto relaTbl = _layout->getDynamicRelocationTable();
+ tbl[_dt_rela].d_un.d_val = relaTbl->virtualAddr();
+ tbl[_dt_relasz].d_un.d_val = relaTbl->memSize();
+ tbl[_dt_relaent].d_un.d_val = relaTbl->getEntSize();
+ }
+ if (_layout->hasPLTRelocationTable()) {
+ auto relaTbl = _layout->getPLTRelocationTable();
+ tbl[_dt_jmprel].d_un.d_val = relaTbl->virtualAddr();
+ tbl[_dt_pltrelsz].d_un.d_val = relaTbl->memSize();
+ auto gotplt = _layout->findOutputSection(".got.plt");
+ tbl[_dt_pltgot].d_un.d_val = gotplt->virtualAddr();
+ }
}
llvm::BumpPtrAllocator _alloc;
@@ -414,6 +447,12 @@ void ExecutableWriter<ELFT>::createDefau
_layout->addSection(_interpSection.get());
_layout->addSection(_hashTable.get());
_dynamicSymbolTable->setStringSection(_dynamicStringTable.get());
+ if (_layout->hasDynamicRelocationTable())
+ _layout->getDynamicRelocationTable()->setSymbolTable(
+ _dynamicSymbolTable.get());
+ if (_layout->hasPLTRelocationTable())
+ _layout->getPLTRelocationTable()->setSymbolTable(
+ _dynamicSymbolTable.get());
}
// give a chance for the target to add sections
More information about the llvm-commits
mailing list