[llvm-commits] [lld] patch for ELF Writer to get it to 'Hello world'

Shankar Easwaran shankare at codeaurora.org
Mon Dec 17 07:15:21 PST 2012


Hi,

Attached is a patch to get the linker for Hexagon to get to 'Hello world'.

The changes are :-

1) Adds a ELF Layout class to WriterELF, becomes much easier to control 
section ordering
2) Adds Section/Segment semantics to the ELF linker
3) Easier to add Linker script support in the future.

Attached is the patch ? Let me know if its ok to commit ?

Thanks

Shankar Easwaran

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation

-------------- next part --------------
Index: include/lld/ReaderWriter/WriterELF.h
===================================================================
--- include/lld/ReaderWriter/WriterELF.h	(revision 169997)
+++ include/lld/ReaderWriter/WriterELF.h	(working copy)
@@ -48,7 +48,7 @@
                    const uint16_t Type,
                    const uint16_t Machine,
                    uint64_t pointerWidth = 4,
-                   uint64_t baseAddress = 0x400000,
+                   uint64_t baseAddress = 0,
                    uint64_t pageSize = 0x1000)
   : _is64Bit(Is64Bit)
   , _endianness(endian)
Index: include/lld/Core/DefinedAtom.h
===================================================================
--- include/lld/Core/DefinedAtom.h	(revision 169997)
+++ include/lld/Core/DefinedAtom.h	(working copy)
@@ -97,6 +97,7 @@
 
   enum Merge {
     mergeNo,                // Another atom with same name is error
+    mergeByContent,         // Merge sections using content
     mergeAsTentative,       // Is ANSI C tentative defintion, can be coalesced
     mergeAsWeak,            // is C++ inline definition that was not inlined,
                             // but address was not taken, so atom can be hidden
@@ -147,8 +148,9 @@
   enum ContentPermissions {
     perm___  = 0,           // mapped as unaccessible
     permR__  = 8,           // mapped read-only
-    permR_X  = 8 + 2,       // mapped readable and executable
-    permRW_  = 8 + 4,       // mapped readable and writable
+    permRW_  = 8 + 2,       // mapped readable and writable
+    permR_X  = 8 + 4,       // mapped readable and executable
+    permRWX  = 8 + 4 + 2,   // mapped readable and writable and executable
     permRW_L = 8 + 4 + 1,   // initially mapped r/w, then made read-only
                             // loader writable
   };
Index: lib/ReaderWriter/ELF/ELFAtoms.h
===================================================================
--- lib/ReaderWriter/ELF/ELFAtoms.h	(revision 0)
+++ lib/ReaderWriter/ELF/ELFAtoms.h	(revision 0)
@@ -0,0 +1,472 @@
+#ifndef LLD_ELFATOMS_H_
+#define LLD_ELFATOMS_H_
+
+#include "lld/Core/LLVM.h"
+#include <memory>
+#include <vector>
+
+namespace lld {
+/// \brief Relocation References: Defined Atoms may contain 
+/// references that will need to be patched before
+/// the executable is written.
+template <llvm::support::endianness target_endianness, bool is64Bits>
+class ELFReference final : public Reference {
+
+  typedef llvm::object::Elf_Rel_Impl
+                        <target_endianness, is64Bits, false> Elf_Rel;
+  typedef llvm::object::Elf_Rel_Impl
+                        <target_endianness, is64Bits, true> Elf_Rela;
+public:
+
+  ELFReference(const Elf_Rela *rela, uint64_t offset, const Atom *target)
+    : _target(target)
+    , _targetSymbolIndex(rela->getSymbol())
+    , _offsetInAtom(offset)
+    , _addend(rela->r_addend)
+    , _kind(rela->getType()) {}
+
+  ELFReference(const Elf_Rel *rel, uint64_t offset, const Atom *target)
+    : _target(target)
+    , _targetSymbolIndex(rel->getSymbol())
+    , _offsetInAtom(offset)
+    , _addend(0)
+    , _kind(rel->getType()) {}
+
+
+  virtual uint64_t offsetInAtom() const {
+    return _offsetInAtom;
+  }
+
+  virtual Kind kind() const {
+    return _kind;
+  }
+
+  virtual void setKind(Kind kind) {
+    _kind = kind;
+  }
+
+  virtual const Atom *target() const {
+    return _target;
+  }
+
+/// \brief targetSymbolIndex: This is the symbol table index that contains
+/// the target reference.
+  uint64_t targetSymbolIndex() const {
+    return _targetSymbolIndex;
+  }
+
+  virtual Addend addend() const {
+    return _addend;
+  }
+
+  virtual void setAddend(Addend A) {
+    _addend = A;
+  }
+
+  virtual void setTarget(const Atom *newAtom) {
+    _target = newAtom;
+  }
+private:
+  const Atom  *_target;
+  uint64_t     _targetSymbolIndex;
+  uint64_t     _offsetInAtom;
+  Addend       _addend;
+  Kind         _kind;
+};
+
+
+/// \brief ELFAbsoluteAtom: These atoms store symbols that are fixed to a
+/// particular address.  This atom has no content its address will be used by
+/// the writer to fixup references that point to it.
+template<llvm::support::endianness target_endianness, bool is64Bits>
+class ELFAbsoluteAtom final : public AbsoluteAtom {
+
+  typedef llvm::object::Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
+
+public:
+  ELFAbsoluteAtom(const File &file,
+                  llvm::StringRef name,
+                  const Elf_Sym *symbol,
+                  uint64_t value)
+    : _owningFile(file)
+    , _name(name)
+    , _symbol(symbol)
+    , _value(value)
+  {}
+
+  virtual const class File &file() const {
+    return _owningFile;
+  }
+
+  virtual Scope scope() const {
+    if (!_symbol) 
+      return scopeGlobal;
+    if (_symbol->st_other == llvm::ELF::STV_HIDDEN)
+      return scopeLinkageUnit;
+    if (_symbol->getBinding() == llvm::ELF::STB_LOCAL)
+      return scopeTranslationUnit;
+    else
+      return scopeGlobal;
+  }
+
+  virtual llvm::StringRef name() const {
+    return _name;
+  }
+
+  virtual uint64_t value() const {
+    return _value;
+  }
+
+private:
+  const File &_owningFile;
+  llvm::StringRef _name;
+  const Elf_Sym *_symbol;
+  uint64_t _value;
+};
+
+
+/// \brief ELFUndefinedAtom: These atoms store undefined symbols and are
+/// place holders that will be replaced by defined atoms later in the
+/// linking process.
+template<llvm::support::endianness target_endianness, bool is64Bits>
+class ELFUndefinedAtom final: public UndefinedAtom {
+
+  typedef llvm::object::Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
+
+public:
+  ELFUndefinedAtom(const File &file,
+                   llvm::StringRef name,
+                   const Elf_Sym *symbol)
+    : _owningFile(file)
+    , _name(name)
+    , _symbol(symbol)
+  {}
+
+  virtual const class File &file() const {
+    return _owningFile;
+  }
+
+  virtual llvm::StringRef name() const {
+    return _name;
+  }
+
+  //   FIXME What distinguishes a symbol in ELF that can help
+  //   decide if the symbol is undefined only during build and not
+  //   runtime? This will make us choose canBeNullAtBuildtime and
+  //   canBeNullAtRuntime
+  //
+  virtual CanBeNull canBeNull() const {
+
+    if (_symbol->getBinding() == llvm::ELF::STB_WEAK)
+      return CanBeNull::canBeNullAtBuildtime;
+    else
+      return CanBeNull::canBeNullNever;
+  }
+
+private:
+  const File &_owningFile;
+  llvm::StringRef _name;
+  const Elf_Sym *_symbol;
+};
+
+
+/// \brief ELFDefinedAtom: This atom stores defined symbols and will contain
+/// either data or code.
+template<llvm::support::endianness target_endianness, bool is64Bits>
+class ELFDefinedAtom final: public DefinedAtom {
+
+  typedef llvm::object::Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
+  typedef llvm::object::Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
+
+public:
+  ELFDefinedAtom(const File &file,
+                 llvm::StringRef symbolName,
+                 llvm::StringRef sectionName,
+                 const Elf_Sym *symbol,
+                 const Elf_Shdr *section,
+                 llvm::ArrayRef<uint8_t> contentData,
+                 unsigned int referenceStart,
+                 unsigned int referenceEnd,
+                 std::vector<ELFReference
+                             <target_endianness, is64Bits> *> &referenceList)
+
+    : _owningFile(file)
+    , _symbolName(symbolName)
+    , _sectionName(sectionName)
+    , _symbol(symbol)
+    , _section(section)
+    , _contentData(contentData) 
+    , _referenceStartIndex(referenceStart)
+    , _referenceEndIndex(referenceEnd)
+    , _referenceList(referenceList) {
+    static uint64_t orderNumber = 0;
+    _ordinal = ++orderNumber;
+  }
+
+  virtual const class File &file() const {
+    return _owningFile;
+  }
+
+  virtual llvm::StringRef name() const {
+    return _symbolName;
+  }
+
+  virtual uint64_t ordinal() const {
+    return _ordinal;
+  }
+
+  virtual uint64_t size() const {
+
+    // Common symbols are not allocated in object files,
+    // so use st_size to tell how many bytes are required.
+    if ((_symbol->getType() == llvm::ELF::STT_COMMON)
+        || _symbol->st_shndx == llvm::ELF::SHN_COMMON)
+      return (uint64_t)_symbol->st_size;
+
+    return _contentData.size();
+
+  }
+
+  virtual Scope scope() const {
+    if (_symbol->st_other == llvm::ELF::STV_HIDDEN)
+      return scopeLinkageUnit;
+    else if (_symbol->getBinding() != llvm::ELF::STB_LOCAL)
+      return scopeGlobal;
+    else
+      return scopeTranslationUnit;
+  }
+
+  //   FIXME   Need to revisit this in future.
+
+  virtual Interposable interposable() const {
+    return interposeNo;
+  }
+
+  //  FIXME What ways can we determine this in ELF?
+
+  virtual Merge merge() const {
+
+    if (_symbol->getBinding() == llvm::ELF::STB_WEAK)
+      return mergeAsWeak;
+
+    if ((_symbol->getType() == llvm::ELF::STT_COMMON)
+        || _symbol->st_shndx == llvm::ELF::SHN_COMMON)
+      return mergeAsTentative;
+
+    return mergeNo;
+  }
+
+  virtual ContentType contentType() const {
+
+    ContentType ret = typeUnknown;
+    uint64_t flags = _section->sh_flags;
+
+    switch (_section->sh_type) {
+    case llvm::ELF::SHT_PROGBITS:
+      flags &= ~llvm::ELF::SHF_ALLOC;
+      switch (flags) {
+      case llvm::ELF::SHF_EXECINSTR:
+      case (llvm::ELF::SHF_WRITE|llvm::ELF::SHF_EXECINSTR):
+        ret = typeCode;
+        break;
+      case llvm::ELF::SHF_WRITE:
+        ret = typeData;
+        break;
+      case llvm::ELF::SHF_MERGE:
+      case llvm::ELF::SHF_STRINGS:
+        ret = typeConstant;
+        break;
+      default:
+        ret = typeCode;
+        break;
+      }
+      break;
+    case llvm::ELF::SHT_NOBITS:
+      ret = typeZeroFill;
+      break;
+    case llvm::ELF::SHT_NULL:
+      if ((_symbol->getType() == llvm::ELF::STT_COMMON)
+          || _symbol->st_shndx == llvm::ELF::SHN_COMMON)
+        ret = typeZeroFill;
+      break;
+    }
+
+    return ret;
+  }
+
+  virtual Alignment alignment() const {
+    // Unallocated common symbols specify their alignment
+    // constraints in st_value.
+    if ((_symbol->getType() == llvm::ELF::STT_COMMON)
+        || _symbol->st_shndx == llvm::ELF::SHN_COMMON) {
+      return Alignment(llvm::Log2_64(_symbol->st_value));
+    }
+    return Alignment(llvm::Log2_64(_section->sh_addralign), 
+                     _symbol->st_value % _section->sh_addralign);
+  }
+
+  // Do we have a choice for ELF?  All symbols
+  // live in explicit sections.
+  virtual SectionChoice sectionChoice() const {
+    return sectionCustomRequired;
+  }
+
+  virtual llvm::StringRef customSectionName() const {
+    if ((contentType() == typeZeroFill) ||
+        (_symbol->st_shndx == llvm::ELF::SHN_COMMON)) 
+      return ".bss";
+    return _sectionName;
+  }
+
+  // It isn't clear that __attribute__((used)) is transmitted to
+  // the ELF object file.
+  virtual DeadStripKind deadStrip() const {
+    return deadStripNormal;
+  }
+
+  virtual ContentPermissions permissions() const {
+
+    uint64_t flags = _section->sh_flags;
+    switch (_section->sh_type) {
+      // permRW_L is for sections modified by the runtime
+      // loader.
+      case llvm::ELF::SHT_REL:
+      case llvm::ELF::SHT_RELA:
+        return permRW_L;
+
+      case llvm::ELF::SHT_PROGBITS:
+        flags &= ~llvm::ELF::SHF_ALLOC;
+        switch (flags) {
+          // Code
+          case llvm::ELF::SHF_EXECINSTR:
+            return permR_X;
+          case (llvm::ELF::SHF_WRITE|llvm::ELF::SHF_EXECINSTR):
+            return permRWX;
+          // Data
+          case llvm::ELF::SHF_WRITE:
+            return permRW_;
+          // Strings
+          case llvm::ELF::SHF_MERGE:
+          case llvm::ELF::SHF_STRINGS:
+            return permR__;
+
+          default:
+            if (flags & llvm::ELF::SHF_WRITE) 
+              return permRW_;
+            return permR__;
+        }
+
+    case llvm::ELF::SHT_NOBITS:
+        return permRW_;
+
+    default:
+      return perm___;
+    }
+  }
+
+  virtual bool isThumb() const {
+    return false;
+  }
+
+  //  FIXME Not Sure if ELF supports alias atoms. Find out more.
+  virtual bool isAlias() const {
+    return false;
+  }
+
+  virtual llvm::ArrayRef<uint8_t> rawContent() const {
+    return _contentData;
+  }
+
+  DefinedAtom::reference_iterator begin() const {
+    uintptr_t index = _referenceStartIndex;
+    const void *it = reinterpret_cast<const void*>(index);
+    return reference_iterator(*this, it);
+  }
+
+  DefinedAtom::reference_iterator end() const {
+    uintptr_t index = _referenceEndIndex;
+    const void *it = reinterpret_cast<const void*>(index);
+    return reference_iterator(*this, it);
+  }
+
+  const Reference *derefIterator(const void *It) const {
+    uintptr_t index = reinterpret_cast<uintptr_t>(It);
+    assert(index >= _referenceStartIndex);
+    assert(index < _referenceEndIndex);
+    return ((_referenceList)[index]);
+  }
+
+  void incrementIterator(const void*& It) const {
+    uintptr_t index = reinterpret_cast<uintptr_t>(It);
+    ++index;
+    It = reinterpret_cast<const void*>(index);
+  }
+
+private:
+
+  const File &_owningFile;
+  llvm::StringRef _symbolName;
+  llvm::StringRef _sectionName;
+  const Elf_Sym *_symbol;
+  const Elf_Shdr *_section;
+  // _contentData will hold the bits that make up the atom.
+  llvm::ArrayRef<uint8_t> _contentData;
+
+  uint64_t _ordinal;
+  unsigned int _referenceStartIndex;
+  unsigned int _referenceEndIndex;
+  std::vector<ELFReference<target_endianness, is64Bits> *> &_referenceList;
+}; // ELFDefinedAtom
+
+
+//
+// Simple File
+//
+class SimpleFile : public File {
+public:
+      SimpleFile(StringRef path) 
+        : File(path) {
+      }
+      
+  virtual void addAtom(const Atom &atom) {
+    if (const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(&atom)) {
+      _definedAtoms._atoms.push_back(defAtom);
+    } 
+    else if (const UndefinedAtom* undefAtom = dyn_cast<UndefinedAtom>(&atom)) {
+      _undefinedAtoms._atoms.push_back(undefAtom);
+    } 
+    else if (const SharedLibraryAtom* slAtom =
+                 dyn_cast<SharedLibraryAtom>(&atom)) {
+      _sharedLibraryAtoms._atoms.push_back(slAtom);
+    } 
+    else if (const AbsoluteAtom* abAtom = dyn_cast<AbsoluteAtom>(&atom)) {
+      _absoluteAtoms._atoms.push_back(abAtom);
+    } 
+    else {
+      llvm_unreachable("atom has unknown definition kind");
+    }
+  }
+
+  virtual const atom_collection<DefinedAtom>& defined() const {
+    return _definedAtoms;
+  }
+  virtual const atom_collection<UndefinedAtom>& undefined() const {
+      return _undefinedAtoms;
+  }
+  virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
+      return _sharedLibraryAtoms;
+  }
+  virtual const atom_collection<AbsoluteAtom>& absolute() const {
+      return _absoluteAtoms;
+  }
+      
+private:
+  atom_collection_vector<DefinedAtom>         _definedAtoms;
+  atom_collection_vector<UndefinedAtom>       _undefinedAtoms;
+  atom_collection_vector<SharedLibraryAtom>   _sharedLibraryAtoms;
+  atom_collection_vector<AbsoluteAtom>        _absoluteAtoms;
+};
+
+} // namespace lld
+
+#endif
Index: lib/ReaderWriter/ELF/WriterELF.cpp
===================================================================
--- lib/ReaderWriter/ELF/WriterELF.cpp	(revision 169997)
+++ lib/ReaderWriter/ELF/WriterELF.cpp	(working copy)
@@ -22,6 +22,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringExtras.h"
 
 #include "llvm/Object/ELF.h"
 
@@ -34,1382 +35,2098 @@
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/system_error.h"
+#include "ELFAtoms.h"
 
 #include <map>
+#include <unordered_map>
 #include <tuple>
 #include <vector>
