[llvm-commits] [lld] r173082 - in /lld/trunk/lib/ReaderWriter/ELF: DefaultELFLayout.h ELFChunk.h ELFHeaderChunks.h ELFLayout.h ELFSectionChunks.h ELFSegmentChunks.h ELFWriter.h WriterELF.cpp

Shankar Easwaran shankare at codeaurora.org
Mon Jan 21 12:09:55 PST 2013


Author: shankare
Date: Mon Jan 21 14:09:55 2013
New Revision: 173082

URL: http://llvm.org/viewvc/llvm-project?rev=173082&view=rev
Log:
no functionality changes(split WriterELF into multiple files)

Added:
    lld/trunk/lib/ReaderWriter/ELF/DefaultELFLayout.h
    lld/trunk/lib/ReaderWriter/ELF/ELFChunk.h
    lld/trunk/lib/ReaderWriter/ELF/ELFHeaderChunks.h
    lld/trunk/lib/ReaderWriter/ELF/ELFLayout.h
    lld/trunk/lib/ReaderWriter/ELF/ELFSectionChunks.h
    lld/trunk/lib/ReaderWriter/ELF/ELFSegmentChunks.h
    lld/trunk/lib/ReaderWriter/ELF/ELFWriter.h
Modified:
    lld/trunk/lib/ReaderWriter/ELF/WriterELF.cpp

Added: lld/trunk/lib/ReaderWriter/ELF/DefaultELFLayout.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/DefaultELFLayout.h?rev=173082&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/DefaultELFLayout.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/DefaultELFLayout.h Mon Jan 21 14:09:55 2013
@@ -0,0 +1,629 @@
+//===- lib/ReaderWriter/ELF/DefaultELFLayout.h ---------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_DEFAULT_ELF_LAYOUT_H_
+#define LLD_READER_WRITER_DEFAULT_ELF_LAYOUT_H_
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+
+#include "ELFChunk.h"
+#include "ELFHeaderChunks.h"
+#include "ELFLayout.h"
+#include "ELFSectionChunks.h"
+#include "ELFSegmentChunks.h"
+
+#include <map>
+#include <unordered_map>
+#include <tuple>
+
+/// \brief The DefaultELFLayout class is used by the Writer to arrange
+///        sections and segments in the order determined by the target ELF
+///        format. The writer creates a single instance of the DefaultELFLayout
+///        class
+
+namespace lld {
+namespace elf {
+
+template<class ELFT>
+class DefaultELFLayout : public ELFLayout {
+public:
+
+  // The order in which the sections appear in the output file
+  // If its determined, that the layout needs to change
+  // just changing the order of enumerations would essentially
+  // change the layout in the output file
+  // Change the enumerations so that Target can override and stick 
+  // a section anywhere it wants to
+  enum DefaultSectionOrder {
+    ORDER_NOT_DEFINED = 0,
+    ORDER_INTERP = 10,
+    ORDER_NOTE = 20,
+    ORDER_HASH = 30,
+    ORDER_DYNAMIC_SYMBOLS = 40,
+    ORDER_DYNAMIC_STRINGS = 50,
+    ORDER_INIT = 60,
+    ORDER_TEXT = 70,
+    ORDER_PLT = 80,
+    ORDER_FINI = 90,
+    ORDER_RODATA = 100,
+    ORDER_EH_FRAME = 110,
+    ORDER_EH_FRAMEHDR = 120,
+    ORDER_CTORS = 130,
+    ORDER_DTORS = 140,
+    ORDER_INIT_ARRAY = 150,
+    ORDER_FINI_ARRAY = 160,
+    ORDER_DYNAMIC = 170,
+    ORDER_GOT = 180,
+    ORDER_GOT_PLT = 190,
+    ORDER_DATA = 200,
+    ORDER_BSS = 210,
+    ORDER_OTHER = 220,
+    ORDER_SECTION_STRINGS = 230,
+    ORDER_SYMBOL_TABLE = 240,
+    ORDER_STRING_TABLE = 250,
+    ORDER_SECTION_HEADERS = 260
+  };
+
+public:
+
+  // The Key used for creating Sections
+  // The sections are created using
+  // SectionName, [contentType, contentPermissions]
+  typedef std::pair<StringRef,
+                    std::pair<int32_t, int32_t>> Key;
+  typedef typename std::vector<Chunk<ELFT> *>::iterator ChunkIter;
+  // The key used for Segments
+  // The segments are created using
+  // SegmentName, Segment flags
+  typedef std::pair<StringRef, int64_t> SegmentKey;
+  // Merged Sections contain the map of Sectionnames to a vector of sections,
+  // that have been merged to form a single section
+  typedef std::map<StringRef, MergedSections<ELFT> *> MergedSectionMapT;
+  typedef typename std::vector<MergedSections<ELFT> *>::iterator
+    MergedSectionIter;
+
+  // HashKey for the Section
+  class HashKey {
+  public:
+    int64_t operator() (const Key &k) const {
+      // k.first = section Name
+      // k.second = [contentType, Permissions]
+      return llvm::hash_combine(k.first, k.second.first, k.second.second);
+    }
+  };
+
+  // HashKey for the Segment
+  class SegmentHashKey {
+  public:
+    int64_t operator() (const SegmentKey &k) const {
+      // k.first = SegmentName
+      // k.second = SegmentFlags
+      return llvm::hash_combine(k.first, k.second);
+    }
+  };
+
+  typedef std::unordered_map<Key, Section<ELFT>*, HashKey> SectionMapT;
+  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; 
+    }
+  };
+
+  typedef typename std::vector<AbsoluteAtomPair>::iterator AbsoluteAtomIterT;
+
+  DefaultELFLayout(const WriterOptionsELF &options) : _options(options) {}
+
+  /// \brief Return the section order for a input section
+  virtual SectionOrder getSectionOrder
+              (const StringRef name,
+              int32_t contentType,
+              int32_t contentPermissions);
+
+  /// \brief This maps the input sections to the output section names
+  StringRef getSectionName(const StringRef name,
+                           const int32_t contentType);
+
+  /// \brief Gets the segment for a output section
+  virtual ELFLayout::SegmentType getSegmentType(Section<ELFT> *section) const;
+
+  /// \brief Returns true/false depending on whether the section has a Output
+  //         segment or not
+  static bool hasOutputSegment(Section<ELFT> *section);
+
+  // Adds an atom to the section
+  virtual error_code addAtom(const Atom *atom);
+
+  /// \brief Find an output Section given a section name.
+  MergedSections<ELFT> *findOutputSection(StringRef name) {
+    auto iter = _mergedSectionMap.find(name);
+    if (iter == _mergedSectionMap.end()) 
+      return nullptr;
+    return iter->second;
+  }
+
+  /// \brief find a absolute atom given a name
+  AbsoluteAtomIterT findAbsoluteAtom(const StringRef name) {
+    return std::find_if(_absoluteAtoms.begin(), _absoluteAtoms.end(),
+                                                FindByName(name));
+  }
+
+  // Merge sections with the same name into a MergedSections
+  void mergeSimiliarSections();
+
+  void assignSectionsToSegments();
+
+  void assignVirtualAddress();
+
+  void assignOffsetsForMiscSections();
+
+  void assignFileOffsets();
+
+  /// Inline functions
+  inline range<AbsoluteAtomIterT> absoluteAtoms() { return _absoluteAtoms; }
+
+  inline void addSection(Chunk<ELFT> *c) {
+    _sections.push_back(c);
+  }
+
+  inline void finalize() {
+    for (auto &si : _sections)
+      si->finalize();
+  }
+
+  inline bool findAtomAddrByName(const StringRef name, uint64_t &addr) {
+    for (auto sec : _sections)
+      if (auto section = dyn_cast<Section<ELFT>>(sec))
+        if (section->findAtomAddrByName(name, addr))
+         return true;
+    return false;
+  }
+
+  inline void setELFHeader(ELFHeader<ELFT> *e) {
+    _elfHeader = e;
+  }
+
+  inline void setProgramHeader(ELFProgramHeader<ELFT> *p) {
+    _programHeader = p;
+  }
+
+  inline range<MergedSectionIter> mergedSections() { return _mergedSections; }
+
+  inline range<ChunkIter> sections() { return _sections; }
+
+  inline range<ChunkIter> segments() { return _segments; }
+
+  inline ELFHeader<ELFT> *elfHeader() {
+    return _elfHeader;
+  }
+
+  inline ELFProgramHeader<ELFT> *elfProgramHeader() {
+    return _programHeader;
+  }
+
+private:
+  SectionMapT _sectionMap;
+  MergedSectionMapT _mergedSectionMap;
+  SegmentMapT _segmentMap;
+  std::vector<Chunk<ELFT> *> _sections;
+  std::vector<Segment<ELFT> *> _segments;
+  std::vector<MergedSections<ELFT> *> _mergedSections;
+  ELFHeader<ELFT> *_elfHeader;
+  ELFProgramHeader<ELFT> *_programHeader;
+  std::vector<AbsoluteAtomPair> _absoluteAtoms;
+  llvm::BumpPtrAllocator _allocator;
+  const WriterOptionsELF _options;
+};
+
+template<class ELFT>
+ELFLayout::SectionOrder
+DefaultELFLayout<ELFT>::getSectionOrder(const StringRef name, 
+                                        int32_t contentType,
+                                        int32_t contentPermissions)
+{
+  switch (contentType) {
+  case DefinedAtom::typeCode:
+    return llvm::StringSwitch<Reference::Kind>(name)
+      .StartsWith(".eh_frame_hdr", ORDER_EH_FRAMEHDR)
+      .StartsWith(".eh_frame", ORDER_EH_FRAME)
+      .StartsWith(".init", ORDER_INIT)
+      .StartsWith(".fini", ORDER_FINI)
+      .StartsWith(".hash", ORDER_HASH)
+      .Default(ORDER_TEXT);
+  
+  case DefinedAtom::typeConstant:
+    return ORDER_RODATA;
+  
+  case DefinedAtom::typeData:
+    return llvm::StringSwitch<Reference::Kind>(name)
+      .StartsWith(".init_array", ORDER_INIT_ARRAY)
+      .Default(ORDER_DATA);
+  
+  case DefinedAtom::typeZeroFill:
+    return ORDER_BSS;
+  
+  default:
+    // If we get passed in a section push it to OTHER
+    if (contentPermissions == DefinedAtom::perm___)
+      return ORDER_OTHER;
+  
+    return ORDER_NOT_DEFINED;
+  }
+}
+
+/// \brief This maps the input sections to the output section names
+template<class ELFT>
+StringRef 
+DefaultELFLayout<ELFT>::getSectionName(const StringRef name, 
+                                       const int32_t contentType) {
+  if (contentType == DefinedAtom::typeZeroFill)
+    return ".bss";
+  if (name.startswith(".text"))
+    return ".text";
+  if (name.startswith(".rodata"))
+    return ".rodata";
+  return name;
+}
+
+/// \brief Gets the segment for a output section
+template<class ELFT>
+ELFLayout::SegmentType 
+DefaultELFLayout<ELFT>::getSegmentType(Section<ELFT> *section) const {
+  switch(section->order()) {
+  case ORDER_INTERP:
+    return llvm::ELF::PT_INTERP;
+
+  case ORDER_TEXT:
+  case ORDER_HASH:
+  case ORDER_DYNAMIC_SYMBOLS:
+  case ORDER_DYNAMIC_STRINGS:
+  case ORDER_INIT:
+  case ORDER_PLT:
+  case ORDER_FINI:
+  case ORDER_RODATA:
+  case ORDER_EH_FRAME:
+  case ORDER_EH_FRAMEHDR:
+    return llvm::ELF::PT_LOAD;
+
+  case ORDER_NOTE:
+    return llvm::ELF::PT_NOTE;
+
+  case ORDER_DYNAMIC:
+    return llvm::ELF::PT_DYNAMIC;
+
+  case ORDER_CTORS:
+  case ORDER_DTORS:
+  case ORDER_GOT:
+    return llvm::ELF::PT_GNU_RELRO;
+
+  case ORDER_GOT_PLT:
+  case ORDER_DATA:
+  case ORDER_BSS:
+  case ORDER_INIT_ARRAY:
+  case ORDER_FINI_ARRAY:
+    return llvm::ELF::PT_LOAD;
+
+  default:
+    return llvm::ELF::PT_NULL;
+  }
+}
+
+template<class ELFT>
+bool
+DefaultELFLayout<ELFT>::hasOutputSegment(Section<ELFT> *section) {
+  switch(section->order()) {
+  case ORDER_INTERP:
+  case ORDER_HASH:
+  case ORDER_DYNAMIC_SYMBOLS:
+  case ORDER_DYNAMIC_STRINGS:
+  case ORDER_INIT:
+  case ORDER_PLT:
+  case ORDER_TEXT:
+  case ORDER_FINI:
+  case ORDER_RODATA:
+  case ORDER_EH_FRAME:
+  case ORDER_EH_FRAMEHDR:
+  case ORDER_NOTE:
+  case ORDER_DYNAMIC:
+  case ORDER_CTORS:
+  case ORDER_DTORS:
+  case ORDER_GOT:
+  case ORDER_GOT_PLT:
+  case ORDER_DATA:
+  case ORDER_INIT_ARRAY:
+  case ORDER_FINI_ARRAY:
+  case ORDER_BSS:
+    return true;
+  
+  default:
+    return false;
+  }
+}
+
+template<class ELFT>
+error_code
+DefaultELFLayout<ELFT>::addAtom(const Atom *atom) {
+  if (const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom)) {
+    const StringRef sectionName =
+                getSectionName(definedAtom->customSectionName(),
+                               definedAtom->contentType());
+    const lld::DefinedAtom::ContentPermissions permissions =
+                                  definedAtom->permissions();
+    const lld::DefinedAtom::ContentType contentType =
+                                  definedAtom->contentType();
+    const Key key(sectionName, std::make_pair(contentType, permissions));
+    const std::pair<Key, Section<ELFT> *>currentSection(key, nullptr);
+    std::pair<typename SectionMapT::iterator, bool>
+      sectionInsert(_sectionMap.insert(currentSection));
+    Section<ELFT> *section;
+    // the section is already in the map
+    if (!sectionInsert.second) {
+      section = sectionInsert.first->second;
+      section->setContentPermissions(permissions);
+    } else {
+      SectionOrder section_order = getSectionOrder(sectionName,
+                                     contentType,
+                                     permissions);
+      section = new (_allocator.Allocate<Section<ELFT>>()) Section<ELFT>(
+        sectionName, contentType, permissions, section_order);
+      sectionInsert.first->second = section;
+      section->setOrder(section_order);
+      _sections.push_back(section);
+    }
+    section->appendAtom(atom);
+  }
+  // Absolute atoms are not part of any section, they are global for the whole
+  // link
+  else if (const AbsoluteAtom *absoluteAtom = dyn_cast<AbsoluteAtom>(atom)) {
+    _absoluteAtoms.push_back(AbsoluteAtomPair(absoluteAtom, 
+                                              absoluteAtom->value()));
+  }
+  else 
+    llvm_unreachable("Only absolute / defined atoms can be added here");
+  return error_code::success();
+}
+
+/// Merge sections with the same name into a MergedSections
+template<class ELFT>
+void 
+DefaultELFLayout<ELFT>::mergeSimiliarSections() {
+  MergedSections<ELFT> *mergedSection;
+
+  for (auto &si : _sections) {
+    const std::pair<StringRef, MergedSections<ELFT> *>
+      currentMergedSections(si->name(), nullptr);
+    std::pair<typename MergedSectionMapT::iterator, bool>
+                            mergedSectionInsert
+                            (_mergedSectionMap.insert(currentMergedSections));
+    if (!mergedSectionInsert.second) {
+      mergedSection = mergedSectionInsert.first->second;
+    } else {
+      mergedSection = new (_allocator.Allocate<MergedSections<ELFT>>())
+        MergedSections<ELFT>(si->name());
+      _mergedSections.push_back(mergedSection);
+      mergedSectionInsert.first->second = mergedSection;
+    }
+    mergedSection->appendSection(si);
+  }
+}
+
+template<class ELFT>
+void 
+DefaultELFLayout<ELFT>::assignSectionsToSegments() {
+  // sort the sections by their order as defined by the layout
+  std::stable_sort(_sections.begin(), _sections.end(),
+  [](Chunk<ELFT> *A, Chunk<ELFT> *B) {
+     return A->order() < B->order();
+  });
+  // Merge all sections
+  mergeSimiliarSections();
+  // Set the ordinal after sorting the sections
+  int ordinal = 1;
+  for (auto msi : _mergedSections) {
+    msi->setOrdinal(ordinal);
+    for (auto ai : msi->sections()) {
+      ai->setOrdinal(ordinal);
+    }
+    ++ordinal;
+  }
+  for (auto msi : _mergedSections) {
+    for (auto ai : msi->sections()) {
+      if (auto section = dyn_cast<Section<ELFT>>(ai)) {
+        if (!hasOutputSegment(section))
+          continue;
+        msi->setHasSegment();
+        section->setSegment(getSegmentType(section));
+        const StringRef segmentName = section->segmentKindToStr();
+        // Use the flags of the merged Section for the segment
+        const SegmentKey key(segmentName, msi->flags());
+        const std::pair<SegmentKey, Segment<ELFT> *>
+          currentSegment(key, nullptr);
+        std::pair<typename SegmentMapT::iterator, bool>
+                            segmentInsert(_segmentMap.insert(currentSegment));
+        Segment<ELFT> *segment;
+        if (!segmentInsert.second) {
+          segment = segmentInsert.first->second;
+        } else {
+          segment = new (_allocator.Allocate<Segment<ELFT>>()) Segment<ELFT>(
+            segmentName, getSegmentType(section), _options);
+          segmentInsert.first->second = segment;
+          _segments.push_back(segment);
+        }
+        segment->append(section);
+      }
+    }
+  }
+}
+
+template<class ELFT>
+void
+DefaultELFLayout<ELFT>::assignFileOffsets() {
+  std::sort(_segments.begin(), _segments.end(),
+            Segment<ELFT>::compareSegments);
+  int ordinal = 0;
+  // Compute the number of segments that might be needed, so that the
+  // size of the program header can be computed
+  uint64_t offset = 0;
+  for (auto si : _segments) {
+    si->setOrdinal(++ordinal);
+    si->assignOffsets(offset);
+    offset += si->fileSize();
+  }
+}
+
+
+template<class ELFT>
+void
+DefaultELFLayout<ELFT>::assignVirtualAddress() {
+  if (_segments.empty())
+    return;
+  
+  uint64_t virtualAddress = _options.baseAddress();
+  
+  // HACK: This is a super dirty hack. The elf header and program header are
+  // not part of a section, but we need them to be loaded at the base address
+  // so that AT_PHDR is set correctly by the loader and so they are accessible
+  // at runtime. To do this we simply prepend them to the first Segment and
+  // let the layout logic take care of it.
+  _segments[0]->prepend(_programHeader);
+  _segments[0]->prepend(_elfHeader);
+  
+  bool newSegmentHeaderAdded = true;
+  while (true) {
+    for (auto si : _segments) {
+      newSegmentHeaderAdded = _programHeader->addSegment(si);
+    }
+    if (!newSegmentHeaderAdded)
+      break;
+    uint64_t fileoffset = 0;
+    uint64_t address = virtualAddress;
+    // Fix the offsets after adding the program header
+    for (auto &si : _segments) {
+      // Align the segment to a page boundary
+      fileoffset = llvm::RoundUpToAlignment(fileoffset,
+                                            _options.pageSize());
+      si->assignOffsets(fileoffset);
+      fileoffset = si->fileOffset() + si->fileSize();
+    }
+    // start assigning virtual addresses
+    for (auto si = _segments.begin(); si != _segments.end(); ++si) {
+      (*si)->setVAddr(virtualAddress);
+      // The first segment has the virtualAddress set to the base address as
+      // we have added the file header and the program header dont align the
+      // first segment to the pagesize
+      (*si)->assignVirtualAddress(address);
+      (*si)->setMemSize(address - virtualAddress);
+      virtualAddress = llvm::RoundUpToAlignment(address,
+                                                _options.pageSize());
+    }
+    _programHeader->resetProgramHeaders();
+  }
+  Section<ELFT> *section;
+  // Fix the offsets of all the atoms within a section
+  for (auto &si : _sections) {
+    section = dyn_cast<Section<ELFT>>(si);
+    if (section && DefaultELFLayout<ELFT>::hasOutputSegment(section))
+      section->assignOffsets(section->fileOffset());
+  }
+  // Set the size of the merged Sections
+  for (auto msi : _mergedSections) {
+    uint64_t sectionfileoffset = 0;
+    uint64_t startFileOffset = 0;
+    uint64_t sectionsize = 0;
+    bool isFirstSection = true;
+    for (auto si : msi->sections()) {
+      if (isFirstSection) {
+        startFileOffset = si->fileOffset();
+        isFirstSection = false;
+      }
+      sectionfileoffset = si->fileOffset();
+      sectionsize = si->fileSize();
+    }
+    sectionsize = (sectionfileoffset - startFileOffset) + sectionsize;
+    msi->setFileOffset(startFileOffset);
+    msi->setSize(sectionsize);
+  }
+  // Set the virtual addr of the merged Sections
+  for (auto msi : _mergedSections) {
+    uint64_t sectionstartaddr = 0;
+    uint64_t startaddr = 0;
+    uint64_t sectionsize = 0;
+    bool isFirstSection = true;
+    for (auto si : msi->sections()) {
+      if (isFirstSection) {
+        startaddr = si->virtualAddr();
+        isFirstSection = false;
+      }
+      sectionstartaddr = si->virtualAddr();
+      sectionsize = si->memSize();
+    }
+    sectionsize = (sectionstartaddr - startaddr) + sectionsize;
+    msi->setMemSize(sectionsize);
+    msi->setAddr(startaddr);
+  }
+}
+
+template<class ELFT>
+void
+DefaultELFLayout<ELFT>::assignOffsetsForMiscSections() {
+  uint64_t fileoffset = 0;
+  uint64_t size = 0;
+  for (auto si : _segments) {
+    fileoffset = si->fileOffset();
+    size = si->fileSize();
+  }
+  fileoffset = fileoffset + size;
+  Section<ELFT> *section;
+  for (auto si : _sections) {
+    section = dyn_cast<Section<ELFT>>(si);
+    if (section && DefaultELFLayout<ELFT>::hasOutputSegment(section))
+      continue;
+    fileoffset = llvm::RoundUpToAlignment(fileoffset, si->align2());
+    si->setFileOffset(fileoffset);
+    si->setVAddr(0);
+    fileoffset += si->fileSize();
+  }
+}
+
+} // elf
+} // lld
+
+#endif // LLD_READER_WRITER_DEFAULT_ELF_LAYOUT_H_

