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

Shankar Easwaran shankare at codeaurora.org
Fri Dec 21 14:23:10 PST 2012


Hi Michael,

Attached is the new diff after the review with the test case changes.

You would need to apply the other changes that were in the previous 
patches to build.

a) ELFAtoms.h
b) ReaderELF changes
c) HexagonRelocation changes

OK to commit ?

Thanks

Shankar Easwaran

On 12/21/2012 11:11 AM, Michael Spencer wrote:
>
> ================
> Comment at: lib/ReaderWriter/ELF/WriterELF.cpp:80-86
> @@ +79,9 @@
> +  /// \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),
> ----------------
> Shankar Kalpathi Easwaran wrote:
>> Michael Spencer wrote:
>>> This either needs to be an enum class, or the members need to follow the naming convention. Currently this breaks MSVC because it doesn't do two phase name lookup and therefore sees Section and Segment in the derived class (Chunk) instead of the templates Section and Segment.
>> Changed the names to add ELF in the front
> http://llvm.org/docs/CodingStandards.html#name-types-functions-variables-and-enumerators-properly
>
> They should start with K_
>
> ================
> Comment at: lib/ReaderWriter/ELF/WriterELF.cpp:121-123
> @@ +120,5 @@
> +  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; }
> ----------------
> Shankar Kalpathi Easwaran wrote:
>> Michael Spencer wrote:
>>> What is the difference between these two function? Is one the virtual address?
>> yes.
> Then the names could be improved and a \brief added.
>
> ================
> Comment at: lib/ReaderWriter/ELF/WriterELF.cpp:549
> @@ -235,1 +548,3 @@
> +  void setOrdinal(int64_t ordinal) {
> +    ordinal = ordinal;
>     }
> ----------------
> Shankar Kalpathi Easwaran wrote:
>> Michael Spencer wrote:
>>>    _ordinal = ordinal;
>> Nice catch.
> Clang -Wall caught it for me :P
>
> ================
> Comment at: lib/ReaderWriter/ELF/WriterELF.cpp:1008
> @@ +1007,3 @@
> +  static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
> +    return c->kind() == Section<target_endianness, is64Bits>::StringTable;
> +  }
> ----------------
> Shankar Kalpathi Easwaran wrote:
>> Michael Spencer wrote:
>>> This is broken. Chunk already has a Kind with the same value.
>> Chunk doesnot have such a type called StringTable.
> Not named StringTable. But StringTable shares the same underlying value as Chunk::Segment
>
> ================
> Comment at: lib/ReaderWriter/ELF/WriterELF.cpp:1491-1502
> @@ -826,1 +1490,14 @@
> +      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;
>   
> ----------------
> Shankar Kalpathi Easwaran wrote:
>> Michael Spencer wrote:
>>> llvm::StringSwitch in llvm/ADT/StringSwitch.h
>> How do you do startswith with StringSwitch ?
> .StartsWith("") instead of .Case("").
>
> https://github.com/Bigcheese/llvm/blob/master/lib/Object/COFFObjectFile.cpp#L214
>
>
> http://llvm-reviews.chandlerc.com/D222
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
>


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

-------------- next part --------------
Index: elf/sections.objtxt
===================================================================
--- elf/sections.objtxt	(revision 170923)
+++ elf/sections.objtxt	(working copy)
@@ -2,22 +2,22 @@
 RUN: llvm-readobj  %t1 |  FileCheck -check-prefix=READOBJ %s 
 RUN: elf-dump  --dump-section %t1 |  FileCheck -check-prefix=ED %s 
 
-OBJDUMP:  0 000000000 00000000000000000
-OBJDUMP:  1 .text         00000000a 00000000000400074 TEXT DATA
-OBJDUMP:  2 .data         000000004 00000000000401080 DATA
-OBJDUMP:  3 .special      000000004 00000000000401084 DATA
-OBJDUMP:  4 .anotherspecial 000000004 00000000000401088 DATA
-OBJDUMP:  5 .bss          000000001 0000000000040108c BSS
-OBJDUMP:  6 .shstrtab     000000045 0000000000040108d
-OBJDUMP:  7 .strtab       00000003b 000000000004010d2
-OBJDUMP:  8 .symtab       000000140 00000000000401110
+OBJDUMP:  0               000000000 00000000000000000
+OBJDUMP:  1 .text         00000000a 00000000000000000 TEXT DATA
+OBJDUMP:  2 .data         000000004 00000000000001000 DATA
+OBJDUMP:  3 .special      000000004 00000000000001004 DATA
+OBJDUMP:  4 .anotherspecial 000000004 00000000000001008 DATA
+OBJDUMP:  5 .bss          000000001 0000000000000100c BSS
+OBJDUMP:  6 .shstrtab     000000045 00000000000000000
+OBJDUMP:  7 .symtab       0000000c0 00000000000000000
+OBJDUMP:  8 .strtab       00000003b 00000000000000000
 
 READOBJ: File Format : ELF32-i386
 READOBJ: Arch        : i386
 READOBJ: Address Size: 32 bits
 READOBJ: Symbols
-READOBJ: baz                               FUNC                 400074                 a                4000e8  global
-READOBJ: y                                 DATA                 401084                 4                401108  global
+READOBJ: baz                               FUNC                 0                 a              1000  global
+READOBJ: y                                 DATA              1004                 4              3008  global
 
 ED: 'e_indent[EI_DATA]', 0x01
 ED: 'e_machine', 0x0003
@@ -27,8 +27,8 @@
 ED: 'sh_addralign', 0x00000004
 ED: Section 6
 ED: 'sh_link', 0x00000000
-ED: 'sh_addralign', 0x00000000
-ED: Section 8
-ED: 'sh_link', 0x00000007
-ED: 'sh_addralign', 0x00000004
+ED: 'sh_addralign', 0x00000001
+ED: Section 7
+ED: 'sh_link', 0x00000008
+ED: 'sh_addralign', 0x00000008
 ED: 'sh_entsize', 0x00000010