-#include <algorithm>
 
 using namespace llvm;
 using namespace llvm::object;
 namespace lld {
 namespace elf {
 
-// The group decides where sections of similar permissions reside
-// inside a file. This is also used to create program headers. Each group
-// will be in a new segment.
+template<support::endianness target_endianness, bool is64Bits>
+class ELFExecutableWriter;
 
-/// \name Chunk Groups
-/// Each "Chunk" should be arranged in a weak strict order
-/// This is done to minimize memory utilization when creating program segments.
-/// This will remain in place till a more felxible mechanism of moving chunks 
-/// around and packing for memory efficiency is put in place. 
-/// The Chunks are arranged by group numbers. Every switch from group A to B
-/// triggers a formation of new segment. Additionally segments are also made
-/// within a group if there are vast regions (multiple pages) of 0 for 
-/// alignment constraints.
-enum {
-/// @{
-///Invalid group (default on creation)
-  CG_INVALID = 0x0,
-///This is a "header" kind of chunk that goes at beginning of ELF file
-  CG_HEADER = 0x1,
-///This is a section chunk with read write and execute permissions
-  CG_RWX = 0x3,
-///This is a section chunk with read and execute permissions
-  CG_RX = 0x4,
-///This is a section chunk with read permission
-  CG_R = 0x5,
-///This is a section chunk with read and write permissions
-  CG_RW = 0x6,
-///This is a section chunk with write and execute permissions
-  CG_WX = 0x7,
-///This is a section chunk with write permission
-  CG_W = 0x8,
-///This is a section chunk with execute permission
-  CG_X = 0x9,
-///This is a section which is no loaded by program loader
-  CG_NO_LOAD = 0xFE,
-///This is ELF file metadata that goes at end of file
-  CG_FILE_END = 0xFF 
-/// @}
-};
+/// \brief The ELFWriter class is a base class for the linker to write
+///        various kinds of ELF files.
+class ELFWriter : public Writer {
+  public:
+    ELFWriter() { }
 
-template<support::endianness target_endianness, bool is64Bits>
-class ELFWriter;
+  public:
+    /// \brief builds the chunks that needs to be written to the output
+    ///        ELF file
+    virtual void buildChunks(const lld::File &file) = 0;
 
-template<support::endianness target_endianness, bool is64Bits>
-class StockSectionChunk;
+    /// \brief Writes the chunks into the output file specified by path
+    virtual error_code writeFile(const lld::File &File, StringRef path) = 0;
 
-/// \brief A Chunk is a contiguous range of space.
+    /// \brief Writes the chunks into the output file specified by path
+    virtual int64_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<support::endianness target_endianness, bool is64Bits>
 class Chunk {
 public:
-  LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
+
+  /// \brief Describes the type of Chunk
+  enum Kind {
+    ELFHeader, // ELF Header
+    ProgramHeader, // Program Header
+    Segment, // Segment
+    Section, // Section
+    SectionHeader // 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() {}
-  virtual StringRef   segmentName() const = 0;
-  virtual bool        occupiesNoDiskSpace();
-  virtual void        write(uint8_t *fileBuffer) = 0;
-  void                assignFileOffset(uint64_t &curOff, uint64_t &curAddr);
-  virtual const char *info() = 0;
-  uint64_t            size() const;
-  uint64_t            address() const;
-  uint64_t            fileOffset() const;
-  uint64_t            align2() const;
-  static uint64_t     alignTo(uint64_t value, uint8_t align2);
-  uint64_t            ordinal() const { return _ordinal;}
-  void                setOrdinal(uint64_t newVal) { _ordinal = newVal;}
-  void                setGroup(uint16_t val) { _group = val;}
-  uint16_t            group() const { return _group;}
-  void                init();
-  bool                isLoadable() { return _isLoadable; }
-  void                isLoadable(uint64_t val) {  _isLoadable = val; }
-  enum class Kind {
-    Header,      // This is a header chunk
-    Section      // chunk represents a section
-  };
-  Kind getChunkKind() const { return _cKind; }
-private:
-  const Kind _cKind;
+  // Does the chunk occupy disk space 
+  virtual bool        occupiesNoDiskSpace() {
+    return false;    
+  }
+  // The name of the chunk
+  StringRef name() const { return _name; }
+  // Kind of chunk
+  Kind kind() const { return _kind; }
+  int64_t            filesize() const { return _fsize; }
+  int64_t            align2() const { return _align2; }
+  void                appendAtom() const;
+
+  // Align the chunk, this doesnot take modulus into account
+  static int64_t     alignTo(int64_t value, int64_t align2) {
+    return ((value + align2 - 1) & ~(align2 - 1));
+  }
+  // The ordinal value of the chunk
+  int64_t            ordinal() const { return _ordinal;}
+  void               setOrdinal(int64_t newVal) { _ordinal = newVal;}
+  // The order in which the chunk would appear in the output file
+  int64_t            order() const { return _order; }
+  void               setOrder(int32_t order) { _order = order; }
+  // Output file offset of the chunk
+  int64_t            fileOffset() const { return _fileoffset; }
+  void               setFileOffset(int64_t offset) { _fileoffset = offset; }
+  // Output start address of the chunk
+  void               setStart(int64_t start) { _start = start; }
+  int64_t            startAddr() const { return _start; }
+  // Does the chunk occupy memory during execution ?
+  int64_t            memsize() const { return _msize; }
+  void               setMemSize(int64_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;
+  static inline bool classof(Chunk<target_endianness, is64Bits> *s) { 
+    return true;
+  }
+
 protected:
-  Chunk();
-  Chunk(Kind K): _cKind(K) { this->init();}
-  uint64_t _size;
-  uint64_t _address;
-  uint64_t _fileOffset;
-  uint64_t _align2;
-  uint64_t _ordinal;
-  uint16_t _group;
-  bool     _isLoadable;
+  StringRef _name;
+  Kind _kind;
+  int64_t _fsize;
+  int64_t _msize;
+  int64_t _align2;
+  int32_t  _order;
+  int64_t _ordinal;
+  int64_t _start;
+  int64_t _fileoffset;
 };
 
-template<support::endianness target_endianness, bool is64Bits>
-static void swapChunkPositions(Chunk<target_endianness, is64Bits>&a,
-                               Chunk<target_endianness, is64Bits>&b) {
-  uint64_t tempOrdinal;
-  if (a.ordinal() == b.ordinal()) return;
-  tempOrdinal = a.ordinal();
-  a.setOrdinal(b.ordinal());
-  b.setOrdinal(tempOrdinal);
-}
+///
+/// \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() { }
 
-template<support::endianness target_endianness, bool is64Bits>
-bool chunkGroupSort(Chunk<target_endianness, is64Bits> *A,
-                    Chunk<target_endianness, is64Bits> *B) {
-  if (A->group() == CG_INVALID || B->group() == CG_INVALID)
-    llvm_unreachable("Invalid group number");
-  return A->group() < B->group();
-}
+  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 int32_t SectionOrder;
+  typedef int32_t SegmentType;
+  typedef int32_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, int64_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 assignFileOffset() = 0;
+
+public:
+  ELFLayout() {}
+  ELFLayout(WriterOptionsELF &writerOptions, 
+            ELFLayoutOptions &layoutOptions) : _writerOptions(writerOptions),
+                                               _layoutOptions(layoutOptions) { }
+  virtual ~ELFLayout() { }
+
+private:
+  WriterOptionsELF _writerOptions;
+  ELFLayoutOptions _layoutOptions;
+};
+
+
+/// \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<support::endianness target_endianness, bool is64Bits>
-struct ChunkComparator {
-  bool operator()(uint16_t A, Chunk<target_endianness, is64Bits> *B) {
-    return A < B->group();
+class Section : public Chunk<target_endianness, is64Bits> {
+public:
+  // The Kind of section that the object represents 
+  enum Kind {
+    Default,
+    SymbolTable,
+    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 Kind kind = Default) : 
+                    Chunk<target_endianness, is64Bits>(sectionName,
+                    Chunk<target_endianness, is64Bits>::Section) {
+    _contentType = contentType;
+    _contentPermissions = contentPermissions;
+    _sectionKind = kind;
+    _link = 0;
+    _entsize = 0;
+    _shinfo = 0;
+    this->setOrder(order);
   }
-  bool operator()(Chunk<target_endianness, is64Bits> *A, uint16_t B) {
-    return A->group() < B;
+
+  // return the section kind
+  Kind sectionKind() const {
+    return _sectionKind;
   }
-#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL == 2
- bool operator()(Chunk<target_endianness, is64Bits> *A,
-        Chunk<target_endianness, is64Bits> *B) {
-   return A->group() < B->group();
- }
-#endif
-};
 
-/// Pair of atom and offset in section.
-typedef std::tuple<const DefinedAtom*, uint64_t> AtomInfo;
+  // append an atom to a Section
+  // The atom gets pushed into a vector that 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 = dyn_cast<DefinedAtom>(atom);
+    assert(atom != nullptr && "Expecting the atom to be a DefinedAtom");
+    DefinedAtom::Alignment atomAlign = definedAtom->alignment();
+    int64_t align2 = 1 << atomAlign.powerOf2;
+    uint64_t foffset = this->filesize();
+    uint64_t moffset = this->memsize();
 
-/// \brief A SectionChunk represents ELF sections 
-template<support::endianness target_endianness, bool is64Bits>
-class SectionChunk : public Chunk<target_endianness, is64Bits> {
-public:
-  virtual StringRef   segmentName() const { return _segmentName; }
-  virtual bool        occupiesNoDiskSpace();
-  virtual const char  *info();
-  StringRef           sectionName() { return _sectionName; }
-  uint64_t            shStrtableOffset(){ return _offsetInStringTable; }
-  void                setShStrtableOffset (uint64_t val) {
-                       _offsetInStringTable = val; } 
-  uint32_t            flags()  { return _flags; }
-  uint32_t            type() const { return _type; }
-  uint64_t            link()   { return _link; }
-  void                link(uint64_t val)   { _link = val; }
-  uint16_t            shinfo() { return _shinfo; }
-  uint64_t            entsize() { return _entsize; }
-  SectionChunk(StringRef secName, StringRef segName, bool loadable, 
-               uint64_t flags , uint64_t link,  uint64_t info ,
-               uint64_t type, uint64_t entsz, const WriterOptionsELF &op, 
-               ELFWriter<target_endianness, is64Bits> &writer);
+    // 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 requiredModulus = atomAlign.modulus;
+    uint64_t fcurrentModulus = (foffset % align2);
+    uint64_t mcurrentModulus = (moffset % align2);
+    // align the file offset
+    if (fcurrentModulus != requiredModulus) {
+      if (requiredModulus > fcurrentModulus)
+        foffset += requiredModulus - fcurrentModulus;
+      else
+        foffset += align2 + requiredModulus - fcurrentModulus;
+    }
+    // align memory offset
+    if (mcurrentModulus != requiredModulus) {
+      if (requiredModulus > mcurrentModulus)
+        moffset += requiredModulus - mcurrentModulus;
+      else
+        moffset += align2 + requiredModulus - mcurrentModulus;
+    }
+    switch (atomType) {
+      case Atom::definitionRegular:
+        switch(definedAtom->contentType()) {
+          case  DefinedAtom::typeCode:
+          case  DefinedAtom::typeData:
+            _atoms.push_back(std::make_pair(atom, std::make_pair(foffset, 0)));
+            this->_fsize = foffset + definedAtom->size();
+            this->_msize = moffset + definedAtom->size();
+            break;
+          case  DefinedAtom::typeZeroFill:
+            _atoms.push_back(std::make_pair(atom, std::make_pair(moffset, 0)));
+            this->_msize = moffset + definedAtom->size();
+            break;
+          default:
+            this->_fsize = foffset + definedAtom->size();
+            this->_msize = moffset + definedAtom->size();
+            break;
+        }
+        break;
+      default:
+        assert(0);
+        break;
+    } 
+    // Set the section alignment to the largest alignment 
+    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(int64_t &addr) {
+    for (auto ai = _atoms.begin(); ai != _atoms.end(); ++ai) {
+      ai->second.second = addr + ai->second.first;
+    }
+    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 assignOffset(int64_t offset) {
+    for (auto ai = _atoms.begin(); ai != _atoms.end(); ++ai) {
+      ai->second.first = offset + ai->second.first;
+    }
+  }
+
+  /// \brief Find the Atom address given a name, this is needed to 
+  ///        to properly apply relocation
+  bool findAtomAddrByName(const StringRef name, int64_t &addr) {
+    for (auto ai = _atoms.begin(); ai != _atoms.end(); ++ai) {
+      if (ai->first->name() == name) {
+        addr = ai->second.second;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /// \brief Does the Atom occupy any disk space
+  bool occupiesNoDiskSpace() const {
+    if (_contentType == DefinedAtom::typeZeroFill)
+      return true;
+    return false;
+  }
+
+  /// \brief The permission of the section is the most 
+  ///        restrictive permission of all atoms that the
+  ///        section contains
+  void setContentPermissions(int32_t perm) {
+    if (perm > _contentPermissions) 
+      _contentPermissions = perm;
+  }
+
+  /// \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(Section<target_endianness, is64Bits> *s) {
+    return true;
+  }
+
   static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
-    return c->getChunkKind() == Chunk<target_endianness, is64Bits>::Kind
-                                                                  ::Section;
+    return c->kind() == Chunk<target_endianness, is64Bits>::Section;
   }
+
+  /// \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.begin(); ai != _atoms.end(); ++ai) {
+      const DefinedAtom* definedAtom = llvm::dyn_cast<DefinedAtom>(ai->first);
+      // 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)->second.first);
+      std::copy_n(content.data(), contentSize, atomContent);
+      for (auto ref = definedAtom->begin(); ref != definedAtom->end(); ++ref) {
+        uint32_t offset = ref->offsetInAtom();
+        uint64_t targetAddress = 0;
+        if ( ref->target() != nullptr )
+          targetAddress = writer->addressOfAtom(ref->target());
+        uint64_t fixupAddress = writer->addressOfAtom(ai->first) + offset;
+        // apply the relocation
+        writer->kindHandler()->applyFixup(ref->kind(), ref->addend(),
+                                                &atomContent[offset],
+                                                fixupAddress,
+                                                targetAddress);
+      }
+    }
+  }
+
+  /// Atom Iterators
+  typedef typename std::vector<std::pair<const Atom *, 
+          std::pair<int64_t, int64_t>>>::iterator atom_iter;
+
+  atom_iter atoms_begin() { return _atoms.begin(); }
+
+  atom_iter atoms_end() { return _atoms.end(); }
+
 protected:
-  uint64_t                                _link;
-  uint64_t                                _shinfo;
-  uint16_t                                _entsize;
-  StringRef                               _segmentName;
-  StringRef                               _sectionName;
-  const WriterOptionsELF                 &_options;
-  ELFWriter<target_endianness, is64Bits> &_writer;
-  uint64_t                                _flags;
-  uint64_t                                _type;
-  uint64_t                                _offsetInStringTable;
-};
+  int32_t _contentType;
+  int32_t _contentPermissions;
+  Kind    _sectionKind;
+  // An Atom is appended to the vector with the following fields
+  // field1 : Atom
+  // field2 : fileoffset (initially set with a base offset of 0)
+  // field3 : virtual address
+  std::vector<std::pair<const Atom *, std::pair<int64_t, int64_t>>> _atoms;
+  ELFLayout::SegmentType _segmentType;
+  int64_t _entsize;
+  int64_t _shinfo;
+  int64_t _link;
+};  
 
+/// \brief A MergedSection 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<support::endianness target_endianness, bool is64Bits>
-bool IsBss(const  Chunk<target_endianness, is64Bits> *A) {
-  if (auto X = llvm::dyn_cast<SectionChunk<target_endianness, is64Bits>>(A)) 
-    return X->type() != ELF::SHT_NOBITS;
-  llvm_unreachable("Call to a non section type chunk");
-  // adding a non-reachable return bool for making compiler happy
-  return false;
-}
+class MergedSection {
+public:
+  MergedSection(StringRef name) : _name(name) {
+    _hasSegment = false;
+    _ordinal = 0; 
+    _flags = 0; 
+    _size = 0; 
+    _memsize = 0; 
+    _fileOffset = 0; 
+    _startAddr = 0; 
+    _shinfo = 0; 
+    _entsize = 0; 
+    _link = 0; 
+    _align2 = 0; 
+    _kind = 0; 
+    _type = 0; 
+  }
+                                  
+  // Set the MergedSection is associated with a segment
+  void setHasSegment() { _hasSegment = true; }
 
-/// \brief Return  pointer to a defined atom whose name is specified as parameter 
-///        if present in the specified section.
-///        When all the atoms are resolved, get addresses and offsets, we 
-///        have atoms with unique names. Only then this routine is guaranteed 
-///        to return the atom of interest. This routine is useful in finding atoms 
-///        which are special such as entry point to a file 
-template<support::endianness target_endianness, bool is64Bits>
-static const DefinedAtom* findDefinedAtomByName(StringRef name,
-                                          StockSectionChunk<target_endianness, 
-                                                            is64Bits> *sec) {
-  ArrayRef<AtomInfo> atoms = sec->atoms();
-  for (auto ai = atoms.begin(); ai != atoms.end(); ai++) {
-    if ((std::get<0>(*ai))->name() == name )
-      return std::get<0>(*ai);
+  // Sets the ordinal 
+  void setOrdinal(int64_t ordinal) {
+    ordinal = ordinal;
   }
-  return nullptr;
-}
 
-/// \brief A StockSectionChunk is a section created by linker with all 
-///        attributes concluded from the defined atom contained within.
-template<support::endianness target_endianness, bool is64Bits>
-class StockSectionChunk : public SectionChunk<target_endianness, is64Bits> {
-public:
-  virtual StringRef segmentName() const { return this->_segmentName; }
-  void                appendAtom(const DefinedAtom*);
-  virtual void        write(uint8_t *filebuffer);
-  const               ArrayRef<AtomInfo> atoms() const;
-  StockSectionChunk(StringRef sectionName, bool loadable,
-                    DefinedAtom::ContentType type, 
-                    const WriterOptionsELF &options,
-                    ELFWriter<target_endianness, is64Bits> &writer);
+  // Sets the Memory size 
+  void setMemSize(int64_t memsz) { 
+    _memsize = memsz;
+  }
+
+  // Sets the size fo the merged Section
+  void setSize(int64_t fsiz) {
+    _size = fsiz;
+  }
+
+  // The offset of the first section contained in the merged section
+  // is contained here
+  void setFileOffset(int64_t foffset) {
+    _fileOffset = foffset;
+  }
+
+  // Sets the starting address of the section
+  void setAddr(int64_t addr) {
+    _startAddr = addr;
+  }
+
+  // Appends a section into the list of sections that are part of this Merged
+  // Section
+  void appendSection(Chunk<target_endianness, is64Bits> *c) {
+    Section<target_endianness, is64Bits> *section;
+    if (c->align2() > _align2) 
+      _align2 = c->align2();
+    if (c->kind() == Chunk<target_endianness, is64Bits>::Section) {
+      section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(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<target_endianness, is64Bits> *>::iterator 
+                                                                     chunk_iter;
+
+  chunk_iter begin_sections() { return _sections.begin(); }
+
+  chunk_iter end_sections() { return _sections.end(); }
+
+  // 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; }
+
+  int64_t align2() const { return _align2; }
+
+  int64_t link() const { return _link; }
+
+  int64_t type() const { return _type; }
+
+  int64_t startAddr() const { return _startAddr; }
+
+  int64_t ordinal() const { return _ordinal; }
+
+  int64_t kind() const { return _kind; }
+
+  int64_t filesize() const { return _size; }
+
+  int64_t entsize() const { return _entsize; }
+
+  int64_t fileOffset() const { return _fileOffset; }
+
+  int64_t flags() const { return _flags; }
+
+  int64_t memsize() { return _memsize; }
+
 private:
-  std::vector<AtomInfo>                   _atoms;
+  StringRef _name;
+  bool _hasSegment;
+  int64_t _ordinal;
+  int64_t _flags;
+  int64_t _size;
+  int64_t _memsize;
+  int64_t _fileOffset;
+  int64_t _startAddr;
+  int64_t _shinfo;
+  int64_t _entsize;
+  int64_t _link;
+  int64_t _align2;
+  int64_t _kind;
+  int64_t _type;
+  std::vector<Chunk<target_endianness, is64Bits> *> _sections;
 };
-                        
-/// \brief An ELFHeaderChunk represents the Elf[32/64]_Ehdr structure at the
-///        start of an ELF executable file.
+
+/// \brief A segment can be divided into segment slices 
+///        depending on how the segments can be split 
 template<support::endianness target_endianness, bool is64Bits>
-class ELFHeaderChunk : public Chunk<target_endianness, is64Bits> {
+class SegmentSlice {
 public:
-  LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
-  typedef object::Elf_Ehdr_Impl<target_endianness, is64Bits> Elf_Ehdr;
+  typedef typename std::vector<Chunk<target_endianness, is64Bits> *>::iterator 
+                                                                    chunk_iter;
 
-  ELFHeaderChunk(const WriterOptionsELF &options,
-                 const File &file);
+  SegmentSlice() { }
 
-  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(uint64_t entry)         { _eh.e_entry = entry; }
-  void e_phoff(uint64_t phoff)         { _eh.e_phoff = phoff; }
-  void e_shoff(uint64_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  size()                     { return sizeof (Elf_Ehdr); }
+  // Set the segment slice so that it begins at the offset specified
+  // by fileoffset and set the start of the slice to be s and the end 
+  // of the slice to be e
+  void set(int64_t fileoffset, int32_t s, int e) {
+    _startChunk = s;
+    _endChunk = e;
+    _offset = fileoffset;
+  }
 
-  virtual StringRef   segmentName() const;
-  virtual void        write(uint8_t *fileBuffer);
-  virtual const char *info();
-  static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
-    return c->getChunkKind() ==  Chunk<target_endianness, is64Bits>::Kind
-                                                                   ::Header;
+  // Set the segment slice start and end iterators
+  // This is used to walk through the sections that are part of the 
+  // Segment slice
+  void setChunks(chunk_iter start, chunk_iter end) {
+    startChunkIter = start;
+    endChunkIter = end;
   }
+
+  // Return the fileOffset of the slice
+  int64_t fileOffset() const { return _offset; }
+
+  // Return the size of the slice
+  int64_t fileSize() const { return _size; }
+
+  // Return the start of the slice
+  int32_t startChunk() const { return _startChunk; }
+
+  // Return the start address of the slice
+  int64_t startAddr() const { return _addr; }
+
+  // Return the memory size of the slice
+  int64_t memsize() const { return _memsize; }
+
+  // Return the alignment of the slice
+  int64_t align2() const { return _align2; }
+
+  void setSize(int64_t sz) { _size = sz; }
+
+  void setMemSize(int64_t memsz) { _memsize = memsz; }
+
+  void setStart(int64_t addr) { _addr = addr; }
+
+  void setAlign(int64_t align) { _align2 = align; }
+
+  static bool compare_slices(SegmentSlice<target_endianness, is64Bits> *a, 
+                             SegmentSlice<target_endianness, is64Bits> *b) {
+    return (a->startChunk() < b->startChunk());
+  }
+
+  // Functions to run through the slice
+  chunk_iter chunks_begin() { return startChunkIter; }
+
+  chunk_iter chunks_end() { return endChunkIter; }
+
 private:
-  Elf_Ehdr             _eh;
+  int32_t _startChunk;
+  int32_t _endChunk;
+  chunk_iter startChunkIter;
+  chunk_iter endChunkIter;
+  int64_t _addr;
+  int64_t _offset;
+  int64_t _size;
+  int64_t _align2;
+  int64_t _memsize;
 };
 
-/// \brief An ELFSectionHeaderChunk represents the Elf[32/64]_Shdr structure
-///        that is placed right after the ELFHeader.
-///
+/// \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<support::endianness target_endianness, bool is64Bits>
-class ELFSectionHeaderChunk : public Chunk<target_endianness, is64Bits> {
+class Segment : public Chunk<target_endianness, is64Bits> {
 public:
-  LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
-  typedef object::Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
-  ELFSectionHeaderChunk(const WriterOptionsELF &Options,
-                        ELFWriter<target_endianness, is64Bits>&);
-  void createHeaders();
-  virtual StringRef   segmentName() const;
-  virtual void        write(uint8_t *filebuffer);
-  virtual const char *info();
-  void                computeSize();
-  uint16_t            count();
-  uint16_t            size();
-  void                fixOffsets();
-  const ArrayRef<Elf_Shdr*> sectionInfo() {
-    return _sectionInfo;
+  typedef typename std::vector
+       <SegmentSlice<target_endianness, is64Bits> *>::iterator slice_iter;
+  typedef typename 
+        std::vector<Chunk<target_endianness, is64Bits> *>::iterator chunk_iter;
+
+  Segment(const StringRef name,
+          const ELFLayout::SegmentType type,
+          const WriterOptionsELF &options):
+                                  Chunk<target_endianness, is64Bits>(name,
+                                  Chunk<target_endianness, is64Bits>::Segment),
+                                  _options(options) {
+    _segmentType = type;
+    _flags = 0;
+    _atomflags = 0;
+    this->_align2 = 0;
+    this->_fsize = 0;
   }
+
+  // append a section to a segment
+  void append(Section<target_endianness, is64Bits> *section) {
+    _chunks.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();
+    }
+  }
+
+  /// 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 compare_segments(Chunk<target_endianness, is64Bits> *a, 
+                               Chunk<target_endianness, is64Bits> *b)
+  {
+
+    Segment<target_endianness, is64Bits> *sega = 
+      llvm::dyn_cast<Segment<target_endianness, is64Bits>>(a);
+    Segment<target_endianness, is64Bits> *segb = 
+      llvm::dyn_cast<Segment<target_endianness, is64Bits>>(b);
+    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
+  void assignOffset(int64_t startOffset) {
+    int startChunk = 0;
+    int currChunk = 0;
+    chunk_iter startChunkIter, endChunkIter;
+    // slice align is set to the max alignment of the chunks that are 
+    // contained in the slice
+    int64_t sliceAlign = 0;
+    // Current slice size
+    int64_t curSliceSize = 0;
+    // Current Slice File Offset
+    int64_t curSliceFileOffset = 0;
+
+    Section<target_endianness, is64Bits> *section;
+    startChunkIter = _chunks.begin();
+    endChunkIter = _chunks.end();
+    startChunk = currChunk;
+    bool isFirstSection = true;
+    for (auto ci = _chunks.begin(); ci != _chunks.end(); ++ci) {
+      section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(*ci);
+      if (isFirstSection) {
+        // align the startOffset to the section alignment
+        int64_t newOffset = Chunk<target_endianness, is64Bits>::alignTo
+                            (startOffset, section->align2());
+        curSliceFileOffset = newOffset;
+        sliceAlign = section->align2();
+        this->setFileOffset(startOffset);
+        section->setFileOffset(newOffset);
+        curSliceSize = section->filesize();
+        isFirstSection = false;
+      } else {
+        uint64_t curOffset = curSliceFileOffset + curSliceSize;
+        uint64_t newOffset = Chunk<target_endianness, is64Bits>::alignTo
+                            (curOffset, section->align2());
+        SegmentSlice<target_endianness, is64Bits> *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()) {
+          for (auto sei = slices_begin(); sei != slices_end(); ++sei) {
+            if ((*sei)->startChunk() == startChunk) {
+              slice = *sei;
+              break;
+            }
+          }
+          if (!slice) {
+            slice = new SegmentSlice<target_endianness, is64Bits>();
+            _segmentSlices.push_back(slice);
+          }
+          slice->set(curSliceFileOffset, startChunk, currChunk);
+          slice->setChunks(startChunkIter, endChunkIter);
+          slice->setSize(curSliceSize);
+          slice->setAlign(sliceAlign);
+          int64_t newPageOffset = Chunk<target_endianness, is64Bits>::alignTo
+                           (curOffset, _options.pageSize());
+          newOffset = Chunk<target_endianness, is64Bits>::alignTo
+                            (newPageOffset, section->align2());
+          curSliceFileOffset = newOffset;
+          startChunkIter = endChunkIter;
+          startChunk = currChunk;
+          section->setFileOffset(curSliceFileOffset);
+          curSliceSize = newOffset - curSliceFileOffset + section->filesize();
+          sliceAlign = section->align2();
+        }
+        else {
+          if (sliceAlign < section->align2())
+            sliceAlign = section->align2();
+          section->setFileOffset(newOffset);
+          curSliceSize = newOffset - curSliceFileOffset + section->filesize();
+        }
+      }
+      currChunk++;
+      endChunkIter = ci;
+    }
+    SegmentSlice<target_endianness, is64Bits> *slice = nullptr;
+    for (auto sei = slices_begin(); sei != slices_end(); ++sei) {
+      if ((*sei)->startChunk() == startChunk) {
+        slice = *sei;
+        break;
+      }
+    }
+    if (!slice) {
+      slice = new SegmentSlice<target_endianness, is64Bits>();
+      _segmentSlices.push_back(slice);
+    }
+    slice->set(curSliceFileOffset, startChunk, currChunk);
+    slice->setChunks(startChunkIter, _chunks.end());
+    slice->setSize(curSliceSize);
+    slice->setAlign(sliceAlign);
+    this->_fsize = curSliceFileOffset - startOffset + curSliceSize;
+    std::stable_sort(slices_begin(), slices_end(), 
+                     SegmentSlice<target_endianness, is64Bits>::compare_slices);
+  }
+
+  /// \brief Assign virtual addresses to the slices
+  void assignVirtualAddress(int64_t &addr, bool isFirstSegment) {
+    Section<target_endianness, is64Bits> *section;
+    for (auto sei = slices_begin(); sei != slices_end(); ++sei) {
+      bool firstSlice = (sei == slices_begin());
+      // The first segment has distinct since it contains the 
+      // ELF header and the Program Header, if we get to the first segment
+      // and the first slice, set it to the baseaddress
+      // which is the segment address
+      if (isFirstSegment && firstSlice) {
+        (*sei)->setStart(this->startAddr());
+      }
+      else {
+        // Align to a page
+        addr = Chunk<target_endianness, is64Bits>::alignTo(addr, 
+                                                           _options.pageSize());
+        // Align to the slice alignment
+        addr = Chunk<target_endianness, is64Bits>::alignTo(addr, 
+                                                           (*sei)->align2());
+      }
+      bool startAddressSet = false;
+      for (auto ci = (*sei)->chunks_begin(); ci != (*sei)->chunks_end(); ++ci) {
+        section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(*ci);
+        // Align the section address
+        addr = Chunk<target_endianness, is64Bits>::alignTo(addr, 
+                                                           section->align2());
+        if (!isFirstSegment && !startAddressSet) {
+          (*sei)->setStart(addr);
+          startAddressSet = true;
+        }
+        section->setStart(addr);
+        section->assignVirtualAddress(addr);
+        section->setMemSize(addr - section->startAddr());
+      }
+      (*sei)->setMemSize(addr - (*sei)->startAddr());
+    }
+  }
+
+  slice_iter slices_begin() {
+    return _segmentSlices.begin();
+  }
+
+  slice_iter slices_end() {
+    return _segmentSlices.end();
+  }
+
+  // Write the Segment 
+  void write(ELFWriter *writer, OwningPtr<FileOutputBuffer> &buffer) {
+    for (auto sei = slices_begin(); sei != slices_end(); ++sei) {
+      for (auto ci = (*sei)->chunks_begin(); ci != (*sei)->chunks_end(); ++ci) {
+        (*ci)->write(writer, buffer);
+      }
+    }
+  }
+
+  // Finalize the segment, before we want to write to the output file
+  void finalize() { }
+
+  // For LLVM RTTI 
+  static inline bool classof(Segment<target_endianness, is64Bits> *s) {
+    return true;
+  }
+
   static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
-    return c->getChunkKind() ==  Chunk<target_endianness, is64Bits>::Kind
-                                                                   ::Header;
+    return c->kind() == Chunk<target_endianness, is64Bits>::Segment;
   }
 
+  // Getters
+  int32_t sectionCount() const {
+    return _chunks.size();
+  }
+
+  ELFLayout::SegmentType segmentType() { return _segmentType; }
+
+  int pgsz() 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:
-  const WriterOptionsELF                 &_options;
-  ELFWriter<target_endianness, is64Bits> &_writer;
-  llvm::BumpPtrAllocator                  _sectionAllocate;
-  std::vector<Elf_Shdr*>                  _sectionInfo;
+  std::vector<Chunk<target_endianness, is64Bits> *> _chunks;
+  std::vector<SegmentSlice<target_endianness, is64Bits> *> _segmentSlices;
+  ELFLayout::SegmentType _segmentType;
+  int64_t _flags;
+  int64_t _atomflags;
+  const WriterOptionsELF _options;
 };
 
-/// \brief Represents the shstr section.
-///
-/// This is a contiguous memory that has all the symbol strings each ending with
-/// null character. We might need more than one such chunks shstrtab for setting
-/// e_shstrndx in ELHHeaderChunk and strtab for use with symtab
+/// \brief The class represents the ELF String Table
 template<support::endianness target_endianness, bool is64Bits>
-class ELFStringSectionChunk : public SectionChunk<target_endianness, is64Bits> {
+class ELFStringTable : public Section<target_endianness, is64Bits> {
+
 public:
-  ELFStringSectionChunk(const WriterOptionsELF &Options,
-                        ELFWriter<target_endianness, is64Bits> &writer,
-                        StringRef secName);
-  virtual StringRef   segmentName() const { return this->_segmentName; }
-  uint64_t            addString(StringRef symName);
-  const char          *info();
-  virtual void        write(uint8_t *filebuffer);
+  ELFStringTable(const char *str, 
+                 int32_t order): 
+                            Section<target_endianness, is64Bits>(str,
+                                                         llvm::ELF::SHT_STRTAB,
+                                                         DefinedAtom::perm___,
+                                                         order,
+                            Section<target_endianness, is64Bits>::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(ELFStringTable<target_endianness, is64Bits> *s) {
+    return true;
+  }
+
+  static inline bool classof(const Section<target_endianness, is64Bits> *c) {
+    return c->kind() == Section<target_endianness, is64Bits>::StringTable;
+  }
+
+  static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
+    return c->kind() == Section<target_endianness, is64Bits>::StringTable;
+  }
+
+  int64_t addString(const StringRef symname) {
+    _strings.push_back(symname);
+    int64_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.begin(); si != _strings.end(); ++si) {
+      memcpy(dest, si->data(), si->size());
+      dest += si->size();
+      memcpy(dest, "", 1);
+      dest += 1;
+    }
+  }
+
+  void finalize() { }
+
 private:
-  std::vector<StringRef> _stringSection;
+  std::vector<StringRef> _strings;
 };
 
-/// \brief Represents the symtab section
-/// 
-/// ELFSymbolTableChunk represents the Symbol table as per ELF ABI
-/// This is a table with Elf[32/64]_Sym entries in it. 
+/// \brief The ELFSymbolTable class represents the symbol table in a ELF file 
 template<support::endianness target_endianness, bool is64Bits>
-class ELFSymbolTableChunk : public SectionChunk<target_endianness, is64Bits> {
+class ELFSymbolTable : public Section<target_endianness, is64Bits> {
+
 public:
   typedef object::Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
-  ELFSymbolTableChunk(const WriterOptionsELF &options,
-                      ELFWriter<target_endianness, is64Bits> &writer,
-                      StringRef secName);
-  virtual StringRef   segmentName() const { return this->_segmentName; }
-  void                addSymbol(const Atom *a, uint16_t shndx);
-  void                addSymbol(Elf_Sym *x); 
-  void                fixSymbolValue(); 
-  const char          *info();
-  void                setAttributes();
-  virtual void               write(uint8_t *fileBuffer);
 
+  ELFSymbolTable(const char *str,
+                 int32_t order):
+                              Section<target_endianness, is64Bits>(str,
+                                                      llvm::ELF::SHT_SYMTAB,
+                                                      0,
+                                                      order,
+                              Section<target_endianness, is64Bits>::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(ELFSymbolTable<target_endianness, is64Bits> *s) {
+    return true;
+  }
+
+  static inline bool classof(const Section<target_endianness, is64Bits> *c) {
+    return c->kind() == Section<target_endianness, is64Bits>::SymbolTable;
+  }
+
+  static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
+    return c->kind() == Section<target_endianness, is64Bits>::SymbolTable;
+  }
+
+  void addSymbol(const Atom *a, int32_t shndx, int64_t addr=0) {
+    Elf_Sym *symbol = new(_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
+    unsigned char b = 0, t = 0;
+    symbol->st_name = _stringSection->addString(a->name());
+    symbol->st_size = 0;
+    symbol->st_shndx = shndx;
+    symbol->st_value = 0;
+    symbol->st_other = ELF::STV_DEFAULT;
+    if (const DefinedAtom *da = llvm::dyn_cast<const DefinedAtom>(a)){
+      symbol->st_size = da->size();
+      lld::DefinedAtom::ContentType ct;
+      switch (ct = da->contentType()){
+        case  DefinedAtom::typeCode:
+          // TODO: add offset
+          symbol->st_value = addr;
+          t = ELF::STT_FUNC;
+          break;
+        case  DefinedAtom::typeData:
+          // TODO: add offset
+          symbol->st_value = addr;
+          t = ELF::STT_OBJECT;
+          break;
+        case  DefinedAtom::typeZeroFill:
+          t = ELF::STT_COMMON;
+          symbol->st_value = addr;
+          break;
+        default:
+          t = ELF::STT_NOTYPE;
+      }
+      if (da->scope() == DefinedAtom::scopeTranslationUnit)  
+        b = ELF::STB_LOCAL;
+      else
+        b = ELF::STB_GLOBAL;
+    } else if (const AbsoluteAtom *aa = llvm::dyn_cast<const AbsoluteAtom>(a)){
+      t = ELF::STT_OBJECT;
+      symbol->st_shndx = ELF::SHN_ABS;
+      switch (aa->scope()) {
+      case AbsoluteAtom::scopeLinkageUnit:
+        symbol->st_other = ELF::STV_HIDDEN;
+        b = ELF::STB_LOCAL;
+        break;
+      case AbsoluteAtom::scopeTranslationUnit:
+        b = ELF::STB_LOCAL;
+        break;
+      case AbsoluteAtom::scopeGlobal:
+        b = ELF::STB_GLOBAL;
+        break;
+      }
+      symbol->st_value = aa->value();
+    } 
+    else {
+     symbol->st_value = 0;
+     t = ELF::STT_NOTYPE;
+     b = ELF::STB_WEAK;
+    }
+    symbol->setBindingAndType(b, t);
+    _symbolTable.push_back(symbol);
+    this->_fsize += sizeof(Elf_Sym);
+  }
+
+  void setStringSection(ELFStringTable<target_endianness, is64Bits> *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) -> bool {
+                     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.begin(); sti != _symbolTable.end(); ++sti) {
+      memcpy(dest, (*sti), sizeof(Elf_Sym));
+      dest += sizeof(Elf_Sym);
+    }
+  }
+
 private:
+  ELFStringTable<target_endianness, is64Bits> *_stringSection;
   std::vector<Elf_Sym*> _symbolTable;
-  ELFStringSectionChunk<target_endianness, is64Bits> *_stringSection;
   llvm::BumpPtrAllocator _symbolAllocate;
-  std::map<Elf_Sym*, const Atom*> _symbolToAtom;
+  int64_t _link;
 };
 
-/// \brief  ELFProgramHeaderChunk represents the Elf[32/64]_Phdr structure near
-/// the start of an ELF executable file. ELFHeader's e_phentsize and e_phnum 
-/// show the number of entries in table and size of each one.
+/// \brief An ELFHeader represents the Elf[32/64]_Ehdr structure at the
+///        start of an ELF executable file.
 template<support::endianness target_endianness, bool is64Bits>
-class ELFProgramHeaderChunk : public Chunk<target_endianness, is64Bits> {
+class ELFHeader : public Chunk<target_endianness, is64Bits> {
 public:
-  LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
-  typedef object::Elf_Phdr<target_endianness, is64Bits> Elf_Phdr;
-  ELFProgramHeaderChunk(const WriterOptionsELF &options, 
-                        ELFWriter<target_endianness, is64Bits> &);
+  typedef object::Elf_Ehdr_Impl<target_endianness, is64Bits> Elf_Ehdr;
 
-  virtual StringRef   segmentName() const;
-  virtual void        write(uint8_t *filebuffer);
-  virtual const char *info();
-  void                createPHeaders();
-  uint64_t            computeNumber();
+  ELFHeader():Chunk<target_endianness, is64Bits>("elfhdr",
+                     Chunk<target_endianness, is64Bits>::ELFHeader)
+  {
+    for (int i=0; i < llvm::ELF::EI_NIDENT; ++i) 
+      e_ident(i, 0);
+    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; }
+  int64_t  filesize()                 { return sizeof (Elf_Ehdr); }
+
   static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
-    return c->getChunkKind() ==  Chunk<target_endianness, is64Bits>::Kind
-                                                                   ::Header;
+    return c->Kind() ==  Chunk<target_endianness, is64Bits>::Header;
   }
 
-private:
-  typedef typename std::vector<SectionChunk<target_endianness, is64Bits>*>
-                    ::iterator secIterator;
-  const WriterOptionsELF                 &_options;
-  ELFWriter<target_endianness, is64Bits> &_writer;
-  std::vector<Elf_Phdr*>                 _programHeaders;
-  llvm::BumpPtrAllocator                 _headerAllocate;
-  typedef std::pair<uint64_t, uint64_t>  sectionRange; 
-  std::vector<sectionRange>              _segments;
-  std::map<uint16_t, uint16_t>           _groupToPF;
+  void write(ELFWriter *writer, 
+             OwningPtr<FileOutputBuffer> &buffer) {
 
-};
+    uint8_t *chunkBuffer = buffer->getBufferStart();
+    uint8_t *atomContent = chunkBuffer + this->fileOffset();
+    memcpy(atomContent, &_eh, filesize());
+  }
 
-//===----------------------------------------------------------------------===//
-//  Chunk
-//===----------------------------------------------------------------------===//
+  void finalize() { }
 
-template<support::endianness target_endianness, bool is64Bits>
-Chunk<target_endianness, is64Bits>::Chunk(){
-  this->init();
-}
+private:
+  Elf_Ehdr             _eh;
+};
 
+/// \brief An ELFProgramHeader represents the Elf[32/64]_Phdr structure at the
+///        start of an ELF executable file.
 template<support::endianness target_endianness, bool is64Bits>
-void Chunk<target_endianness, is64Bits>::init(){
-  this->_size = 0; 
-  this->_address = 0; 
-  this->_fileOffset = 0; 
-  this->_align2 = 0; 
-  this->_group = CG_INVALID; 
-  this->_isLoadable = false;
-   // 0 and 1 are reserved. 0 for ELF header and 1 for program  header.
-  static uint64_t orderNumber = 0;
-  _ordinal = orderNumber++;
-}
+class ELFProgramHeader : public Chunk<target_endianness, is64Bits> {
+public:
+  typedef object::Elf_Phdr<target_endianness, is64Bits> Elf_Phdr;
 
-template<support::endianness target_endianness, bool is64Bits>
-bool Chunk<target_endianness, is64Bits>::occupiesNoDiskSpace() {
-  return false;
-}
+  ELFProgramHeader():Chunk<target_endianness, is64Bits>("elfphdr",
+                     Chunk<target_endianness, is64Bits>::ProgramHeader)
+  {
+  }
 
-template<support::endianness target_endianness, bool is64Bits>
-uint64_t Chunk<target_endianness, is64Bits>::size() const {
-  return _size;
-}
+  bool addSegment(Segment<target_endianness, is64Bits> *segment) {
+    Elf_Phdr *phdr = nullptr;
+    bool ret = false;
 
-template<support::endianness target_endianness, bool is64Bits>
-uint64_t Chunk<target_endianness, is64Bits>::align2() const {
-  return _align2;
-}
+    for (auto sei = segment->slices_begin(); sei != segment->slices_end(); 
+         ++sei) {
+      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 = (*sei)->fileOffset();
+      phdr->p_vaddr = (*sei)->startAddr();
+      phdr->p_paddr = (*sei)->startAddr();
+      phdr->p_filesz = (*sei)->fileSize();
+      phdr->p_memsz = (*sei)->memsize();
+      phdr->p_flags = segment->flags();
+      phdr->p_align = (phdr->p_type == llvm::ELF::PT_LOAD) ? 
+                       segment->pgsz() : (*sei)->align2();
+    }
+    return ret;
+  }
 
-template<support::endianness target_endianness, bool is64Bits>
-uint64_t Chunk<target_endianness, is64Bits>::address() const {
-  return _address;
-}
+  void resetProgramHeaders() {
+    _phi = _ph.begin();    
+  }
 
-template<support::endianness target_endianness, bool is64Bits>
-uint64_t Chunk<target_endianness, is64Bits>::fileOffset() const {
-  return _fileOffset;
-}
+  void setStart(int64_t addr) {
+    this->_start = Chunk<target_endianness, is64Bits>::alignTo(addr, 8);
+    this->_fsize = this->_start - addr;
+  }
 
-template<support::endianness target_endianness, bool is64Bits>
-uint64_t Chunk<target_endianness, is64Bits>::
-         alignTo(uint64_t value, uint8_t align2) {
-  uint64_t align = 1 << align2;
-  return (value + (align - 1)) & (-align);
-}
+  int64_t  filesize() { return this->_fsize + (sizeof (Elf_Phdr) * _ph.size()); }
 
-template<support::endianness target_endianness, bool is64Bits>
-void Chunk<target_endianness, is64Bits>::
-     assignFileOffset(uint64_t &curOffset, uint64_t &curAddress) {
-  if (occupiesNoDiskSpace()) {
-    // FileOffset does not change, but virtual address does change.
-    uint64_t alignedAddress =
-      alignTo(curAddress, _align2 ? static_cast<uint8_t>(llvm::Log2_64(_align2))
-                                  : 0);
-    _address = alignedAddress;
-    curAddress = alignedAddress + _size;
-  } else {
-    // FileOffset and address both move by _size amount after alignment.
-    uint64_t alignPadding =
-      alignTo(curAddress, _align2 ? static_cast<uint8_t>(llvm::Log2_64(_align2))
-                                  : 0) - curAddress;
-    _fileOffset = curOffset + alignPadding;
-    _address    = curAddress + alignPadding;
-    curOffset   = _fileOffset + _size;
-    curAddress  = _address + _size;
+  static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
+    return c->Kind() ==  Chunk<target_endianness, is64Bits>::ProgramHeader;
   }
 
-  DEBUG_WITH_TYPE("WriterELF-layout", dbgs()  
-                      << "   fileOffset="
-                      << format("0x%08X", _fileOffset)
-                      << " address="
-                      << format("0x%016X", _address)
-                      << " info=" << info() << "\n");
-}
+  void write(ELFWriter *writer, 
+             OwningPtr<FileOutputBuffer> &buffer) {
 
-//===----------------------------------------------------------------------===//
-//  SectionChunk
-//===----------------------------------------------------------------------===//
+    uint8_t *chunkBuffer = buffer->getBufferStart();
+    uint8_t *dest = chunkBuffer + this->fileOffset();
+    for (auto phi = _ph.begin(); phi != _ph.end(); ++phi) {
+      memcpy(dest, (*phi), sizeof(Elf_Phdr));
+      dest += sizeof(Elf_Phdr);
+    }
+  }
 
-template<support::endianness target_endianness, bool is64Bits>
-SectionChunk<target_endianness, is64Bits>::
- SectionChunk(StringRef secName, StringRef segName, bool loadable, 
-              uint64_t flags , uint64_t link,  uint64_t info , uint64_t type,
-              uint64_t entsz, const WriterOptionsELF &op, 
-              ELFWriter<target_endianness, is64Bits> &writer)
-  : Chunk<target_endianness, is64Bits>(Chunk<target_endianness, is64Bits>
-                                       ::Kind::Section)
-  , _link(link)
-  , _shinfo(info)
-  , _entsize(entsz)
-  , _segmentName(segName)
-  , _sectionName(secName)
-  , _options(op)
-  , _writer(writer)
-  , _flags(flags)
-  , _type(type)
-  , _offsetInStringTable(0) {
-    this->isLoadable(loadable);
-}
-//FIXME: We need to make decision here for every section created
-template<support::endianness target_endianness, bool is64Bits>
-bool SectionChunk<target_endianness, is64Bits>::occupiesNoDiskSpace() {
-  return false;
-}
+  void finalize() { }
 
-template<support::endianness target_endianness, bool is64Bits>
-const char *SectionChunk<target_endianness, is64Bits>::info() {
-  return _sectionName.data();
-}
+  int64_t entsize() { 
+    return sizeof(Elf_Phdr);
+  }
 
-//===----------------------------------------------------------------------===//
-//  StockSectionChunk
-//===----------------------------------------------------------------------===//
+  int64_t numHeaders() {
+    return _ph.size();
+  }
 
+private:
+  std::vector<Elf_Phdr *> _ph;
+  typedef typename std::vector<Elf_Phdr *>::iterator ph_iter;
+  ph_iter _phi;
+  llvm::BumpPtrAllocator  _allocator;
+};
+
+/// \brief An ELFSectionHeader represents the Elf[32/64]_Shdr structure
+/// at the end of the file
 template<support::endianness target_endianness, bool is64Bits>
-StockSectionChunk<target_endianness, is64Bits>::
-  StockSectionChunk(StringRef secName, bool loadable, 
-                    DefinedAtom::ContentType type,
-                    const WriterOptionsELF &options, 
-                    ELFWriter<target_endianness, is64Bits> &writer)
- : SectionChunk<target_endianness, is64Bits>(secName, "PT_NULL", 
-                                             loadable, 0lu, 0lu, 0u, 0lu, 0lu,
-                                             options, writer) {
-  this->_segmentName = this->_isLoadable ? "PT_LOAD" : "PT_NULL" ;
-  // If the section is custom loadable section, group should be set explicitly.
-  // Stock non loadable section go as NO_LOAD and others  will get their 
-  // group determined by the atoms contained within. Many constant 
-  // sections will have no symbols but the constants are referred as 
-  // offset from start symbol, hence there may not be any defined atoms being 
-  // appended to them, we force them  at time of creation to CG_R
-  this->setGroup(this->isLoadable() ? CG_INVALID : CG_NO_LOAD);
-  switch(type) {
-  case DefinedAtom::typeCode:
-    this->_type        = ELF::SHT_PROGBITS;
-    break;
-  case DefinedAtom::typeData:
-    this->_type        = ELF::SHT_PROGBITS;
-    break;
-  case DefinedAtom::typeZeroFill:
-    this->_type        = ELF::SHT_NOBITS;
-    break;
-  case DefinedAtom::typeConstant:
-    this->_type        = ELF::SHT_PROGBITS;
-    this->_flags       = ELF::SHF_ALLOC;
-    this->setGroup(CG_R);
-    break;
-  default:
-    llvm_unreachable("Unhandled content type for section!");
+class ELFSectionHeader : public Chunk<target_endianness, is64Bits> {
+public:
+  typedef object::Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
+
+  ELFSectionHeader(int32_t order):Chunk<target_endianness, is64Bits>("shdr",
+                                 Chunk<target_endianness, is64Bits>::SectionHeader)
+  {
+    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<support::endianness target_endianness, bool is64Bits>
-const ArrayRef<AtomInfo> StockSectionChunk<target_endianness, is64Bits>::
-    atoms() const {
-  return _atoms;
-}
+  uint16_t filesize() { 
+    return sizeof(Elf_Shdr) * _sectionInfo.size();
+  }
 
-template<support::endianness target_endianness, bool is64Bits>
-void StockSectionChunk<target_endianness, is64Bits>::
-     appendAtom(const DefinedAtom *atom) {
-  static uint16_t groupArray[] = {CG_INVALID, CG_W, CG_R, CG_RW, CG_X,
-                                  CG_WX, CG_RX, CG_RWX};
-  // Figure out offset for atom in this section given alignment constraints.
-  uint64_t offset = this->_size;
-  DefinedAtom::Alignment atomAlign = atom->alignment();
-  uint64_t align2 = 1 << atomAlign.powerOf2;
-  uint64_t requiredModulus = atomAlign.modulus;
-  uint64_t currentModulus = (offset % align2);
-  if (currentModulus != requiredModulus) {
-    if (requiredModulus > currentModulus)
-      offset += requiredModulus - currentModulus;
-    else
-      offset += align2 + requiredModulus - currentModulus;
+  void appendSection(MergedSection<target_endianness, is64Bits> *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->startAddr();
+    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);
   }
-  // Record max alignment of any atom in this section.
-  if (align2 > this->_align2)
-    this->_align2 = align2;
-  // Assign atom to this section with this offset.
-  _atoms.emplace_back(atom, offset);
-  // Update section size to include this atom.
-  this->_size = offset + atom->size();
-  // Update permissions
-  DefinedAtom::ContentPermissions perms = atom->permissions();
- 
-  if ((perms & DefinedAtom::permR__) == DefinedAtom::permR__)
-    this->_flags |= ELF::SHF_ALLOC;
-  if ((perms & DefinedAtom::permRW_) == DefinedAtom::permRW_)
-    this->_flags |= (ELF::SHF_ALLOC | ELF::SHF_WRITE);
-  if ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X)
-    this->_flags |= (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR);
-  if (atom->contentType() == DefinedAtom::typeZeroFill)
-    this->_flags |= (ELF::SHF_ALLOC | ELF::SHF_WRITE);
-  this->setGroup(groupArray[this->_flags]);
-}
 
-template<support::endianness target_endianness, bool is64Bits>
-void StockSectionChunk<target_endianness, is64Bits>
-                      ::write(uint8_t *chunkBuffer) {
-  // Each section's content is just its atoms' content.
-  for (const auto &ai : _atoms ) {
-    // Copy raw content of atom to file buffer.
-   ArrayRef<uint8_t> content = std::get<0>(ai)->rawContent();
-   uint64_t contentSize = content.size();
-   if (contentSize == 0)
-     continue;
-   uint8_t *atomContent = chunkBuffer + std::get<1>(ai);
-   std::copy_n(content.data(), contentSize, atomContent);
+  void updateSection(Section<target_endianness, is64Bits> *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->startAddr();
+    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();
+  }
 
-  for (const Reference *ref : *std::get<0>(ai)){
-    uint32_t offset = ref->offsetInAtom();
-    uint64_t targetAddress = 0;
+  static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
+    return c->getChunkKind() ==  Chunk<target_endianness, is64Bits>::SectionHeader;
+  }
 
-    if ( ref->target() != nullptr )
-      targetAddress = this->_writer.addressOfAtom(ref->target());
+  void setStringSection(ELFStringTable<target_endianness, is64Bits> *s) {
+    _stringSection = s;
+  }
 
-    uint64_t fixupAddress = this->_writer.addressOfAtom(std::get<0>(ai)) +
-                            offset;
-    this->_writer.kindHandler()->applyFixup(ref->kind(), ref->addend(),
-                                            &atomContent[offset],
-                                            fixupAddress,
-                                            targetAddress);
+  void write(ELFWriter *writer, 
+             OwningPtr<FileOutputBuffer> &buffer) {
+
+    uint8_t *chunkBuffer = buffer->getBufferStart();
+    uint8_t *dest = chunkBuffer + this->fileOffset();
+    for (auto shi = _sectionInfo.begin(); shi != _sectionInfo.end(); ++shi) {
+      memcpy(dest, (*shi), sizeof(Elf_Shdr));
+      dest += sizeof(Elf_Shdr);
     }
+    _stringSection->write(writer, buffer);
   }
-}
 
-//===----------------------------------------------------------------------===//
-//  ELFStringSectionChunk
-//===----------------------------------------------------------------------===//
-template<support::endianness target_endianness, bool is64Bits>
-ELFStringSectionChunk<target_endianness, is64Bits>::
-    ELFStringSectionChunk(const WriterOptionsELF &options,
-                          ELFWriter<target_endianness, is64Bits> &writer, 
-                          StringRef secName) 
-  : SectionChunk<target_endianness, is64Bits>(secName, "PT_NULL", 
-                                              false, 0lu, 0lu, 0lu, 
-                                              ELF::SHT_STRTAB, 0lu, options, 
-                                              writer) {
-  // First Add a null character. It also occupies 1 byte
-  _stringSection.emplace_back("");
-  this->_size = 1;
-  this->setGroup(CG_NO_LOAD);
-}
+  void finalize() { }
 
-template<support::endianness target_endianness, bool is64Bits>
-uint64_t ELFStringSectionChunk<target_endianness, is64Bits>::
-         addString(StringRef symName) {
-  _stringSection.emplace_back(symName);
-  uint64_t offset = this->_size;
-  this->_size += symName.size() + 1;
+  int64_t entsize() { 
+    return sizeof(Elf_Shdr);
+  }
 
-  return offset;
-}
-
-// We need to unwrap the _stringSection and then make one large memory 
-// chunk of null terminated strings
-template<support::endianness target_endianness, bool is64Bits>
-void ELFStringSectionChunk<target_endianness, is64Bits>::
-     write(uint8_t *chunkBuffer) {
-  uint64_t chunkOffset = 0;
- 
-  for (auto it : _stringSection) {
-    ::memcpy(chunkBuffer + chunkOffset, it.data(), it.size());
-    chunkOffset += it.size();
-    ::memcpy(chunkBuffer + chunkOffset, "", 1);
-    chunkOffset += 1;
+  int64_t numHeaders() {
+    return _sectionInfo.size();
   }
-}
 
+private:
+  ELFStringTable<target_endianness, is64Bits> *_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<support::endianness target_endianness, bool is64Bits>
-const char *ELFStringSectionChunk<target_endianness, is64Bits>::info() {
-  return "String Table";
-}
+class DefaultELFLayout : public ELFLayout {
+public:
 
-//===----------------------------------------------------------------------===//
-//  ELFSymbolTableChunk
-//===----------------------------------------------------------------------===//
-template< support::endianness target_endianness, bool is64Bits>
-ELFSymbolTableChunk<target_endianness, is64Bits>::ELFSymbolTableChunk
-                    (const WriterOptionsELF &options, 
-                     ELFWriter<target_endianness, is64Bits> &writer, 
-                     StringRef secName)
-  : SectionChunk<target_endianness, is64Bits>(secName, StringRef("PT_NULL"), 
-                                              false, 0, 0, 0, ELF::SHT_SYMTAB,
-                                              sizeof(Elf_Sym), options, writer)
-{
-  _stringSection = this->_writer.strtab();
-  Elf_Sym *symbol = new (_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
-  memset ((void *)symbol,0, sizeof(Elf_Sym));
-  _symbolTable.push_back(symbol);
-  this->_link = 0;
-  this->_entsize = sizeof(Elf_Sym);
-  this->_size = sizeof(Elf_Sym);
-  this->_align2 = this->_options.pointerWidth();
-  this->setGroup(CG_NO_LOAD);
-}
+  // 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_DYNAMIC,
+    ORDER_GOT,
+    ORDER_GOT_PLT,
+    ORDER_DATA,
+    ORDER_BSS,
+    ORDER_OTHER,
+    ORDER_SECTION_STRINGS,
+    ORDER_SYMBOL_TABLE,
+    ORDER_STRING_TABLE,
+    ORDER_SECTION_HEADERS
+  };
 
-template< support::endianness target_endianness, bool is64Bits>
-void ELFSymbolTableChunk<target_endianness, is64Bits>::fixSymbolValue(){
-  for (auto sym : _symbolTable) {
-    if ( sym->st_shndx != ELF::SHN_ABS) {
-      sym->st_value = this->_writer.addressOfAtom(_symbolToAtom[sym]);
-    }
-  }
-}
+public:
 
-template< support::endianness target_endianness, bool is64Bits>
-void ELFSymbolTableChunk<target_endianness, is64Bits>::addSymbol(Elf_Sym *sym){
-   _symbolTable.push_back(sym);
-   this->_size+= sizeof(Elf_Sym) ;
-}
+  // 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<target_endianness, is64Bits> *>::iterator 
+                                                                     chunk_iter;
+  // 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, MergedSection<target_endianness, is64Bits> *> 
+                                                            mergedSectionMap_t;
+  typedef typename std::vector
+   <MergedSection<target_endianness, is64Bits> *>::iterator merged_section_iter;
 
-/// \brief Add symbols to symbol table
-/// We examine each property of atom to infer the various st_* fields in Elf*_Sym
-template< support::endianness target_endianness, bool is64Bits>
-void ELFSymbolTableChunk<target_endianness, is64Bits>
-                  ::addSymbol(const Atom *a, uint16_t shndx) {
- Elf_Sym *symbol = new(_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
- unsigned char b = 0, t = 0;
- symbol->st_name = _stringSection->addString(a->name());
- _symbolToAtom[symbol] = a;
-// In relocatable files, st_value holds a section offset for a defined symbol.
-// st_value is an offset from the beginning of the section that st_shndx
-// identifies. After we assign file offsets we can set this value correctly.
- symbol->st_size = 0;
- symbol->st_shndx = shndx;
- symbol->st_value = 0;
-// FIXME: Need to change and account all STV* when visibilities are supported
- symbol->st_other = ELF::STV_DEFAULT;
- if (const DefinedAtom *da = llvm::dyn_cast<const DefinedAtom>(a)){
-    symbol->st_size = da->size();
-    lld::DefinedAtom::ContentType ct;
-    switch (ct = da->contentType()){
-    case  DefinedAtom::typeCode:
-      t = ELF::STT_FUNC;
-      break;
-    case  DefinedAtom::typeData:
-      t = ELF::STT_OBJECT;
-      break;
-    case  DefinedAtom::typeZeroFill:
-   // In relocatable files, st_value holds alignment constraints for a symbol whose 
-   // section index is SHN_COMMON
-      if (this->_options.type() == ELF::ET_REL){
-        t = ELF::STT_COMMON;
-        symbol->st_value = 1 << (da->alignment()).powerOf2;
-        symbol->st_shndx = ELF::SHN_COMMON;
-      }
-      break;
-   // TODO:: How to find STT_FILE symbols?
-    default:
-      t = ELF::STT_NOTYPE;
+  // HashKey for the Section
+  class HashKey {
+  public:
+    int64_t operator() (const Key &k) const {
+      // k.first = section Name
+      // k.second = [contentType, Permissions]
+      return llvm::HashString(k.first) + k.second.first + k.second.second;
     }
- 
-    if (da->scope() == DefinedAtom::scopeTranslationUnit)  
-      b = ELF::STB_LOCAL;
-    else if (da->merge() == DefinedAtom::mergeAsWeak)
-      b = ELF::STB_WEAK;
-    else
-      b = ELF::STB_GLOBAL;
-  } else if (const AbsoluteAtom *aa = llvm::dyn_cast<const AbsoluteAtom>(a)){
-//FIXME: Absolute atoms need more properties to differentiate each other
-// based on binding and type of symbol
-    t = ELF::STT_OBJECT;
+  };
 
-    switch (aa->scope()) {
-    case AbsoluteAtom::scopeLinkageUnit:
-      symbol->st_other = ELF::STV_HIDDEN;
-      b = ELF::STB_LOCAL;
-      break;
-    case AbsoluteAtom::scopeTranslationUnit:
-      b = ELF::STB_LOCAL;
-      break;
-    case AbsoluteAtom::scopeGlobal:
-      b = ELF::STB_GLOBAL;
-      break;
+  // HashKey for the Segment
+  class SegmentHashKey {
+  public:
+    int64_t operator() (const SegmentKey &k) const {
+      // k.first = SegmentName
+      // k.second = SegmentFlags
+      return llvm::HashString(k.first) + k.second;
     }
-    symbol->st_value = aa->value();
- } else {
-   symbol->st_value = 0;
-   t = ELF::STT_NOTYPE;
-   b = ELF::STB_LOCAL;
- }
- symbol->setBindingAndType(b, t);
+  };
 
- _symbolTable.push_back(symbol);
- this->_size += sizeof(Elf_Sym);
-}
+  typedef std::unordered_map<Key, 
+          Section<target_endianness, is64Bits>*, HashKey> sectionMap_t;
+  typedef std::unordered_map<SegmentKey,
+                             Segment<target_endianness, is64Bits>*, 
+                             SegmentHashKey> segmentMap_t;
 
-template<support::endianness target_endianness, bool is64Bits>
-void ELFSymbolTableChunk<target_endianness, is64Bits>::setAttributes() {
-// 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) -> bool {
-                   return (A->getBinding() < B->getBinding());}));
-  uint16_t shInfo = 0;
-  for (auto i : _symbolTable) {
-    if (i->getBinding() != ELF::STB_LOCAL)
-      break;
-    shInfo++;
-  }
-  this->_shinfo = shInfo;
-// we set the associated string table index in th sh_link member
-  this->_link = this->_writer.strtab()->ordinal() - 1;
-  this->_align2 = this->_options.pointerWidth();
-}
+  DefaultELFLayout(const WriterOptionsELF &options):_options(options) { }
 
-template<support::endianness target_endianness, bool is64Bits>
-const char *ELFSymbolTableChunk<target_endianness, is64Bits>::info() {
-  return "Symbol Table";
-}
+  /// \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:
+          if (name.startswith(".eh_frame_hdr")) 
+            return ORDER_EH_FRAMEHDR;
+          if (name.startswith(".eh_frame")) 
+            return ORDER_EH_FRAME;
+          else if (name.startswith(".init")) 
+            return ORDER_INIT;
+          else if (name.startswith(".fini"))
+            return ORDER_FINI;
+          else if (name.startswith(".hash")) 
+            return ORDER_HASH;
+          else
+            return ORDER_TEXT;
 
-template<support::endianness target_endianness, bool is64Bits>
-void ELFSymbolTableChunk<target_endianness, is64Bits>::
-     write(uint8_t *chunkBuffer) {
-  uint64_t chunkOffset = 0;
-  for (auto it : _symbolTable) {
-    ::memcpy(chunkBuffer + chunkOffset, it, this->_entsize);
-    chunkOffset += this->_entsize;
+      case DefinedAtom::typeConstant:
+          return ORDER_RODATA;        
+  
+      case DefinedAtom::typeData:
+          return 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;
+    }
   }
-}
 
-//===----------------------------------------------------------------------===//
-//  ELFHeaderChunk
-//===----------------------------------------------------------------------===//
-template<support::endianness target_endianness, bool is64Bits>
-ELFHeaderChunk<target_endianness, is64Bits>
-              ::ELFHeaderChunk(const WriterOptionsELF &options,
-                               const File &File) 
-  : Chunk<target_endianness, is64Bits>(Chunk<target_endianness, is64Bits>
-                                       ::Kind::Header){
-  this->_size = size();
-  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_ident(ELF::EI_CLASS, (options.is64Bit() ? ELF::ELFCLASS64
-                                            : ELF::ELFCLASS32));
-  e_ident(ELF::EI_DATA, (options.endianness() == llvm::support::big)
-                         ? ELF::ELFDATA2MSB
-                         : ELF::ELFDATA2LSB);
-  e_ident(ELF::EI_VERSION, 1);
-  e_ident(ELF::EI_OSABI, ELF::ELFOSABI_NONE);
+  /// \brief This maps the input sections to the output section names
+  StringRef getSectionName(const StringRef name) {
+    if (name.startswith(".text")) 
+      return ".text";
+    if (name.startswith(".rodata")) 
+      return ".rodata";
+    return name;
+  }
 
-  e_type(options.type());
-  e_machine(options.machine());
-  e_version(1);
+  /// \brief Gets the segment for a output section
+  virtual ELFLayout::SegmentType getSegmentType(Section<target_endianness, 
+                                     is64Bits> *section) const {
+    switch(section->order()) {
+      case ORDER_INTERP:
+        return llvm::ELF::PT_INTERP;
 
-  e_entry(0ULL);
-  e_phoff(0);
-  e_shoff(0ULL);
-  
-  e_flags(2);
-  e_ehsize(this->_size);
-  e_phentsize(0);
-  e_phnum(0);
-  e_shentsize(0);
-  e_shnum(0);
-  e_shstrndx(0);
-  this->setGroup(CG_HEADER);
-}
+      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;
 
-template<support::endianness target_endianness, bool is64Bits>
-StringRef ELFHeaderChunk<target_endianness, is64Bits>
-                        ::segmentName() const {
-  return "ELF";
-}
+      case ORDER_NOTE:
+        return llvm::ELF::PT_NOTE;
 
-template<support::endianness target_endianness, bool is64Bits>
-void ELFHeaderChunk<target_endianness, is64Bits>
-                   ::write(uint8_t *chunkBuffer) {
-  ::memcpy(chunkBuffer, &_eh, size());
-}
+      case ORDER_DYNAMIC:
+        return llvm::ELF::PT_DYNAMIC;
 
-template<support::endianness target_endianness, bool is64Bits>
-const char *ELFHeaderChunk<target_endianness, is64Bits>::info() {
-  return "elf_header";
-}
+      case ORDER_CTORS:
+      case ORDER_DTORS:
+      case ORDER_GOT:
+        return llvm::ELF::PT_GNU_RELRO;
 
-//===----------------------------------------------------------------------===//
-//  ELFSectionHeaderChunk
-//  List of Section Headers:
-//[Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
-//[ 0]                   NULL            00000000 000000 000000 00      0   0  0
-//[ 1] .text             PROGBITS        00000000 000034 000040 00  AX  0   0  4
-//===----------------------------------------------------------------------===//
-template<support::endianness target_endianness, bool is64Bits>
-ELFSectionHeaderChunk<target_endianness, is64Bits>
-                     ::ELFSectionHeaderChunk(const WriterOptionsELF& options,
-                                             ELFWriter<target_endianness, 
-                                                       is64Bits> &writer) 
-  : Chunk<target_endianness, is64Bits>(Chunk<target_endianness, is64Bits>
-                                       ::Kind::Header)
-  , _options(options)
-  , _writer(writer) {
-  this->_size = 0;
-  this->_align2 = 0;
-  // 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->_size += sizeof (Elf_Shdr);
-  this->setGroup(CG_FILE_END);
+      case ORDER_GOT_PLT:
+      case ORDER_DATA:
+      case ORDER_BSS:
+        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<target_endianness, 
+                                 is64Bits> *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_BSS:
+        return true;
 
-template<support::endianness target_endianness, bool is64Bits>
-void ELFSectionHeaderChunk<target_endianness, is64Bits>::computeSize(){
-  this->_size = (this->_writer.sectionChunks().size() + 1) * sizeof(Elf_Shdr);
-}
+      default:
+        return false;
+    }
+  }
 
-template<support::endianness target_endianness, bool is64Bits>
-void ELFSectionHeaderChunk<target_endianness, is64Bits>::fixOffsets(){
-  auto it = _sectionInfo.begin();
-  auto sections =  _writer.sectionChunks();
-  // First section is a NULL section with no sh_offset fix
-  (*it)->sh_offset = 0;
-  (*it)->sh_addr = 0;
-  ++it;
-  for (auto &chunk : sections){
-    (*it)->sh_offset = chunk->fileOffset();
-    (*it)->sh_addr = chunk->address();
-    ++it;
+  // Adds an atom to the section
+  virtual error_code addAtom(const Atom *atom) {
+    const DefinedAtom *definedAtom = dyn_cast<DefinedAtom> (atom);
+    const StringRef sectionName = getSectionName
+                                  (definedAtom->customSectionName());
+    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<target_endianness, is64Bits> *> 
+                                                currentSection(key, nullptr);
+    std::pair<typename sectionMap_t::iterator, bool> 
+                              sectionInsert(_sectionMap.insert(currentSection));
+    Section<target_endianness, is64Bits> *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<target_endianness, is64Bits>>())
+                     Section<target_endianness, is64Bits>
+                     (sectionName, contentType, 
+                      permissions, section_order);
+      sectionInsert.first->second = section;
+      section->setOrder(section_order);
+      _sections.push_back(section);
+    }
+    section->appendAtom(atom);
+    return error_code::success();
   }
-}
 
-template<support::endianness target_endianness, bool is64Bits>
-void ELFSectionHeaderChunk<target_endianness, is64Bits>::createHeaders(){
-  ELFStringSectionChunk<target_endianness, is64Bits> *str = _writer.shstrtab();
+  // Merge sections with the same name into a MergedSection
+  void mergeSimiliarSections()
+  {
+    MergedSection<target_endianness, is64Bits> *mergedSection;
+  
+    for (auto si = _sections.begin(); si != _sections.end(); ++si) {
+      const std::pair<StringRef, MergedSection<target_endianness, is64Bits> *> 
+                                            currentMergedSection((*si)->name(), 
+                                                                 nullptr);
+      std::pair<typename mergedSectionMap_t::iterator, bool>
+                              mergedSectionInsert
+                              (_mergedSectionMap.insert(currentMergedSection));
+      if (!mergedSectionInsert.second) {
+        mergedSection = mergedSectionInsert.first->second;
+      }
+      else {
+        mergedSection = new (_allocator.Allocate
+                     <MergedSection<target_endianness, is64Bits>>())
+                     MergedSection<target_endianness, is64Bits>((*si)->name());
+        _mergedSections.push_back(mergedSection);
+        mergedSectionInsert.first->second = mergedSection;
+      }
+      mergedSection->appendSection(*si);
+    }
+  }
 
- for (const  auto &chunk : _writer.sectionChunks()) {
-    Elf_Shdr *shdr  = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
-    StringRef Name  = chunk->sectionName();
-    if (chunk->shStrtableOffset() == 0){
-      chunk->setShStrtableOffset(str->addString(Name));
+  void assignSectionsToSegments() 
+  {
+    // sort the sections by their order as defined by the layout
+    std::stable_sort(_sections.begin(), _sections.end(), ([]
+                     (Chunk<target_endianness, is64Bits> *A, 
+                      Chunk<target_endianness, is64Bits> *B) -> 
+                      bool { return (A->order() < B->order());}));
+    // Merge all sections
+    mergeSimiliarSections();
+    // Set the ordinal after sorting the sections
+    int ordinal = 1;
+    for (auto msi = _mergedSections.begin(); msi != _mergedSections.end(); 
+                                                                   ++msi) {
+      (*msi)->setOrdinal(ordinal);
+      for (auto ai = (*msi)->begin_sections(); ai != (*msi)->end_sections(); 
+                                                                        ++ai) {
+        (*ai)->setOrdinal(ordinal);
+      }
+      ++ordinal;
     }
-    shdr->sh_name   = chunk->shStrtableOffset();
+    Section<target_endianness, is64Bits> *section;
+    Segment<target_endianness, is64Bits> *segment;
+    for (auto msi = merged_sections_begin(); msi != merged_sections_end(); 
+                                                                    ++msi) {
+      for (auto ai = (*msi)->begin_sections(); ai != (*msi)->end_sections(); 
+                                                                    ++ai) {
+        if ((*ai)->kind() == Chunk<target_endianness, is64Bits>::Section) {
+          section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(*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<target_endianness, is64Bits> *> 
+                                                  currentSegment(key, nullptr);
+          std::pair<typename segmentMap_t::iterator, bool> 
+                              segmentInsert(_segmentMap.insert(currentSegment));
 
-    shdr->sh_type   = chunk->type();
-    shdr->sh_flags  = chunk->flags();
-    // TODO: At the time of creation of this section header, we will not have
-    // any address and offset info. We  revisit this after assigning the file
-    // offsets.
-    shdr->sh_offset = chunk->fileOffset();
-    shdr->sh_addr   = chunk->address();
-    shdr->sh_size   = chunk->size();
-    shdr->sh_link = chunk->link() ;
-    shdr->sh_info = chunk->shinfo();
-    shdr->sh_addralign = chunk->align2();
-    shdr->sh_entsize = chunk->entsize();
+          if (!segmentInsert.second) {
+            segment = segmentInsert.first->second;
+          }
+          else {
+            segment = new (_allocator.Allocate
+                           <Segment<target_endianness, is64Bits>>())
+                           Segment<target_endianness, is64Bits>
+                           (segmentName, getSegmentType(section), 
+                            _options);
+            segmentInsert.first->second = segment;
+            _segments.push_back(segment);
+          }
+          segment->append(section);
+        }
+      }
+    }
+  }
 
-    _sectionInfo.push_back(shdr);
-    this->_size += sizeof (Elf_Shdr);
-    _writer.symtab()->setAttributes();
+  void addSection(Chunk<target_endianness, is64Bits> *c) {
+    _sections.push_back(c);
   }
-}
 
-template<support::endianness target_endianness, bool is64Bits>
-StringRef ELFSectionHeaderChunk<target_endianness, is64Bits>
-                               ::segmentName() const {
-  return "PT_NULL";
-}
-
-template<support::endianness target_endianness, bool is64Bits>
-void ELFSectionHeaderChunk<target_endianness, is64Bits>
-                          ::write(uint8_t *chunkBuffer) {
-  for (const auto si : _sectionInfo) {
-    ::memcpy(chunkBuffer, si, sizeof(*si));
-    chunkBuffer += sizeof (*si);
+  void findSectionByOrder(chunk_iter *chunk, DefaultSectionOrder s) {
+    for (auto ai = sections_begin(); ai != sections_end(); ++ai) {
+      if ((*ai)->order() == s) {
+        chunk = *ai;
+        return;
+      }
+    }
+    chunk = sections_end();
   }
-}
+  void findSectionByName(chunk_iter *chunk, StringRef s) {
+    for (auto ai = sections_begin(); ai != sections_end(); ++ai) {
+      if ((*ai)->name() == s) {
+        chunk = *ai;
+        return;
+      }
+    }
+    chunk = sections_end();
+  }
 
-template<support::endianness target_endianness, bool is64Bits>
-uint16_t ELFSectionHeaderChunk<target_endianness, is64Bits>::count() {
-  return _sectionInfo.size();
-}
-template<support::endianness target_endianness, bool is64Bits>
-uint16_t ELFSectionHeaderChunk<target_endianness, is64Bits>::size() {
-  return sizeof (Elf_Shdr);
-}
+  void assignFileOffset() {
+    Segment<target_endianness, is64Bits> *segment;
 
-template<support::endianness target_endianness, bool is64Bits>
-const char *ELFSectionHeaderChunk<target_endianness, is64Bits>::info() {
-  return "elf_section_header";
-}
+    std::sort(_segments.begin(), _segments.end(), 
+                     Segment<target_endianness, is64Bits>::compare_segments);
+    int ordinal = 0;
+    for (auto si = _segments.begin(); si != _segments.end(); ++si) {
+      segment = llvm::dyn_cast<Segment<target_endianness, is64Bits>>(*si);
+      segment->setOrdinal(++ordinal);
+    }
+    // Compute the number of segments that might be needed, so that the
+    // size of the program header can be computed
+    int64_t offset = 0;
+    for (auto si = _segments.begin(); si != _segments.end(); ++si) {
+      segment = llvm::dyn_cast<Segment<target_endianness, is64Bits>>(*si);
+      segment->assignOffset(offset);
+      offset += segment->filesize();
+    }
+  }
 
-//===----------------------------------------------------------------------===//
-//  ELFProgramHeaderChunk
-//===----------------------------------------------------------------------===//
-template<support::endianness target_endianness, bool is64Bits>
-ELFProgramHeaderChunk<target_endianness, is64Bits>
-          ::ELFProgramHeaderChunk(const WriterOptionsELF &options, 
-                                  ELFWriter<target_endianness, is64Bits>
-                                                 &writer)
-  : Chunk<target_endianness, is64Bits>(Chunk<target_endianness, is64Bits>
-                                       ::Kind::Header)
-  , _options(options)
-  , _writer(writer) {
-  this->_align2 = 0;
-  this->setGroup(CG_HEADER);
-  _groupToPF[CG_RWX] = ELF::PF_R | ELF::PF_W | ELF::PF_X;
-  _groupToPF[CG_RW]  = ELF::PF_R | ELF::PF_W;
-  _groupToPF[CG_RX]  = ELF::PF_R | ELF::PF_X;
-  _groupToPF[CG_R]   = ELF::PF_R;
-  _groupToPF[CG_W]   = ELF::PF_W;
-  _groupToPF[CG_WX]  = ELF::PF_W | ELF::PF_X;
-  _groupToPF[CG_X]   = ELF::PF_X;
+  void setELFHeader(ELFHeader<target_endianness, is64Bits> *e) {
+    _elfHeader = e;
   }
 
-template<support::endianness target_endianness, bool is64Bits>
-void ELFProgramHeaderChunk<target_endianness, is64Bits>::createPHeaders() {
+  void setProgramHeader(ELFProgramHeader<target_endianness, is64Bits> *p) {
+    _programHeader = p;
+  }
 
-  //TODO Once dynamic linking is supported, implement PHDR segment
-  //     Implement mechanism inside this class to correctly find
-  //     attributes for sections such as eh_frame, note etc 
-  //     when they are supported.
-  const uint16_t seg[] = { CG_RWX, CG_RX, CG_R, CG_RW, CG_WX, CG_W, CG_X };
-  std::pair<secIterator, secIterator> sectionPair;
-  auto sections = _writer.sectionChunks();
-  _programHeaders.clear();
-  this->_size = 0;
-  for (auto group : seg) {
-    uint64_t size = 0, mSize = 0;
-    sectionPair = std::equal_range(sections.begin(), sections.end(), 
-                                   group, ChunkComparator<target_endianness, 
-                                                      is64Bits>());
-    if (sectionPair.first != sectionPair.second) {
-      // FIXME: fix occupiesNoDiskSpace() function in Chunks class
-      auto segBegin = sectionPair.first, segEnd = segBegin + 1;
-      // Since  this group has a section, atleast this is a part of segment
-      size = (*segBegin)->occupiesNoDiskSpace() ? 0 : (*segBegin)->size();
-      mSize = (*segBegin)->size();
+  void assignVirtualAddress() {
+    int32_t numSlices = 0;
+    int64_t startAddress = _options.baseAddress();
 
-      for (; segEnd != sectionPair.second; segEnd++) {
-      // This means there are more than 1 sections of same permissions
-        if ((*segEnd)->fileOffset() - (*segBegin)->fileOffset() - size >
-             _options.pageSize()) {
-          // we have a case where padding zeros span more than a page
-          // we can skip those pages.
-          Elf_Phdr *phdr = new(_headerAllocate.Allocate<Elf_Phdr>()) Elf_Phdr;
-          phdr->p_type = ELF::PT_LOAD;
-          phdr->p_offset = (*segBegin)->fileOffset();
-          phdr->p_vaddr =  (*segBegin)->address();
-          phdr->p_paddr = phdr->p_vaddr;
-          phdr->p_filesz = size;
-          // memory size may be more than file size if there are sections
-          // that do not occupy space on disk such as .bss
-          phdr->p_memsz = mSize;
-          phdr->p_flags = _groupToPF[group];
-          phdr->p_align = _options.pageSize();
-          _programHeaders.push_back(phdr);
-          this->_size += sizeof(Elf_Phdr);
-          segBegin = segEnd;
-          size = (*segBegin)->occupiesNoDiskSpace() ? 0 : (*segBegin)->size();
-          mSize = (*segBegin)->size();
-        } else {
-          size = (*segEnd)->fileOffset() - (*segBegin)->fileOffset() + 
-                 ((*segEnd)->occupiesNoDiskSpace() ? 0 : (*segEnd)->size())  ;
-          mSize =  (*segEnd)->fileOffset() - (*segBegin)->fileOffset() + 
-                   (*segEnd)->size();
+    // Add the ELF Header
+    if (_elfHeader) {
+      _elfHeader->setFileOffset(0);
+      _elfHeader->setStart(startAddress);
+    }
+    // Add the program header
+    if (_programHeader) {
+      _programHeader->setStart(int64_t(startAddress + _elfHeader->filesize()));
+      _programHeader->setFileOffset(_elfHeader->filesize());
+    }
+    Segment<target_endianness, is64Bits> *segment;
+    bool newSegmentHeaderAdded = true;
+    while (true) {
+      for (auto si = _segments.begin(); si != _segments.end(); ++si) {
+        segment = llvm::dyn_cast<Segment<target_endianness, is64Bits>>(*si);
+        newSegmentHeaderAdded = _programHeader->addSegment(segment);
+        numSlices += segment->numSlices();
+      }
+      if (!newSegmentHeaderAdded) 
+        break;
+      int64_t fileoffset = _elfHeader->filesize() + _programHeader->filesize();
+      int64_t address = startAddress;
+      // Fix the offsets after adding the program header
+      for (auto si = _segments.begin(); si != _segments.end(); ++si) {
+        segment = llvm::dyn_cast<Segment<target_endianness, is64Bits>>(*si);
+        // Align the segment to a page boundary
+        fileoffset = Chunk<target_endianness, is64Bits>::alignTo(fileoffset, 
+                                                                 _options.pageSize());
+        segment->assignOffset(fileoffset);
+        fileoffset = segment->fileOffset() + segment->filesize();
+      }
+      // start assigning virtual addresses
+      for (auto si = _segments.begin(); si != _segments.end(); ++si) {
+        segment = llvm::dyn_cast<Segment<target_endianness, is64Bits>>(*si);
+        segment->setStart(startAddress);
+        // The first segment has the startAddress set to the base address
+        // as we have added the file header and the program header 
+        // dont align the first segment to the pagesize 
+        // TODO: check in addition to this, that the first segment is a load
+        // segment, only load segments have the addresses aligned
+        segment->assignVirtualAddress(address, (si == _segments.begin()));
+        segment->setMemSize(address - startAddress);
+        startAddress = Chunk<target_endianness, is64Bits>::alignTo(address, 
+                                                                   _options.pageSize());
+      }
+      _programHeader->resetProgramHeaders();
+    }
+    Section<target_endianness, is64Bits> *section;
+    // Fix the offsets of all the atoms within a section
+    for (auto si = _sections.begin(); si != _sections.end(); ++si) {
+      section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(*si);
+      if (section && DefaultELFLayout<target_endianness, is64Bits>::hasOutputSegment(section))
+        section->assignOffset(section->fileOffset());
+    }
+    // Set the size of the merged Sections
+    for (auto msi = merged_sections_begin(); msi != merged_sections_end(); ++msi) {
+      int64_t sectionfileoffset = 0;
+      int64_t startFileOffset = 0;
+      int64_t sectionsize = 0;
+      bool isFirstSection = true;
+      for (auto si = (*msi)->begin_sections(); si != (*msi)->end_sections(); ++si) {
+        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 = merged_sections_begin(); msi != merged_sections_end(); ++msi) {
+      int64_t sectionstartaddr = 0;
+      int64_t startaddr = 0;
+      int64_t sectionsize = 0;
+      bool isFirstSection = true;
+      for (auto si = (*msi)->begin_sections(); si != (*msi)->end_sections(); ++si) {
+        if (isFirstSection) {
+          startaddr = (*si)->startAddr();
+          isFirstSection = false;
+        }
+        sectionstartaddr = (*si)->startAddr();
+        sectionsize = (*si)->memsize();
+      }
+      sectionsize = (sectionstartaddr - startaddr) + sectionsize;
+      (*msi)->setMemSize(sectionsize);
+      (*msi)->setAddr(startaddr);
+    }
+  }
 
-      Elf_Phdr *phdr = new(_headerAllocate.Allocate<Elf_Phdr>()) Elf_Phdr;
-      phdr->p_type = ELF::PT_LOAD;
-      phdr->p_offset = (*segBegin)->fileOffset();
-      phdr->p_vaddr = (*segBegin)->address();
-      phdr->p_paddr = phdr->p_vaddr;
-      phdr->p_filesz = size;
-      phdr->p_memsz = mSize;
-      phdr->p_flags = _groupToPF[group];
-      phdr->p_align = _options.pageSize();
-      _programHeaders.push_back(phdr);
-      this->_size += sizeof(Elf_Phdr);
+  void assignOffsetsForMiscSections() {
+    int64_t fileoffset = 0;
+    int64_t size = 0;
+    for (auto si = _segments.begin(); si != _segments.end(); ++si) {
+      fileoffset = (*si)->fileOffset();
+      size = (*si)->filesize();
     }
+    fileoffset = fileoffset + size;
+    Section<target_endianness, is64Bits> *section;
+    for (auto si = _sections.begin(); si != _sections.end(); ++si) {
+      section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(*si);
+      if (section && 
+          DefaultELFLayout<target_endianness, is64Bits>::hasOutputSegment
+                                                         (section))
+        continue;
+      fileoffset = Chunk<target_endianness, is64Bits>::alignTo(fileoffset, 
+                                                              (*si)->align2());
+      (*si)->setFileOffset(fileoffset);
+      (*si)->setStart(0);
+      fileoffset += (*si)->filesize();
+    }
   }
-}
 
-template<support::endianness target_endianness, bool is64Bits>
-uint64_t ELFProgramHeaderChunk<target_endianness, is64Bits>::computeNumber() {
-  return _programHeaders.size();
-}
-template<support::endianness target_endianness, bool is64Bits>
-const char *ELFProgramHeaderChunk<target_endianness, is64Bits>::info() {
-  return "elf_program_header";
-}
+  void finalize() {
+    for (auto si = _sections.begin(); si != _sections.end(); ++si) {
+      (*si)->finalize();
+    }
+  }
 
-template<support::endianness target_endianness, bool is64Bits>
-void ELFProgramHeaderChunk<target_endianness, is64Bits>
-                          ::write(uint8_t *chunkBuffer) {
-  for (const auto si : _programHeaders) {
-    ::memcpy(chunkBuffer, si, sizeof(*si));
-    chunkBuffer += sizeof (*si);
+  bool findAtomAddrByName(const StringRef name, int64_t &addr) {
+    Section<target_endianness, is64Bits> *section;
+    for (auto ai = _sections.begin(); ai != _sections.end(); ++ai) {
+      if ((*ai)->kind() == Chunk<target_endianness, is64Bits>::Section) {
+        section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(*ai);
+        if (section->findAtomAddrByName(name, addr))
+         return true;
+      }
+    }
+    return false;    
   }
-}
-template<support::endianness target_endianness, bool is64Bits>
-StringRef ELFProgramHeaderChunk<target_endianness, is64Bits>
-                               ::segmentName() const {
-  return "PT_NULL";
-}
+
+  merged_section_iter merged_sections_begin() { 
+    return _mergedSections.begin();
+  }
+
+  merged_section_iter merged_sections_end() { 
+    return _mergedSections.end();
+  }
+
+  chunk_iter sections_begin() {
+    return _sections.begin();
+  }
+  chunk_iter sections_end() {
+    return _sections.end();
+  }
+
+  chunk_iter segments_begin() {
+    return _segments.begin();
+  }
+
+  chunk_iter segments_end() {
+    return _segments.end();
+  }
+
+  ELFHeader<target_endianness, is64Bits> *elfHeader() { 
+    return _elfHeader;
+  }
+
+  ELFProgramHeader<target_endianness, is64Bits> *elfProgramHeader() { 
+    return _programHeader;
+  }
+
+private:
+  sectionMap_t _sectionMap;
+  mergedSectionMap_t _mergedSectionMap;
+  segmentMap_t _segmentMap;
+
+  std::vector<Chunk<target_endianness, is64Bits> *> _sections;
+  std::vector<Chunk<target_endianness, is64Bits> *> _segments;
+  std::vector<MergedSection<target_endianness, is64Bits> *> _mergedSections;
+  ELFHeader<target_endianness, is64Bits> *_elfHeader;
+  ELFProgramHeader<target_endianness, is64Bits> *_programHeader;
+  llvm::BumpPtrAllocator _allocator;
+  const WriterOptionsELF &_options;
+};
+
 //===----------------------------------------------------------------------===//
-//  ELFWriter Class
+//  ELFExecutableWriter Class
 //===----------------------------------------------------------------------===//
 template<support::endianness target_endianness, bool is64Bits>
-class ELFWriter : public Writer {
+class ELFExecutableWriter : public ELFWriter {
 public:
-  LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
   typedef object::Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
   typedef object::Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
-  typedef object::Elf_Phdr<target_endianness, is64Bits> Elf_Phdr;
-  ELFWriter(const WriterOptionsELF &options);
+
+  ELFExecutableWriter(const WriterOptionsELF &options);
+
+private:
+  // build the sections that need to be created 
+  void buildChunks(const lld::File &file);
   virtual error_code writeFile(const lld::File &File, StringRef path);
-  uint64_t addressOfAtom(const Atom *atom);
+  void buildAtomToAddressMap();
+  void buildSymbolTable ();
+  void buildSectionHeaderTable();
+  void assignSectionsWithNoSegments();
+  void addAbsoluteUndefinedSymbols(const lld::File &File);
 
-  std::vector<Chunk<target_endianness, is64Bits>*> chunks() const {
-    return _chunks; }
+  int64_t addressOfAtom(const Atom *atom) { 
+    return _atomToAddressMap[atom];
+  }
 
   KindHandler *kindHandler() { return _referenceKindHandler.get(); }
-  
-  std::vector<SectionChunk<target_endianness, is64Bits>*> sectionChunks() const {
-    return _sectionChunks ;
-  }
- 
-  ELFStringSectionChunk<target_endianness, is64Bits> *shstrtab()  const {
-    return _shstrtable;
-  }
-  
-  ELFStringSectionChunk<target_endianness, is64Bits> *strtab() const {
-    return _strtable;
-  }
-  ELFSymbolTableChunk<target_endianness, is64Bits> *symtab() const {
-    return _symtable;
-  }
 
-private:
-  void build(const lld::File &file);
-  void createChunks(const lld::File &file);
-  void buildAtomToAddressMap();
-  void assignFileOffsets();
+  void createDefaultSections();
+
   const WriterOptionsELF &_options;
 
-/// \brief AtomToAddress: Is a mapping from an Atom to the address where
-/// it will live in the output file.
-  typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
-  typedef typename std::vector<Chunk<target_endianness, is64Bits>*>
-                     ::iterator chunkIterator;
-  ELFProgramHeaderChunk<target_endianness, is64Bits> *_phdr;
-  ELFHeaderChunk<target_endianness, is64Bits> *ehc;
-  ELFStringSectionChunk<target_endianness, is64Bits> *_shstrtable ;
-  ELFStringSectionChunk<target_endianness, is64Bits> *_strtable ;
-  ELFSymbolTableChunk<target_endianness, is64Bits> *_symtable;
+  typedef llvm::DenseMap<const Atom*, int64_t> AtomToAddress;
   std::unique_ptr<KindHandler> _referenceKindHandler;
-  ELFSectionHeaderChunk<target_endianness, is64Bits> *_sectionHeaderChunk;
-  AtomToAddress _atomToAddress;
-  std::vector<Chunk<target_endianness, is64Bits>*> _chunks;
-  const DefinedAtom *_entryAtom;
-  std::vector<SectionChunk<target_endianness, is64Bits>*> _sectionChunks;
-  std::vector<StockSectionChunk<target_endianness, is64Bits>*> 
-                                                      _stockSectionChunks;
+  AtomToAddress _atomToAddressMap;
   llvm::BumpPtrAllocator _chunkAllocate;
+  DefaultELFLayout<target_endianness, is64Bits> *_layout;
+  ELFHeader<target_endianness, is64Bits> *_elfHeader;
+  ELFProgramHeader<target_endianness, is64Bits> *_programHeader;
+  ELFSymbolTable<target_endianness, is64Bits> * _symtab;
+  ELFStringTable<target_endianness, is64Bits> *_strtab;
+  ELFStringTable<target_endianness, is64Bits> *_shstrtab;
+  ELFSectionHeader<target_endianness, is64Bits> *_shdrtab;
 };
 
 //===----------------------------------------------------------------------===//
-//  ELFWriter
+//  ELFExecutableWriter
 //===----------------------------------------------------------------------===//
 template<support::endianness target_endianness, bool is64Bits>
-ELFWriter<target_endianness, is64Bits>
-         ::ELFWriter(const WriterOptionsELF &options)
+ELFExecutableWriter<target_endianness, is64Bits>
+         ::ELFExecutableWriter(const WriterOptionsELF &options)
   : _options(options)
   , _referenceKindHandler(KindHandler::makeHandler(_options.machine(),
                                                    target_endianness))
-{}
+{
+  _layout = new DefaultELFLayout<target_endianness, is64Bits>(options);
+}
 
 template<support::endianness target_endianness, bool is64Bits>
-void ELFWriter<target_endianness, is64Bits>::build(const lld::File &file){
-// Create objects for each chunk.
-  createChunks(file);
-  assignFileOffsets();
-  _phdr->createPHeaders();
-  _sectionHeaderChunk->createHeaders();
-  // Creating program headers changed its size. so we need to re-assign offsets
-  assignFileOffsets();
-  _sectionHeaderChunk->fixOffsets();
-  _phdr->createPHeaders();
-  buildAtomToAddressMap();
-  _symtable->fixSymbolValue();
-  ehc->e_shentsize(_sectionHeaderChunk->size());
-  ehc->e_shnum(_sectionHeaderChunk->count());
-  // We need to put the index of section string table in ELF header
-  // first two chunks are not sections so we subtract 2 to start sections
-  // and add 1 since we have a NULL header
-  ehc->e_shstrndx(_shstrtable->ordinal() - 1);
-  ehc->e_phnum(_phdr->computeNumber());
-  ehc->e_phoff(_phdr->fileOffset());
-  ehc->e_phentsize(sizeof(Elf_Phdr));
-  for (auto i : _stockSectionChunks) {
-    if(const DefinedAtom* da = findDefinedAtomByName(_options.entryPoint(), i)) {
-      ehc->e_entry(this->addressOfAtom(da));
-      return;
-    }
+void ELFExecutableWriter<target_endianness, is64Bits>::buildChunks
+                                                   (const lld::File &file){
+  for (const DefinedAtom *definedAtom : file.defined() ) {
+    _layout->addAtom(definedAtom);
   }
 }
 
 template<support::endianness target_endianness, bool is64Bits>
-void ELFWriter<target_endianness, is64Bits>
-              ::createChunks (const lld::File &file) {
-  std::map<StringRef, StockSectionChunk<target_endianness, is64Bits>*> 
-             sectionMap;
-
-// Make header chunk
-  ehc = new (_chunkAllocate.Allocate
-        <ELFHeaderChunk<target_endianness, is64Bits>>())
-        ELFHeaderChunk<target_endianness, is64Bits>(_options, file);
-  _chunks.push_back(ehc);
-
-  _phdr = new (_chunkAllocate.Allocate
-               <ELFProgramHeaderChunk<target_endianness, is64Bits>>())
-                ELFProgramHeaderChunk<target_endianness, is64Bits>(_options, 
-                                                                   *this);
-  _chunks.push_back(_phdr);
-        
-// We need to create hand crafted sections such as shstrtab strtab hash and
-// symtab to put relevant information in ELF structures and then process the
-// atoms.
-
-  _shstrtable = new (_chunkAllocate.Allocate
-                     <ELFStringSectionChunk<target_endianness, is64Bits>>()) 
-                    ELFStringSectionChunk<target_endianness, is64Bits>
-                             (_options, *this, ".shstrtab");
-  _shstrtable->setShStrtableOffset(_shstrtable->addString(".shstrtab"));
-  _sectionChunks.push_back(_shstrtable);
-  
-  _strtable = new (_chunkAllocate.Allocate
-                     <ELFStringSectionChunk<target_endianness, is64Bits>>()) 
-                    ELFStringSectionChunk<target_endianness, is64Bits>
-                             (_options, *this, ".strtab");
-  _strtable->setShStrtableOffset( _shstrtable->addString(".strtab"));
-  _sectionChunks.push_back(_strtable);
-  
-  _symtable = new (_chunkAllocate.Allocate
-                     <ELFSymbolTableChunk<target_endianness, is64Bits>>()) 
-                    ELFSymbolTableChunk<target_endianness, is64Bits>
-                             (_options, *this, ".symtab");
-  _symtable->setShStrtableOffset( _shstrtable->addString(".symtab"));
-  _sectionChunks.push_back(_symtable);
-
-//TODO: implement .hash section
-
-  DEBUG_WITH_TYPE("WriterELF-layout", dbgs() 
-                    << "Atoms in file" << file.path()<<":\n");
-  for (const DefinedAtom *a : file.defined() ) {
-    DEBUG_WITH_TYPE("WriterELF-layout", dbgs() 
-                    << a->name() << " type: " << a->contentType() <<"\n");
-    StringRef sectionName = a->customSectionName();
-    if (a->sectionChoice() == 
-        DefinedAtom::SectionChoice::sectionBasedOnContent) {
-      if (a->contentType() == DefinedAtom::typeZeroFill)
-         sectionName = ".bss";
+void ELFExecutableWriter<target_endianness, is64Bits>::buildSymbolTable () {
+  Section<target_endianness, is64Bits> *section;
+  for (auto si = _layout->sections_begin(); si != _layout->sections_end(); ++si) {
+    if ((*si)->kind() != Chunk<target_endianness, is64Bits>::Section) 
+      continue;
+    section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(*si);
+    for (auto ai = section->atoms_begin(); ai != section->atoms_end(); ++ai) {
+      _symtab->addSymbol(ai->first, section->ordinal(), ai->second.second);
     }
-    auto pos = sectionMap.find(sectionName);
-    DefinedAtom::ContentType type = a->contentType();
-    if (type != DefinedAtom::typeUnknown){
-      if (pos == sectionMap.end()) {
-       StockSectionChunk<target_endianness, is64Bits>
-                  *chunk = new(_chunkAllocate.Allocate
-                               <StockSectionChunk<target_endianness, is64Bits>>
-                               ())StockSectionChunk<target_endianness, is64Bits>
-                                   (sectionName, true, type, _options, *this);
-
-       sectionMap[sectionName] = chunk;
-       chunk->appendAtom(a);
-       _sectionChunks.push_back(chunk);
-       _stockSectionChunks.push_back(chunk);
-                            
-      } else {
-        pos->second->appendAtom(a);
-      }
-    }
   }
+}
 
-  for (auto chnk : _sectionChunks)
-    _chunks.push_back(chnk);
-
-  _sectionHeaderChunk = new (_chunkAllocate.Allocate<ELFSectionHeaderChunk
-                               <target_endianness, is64Bits>>())
-                              ELFSectionHeaderChunk
-                               <target_endianness, is64Bits>(_options, *this); 
-  _chunks.push_back(_sectionHeaderChunk);
-  // We sort the chunks based on the group they belong to
-  std::stable_sort(_chunks.begin(), _chunks.end(), 
-                   chunkGroupSort<target_endianness, is64Bits>);
-  
-  // The CG_RW group also has to be arranged such that all
-  // SHT_NOBITS type of sections (.*bss) are at end of this 
-  // "partition" of group.
-  chunkIterator cI;
-  std::pair<chunkIterator, chunkIterator> range;
-  range = std::equal_range(_chunks.begin() + 2, _chunks.end() - 1, CG_RW, 
-                           ChunkComparator<target_endianness, is64Bits>());
-                           
-  cI = std::stable_partition(range.first, range.second, 
-                             IsBss<target_endianness, is64Bits>);
-
-  // We reassign all the ordinals since its needed when making headers and 
-  // populating symbol table.
-  uint64_t i = 0;
-  for (auto chnk : _chunks) {
-    chnk->setOrdinal(i++);
-  }
-
-  // We sort the sections as per new ordinal set after group sorting.
-  std::stable_sort(_sectionChunks.begin(), _sectionChunks.end(),([]
-  (const SectionChunk<target_endianness, is64Bits> *A, 
-   const SectionChunk<target_endianness, is64Bits> *B) -> bool {
-     return A->ordinal() < B->ordinal();}));
-
-  // Populate symbol table  with correct st_shndx member.
-  for (auto chnk : _sectionChunks ) {
-     Elf_Sym *sym  = new (_chunkAllocate.Allocate<Elf_Sym>()) Elf_Sym;
-     sym->st_name  = 0;
-     sym->st_value = 0;
-     sym->st_size  = 0;
-     sym->st_other = ELF::STV_DEFAULT;
-    // first two chunks are not sections hence we subtract 2 but there is a 
-    // NULL section in section table so add 1
-     sym->st_shndx = chnk->ordinal() - 1 ;
-     sym->setBindingAndType(ELF::STB_LOCAL, ELF::STT_SECTION);
-     _symtable->addSymbol(sym);
-  }
- for (const auto ssc : _stockSectionChunks){
-   for (const auto da : ssc->atoms()) {
-     _symtable->addSymbol(std::get<0>(da), ssc->ordinal() -1);
-   }
- }
+template<support::endianness target_endianness, bool is64Bits>
+void ELFExecutableWriter<target_endianness, is64Bits>::
+                addAbsoluteUndefinedSymbols(const lld::File &file) {
  for (const UndefinedAtom *a : file.undefined()) {
-   _symtable->addSymbol(a, ELF::SHN_UNDEF);
+   _symtab->addSymbol(a, ELF::SHN_UNDEF);
  }
  
  for (const AbsoluteAtom *a : file.absolute()) {
-   _symtable->addSymbol(a, ELF::SHN_ABS);
+   _symtab->addSymbol(a, ELF::SHN_ABS);
  }
 }
 
 template<support::endianness target_endianness, bool is64Bits>
-void ELFWriter<target_endianness, is64Bits>
+void ELFExecutableWriter<target_endianness, is64Bits>
               ::buildAtomToAddressMap () {
-
-// _atomToAddress is a DenseMap that maps an atom its file address.
-// std::get<1>(ai) is the offset from the start of the section to the atom.
-  for (auto chunk : _stockSectionChunks){
-    for (auto &ai : chunk->atoms() ) {
-      _atomToAddress[std::get<0>(ai)] = chunk->address() + std::get<1>(ai);
+  Section<target_endianness, is64Bits> *section;
+  for (auto si = _layout->sections_begin(); 
+       si != _layout->sections_end(); ++si) {
+    if ((*si)->kind() != Chunk<target_endianness, is64Bits>::Section) 
+      continue;
+    section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(*si);
+    for (auto ai = section->atoms_begin(); ai != section->atoms_end(); ++ai) {
+      _atomToAddressMap[ai->first] = (ai)->second.second;
     }
   }
 }
 
 template<support::endianness target_endianness, bool is64Bits>
-void ELFWriter<target_endianness, is64Bits>::assignFileOffsets() {
-  DEBUG_WITH_TYPE("WriterELF-layout", dbgs() 
-                    << "assign file offsets:\n");
-  uint64_t offset = 0;
-  uint64_t address = _options.type() == ELF::ET_REL ? 0 : 
-                                        _options.baseAddress();
-  uint16_t chunkGroup;
-  auto chunkIt = _chunks.begin();
-  // first (two in case of ET_EXEC or ET_DYN) chunks is (are) not  section(s)
-  (*chunkIt)->assignFileOffset(offset, address);
-  chunkIt++;
-  if (_options.type() == ELF::ET_EXEC || 
-      _options.type() == ELF::ET_DYN) {
-    (*chunkIt)->assignFileOffset(offset, address);
-    chunkIt++;
+void ELFExecutableWriter<target_endianness, is64Bits>
+              ::buildSectionHeaderTable() {
+  for (auto msi = _layout->merged_sections_begin(); 
+       msi != _layout->merged_sections_end(); ++msi) {
+    if ((*msi)->kind() != Chunk<target_endianness, is64Bits>::Section) 
+      continue;
+    if ((*msi)->hasSegment())
+      _shdrtab->appendSection(*msi);
   }
-  while (chunkIt != (_chunks.end() - 1) ) {
-    (*chunkIt)->assignFileOffset(offset, address);
-    if (_options.type() == ELF::ET_EXEC || 
-        _options.type() == ELF::ET_DYN) {
-      chunkGroup = (*chunkIt)->group();
-      chunkIt++;
-    // If the chunk group changes we start on new page
-      if (chunkGroup != (*chunkIt)->group() && (*chunkIt)->group() != CG_NO_LOAD 
-                                            && (*chunkIt)->group() != CG_FILE_END)
-        address = address + _options.pageSize();
-    } else {
-      chunkIt++;
-    }
+}
+
+template<support::endianness target_endianness, bool is64Bits>
+void ELFExecutableWriter<target_endianness, is64Bits>
+              ::assignSectionsWithNoSegments() {
+  Section<target_endianness, is64Bits> *section;
+  for (auto msi = _layout->merged_sections_begin(); 
+       msi != _layout->merged_sections_end(); ++msi) {
+    if ((*msi)->kind() != Chunk<target_endianness, is64Bits>::Section) 
+      continue;
+    if (!(*msi)->hasSegment())
+      _shdrtab->appendSection(*msi);
   }
-  (*chunkIt)->assignFileOffset(offset, address);
-  ehc->e_shoff(_sectionHeaderChunk->fileOffset());
+  _layout->assignOffsetsForMiscSections();
+  for (auto si = _layout->sections_begin(); 
+       si != _layout->sections_end(); ++si) {
+    if ((*si)->kind() != Chunk<target_endianness, is64Bits>::Section) 
+      continue;
+    section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(*si);
+    if (!DefaultELFLayout<target_endianness, is64Bits>::hasOutputSegment
+                                                        (section))
+      _shdrtab->updateSection(section);
+  }
 }
 
 template<support::endianness target_endianness, bool is64Bits>
-error_code ELFWriter<target_endianness, is64Bits>
+error_code ELFExecutableWriter<target_endianness, is64Bits>
                     ::writeFile(const lld::File &file, StringRef path) {
-  build(file);
+  buildChunks(file);
+  // Create the default sections like the symbol table, string table, and the
+  // section string table
+  createDefaultSections();
 
-  uint64_t totalSize = _chunks.back()->fileOffset() + _chunks.back()->size();
+  // Set the Layout
+  _layout->assignSectionsToSegments();
+  _layout->assignFileOffset();
+  _layout->assignVirtualAddress();
 
+  // Build the Atom To Address map for applying relocations
+  buildAtomToAddressMap();
+
+  // Create symbol table and section string table
+  buildSymbolTable();
+
+  // add other symbols
+  addAbsoluteUndefinedSymbols(file);
+
+  // Finalize the layout by calling the finalize() functions
+  _layout->finalize();
+
+  // build Section Header table
+  buildSectionHeaderTable();
+
+  // assign Offsets and virtual addresses
+  // for sections with no segments
+  assignSectionsWithNoSegments();
+
+  uint64_t totalSize = _shdrtab->fileOffset() + _shdrtab->filesize();
+
   OwningPtr<FileOutputBuffer> buffer;
   error_code ec = FileOutputBuffer::create(path,
                                            totalSize, buffer,
@@ -1417,28 +2134,80 @@
   if (ec)
     return ec;
 
-  for (auto chunk : _chunks) {
-    chunk->write(buffer->getBufferStart() + chunk->fileOffset());
-  }
+  for (auto si = _layout->sections_begin(); si != _layout->sections_end(); ++si)
+    (*si)->write(this, buffer);
+
+  _elfHeader->e_ident(ELF::EI_CLASS, (_options.is64Bit() ? ELF::ELFCLASS64
+                                                        : ELF::ELFCLASS32));
+  _elfHeader->e_ident(ELF::EI_DATA, (_options.endianness() == llvm::support::big)
+                                    ? ELF::ELFDATA2MSB : ELF::ELFDATA2LSB);
+  _elfHeader->e_ident(ELF::EI_VERSION, 1);
+  _elfHeader->e_ident(ELF::EI_OSABI, 0);
+  _elfHeader->e_type(_options.type());
+  _elfHeader->e_machine(_options.machine());
+  _elfHeader->e_version(1);
+  _elfHeader->e_entry(0ULL);
+  _elfHeader->e_phoff(_programHeader->fileOffset());
+  _elfHeader->e_shoff(_shdrtab->fileOffset());
+  _elfHeader->e_phentsize(_programHeader->entsize());
+  _elfHeader->e_phnum(_programHeader->numHeaders());
+  _elfHeader->e_shentsize(_shdrtab->entsize());
+  _elfHeader->e_shnum(_shdrtab->numHeaders());
+  _elfHeader->e_shstrndx(_shstrtab->ordinal());
+  int64_t startAddr = 0;
+  _layout->findAtomAddrByName("_start", startAddr);
+  _elfHeader->e_entry(startAddr);
+  _elfHeader->write(this, buffer);
+  _programHeader->write(this, buffer);
+
   return buffer->commit();
+
+  return error_code::success();
 }
 
 template<support::endianness target_endianness, bool is64Bits>
-uint64_t ELFWriter<target_endianness, is64Bits>
-                    ::addressOfAtom(const Atom *atom) {
-  return _atomToAddress[atom];
+void ELFExecutableWriter<target_endianness, is64Bits>
+                    ::createDefaultSections() {
+  _elfHeader = new ELFHeader<target_endianness, is64Bits>();
+  _programHeader = new ELFProgramHeader<target_endianness, is64Bits>();
+  _layout->setELFHeader(_elfHeader);
+  _layout->setProgramHeader(_programHeader);
+
+  _symtab = new ELFSymbolTable<target_endianness, is64Bits>
+            (".symtab", 
+            DefaultELFLayout<target_endianness, is64Bits>::ORDER_SYMBOL_TABLE);
+  _strtab = new ELFStringTable<target_endianness, is64Bits>
+          (".strtab", 
+          DefaultELFLayout<target_endianness, is64Bits>::ORDER_STRING_TABLE);
+  _shstrtab = new ELFStringTable<target_endianness, is64Bits>
+          (".shstrtab", 
+          DefaultELFLayout<target_endianness, is64Bits>::ORDER_SECTION_STRINGS);
+  _shdrtab  = new ELFSectionHeader<target_endianness, is64Bits>
+         (DefaultELFLayout<target_endianness, is64Bits>::ORDER_SECTION_HEADERS);
+  _layout->addSection(_symtab);
+  _layout->addSection(_strtab);
+  _layout->addSection(_shstrtab);
+  _shdrtab->setStringSection(_shstrtab);
+  _symtab->setStringSection(_strtab);
+  _layout->addSection(_shdrtab);
 }
+
 } // namespace elf
 
 Writer *createWriterELF(const WriterOptionsELF &options) {
+
+  // Set the default layout to be the static executable layout
+  // We would set the layout to a dynamic executable layout 
+  // if we came across any shared libraries in the process
+  
   if (!options.is64Bit() && options.endianness() == llvm::support::little)
-    return new lld::elf::ELFWriter<support::little, false>(options);
+    return new lld::elf::ELFExecutableWriter<support::little, false>(options);
   else if (options.is64Bit() && options.endianness() == llvm::support::little)
-    return new lld::elf::ELFWriter<support::little, true>(options);
+    return new lld::elf::ELFExecutableWriter<support::little, true>(options);
   else if (!options.is64Bit() && options.endianness() == llvm::support::big)
-    return new lld::elf::ELFWriter<support::big, false>(options);
+    return new lld::elf::ELFExecutableWriter<support::big, false>(options);
   else if (options.is64Bit() && options.endianness() == llvm::support::big)
-    return new lld::elf::ELFWriter<support::big, true>(options);
+    return new lld::elf::ELFExecutableWriter<support::big, true>(options);
 
   llvm_unreachable("Invalid Options!");
 }
Index: lib/ReaderWriter/ELF/HexagonReference.cpp
===================================================================
--- lib/ReaderWriter/ELF/HexagonReference.cpp	(revision 169997)
+++ lib/ReaderWriter/ELF/HexagonReference.cpp	(working copy)
@@ -67,7 +67,7 @@
 /// \brief Word32_LO: 0x00c03fff : (S + A) : Truncate
 int relocLO16(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
   uint32_t result = (uint32_t)(S + A);
-  result = ((result & 0x3fff) | ((result << 2) & 0x00c00000));
+  result = ((result & 0x3fff) | ((result << 8) & 0x00c00000));
   *reinterpret_cast<llvm::support::ulittle32_t *>(location) = result |
             (uint32_t)*reinterpret_cast<llvm::support::ulittle32_t *>(location);
   return HexagonKindHandler::NoError;
@@ -76,7 +76,7 @@
 /// \brief Word32_LO: 0x00c03fff : (S + A) >> 16 : Truncate
 int relocHI16(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
   uint32_t result = (uint32_t)((S + A)>>16);
-  result = ((result & 0x3fff) | ((result << 2) & 0x00c00000));
+  result = ((result & 0x3fff) | ((result << 8) & 0x00c00000));
   *reinterpret_cast<llvm::support::ulittle32_t *>(location) = result |
             (uint32_t)*reinterpret_cast<llvm::support::ulittle32_t *>(location);
   return HexagonKindHandler::NoError;
Index: lib/ReaderWriter/ELF/ReaderELF.cpp
===================================================================
--- lib/ReaderWriter/ELF/ReaderELF.cpp	(revision 169997)
+++ lib/ReaderWriter/ELF/ReaderELF.cpp	(working copy)
@@ -22,6 +22,7 @@
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Casting.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/ELF.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -30,7 +31,7 @@
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/system_error.h"
-#include "llvm/Support/Path.h"
+#include "ELFAtoms.h"
 
 
 #include <map>
@@ -40,415 +41,6 @@
 using namespace lld;
 
 namespace { // anonymous
-
-
-/// \brief Relocation References: Defined Atoms may contain 
-/// references that will need to be patched before
-/// the executable is written.
-template <llvm::support::endianness target_endianness, bool is64Bits>
-class ELFReference final : public Reference {
-
-  typedef llvm::object::Elf_Rel_Impl
-                        <target_endianness, is64Bits, false> Elf_Rel;
-  typedef llvm::object::Elf_Rel_Impl
-                        <target_endianness, is64Bits, true> Elf_Rela;
-public:
-
-  ELFReference(const Elf_Rela *rela, uint64_t offset, const Atom *target)
-    : _target(target)
-    , _targetSymbolIndex(rela->getSymbol())
-    , _offsetInAtom(offset)
-    , _addend(rela->r_addend)
-    , _kind(rela->getType()) {}
-
-  ELFReference(const Elf_Rel *rel, uint64_t offset, const Atom *target)
-    : _target(target)
-    , _targetSymbolIndex(rel->getSymbol())
-    , _offsetInAtom(offset)
-    , _addend(0)
-    , _kind(rel->getType()) {}
-
-
-  virtual uint64_t offsetInAtom() const {
-    return _offsetInAtom;
-  }
-
-  virtual Kind kind() const {
-    return _kind;
-  }
-
-  virtual void setKind(Kind kind) {
-    _kind = kind;
-  }
-
-  virtual const Atom *target() const {
-    return _target;
-  }
-
-/// \brief targetSymbolIndex: This is the symbol table index that contains
-/// the target reference.
-  uint64_t targetSymbolIndex() const {
-    return _targetSymbolIndex;
-  }
-
-  virtual Addend addend() const {
-    return _addend;
-  }
-
-  virtual void setAddend(Addend A) {
-    _addend = A;
-  }
-
-  virtual void setTarget(const Atom *newAtom) {
-    _target = newAtom;
-  }
-private:
-  const Atom  *_target;
-  uint64_t     _targetSymbolIndex;
-  uint64_t     _offsetInAtom;
-  Addend       _addend;
-  Kind         _kind;
-};
-
-
-/// \brief ELFAbsoluteAtom: These atoms store symbols that are fixed to a
-/// particular address.  This atom has no content its address will be used by
-/// the writer to fixup references that point to it.
-template<llvm::support::endianness target_endianness, bool is64Bits>
-class ELFAbsoluteAtom final : public AbsoluteAtom {
-
-  typedef llvm::object::Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
-
-public:
-  ELFAbsoluteAtom(const File &file,
-                  llvm::StringRef name,
-                  const Elf_Sym *symbol,
-                  uint64_t value)
-    : _owningFile(file)
-    , _name(name)
-    , _symbol(symbol)
-    , _value(value)
-  {}
-
-  virtual const class File &file() const {
-    return _owningFile;
-  }
-
-  virtual Scope scope() const {
-    if (_symbol->st_other == llvm::ELF::STV_HIDDEN)
-      return scopeLinkageUnit;
-    if (_symbol->getBinding() == llvm::ELF::STB_LOCAL)
-      return scopeTranslationUnit;
-    else
-      return scopeGlobal;
-  }
-
-  virtual llvm::StringRef name() const {
-    return _name;
-  }
-
-  virtual uint64_t value() const {
-    return _value;
-  }
-
-private:
-  const File &_owningFile;
-  llvm::StringRef _name;
-  const Elf_Sym *_symbol;
-  uint64_t _value;
-};
-
-
-/// \brief ELFUndefinedAtom: These atoms store undefined symbols and are
-/// place holders that will be replaced by defined atoms later in the
-/// linking process.
-template<llvm::support::endianness target_endianness, bool is64Bits>
-class ELFUndefinedAtom final: public UndefinedAtom {
-
-  typedef llvm::object::Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
-
-public:
-  ELFUndefinedAtom(const File &file,
-                   llvm::StringRef name,
-                   const Elf_Sym *symbol)
-    : _owningFile(file)
-    , _name(name)
-    , _symbol(symbol)
-  {}
-
-  virtual const class File &file() const {
-    return _owningFile;
-  }
-
-  virtual llvm::StringRef name() const {
-    return _name;
-  }
-
-  //   FIXME What distinguishes a symbol in ELF that can help
-  //   decide if the symbol is undefined only during build and not
-  //   runtime? This will make us choose canBeNullAtBuildtime and
-  //   canBeNullAtRuntime
-  //
-  virtual CanBeNull canBeNull() const {
-
-    if (_symbol->getBinding() == llvm::ELF::STB_WEAK)
-      return CanBeNull::canBeNullAtBuildtime;
-    else
-      return CanBeNull::canBeNullNever;
-  }
-
-private:
-  const File &_owningFile;
-  llvm::StringRef _name;
-  const Elf_Sym *_symbol;
-};
-
-
-/// \brief ELFDefinedAtom: This atom stores defined symbols and will contain
-/// either data or code.
-template<llvm::support::endianness target_endianness, bool is64Bits>
-class ELFDefinedAtom final: public DefinedAtom {
-
-  typedef llvm::object::Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
-  typedef llvm::object::Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
-
-public:
-  ELFDefinedAtom(const File &file,
-                 llvm::StringRef symbolName,
-                 llvm::StringRef sectionName,
-                 const Elf_Sym *symbol,
-                 const Elf_Shdr *section,
-                 llvm::ArrayRef<uint8_t> contentData,
-                 unsigned int referenceStart,
-                 unsigned int referenceEnd,
-                 std::vector<ELFReference
-                             <target_endianness, is64Bits> *> &referenceList)
-
-    : _owningFile(file)
-    , _symbolName(symbolName)
-    , _sectionName(sectionName)
-    , _symbol(symbol)
-    , _section(section)
-    , _contentData(contentData) 
-    , _referenceStartIndex(referenceStart)
-    , _referenceEndIndex(referenceEnd)
-    , _referenceList(referenceList) {
-    static uint64_t orderNumber = 0;
-    _ordinal = ++orderNumber;
-  }
-
-  virtual const class File &file() const {
-    return _owningFile;
-  }
-
-  virtual llvm::StringRef name() const {
-    return _symbolName;
-  }
-
-  virtual uint64_t ordinal() const {
-    return _ordinal;
-  }
-
-  virtual uint64_t size() const {
-
-    // Common symbols are not allocated in object files,
-    // so use st_size to tell how many bytes are required.
-    if ((_symbol->getType() == llvm::ELF::STT_COMMON)
-        || _symbol->st_shndx == llvm::ELF::SHN_COMMON)
-      return (uint64_t)_symbol->st_size;
-
-    return _contentData.size();
-
-  }
-
-  virtual Scope scope() const {
-    if (_symbol->st_other == llvm::ELF::STV_HIDDEN)
-      return scopeLinkageUnit;
-    else if (_symbol->getBinding() != llvm::ELF::STB_LOCAL)
-      return scopeGlobal;
-    else
-      return scopeTranslationUnit;
-  }
-
-  //   FIXME   Need to revisit this in future.
-
-  virtual Interposable interposable() const {
-    return interposeNo;
-  }
-
-  //  FIXME What ways can we determine this in ELF?
-
-  virtual Merge merge() const {
-
-    if (_symbol->getBinding() == llvm::ELF::STB_WEAK)
-      return mergeAsWeak;
-
-    if ((_symbol->getType() == llvm::ELF::STT_COMMON)
-        || _symbol->st_shndx == llvm::ELF::SHN_COMMON)
-      return mergeAsTentative;
-
-    return mergeNo;
-  }
-
-  virtual ContentType contentType() const {
-
-    ContentType ret = typeUnknown;
-
-    switch (_section->sh_type) {
-    case llvm::ELF::SHT_PROGBITS:
-    case llvm::ELF::SHT_DYNAMIC:
-      switch (_section->sh_flags) {
-      case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR
-            | llvm::ELF::SHF_WRITE):
-        ret = typeCode;
-        break;
-      case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR):
-        ret = typeCode;
-        break;
-      case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE):
-        ret = typeData;
-        break;
-      case llvm::ELF::SHF_ALLOC:
-      case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE):
-      case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE |
-            llvm::ELF::SHF_STRINGS):
-        ret = typeConstant;
-        break;
-      }
-      break;
-    case llvm::ELF::SHT_NOBITS:
-      ret = typeZeroFill;
-      break;
-    case llvm::ELF::SHT_NULL:
-      if ((_symbol->getType() == llvm::ELF::STT_COMMON)
-          || _symbol->st_shndx == llvm::ELF::SHN_COMMON)
-        ret = typeZeroFill;
-      break;
-    }
-
-    return ret;
-  }
-
-  virtual Alignment alignment() const {
-
-    // Unallocated common symbols specify their alignment
-    // constraints in st_value.
-    if ((_symbol->getType() == llvm::ELF::STT_COMMON)
-        || _symbol->st_shndx == llvm::ELF::SHN_COMMON) {
-      return Alignment(llvm::Log2_64(_symbol->st_value));
-    }
-    return Alignment(llvm::Log2_64(_section->sh_addralign));
-  }
-
-  // Do we have a choice for ELF?  All symbols
-  // live in explicit sections.
-  virtual SectionChoice sectionChoice() const {
-    if (_symbol->st_shndx > llvm::ELF::SHN_LORESERVE)
-      return sectionBasedOnContent;
-
-    return sectionCustomRequired;
-  }
-
-  virtual llvm::StringRef customSectionName() const {
-    return _sectionName;
-  }
-
-  // It isn't clear that __attribute__((used)) is transmitted to
-  // the ELF object file.
-  virtual DeadStripKind deadStrip() const {
-    return deadStripNormal;
-  }
-
-  virtual ContentPermissions permissions() const {
-
-    switch (_section->sh_type) {
-    // permRW_L is for sections modified by the runtime
-    // loader.
-    case llvm::ELF::SHT_REL:
-    case llvm::ELF::SHT_RELA:
-      return permRW_L;
-
-    case llvm::ELF::SHT_DYNAMIC:
-    case llvm::ELF::SHT_PROGBITS:
-      switch (_section->sh_flags) {
-
-      case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR):
-        return permR_X;
-
-      case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE):
-        return permRW_;
-
-      case llvm::ELF::SHF_ALLOC:
-      case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE):
-      case (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_MERGE
-            | llvm::ELF::SHF_STRINGS):
-        return permR__;
-      }
-      default:
-        return perm___;
-    }
-  }
-
-  //   Many non ARM architectures use ELF file format
-  //   This not really a place to put a architecture
-  //   specific method in an atom. A better approach is
-  //   needed.
-  //
-  virtual bool isThumb() const {
-    return false;
-  }
-
-  //  FIXME Not Sure if ELF supports alias atoms. Find out more.
-  virtual bool isAlias() const {
-    return false;
-  }
-
-  virtual llvm::ArrayRef<uint8_t> rawContent() const {
-    return _contentData;
-  }
-
-  DefinedAtom::reference_iterator begin() const {
-    uintptr_t index = _referenceStartIndex;
-    const void *it = reinterpret_cast<const void*>(index);
-    return reference_iterator(*this, it);
-  }
-
-  DefinedAtom::reference_iterator end() const {
-    uintptr_t index = _referenceEndIndex;
-    const void *it = reinterpret_cast<const void*>(index);
-    return reference_iterator(*this, it);
-  }
-
-  const Reference *derefIterator(const void *It) const {
-    uintptr_t index = reinterpret_cast<uintptr_t>(It);
-    assert(index >= _referenceStartIndex);
-    assert(index < _referenceEndIndex);
-    return ((_referenceList)[index]);
-  }
-
-  void incrementIterator(const void*& It) const {
-    uintptr_t index = reinterpret_cast<uintptr_t>(It);
-    ++index;
-    It = reinterpret_cast<const void*>(index);
-  }
-
-private:
-
-  const File &_owningFile;
-  llvm::StringRef _symbolName;
-  llvm::StringRef _sectionName;
-  const Elf_Sym *_symbol;
-  const Elf_Shdr *_section;
-  // _contentData will hold the bits that make up the atom.
-  llvm::ArrayRef<uint8_t> _contentData;
-
-  uint64_t _ordinal;
-  unsigned int _referenceStartIndex;
-  unsigned int _referenceEndIndex;
-  std::vector<ELFReference<target_endianness, is64Bits> *> &_referenceList;
-};
-
-
 //   FileELF will read a binary, find out based on the symbol table contents
 //   what kind of symbol it is and create corresponding atoms for it
 
@@ -644,7 +236,6 @@
         symbolData = llvm::ArrayRef<uint8_t>((uint8_t *)symbolContents.data()
                                     + (*si)->st_value, contentSize);
 
-
         unsigned int referenceStart = _references.size();
 
         // Only relocations that are inside the domain of the atom are 
@@ -683,7 +274,7 @@
                        <ELFDefinedAtom<target_endianness, is64Bits> > ()) 
                         ELFDefinedAtom<target_endianness, is64Bits>
                            (*this, symbolName, sectionName,
-                             *si, i.first, symbolData,
+                             *si, i.first, symbolData, 
                              referenceStart, _references.size(), _references);
 
         _definedAtoms._atoms.push_back(newAtom);
Index: lib/Core/SymbolTable.cpp
===================================================================
--- lib/Core/SymbolTable.cpp	(revision 169997)
+++ lib/Core/SymbolTable.cpp	(working copy)
@@ -73,7 +73,7 @@
   },
   {
     // first is absolute
-    NCR_Error,  NCR_Error,  NCR_First, NCR_First
+    NCR_Error,  NCR_First,  NCR_First, NCR_First
   },
   {
     // first is undef


More information about the llvm-commits mailing list