Added: lld/trunk/lib/ReaderWriter/ELF/ELFChunk.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFChunk.h?rev=173082&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFChunk.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFChunk.h Mon Jan 21 14:09:55 2013
@@ -0,0 +1,99 @@
+//===- lib/ReaderWriter/ELF/ELFChunks.h ---------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_ELF_CHUNKS_H_
+#define LLD_READER_WRITER_ELF_CHUNKS_H_
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Object/ELF.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ELF.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileOutputBuffer.h"
+
+namespace lld {
+namespace elf {  
+
+class ELFWriter;
+
+/// \brief A chunk is a contiguous region of space
+template<class ELFT>
+class Chunk {
+public:
+
+  /// \brief Describes the type of Chunk
+  enum Kind {
+    K_ELFHeader, // ELF Header
+    K_ELFProgramHeader, // Program Header
+    K_ELFSegment, // Segment
+    K_ELFSection, // Section
+    K_ELFSectionHeader // Section header
+  };
+  Chunk(llvm::StringRef name, Kind kind)
+    : _name(name)
+    , _kind(kind)
+    , _fsize(0)
+    , _msize(0)
+    , _align2(0)
+    , _order(0)
+    , _ordinal(1)
+    , _start(0)
+    , _fileoffset(0) {}
+  virtual             ~Chunk() {}
+  // Does the chunk occupy disk space
+  virtual bool        occupiesNoDiskSpace() const {
+    return false;
+  }
+  // The name of the chunk
+  llvm::StringRef name() const { return _name; }
+  // Kind of chunk
+  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;}
+  void               setOrdinal(uint64_t newVal) { _ordinal = newVal;}
+  // The order in which the chunk would appear in the output file
+  uint64_t            order() const { return _order; }
+  void               setOrder(uint32_t order) { _order = order; }
+  // Output file offset of the chunk
+  uint64_t            fileOffset() const { return _fileoffset; }
+  void               setFileOffset(uint64_t offset) { _fileoffset = offset; }
+  // Output start address of the chunk
+  void               setVAddr(uint64_t start) { _start = start; }
+  uint64_t            virtualAddr() const { return _start; }
+  // Does the chunk occupy memory during execution ?
+  uint64_t            memSize() const { return _msize; }
+  void               setMemSize(uint64_t msize) { _msize = msize; }
+  // Writer the chunk
+  virtual void       write(ELFWriter *writer,
+                           llvm::OwningPtr<llvm::FileOutputBuffer> &buffer) = 0;
+  // Finalize the chunk before writing
+  virtual void       finalize() = 0;
+
+protected:
+  llvm::StringRef _name;
+  Kind _kind;
+  uint64_t _fsize;
+  uint64_t _msize;
+  uint64_t _align2;
+  uint32_t  _order;
+  uint64_t _ordinal;
+  uint64_t _start;
+  uint64_t _fileoffset;
+};
+
+} // elf
+} // lld
+
+#endif // LLD_READER_WRITER_ELF_CHUNKS_H_

Added: lld/trunk/lib/ReaderWriter/ELF/ELFHeaderChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFHeaderChunks.h?rev=173082&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFHeaderChunks.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFHeaderChunks.h Mon Jan 21 14:09:55 2013
@@ -0,0 +1,316 @@
+//===- lib/ReaderWriter/ELF/ELFHeaderChunks.h -----------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_ELF_HEADER_CHUNKS_H_
+#define LLD_READER_WRITER_ELF_HEADER_CHUNKS_H_
+
+#include "llvm/Object/ELF.h"
+
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ELF.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileOutputBuffer.h"
+
+#include "ELFSegmentChunks.h"
+
+/// \brief An ELFHeader represents the Elf[32/64]_Ehdr structure at the
+///        start of an ELF executable file.
+namespace lld {
+namespace elf {
+
+template<class ELFT>
+class ELFHeader : public Chunk<ELFT> {
+public:
+  typedef llvm::object::Elf_Ehdr_Impl<ELFT> Elf_Ehdr;
+
+  ELFHeader();
+
+  void e_ident(int I, unsigned char C) { _eh.e_ident[I] = C; }
+  void e_type(uint16_t type)           { _eh.e_type = type; }
+  void e_machine(uint16_t machine)     { _eh.e_machine = machine; }
+  void e_version(uint32_t version)     { _eh.e_version = version; }
+  void e_entry(int64_t entry)         { _eh.e_entry = entry; }
+  void e_phoff(int64_t phoff)         { _eh.e_phoff = phoff; }
+  void e_shoff(int64_t shoff)         { _eh.e_shoff = shoff; }
+  void e_flags(uint32_t flags)         { _eh.e_flags = flags; }
+  void e_ehsize(uint16_t ehsize)       { _eh.e_ehsize = ehsize; }
+  void e_phentsize(uint16_t phentsize) { _eh.e_phentsize = phentsize; }
+  void e_phnum(uint16_t phnum)         { _eh.e_phnum = phnum; }
+  void e_shentsize(uint16_t shentsize) { _eh.e_shentsize = shentsize; }
+  void e_shnum(uint16_t shnum)         { _eh.e_shnum = shnum; }
+  void e_shstrndx(uint16_t shstrndx)   { _eh.e_shstrndx = shstrndx; }
+  uint64_t  fileSize()                 { return sizeof (Elf_Ehdr); }
+
+  static inline bool classof(const Chunk<ELFT> *c) {
+    return c->Kind() == Chunk<ELFT>::K_ELFHeader;
+  }
+
+  void write(ELFWriter *writer, llvm::OwningPtr<llvm::FileOutputBuffer> &buffer);
+
+  void finalize() { }
+
+private:
+  Elf_Ehdr _eh;
+};
+
+template<class ELFT>
+ELFHeader<ELFT>::ELFHeader()
+: Chunk<ELFT>("elfhdr", Chunk<ELFT>::K_ELFHeader) {
+  this->_align2 = ELFT::Is64Bits ? 8 : 4;
+  this->_fsize = sizeof(Elf_Ehdr);
+  this->_msize = sizeof(Elf_Ehdr);
+  memset(_eh.e_ident, 0, llvm::ELF::EI_NIDENT);
+  e_ident(llvm::ELF::EI_MAG0, 0x7f);
+  e_ident(llvm::ELF::EI_MAG1, 'E');
+  e_ident(llvm::ELF::EI_MAG2, 'L');
+  e_ident(llvm::ELF::EI_MAG3, 'F');
+  e_ehsize(sizeof(Elf_Ehdr));
+  e_flags(2);
+}
+
+template<class ELFT>
+void 
+ELFHeader<ELFT>::write(ELFWriter *writer,
+                       llvm::OwningPtr<llvm::FileOutputBuffer> &buffer) {
+  uint8_t *chunkBuffer = buffer->getBufferStart();
+  uint8_t *atomContent = chunkBuffer + this->fileOffset();
+  memcpy(atomContent, &_eh, fileSize());
+}
+
+/// \brief An ELFProgramHeader represents the Elf[32/64]_Phdr structure at the
+///        start of an ELF executable file.
+template<class ELFT>
+class ELFProgramHeader : public Chunk<ELFT> {
+public:
+  typedef llvm::object::Elf_Phdr_Impl<ELFT> Elf_Phdr;
+  typedef typename std::vector<Elf_Phdr *>::iterator PhIterT;
+
+  /// \brief Find a program header entry, given the type of entry that
+  /// we are looking for
+  class FindPhdr {
+  public:
+    FindPhdr(uint64_t type, uint64_t flags, uint64_t flagsClear) 
+             : _type(type)
+             , _flags(flags)
+             , _flagsClear(flagsClear)
+    {}
+
+    bool operator()(const Elf_Phdr *j) const { 
+      return ((j->p_type == _type) &&
+              ((j->p_flags & _flags) == _flags) &&
+              (!(j->p_flags & _flagsClear)));
+    }
+  private:
+    uint64_t _type;
+    uint64_t _flags;
+    uint64_t _flagsClear;
+  };
+
+  ELFProgramHeader()
+  : Chunk<ELFT>("elfphdr", Chunk<ELFT>::K_ELFProgramHeader) {
+    this->_align2 = ELFT::Is64Bits ? 8 : 4;
+    resetProgramHeaders();
+  }
+
+  bool addSegment(Segment<ELFT> *segment);
+
+  void resetProgramHeaders() {
+    _phi = _ph.begin();
+  }
+
+  uint64_t  fileSize() {
+    return sizeof(Elf_Phdr) * _ph.size();
+  }
+
+  static inline bool classof(const Chunk<ELFT> *c) {
+    return c->Kind() == Chunk<ELFT>::K_ELFProgramHeader;
+  }
+
+  void write(ELFWriter *writer, llvm::OwningPtr<llvm::FileOutputBuffer> &buffer);
+
+  /// \brief find a program header entry in the list of program headers
+  PhIterT findProgramHeader(uint64_t type, uint64_t flags, uint64_t flagClear) {
+    return std::find_if(_ph.begin(), _ph.end(), 
+                        FindPhdr(type, flags, flagClear));
+  }
+
+  PhIterT begin() {
+    return _ph.begin();
+  }
+
+  PhIterT end() {
+    return _ph.end();
+  }
+
+  void finalize() { }
+
+  int64_t entsize() {
+    return sizeof(Elf_Phdr);
+  }
+
+  int64_t numHeaders() {
+    return _ph.size();
+  }
+
+private:
+  std::vector<Elf_Phdr *> _ph;
+  PhIterT _phi;
+  llvm::BumpPtrAllocator  _allocator;
+};
+
+template<class ELFT>
+bool
+ELFProgramHeader<ELFT>::addSegment(Segment<ELFT> *segment) {
+  Elf_Phdr *phdr = nullptr;
+  bool ret = false;
+
+  for (auto slice : segment->slices()) {
+    if (_phi == _ph.end()) {
+      phdr = new(_allocator.Allocate<Elf_Phdr>()) Elf_Phdr;
+      _ph.push_back(phdr);
+      _phi = _ph.end();
+      ret = true;
+    } else {
+      phdr = (*_phi);
+      ++_phi;
+    }
+    phdr->p_type = segment->segmentType();
+    phdr->p_offset = slice->fileOffset();
+    phdr->p_vaddr = slice->virtualAddr();
+    phdr->p_paddr = slice->virtualAddr();
+    phdr->p_filesz = slice->fileSize();
+    phdr->p_memsz = slice->memSize();
+    phdr->p_flags = segment->flags();
+    phdr->p_align = (phdr->p_type == llvm::ELF::PT_LOAD) ?
+                     segment->pageSize() : slice->align2();
+  }
+  this->_fsize = fileSize();
+  this->_msize = this->_fsize;
+
+  return ret;
+}
+
+template<class ELFT>
+void
+ELFProgramHeader<ELFT>::write(ELFWriter *writer,
+           llvm::OwningPtr<llvm::FileOutputBuffer> &buffer) {
+  uint8_t *chunkBuffer = buffer->getBufferStart();
+  uint8_t *dest = chunkBuffer + this->fileOffset();
+  for (auto phi : _ph) {
+    memcpy(dest, phi, sizeof(Elf_Phdr));
+    dest += sizeof(Elf_Phdr);
+  }
+}
+
+/// \brief An ELFSectionHeader represents the Elf[32/64]_Shdr structure
+/// at the end of the file
+template<class ELFT>
+class ELFSectionHeader : public Chunk<ELFT> {
+public:
+  typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
+
+  ELFSectionHeader(int32_t order);
+
+  void appendSection(MergedSections<ELFT> *section);
+  
+  void updateSection(Section<ELFT> *section);
+  
+  static inline bool classof(const Chunk<ELFT> *c) {
+    return c->getChunkKind() == Chunk<ELFT>::K_ELFSectionHeader;
+  }
+  
+  void setStringSection(ELFStringTable<ELFT> *s) {
+    _stringSection = s;
+  }
+  
+  void write(ELFWriter *writer, llvm::OwningPtr<llvm::FileOutputBuffer> &buffer);
+  
+  void finalize() { }
+  
+  inline uint16_t fileSize() {
+    return sizeof(Elf_Shdr) * _sectionInfo.size();
+  }
+
+  inline int64_t entsize() {
+    return sizeof(Elf_Shdr);
+  }
+  
+  inline int64_t numHeaders() {
+    return _sectionInfo.size();
+  }
+
+private:
+  ELFStringTable<ELFT> *_stringSection;
+  std::vector<Elf_Shdr*>                  _sectionInfo;
+  llvm::BumpPtrAllocator                  _sectionAllocate;
+};
+
+template<class ELFT>
+ELFSectionHeader<ELFT>::ELFSectionHeader(int32_t order) 
+  : Chunk<ELFT>("shdr", Chunk<ELFT>::K_ELFSectionHeader) {
+  this->_fsize = 0;
+  this->_align2 = 8;
+  this->setOrder(order);
+  // The first element in the list is always NULL
+  Elf_Shdr *nullshdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
+  ::memset(nullshdr, 0, sizeof (Elf_Shdr));
+  _sectionInfo.push_back(nullshdr);
+  this->_fsize += sizeof (Elf_Shdr);
+}
+
+template<class ELFT>
+void 
+ELFSectionHeader<ELFT>::appendSection(MergedSections<ELFT> *section) {
+  Elf_Shdr *shdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
+  shdr->sh_name   = _stringSection->addString(section->name());
+  shdr->sh_type   = section->type();
+  shdr->sh_flags  = section->flags();
+  shdr->sh_offset = section->fileOffset();
+  shdr->sh_addr   = section->virtualAddr();
+  shdr->sh_size   = section->memSize();
+  shdr->sh_link   = section->link();
+  shdr->sh_info   = section->shinfo();
+  shdr->sh_addralign = section->align2();
+  shdr->sh_entsize = section->entsize();
+  _sectionInfo.push_back(shdr);
+}
+
+template<class ELFT>
+void 
+ELFSectionHeader<ELFT>::updateSection(Section<ELFT> *section) {
+  Elf_Shdr *shdr = _sectionInfo[section->ordinal()];
+  shdr->sh_type   = section->type();
+  shdr->sh_flags  = section->flags();
+  shdr->sh_offset = section->fileOffset();
+  shdr->sh_addr   = section->virtualAddr();
+  shdr->sh_size   = section->fileSize();
+  shdr->sh_link   = section->link();
+  shdr->sh_info   = section->shinfo();
+  shdr->sh_addralign = section->align2();
+  shdr->sh_entsize = section->entsize();
+}
+
+template<class ELFT>
+void 
+ELFSectionHeader<ELFT>::write(ELFWriter *writer,
+           llvm::OwningPtr<llvm::FileOutputBuffer> &buffer) {
+  uint8_t *chunkBuffer = buffer->getBufferStart();
+  uint8_t *dest = chunkBuffer + this->fileOffset();
+  for (auto shi : _sectionInfo) {
+    memcpy(dest, shi, sizeof(Elf_Shdr));
+    dest += sizeof(Elf_Shdr);
+  }
+  _stringSection->write(writer, buffer);
+}
+
+} // elf
+} // lld
+
+#endif // LLD_READER_WRITER_ELF_HEADER_CHUNKS_H_

