[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