Index: elf/rodata.objtxt
===================================================================
--- elf/rodata.objtxt	(revision 170923)
+++ elf/rodata.objtxt	(working copy)
@@ -3,5 +3,5 @@
 
   i386: 2 .rodata       000000004
 
-  hexagon: 2 .rodata       000000004
+  hexagon: 3 .rodata       000000004
 
Index: elf/phdr.objtxt
===================================================================
--- elf/phdr.objtxt	(revision 170923)
+++ elf/phdr.objtxt	(working copy)
@@ -1,17 +1,42 @@
 RUN: lld-core -reader ELF -writer ELF -o %t1 %p/Inputs/phdr.i386 | elf-dump %t1 |  FileCheck -check-prefix=ED %s 
 
-ED: # Program Header 0
-ED: 'p_flags', 0x00000005
-ED: 'p_filesz', 0x0000002a
-ED: # Program Header 1
-ED: 'p_flags', 0x00000004
-ED: 'p_vaddr', 0x004010e0
-ED: 'p_memsz', 0x00000078
-ED: # Program Header 2
-ED: 'p_flags', 0x00000006
-ED: 'p_vaddr', 0x00402158
-ED: 'p_memsz', 0x000000ac
-ED: # Program Header 3
-ED: 'p_flags', 0x00000006
-ED: 'p_vaddr', 0x00404000
-ED: 'p_memsz', 0x00000005
+ED:  # Program Header 0
+ED:  (('p_type', 0x00000001)
+ED:   ('p_flags', 0x00000005)
+ED:   ('p_offset', 0x00001000)
+ED:   ('p_vaddr', 0x00000000)
+ED:   ('p_paddr', 0x00000000)
+ED:   ('p_filesz', 0x00000025)
+ED:   ('p_memsz', 0x00000025)
+ED:   ('p_align', 0x00001000)
+ED:  ),
+ED:  # Program Header 1
+ED:  (('p_type', 0x00000001)
+ED:   ('p_flags', 0x00000006)
+ED:   ('p_offset', 0x00002000)
+ED:   ('p_vaddr', 0x00001000)
+ED:   ('p_paddr', 0x00001000)
+ED:   ('p_filesz', 0x00000104)
+ED:   ('p_memsz', 0x00000004)
+ED:   ('p_align', 0x00001000)
+ED:  ),
+ED:  # Program Header 2
+ED:  (('p_type', 0x00000001)
+ED:   ('p_flags', 0x00000006)
+ED:   ('p_offset', 0x00004000)
+ED:   ('p_vaddr', 0x00004000)
+ED:   ('p_paddr', 0x00004000)
+ED:   ('p_filesz', 0x00000004)
+ED:   ('p_memsz', 0x00004005)
+ED:   ('p_align', 0x00001000)
+ED:  ),
+ED:  # Program Header 3
+ED:  (('p_type', 0x00000001)
+ED:   ('p_flags', 0x00000004)
+ED:   ('p_offset', 0x00005000)
+ED:   ('p_vaddr', 0x00009000)
+ED:   ('p_paddr', 0x00009000)
+ED:   ('p_filesz', 0x0000008c)
+ED:   ('p_memsz', 0x0000008c)
+ED:   ('p_align', 0x00001000)
+ED:  ),
Index: elf/reloc.objtxt
===================================================================
--- elf/reloc.objtxt	(revision 170923)
+++ elf/reloc.objtxt	(working copy)
@@ -44,19 +44,19 @@
 ELF-i386:        target:            puts
 
 ELF-i386:    - name:              .comment
-ELF-i386:      type:              unknown
+ELF-i386:      type:              constant
 ELF-i386:      section-choice:    custom-required
 ELF-i386:      section-name:      .comment
 ELF-i386:      content:           [ 00, 47, 43, 43, 3A, 20, 28, 47, 4E, 55, 29, 20, 
 ELF-i386:                           34, 2E, 37, 2E, 30, 00 ]
 
 ELF-i386:    - name:              .note.GNU-stack
-ELF-i386:      type:              unknown
+ELF-i386:      type:              code
 ELF-i386:      section-choice:    custom-required
 ELF-i386:      section-name:      .note.GNU-stack
 
 ELF-i386:    - name:              .eh_frame
-ELF-i386:      type:              constant
+ELF-i386:      type:              code
 ELF-i386:      section-choice:    custom-required
 ELF-i386:      section-name:      .eh_frame
 ELF-i386:      content:           [ 14, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 52, 00, 
-------------- next part --------------
Index: WriterELF.cpp
===================================================================
--- WriterELF.cpp	(revision 170923)
+++ WriterELF.cpp	(working copy)
@@ -11,20 +11,20 @@
 #include "ReferenceKinds.h"
 
 #include "lld/Core/DefinedAtom.h"
+#include "llvm/Object/ELF.h"
 #include "lld/Core/File.h"
 #include "lld/Core/InputFiles.h"
 #include "lld/Core/Reference.h"
 #include "lld/Core/SharedLibraryAtom.h"
-
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
-
-#include "llvm/Object/ELF.h"
-
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ELF.h"
@@ -34,1382 +34,2020 @@
 #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 {
+    K_ELFHeader, // ELF Header
+    K_ELFProgramHeader, // Program Header
+    K_ELFSegment, // Segment
+    K_ELFSection, // Section
+    K_ELFSectionHeader // Section header
+  };
+  Chunk(StringRef name, Kind kind) 
+    : _name(name)
+    , _kind(kind)
+    , _fsize(0)
+    , _msize(0)
+    , _align2(0)
+    , _order(0)
+    , _ordinal(1)
+    , _start(0)
+    , _fileoffset(0) {}
   virtual             ~Chunk() {}