Added: lld/trunk/lib/ReaderWriter/ELF/ELFLayout.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFLayout.h?rev=173082&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFLayout.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFLayout.h Mon Jan 21 14:09:55 2013
@@ -0,0 +1,74 @@
+//===- lib/ReaderWriter/ELF/ELFLayout.h ---------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_ELF_LAYOUT_H_
+#define LLD_READER_WRITER_ELF_LAYOUT_H_
+
+#include "lld/Core/DefinedAtom.h"
+
+#include "llvm/ADT/StringRef.h"
+
+#include "llvm/Object/ELF.h"
+
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ELF.h"
+
+namespace lld {
+namespace elf {
+/// \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 ELFLayout for generating each binary thats
+//         needed by the lld linker
+class ELFLayout {
+public:
+  typedef uint32_t SectionOrder;
+  typedef uint32_t SegmentType;
+  typedef uint32_t Flags;
+
+public:
+  /// Return the order the section would appear in the output file
+  virtual SectionOrder getSectionOrder
+                        (const llvm::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;
+  /// find the Atom Address in the current layout
+  virtual bool findAtomAddrByName(const llvm::StringRef name, 
+                                  uint64_t &addr) = 0;
+  /// associates a section to a segment
+  virtual void assignSectionsToSegments() = 0;
+  /// associates a virtual address to the segment, section, and the atom
+  virtual void assignVirtualAddress() = 0;
+  /// associates a file offset to the segment, section and the atom
+  virtual void assignFileOffsets() = 0;
+
+public:
+  ELFLayout() {}
+
+  virtual ~ELFLayout() { }
+};
+
+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;
+};
+} // lld
+} // elf
+
+#endif // LLD_READER_WRITER_ELF_LAYOUT_H_

Added: lld/trunk/lib/ReaderWriter/ELF/ELFSectionChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFSectionChunks.h?rev=173082&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFSectionChunks.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFSectionChunks.h Mon Jan 21 14:09:55 2013
@@ -0,0 +1,706 @@
+//===- lib/ReaderWriter/ELF/ELFSectionChunks.h -----------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_ELF_SECTION_CHUNKS_H_
+#define LLD_READER_WRITER_ELF_SECTION_CHUNKS_H_
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/range.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
+
+#include "llvm/Object/ELF.h"
+
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ELF.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileOutputBuffer.h"
+
+#include "ELFChunk.h"
+#include "ELFLayout.h"
+#include "ELFWriter.h"
+
+namespace lld {
+namespace elf {
+
+/// \brief A section contains a set of atoms that have similiar properties
+///        The atoms that have similiar properties are merged to form a section
+template<class ELFT>
+class Section : public Chunk<ELFT> {
+public:
+  // The Kind of section that the object represents
+  enum SectionKind {
+    K_Default,
+    K_Target, // The section is handed over to the target
+    K_SymbolTable,
+    K_StringTable,
+  };
+  // Create a section object, the section is set to the default type if the
+  // caller doesnot set it
+  Section(const llvm::StringRef sectionName,
+          const int32_t contentType,
+          const int32_t contentPermissions,
+          const int32_t order,
+          const SectionKind kind = K_Default);
+
+  /// return the section kind
+  inline SectionKind sectionKind() const {
+    return _sectionKind;
+  }
+
+  /// Align the offset to the required modulus defined by the atom alignment
+  uint64_t alignOffset(uint64_t offset, DefinedAtom::Alignment &atomAlign);
+
+  // \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);
+
+  /// \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;
+    }
+    addr += this->memSize();
+  }
+
+  /// \brief Set the file offset of each Atom in the section. This routine
+  /// 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;
+    }
+  }
+
+  /// \brief Find the Atom address given a name, this is needed to to properly
+  ///  apply relocation. The section class calls this to find the atom address
+  ///  to fix the relocation
+  inline bool findAtomAddrByName(const llvm::StringRef name, uint64_t &addr) {
+    for (auto ai : _atoms) {
+      if (ai._atom->name() == name) {
+        addr = ai._virtualAddr;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /// \brief Does the Atom occupy any disk space
+  inline bool occupiesNoDiskSpace() const {
+    return _contentType == DefinedAtom::typeZeroFill;
+  }
+
+  /// \brief The permission of the section is the most permissive permission
+  /// of all atoms that the section contains
+  inline void setContentPermissions(int32_t perm) {
+    _contentPermissions = std::max(perm, _contentPermissions);
+  }
+
+  /// \brief Get the section flags, defined by the permissions of the section
+  int64_t flags();
+
+  /// \brief Return the section type, the returned value is recorded in the
+  /// sh_type field of the Section Header
+  int type();
+
+  /// \brief convert the segment type to a String for diagnostics
+  ///        and printing purposes
+  llvm::StringRef segmentKindToStr() const;
+
+  /// \brief Return the raw flags, we need this to sort segments
+  inline int64_t atomflags() const {
+    return _contentPermissions;
+  }
+
+  /// \brief Returns the section link field, the returned value is
+  ///        recorded in the sh_link field of the Section Header
+  inline int link() const {
+    return _link;
+  }
+
+  inline void setLink(int32_t link) {
+    _link = link;
+  }
+
+  /// \brief Returns the section entsize field, the returned value is
+  ///        recorded in the sh_entsize field of the Section Header
+  inline int entsize() const {
+    return _entSize;
+  }
+
+  /// \brief Returns the shinfo field, the returned value is
+  ///        recorded in the sh_info field of the Section Header
+  inline int shinfo() const {
+    return _shInfo;
+  }
+
+  /// \brief Records the segmentType, that this section belongs to
+  inline void setSegment(const ELFLayout::SegmentType segmentType) {
+    _segmentType = segmentType;
+  }
+
+  /// \brief for LLVM style RTTI information
+  static inline bool classof(const Chunk<ELFT> *c) {
+    return c->kind() == Chunk<ELFT>::K_ELFSection;
+  }
+
+  /// \brief Finalize the section contents before writing
+  inline void finalize() { }
+
+  /// \brief Write the section and the atom contents to the buffer
+  void write(ELFWriter *writer,
+             llvm::OwningPtr<llvm::FileOutputBuffer> &buffer);
+
+  /// Atom Iterators
+  typedef typename std::vector<AtomLayout>::iterator atom_iter;
+
+  range<atom_iter> atoms() { return _atoms; }
+
+protected:
+  int32_t _contentType;
+  int32_t _contentPermissions;
+  SectionKind _sectionKind;
+  std::vector<AtomLayout> _atoms;
+  ELFLayout::SegmentType _segmentType;
+  int64_t _entSize;
+  int64_t _shInfo;
+  int64_t _link;
+};
+
+// Create a section object, the section is set to the default type if the
+// caller doesnot set it
+template<class ELFT>
+Section<ELFT>::Section(const StringRef sectionName,
+                       const int32_t contentType,
+                       const int32_t contentPermissions,
+                       const int32_t order,
+                       const SectionKind kind)
+  : Chunk<ELFT>(sectionName, Chunk<ELFT>::K_ELFSection)
+  , _contentType(contentType)
+  , _contentPermissions(contentPermissions)
+  , _sectionKind(kind)
+  , _entSize(0)
+  , _shInfo(0)
+  , _link(0) {
+  this->setOrder(order);
+}
+
+/// Align the offset to the required modulus defined by the atom alignment
+template<class ELFT>
+uint64_t 
+Section<ELFT>::alignOffset(uint64_t offset, DefinedAtom::Alignment &atomAlign) {
+  uint64_t requiredModulus = atomAlign.modulus;
+  uint64_t align2 = 1u << atomAlign.powerOf2;
+  uint64_t currentModulus = (offset % align2);
+  uint64_t retOffset = offset;
+  if (currentModulus != requiredModulus) {
+    if (requiredModulus > currentModulus)
+      retOffset += requiredModulus - currentModulus;
+    else
+      retOffset += align2 + requiredModulus - currentModulus;
+  }
+  return retOffset;
+}
+
+// \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) {
+  Atom::Definition atomType = atom->definition();
+  const DefinedAtom *definedAtom = cast<DefinedAtom>(atom);
+
+  DefinedAtom::Alignment atomAlign = definedAtom->alignment();
+  uint64_t align2 = 1u << atomAlign.powerOf2;
+  // Align the atom to the required modulus/ align the file offset and the
+  // memory offset seperately this is required so that BSS symbols are handled
+  // properly as the BSS symbols only occupy memory size and not file size
+  uint64_t fOffset = alignOffset(this->fileSize(), atomAlign);
+  uint64_t mOffset = alignOffset(this->memSize(), atomAlign);
+  switch (atomType) {
+  case Atom::definitionRegular:
+    switch(definedAtom->contentType()) {
+    case  DefinedAtom::typeCode:
+    case  DefinedAtom::typeData:
+    case  DefinedAtom::typeConstant:
+      _atoms.push_back(AtomLayout(atom, fOffset, 0));
+      this->_fsize = fOffset + definedAtom->size();
+      this->_msize = mOffset + definedAtom->size();
+      break;
+    case  DefinedAtom::typeZeroFill:
+      _atoms.push_back(AtomLayout(atom, mOffset, 0));
+      this->_msize = mOffset + definedAtom->size();
+      break;
+    default:
+      this->_fsize = fOffset + definedAtom->size();
+      this->_msize = mOffset + definedAtom->size();
+      break;
+    }
+    break;
+  default:
+    llvm_unreachable("Expecting only definedAtoms being passed here");
+    break;
+  }
+  // Set the section alignment to the largest alignment
+  // std::max doesnot support uint64_t
+  if (this->_align2 < align2)
+    this->_align2 = align2;
+}
+
+/// \brief Get the section flags, defined by the permissions of the section
+template<class ELFT>
+int64_t 
+Section<ELFT>::flags() {
+  switch (_contentPermissions) {
+  case DefinedAtom::perm___:
+    return 0;
+
+  case DefinedAtom::permR__:
+      return llvm::ELF::SHF_ALLOC;
+
+  case DefinedAtom::permR_X:
+      return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR;
+
+  case DefinedAtom::permRW_:
+  case DefinedAtom::permRW_L:
+      return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE;
+
+  case DefinedAtom::permRWX:
+      return llvm::ELF::SHF_ALLOC |
+              llvm::ELF::SHF_WRITE |
+              llvm::ELF::SHF_EXECINSTR;
+
+  default:
+      break;
+  }
+  return llvm::ELF::SHF_ALLOC;
+}
+
+/// \brief Return the section type, the returned value is recorded in the
+/// sh_type field of the Section Header
+
+template<class ELFT>
+int 
+Section<ELFT>::type() {
+  switch (_contentType) {
+  case DefinedAtom::typeCode:
+  case DefinedAtom::typeData:
+  case DefinedAtom::typeConstant:
+    return llvm::ELF::SHT_PROGBITS;
+
+  case DefinedAtom::typeZeroFill:
+   return llvm::ELF::SHT_NOBITS;
+
+  // Case to handle section types
+  // Symtab, String Table ...
+  default:
+   return _contentType;
+  }
+}
+
+/// \brief convert the segment type to a String for diagnostics
+///        and printing purposes
+template<class ELFT>
+StringRef 
+Section<ELFT>::segmentKindToStr() const {
+  switch(_segmentType) {
+  case llvm::ELF::PT_INTERP:
+    return "INTERP";
+  case llvm::ELF::PT_LOAD:
+    return "LOAD";
+  case llvm::ELF::PT_GNU_EH_FRAME:
+    return "EH_FRAME";
+  case llvm::ELF::PT_NOTE:
+    return "NOTE";
+  case llvm::ELF::PT_DYNAMIC:
+    return "DYNAMIC";
+  case llvm::ELF::PT_GNU_RELRO:
+    return "RELRO";
+  case llvm::ELF::PT_NULL:
+    return "NULL";
+  default:
+    return "UNKNOWN";
+  }
+}
+
+/// \brief Write the section and the atom contents to the buffer
+template<class ELFT>
+void 
+Section<ELFT>::write(ELFWriter *writer,
+                     llvm::OwningPtr<llvm::FileOutputBuffer> &buffer) {
+  uint8_t *chunkBuffer = buffer->getBufferStart();
+  for (auto &ai : _atoms) {
+    const DefinedAtom *definedAtom = cast<DefinedAtom>(ai._atom);
+    if (definedAtom->contentType() == DefinedAtom::typeZeroFill)
+      continue;
+    // Copy raw content of atom to file buffer.
+    llvm::ArrayRef<uint8_t> content = definedAtom->rawContent();
+    uint64_t contentSize = content.size();
+    if (contentSize == 0)
+      continue;
+    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;
+      // apply the relocation
+      writer->kindHandler()->applyFixup(ref->kind(),
+                                        ref->addend(),
+                                        &atomContent[offset],
+                                        fixupAddress,
+                                        targetAddress);
+    }
+  }
+}
+
+/// \brief A MergedSections represents a set of sections grouped by the same
+/// name. The output file that gets written by the linker has sections grouped
+/// by similiar names
+template<class ELFT>
+class MergedSections {
+public:
+  // Iterators
+  typedef typename std::vector<Chunk<ELFT> *>::iterator ChunkIter;
+
+  MergedSections(llvm::StringRef name);
+
+  // Appends a section into the list of sections that are part of this Merged
+  // Section
+  void appendSection(Chunk<ELFT> *c);
+
+  // Set the MergedSections is associated with a segment
+  inline void setHasSegment() { _hasSegment = true; }
+
+  /// Sets the ordinal
+  inline void setOrdinal(uint64_t ordinal) {
+    _ordinal = ordinal;
+  }
+
+  /// Sets the Memory size
+  inline void setMemSize(uint64_t memsz) {
+    _memSize = memsz;
+  }
+
+  /// Sets the size fo the merged Section
+  inline void setSize(uint64_t fsiz) {
+    _size = fsiz;
+  }
+
+  // The offset of the first section contained in the merged section is
+  // contained here
+  inline void setFileOffset(uint64_t foffset) {
+    _fileOffset = foffset;
+  }
+
+  // Sets the starting address of the section
+  inline void setAddr(uint64_t addr) {
+    _virtualAddr = addr;
+  }
+
+  inline range<ChunkIter> sections() { return _sections; }
+
+  // The below functions returns the properties of the MergeSection
+  inline bool hasSegment() const { return _hasSegment; }
+
+  inline llvm::StringRef name() const { return _name; }
+
+  inline int64_t shinfo() const { return _shInfo; }
+
+  inline uint64_t align2() const { return _align2; }
+
+  inline int64_t link() const { return _link; }
+
+  inline int64_t type() const { return _type; }
+
+  inline uint64_t virtualAddr() const { return _virtualAddr; }
+
+  inline int64_t ordinal() const { return _ordinal; }
+
+  inline int64_t kind() const { return _kind; }
+
+  inline uint64_t fileSize() const { return _size; }
+
+  inline int64_t entsize() const { return _entSize; }
+
+  inline uint64_t fileOffset() const { return _fileOffset; }
+
+  inline int64_t flags() const { return _flags; }
+
+  inline uint64_t memSize() { return _memSize; }
+
+private:
+  llvm::StringRef _name;
+  bool _hasSegment;
+  uint64_t _ordinal;
+  int64_t _flags;
+  uint64_t _size;
+  uint64_t _memSize;
+  uint64_t _fileOffset;
+  uint64_t _virtualAddr;
+  int64_t _shInfo;
+  int64_t _entSize;
+  int64_t _link;
+  uint64_t _align2;
+  int64_t _kind;
+  int64_t _type;
+  std::vector<Chunk<ELFT> *> _sections;
+};
+
+/// MergedSections
+template<class ELFT>
+MergedSections<ELFT>::MergedSections(StringRef name)
+  : _name(name)
+  ,_hasSegment(false)
+  ,_ordinal(0)
+  ,_flags(0)
+  ,_size(0)
+  ,_memSize(0)
+  ,_fileOffset(0)
+  ,_virtualAddr(0)
+  ,_shInfo(0)
+  ,_entSize(0)
+  ,_link(0)
+  ,_align2(0)
+  ,_kind(0)
+  ,_type(0) { }
+  
+
+template<class ELFT>
+void
+MergedSections<ELFT>::appendSection(Chunk<ELFT> *c) {
+  if (c->align2() > _align2)
+    _align2 = c->align2();
+  if (const auto section = dyn_cast<Section<ELFT>>(c)) {
+    _link = section->link();
+    _shInfo = section->shinfo();
+    _entSize = section->entsize();
+    _type = section->type();
+    if (_flags < section->flags())
+      _flags = section->flags();
+  }
+  _kind = c->kind();
+  _sections.push_back(c);
+}
+
+/// \brief The class represents the ELF String Table
+template<class ELFT>
+class ELFStringTable : public Section<ELFT> {
+public:
+  ELFStringTable(const char *str, int32_t order);
+
+  static inline bool classof(const Chunk<ELFT> *c) {
+    return c->kind() == Section<ELFT>::K_StringTable;
+  }
+
+  uint64_t addString(const llvm::StringRef symname);
+
+  void write(ELFWriter *writer,
+             llvm::OwningPtr<llvm::FileOutputBuffer> &buffer);
+
+  inline void finalize() { }
+
+private:
+  std::vector<llvm::StringRef> _strings;
+};
+
+template<class ELFT>
+ELFStringTable<ELFT>::ELFStringTable(const char *str, 
+                                     int32_t order)
+  : Section<ELFT>(
+      str,
+      llvm::ELF::SHT_STRTAB,
+      DefinedAtom::perm___,
+      order,
+      Section<ELFT>::K_StringTable) {
+  // the string table has a NULL entry for which
+  // add an empty string
+  _strings.push_back("");
+  this->_fsize = 1;
+  this->_align2 = 1;
+  this->setOrder(order);
+}
+
+template<class ELFT>
+uint64_t
+ELFStringTable<ELFT>::addString(const StringRef symname) {
+  _strings.push_back(symname);
+  uint64_t offset = this->_fsize;
+  this->_fsize += symname.size() + 1;
+  return offset;
+}
+
+template<class ELFT>
+void
+ELFStringTable<ELFT>::write(ELFWriter *writer,
+           llvm::OwningPtr<llvm::FileOutputBuffer> &buffer) {
+  uint8_t *chunkBuffer = buffer->getBufferStart();
+  uint8_t *dest = chunkBuffer + this->fileOffset();
+  for (auto si : _strings) {
+    memcpy(dest, si.data(), si.size());
+    dest += si.size();
+    memcpy(dest, "", 1);
+    dest += 1;
+  }
+}
+
+/// \brief The ELFSymbolTable class represents the symbol table in a ELF file
+template<class ELFT>
+class ELFSymbolTable : public Section<ELFT> {
+public:
+  typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
+
+  ELFSymbolTable(const char *str, int32_t order);
+
+  void addSymbol(const Atom *atom, int32_t sectionIndex, uint64_t addr = 0);
+
+  void finalize();
+
+  void write(ELFWriter *writer,
+             llvm::OwningPtr<llvm::FileOutputBuffer> &buffer);
+
+  static inline bool classof(const Chunk<ELFT> *c) {
+    return c->kind() == Section<ELFT>::K_SymbolTable;
+  }
+
+  inline void setStringSection(ELFStringTable<ELFT> *s) {
+    _stringSection = s;
+  }
+
+private:
+  ELFStringTable<ELFT> *_stringSection;
+  std::vector<Elf_Sym*> _symbolTable;
+  llvm::BumpPtrAllocator _symbolAllocate;
+  int64_t _link;
+};
+
+/// ELF Symbol Table 
+template<class ELFT>
+ELFSymbolTable<ELFT>::ELFSymbolTable(const char *str, 
+                                     int32_t order)
+  : Section<ELFT>(
+      str,
+      llvm::ELF::SHT_SYMTAB,
+      0,
+      order,
+      Section<ELFT>::K_SymbolTable) {
+  this->setOrder(order);
+  Elf_Sym *symbol = new (_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
+  memset((void *)symbol, 0, sizeof(Elf_Sym));
+  _symbolTable.push_back(symbol);
+  this->_entSize = sizeof(Elf_Sym);
+  this->_fsize = sizeof(Elf_Sym);
+  this->_align2 = sizeof(void *);
+}
+
+template<class ELFT>
+void 
+ELFSymbolTable<ELFT>::addSymbol(const Atom *atom, 
+                                int32_t sectionIndex, 
+                                uint64_t addr) {
+  Elf_Sym *symbol = new(_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
+  unsigned char binding = 0, type = 0;
+  symbol->st_name = _stringSection->addString(atom->name());
+  symbol->st_size = 0;
+  symbol->st_shndx = sectionIndex;
+  symbol->st_value = 0;
+  symbol->st_other = llvm::ELF::STV_DEFAULT;
+  if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom)){
+    symbol->st_size = da->size();
+    lld::DefinedAtom::ContentType ct;
+    switch (ct = da->contentType()){
+    case  DefinedAtom::typeCode:
+      symbol->st_value = addr;
+      type = llvm::ELF::STT_FUNC;
+      break;
+    case  DefinedAtom::typeData:
+    case  DefinedAtom::typeConstant:
+      symbol->st_value = addr;
+      type = llvm::ELF::STT_OBJECT;
+      break;
+    case  DefinedAtom::typeZeroFill:
+      type = llvm::ELF::STT_OBJECT;
+      symbol->st_value = addr;
+      break;
+    default:
+      type = llvm::ELF::STT_NOTYPE;
+    }
+    if (da->scope() == DefinedAtom::scopeTranslationUnit)
+      binding = llvm::ELF::STB_LOCAL;
+    else
+      binding = llvm::ELF::STB_GLOBAL;
+  } else if (const AbsoluteAtom *aa = dyn_cast<const AbsoluteAtom>(atom)){
+    type = llvm::ELF::STT_OBJECT;
+    symbol->st_shndx = llvm::ELF::SHN_ABS;
+    switch (aa->scope()) {
+    case AbsoluteAtom::scopeLinkageUnit:
+      symbol->st_other = llvm::ELF::STV_HIDDEN;
+      binding = llvm::ELF::STB_LOCAL;
+      break;
+    case AbsoluteAtom::scopeTranslationUnit:
+      binding = llvm::ELF::STB_LOCAL;
+      break;
+    case AbsoluteAtom::scopeGlobal:
+      binding = llvm::ELF::STB_GLOBAL;
+      break;
+    }
+    symbol->st_value = addr;
+  } else {
+   symbol->st_value = 0;
+   type = llvm::ELF::STT_NOTYPE;
+   binding = llvm::ELF::STB_WEAK;
+  }
+  symbol->setBindingAndType(binding, type);
+  _symbolTable.push_back(symbol);
+  this->_fsize += sizeof(Elf_Sym);
+}
+
+template<class ELFT>
+void 
+ELFSymbolTable<ELFT>::finalize() {
+  // sh_info should be one greater than last symbol with STB_LOCAL binding
+  // we sort the symbol table to keep all local symbols at the beginning
+  std::stable_sort(_symbolTable.begin(), _symbolTable.end(),
+  [](const Elf_Sym *A, const Elf_Sym *B) {
+     return A->getBinding() < B->getBinding();
+  });
+  uint16_t shInfo = 0;
+  for (auto i : _symbolTable) {
+    if (i->getBinding() != llvm::ELF::STB_LOCAL)
+      break;
+    shInfo++;
+  }
+  this->_shInfo = shInfo;
+  this->setLink(_stringSection->ordinal());
+}
+
+template<class ELFT>
+void 
+ELFSymbolTable<ELFT>::write(ELFWriter *writer,
+           llvm::OwningPtr<llvm::FileOutputBuffer> &buffer) {
+  uint8_t *chunkBuffer = buffer->getBufferStart();
+  uint8_t *dest = chunkBuffer + this->fileOffset();
+  for (auto sti : _symbolTable) {
+    memcpy(dest, sti, sizeof(Elf_Sym));
+    dest += sizeof(Elf_Sym);
+  }
+}
+
+} // elf
+} // lld
+
+#endif //LLD_READER_WRITER_ELF_SECTION_CHUNKS_H_

