[lld] r173874 - [ELF] Make AtomLayout more accessible.

Michael J. Spencer bigcheesegs at gmail.com
Tue Jan 29 17:25:06 PST 2013


Author: mspencer
Date: Tue Jan 29 19:25:06 2013
New Revision: 173874

URL: http://llvm.org/viewvc/llvm-project?rev=173874&view=rev
Log:
[ELF] Make AtomLayout more accessible.

This is needed to allow constant time access to the final layout of atoms.

Modified:
    lld/trunk/lib/ReaderWriter/ELF/Chunk.h
    lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h
    lld/trunk/lib/ReaderWriter/ELF/Layout.h
    lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
    lld/trunk/lib/ReaderWriter/ELF/Writer.cpp

Modified: lld/trunk/lib/ReaderWriter/ELF/Chunk.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Chunk.h?rev=173874&r1=173873&r2=173874&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Chunk.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Chunk.h Tue Jan 29 19:25:06 2013
@@ -55,7 +55,6 @@ public:
   Kind kind() const { return _kind; }
   uint64_t            fileSize() const { return _fsize; }
   uint64_t            align2() const { return _align2; }
-  void                appendAtom() const;
 
   // The ordinal value of the chunk
   uint64_t            ordinal() const { return _ordinal;}

Modified: lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h?rev=173874&r1=173873&r2=173874&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h Tue Jan 29 19:25:06 2013
@@ -132,34 +132,14 @@ public:
   typedef std::unordered_map<SegmentKey, Segment<ELFT> *,
                              SegmentHashKey> SegmentMapT;
 
-  /// \brief All absolute atoms are created in the ELF Layout by using 
-  /// an AbsoluteAtomPair. Contains a pair of AbsoluteAtom and the 
-  /// value which is the address of the absolute atom
-  class AbsoluteAtomPair {
-  public:
-    AbsoluteAtomPair(const AbsoluteAtom *a, int64_t value) 
-                     : _absoluteAtom(a)
-                     , _value(value) { }
-
-    const AbsoluteAtom *absoluteAtom() { return _absoluteAtom; }
-    int64_t value() const { return _value; }
-    void setValue(int64_t val) { _value = val; }
-
-  private:
-    const AbsoluteAtom *_absoluteAtom;
-    int64_t _value;
-  };
-
   /// \brief find a absolute atom pair given a absolute atom name
   struct FindByName {
     const std::string _name;
     FindByName(StringRef name) : _name(name) {}
-    bool operator()(AbsoluteAtomPair& j) { 
-      return j.absoluteAtom()->name() == _name; 
-    }
+    bool operator()(const AtomLayout *j) { return j->_atom->name() == _name; }
   };
 
-  typedef typename std::vector<AbsoluteAtomPair>::iterator AbsoluteAtomIterT;
+  typedef typename std::vector<AtomLayout *>::iterator AbsoluteAtomIterT;
 
   DefaultLayout(const ELFTargetInfo &ti) : _targetInfo(ti) {}
 
@@ -181,7 +161,7 @@ public:
   static bool hasOutputSegment(Section<ELFT> *section);
 
   // Adds an atom to the section
-  virtual error_code addAtom(const Atom *atom);
+  virtual ErrorOr<const AtomLayout &> addAtom(const Atom *atom);
 
   /// \brief Find an output Section given a section name.
   MergedSections<ELFT> *findOutputSection(StringRef name) {
@@ -270,7 +250,7 @@ private:
   Header<ELFT> *_header;
   ProgramHeader<ELFT> *_programHeader;
   RelocationTable<ELFT> *_relocationTable;
-  std::vector<AbsoluteAtomPair> _absoluteAtoms;
+  std::vector<AtomLayout *> _absoluteAtoms;
   llvm::BumpPtrAllocator _allocator;
   const ELFTargetInfo &_targetInfo;
 };
@@ -408,10 +388,14 @@ DefaultLayout<ELFT>::hasOutputSegment(Se
   }
 }
 