-  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() const {
+    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;
+
+  // 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               setVAddr(int64_t start) { _start = start; }
+  int64_t            virtualAddr() 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;
+
 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 assignFileOffsets() = 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 {
+    K_Default = 0x100,
+    K_SymbolTable,
+    K_StringTable,
+  };
+  // Create a section object, the section is set to the default type if the
+  // caller doesnot set it
+  Section(const StringRef sectionName, 
+          const int32_t contentType,
+          const int32_t contentPermissions,
+          const int32_t order,
+          const Kind kind = K_Default) 
+    : Chunk<target_endianness, is64Bits>
+      (sectionName, Chunk<target_endianness, is64Bits>::K_ELFSection)
+    , _contentType(contentType)
+    , _contentPermissions(contentPermissions)
+    , _sectionKind(kind)
+    , _entSize(0)
+    , _shInfo(0)
+    , _link(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;
+  /// Align the offset to the required modulus defined by the atom alignment
+  uint64_t alignOffset(uint64_t offset, DefinedAtom::Alignment &atomAlign) {
+    uint64_t requiredModulus = atomAlign.modulus;
+    int64_t align2 = 1 << atomAlign.powerOf2;
+    uint64_t currentModulus = (offset % align2);
+    uint64_t retOffset = offset;
+    if (currentModulus != requiredModulus) {
+      if (requiredModulus > currentModulus)
+        retOffset += requiredModulus - currentModulus;
+      else
+        retOffset += align2 + requiredModulus - currentModulus;
+    }
+    return retOffset;
+  }
 
-/// \brief 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);
+  // \brief Append an atom to a Section. The atom gets pushed into a vector 
+  // contains the atom, the atom file offset, the atom virtual address
+  // the atom file offset is aligned appropriately as set by the Reader
+  void appendAtom(const Atom *atom) {
+    Atom::Definition atomType = atom->definition();
+    const DefinedAtom *definedAtom = 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;
+    // Align the atom to the required modulus/ align the file offset and the 
+    // memory offset seperately this is required so that BSS symbols are handled
+    // properly as the BSS symbols only occupy memory size and not file size
+    uint64_t fOffset = alignOffset(this->fileSize(), atomAlign);
+    uint64_t mOffset = alignOffset(this->memSize(), atomAlign);
+    switch (atomType) {
+    case Atom::definitionRegular:
+      switch(definedAtom->contentType()) {
+      case  DefinedAtom::typeCode:
+      case  DefinedAtom::typeData:
+        _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:
+      llvm_unreachable("Expecting only definedAtoms being passed here");
+      break;
+    } 
+    // Set the section alignment to the largest alignment 
+    this->_align2 = std::max(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) {
+      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 assignOffsets(int64_t offset) {
+    for (auto &ai : _atoms) {
+      ai.second.first = offset + ai.second.first;
+    }
+  }
+
+  /// \brief Find the Atom address given a name, this is needed to to properly 
+  ///  apply relocation. The section class calls this to find the atom address
+  ///  to fix the relocation
+  bool findAtomAddrByName(const StringRef name, int64_t &addr) {
+    for (auto ai : _atoms) {
+      if (ai.first->name() == name) {
+        addr = ai.second.second;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /// \brief Does the Atom occupy any disk space
+  bool occupiesNoDiskSpace() const {
+    return _contentType == DefinedAtom::typeZeroFill;
+  }
+
+  /// \brief The permission of the section is the most permissive permission 
+  /// of all atoms that the section contains
+  void setContentPermissions(int32_t perm) {
+    _contentPermissions = std::max(perm, _contentPermissions);
+  }
+
+  /// \brief Get the section flags, defined by the permissions of the section
+  int64_t flags() {
+    switch (_contentPermissions) {
+    case DefinedAtom::perm___:
+      return 0;
+
+    case DefinedAtom::permR__:
+        return llvm::ELF::SHF_ALLOC;
   
+    case DefinedAtom::permR_X:
+        return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR;
+  
+    case DefinedAtom::permRW_:
+    case DefinedAtom::permRW_L:
+        return llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE;
+  
+    case DefinedAtom::permRWX:
+        return llvm::ELF::SHF_ALLOC | 
+                llvm::ELF::SHF_WRITE | 
+                llvm::ELF::SHF_EXECINSTR;
+
+    default:
+        break;
+    }
+    return llvm::ELF::SHF_ALLOC;
+  }
+
+  /// \brief Return the raw flags, we need this to sort segments
+  int64_t atomflags() const {
+    return _contentPermissions;
+  }
+
+  /// \brief Return the section type, the returned value is recorded in the 
+  /// sh_type field of the Section Header
+  int type() {
+    switch (_contentType) {
+    case DefinedAtom::typeCode:
+    case DefinedAtom::typeData:
+    case DefinedAtom::typeConstant:
+      return llvm::ELF::SHT_PROGBITS;
+
+    case DefinedAtom::typeZeroFill:
+     return llvm::ELF::SHT_NOBITS;
+
+    // Case to handle section types
+    // Symtab, String Table ...
+    default:
+     return _contentType;
+    }
+  }
+
+  /// \brief Returns the section link field, the returned value is 
+  ///        recorded in the sh_link field of the Section Header
+  int link() const {
+    return _link;
+  }
+
+  void setLink(int32_t link) {
+    _link = link;
+  }
+
+  /// \brief Returns the section entsize field, the returned value is 
+  ///        recorded in the sh_entsize field of the Section Header
+  int entsize() const {
+    return _entSize;
+  }
+
+  /// \brief Returns the shinfo field, the returned value is 
+  ///        recorded in the sh_info field of the Section Header
+  int shinfo() const { 
+    return _shInfo;
+  }
+
+  /// \brief Records the segmentType, that this section belongs to
+  void setSegment(const ELFLayout::SegmentType segmentType) {
+    _segmentType = segmentType;
+  }
+
+  /// \brief convert the segment type to a String for diagnostics
+  ///        and printing purposes
+  StringRef segmentKindToStr() const {
+    switch(_segmentType) {
+    case llvm::ELF::PT_INTERP:
+      return "INTERP";
+    case llvm::ELF::PT_LOAD:
+      return "LOAD";
+    case llvm::ELF::PT_GNU_EH_FRAME:
+      return "EH_FRAME";
+    case llvm::ELF::PT_NOTE:
+      return "NOTE";
+    case llvm::ELF::PT_DYNAMIC:
+      return "DYNAMIC";
+    case llvm::ELF::PT_GNU_RELRO:
+      return "RELRO";
+    case llvm::ELF::PT_NULL:
+      return "NULL";
+    default:
+      return "UNKNOWN";
+    }
+  }
+
+  /// \brief for LLVM style RTTI information
   static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
-    return c->getChunkKind() == Chunk<target_endianness, is64Bits>::Kind
-                                                                  ::Section;
+    return c->kind() == Chunk<target_endianness, is64Bits>::K_ELFSection;
   }
+
+  /// \brief Finalize the section contents before writing
+  void finalize() { }
+
+  /// \brief Write the section and the atom contents to the buffer 
+  void write(ELFWriter *writer, 
+             OwningPtr<FileOutputBuffer> &buffer) {
+    uint8_t *chunkBuffer = buffer->getBufferStart();
+    for (auto &ai : _atoms) {
+      const DefinedAtom *definedAtom = 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());
+        else
+          assert(0 && "Found the target to be NULL");
+        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 MergedSections represents a set of sections grouped by the same name
+///        The output file that gets written by the linker has sections grouped
+///        by similiar names
 template<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 MergedSections {
+public:
+  MergedSections(StringRef name) 
+    : _name(name)
+    ,_hasSegment(false)
+    ,_ordinal(0)
+    ,_flags(0)
+    ,_size(0)
+    ,_memSize(0)
+    ,_fileOffset(0)
+    ,_virtualAddr(0)
+    ,_shInfo(0)
+    ,_entSize(0)
+    ,_link(0)
+    ,_align2(0)
+    ,_kind(0)
+    ,_type(0) { }
+                                  
+  // Set the MergedSections is associated with a segment
+  void setHasSegment() { _hasSegment = true; }
 
-/// \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) {
+    _virtualAddr = addr;
+  }
+
+  // Appends a section into the list of sections that are part of this Merged
+  // Section
+  void appendSection(Chunk<target_endianness, is64Bits> *c) {
+    if (c->align2() > _align2) 
+      _align2 = c->align2();
+    if (c->kind() == Chunk<target_endianness, is64Bits>::K_ELFSection) {
+      Section<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 
+                                                                     ChunkIter;
+
+  ChunkIter begin_sections() { return _sections.begin(); }
+
+  ChunkIter 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 virtualAddr() const { return _virtualAddr; }
+
+  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 _virtualAddr;
+  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<Section<target_endianness, is64Bits> *>::iterator 
+                                                                    sectionIter;
 
-  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) {
+    _startSection = s;
+    _endSection = e+1;
+    _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 setSections(sectionIter start, sectionIter end) {
+    _startSectionIter = start;
+    _endSectionIter = 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 startSection() const { return _startSection; }
+
+  // Return the start address of the slice
+  int64_t virtualAddr() 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 setVAddr(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->startSection() < b->startSection());
+  }
+
+  // Functions to run through the slice
+  sectionIter sections_begin() { return _startSectionIter; }
+
+  sectionIter sections_end() { return _endSectionIter; }
+
 private:
-  Elf_Ehdr             _eh;
+  int32_t _startSection;
+  int32_t _endSection;
+  sectionIter _startSectionIter;
+  sectionIter _endSectionIter;
+  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<Section<target_endianness, is64Bits> *>::iterator SectionIter;
+
+  Segment(const StringRef name,
+          const ELFLayout::SegmentType type,
+          const WriterOptionsELF &options)
+    : Chunk<target_endianness, is64Bits>(name
+    , Chunk<target_endianness, is64Bits>::K_ELFSegment)
+    , _segmentType(type)
+    , _flags(0)
+    , _atomflags(0)
+    , _options(options) {
+    this->_align2 = 0;
+    this->_fsize = 0;
   }
+
+  /// append a section to a segment
+  void append(Section<target_endianness, is64Bits> *section) {
+    _sections.push_back(section);
+    if (_flags < section->flags())
+      _flags = section->flags();
+    if (_atomflags < section->atomflags())
+      _atomflags = section->atomflags();
+    if (this->_align2 < section->align2())
+      this->_align2 = section->align2();
+  }
+
+  /// Sort segments depending on the property
+  /// If we have a Program Header segment, it should appear first
+  /// If we have a INTERP segment, that should appear after the Program Header
+  /// All Loadable segments appear next in this order
+  /// All Read Write Execute segments follow
+  /// All Read Execute segments appear next
+  /// All Read only segments appear first
+  /// All Write execute segments follow 
+  static bool compareSegments(Segment<target_endianness, is64Bits> *sega, 
+                              Segment<target_endianness, is64Bits> *segb)
+  {
+
+    if (sega->atomflags() < segb->atomflags()) 
+      return false;
+    return true;
+  }
+
+  /// \brief Start assigning file offset to the segment chunks The fileoffset
+  /// needs to be page at the start of the segment and in addition the
+  /// fileoffset needs to be aligned to the max section alignment within the
+  /// segment. This is required so that the ELF property p_poffset % p_align =
+  /// p_vaddr mod p_align holds true.
+  /// The algorithm starts off by assigning the startOffset thats passed in as
+  /// parameter to the first section in the segment, if the difference between
+  /// the newly computed offset is greater than a page, then we create a segment
+  /// slice, as it would be a waste of virtual memory just to be filled with 
+  /// zeroes
+  void assignOffsets(int64_t startOffset) {
+    int startSection = 0;
+    int currSection = 0;
+    SectionIter startSectionIter, endSectionIter;
+    // slice align is set to the max alignment of the chunks that are 
+    // contained in the slice
+    int64_t sliceAlign = 0;
+    // Current slice size
+    int64_t curSliceSize = 0;
+    // Current Slice File Offset
+    int64_t curSliceFileOffset = 0;
+
+    startSectionIter = _sections.begin();
+    endSectionIter = _sections.end();
+    startSection = 0;
+    bool isFirstSection = true;
+    for (auto si = _sections.begin(); si != _sections.end(); ++si) {
+      if (isFirstSection) {
+        // align the startOffset to the section alignment
+        int64_t newOffset = llvm::RoundUpToAlignment(startOffset, (*si)->align2());
+        curSliceFileOffset = newOffset;
+        sliceAlign = (*si)->align2();
+        this->setFileOffset(startOffset);
+        (*si)->setFileOffset(newOffset);
+        curSliceSize = (*si)->fileSize();
+        isFirstSection = false;
+      } else {
+        uint64_t curOffset = curSliceFileOffset + curSliceSize;
+        uint64_t newOffset = llvm::RoundUpToAlignment(curOffset, (*si)->align2());
+        SegmentSlice<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()) {
+          // TODO: use std::find here
+          for (auto sei = slices_begin(); sei != slices_end(); ++sei) {
+            if ((*sei)->startSection() == startSection) {
+              slice = *sei;
+              break;
+            }
+          }
+          if (!slice) {
+            slice = new (_segmentAllocate.Allocate
+                         <SegmentSlice<target_endianness, is64Bits>>()) 
+                         SegmentSlice<target_endianness, is64Bits>();
+            _segmentSlices.push_back(slice);
+          }
+          slice->set(curSliceFileOffset, startSection, currSection);
+          slice->setSections(startSectionIter, endSectionIter);
+          slice->setSize(curSliceSize);
+          slice->setAlign(sliceAlign);
+          int64_t newPageOffset = llvm::RoundUpToAlignment(curOffset, _options.pageSize());
+          newOffset = llvm::RoundUpToAlignment(newPageOffset, (*si)->align2());
+          curSliceFileOffset = newOffset;
+          startSectionIter = endSectionIter;
+          startSection = currSection;
+          (*si)->setFileOffset(curSliceFileOffset);
+          curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
+          sliceAlign = (*si)->align2();
+        }
+        else {
+          if (sliceAlign < (*si)->align2())
+            sliceAlign = (*si)->align2();
+          (*si)->setFileOffset(newOffset);
+          curSliceSize = newOffset - curSliceFileOffset + (*si)->fileSize();
+        }
+      }
+      currSection++;
+      endSectionIter = si;
+    }
+    SegmentSlice<target_endianness, is64Bits> *slice = nullptr;
+    for (auto sei = slices_begin(); sei != slices_end(); ++sei) {
+      // TODO: add std::find
+      if ((*sei)->startSection() == startSection) {
+        slice = *sei;
+        break;
+      }
+    }
+    if (!slice) {
+      slice = new (_segmentAllocate.Allocate
+                   <SegmentSlice<target_endianness, is64Bits>>()) 
+                   SegmentSlice<target_endianness, is64Bits>();
+      _segmentSlices.push_back(slice);
+    }
+    slice->set(curSliceFileOffset, startSection, currSection);
+    slice->setSections(startSectionIter, _sections.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) {
+    for (auto sei = slices_begin(), see = slices_end(); sei != see; ++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)->setVAddr(this->virtualAddr());
+      else {
+        // Align to a page
+        addr = llvm::RoundUpToAlignment(addr, _options.pageSize());
+        // Align to the slice alignment
+        addr = llvm::RoundUpToAlignment(addr, (*sei)->align2());
+      }
+      bool virtualAddressSet = false;
+      for (auto si = (*sei)->sections_begin(), se = (*sei)->sections_end(); 
+                                               si != se; ++si) {
+        // Align the section address
+        addr = llvm::RoundUpToAlignment(addr, (*si)->align2());
+        if (!isFirstSegment && !virtualAddressSet) {
+          (*sei)->setVAddr(addr);
+          virtualAddressSet = true;
+        }
+        (*si)->setVAddr(addr);
+        (*si)->assignVirtualAddress(addr);
+        (*si)->setMemSize(addr - (*si)->virtualAddr());
+      }
+      (*sei)->setMemSize(addr - (*sei)->virtualAddr());
+    }
+  }
+
+  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(), see = slices_end(); sei != see; ++sei) {
+      for (auto si = (*sei)->sections_begin(), se = (*sei)->sections_end(); 
+                                               si != se; ++si) {
+        (*si)->write(writer, buffer);
+      }
+    }
+  }
+
+  // Finalize the segment, before we want to write to the output file
+  void finalize() { }
+
+  // For LLVM RTTI 
   static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
-    return c->getChunkKind() ==  Chunk<target_endianness, is64Bits>::Kind
-                                                                   ::Header;
+    return c->kind() == Chunk<target_endianness, is64Bits>::K_ELFSegment;
   }
 
+  // Getters
+  int32_t sectionCount() const {
+    return _sections.size();
+  }
+
+  ELFLayout::SegmentType segmentType() { return _segmentType; }
+
+  int pageSize() const { return _options.pageSize(); }
+
+  int64_t atomflags() const { return _atomflags; }
+
+  int64_t flags() const {
+    int64_t fl = 0;
+    if (_flags & llvm::ELF::SHF_ALLOC)
+      fl |= llvm::ELF::PF_R;
+    if (_flags & llvm::ELF::SHF_WRITE)
+      fl |= llvm::ELF::PF_W;
+    if (_flags & llvm::ELF::SHF_EXECINSTR)
+      fl |= llvm::ELF::PF_X;
+    return fl;
+  }
+
+  int64_t numSlices() const {
+    return _segmentSlices.size();
+  }
+
 private:
-  const WriterOptionsELF                 &_options;
-  ELFWriter<target_endianness, is64Bits> &_writer;
-  llvm::BumpPtrAllocator                  _sectionAllocate;
-  std::vector<Elf_Shdr*>                  _sectionInfo;
+  std::vector<Section<target_endianness, is64Bits> *> _sections;
+  std::vector<SegmentSlice<target_endianness, is64Bits> *> _segmentSlices;
+  ELFLayout::SegmentType _segmentType;
+  int64_t _flags;
+  int64_t _atomflags;
+  const WriterOptionsELF _options;
+  llvm::BumpPtrAllocator _segmentAllocate;
 };
 
-/// \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>::K_StringTable) {
+    // the string table has a NULL entry for which
+    // add an empty string
+    _strings.push_back("");
+    this->_fsize = 1;
+    this->_align2 = 1;
+    this->setOrder(order);
+  }
 
+  static inline bool classof(ELFStringTable<target_endianness, is64Bits> *s) {
+    return true;
+  }
+
+  static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
+    return c->kind() == Section<target_endianness, is64Bits>::K_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) {
+      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>::K_SymbolTable) {
+    this->setOrder(order);
+    Elf_Sym *symbol = new (_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
+    memset ((void *)symbol,0, sizeof(Elf_Sym));
+    _symbolTable.push_back(symbol);
+    this->_entSize = sizeof(Elf_Sym);
+    this->_fsize = sizeof(Elf_Sym);
+    this->_align2 = sizeof(void *);
+  }
+
+  static inline bool classof(ELFSymbolTable<target_endianness, is64Bits> *s) {
+    return true;
+  }
+
+  static inline bool classof(const Chunk<target_endianness, is64Bits> *c) {
+    return c->kind() == Section<target_endianness, is64Bits>::K_SymbolTable;
+  }
+
+  void addSymbol(const Atom *atom, int32_t sectionIndex, int64_t addr = 0) {
+    Elf_Sym *symbol = new(_symbolAllocate.Allocate<Elf_Sym>()) Elf_Sym;
+    unsigned char binding = 0, type = 0;
+    symbol->st_name = _stringSection->addString(atom->name());
+    symbol->st_size = 0;
+    symbol->st_shndx = sectionIndex;
+    symbol->st_value = 0;
+    symbol->st_other = ELF::STV_DEFAULT;
+    if (const DefinedAtom *da = llvm::dyn_cast<const DefinedAtom>(atom)){
+      symbol->st_size = da->size();
+      lld::DefinedAtom::ContentType ct;
+      switch (ct = da->contentType()){
+      case  DefinedAtom::typeCode:
+        symbol->st_value = addr;
+        type = ELF::STT_FUNC;
+        break;
+      case  DefinedAtom::typeData:
+        symbol->st_value = addr;
+        type = ELF::STT_OBJECT;
+        break;
+      case  DefinedAtom::typeZeroFill:
+        type = ELF::STT_COMMON;
+        symbol->st_value = addr;
+        break;
+      default:
+        type = ELF::STT_NOTYPE;
+      }
+      if (da->scope() == DefinedAtom::scopeTranslationUnit)  
+        binding = ELF::STB_LOCAL;
+      else
+        binding = ELF::STB_GLOBAL;
+    } else if (const AbsoluteAtom *aa = llvm::dyn_cast<const AbsoluteAtom>(atom)){
+      type = ELF::STT_OBJECT;
+      symbol->st_shndx = ELF::SHN_ABS;
+      switch (aa->scope()) {
+      case AbsoluteAtom::scopeLinkageUnit:
+        symbol->st_other = ELF::STV_HIDDEN;
+        binding = ELF::STB_LOCAL;
+        break;
+      case AbsoluteAtom::scopeTranslationUnit:
+        binding = ELF::STB_LOCAL;
+        break;
+      case AbsoluteAtom::scopeGlobal:
+        binding = ELF::STB_GLOBAL;
+        break;
+      }
+      symbol->st_value = aa->value();
+    } 
+    else {
+     symbol->st_value = 0;
+     type = ELF::STT_NOTYPE;
+     binding = ELF::STB_WEAK;
+    }
+    symbol->setBindingAndType(binding, type);
+    _symbolTable.push_back(symbol);
+    this->_fsize += sizeof(Elf_Sym);
+  }
+
+  void setStringSection(ELFStringTable<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) {
+                     return A->getBinding() < B->getBinding();
+                     }); 
+    uint16_t shInfo = 0;
+    for (auto i : _symbolTable) {
+      if (i->getBinding() != ELF::STB_LOCAL)
+        break;
+      shInfo++;
+    }
+    this->_shInfo = shInfo;
+    this->setLink(_stringSection->ordinal());
+  }
+
+  void write(ELFWriter *writer, 
+             OwningPtr<FileOutputBuffer> &buffer) {
+
+    uint8_t *chunkBuffer = buffer->getBufferStart();
+    uint8_t *dest = chunkBuffer + this->fileOffset();
+    for (auto sti : _symbolTable) {
+      memcpy(dest, sti, sizeof(Elf_Sym));
+      dest += sizeof(Elf_Sym);
+    }
+  }
+
 private:
+  ELFStringTable<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>::K_ELFHeader) {
+    memset(_eh.e_ident, 0, llvm::ELF::EI_NIDENT);
+    e_ident(ELF::EI_MAG0, 0x7f);
+    e_ident(ELF::EI_MAG1, 'E');
+    e_ident(ELF::EI_MAG2, 'L');
+    e_ident(ELF::EI_MAG3, 'F');
+    e_ehsize(sizeof(Elf_Ehdr));
+    e_flags(2);
+  }
+  void e_ident(int I, unsigned char C) { _eh.e_ident[I] = C; }
+  void e_type(uint16_t type)           { _eh.e_type = type; }
+  void e_machine(uint16_t machine)     { _eh.e_machine = machine; }
+  void e_version(uint32_t version)     { _eh.e_version = version; }
+  void e_entry(int64_t entry)         { _eh.e_entry = entry; }
+  void e_phoff(int64_t phoff)         { _eh.e_phoff = phoff; }
+  void e_shoff(int64_t shoff)         { _eh.e_shoff = shoff; }
+  void e_flags(uint32_t flags)         { _eh.e_flags = flags; }
+  void e_ehsize(uint16_t ehsize)       { _eh.e_ehsize = ehsize; }
+  void e_phentsize(uint16_t phentsize) { _eh.e_phentsize = phentsize; }
+  void e_phnum(uint16_t phnum)         { _eh.e_phnum = phnum; }
+  void e_shentsize(uint16_t shentsize) { _eh.e_shentsize = shentsize; }
+  void e_shnum(uint16_t shnum)         { _eh.e_shnum = shnum; }
+  void e_shstrndx(uint16_t shstrndx)   { _eh.e_shstrndx = shstrndx; }
+  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>::K_ELFHeader;
   }
 