Added: lld/trunk/lib/ReaderWriter/ELF/ELFSegmentChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFSegmentChunks.h?rev=173082&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFSegmentChunks.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFSegmentChunks.h Mon Jan 21 14:09:55 2013
@@ -0,0 +1,383 @@
+//===- lib/ReaderWriter/ELF/ELFSegmentChunks.h -----------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_ELF_SEGMENT_CHUNKS_H_
+#define LLD_READER_WRITER_ELF_SEGMENT_CHUNKS_H_
+
+#include "lld/Core/range.h"
+#include "lld/ReaderWriter/WriterELF.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
+
+#include "llvm/Object/ELF.h"
+
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ELF.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileOutputBuffer.h"
+
+#include "ELFChunk.h"
+#include "ELFLayout.h"
+#include "ELFSectionChunks.h"
+#include "ELFWriter.h"
+
+/// \brief A segment can be divided into segment slices
+///        depending on how the segments can be split
+namespace lld {
+namespace elf {
+
+template<class ELFT>
+class SegmentSlice {
+public:
+  typedef typename std::vector<Chunk<ELFT> *>::iterator SectionIter;
+
+  SegmentSlice() { }
+
+  /// Set the segment slice so that it begins at the offset specified
+  /// by file offset and set the start of the slice to be s and the end
+  /// of the slice to be e
+  void set(uint64_t fileoffset, int32_t s, int e) {
+    _startSection = s;
+    _endSection = e + 1;
+    _offset = fileoffset;
+  }
+
+  // Set the segment slice start and end iterators. This is used to walk through
+  // the sections that are part of the Segment slice
+  inline void setSections(range<SectionIter> sections) {
+    _sections = sections;
+  }
+
+  // Return the fileOffset of the slice
+  inline uint64_t fileOffset() const { return _offset; }
+
+  // Return the size of the slice
+  inline uint64_t fileSize() const { return _size; }
+
+  // Return the start of the slice
+  inline int32_t startSection() const { return _startSection; }
+
+  // Return the start address of the slice
+  inline uint64_t virtualAddr() const { return _addr; }
+
+  // Return the memory size of the slice
+  inline uint64_t memSize() const { return _memSize; }
+
+  // Return the alignment of the slice
+  inline uint64_t align2() const { return _align2; }
+
+  inline void setSize(uint64_t sz) { _size = sz; }
+
+  inline void setMemSize(uint64_t memsz) { _memSize = memsz; }
+
+  inline void setVAddr(uint64_t addr) { _addr = addr; }
+
+  inline void setAlign(uint64_t align) { _align2 = align; }
+
+  static bool compare_slices(SegmentSlice<ELFT> *a, SegmentSlice<ELFT> *b) {
+    return a->startSection() < b->startSection();
+  }
+
+  inline range<SectionIter> sections() {
+    return _sections;
+  }
+
+private:
+  int32_t _startSection;
+  int32_t _endSection;
+  range<SectionIter> _sections;
+  uint64_t _addr;
+  uint64_t _offset;
+  uint64_t _size;
+  uint64_t _align2;
+  uint64_t _memSize;
+};
+
+/// \brief A segment contains a set of sections, that have similiar properties
+//  the sections are already seperated based on different flags and properties
+//  the segment is just a way to concatenate sections to segments
+template<class ELFT>
+class Segment : public Chunk<ELFT> {
+public:
+  typedef typename std::vector<SegmentSlice<ELFT> *>::iterator SliceIter;
+  typedef typename std::vector<Chunk<ELFT> *>::iterator SectionIter;
+
+  Segment(const StringRef name,
+          const ELFLayout::SegmentType type,
+          const WriterOptionsELF &options);
+
+  /// append a section to a segment
+  void append(Section<ELFT> *section);
+
+  /// Sort segments depending on the property
+  /// If we have a Program Header segment, it should appear first
+  /// If we have a INTERP segment, that should appear after the Program Header
+  /// All Loadable segments appear next in this order
+  /// All Read Write Execute segments follow
+  /// All Read Execute segments appear next
+  /// All Read only segments appear first
+  /// All Write execute segments follow
+  static bool compareSegments(Segment<ELFT> *sega, Segment<ELFT> *segb);
+
+  /// \brief Start assigning file offset to the segment chunks The fileoffset
+  /// needs to be page at the start of the segment and in addition the
+  /// fileoffset needs to be aligned to the max section alignment within the
+  /// segment. This is required so that the ELF property p_poffset % p_align =
+  /// p_vaddr mod p_align holds true.
+  /// The algorithm starts off by assigning the startOffset thats passed in as
+  /// parameter to the first section in the segment, if the difference between
+  /// the newly computed offset is greater than a page, then we create a segment
+  /// slice, as it would be a waste of virtual memory just to be filled with
+  /// zeroes
+  void assignOffsets(uint64_t startOffset);
+
+  /// \brief Assign virtual addresses to the slices
+  void assignVirtualAddress(uint64_t &addr);
+
+  // Write the Segment
+  void write(ELFWriter *writer, OwningPtr<llvm::FileOutputBuffer> &buffer);
+
+  int64_t flags() const;
+
+  /// Prepend a generic chunk to the segment.
+  void prepend(Chunk<ELFT> *c) {
+    _sections.insert(_sections.begin(), c);
+  }
+
+  // Finalize the segment, before we want to write to the output file
+  inline void finalize() { }
+
+  // For LLVM RTTI
+  static inline bool classof(const Chunk<ELFT> *c) {
+    return c->kind() == Chunk<ELFT>::K_ELFSegment;
+  }
+
+  // Getters
+  inline int32_t sectionCount() const {
+    return _sections.size();
+  }
+
+  inline ELFLayout::SegmentType segmentType() { return _segmentType; }
+
+  inline int pageSize() const { return _options.pageSize(); }
+
+  inline int64_t atomflags() const { return _atomflags; }
+
+  inline int64_t numSlices() const {
+    return _segmentSlices.size();
+  }
+
+  inline range<SliceIter> slices() { return _segmentSlices; }
+
+  // These two accessors are still needed for a call to std::stable_sort.
+  // Consider adding wrappers for two iterator algorithms.
+  inline SliceIter slices_begin() {
+    return _segmentSlices.begin();
+  }
+
+  inline SliceIter slices_end() {
+    return _segmentSlices.end();
+  }
+
+protected:
+  /// \brief Section or some other chunk type.
+  std::vector<Chunk<ELFT> *> _sections;
+  std::vector<SegmentSlice<ELFT> *> _segmentSlices;
+  ELFLayout::SegmentType _segmentType;
+  int64_t _flags;
+  int64_t _atomflags;
+  const WriterOptionsELF _options;
+  llvm::BumpPtrAllocator _segmentAllocate;
+};
+
+template<class ELFT>
+Segment<ELFT>::Segment(const StringRef name,
+                       const ELFLayout::SegmentType type,
+                       const WriterOptionsELF &options)
+  : Chunk<ELFT>(name, Chunk<ELFT>::K_ELFSegment)
+  , _segmentType(type)
+  , _flags(0)
+  , _atomflags(0)
+  , _options(options) {
+  this->_align2 = 0;
+  this->_fsize = 0;
+}
+
+template<class ELFT>
+void 
+Segment<ELFT>::append(Section<ELFT> *section) {
+  _sections.push_back(section);
+  if (_flags < section->flags())
+    _flags = section->flags();
+  if (_atomflags < section->atomflags())
+    _atomflags = section->atomflags();
+  if (this->_align2 < section->align2())
+    this->_align2 = section->align2();
+}
+
+template<class ELFT>
+bool 
+Segment<ELFT>::compareSegments(Segment<ELFT> *sega, Segment<ELFT> *segb) {
+  if (sega->atomflags() < segb->atomflags())
+    return false;
+  return true;
+}
+
+template<class ELFT>
+void 
+Segment<ELFT>::assignOffsets(uint64_t startOffset) {
+  int startSection = 0;
+  int currSection = 0;
+  SectionIter startSectionIter, endSectionIter;
+  // slice align is set to the max alignment of the chunks that are
+  // contained in the slice
+  uint64_t sliceAlign = 0;
+  // Current slice size
+  uint64_t curSliceSize = 0;
+  // Current Slice File Offset
+  uint64_t curSliceFileOffset = 0;
+
+  startSectionIter = _sections.begin();
+  endSectionIter = _sections.end();
+  startSection = 0;
+  bool isFirstSection = true;
+  for (auto si = _sections.begin(); si != _sections.end(); ++si) {
+    if (isFirstSection) {
+      // align the startOffset to the section alignment
+      uint64_t newOffset =
+        llvm::RoundUpToAlignment(startOffset, (*si)->align2());
+      curSliceFileOffset = newOffset;
+      sliceAlign = (*si)->align2();
+      this->setFileOffset(startOffset);
+      (*si)->setFileOffset(newOffset);
+      curSliceSize = (*si)->fileSize();
+      isFirstSection = false;
+    } else {
+      uint64_t curOffset = curSliceFileOffset + curSliceSize;
+      uint64_t newOffset =
+        llvm::RoundUpToAlignment(curOffset, (*si)->align2());
+      SegmentSlice<ELFT> *slice = nullptr;
+      // If the newOffset computed is more than a page away, lets create
+      // a seperate segment, so that memory is not used up while running
+      if ((newOffset - curOffset) > _options.pageSize()) {
+        // TODO: use std::find here
+        for (auto s : slices()) {
+          if (s->startSection() == startSection) {
+            slice = s;
+            break;
+          }
+        }
+        if (!slice) {
+          slice = new (_segmentAllocate.Allocate<SegmentSlice<ELFT>>())
+            SegmentSlice<ELFT>();
+          _segmentSlices.push_back(slice);
+        }
+        slice->set(curSliceFileOffset, startSection, currSection);
+        slice->setSections(make_range(startSectionIter, endSectionIter));
+        slice->setSize(curSliceSize);
+        slice->setAlign(sliceAlign);
+        uint64_t newPageOffset =
+          llvm::RoundUpToAlignment(curOffset, _options.pageSize());
+        newOffset = llvm::RoundUpToAlignment(newPageOffset, (*si)->align2());
+        curSliceFileOffset = newOffset;
+        startSectionIter = endSectionIter;
+        startSection = currSection;
+        (*si)->setFileOffset(curSliceFileOffset);
+        curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
+        sliceAlign = (*si)->align2();
+      } else {
+        if (sliceAlign < (*si)->align2())
+          sliceAlign = (*si)->align2();
+        (*si)->setFileOffset(newOffset);
+        curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
+      }
+    }
+    currSection++;
+    endSectionIter = si;
+  }
+  SegmentSlice<ELFT> *slice = nullptr;
+  for (auto s : slices()) {
+    // TODO: add std::find
+    if (s->startSection() == startSection) {
+      slice = s;
+      break;
+    }
+  }
+  if (!slice) {
+    slice = new (_segmentAllocate.Allocate<SegmentSlice<ELFT>>())
+      SegmentSlice<ELFT>();
+    _segmentSlices.push_back(slice);
+  }
+  slice->set(curSliceFileOffset, startSection, currSection);
+  slice->setSections(make_range(startSectionIter, _sections.end()));
+  slice->setSize(curSliceSize);
+  slice->setAlign(sliceAlign);
+  this->_fsize = curSliceFileOffset - startOffset + curSliceSize;
+  std::stable_sort(slices_begin(), slices_end(),
+                   SegmentSlice<ELFT>::compare_slices);
+}
+
+/// \brief Assign virtual addresses to the slices
+template<class ELFT>
+void 
+Segment<ELFT>::assignVirtualAddress(uint64_t &addr) {
+  for (auto slice : slices()) {
+    // Align to a page
+    addr = llvm::RoundUpToAlignment(addr, _options.pageSize());
+    // Align to the slice alignment
+    addr = llvm::RoundUpToAlignment(addr, slice->align2());
+
+    bool virtualAddressSet = false;
+    for (auto section : slice->sections()) {
+      // Align the section address
+      addr = llvm::RoundUpToAlignment(addr, section->align2());
+      if (!virtualAddressSet) {
+        slice->setVAddr(addr);
+        virtualAddressSet = true;
+      }
+      section->setVAddr(addr);
+      if (auto s = dyn_cast<Section<ELFT>>(section))
+        s->assignVirtualAddress(addr);
+      else
+        addr += section->memSize();
+      section->setMemSize(addr - section->virtualAddr());
+    }
+    slice->setMemSize(addr - slice->virtualAddr());
+  }
+}
+
+// Write the Segment
+template<class ELFT>
+void 
+Segment<ELFT>::write(ELFWriter *writer, OwningPtr<llvm::FileOutputBuffer> &buffer) {
+  for (auto slice : slices())
+    for (auto section : slice->sections())
+      section->write(writer, buffer);
+}
+
+template<class ELFT>
+int64_t 
+Segment<ELFT>::flags() const {
+  int64_t fl = 0;
+  if (_flags & llvm::ELF::SHF_ALLOC)
+    fl |= llvm::ELF::PF_R;
+  if (_flags & llvm::ELF::SHF_WRITE)
+    fl |= llvm::ELF::PF_W;
+  if (_flags & llvm::ELF::SHF_EXECINSTR)
+    fl |= llvm::ELF::PF_X;
+  return fl;
+}
+
+} // elf
+} // lld
+
+#endif // LLD_READER_WRITER_ELF_SEGMENT_CHUNKS_H_