-template<class ELFT>
-error_code
-DefaultLayout<ELFT>::addAtom(const Atom *atom) {
+template <class ELFT>
+ErrorOr<const AtomLayout &> DefaultLayout<ELFT>::addAtom(const Atom *atom) {
   if (const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom)) {
+    // HACK: Ignore undefined atoms. We need to adjust the interface so that
+    // undefined atoms can still be included in the output symbol table for
+    // -noinhibit-exec.
+    if (definedAtom->contentType() == DefinedAtom::typeUnknown)
+      return make_error_code(llvm::errc::invalid_argument);
     const StringRef sectionName = getSectionName(
         definedAtom->customSectionName(), definedAtom->contentType());
     const DefinedAtom::ContentPermissions permissions =
@@ -432,7 +416,7 @@ DefaultLayout<ELFT>::addAtom(const Atom 
     } else {
       section = _sectionMap[sectionKey];
     }
-    section->appendAtom(atom);
+    return section->appendAtom(atom);
     // Add runtime relocations to the .rela section.
     for (const auto &reloc : *definedAtom)
       if (_targetInfo.isRuntimeRelocation(*definedAtom, *reloc))
@@ -440,12 +424,12 @@ DefaultLayout<ELFT>::addAtom(const Atom 
   } else if (const AbsoluteAtom *absoluteAtom = dyn_cast<AbsoluteAtom>(atom)) {
     // Absolute atoms are not part of any section, they are global for the whole
     // link
-    _absoluteAtoms.push_back(AbsoluteAtomPair(absoluteAtom,
-                                              absoluteAtom->value()));
+    _absoluteAtoms.push_back(
+        new (_allocator) AtomLayout(absoluteAtom, 0, absoluteAtom->value()));
+    return *_absoluteAtoms.back();
   } else {
     llvm_unreachable("Only absolute / defined atoms can be added here");
   }
-  return error_code::success();
 }
 
 /// Merge sections with the same name into a MergedSections

Modified: lld/trunk/lib/ReaderWriter/ELF/Layout.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Layout.h?rev=173874&r1=173873&r2=173874&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Layout.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Layout.h Tue Jan 29 19:25:06 2013
@@ -17,10 +17,23 @@
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ELF.h"
+#include "llvm/Support/ErrorOr.h"
 
 namespace lld {
 namespace elf {
-/// \brief The Layout is an abstract class for managing the final layout for
+struct AtomLayout {
+  AtomLayout(const Atom *a, uint64_t fileOff, uint64_t virAddr)
+      : _atom(a), _fileOffset(fileOff), _virtualAddr(virAddr) {
+  }
+
+  AtomLayout() : _atom(nullptr), _fileOffset(0), _virtualAddr(0) {}
+
+  const Atom *_atom;
+  uint64_t _fileOffset;
+  uint64_t _virtualAddr;
+};
+
+/// \brief The ELFLayout is an abstract class for managing the final layout for
 ///        the kind of binaries(Shared Libraries / Relocatables / Executables 0
 ///        Each architecture (Hexagon, PowerPC, MIPS) would have a concrete
 ///        subclass derived from Layout for generating each binary thats
@@ -37,8 +50,10 @@ public:
                         (const StringRef name,
                          int32_t contentType,
                          int32_t contentPerm) = 0;
-  /// append the Atom to the layout and create appropriate sections
-  virtual error_code addAtom(const Atom *atom) = 0;
+  /// \brief Append the Atom to the layout and create appropriate sections.
+  /// \returns A reference to the atom layout or an error. The atom layout will
+  /// be updated as linking progresses.
+  virtual ErrorOr<const AtomLayout &> addAtom(const Atom *atom) = 0;
   /// find the Atom Address in the current layout
   virtual bool findAtomAddrByName(const StringRef name, 
                                   uint64_t &addr) = 0;
@@ -54,18 +69,6 @@ public:
 
   virtual ~Layout() { }
 };
-
-struct AtomLayout {
-  AtomLayout(const Atom *a, uint64_t fileOff, uint64_t virAddr)
-    : _atom(a), _fileOffset(fileOff), _virtualAddr(virAddr) {}
-
-  AtomLayout()
-    : _atom(nullptr), _fileOffset(0), _virtualAddr(0) {}
-
-  const Atom *_atom;
-  uint64_t _fileOffset;
-  uint64_t _virtualAddr;
-};
 } // end namespace elf
 } // end namespace lld
 

Modified: lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h?rev=173874&r1=173873&r2=173874&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h Tue Jan 29 19:25:06 2013
@@ -60,14 +60,14 @@ public:
   // \brief Append an atom to a Section. The atom gets pushed into a vector
   // contains the atom, the atom file offset, the atom virtual address
   // the atom file offset is aligned appropriately as set by the Reader
-  void appendAtom(const Atom *atom);
+  const AtomLayout &appendAtom(const Atom *atom);
 
   /// \brief Set the virtual address of each Atom in the Section. This
   /// routine gets called after the linker fixes up the virtual address
   /// of the section
   inline void assignVirtualAddress(uint64_t &addr) {
     for (auto &ai : _atoms) {
-      ai._virtualAddr = addr + ai._fileOffset;
+      ai->_virtualAddr = addr + ai->_fileOffset;
     }
     addr += this->memSize();
   }