-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>::K_ELFProgramHeader) { }
 
-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(), see = segment->slices_end(); 
+                                             sei != see; ++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)->virtualAddr();
+      phdr->p_paddr = (*sei)->virtualAddr();
+      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->pageSize() : (*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 setVAddr(int64_t addr) {
+    this->_start = llvm::RoundUpToAlignment(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>::K_ELFProgramHeader;
   }
 
-  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) {
+      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>::K_ELFSectionHeader)
+  {
+    this->_fsize = 0;
+    this->_align2 = 8;
+    this->setOrder(order);
+    // The first element in the list is always NULL
+    Elf_Shdr *nullshdr = new (_sectionAllocate.Allocate<Elf_Shdr>()) Elf_Shdr;
+    ::memset(nullshdr, 0, sizeof (Elf_Shdr));
+    _sectionInfo.push_back(nullshdr);
+    this->_fsize += sizeof (Elf_Shdr);
   }
-}
- 
 
-template<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(MergedSections<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->virtualAddr();
+    shdr->sh_size   = section->memSize();
+    shdr->sh_link   = section->link();
+    shdr->sh_info   = section->shinfo();
+    shdr->sh_addralign = section->align2();
+    shdr->sh_entsize = section->entsize();
+    _sectionInfo.push_back(shdr);
   }