Added: lld/trunk/lib/ReaderWriter/ELF/ELFWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFWriter.h?rev=173082&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFWriter.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFWriter.h Mon Jan 21 14:09:55 2013
@@ -0,0 +1,44 @@
+//===- lib/ReaderWriter/ELF/ELFWriter.h ---------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_ELF_WRITER_H_
+#define LLD_READER_WRITER_ELF_WRITER_H_
+
+#include "lld/Core/File.h"
+#include "lld/Core/InputFiles.h"
+#include "lld/ReaderWriter/WriterELF.h"
+#include "ReferenceKinds.h"
+
+namespace lld {
+namespace elf {
+/// \brief The ELFWriter class is a base class for the linker to write
+///        various kinds of ELF files.
+class ELFWriter : public Writer {
+public:
+  ELFWriter() { }
+
+public:
+  /// \brief builds the chunks that needs to be written to the output
+  ///        ELF file
+  virtual void buildChunks(const lld::File &file) = 0;
+
+  /// \brief Writes the chunks into the output file specified by path
+  virtual error_code writeFile(const lld::File &File, StringRef path) = 0;
+
+  /// \brief Get the virtual address of \p atom after layout.
+  virtual uint64_t addressOfAtom(const Atom *atom) = 0;
+
+  /// \brief Return the processing function to apply Relocations
+  virtual KindHandler *kindHandler()  = 0;
+};
+
+} // elf
+} // lld
+
+#endif // LLD_READER_WRITER_ELF_WRITER_H_

Modified: lld/trunk/lib/ReaderWriter/ELF/WriterELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/WriterELF.cpp?rev=173082&r1=173081&r2=173082&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/WriterELF.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/WriterELF.cpp Mon Jan 21 14:09:55 2013
@@ -7,41 +7,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "lld/ReaderWriter/WriterELF.h"
-#include "ReferenceKinds.h"
-
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/InputFiles.h"
-#include "lld/Core/range.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/SharedLibraryAtom.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/system_error.h"
+#include "DefaultELFLayout.h"
 #include "ExecutableAtoms.h"
 