@@ -76,7 +76,7 @@ public:
   /// gets called after the linker fixes up the section offset
   inline void assignOffsets(uint64_t offset) {
     for (auto &ai : _atoms) {
-      ai._fileOffset = offset + ai._fileOffset;
+      ai->_fileOffset = offset + ai->_fileOffset;
     }
   }
 
@@ -85,8 +85,8 @@ public:
   ///  to fix the relocation
   inline bool findAtomAddrByName(const StringRef name, uint64_t &addr) {
     for (auto ai : _atoms) {
-      if (ai._atom->name() == name) {
-        addr = ai._virtualAddr;
+      if (ai->_atom->name() == name) {
+        addr = ai->_virtualAddr;
         return true;
       }
     }
@@ -159,7 +159,7 @@ public:
   void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer);
 
   /// Atom Iterators
-  typedef typename std::vector<AtomLayout>::iterator atom_iter;
+  typedef typename std::vector<AtomLayout *>::iterator atom_iter;
 
   range<atom_iter> atoms() { return _atoms; }
 
@@ -167,11 +167,12 @@ protected:
   int32_t _contentType;
   int32_t _contentPermissions;
   SectionKind _sectionKind;
-  std::vector<AtomLayout> _atoms;
+  std::vector<AtomLayout *> _atoms;
   Layout::SegmentType _segmentType;
   int64_t _entSize;
   int64_t _shInfo;
   int64_t _link;
+  llvm::BumpPtrAllocator _alloc;
 };
 
 // Create a section object, the section is set to the default type if the