-  // 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->virtualAddr();
+    shdr->sh_size   = section->fileSize();
+    shdr->sh_link   = section->link();
+    shdr->sh_info   = section->shinfo();
+    shdr->sh_addralign = section->align2();
+    shdr->sh_entsize = section->entsize();
+  }
 
-  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>::K_ELFSectionHeader;
+  }
 
-    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) {
+      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 
+                                                                     ChunkIter;
+  // The key used for Segments
+  // The segments are created using 
+  // SegmentName, Segment flags
+  typedef std::pair<StringRef, int64_t> SegmentKey;
+  // Merged Sections contain the map of Sectionnames to a vector of sections,
+  // that have been merged to form a single section
+  typedef std::map<StringRef, MergedSections<target_endianness, is64Bits> *> 
+                                                            MergedSectionMapT;
+  typedef typename std::vector
+   <MergedSections<target_endianness, is64Bits> *>::iterator MergedSectionIter;
 
-/// \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::hash_combine(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::hash_combine(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> SectionMapT;
+  typedef std::unordered_map<SegmentKey,
+                             Segment<target_endianness, is64Bits>*, 
+                             SegmentHashKey> SegmentMapT;
 
-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:
+      return llvm::StringSwitch<Reference::Kind>(name)
+        .StartsWith(".eh_frame_hdr", ORDER_EH_FRAMEHDR)
+        .StartsWith(".eh_frame", ORDER_EH_FRAME)
+        .StartsWith(".init", ORDER_INIT)
+        .StartsWith(".fini", ORDER_FINI)
+        .StartsWith(".hash", ORDER_HASH)
+        .Default(ORDER_TEXT);
 
-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,
+                           const int32_t contentType) {
+    if (contentType == DefinedAtom::typeZeroFill) 
+      return ".bss";
+    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(),
+                               definedAtom->contentType());
+    const lld::DefinedAtom::ContentPermissions permissions = 
+                                  definedAtom->permissions();
+    const lld::DefinedAtom::ContentType contentType = 
+                                  definedAtom->contentType();
+    const Key key(sectionName, std::make_pair(contentType, permissions));
+    const std::pair<Key, Section<target_endianness, is64Bits> *> 
+                                                currentSection(key, nullptr);
+    std::pair<typename SectionMapT::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 MergedSections
+  void mergeSimiliarSections() {
+    MergedSections<target_endianness, is64Bits> *mergedSection;
+  
+    for (auto &si : _sections) {
+      const std::pair<StringRef, MergedSections<target_endianness, is64Bits> *> 
+                                            currentMergedSections(si->name(), 
+                                                                 nullptr);
+      std::pair<typename MergedSectionMapT::iterator, bool>
+                              mergedSectionInsert
+                              (_mergedSectionMap.insert(currentMergedSections));
+      if (!mergedSectionInsert.second) {
+        mergedSection = mergedSectionInsert.first->second;
+      }
+      else {
+        mergedSection = new (_allocator.Allocate
+                     <MergedSections<target_endianness, is64Bits>>())
+                     MergedSections<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) {
+                       return A->order() < B->order();
+                       });
+    // Merge all sections
+    mergeSimiliarSections();
+    // Set the ordinal after sorting the sections
+    int ordinal = 1;
+    for (auto &msi : _mergedSections) {
+      (*msi).setOrdinal(ordinal);
+      for (auto ai = (*msi).begin_sections(), ae = (*msi).end_sections();
+                                               ai != ae; ++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(), mse = merged_sections_end(); 
+                                             msi != mse; ++msi) {
+      for (auto ai = (*msi)->begin_sections(), ae = (*msi)->end_sections(); 
+                                               ai != ae; ++ai) {
+        if ((*ai)->kind() == Chunk<target_endianness, is64Bits>::K_ELFSection) {
+          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 SegmentMapT::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";
-}
+  void assignFileOffsets() {
+    std::sort(_segments.begin(), 
+              _segments.end(), 
+              Segment<target_endianness, is64Bits>::compareSegments);
+    int ordinal = 0;
+    // 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) {
+      si->setOrdinal(++ordinal);
+      si->assignOffsets(offset);
+      offset += si->fileSize();
+    }
+  }
 
-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 setELFHeader(ELFHeader<target_endianness, is64Bits> *e) {
+    _elfHeader = e;
   }
-}
 
-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 setProgramHeader(ELFProgramHeader<target_endianness, is64Bits> *p) {
+    _programHeader = p;
+  }
 
-template<support::endianness target_endianness, bool is64Bits>
-const char *ELFSectionHeaderChunk<target_endianness, is64Bits>::info() {
-  return "elf_section_header";
-}
+  void assignVirtualAddress() {
+    int32_t numSlices = 0;
+    int64_t virtualAddress = _options.baseAddress();
 
-//===----------------------------------------------------------------------===//
-//  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;
+    // Add the ELF Header
+    if (_elfHeader) {
+      _elfHeader->setFileOffset(0);
+      _elfHeader->setVAddr(virtualAddress);
+    }
+    // Add the program header
+    if (_programHeader) {
+      _programHeader->setVAddr(int64_t(virtualAddress + _elfHeader->fileSize()));
+      _programHeader->setFileOffset(_elfHeader->fileSize());
+    }
+    bool newSegmentHeaderAdded = true;
+    while (true) {
+      for (auto si : _segments) {
+        newSegmentHeaderAdded = _programHeader->addSegment(si);
+        numSlices += si->numSlices();
+      }
+      if (!newSegmentHeaderAdded) 
+        break;
+      int64_t fileoffset = _elfHeader->fileSize() + _programHeader->fileSize();
+      int64_t address = virtualAddress;
+      // Fix the offsets after adding the program header
+      for (auto &si : _segments) {
+        // Align the segment to a page boundary
+        fileoffset = llvm::RoundUpToAlignment(fileoffset, _options.pageSize());
+        si->assignOffsets(fileoffset);
+        fileoffset = si->fileOffset() + si->fileSize();
+      }
+      // start assigning virtual addresses
+      for (auto si = _segments.begin(); si != _segments.end(); ++si) {
+        (*si)->setVAddr(virtualAddress);
+        // The first segment has the virtualAddress set to the base address as
+        // we have added the file header and the program header dont align the
+        // first segment to the pagesize 
+        (*si)->assignVirtualAddress(address, (si == _segments.begin()));
+        (*si)->setMemSize(address - virtualAddress);
+        virtualAddress = llvm::RoundUpToAlignment(address, _options.pageSize());
+      }
+      _programHeader->resetProgramHeaders();
+    }
+    Section<target_endianness, is64Bits> *section;
+    // Fix the offsets of all the atoms within a section
+    for (auto &si : _sections) {
+      section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(si);
+      if (section && 
+          DefaultELFLayout<target_endianness, is64Bits>::hasOutputSegment(section))
+        section->assignOffsets(section->fileOffset());
+    }
+    // Set the size of the merged Sections
+    for (auto msi = merged_sections_begin(), mse = merged_sections_end(); 
+                                             msi != mse; ++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(), mse = merged_sections_end(); 
+                                             msi != mse; ++msi) {
+      int64_t sectionstartaddr = 0;
+      int64_t startaddr = 0;
+      int64_t sectionsize = 0;
+      bool isFirstSection = true;
+      for (auto si = (*msi)->begin_sections(), se = (*msi)->end_sections(); 
+                                               si != se; ++si) {
+        if (isFirstSection) {
+          startaddr = (*si)->virtualAddr();
+          isFirstSection = false;
+        }
+        sectionstartaddr = (*si)->virtualAddr();
+        sectionsize = (*si)->memSize();
+      }
+      sectionsize = (sectionstartaddr - startaddr) + sectionsize;
+      (*msi)->setMemSize(sectionsize);
+      (*msi)->setAddr(startaddr);
+    }
   }
 
-template<support::endianness target_endianness, bool is64Bits>
-void ELFProgramHeaderChunk<target_endianness, is64Bits>::createPHeaders() {
+  void assignOffsetsForMiscSections() {
+    int64_t fileoffset = 0;
+    int64_t size = 0;
+    for (auto si : _segments) {
+      fileoffset = si->fileOffset();
+      size = si->fileSize();
+    }
+    fileoffset = fileoffset + size;
+    Section<target_endianness, is64Bits> *section;
+    for (auto si : _sections) {
+      section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(si);
+      if (section && 
+          DefaultELFLayout<target_endianness, is64Bits>::hasOutputSegment
+                                                         (section))
+        continue;
+      fileoffset = llvm::RoundUpToAlignment(fileoffset, si->align2());
+      si->setFileOffset(fileoffset);
+      si->setVAddr(0);
+      fileoffset += si->fileSize();
+    }
+  }
 
-  //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 finalize() {
+    for (auto &si : _sections) {
+      si->finalize();
+    }
+  }
 
-      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();
-        }
+  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>::K_ELFSection) {
+        section = llvm::dyn_cast<Section<target_endianness, is64Bits>>(*ai);
+        if (section->findAtomAddrByName(name, addr))
+         return true;
       }