-#include <map>
-#include <unordered_map>
-#include <tuple>
-#include <vector>
-
 using namespace llvm;
 using namespace llvm::object;
 namespace lld {
@@ -49,1855 +17,6 @@
 template<class ELFT>
 class ELFExecutableWriter;
 
-/// \brief The ELFWriter class is a base class for the linker to write
-///        various kinds of ELF files.
-class ELFWriter : public Writer {
-public:
-  ELFWriter() { }
-
-public:
-  /// \brief builds the chunks that needs to be written to the output
-  ///        ELF file
-  virtual void buildChunks(const lld::File &file) = 0;
-
-  /// \brief Writes the chunks into the output file specified by path
-  virtual error_code writeFile(const lld::File &File, StringRef path) = 0;
-
-  /// \brief Get the virtual address of \p atom after layout.
-  virtual uint64_t addressOfAtom(const Atom *atom) = 0;
-
-  /// \brief Return the processing function to apply Relocations
-  virtual KindHandler *kindHandler()  = 0;
-};
-
-/// \brief A chunk is a contiguous region of space
-template<class ELFT>
-class Chunk {
-public:
-
-  /// \brief Describes the type of Chunk
-  enum Kind {
-    K_ELFHeader, // ELF Header
-    K_ELFProgramHeader, // Program Header
-    K_ELFSegment, // Segment
-    K_ELFSection, // Section
-    K_ELFSectionHeader // Section header
-  };
-  Chunk(StringRef name, Kind kind)
-    : _name(name)
-    , _kind(kind)
-    , _fsize(0)
-    , _msize(0)
-    , _align2(0)
-    , _order(0)
-    , _ordinal(1)
-    , _start(0)
-    , _fileoffset(0) {}
-  virtual             ~Chunk() {}
-  // Does the chunk occupy disk space
-  virtual bool        occupiesNoDiskSpace() const {
-    return false;
-  }
-  // The name of the chunk
-  StringRef name() const { return _name; }
-  // Kind of chunk
-  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;}
-  void               setOrdinal(uint64_t newVal) { _ordinal = newVal;}
-  // The order in which the chunk would appear in the output file
-  uint64_t            order() const { return _order; }
-  void               setOrder(uint32_t order) { _order = order; }
-  // Output file offset of the chunk
-  uint64_t            fileOffset() const { return _fileoffset; }
-  void               setFileOffset(uint64_t offset) { _fileoffset = offset; }
-  // Output start address of the chunk
-  void               setVAddr(uint64_t start) { _start = start; }
-  uint64_t            virtualAddr() const { return _start; }
-  // Does the chunk occupy memory during execution ?
-  uint64_t            memSize() const { return _msize; }
-  void               setMemSize(uint64_t msize) { _msize = msize; }
-  // Writer the chunk
-  virtual void       write(ELFWriter *writer,
-                           OwningPtr<FileOutputBuffer> &buffer) = 0;
-  // Finalize the chunk before writing
-  virtual void       finalize() = 0;
-
-protected:
-  StringRef _name;
-  Kind _kind;
-  uint64_t _fsize;
-  uint64_t _msize;
-  uint64_t _align2;
-  uint32_t  _order;
-  uint64_t _ordinal;
-  uint64_t _start;
-  uint64_t _fileoffset;
-};
-
-/// \brief The ELFLayoutOptions encapsulates the options used by all Layouts
-///        Examples of the ELFLayoutOptions would be a script that would be used
-///        to drive the layout
-class ELFLayoutOptions {
-public:
-  ELFLayoutOptions() { }
-
-  ELFLayoutOptions(StringRef &linker_script) : _script(linker_script)
-  {}
-
-  /// parse the linker script
-  error_code parseLinkerScript();
-
-  /// Is the current section present in the linker script
-  bool isSectionPresent();
-
-private:
-  StringRef _script;
-};
-
-/// \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 ELFLayout for generating each binary thats
-//         needed by the lld linker
-class ELFLayout {
-public:
-  typedef uint32_t SectionOrder;
-  typedef uint32_t SegmentType;
-  typedef uint32_t Flags;
-
-public:
-  /// Return the order the section would appear in the output file
-  virtual SectionOrder getSectionOrder
-                        (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;
-  /// find the Atom Address in the current layout
-  virtual bool findAtomAddrByName(const StringRef name, uint64_t &addr) = 0;
-  /// associates a section to a segment
-  virtual void assignSectionsToSegments() = 0;
-  /// associates a virtual address to the segment, section, and the atom
-  virtual void assignVirtualAddress() = 0;
-  /// associates a file offset to the segment, section and the atom
-  virtual void assignFileOffsets() = 0;
-
-public:
-  ELFLayout() {}
-  ELFLayout(WriterOptionsELF &writerOptions,
-            ELFLayoutOptions &layoutOptions)
-    : _writerOptions(writerOptions)
-    , _layoutOptions(layoutOptions) {}
-  virtual ~ELFLayout() { }
-
-private:
-  WriterOptionsELF _writerOptions;
-  ELFLayoutOptions _layoutOptions;
-};
-
-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 A section contains a set of atoms that have similiar properties
-///        The atoms that have similiar properties are merged to form a section
-template<class ELFT>
-class Section : public Chunk<ELFT> {
-public:
-  // The Kind of section that the object represents
-  enum SectionKind {
-    K_Default,
-    K_SymbolTable,
-    K_StringTable,
-  };
-  // Create a section object, the section is set to the default type if the
-  // caller doesnot set it
-  Section(const StringRef sectionName,
-          const int32_t contentType,
-          const int32_t contentPermissions,
-          const int32_t order,
-          const SectionKind kind = K_Default)
-    : Chunk<ELFT>(sectionName, Chunk<ELFT>::K_ELFSection)
-    , _contentType(contentType)
-    , _contentPermissions(contentPermissions)
-    , _sectionKind(kind)
-    , _entSize(0)
-    , _shInfo(0)
-    , _link(0) {
-    this->setOrder(order);
-  }
-
-  /// return the section kind
-  SectionKind sectionKind() const {
-    return _sectionKind;
-  }
-
-  /// Align the offset to the required modulus defined by the atom alignment
-  uint64_t alignOffset(uint64_t offset, DefinedAtom::Alignment &atomAlign) {
-    uint64_t requiredModulus = atomAlign.modulus;
-    uint64_t align2 = 1u << atomAlign.powerOf2;
-    uint64_t currentModulus = (offset % align2);
-    uint64_t retOffset = offset;
-    if (currentModulus != requiredModulus) {
-      if (requiredModulus > currentModulus)
-        retOffset += requiredModulus - currentModulus;
-      else
-        retOffset += align2 + requiredModulus - currentModulus;
-    }
-    return retOffset;
-  }
-
-  // \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) {
-    Atom::Definition atomType = atom->definition();
-    const DefinedAtom *definedAtom = cast<DefinedAtom>(atom);
-
-    DefinedAtom::Alignment atomAlign = definedAtom->alignment();
-    uint64_t align2 = 1u << atomAlign.powerOf2;
-    // Align the atom to the required modulus/ align the file offset and the
-    // memory offset seperately this is required so that BSS symbols are handled
-    // properly as the BSS symbols only occupy memory size and not file size
-    uint64_t fOffset = alignOffset(this->fileSize(), atomAlign);
-    uint64_t mOffset = alignOffset(this->memSize(), atomAlign);
-    switch (atomType) {
-    case Atom::definitionRegular:
-      switch(definedAtom->contentType()) {
-      case  DefinedAtom::typeCode:
-      case  DefinedAtom::typeData:
-      case  DefinedAtom::typeConstant:
-        _atoms.push_back(AtomLayout(atom, fOffset, 0));
-        this->_fsize = fOffset + definedAtom->size();
-        this->_msize = mOffset + definedAtom->size();
-        break;
-      case  DefinedAtom::typeZeroFill:
-        _atoms.push_back(AtomLayout(atom, mOffset, 0));
-        this->_msize = mOffset + definedAtom->size();
-        break;
-      default:
-        this->_fsize = fOffset + definedAtom->size();
-        this->_msize = mOffset + definedAtom->size();
-        break;
-      }
-      break;
-    default:
-      llvm_unreachable("Expecting only definedAtoms being passed here");
-      break;
-    }
-    // Set the section alignment to the largest alignment
-    // std::max doesnot support uint64_t
-    if (this->_align2 < align2)
-      this->_align2 = align2;
-  }
-
-  /// \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
-  void assignVirtualAddress(uint64_t &addr) {
-    for (auto &ai : _atoms) {
-      ai._virtualAddr = addr + ai._fileOffset;
-    }
-    addr += this->memSize();
-  }
-
-  /// \brief Set the file offset of each Atom in the section. This routine
-  /// gets called after the linker fixes up the section offset
-  void assignOffsets(uint64_t offset) {
-    for (auto &ai : _atoms) {
-      ai._fileOffset = offset + ai._fileOffset;
-    }
-  }
-
-  /// \brief Find the Atom address given a name, this is needed to to properly
-  ///  apply relocation. The section class calls this to find the atom address
-  ///  to fix the relocation
-  bool findAtomAddrByName(const StringRef name, uint64_t &addr) {
-    for (auto ai : _atoms) {
-      if (ai._atom->name() == name) {
-        addr = ai._virtualAddr;
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /// \brief Does the Atom occupy any disk space
-  bool occupiesNoDiskSpace() const {
-    return _contentType == DefinedAtom::typeZeroFill;
-  }
-
-  /// \brief The permission of the section is the most permissive permission
-  /// of all atoms that the section contains
-  void setContentPermissions(int32_t perm) {
-    _contentPermissions = std::max(perm, _contentPermissions);
-  }
-
-  /// \brief Get the section flags, defined by the permissions of the section
-  int64_t flags() {
-    switch (_contentPermissions) {
-    case DefinedAtom::perm___:
-      return 0;
-
-    case DefinedAtom::permR__:
-        return llvm::ELF::SHF_ALLOC;
-
-    case DefinedAtom::permR_X:
-        return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR;
-
-    case DefinedAtom::permRW_:
-    case DefinedAtom::permRW_L:
-        return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE;
-
-    case DefinedAtom::permRWX:
-        return llvm::ELF::SHF_ALLOC |
-                llvm::ELF::SHF_WRITE |
-                llvm::ELF::SHF_EXECINSTR;
-
-    default:
-        break;
-    }
-    return llvm::ELF::SHF_ALLOC;
-  }
-
-  /// \brief Return the raw flags, we need this to sort segments
-  int64_t atomflags() const {
-    return _contentPermissions;
-  }
-
-  /// \brief Return the section type, the returned value is recorded in the
-  /// sh_type field of the Section Header
-  int type() {
-    switch (_contentType) {
-    case DefinedAtom::typeCode:
-    case DefinedAtom::typeData:
-    case DefinedAtom::typeConstant:
-      return llvm::ELF::SHT_PROGBITS;
-
-    case DefinedAtom::typeZeroFill:
-     return llvm::ELF::SHT_NOBITS;
-
-    // Case to handle section types
-    // Symtab, String Table ...
-    default:
-     return _contentType;
-    }
-  }
-
-  /// \brief Returns the section link field, the returned value is
-  ///        recorded in the sh_link field of the Section Header
-  int link() const {
-    return _link;
-  }
-
-  void setLink(int32_t link) {
-    _link = link;
-  }
-
-  /// \brief Returns the section entsize field, the returned value is
-  ///        recorded in the sh_entsize field of the Section Header
-  int entsize() const {
-    return _entSize;
-  }
-
-  /// \brief Returns the shinfo field, the returned value is
-  ///        recorded in the sh_info field of the Section Header
-  int shinfo() const {
-    return _shInfo;
-  }
-
-  /// \brief Records the segmentType, that this section belongs to
-  void setSegment(const ELFLayout::SegmentType segmentType) {
-    _segmentType = segmentType;
-  }
-
-  /// \brief convert the segment type to a String for diagnostics
-  ///        and printing purposes
-  StringRef segmentKindToStr() const {
-    switch(_segmentType) {
-    case llvm::ELF::PT_INTERP:
-      return "INTERP";
-    case llvm::ELF::PT_LOAD:
-      return "LOAD";
-    case llvm::ELF::PT_GNU_EH_FRAME:
-      return "EH_FRAME";
-    case llvm::ELF::PT_NOTE:
-      return "NOTE";
-    case llvm::ELF::PT_DYNAMIC:
-      return "DYNAMIC";
-    case llvm::ELF::PT_GNU_RELRO:
-      return "RELRO";
-    case llvm::ELF::PT_NULL:
-      return "NULL";
-    default:
-      return "UNKNOWN";
-    }
-  }
-
-  /// \brief for LLVM style RTTI information
-  static inline bool classof(const Chunk<ELFT> *c) {
-    return c->kind() == Chunk<ELFT>::K_ELFSection;
-  }
-
-  /// \brief Finalize the section contents before writing
-  void finalize() { }
-
-  /// \brief Write the section and the atom contents to the buffer
-  void write(ELFWriter *writer,
-             OwningPtr<FileOutputBuffer> &buffer) {
-    uint8_t *chunkBuffer = buffer->getBufferStart();
-    for (auto &ai : _atoms) {
-      const DefinedAtom *definedAtom = cast<DefinedAtom>(ai._atom);
-      if (definedAtom->contentType() == DefinedAtom::typeZeroFill)
-        continue;
-      // Copy raw content of atom to file buffer.
-      ArrayRef<uint8_t> content = definedAtom->rawContent();
-      uint64_t contentSize = content.size();
-      if (contentSize == 0)
-        continue;
-      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;
-        // apply the relocation
-        writer->kindHandler()->applyFixup(ref->kind(),
-                                          ref->addend(),
-                                          &atomContent[offset],
-                                          fixupAddress,
-                                          targetAddress);
-      }
-    }
-  }
-
-  /// Atom Iterators
-  typedef typename std::vector<AtomLayout>::iterator atom_iter;
-
-  range<atom_iter> atoms() { return _atoms; }
-
-protected:
-  int32_t _contentType;
-  int32_t _contentPermissions;
-  SectionKind _sectionKind;
-  std::vector<AtomLayout> _atoms;
-  ELFLayout::SegmentType _segmentType;
-  int64_t _entSize;
-  int64_t _shInfo;
-  int64_t _link;
-};
-
-/// \brief A MergedSections represents a set of sections grouped by the same
-/// name. The output file that gets written by the linker has sections grouped
-/// by similiar names
-template<class ELFT>
-class MergedSections {
-public:
-  MergedSections(StringRef name)
-    : _name(name)
-    ,_hasSegment(false)
-    ,_ordinal(0)
-    ,_flags(0)
-    ,_size(0)
-    ,_memSize(0)
-    ,_fileOffset(0)
-    ,_virtualAddr(0)
-    ,_shInfo(0)
-    ,_entSize(0)
-    ,_link(0)
-    ,_align2(0)
-    ,_kind(0)
-    ,_type(0) { }
-
-  // Set the MergedSections is associated with a segment
-  void setHasSegment() { _hasSegment = true; }
-
-  /// Sets the ordinal
-  void setOrdinal(uint64_t ordinal) {
-    _ordinal = ordinal;
-  }
-
-  /// Sets the Memory size
-  void setMemSize(uint64_t memsz) {
-    _memSize = memsz;
-  }
-
-  /// Sets the size fo the merged Section
-  void setSize(uint64_t fsiz) {
-    _size = fsiz;
-  }
-
-  // The offset of the first section contained in the merged section is
-  // contained here
-  void setFileOffset(uint64_t foffset) {
-    _fileOffset = foffset;
-  }
-
-  // Sets the starting address of the section
-  void setAddr(uint64_t addr) {
-    _virtualAddr = addr;
-  }
-
-  // Appends a section into the list of sections that are part of this Merged
-  // Section
-  void appendSection(Chunk<ELFT> *c) {
-    if (c->align2() > _align2)
-      _align2 = c->align2();
-    if (const auto section = dyn_cast<Section<ELFT>>(c)) {
-      _link = section->link();
-      _shInfo = section->shinfo();
-      _entSize = section->entsize();
-      _type = section->type();
-      if (_flags < section->flags())
-        _flags = section->flags();
-    }
-    _kind = c->kind();
-    _sections.push_back(c);
-  }
-
-  // Iterators
-  typedef typename std::vector<Chunk<ELFT> *>::iterator ChunkIter;
-
-  range<ChunkIter> sections() { return _sections; }
-
-  // The below functions returns the properties of the MergeSection
-  bool hasSegment() const { return _hasSegment; }
-
-  StringRef name() const { return _name; }
-
-  int64_t shinfo() const { return _shInfo; }
-
-  uint64_t align2() const { return _align2; }
-
-  int64_t link() const { return _link; }
-
-  int64_t type() const { return _type; }
-
-  uint64_t virtualAddr() const { return _virtualAddr; }
-
-  int64_t ordinal() const { return _ordinal; }
-
-  int64_t kind() const { return _kind; }
-
-  uint64_t fileSize() const { return _size; }
-
-  int64_t entsize() const { return _entSize; }
-
-  uint64_t fileOffset() const { return _fileOffset; }
-
-  int64_t flags() const { return _flags; }
-
-  uint64_t memSize() { return _memSize; }
-
-private:
-  StringRef _name;
-  bool _hasSegment;
-  uint64_t _ordinal;
-  int64_t _flags;
-  uint64_t _size;
-  uint64_t _memSize;
-  uint64_t _fileOffset;
-  uint64_t _virtualAddr;
-  int64_t _shInfo;
-  int64_t _entSize;
-  int64_t _link;
-  uint64_t _align2;
-  int64_t _kind;
-  int64_t _type;
-  std::vector<Chunk<ELFT> *> _sections;
-};
-
-/// \brief A segment can be divided into segment slices
-///        depending on how the segments can be split
-template<class ELFT>
-class SegmentSlice {
-public:
-  typedef typename std::vector<Chunk<ELFT> *>::iterator SectionIter;
-
-  SegmentSlice() { }
-
-  /// Set the segment slice so that it begins at the offset specified
-  /// by file offset and set the start of the slice to be s and the end
-  /// of the slice to be e
-  void set(uint64_t fileoffset, int32_t s, int e) {
-    _startSection = s;
-    _endSection = e + 1;
-    _offset = fileoffset;
-  }
-
-  // Set the segment slice start and end iterators. This is used to walk through
-  // the sections that are part of the Segment slice
-  void setSections(range<SectionIter> sections) {
-    _sections = sections;
-  }
-
-  // Return the fileOffset of the slice
-  uint64_t fileOffset() const { return _offset; }
-
-  // Return the size of the slice
-  uint64_t fileSize() const { return _size; }
-
-  // Return the start of the slice
-  int32_t startSection() const { return _startSection; }
-
-  // Return the start address of the slice
-  uint64_t virtualAddr() const { return _addr; }
-
-  // Return the memory size of the slice
-  uint64_t memSize() const { return _memSize; }
-
-  // Return the alignment of the slice
-  uint64_t align2() const { return _align2; }
-
-  void setSize(uint64_t sz) { _size = sz; }
-
-  void setMemSize(uint64_t memsz) { _memSize = memsz; }
-
-  void setVAddr(uint64_t addr) { _addr = addr; }
-
-  void setAlign(uint64_t align) { _align2 = align; }
-
-  static bool compare_slices(SegmentSlice<ELFT> *a, SegmentSlice<ELFT> *b) {
-    return a->startSection() < b->startSection();
-  }
-
-  range<SectionIter> sections() {
-    return _sections;
-  }
-
-private:
-  int32_t _startSection;
-  int32_t _endSection;
-  range<SectionIter> _sections;
-  uint64_t _addr;
-  uint64_t _offset;
-  uint64_t _size;
-  uint64_t _align2;
-  uint64_t _memSize;
-};
-
-/// \brief A segment contains a set of sections, that have similiar properties
-//  the sections are already seperated based on different flags and properties
-//  the segment is just a way to concatenate sections to segments
-template<class ELFT>
-class Segment : public Chunk<ELFT> {
-public:
-  typedef typename std::vector<SegmentSlice<ELFT> *>::iterator SliceIter;
-  typedef typename std::vector<Chunk<ELFT> *>::iterator SectionIter;
-
-  Segment(const StringRef name,
-          const ELFLayout::SegmentType type,
-          const WriterOptionsELF &options)
-    : Chunk<ELFT>(name, Chunk<ELFT>::K_ELFSegment)
-    , _segmentType(type)
-    , _flags(0)
-    , _atomflags(0)
-    , _options(options) {
-    this->_align2 = 0;
-    this->_fsize = 0;
-  }
-
-  /// append a section to a segment
-  void append(Section<ELFT> *section) {
-    _sections.push_back(section);
-    if (_flags < section->flags())
-      _flags = section->flags();
-    if (_atomflags < section->atomflags())
-      _atomflags = section->atomflags();
-    if (this->_align2 < section->align2())
-      this->_align2 = section->align2();
-  }
-
-  /// Prepend a generic chunk to the segment.
-  void prepend(Chunk<ELFT> *c) {
-    _sections.insert(_sections.begin(), c);
-  }
-
-  /// Sort segments depending on the property
-  /// If we have a Program Header segment, it should appear first
-  /// If we have a INTERP segment, that should appear after the Program Header
-  /// All Loadable segments appear next in this order
-  /// All Read Write Execute segments follow
-  /// All Read Execute segments appear next
-  /// All Read only segments appear first
-  /// All Write execute segments follow
-  static bool compareSegments(Segment<ELFT> *sega, Segment<ELFT> *segb) {
-    if (sega->atomflags() < segb->atomflags())
-      return false;
-    return true;
-  }
-
-  /// \brief Start assigning file offset to the segment chunks The fileoffset
-  /// needs to be page at the start of the segment and in addition the
-  /// fileoffset needs to be aligned to the max section alignment within the
-  /// segment. This is required so that the ELF property p_poffset % p_align =
-  /// p_vaddr mod p_align holds true.
-  /// The algorithm starts off by assigning the startOffset thats passed in as
-  /// parameter to the first section in the segment, if the difference between
-  /// the newly computed offset is greater than a page, then we create a segment
-  /// slice, as it would be a waste of virtual memory just to be filled with
-  /// zeroes
-  void assignOffsets(uint64_t startOffset) {
-    int startSection = 0;
-    int currSection = 0;
-    SectionIter startSectionIter, endSectionIter;
-    // slice align is set to the max alignment of the chunks that are
-    // contained in the slice
-    uint64_t sliceAlign = 0;
-    // Current slice size
-    uint64_t curSliceSize = 0;
-    // Current Slice File Offset
-    uint64_t curSliceFileOffset = 0;
-
-    startSectionIter = _sections.begin();
-    endSectionIter = _sections.end();
-    startSection = 0;
-    bool isFirstSection = true;
-    for (auto si = _sections.begin(); si != _sections.end(); ++si) {
-      if (isFirstSection) {
-        // align the startOffset to the section alignment
-        uint64_t newOffset =
-          llvm::RoundUpToAlignment(startOffset, (*si)->align2());
-        curSliceFileOffset = newOffset;
-        sliceAlign = (*si)->align2();
-        this->setFileOffset(startOffset);
-        (*si)->setFileOffset(newOffset);
-        curSliceSize = (*si)->fileSize();
-        isFirstSection = false;
-      } else {
-        uint64_t curOffset = curSliceFileOffset + curSliceSize;
-        uint64_t newOffset =
-          llvm::RoundUpToAlignment(curOffset, (*si)->align2());
-        SegmentSlice<ELFT> *slice = nullptr;
-        // If the newOffset computed is more than a page away, lets create
-        // a seperate segment, so that memory is not used up while running
-        if ((newOffset - curOffset) > _options.pageSize()) {
-          // TODO: use std::find here
-          for (auto s : slices()) {
-            if (s->startSection() == startSection) {
-              slice = s;
-              break;
-            }
-          }
-          if (!slice) {
-            slice = new (_segmentAllocate.Allocate<SegmentSlice<ELFT>>())
-              SegmentSlice<ELFT>();
-            _segmentSlices.push_back(slice);
-          }
-          slice->set(curSliceFileOffset, startSection, currSection);
-          slice->setSections(make_range(startSectionIter, endSectionIter));
-          slice->setSize(curSliceSize);
-          slice->setAlign(sliceAlign);
-          uint64_t newPageOffset =
-            llvm::RoundUpToAlignment(curOffset, _options.pageSize());
-          newOffset = llvm::RoundUpToAlignment(newPageOffset, (*si)->align2());
-          curSliceFileOffset = newOffset;
-          startSectionIter = endSectionIter;
-          startSection = currSection;
-          (*si)->setFileOffset(curSliceFileOffset);
-          curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
-          sliceAlign = (*si)->align2();
-        } else {
-          if (sliceAlign < (*si)->align2())
-            sliceAlign = (*si)->align2();
-          (*si)->setFileOffset(newOffset);
-          curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
-        }
-      }
-      currSection++;
-      endSectionIter = si;
-    }
-    SegmentSlice<ELFT> *slice = nullptr;
-    for (auto s : slices()) {
-      // TODO: add std::find
-      if (s->startSection() == startSection) {
-        slice = s;
-        break;
-      }
-    }
-    if (!slice) {
-      slice = new (_segmentAllocate.Allocate<SegmentSlice<ELFT>>())
-        SegmentSlice<ELFT>();
-      _segmentSlices.push_back(slice);
-    }
-    slice->set(curSliceFileOffset, startSection, currSection);
-    slice->setSections(make_range(startSectionIter, _sections.end()));
-    slice->setSize(curSliceSize);
-    slice->setAlign(sliceAlign);
-    this->_fsize = curSliceFileOffset - startOffset + curSliceSize;
-    std::stable_sort(slices_begin(), slices_end(),
-                     SegmentSlice<ELFT>::compare_slices);
-  }
-
-  /// \brief Assign virtual addresses to the slices
-  void assignVirtualAddress(uint64_t &addr) {
-    for (auto slice : slices()) {
-      // Align to a page
-      addr = llvm::RoundUpToAlignment(addr, _options.pageSize());
-      // Align to the slice alignment
-      addr = llvm::RoundUpToAlignment(addr, slice->align2());
-
-      bool virtualAddressSet = false;
-      for (auto section : slice->sections()) {
-        // Align the section address
-        addr = llvm::RoundUpToAlignment(addr, section->align2());
-        if (!virtualAddressSet) {
-          slice->setVAddr(addr);
-          virtualAddressSet = true;
-        }
-        section->setVAddr(addr);
-        if (auto s = dyn_cast<Section<ELFT>>(section))
-          s->assignVirtualAddress(addr);
-        else
-          addr += section->memSize();
-        section->setMemSize(addr - section->virtualAddr());
-      }
-      slice->setMemSize(addr - slice->virtualAddr());
-    }
-  }
-
-  range<SliceIter> slices() { return _segmentSlices; }
-
-  // These two accessors are still needed for a call to std::stable_sort.
-  // Consider adding wrappers for two iterator algorithms.
-  SliceIter slices_begin() {
-    return _segmentSlices.begin();
-  }
-
-  SliceIter slices_end() {
-    return _segmentSlices.end();
-  }
-
-  // Write the Segment
-  void write(ELFWriter *writer, OwningPtr<FileOutputBuffer> &buffer) {
-    for (auto slice : slices())
-      for (auto section : slice->sections())
-        section->write(writer, buffer);
-  }
-
-  // Finalize the segment, before we want to write to the output file
-  void finalize() { }
-
-  // For LLVM RTTI
-  static inline bool classof(const Chunk<ELFT> *c) {
-    return c->kind() == Chunk<ELFT>::K_ELFSegment;
-  }
-
-  // Getters
-  int32_t sectionCount() const {
-    return _sections.size();
-  }
-
-  ELFLayout::SegmentType segmentType() { return _segmentType; }
-
-  int pageSize() const { return _options.pageSize(); }
-
-  int64_t atomflags() const { return _atomflags; }
-
-  int64_t flags() const {
-    int64_t fl = 0;
-    if (_flags & llvm::ELF::SHF_ALLOC)
-      fl |= llvm::ELF::PF_R;
-    if (_flags & llvm::ELF::SHF_WRITE)
-      fl |= llvm::ELF::PF_W;
-    if (_flags & llvm::ELF::SHF_EXECINSTR)
-      fl |= llvm::ELF::PF_X;
-    return fl;
-  }
-
-  int64_t numSlices() const {
-    return _segmentSlices.size();
-  }
-
-private:
-  /// \brief Section or some other chunk type.
-  std::vector<Chunk<ELFT> *> _sections;
-  std::vector<SegmentSlice<ELFT> *> _segmentSlices;
-  ELFLayout::SegmentType _segmentType;
-  int64_t _flags;
-  int64_t _atomflags;
-  const WriterOptionsELF _options;
-  llvm::BumpPtrAllocator _segmentAllocate;
-};
-
-/// \brief The class represents the ELF String Table
-template<class ELFT>
-class ELFStringTable : public Section<ELFT> {
-public:
-  ELFStringTable(const char *str, int32_t order)
-    : Section<ELFT>(
-        str,
-        llvm::ELF::SHT_STRTAB,
-        DefinedAtom::perm___,
-        order,
-        Section<ELFT>::K_StringTable) {
-    // the string table has a NULL entry for which
-    // add an empty string
-    _strings.push_back("");
-    this->_fsize = 1;
-    this->_align2 = 1;
-    this->setOrder(order);
-  }
-
-  static inline bool classof(const Chunk<ELFT> *c) {
-    return c->kind() == Section<ELFT>::K_StringTable;
-  }
-
-  uint64_t addString(const StringRef symname) {
-    _strings.push_back(symname);
-    uint64_t offset = this->_fsize;
-    this->_fsize += symname.size() + 1;
-    return offset;
-  }
-
-  void write(ELFWriter *writer,
-             OwningPtr<FileOutputBuffer> &buffer) {
-    uint8_t *chunkBuffer = buffer->getBufferStart();
-    uint8_t *dest = chunkBuffer + this->fileOffset();
-    for (auto si : _strings) {
-      memcpy(dest, si.data(), si.size());
-      dest += si.size();
-      memcpy(dest, "", 1);
-      dest += 1;
-    }
-  }
-
-  void finalize() { }
-
-private:
-  std::vector<StringRef> _strings;
-};
-
-/// \brief The ELFSymbolTable class represents the symbol table in a ELF file
-template<class ELFT>
-class ELFSymbolTable : public Section<ELFT> {
-public:
-  typedef object::Elf_Sym_Impl<ELFT> Elf_Sym;
-
-  ELFSymbolTable(const char *str, int32_t order)
-    : Section<ELFT>(
-        str,
-        llvm::ELF::SHT_SYMTAB,
-        0,
-        order,
-        Section<ELFT>::K_SymbolTable) {
-    this->setOrder(order);
-    Elf_Sym *symbol = new (_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
-    memset((void *)symbol, 0, sizeof(Elf_Sym));
-    _symbolTable.push_back(symbol);
-    this->_entSize = sizeof(Elf_Sym);
-    this->_fsize = sizeof(Elf_Sym);
-    this->_align2 = sizeof(void *);
-  }
-
-  static inline bool classof(const Chunk<ELFT> *c) {
-    return c->kind() == Section<ELFT>::K_SymbolTable;
-  }
-
-  void addSymbol(const Atom *atom, int32_t sectionIndex, uint64_t addr = 0) {
-    Elf_Sym *symbol = new(_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
-    unsigned char binding = 0, type = 0;
-    symbol->st_name = _stringSection->addString(atom->name());
-    symbol->st_size = 0;
-    symbol->st_shndx = sectionIndex;
-    symbol->st_value = 0;
-    symbol->st_other = ELF::STV_DEFAULT;
-    if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom)){
-      symbol->st_size = da->size();
-      lld::DefinedAtom::ContentType ct;
-      switch (ct = da->contentType()){
-      case  DefinedAtom::typeCode:
-        symbol->st_value = addr;
-        type = ELF::STT_FUNC;
-        break;
-      case  DefinedAtom::typeData:
-      case  DefinedAtom::typeConstant:
-        symbol->st_value = addr;
-        type = ELF::STT_OBJECT;
-        break;
-      case  DefinedAtom::typeZeroFill:
-        type = ELF::STT_OBJECT;
-        symbol->st_value = addr;
-        break;
-      default:
-        type = ELF::STT_NOTYPE;
-      }
-      if (da->scope() == DefinedAtom::scopeTranslationUnit)
-        binding = ELF::STB_LOCAL;
-      else
-        binding = ELF::STB_GLOBAL;
-    } else if (const AbsoluteAtom *aa = dyn_cast<const AbsoluteAtom>(atom)){
-      type = ELF::STT_OBJECT;
-      symbol->st_shndx = ELF::SHN_ABS;
-      switch (aa->scope()) {
-      case AbsoluteAtom::scopeLinkageUnit:
-        symbol->st_other = ELF::STV_HIDDEN;
-        binding = ELF::STB_LOCAL;
-        break;
-      case AbsoluteAtom::scopeTranslationUnit:
-        binding = ELF::STB_LOCAL;
-        break;
-      case AbsoluteAtom::scopeGlobal:
-        binding = ELF::STB_GLOBAL;
-        break;
-      }
-      symbol->st_value = addr;
-    } else {
-     symbol->st_value = 0;
-     type = ELF::STT_NOTYPE;
-     binding = ELF::STB_WEAK;
-    }
-    symbol->setBindingAndType(binding, type);
-    _symbolTable.push_back(symbol);
-    this->_fsize += sizeof(Elf_Sym);
-  }
-
-  void setStringSection(ELFStringTable<ELFT> *s) {
-    _stringSection = s;
-  }
-
-  void finalize() {
-    // sh_info should be one greater than last symbol with STB_LOCAL binding
-    // we sort the symbol table to keep all local symbols at the beginning
-    std::stable_sort(_symbolTable.begin(), _symbolTable.end(),
-    [](const Elf_Sym *A, const Elf_Sym *B) {
-       return A->getBinding() < B->getBinding();
-    });
-    uint16_t shInfo = 0;
-    for (auto i : _symbolTable) {
-      if (i->getBinding() != ELF::STB_LOCAL)
-        break;
-      shInfo++;
-    }
-    this->_shInfo = shInfo;
-    this->setLink(_stringSection->ordinal());
-  }
-
-  void write(ELFWriter *writer,
-             OwningPtr<FileOutputBuffer> &buffer) {
-    uint8_t *chunkBuffer = buffer->getBufferStart();
-    uint8_t *dest = chunkBuffer + this->fileOffset();
-    for (auto sti : _symbolTable) {
-      memcpy(dest, sti, sizeof(Elf_Sym));
-      dest += sizeof(Elf_Sym);
-    }
-  }
-
-private:
-  ELFStringTable<ELFT> *_stringSection;
-  std::vector<Elf_Sym*> _symbolTable;
-  llvm::BumpPtrAllocator _symbolAllocate;
-  int64_t _link;
-};
-
-/// \brief An ELFHeader represents the Elf[32/64]_Ehdr structure at the
-///        start of an ELF executable file.
-template<class ELFT>
-class ELFHeader : public Chunk<ELFT> {
-public:
-  typedef Elf_Ehdr_Impl<ELFT> Elf_Ehdr;
-
-  ELFHeader()
-  : Chunk<ELFT>("elfhdr", Chunk<ELFT>::K_ELFHeader) {
-    this->_align2 = ELFT::Is64Bits ? 8 : 4;
-    this->_fsize = sizeof(Elf_Ehdr);
-    this->_msize = sizeof(Elf_Ehdr);
-    memset(_eh.e_ident, 0, llvm::ELF::EI_NIDENT);
-    e_ident(ELF::EI_MAG0, 0x7f);
-    e_ident(ELF::EI_MAG1, 'E');
-    e_ident(ELF::EI_MAG2, 'L');
-    e_ident(ELF::EI_MAG3, 'F');
-    e_ehsize(sizeof(Elf_Ehdr));
-    e_flags(2);
-  }
-  void e_ident(int I, unsigned char C) { _eh.e_ident[I] = C; }
-  void e_type(uint16_t type)           { _eh.e_type = type; }
-  void e_machine(uint16_t machine)     { _eh.e_machine = machine; }
-  void e_version(uint32_t version)     { _eh.e_version = version; }
-  void e_entry(int64_t entry)         { _eh.e_entry = entry; }
-  void e_phoff(int64_t phoff)         { _eh.e_phoff = phoff; }
-  void e_shoff(int64_t shoff)         { _eh.e_shoff = shoff; }
-  void e_flags(uint32_t flags)         { _eh.e_flags = flags; }
-  void e_ehsize(uint16_t ehsize)       { _eh.e_ehsize = ehsize; }
-  void e_phentsize(uint16_t phentsize) { _eh.e_phentsize = phentsize; }
-  void e_phnum(uint16_t phnum)         { _eh.e_phnum = phnum; }
-  void e_shentsize(uint16_t shentsize) { _eh.e_shentsize = shentsize; }
-  void e_shnum(uint16_t shnum)         { _eh.e_shnum = shnum; }
-  void e_shstrndx(uint16_t shstrndx)   { _eh.e_shstrndx = shstrndx; }
-  uint64_t  fileSize()                 { return sizeof (Elf_Ehdr); }
-
-  static inline bool classof(const Chunk<ELFT> *c) {
-    return c->Kind() == Chunk<ELFT>::K_ELFHeader;
-  }
-
-  void write(ELFWriter *writer,
-             OwningPtr<FileOutputBuffer> &buffer) {
-    uint8_t *chunkBuffer = buffer->getBufferStart();
-    uint8_t *atomContent = chunkBuffer + this->fileOffset();
-    memcpy(atomContent, &_eh, fileSize());
-  }
-
-  void finalize() { }
-
-private:
-  Elf_Ehdr _eh;
-};
-
-/// \brief An ELFProgramHeader represents the Elf[32/64]_Phdr structure at the
-///        start of an ELF executable file.
-template<class ELFT>
-class ELFProgramHeader : public Chunk<ELFT> {
-public:
-  typedef Elf_Phdr_Impl<ELFT> Elf_Phdr;
-  typedef typename std::vector<Elf_Phdr *>::iterator PhIterT;
-
-  /// \brief Find a program header entry, given the type of entry that
-  /// we are looking for
-  class FindPhdr {
-  public:
-    FindPhdr(uint64_t type, uint64_t flags, uint64_t flagsClear) 
-             : _type(type)
-             , _flags(flags)
-             , _flagsClear(flagsClear)
-    {}
-
-    bool operator()(const Elf_Phdr *j) const { 
-      return ((j->p_type == _type) &&
-              ((j->p_flags & _flags) == _flags) &&
-              (!(j->p_flags & _flagsClear)));
-    }
-  private:
-    uint64_t _type;
-    uint64_t _flags;
-    uint64_t _flagsClear;
-  };
-
-  ELFProgramHeader()
-  : Chunk<ELFT>("elfphdr", Chunk<ELFT>::K_ELFProgramHeader) {
-    this->_align2 = ELFT::Is64Bits ? 8 : 4;
-    resetProgramHeaders();
-  }
-
-  bool addSegment(Segment<ELFT> *segment) {
-    Elf_Phdr *phdr = nullptr;
-    bool ret = false;
-
-    for (auto slice : segment->slices()) {
-      if (_phi == _ph.end()) {
-        phdr = new(_allocator.Allocate<Elf_Phdr>()) Elf_Phdr;
-        _ph.push_back(phdr);
-        _phi = _ph.end();
-        ret = true;
-      } else {
-        phdr = (*_phi);
-        ++_phi;
-      }
-      phdr->p_type = segment->segmentType();
-      phdr->p_offset = slice->fileOffset();
-      phdr->p_vaddr = slice->virtualAddr();
-      phdr->p_paddr = slice->virtualAddr();
-      phdr->p_filesz = slice->fileSize();
-      phdr->p_memsz = slice->memSize();
-      phdr->p_flags = segment->flags();
-      phdr->p_align = (phdr->p_type == llvm::ELF::PT_LOAD) ?
-                       segment->pageSize() : slice->align2();
-    }
-
-    this->_fsize = fileSize();
-    this->_msize = this->_fsize;
-
-    return ret;
-  }
-
-  void resetProgramHeaders() {
-    _phi = _ph.begin();
-  }
-
-  uint64_t  fileSize() {
-    return sizeof(Elf_Phdr) * _ph.size();
-  }
-
-  static inline bool classof(const Chunk<ELFT> *c) {
-    return c->Kind() == Chunk<ELFT>::K_ELFProgramHeader;
-  }
-
-  void write(ELFWriter *writer,
-             OwningPtr<FileOutputBuffer> &buffer) {
-    uint8_t *chunkBuffer = buffer->getBufferStart();
-    uint8_t *dest = chunkBuffer + this->fileOffset();
-    for (auto phi : _ph) {
-      memcpy(dest, phi, sizeof(Elf_Phdr));
-      dest += sizeof(Elf_Phdr);
-    }
-  }
-
-  /// \brief find a program header entry in the list of program headers
-  PhIterT findProgramHeader(uint64_t type, uint64_t flags, uint64_t flagClear) {
-    return std::find_if(_ph.begin(), _ph.end(), 
-                        FindPhdr(type, flags, flagClear));
-  }
-
-  PhIterT begin() {
-    return _ph.begin();
-  }
-
-  PhIterT end() {
-    return _ph.end();
-  }
-
-  void finalize() { }
-
-  int64_t entsize() {
-    return sizeof(Elf_Phdr);
-  }
-
-  int64_t numHeaders() {
-    return _ph.size();
-  }
-
-private:
-  std::vector<Elf_Phdr *> _ph;
-  PhIterT _phi;
-  llvm::BumpPtrAllocator  _allocator;
-};
-
-/// \brief An ELFSectionHeader represents the Elf[32/64]_Shdr structure
-/// at the end of the file
-template<class ELFT>
-class ELFSectionHeader : public Chunk<ELFT> {
-public:
-  typedef Elf_Shdr_Impl<ELFT> Elf_Shdr;
-
-  ELFSectionHeader(int32_t order)
-    : Chunk<ELFT>("shdr", Chunk<ELFT>::K_ELFSectionHeader) {
-    this->_fsize = 0;
-    this->_align2 = 8;
-    this->setOrder(order);
-    // The first element in the list is always NULL
-    Elf_Shdr *nullshdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
-    ::memset(nullshdr, 0, sizeof (Elf_Shdr));
-    _sectionInfo.push_back(nullshdr);
-    this->_fsize += sizeof (Elf_Shdr);
-  }
-
-  uint16_t fileSize() {
-    return sizeof(Elf_Shdr) * _sectionInfo.size();
-  }
-
-  void appendSection(MergedSections<ELFT> *section) {
-    Elf_Shdr *shdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
-    shdr->sh_name   = _stringSection->addString(section->name());
-    shdr->sh_type   = section->type();
-    shdr->sh_flags  = section->flags();
-    shdr->sh_offset = section->fileOffset();
-    shdr->sh_addr   = section->virtualAddr();
-    shdr->sh_size   = section->memSize();
-    shdr->sh_link   = section->link();
-    shdr->sh_info   = section->shinfo();
-    shdr->sh_addralign = section->align2();
-    shdr->sh_entsize = section->entsize();
-    _sectionInfo.push_back(shdr);
-  }
-
-  void updateSection(Section<ELFT> *section) {
-    Elf_Shdr *shdr = _sectionInfo[section->ordinal()];
-    shdr->sh_type   = section->type();
-    shdr->sh_flags  = section->flags();
-    shdr->sh_offset = section->fileOffset();
-    shdr->sh_addr   = section->virtualAddr();
-    shdr->sh_size   = section->fileSize();
-    shdr->sh_link   = section->link();
-    shdr->sh_info   = section->shinfo();
-    shdr->sh_addralign = section->align2();
-    shdr->sh_entsize = section->entsize();
-  }
-
-  static inline bool classof(const Chunk<ELFT> *c) {
-    return c->getChunkKind() == Chunk<ELFT>::K_ELFSectionHeader;
-  }
-
-  void setStringSection(ELFStringTable<ELFT> *s) {
-    _stringSection = s;
-  }
-
-  void write(ELFWriter *writer,
-             OwningPtr<FileOutputBuffer> &buffer) {
-    uint8_t *chunkBuffer = buffer->getBufferStart();
-    uint8_t *dest = chunkBuffer + this->fileOffset();
-    for (auto shi : _sectionInfo) {
-      memcpy(dest, shi, sizeof(Elf_Shdr));
-      dest += sizeof(Elf_Shdr);
-    }
-    _stringSection->write(writer, buffer);
-  }
-
-  void finalize() { }
-
-  int64_t entsize() {
-    return sizeof(Elf_Shdr);
-  }
-
-  int64_t numHeaders() {
-    return _sectionInfo.size();
-  }
-
-private:
-  ELFStringTable<ELFT> *_stringSection;
-  std::vector<Elf_Shdr*>                  _sectionInfo;
-  llvm::BumpPtrAllocator                  _sectionAllocate;
-};
-
-/// \brief The DefaultELFLayout class is used by the Writer to arrange
-///        sections and segments in the order determined by the target ELF
-///        format. The writer creates a single instance of the DefaultELFLayout
-///        class
-template<class ELFT>
-class DefaultELFLayout : public ELFLayout {
-public:
-
-  // The order in which the sections appear in the output file
-  // If its determined, that the layout needs to change
-  // just changing the order of enumerations would essentially
-  // change the layout in the output file
-  enum DefaultSectionOrder {
-    ORDER_NOT_DEFINED = 0,
-    ORDER_INTERP,
-    ORDER_NOTE,
-    ORDER_HASH,
-    ORDER_DYNAMIC_SYMBOLS,
-    ORDER_DYNAMIC_STRINGS,
-    ORDER_INIT,
-    ORDER_TEXT,
-    ORDER_PLT,
-    ORDER_FINI,
-    ORDER_RODATA,
-    ORDER_EH_FRAME,
-    ORDER_EH_FRAMEHDR,
-    ORDER_CTORS,
-    ORDER_DTORS,
-    ORDER_INIT_ARRAY,
-    ORDER_FINI_ARRAY,
-    ORDER_DYNAMIC,
-    ORDER_GOT,
-    ORDER_GOT_PLT,
-    ORDER_DATA,
-    ORDER_BSS,
-    ORDER_OTHER,
-    ORDER_SECTION_STRINGS,
-    ORDER_SYMBOL_TABLE,
-    ORDER_STRING_TABLE,
-    ORDER_SECTION_HEADERS
-  };
-
-public:
-
-  // The Key used for creating Sections
-  // The sections are created using
-  // SectionName, [contentType, contentPermissions]
-  typedef std::pair<StringRef,
-                    std::pair<int32_t, int32_t>> Key;
-  typedef typename std::vector<Chunk<ELFT> *>::iterator ChunkIter;
-  // The key used for Segments
-  // The segments are created using
-  // SegmentName, Segment flags
-  typedef std::pair<StringRef, int64_t> SegmentKey;
-  // Merged Sections contain the map of Sectionnames to a vector of sections,
-  // that have been merged to form a single section
-  typedef std::map<StringRef, MergedSections<ELFT> *> MergedSectionMapT;
-  typedef typename std::vector<MergedSections<ELFT> *>::iterator
-    MergedSectionIter;
-
-  // HashKey for the Section
-  class HashKey {
-  public:
-    int64_t operator() (const Key &k) const {
-      // k.first = section Name
-      // k.second = [contentType, Permissions]
-      return llvm::hash_combine(k.first, k.second.first, k.second.second);
-    }
-  };
-
-  // HashKey for the Segment
-  class SegmentHashKey {
-  public:
-    int64_t operator() (const SegmentKey &k) const {
-      // k.first = SegmentName
-      // k.second = SegmentFlags
-      return llvm::hash_combine(k.first, k.second);
-    }
-  };
-
-  typedef std::unordered_map<Key, Section<ELFT>*, HashKey> SectionMapT;
-  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; 
-    }
-  };
-
-  typedef typename std::vector<AbsoluteAtomPair>::iterator AbsoluteAtomIterT;
-
-  DefaultELFLayout(const WriterOptionsELF &options):_options(options) { }
-
-  /// \brief Return the section order for a input section
-  virtual SectionOrder getSectionOrder
-              (const StringRef name,
-              int32_t contentType,
-              int32_t contentPermissions) {
-    switch (contentType) {
-    case DefinedAtom::typeCode:
-      return llvm::StringSwitch<Reference::Kind>(name)
-        .StartsWith(".eh_frame_hdr", ORDER_EH_FRAMEHDR)
-        .StartsWith(".eh_frame", ORDER_EH_FRAME)
-        .StartsWith(".init", ORDER_INIT)
-        .StartsWith(".fini", ORDER_FINI)
-        .StartsWith(".hash", ORDER_HASH)
-        .Default(ORDER_TEXT);
-
-    case DefinedAtom::typeConstant:
-      return ORDER_RODATA;
-
-    case DefinedAtom::typeData:
-      return llvm::StringSwitch<Reference::Kind>(name)
-        .StartsWith(".init_array", ORDER_INIT_ARRAY)
-        .Default(ORDER_DATA);
-
-    case DefinedAtom::typeZeroFill:
-      return ORDER_BSS;
-
-    default:
-      // If we get passed in a section push it to OTHER
-      if (contentPermissions == DefinedAtom::perm___)
-        return ORDER_OTHER;
-
-      return ORDER_NOT_DEFINED;
-    }
-  }
-
-  /// \brief This maps the input sections to the output section names
-  StringRef getSectionName(const StringRef name,
-                           const int32_t contentType) {
-    if (contentType == DefinedAtom::typeZeroFill)
-      return ".bss";
-    if (name.startswith(".text"))
-      return ".text";
-    if (name.startswith(".rodata"))
-      return ".rodata";
-    return name;
-  }
-
-  /// \brief Gets the segment for a output section
-  virtual ELFLayout::SegmentType getSegmentType(Section<ELFT> *section) const {
-    switch(section->order()) {
-    case ORDER_INTERP:
-      return llvm::ELF::PT_INTERP;
-
-    case ORDER_TEXT:
-    case ORDER_HASH:
-    case ORDER_DYNAMIC_SYMBOLS:
-    case ORDER_DYNAMIC_STRINGS:
-    case ORDER_INIT:
-    case ORDER_PLT:
-    case ORDER_FINI:
-    case ORDER_RODATA:
-    case ORDER_EH_FRAME:
-    case ORDER_EH_FRAMEHDR:
-      return llvm::ELF::PT_LOAD;
-
-    case ORDER_NOTE:
-      return llvm::ELF::PT_NOTE;
-
-    case ORDER_DYNAMIC:
-      return llvm::ELF::PT_DYNAMIC;
-
-    case ORDER_CTORS:
-    case ORDER_DTORS:
-    case ORDER_GOT:
-      return llvm::ELF::PT_GNU_RELRO;
-
-    case ORDER_GOT_PLT:
-    case ORDER_DATA:
-    case ORDER_BSS:
-    case ORDER_INIT_ARRAY:
-    case ORDER_FINI_ARRAY:
-      return llvm::ELF::PT_LOAD;
-
-    default:
-      return llvm::ELF::PT_NULL;
-    }
-  }
-
-  /// \brief Returns true/false depending on whether the section has a Output
-  //         segment or not
-  static bool hasOutputSegment(Section<ELFT> *section) {
-    switch(section->order()) {
-    case ORDER_INTERP:
-    case ORDER_HASH:
-    case ORDER_DYNAMIC_SYMBOLS:
-    case ORDER_DYNAMIC_STRINGS:
-    case ORDER_INIT:
-    case ORDER_PLT:
-    case ORDER_TEXT:
-    case ORDER_FINI:
-    case ORDER_RODATA:
-    case ORDER_EH_FRAME:
-    case ORDER_EH_FRAMEHDR:
-    case ORDER_NOTE:
-    case ORDER_DYNAMIC:
-    case ORDER_CTORS:
-    case ORDER_DTORS:
-    case ORDER_GOT:
-    case ORDER_GOT_PLT:
-    case ORDER_DATA:
-    case ORDER_INIT_ARRAY:
-    case ORDER_FINI_ARRAY:
-    case ORDER_BSS:
-      return true;
-
-    default:
-      return false;
-    }
-  }
-
-  // Adds an atom to the section
-  virtual error_code addAtom(const Atom *atom) {
-    if (const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom)) {
-      const StringRef sectionName =
-                  getSectionName(definedAtom->customSectionName(),
-                                 definedAtom->contentType());
-      const lld::DefinedAtom::ContentPermissions permissions =
-                                    definedAtom->permissions();
-      const lld::DefinedAtom::ContentType contentType =
-                                    definedAtom->contentType();
-      const Key key(sectionName, std::make_pair(contentType, permissions));
-      const std::pair<Key, Section<ELFT> *>currentSection(key, nullptr);
-      std::pair<typename SectionMapT::iterator, bool>
-        sectionInsert(_sectionMap.insert(currentSection));
-      Section<ELFT> *section;
-      // the section is already in the map
-      if (!sectionInsert.second) {
-        section = sectionInsert.first->second;
-        section->setContentPermissions(permissions);
-      } else {
-        SectionOrder section_order = getSectionOrder(sectionName,
-                                       contentType,
-                                       permissions);
-        section = new (_allocator.Allocate<Section<ELFT>>()) Section<ELFT>(
-          sectionName, contentType, permissions, section_order);
-        sectionInsert.first->second = section;
-        section->setOrder(section_order);
-        _sections.push_back(section);
-      }
-      section->appendAtom(atom);
-    }
-    // Absolute atoms are not part of any section, they are global for the whole
-    // link
-    else if (const AbsoluteAtom *absoluteAtom = dyn_cast<AbsoluteAtom>(atom)) {
-      _absoluteAtoms.push_back(AbsoluteAtomPair(absoluteAtom, 
-                                                absoluteAtom->value()));
-    }
-    else 
-      llvm_unreachable("Only absolute / defined atoms can be added here");
-    return error_code::success();
-  }
-
-  /// \brief Find an output Section given a section name.
-  MergedSections<ELFT> *findOutputSection(StringRef name) {
-    auto iter = _mergedSectionMap.find(name);
-    if (iter == _mergedSectionMap.end()) 
-      return nullptr;
-    return iter->second;
-  }
-
-  /// \brief find a absolute atom given a name
-  AbsoluteAtomIterT findAbsoluteAtom(const StringRef name) {
-    return std::find_if(_absoluteAtoms.begin(), _absoluteAtoms.end(),
-                                                FindByName(name));
-  }
-
-  range<AbsoluteAtomIterT> absoluteAtoms() { return _absoluteAtoms; }
-
-  // Merge sections with the same name into a MergedSections
-  void mergeSimiliarSections() {
-    MergedSections<ELFT> *mergedSection;
-
-    for (auto &si : _sections) {
-      const std::pair<StringRef, MergedSections<ELFT> *>
-        currentMergedSections(si->name(), nullptr);
-      std::pair<typename MergedSectionMapT::iterator, bool>
-                              mergedSectionInsert
-                              (_mergedSectionMap.insert(currentMergedSections));
-      if (!mergedSectionInsert.second) {
-        mergedSection = mergedSectionInsert.first->second;
-      } else {
-        mergedSection = new (_allocator.Allocate<MergedSections<ELFT>>())
-          MergedSections<ELFT>(si->name());
-        _mergedSections.push_back(mergedSection);
-        mergedSectionInsert.first->second = mergedSection;
-      }
-      mergedSection->appendSection(si);
-    }
-  }
-
-  void assignSectionsToSegments() {
-    // sort the sections by their order as defined by the layout
-    std::stable_sort(_sections.begin(), _sections.end(),
-    [](Chunk<ELFT> *A, Chunk<ELFT> *B) {
-       return A->order() < B->order();
-    });
-    // Merge all sections
-    mergeSimiliarSections();
-    // Set the ordinal after sorting the sections
-    int ordinal = 1;
-    for (auto msi : _mergedSections) {
-      msi->setOrdinal(ordinal);
-      for (auto ai : msi->sections()) {
-        ai->setOrdinal(ordinal);
-      }
-      ++ordinal;
-    }
-    for (auto msi : _mergedSections) {
-      for (auto ai : msi->sections()) {
-        if (auto section = dyn_cast<Section<ELFT>>(ai)) {
-          if (!hasOutputSegment(section))
-            continue;
-          msi->setHasSegment();
-          section->setSegment(getSegmentType(section));
-          const StringRef segmentName = section->segmentKindToStr();
-          // Use the flags of the merged Section for the segment
-          const SegmentKey key(segmentName, msi->flags());
-          const std::pair<SegmentKey, Segment<ELFT> *>
-            currentSegment(key, nullptr);
-          std::pair<typename SegmentMapT::iterator, bool>
-                              segmentInsert(_segmentMap.insert(currentSegment));
-          Segment<ELFT> *segment;
-          if (!segmentInsert.second) {
-            segment = segmentInsert.first->second;
-          } else {
-            segment = new (_allocator.Allocate<Segment<ELFT>>()) Segment<ELFT>(
-              segmentName, getSegmentType(section), _options);
-            segmentInsert.first->second = segment;
-            _segments.push_back(segment);
-          }
-          segment->append(section);
-        }
-      }
-    }
-  }
-
-  void addSection(Chunk<ELFT> *c) {
-    _sections.push_back(c);
-  }
-
-  void assignFileOffsets() {
-    std::sort(_segments.begin(), _segments.end(),
-              Segment<ELFT>::compareSegments);
-    int ordinal = 0;
-    // Compute the number of segments that might be needed, so that the
-    // size of the program header can be computed
-    uint64_t offset = 0;
-    for (auto si : _segments) {
-      si->setOrdinal(++ordinal);
-      si->assignOffsets(offset);
-      offset += si->fileSize();
-    }
-  }
-
-  void setELFHeader(ELFHeader<ELFT> *e) {
-    _elfHeader = e;
-  }
-
-  void setProgramHeader(ELFProgramHeader<ELFT> *p) {
-    _programHeader = p;
-  }
-
-  void assignVirtualAddress() {
-    if (_segments.empty())
-      return;
-
-    uint64_t virtualAddress = _options.baseAddress();
-
-    // HACK: This is a super dirty hack. The elf header and program header are
-    // not part of a section, but we need them to be loaded at the base address
-    // so that AT_PHDR is set correctly by the loader and so they are accessible
-    // at runtime. To do this we simply prepend them to the first Segment and
-    // let the layout logic take care of it.
-    _segments[0]->prepend(_programHeader);
-    _segments[0]->prepend(_elfHeader);
-
-    bool newSegmentHeaderAdded = true;
-    while (true) {
-      for (auto si : _segments) {
-        newSegmentHeaderAdded = _programHeader->addSegment(si);
-      }
-      if (!newSegmentHeaderAdded)
-        break;
-      uint64_t fileoffset = 0;
-      uint64_t address = virtualAddress;
-      // Fix the offsets after adding the program header
-      for (auto &si : _segments) {
-        // Align the segment to a page boundary
-        fileoffset = llvm::RoundUpToAlignment(fileoffset, _options.pageSize());
-        si->assignOffsets(fileoffset);
-        fileoffset = si->fileOffset() + si->fileSize();
-      }
-      // start assigning virtual addresses
-      for (auto si = _segments.begin(); si != _segments.end(); ++si) {
-        (*si)->setVAddr(virtualAddress);
-        // The first segment has the virtualAddress set to the base address as
-        // we have added the file header and the program header dont align the
-        // first segment to the pagesize
-        (*si)->assignVirtualAddress(address);
-        (*si)->setMemSize(address - virtualAddress);
-        virtualAddress = llvm::RoundUpToAlignment(address, _options.pageSize());
-      }
-      _programHeader->resetProgramHeaders();
-    }
-    Section<ELFT> *section;
-    // Fix the offsets of all the atoms within a section
-    for (auto &si : _sections) {
-      section = dyn_cast<Section<ELFT>>(si);
-      if (section && DefaultELFLayout<ELFT>::hasOutputSegment(section))
-        section->assignOffsets(section->fileOffset());
-    }
-    // Set the size of the merged Sections
-    for (auto msi : _mergedSections) {
-      uint64_t sectionfileoffset = 0;
-      uint64_t startFileOffset = 0;
-      uint64_t sectionsize = 0;
-      bool isFirstSection = true;
-      for (auto si : msi->sections()) {
-        if (isFirstSection) {
-          startFileOffset = si->fileOffset();
-          isFirstSection = false;
-        }
-        sectionfileoffset = si->fileOffset();
-        sectionsize = si->fileSize();
-      }
-      sectionsize = (sectionfileoffset - startFileOffset) + sectionsize;
-      msi->setFileOffset(startFileOffset);
-      msi->setSize(sectionsize);
-    }
-    // Set the virtual addr of the merged Sections
-    for (auto msi : _mergedSections) {
-      uint64_t sectionstartaddr = 0;
-      uint64_t startaddr = 0;
-      uint64_t sectionsize = 0;
-      bool isFirstSection = true;
-      for (auto si : msi->sections()) {
-        if (isFirstSection) {
-          startaddr = si->virtualAddr();
-          isFirstSection = false;
-        }
-        sectionstartaddr = si->virtualAddr();
-        sectionsize = si->memSize();
-      }
-      sectionsize = (sectionstartaddr - startaddr) + sectionsize;
-      msi->setMemSize(sectionsize);
-      msi->setAddr(startaddr);
-    }
-  }
-
-  void assignOffsetsForMiscSections() {
-    uint64_t fileoffset = 0;
-    uint64_t size = 0;
-    for (auto si : _segments) {
-      fileoffset = si->fileOffset();
-      size = si->fileSize();
-    }
-    fileoffset = fileoffset + size;
-    Section<ELFT> *section;
-    for (auto si : _sections) {
-      section = dyn_cast<Section<ELFT>>(si);
-      if (section && DefaultELFLayout<ELFT>::hasOutputSegment(section))
-        continue;
-      fileoffset = llvm::RoundUpToAlignment(fileoffset, si->align2());
-      si->setFileOffset(fileoffset);
-      si->setVAddr(0);
-      fileoffset += si->fileSize();
-    }
-  }
-
-  void finalize() {
-    for (auto &si : _sections)
-      si->finalize();
-  }
-
-  bool findAtomAddrByName(const StringRef name, uint64_t &addr) {
-    for (auto sec : _sections)
-      if (auto section = dyn_cast<Section<ELFT>>(sec))
-        if (section->findAtomAddrByName(name, addr))
-         return true;
-    return false;
-  }
-
-  range<MergedSectionIter> mergedSections() { return _mergedSections; }
-
-  range<ChunkIter> sections() { return _sections; }
-
-  range<ChunkIter> segments() { return _segments; }
-
-  ELFHeader<ELFT> *elfHeader() {
-    return _elfHeader;
-  }
-
-  ELFProgramHeader<ELFT> *elfProgramHeader() {
-    return _programHeader;
-  }
-
-private:
-  SectionMapT _sectionMap;
-  MergedSectionMapT _mergedSectionMap;
-  SegmentMapT _segmentMap;
-  std::vector<Chunk<ELFT> *> _sections;
-  std::vector<Segment<ELFT> *> _segments;
-  std::vector<MergedSections<ELFT> *> _mergedSections;
-  ELFHeader<ELFT> *_elfHeader;
-  ELFProgramHeader<ELFT> *_programHeader;
-  std::vector<AbsoluteAtomPair> _absoluteAtoms;
-  llvm::BumpPtrAllocator _allocator;
-  const WriterOptionsELF &_options;
-};
-
 //===----------------------------------------------------------------------===//
 //  ELFExecutableWriter Class
 //===----------------------------------------------------------------------===//





More information about the llvm-commits mailing list