@@ -207,9 +208,8 @@ Section<ELFT>::alignOffset(uint64_t offs
 // \brief Append an atom to a Section. The atom gets pushed into a vector
 // contains the atom, the atom file offset, the atom virtual address
 // the atom file offset is aligned appropriately as set by the Reader
-template<class ELFT>
-void 
-Section<ELFT>::appendAtom(const Atom *atom) {
+template <class ELFT>
+const AtomLayout &Section<ELFT>::appendAtom(const Atom *atom) {
   Atom::Definition atomType = atom->definition();
   const DefinedAtom *definedAtom = cast<DefinedAtom>(atom);
 
@@ -229,7 +229,7 @@ Section<ELFT>::appendAtom(const Atom *at
     case DefinedAtom::typeGOT:
     case DefinedAtom::typeStub:
     case DefinedAtom::typeResolver:
-      _atoms.push_back(AtomLayout(atom, fOffset, 0));
+      _atoms.push_back(new (_alloc) AtomLayout(atom, fOffset, 0));
       this->_fsize = fOffset + definedAtom->size();
       this->_msize = mOffset + definedAtom->size();
       DEBUG_WITH_TYPE("Section",
@@ -238,13 +238,12 @@ Section<ELFT>::appendAtom(const Atom *at
                                    << fOffset << "\n");
       break;
     case  DefinedAtom::typeZeroFill:
-      _atoms.push_back(AtomLayout(atom, mOffset, 0));
+      _atoms.push_back(new (_alloc) AtomLayout(atom, mOffset, 0));
       this->_msize = mOffset + definedAtom->size();
       break;
     default:
-      this->_fsize = fOffset + definedAtom->size();
-      this->_msize = mOffset + definedAtom->size();
-      break;
+      llvm::dbgs() << definedAtom->contentType() << "\n";
+      llvm_unreachable("Uexpected content type.");
     }
     break;
   default:
@@ -255,6 +254,8 @@ Section<ELFT>::appendAtom(const Atom *at
   // std::max doesnot support uint64_t
   if (this->_align2 < align2)
     this->_align2 = align2;
+
+  return *_atoms.back();
 }
 
 /// \brief Get the section flags, defined by the permissions of the section
@@ -345,9 +346,9 @@ void Section<ELFT>::write(ELFWriter *wri
   uint8_t *chunkBuffer = buffer.getBufferStart();
   for (auto &ai : _atoms) {
     DEBUG_WITH_TYPE("Section",
-                    llvm::dbgs() << "Writing atom: " << ai._atom->name()
-                                 << " | " << ai._fileOffset << "\n");
-    const DefinedAtom *definedAtom = cast<DefinedAtom>(ai._atom);
+                    llvm::dbgs() << "Writing atom: " << ai->_atom->name()
+                                 << " | " << ai->_fileOffset << "\n");
+    const DefinedAtom *definedAtom = cast<DefinedAtom>(ai->_atom);
     if (definedAtom->contentType() == DefinedAtom::typeZeroFill)
       continue;
     // Copy raw content of atom to file buffer.
@@ -355,14 +356,14 @@ void Section<ELFT>::write(ELFWriter *wri
     uint64_t contentSize = content.size();
     if (contentSize == 0)
       continue;
-    uint8_t *atomContent = chunkBuffer + ai._fileOffset;
+    uint8_t *atomContent = chunkBuffer + ai->_fileOffset;
     std::copy_n(content.data(), contentSize, atomContent);
     for (const auto ref : *definedAtom) {
       uint32_t offset = ref->offsetInAtom();
       uint64_t targetAddress = 0;
       assert(ref->target() != nullptr && "Found the target to be NULL");
       targetAddress = writer->addressOfAtom(ref->target());
-      uint64_t fixupAddress = writer->addressOfAtom(ai._atom) + offset;
+      uint64_t fixupAddress = writer->addressOfAtom(ai->_atom) + offset;
       // apply the relocation
       writer->kindHandler()->applyFixup(ref->kind(),
                                         ref->addend(),

Modified: lld/trunk/lib/ReaderWriter/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Writer.cpp?rev=173874&r1=173873&r2=173874&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Writer.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Writer.cpp Tue Jan 29 19:25:06 2013
@@ -97,7 +97,7 @@ void ExecutableWriter<ELFT>::buildSymbol
   for (auto sec : _layout->sections())
     if (auto section = dyn_cast<Section<ELFT>>(sec))
       for (const auto &atom : section->atoms())
-        _symtab->addSymbol(atom._atom, section->ordinal(), atom._virtualAddr);
+        _symtab->addSymbol(atom->_atom, section->ordinal(), atom->_virtualAddr);
 }
 
 template<class ELFT>
@@ -106,7 +106,7 @@ ExecutableWriter<ELFT>::addAbsoluteUndef
   // add all the absolute symbols that the layout contains to the output symbol
   // table
   for (auto &atom : _layout->absoluteAtoms())
-    _symtab->addSymbol(atom.absoluteAtom(), ELF::SHN_ABS, atom.value());
+    _symtab->addSymbol(atom->_atom, ELF::SHN_ABS, atom->_virtualAddr);
   for (const UndefinedAtom *a : file.undefined())
     _symtab->addSymbol(a, ELF::SHN_UNDEF);
 }
@@ -116,10 +116,10 @@ void ExecutableWriter<ELFT>::buildAtomTo
   for (auto sec : _layout->sections())
     if (auto section = dyn_cast<Section<ELFT>>(sec))
       for (const auto &atom : section->atoms())
-        _atomToAddressMap[atom._atom] = atom._virtualAddr;
+        _atomToAddressMap[atom->_atom] = atom->_virtualAddr;
   // build the atomToAddressMap that contains absolute symbols too
   for (auto &atom : _layout->absoluteAtoms())
-    _atomToAddressMap[atom.absoluteAtom()] = atom.value();
+    _atomToAddressMap[atom->_atom] = atom->_virtualAddr;
 }
 
 template<class ELFT>
@@ -187,11 +187,11 @@ void ExecutableWriter<ELFT>::finalizeDef
                       StringRef sec) -> void {
     auto section = _layout->findOutputSection(sec);
     if (section) {
-      start->setValue(section->virtualAddr());
-      end->setValue(section->virtualAddr() + section->memSize());
+      (*start)->_virtualAddr = section->virtualAddr();
+      (*end)->_virtualAddr = section->virtualAddr() + section->memSize();
     } else {
-      start->setValue(0);
-      end->setValue(0);
+      (*start)->_virtualAddr = 0;
+      (*end)->_virtualAddr = 0;
     }
   };
 
@@ -210,10 +210,10 @@ void ExecutableWriter<ELFT>::finalizeDef
   assert(!(phe == _programHeader->end()) &&
          "Can't find a data segment in the program header!");
 
-  bssStartAtomIter->setValue((*phe)->p_vaddr + (*phe)->p_filesz);
-  bssEndAtomIter->setValue((*phe)->p_vaddr + (*phe)->p_memsz);
-  underScoreEndAtomIter->setValue((*phe)->p_vaddr + (*phe)->p_memsz);
-  endAtomIter->setValue((*phe)->p_vaddr + (*phe)->p_memsz);
+  (*bssStartAtomIter)->_virtualAddr = (*phe)->p_vaddr + (*phe)->p_filesz;
+  (*bssEndAtomIter)->_virtualAddr = (*phe)->p_vaddr + (*phe)->p_memsz;
+  (*underScoreEndAtomIter)->_virtualAddr = (*phe)->p_vaddr + (*phe)->p_memsz;
+  (*endAtomIter)->_virtualAddr = (*phe)->p_vaddr + (*phe)->p_memsz;
 }
 
 template<class ELFT>





More information about the llvm-commits mailing list