-
-      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);
     }
+    return false;    
   }
-}
 
-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";
-}
+  MergedSectionIter merged_sections_begin() { 
+    return _mergedSections.begin();
+  }
 
-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);
+  MergedSectionIter merged_sections_end() { 
+    return _mergedSections.end();
   }
-}
-template<support::endianness target_endianness, bool is64Bits>
-StringRef ELFProgramHeaderChunk<target_endianness, is64Bits>
-                               ::segmentName() const {
-  return "PT_NULL";
-}
+
+  ChunkIter sections_begin() {
+    return _sections.begin();
+  }
+  ChunkIter sections_end() {
+    return _sections.end();
+  }
+
+  ChunkIter segments_begin() {
+    return _segments.begin();
+  }
+
+  ChunkIter segments_end() {
+    return _segments.end();
+  }
+
+  ELFHeader<target_endianness, is64Bits> *elfHeader() { 
+    return _elfHeader;
+  }
+
+  ELFProgramHeader<target_endianness, is64Bits> *elfProgramHeader() { 
+    return _programHeader;
+  }
+
+private:
+  SectionMapT _sectionMap;
+  MergedSectionMapT _mergedSectionMap;
+  SegmentMapT _segmentMap;
+
+  std::vector<Chunk<target_endianness, is64Bits> *> _sections;
+  std::vector<Segment<target_endianness, is64Bits> *> _segments;
+  std::vector<MergedSections<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>::K_ELFSection) 
+      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>::K_ELFSection) 
+      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>::K_ELFSection) 
+      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>::K_ELFSection) 
+      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>::K_ELFSection) 
+      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->assignFileOffsets();
+  _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 +2055,78 @@
   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 virtualAddr = 0;
+  _layout->findAtomAddrByName("_start", virtualAddr);
+  _elfHeader->e_entry(virtualAddr);
+  _elfHeader->write(this, buffer);
+  _programHeader->write(this, buffer);
+
   return buffer->commit();
 }
 
 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!");
 }


More information about the llvm-commits mailing list