Update mclinker to 176d79dc69b439b23ce7101ef8c3250057119664.

Change-Id: Ibae073aefc7838fce46875a6bf6ce7b7e18eced8
Date:   Mon Mar 4 22:29:06 2013 +0100
diff --git a/include/mcld/ADT/BinTree.h b/include/mcld/ADT/BinTree.h
index f015ac8..76de607 100644
--- a/include/mcld/ADT/BinTree.h
+++ b/include/mcld/ADT/BinTree.h
@@ -12,8 +12,9 @@
 #include <gtest.h>
 #endif
 
-#include "mcld/ADT/Uncopyable.h"
-#include "mcld/ADT/TreeAllocator.h"
+#include <mcld/ADT/Uncopyable.h>
+#include <mcld/ADT/TreeBase.h>
+#include <mcld/ADT/TreeAllocator.h>
 
 #include <cstddef>
 #include <iterator>
@@ -21,8 +22,7 @@
 #include <queue>
 #include <stack>
 
-namespace mcld
-{
+namespace mcld {
 
 template<class DataType>
 class BinaryTree;
diff --git a/include/mcld/ADT/SizeTraits.h b/include/mcld/ADT/SizeTraits.h
index c8822cf..dbd5d7b 100644
--- a/include/mcld/ADT/SizeTraits.h
+++ b/include/mcld/ADT/SizeTraits.h
@@ -13,6 +13,7 @@
 #endif
 
 #include <llvm/Support/DataTypes.h>
+#include <llvm/Support/ELF.h>
 
 namespace mcld
 {
@@ -40,6 +41,50 @@
   typedef int64_t  SWord;
 };
 
+// FIXME: move this to mcld internal ELF header file?
+template<size_t SIZE>
+class ELFSizeTraits;
+
+template<>
+class ELFSizeTraits<32>
+{
+public:
+  typedef llvm::ELF::Elf32_Addr  Addr; // Program address
+  typedef llvm::ELF::Elf32_Off   Off;  // File offset
+  typedef llvm::ELF::Elf32_Half  Half;
+  typedef llvm::ELF::Elf32_Word  Word;
+  typedef llvm::ELF::Elf32_Sword Sword;
+
+  typedef llvm::ELF::Elf32_Ehdr  Ehdr;
+  typedef llvm::ELF::Elf32_Shdr  Shdr;
+  typedef llvm::ELF::Elf32_Sym   Sym;
+  typedef llvm::ELF::Elf32_Rel   Rel;
+  typedef llvm::ELF::Elf32_Rela  Rela;
+  typedef llvm::ELF::Elf32_Phdr  Phdr;
+  typedef llvm::ELF::Elf32_Dyn   Dyn;
+};
+
+template<>
+class ELFSizeTraits<64>
+{
+public:
+  typedef llvm::ELF::Elf64_Addr   Addr;
+  typedef llvm::ELF::Elf64_Off    Off;
+  typedef llvm::ELF::Elf64_Half   Half;
+  typedef llvm::ELF::Elf64_Word   Word;
+  typedef llvm::ELF::Elf64_Sword  Sword;
+  typedef llvm::ELF::Elf64_Xword  Xword;
+  typedef llvm::ELF::Elf64_Sxword Sxword;
+
+  typedef llvm::ELF::Elf64_Ehdr   Ehdr;
+  typedef llvm::ELF::Elf64_Shdr   Shdr;
+  typedef llvm::ELF::Elf64_Sym    Sym;
+  typedef llvm::ELF::Elf64_Rel    Rel;
+  typedef llvm::ELF::Elf64_Rela   Rela;
+  typedef llvm::ELF::Elf64_Phdr   Phdr;
+  typedef llvm::ELF::Elf64_Dyn    Dyn;
+};
+
 /// alignAddress - helper function to align an address with given alignment
 /// constraint
 ///
diff --git a/include/mcld/ADT/TreeAllocator.h b/include/mcld/ADT/TreeAllocator.h
index 899896c..10de761 100644
--- a/include/mcld/ADT/TreeAllocator.h
+++ b/include/mcld/ADT/TreeAllocator.h
@@ -13,10 +13,8 @@
 #endif
 #include <set>
 #include "mcld/Support/GCFactory.h"
-#include "mcld/ADT/TreeBase.h"
 
-namespace mcld
-{
+namespace mcld {
 
 /** \class NodeFactory
  *  \brief NodeFactory manages the creation and destruction of mcld::Node.
diff --git a/include/mcld/ADT/TreeBase.h b/include/mcld/ADT/TreeBase.h
index 6fb3bf6..13eb474 100644
--- a/include/mcld/ADT/TreeBase.h
+++ b/include/mcld/ADT/TreeBase.h
@@ -11,6 +11,8 @@
 #include "mcld/ADT/TypeTraits.h"
 
 #include <cstddef>
+#include <cassert>
+#include <iterator>
 
 namespace mcld {
 
diff --git a/include/mcld/Config/Config.h.in b/include/mcld/Config/Config.h.in
index 7b55240..1967ca1 100644
--- a/include/mcld/Config/Config.h.in
+++ b/include/mcld/Config/Config.h.in
@@ -1,3 +1,6 @@
+/* include/mcld/Config/Config.h.in.  Generated from configure.ac by autoheader.  */
+
+
 //===- Config.h.in --------------------------------------------------------===//
 //
 //                     The MCLinker Project
@@ -9,8 +12,84 @@
 #ifndef MCLD_CONFIG_H
 #define MCLD_CONFIG_H
 
-#define @MCLD_ON_PLATFORM@ 1
-#define MCLD_VERSION "@MCLD_VERSION@"
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if you have POSIX threads libraries and header files. */
+#undef HAVE_PTHREAD
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if this is Unixish platform */
+#undef MCLD_ON_UNIX
+
+/* Define if this is Win32ish platform */
+#undef MCLD_ON_WIN32
+
+/* MCLINKER version */
+#undef MCLD_VERSION
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to necessary symbol if this constant uses a non-standard name on
+   your system. */
+#undef PTHREAD_CREATE_JOINABLE
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define for standalone Android linker */
+#undef TARGET_BUILD
+
+/* Version number of package */
+#undef VERSION
+
+
 #define MCLD_REGION_CHUNK_SIZE 32
 #define MCLD_NUM_OF_INPUTS 32
 #define MCLD_SECTIONS_PER_INPUT 16
diff --git a/include/mcld/Fragment/FGNode.h b/include/mcld/Fragment/FGNode.h
new file mode 100644
index 0000000..0afee0e
--- /dev/null
+++ b/include/mcld/Fragment/FGNode.h
@@ -0,0 +1,91 @@
+//===- FGNode.h -----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_FGNODE_H
+#define MCLD_FGNODE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/Support/DataTypes.h>
+
+#include <vector>
+
+namespace mcld
+{
+
+class Relocation;
+class ResolveInfo;
+class Fragment;
+
+/** \class FGNode
+ *  \brief FGNode is a node for FragmentGraph
+ */
+class FGNode
+{
+public:
+  typedef ResolveInfo* Slot;
+  typedef Relocation*  Signal;
+
+  typedef std::vector<Fragment*> FragmentListType;
+  typedef FragmentListType::iterator frag_iterator;
+  typedef FragmentListType::const_iterator const_frag_iterator;
+
+  typedef std::vector<Slot> SlotListType;
+  typedef SlotListType::iterator slot_iterator;
+  typedef SlotListType::const_iterator const_slot_iterator;
+
+  typedef std::vector<Signal> SignalListType;
+  typedef SignalListType::iterator signal_iterator;
+  typedef SignalListType::const_iterator const_signal_iterator;
+
+public:
+  FGNode();
+  explicit FGNode(uint32_t pIndex);
+
+  void addFragment(Fragment* pFrag);
+  void addSignal(Signal pSignal);
+  void addSlot(Slot pSlot);
+
+  /// ----- observers ----- ///
+  uint32_t getIndex() const
+  {  return m_Index; }
+
+  slot_iterator         slot_begin   ()       { return m_Slots.begin();     }
+  const_slot_iterator   slot_begin   () const { return m_Slots.begin();     }
+  slot_iterator         slot_end     ()       { return m_Slots.end();       }
+  const_slot_iterator   slot_end     () const { return m_Slots.end();       }
+
+  signal_iterator       signal_begin ()       { return m_Signals.begin();   }
+  const_signal_iterator signal_begin () const { return m_Signals.begin();   }
+  signal_iterator       signal_end   ()       { return m_Signals.end();     }
+  const_signal_iterator signal_end   () const { return m_Signals.end();     }
+
+  frag_iterator         frag_begin   ()       { return m_Fragments.begin(); }
+  const_frag_iterator   frag_begin   () const { return m_Fragments.begin(); }
+  frag_iterator         frag_end     ()       { return m_Fragments.end();   }
+  const_frag_iterator   frag_end     () const { return m_Fragments.end();   }
+
+private:
+  FragmentListType m_Fragments;
+
+  /// m_Signals - a list of relocations describes the possible fan-out of this
+  /// node
+  SignalListType m_Signals;
+
+  /// m_Slots - a list of symbols describes the possible fan-in of this node
+  SlotListType m_Slots;
+
+  /// m_Index - the index in the reachability matrix
+  uint32_t m_Index;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Fragment/FragmentGraph.h b/include/mcld/Fragment/FragmentGraph.h
new file mode 100644
index 0000000..96d438f
--- /dev/null
+++ b/include/mcld/Fragment/FragmentGraph.h
@@ -0,0 +1,177 @@
+//===- FragmentGraph.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_FRAGMENTGRAPH_H
+#define MCLD_FRAGMENTGRAPH_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <vector>
+
+#include <mcld/ADT/HashTable.h>
+#include <mcld/ADT/HashEntry.h>
+#include <mcld/Config/Config.h>
+#include <mcld/Fragment/FGNode.h>
+#include <mcld/Fragment/FGEdge.h>
+#include <mcld/Support/GCFactory.h>
+
+#include <llvm/Support/DataTypes.h>
+
+namespace mcld
+{
+class Module;
+class ResolveInfo;
+class Relocation;
+class LinkerConfig;
+
+/** \class FragmentGraph
+ *  \brief FragmentGraph describes the references between fragments.
+ */
+class FragmentGraph
+{
+public:
+  typedef FGNode::Slot   Slot;
+  typedef FGNode::Signal Signal;
+
+  typedef GCFactory<FGNode, MCLD_SECTIONS_PER_INPUT> NodeFactoryType;
+  typedef NodeFactoryType::iterator node_iterator;
+  typedef NodeFactoryType::const_iterator const_node_iterator;
+
+  typedef std::vector<FGEdge> EdgeListType;
+  typedef EdgeListType::iterator edge_iterator;
+  typedef EdgeListType::const_iterator const_edge_iterator;
+
+
+public:
+  FragmentGraph();
+  ~FragmentGraph();
+
+  /// construct - construct the whole graph from input Fragments, relocations
+  /// and symbols
+  bool construct(const LinkerConfig& pConfig, Module& pModule);
+
+  /// connect - connect two nodes
+  bool connect(Signal pSignal, Slot pSlot);
+  bool connect(FGNode& pFrom, Slot pSlot);
+
+  /// getEdges - given a node, get the list of edges which are the fan-out of
+  /// this node
+  /// @param pEdges - the edge list which contains the found edges
+  /// @return false - the given node
+  bool getEdges(FGNode& pNode, EdgeListType& pEdges);
+
+  /// ----- observers -----///
+  /// getNode - given a fragment, finde the node which the fragment is belong to
+  FGNode* getNode(const Fragment& pFrag);
+  const FGNode* getNode(const Fragment& pFrag) const;
+
+  FGNode* getNode(const ResolveInfo& pSym);
+  const FGNode* getNode(const ResolveInfo& pSym) const;
+
+private:
+  typedef std::vector<Relocation*> RelocationListType;
+  typedef RelocationListType::iterator reloc_iterator;
+  typedef RelocationListType::const_iterator const_reloc_iterator;
+
+  struct PtrCompare
+  {
+    bool operator()(const void* X, const void* Y) const
+    { return (X==Y); }
+  };
+
+  struct PtrHash
+  {
+    size_t operator()(const void* pKey) const
+    {
+      return (unsigned((uintptr_t)pKey) >> 4) ^
+             (unsigned((uintptr_t)pKey) >> 9);
+    }
+  };
+
+  /// HashTable for Fragment* to Node*
+  typedef HashEntry<const Fragment*, FGNode*, PtrCompare> FragHashEntryType;
+  typedef HashTable<FragHashEntryType,
+                    PtrHash,
+                    EntryFactory<FragHashEntryType> > FragHashTableType;
+
+  /// HashTable for ResolveInfo* to Node*
+  typedef HashEntry<const ResolveInfo*, FGNode*, PtrCompare> SymHashEntryType;
+  typedef HashTable<SymHashEntryType,
+                    PtrHash,
+                    EntryFactory<SymHashEntryType> > SymHashTableType;
+
+  /** \class ReachMatrix
+   *  \brief ReachMatrix is the reachability matrix which describes the relation
+   *   of Nodes in FragmentGraph
+   */
+  class ReachMatrix
+  {
+  public:
+    typedef std::vector<uint32_t> MatrixDataType;
+
+  public:
+    ReachMatrix(size_t pSize);
+    ~ReachMatrix();
+    uint32_t& at(uint32_t pX, uint32_t pY);
+    uint32_t at(uint32_t pX, uint32_t pY) const;
+
+    uint32_t getN() const
+    { return m_N; }
+
+    void print();
+
+  private:
+    // m_Data - the contents of the matrix. Here we use a one dimensional array
+    // to represent the two dimensional matrix
+    MatrixDataType m_Data;
+
+    // m_N - this is an m_N x m_N matrix
+    size_t m_N;
+  };
+
+private:
+  FGNode* producePseudoNode();
+  FGNode* produceRegularNode();
+  void destroyPseudoNode();
+  void destroyRegularNode();
+
+  void initMatrix();
+
+  bool createRegularNodes(Module& pModule);
+  bool setNodeSlots(Module& pModule);
+  bool createPseudoNodes(Module& pModule);
+
+  bool createRegularEdges(Module& pModule);
+  bool createPseudoEdges(Module& pModule);
+
+private:
+  NodeFactoryType* m_pPseudoNodeFactory;
+  NodeFactoryType* m_pRegularNodeFactory;
+
+  /// m_pFragNodeMap - HashTable to map the fragment to the node it belongs to
+  FragHashTableType* m_pFragNodeMap;
+
+  /// m_pSymNodeMap - HashTable to map the ResolveInfo to the node. The node is
+  /// the pseudo node which the contains it's fan-out is to the ResolveInfo
+  SymHashTableType* m_pSymNodeMap;
+
+  ReachMatrix* m_pMatrix;
+
+  /// m_NumOfPNodes - number of pseudo nodes
+  size_t m_NumOfPNodes;
+  /// m_NumOfRNodes - number of regular nodes
+  size_t m_NumOfRNodes;
+  /// m_NumOfEdges - number of edges
+  size_t m_NumOfEdges;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Fragment/FragmentLinker.h b/include/mcld/Fragment/FragmentLinker.h
index 17e80bd..45ef85d 100644
--- a/include/mcld/Fragment/FragmentLinker.h
+++ b/include/mcld/Fragment/FragmentLinker.h
@@ -30,14 +30,7 @@
 class Module;
 class TargetLDBackend;
 class LinkerConfig;
-class LDSection;
-class LDSectionFactory;
-class SectionData;
-class Output;
-class EhFrame;
-class EhFrameHdr;
 class MemoryArea;
-class RelocData;
 
 /** \class FragmentLinker
  *  \brief FragmentLinker provides a pass to link object files.
@@ -45,56 +38,12 @@
 class FragmentLinker
 {
 public:
-  enum DefinePolicy
-  {
-    Force,
-    AsRefered
-  };
-
-  enum ResolvePolicy
-  {
-    Unresolve,
-    Resolve
-  };
-
-public:
   FragmentLinker(const LinkerConfig& pConfig,
                  Module& pModule,
                  TargetLDBackend& pBackend);
 
   ~FragmentLinker();
 
-  // ----- about symbols  ----- //
-  /// defineSymbol - add a symbol
-  /// defineSymbol define a output symbol
-  ///
-  /// @tparam POLICY idicate how to define the symbol.
-  ///   - Force
-  ///     - Define the symbol forcefully. If the symbol has existed, override
-  ///       it. Otherwise, define it.
-  ///   - AsRefered
-  ///     - If the symbol has existed, override it. Otherwise, return NULL
-  ///       immediately.
-  ///
-  /// @tparam RESOLVE indicate whether to resolve the symbol or not.
-  ///   - Unresolve
-  ///      - Do not resolve the symbol, and override the symbol immediately.
-  ///   - Resolve
-  ///      - Resolve the defined symbol.
-  ///
-  /// @return If the output symbol has existed, return it. Otherwise, create
-  ///         a new symbol and return the new one.
-  template<DefinePolicy POLICY, ResolvePolicy RESOLVE>
-  LDSymbol* defineSymbol(const llvm::StringRef& pName,
-                         bool pIsDyn,
-                         ResolveInfo::Type pType,
-                         ResolveInfo::Desc pDesc,
-                         ResolveInfo::Binding pBinding,
-                         ResolveInfo::SizeType pSize,
-                         LDSymbol::ValueType pValue,
-                         FragmentRef* pFragmentRef,
-                         ResolveInfo::Visibility pVisibility = ResolveInfo::Default);
-
   bool finalizeSymbols();
 
   /// applyRelocations - apply all relocation enties.
@@ -104,67 +53,7 @@
   /// data to output file.
   void syncRelocationResult(MemoryArea& pOutput);
 
-  // -----  capacity  ----- //
-  const LinkerConfig& getLDInfo() const { return m_Config; }
-
-  // ----- output attribute ----- //
-  /// isOutputPIC - return whether the output is position-independent
-  bool isOutputPIC() const;
-
-  /// isStaticLink - return whether we're doing static link
-  bool isStaticLink() const;
-
 private:
-  LDSymbol* defineSymbolForcefully(const llvm::StringRef& pName,
-                                   bool pIsDyn,
-                                   ResolveInfo::Type pType,
-                                   ResolveInfo::Desc pDesc,
-                                   ResolveInfo::Binding pBinding,
-                                   ResolveInfo::SizeType pSize,
-                                   LDSymbol::ValueType pValue,
-                                   FragmentRef* pFragmentRef,
-                                   ResolveInfo::Visibility pVisibility);
-
-  LDSymbol* defineAndResolveSymbolForcefully(const llvm::StringRef& pName,
-                                             bool pIsDyn,
-                                             ResolveInfo::Type pType,
-                                             ResolveInfo::Desc pDesc,
-                                             ResolveInfo::Binding pBinding,
-                                             ResolveInfo::SizeType pSize,
-                                             LDSymbol::ValueType pValue,
-                                             FragmentRef* pFragmentRef,
-                                             ResolveInfo::Visibility pVisibility);
-
-  LDSymbol* defineSymbolAsRefered(const llvm::StringRef& pName,
-                                  bool pIsDyn,
-                                  ResolveInfo::Type pType,
-                                  ResolveInfo::Desc pDesc,
-                                  ResolveInfo::Binding pBinding,
-                                  ResolveInfo::SizeType pSize,
-                                  LDSymbol::ValueType pValue,
-                                  FragmentRef* pFragmentRef,
-                                  ResolveInfo::Visibility pVisibility);
-
-  LDSymbol* defineAndResolveSymbolAsRefered(const llvm::StringRef& pName,
-                                            bool pIsDyn,
-                                            ResolveInfo::Type pType,
-                                            ResolveInfo::Desc pDesc,
-                                            ResolveInfo::Binding pBinding,
-                                            ResolveInfo::SizeType pSize,
-                                            LDSymbol::ValueType pValue,
-                                            FragmentRef* pFragmentRef,
-                                            ResolveInfo::Visibility pVisibility);
-
-  bool shouldForceLocal(const ResolveInfo& pInfo) const;
-
-  /// checkIsOutputPIC - return whether the output is position-independent,
-  /// called by isOutputPIC()
-  bool checkIsOutputPIC() const;
-
-  /// checkIsStaticLink - return whether we're doing static link, called by
-  /// isStaticLink()
-  bool checkIsStaticLink() const;
-
   /// normalSyncRelocationResult - sync relocation result when producing shared
   /// objects or executables
   void normalSyncRelocationResult(MemoryArea& pOutput);
@@ -183,8 +72,6 @@
   TargetLDBackend& m_Backend;
 };
 
-#include "FragmentLinker.tcc"
-
 } // namespace of mcld
 
 #endif
diff --git a/include/mcld/Fragment/FragmentLinker.tcc b/include/mcld/Fragment/FragmentLinker.tcc
deleted file mode 100644
index cc3fad6..0000000
--- a/include/mcld/Fragment/FragmentLinker.tcc
+++ /dev/null
@@ -1,68 +0,0 @@
-//===- FragmentLinker.tcc --------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// defineSymbol - define a new symbol
-template<FragmentLinker::DefinePolicy POLICY,
-         FragmentLinker::ResolvePolicy RESOLVE>
-LDSymbol* FragmentLinker::defineSymbol(const llvm::StringRef& pName,
-                                       bool pIsDyn,
-                                       ResolveInfo::Type pType,
-                                       ResolveInfo::Desc pDesc,
-                                       ResolveInfo::Binding pBinding,
-                                       ResolveInfo::SizeType pSize,
-                                       LDSymbol::ValueType pValue,
-                                       FragmentRef* pFragmentRef,
-                                       ResolveInfo::Visibility pVisibility)
-{
-  // These if/return should be optimized by compiler.
-  // This function is defined for clarity.
-  if (FragmentLinker::Force == POLICY && FragmentLinker::Unresolve == RESOLVE)
-    return defineSymbolForcefully(pName,
-                                  pIsDyn,
-                                  pType,
-                                  pDesc,
-                                  pBinding,
-                                  pSize,
-                                  pValue,
-                                  pFragmentRef,
-                                  pVisibility);
-
-  if (FragmentLinker::AsRefered == POLICY && FragmentLinker::Unresolve == RESOLVE)
-    return defineSymbolAsRefered(pName,
-                                 pIsDyn,
-                                 pType,
-                                 pDesc,
-                                 pBinding,
-                                 pSize,
-                                 pValue,
-                                 pFragmentRef,
-                                 pVisibility);
-
-  if (FragmentLinker::Force == POLICY && FragmentLinker::Resolve == RESOLVE)
-    return defineAndResolveSymbolForcefully(pName,
-                                            pIsDyn,
-                                            pType,
-                                            pDesc,
-                                            pBinding,
-                                            pSize,
-                                            pValue,
-                                            pFragmentRef,
-                                            pVisibility);
-
-  if (FragmentLinker::AsRefered == POLICY && FragmentLinker::Resolve == RESOLVE)
-    return defineAndResolveSymbolAsRefered(pName,
-                                           pIsDyn,
-                                           pType,
-                                           pDesc,
-                                           pBinding,
-                                           pSize,
-                                           pValue,
-                                           pFragmentRef,
-                                           pVisibility);
-}
-
diff --git a/include/mcld/Fragment/Relocation.h b/include/mcld/Fragment/Relocation.h
index 37b32f6..e8c57e4 100644
--- a/include/mcld/Fragment/Relocation.h
+++ b/include/mcld/Fragment/Relocation.h
@@ -32,9 +32,10 @@
 
 public:
   typedef uint64_t Address; // FIXME: use SizeTrait<T>::Address instead
-  typedef uint64_t DWord; // FIXME: use SizeTrait<T>::Word instead
-  typedef int64_t SWord; // FIXME: use SizeTrait<T>::SWord instead
-  typedef uint8_t Type;
+  typedef uint64_t DWord;   // FIXME: use SizeTrait<T>::Word instead
+  typedef int64_t  SWord;   // FIXME: use SizeTrait<T>::SWord instead
+  typedef uint8_t  Type;
+  typedef uint32_t Size;
 
 private:
   Relocation();
@@ -80,6 +81,9 @@
   /// place - P value - address of the place being relocated
   Address place() const;
 
+  /// size - the size of the relocation in bit
+  Size size(Relocator& pRelocator) const;
+
   /// symbol info - binding, type
   const ResolveInfo* symInfo() const { return m_pSymInfo; }
   ResolveInfo*       symInfo()       { return m_pSymInfo; }
@@ -105,8 +109,6 @@
 
   void setSymInfo(ResolveInfo* pSym);
 
-  size_t size() const;
-
 private:
   /// m_Type - the type of the relocation entries
   Type m_Type;
diff --git a/include/mcld/GeneralOptions.h b/include/mcld/GeneralOptions.h
index 1468704..9d31097 100644
--- a/include/mcld/GeneralOptions.h
+++ b/include/mcld/GeneralOptions.h
@@ -30,6 +30,28 @@
 class GeneralOptions
 {
 public:
+  enum StripSymbolMode {
+    KeepAllSymbols,
+    StripTemporaries,
+    StripLocals,
+    StripAllSymbols
+  };
+
+  enum HashStyle {
+    SystemV = 0x1,
+    GNU     = 0x2,
+    Both    = 0x3
+  };
+
+  typedef std::vector<std::string> RpathList;
+  typedef RpathList::iterator rpath_iterator;
+  typedef RpathList::const_iterator const_rpath_iterator;
+
+  typedef std::vector<std::string> AuxiliaryList;
+  typedef AuxiliaryList::iterator aux_iterator;
+  typedef AuxiliaryList::const_iterator const_aux_iterator;
+
+public:
   GeneralOptions();
   ~GeneralOptions();
 
@@ -43,6 +65,8 @@
 
   void setSysroot(const sys::fs::Path &pPath);
 
+  bool hasSysroot() const;
+
   /// search directory
   SearchDirs& directories()
   { return m_SearchDirs; }
@@ -98,12 +122,6 @@
   const std::string& soname() const
   { return m_SOName; }
 
-  void setAllowShlibUndefined(bool pEnabled = true)
-  { m_bAllowShlibUndefined = pEnabled; }
-
-  bool isAllowShlibUndefined() const
-  { return m_bAllowShlibUndefined; }
-
   void setVerbose(int8_t pVerbose = -1)
   { m_Verbose = pVerbose; }
 
@@ -201,7 +219,7 @@
   void setNMagic(bool pMagic = true)
   { m_bNMagic = pMagic; }
 
-  bool nnagic() const
+  bool nmagic() const
   { return m_bNMagic; }
 
   // -N, --omagic
@@ -250,6 +268,56 @@
   bool isFatalWarnings() const
   { return m_bFatalWarnings; }
 
+  StripSymbolMode getStripSymbolMode() const
+  { return m_StripSymbols; }
+
+  void setStripSymbols(StripSymbolMode pMode)
+  { m_StripSymbols = pMode; }
+
+  void setNewDTags(bool pEnable = true)
+  { m_bNewDTags = pEnable; }
+
+  bool hasNewDTags() const
+  { return m_bNewDTags; }
+
+  void setNoStdlib(bool pEnable = true)
+  { m_bNoStdlib = pEnable; }
+
+  bool nostdlib() const
+  { return m_bNoStdlib; }
+
+  unsigned int getHashStyle() const { return m_HashStyle; }
+
+  void setHashStyle(unsigned int pStyle)
+  { m_HashStyle = pStyle; }
+
+  // -----  link-in rpath  ----- //
+  const RpathList& getRpathList() const { return m_RpathList; }
+  RpathList&       getRpathList()       { return m_RpathList; }
+
+  const_rpath_iterator rpath_begin() const { return m_RpathList.begin(); }
+  rpath_iterator       rpath_begin()       { return m_RpathList.begin(); }
+  const_rpath_iterator rpath_end  () const { return m_RpathList.end();   }
+  rpath_iterator       rpath_end  ()       { return m_RpathList.end();   }
+
+  // -----  filter and auxiliary filter  ----- //
+  void setFilter(const std::string& pFilter)
+  { m_Filter = pFilter; }
+
+  const std::string& filter() const
+  { return m_Filter; }
+
+  bool hasFilter() const
+  { return !m_Filter.empty(); }
+
+  const AuxiliaryList& getAuxiliaryList() const { return m_AuxiliaryList; }
+  AuxiliaryList&       getAuxiliaryList()       { return m_AuxiliaryList; }
+
+  const_aux_iterator aux_begin() const { return m_AuxiliaryList.begin(); }
+  aux_iterator       aux_begin()       { return m_AuxiliaryList.begin(); }
+  const_aux_iterator aux_end  () const { return m_AuxiliaryList.end();   }
+  aux_iterator       aux_end  ()       { return m_AuxiliaryList.end();   }
+
 private:
   enum status {
     YES,
@@ -289,7 +357,6 @@
   bool m_Bgroup         : 1;
   bool m_bPIE           : 1;
   bool m_bColor         : 1;   // --color[=true,false,auto]
-  bool m_bAllowShlibUndefined : 1; // --[no-]allow-shlib-undefined and
   bool m_bCreateEhFrameHdr : 1;    // --eh-frame-hdr
   bool m_bNMagic : 1; // -n, --nmagic
   bool m_bOMagic : 1; // -N, --omagic
@@ -299,6 +366,13 @@
   bool m_bBinaryInput : 1; // -b [input-format], --format=[input-format]
   bool m_bDefineCommon : 1; // -d, -dc, -dp
   bool m_bFatalWarnings : 1; // --fatal-warnings
+  bool m_bNewDTags: 1; // --enable-new-dtags
+  bool m_bNoStdlib: 1; // -nostdlib
+  StripSymbolMode m_StripSymbols;
+  RpathList m_RpathList;
+  unsigned int m_HashStyle;
+  std::string m_Filter;
+  AuxiliaryList m_AuxiliaryList;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/IRBuilder.h b/include/mcld/IRBuilder.h
index 3de292f..e189ce8 100644
--- a/include/mcld/IRBuilder.h
+++ b/include/mcld/IRBuilder.h
@@ -25,6 +25,7 @@
 #include <mcld/Fragment/Relocation.h>
 #include <mcld/Fragment/RegionFragment.h>
 #include <mcld/Fragment/FillFragment.h>
+#include <mcld/Fragment/FragmentRef.h>
 
 #include <mcld/Support/Path.h>
 #include <mcld/Support/FileHandle.h>
@@ -53,6 +54,16 @@
     COFF
   };
 
+  enum SymbolDefinePolicy {
+    Force,
+    AsReferred
+  };
+
+  enum SymbolResolvePolicy {
+    Unresolve,
+    Resolve
+  };
+
 public:
   IRBuilder(Module& pModule, const LinkerConfig& pConfig);
 
@@ -361,15 +372,19 @@
   /// @return Total size of the inserted fragments.
   static uint64_t AppendEhFrame(EhFrame::CIE& pCIE, EhFrame& pEhFrame);
 
-  /// AddSymbol - To add a symbol to the input file and module. The symbol is
-  /// resolved immediately.
+  /// AddSymbol - To add a symbol to the input file.
+  /// This function create a new symbol and insert it into the input file. If
+  /// mcld::Module has another symbol with the same name, then this function
+  /// resolves these two symbols and keeps one in mcld::Module by their
+  /// attributes.
   ///
   /// This is a general method for all kinds of symbol.
   ///
   /// @param [in, out] pInput   The input file. Either a relocatable or dynamic
   ///                           object
   /// @param [in]      pName    The name of the symbol
-  /// @param [in]      pType    What the symbol refers to
+  /// @param [in]      pType    What the symbol refers to. May be a object,
+  ///                           function, no-type and so on. @see ResolveInfo
   /// @param [in]      pDesc    { Undefined, Define, Common, Indirect }
   /// @param [in]      pBind    { Global, Weak, Local, Absolute }
   /// @param [in]      pSize    The size of the symbol. Bigger common symbols
@@ -381,6 +396,9 @@
   /// @param [in]      pSection Absolute, undefined, common symbols do not have
   ///                           pSection. Keep their pSection be NULL.
   /// @oaram [in]      pVis     The visibility of the symbol
+  ///
+  /// @return The added symbol. If the insertion fails due to the resoluction,
+  /// return NULL.
   LDSymbol* AddSymbol(Input& pInput,
                       const std::string& pName,
                       ResolveInfo::Type pType,
@@ -391,6 +409,51 @@
                       LDSection* pSection = NULL,
                       ResolveInfo::Visibility pVis = ResolveInfo::Default);
 
+  /// AddSymbol - To add a symbol in mcld::Module
+  /// This function create a new symbol and insert it into mcld::Module.
+  ///
+  /// @tparam POLICY idicate the condition to define or not to define the
+  /// symbol.
+  ///   - AsRefered
+  ///     - Define a symbol only if mcld::Module contains a symbol with
+  ///       identical name. If mcld::Module does not have any symbol with
+  ///       the same name, this function returns NULL.
+  ///
+  ///   - Force
+  ///     - Define a symbol no matter mcld::Module has a symbol with identical
+  ///       name or not.
+  ///
+  /// @tparam RESOLVE indicate the method to define a symbol. If we must define
+  /// a symbol in mcld::Module, then how to define it.
+  ///
+  ///   - Resolve
+  ///      - Follow the symbol resolution rule to bind the symbol references.
+  ///        Resolution of the symbols with idential name depends on their
+  ///        attributes.
+  ///
+  ///   - Unresolve
+  ///      - Forcefully override the symbol in mcld::Module.  With this
+  ///        argument, AddSymbol function turns a blind eye to symbol
+  ///        resolution rules.
+  ///
+  /// @param [in] pName    The name of the symbol
+  /// @param [in] pType    The type of the symbol
+  /// @param [in] pDesc    The description of the symbol, Could be one of
+  ///                      { Undefined, Define, Common, Indirect }
+  /// @param [in] pBinding The binding of the symbol. Could be one of
+  ///                      { Global, Weak, Local, Absolute }
+  ///
+  /// @return The symbol kept in mcld::Module.
+  template<SymbolDefinePolicy POLICY, SymbolResolvePolicy RESOLVE>
+  LDSymbol* AddSymbol(const llvm::StringRef& pName,
+                      ResolveInfo::Type pType,
+                      ResolveInfo::Desc pDesc,
+                      ResolveInfo::Binding pBinding,
+                      ResolveInfo::SizeType pSize = 0,
+                      LDSymbol::ValueType pValue = 0x0,
+                      FragmentRef* pFragmentRef = FragmentRef::Null(),
+                      ResolveInfo::Visibility pVisibility = ResolveInfo::Default);
+
   /// AddRelocation - To add a relocation entry
   ///
   /// @param [in] pSection The relocation section. pSection's link should point to
@@ -415,7 +478,8 @@
                                 FragmentRef* pFragmentRef,
                                 ResolveInfo::Visibility pVisibility);
 
-  LDSymbol* addSymbolFromDynObj(const std::string& pName,
+  LDSymbol* addSymbolFromDynObj(Input& pInput,
+                                const std::string& pName,
                                 ResolveInfo::Type pType,
                                 ResolveInfo::Desc pDesc,
                                 ResolveInfo::Binding pBinding,
@@ -430,6 +494,50 @@
   InputBuilder m_InputBuilder;
 };
 
+template<> LDSymbol*
+IRBuilder::AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
+                         const llvm::StringRef& pName,
+                         ResolveInfo::Type pType,
+                         ResolveInfo::Desc pDesc,
+                         ResolveInfo::Binding pBinding,
+                         ResolveInfo::SizeType pSize,
+                         LDSymbol::ValueType pValue,
+                         FragmentRef* pFragmentRef,
+                         ResolveInfo::Visibility pVisibility);
+
+template<> LDSymbol*
+IRBuilder::AddSymbol<IRBuilder::AsReferred, IRBuilder::Unresolve>(
+                         const llvm::StringRef& pName,
+                         ResolveInfo::Type pType,
+                         ResolveInfo::Desc pDesc,
+                         ResolveInfo::Binding pBinding,
+                         ResolveInfo::SizeType pSize,
+                         LDSymbol::ValueType pValue,
+                         FragmentRef* pFragmentRef,
+                         ResolveInfo::Visibility pVisibility);
+
+template<> LDSymbol*
+IRBuilder::AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
+                         const llvm::StringRef& pName,
+                         ResolveInfo::Type pType,
+                         ResolveInfo::Desc pDesc,
+                         ResolveInfo::Binding pBinding,
+                         ResolveInfo::SizeType pSize,
+                         LDSymbol::ValueType pValue,
+                         FragmentRef* pFragmentRef,
+                         ResolveInfo::Visibility pVisibility);
+
+template<> LDSymbol*
+IRBuilder::AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                         const llvm::StringRef& pName,
+                         ResolveInfo::Type pType,
+                         ResolveInfo::Desc pDesc,
+                         ResolveInfo::Binding pBinding,
+                         ResolveInfo::SizeType pSize,
+                         LDSymbol::ValueType pValue,
+                         FragmentRef* pFragmentRef,
+                         ResolveInfo::Visibility pVisibility);
+
 } // end of namespace mcld
 
 #endif
diff --git a/include/mcld/LD/BinaryWriter.h b/include/mcld/LD/BinaryWriter.h
deleted file mode 100644
index d8133c4..0000000
--- a/include/mcld/LD/BinaryWriter.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//===- BinaryWriter.h -----------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_BINARY_WRITER_INTERFACE_H
-#define MCLD_BINARY_WRITER_INTERFACE_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <llvm/Support/system_error.h>
-
-namespace mcld {
-
-class Module;
-class MemoryArea;
-class GNULDBackend;
-
-/** \class BinaryWriter
- *  \brief BinaryWriter provides a common interface for Binary file writers.
- */
-class BinaryWriter
-{
-protected:
-  BinaryWriter(GNULDBackend& pBackend);
-
-public:
-  virtual ~BinaryWriter();
-
-  virtual llvm::error_code writeBinary(Module& pModule, MemoryArea& pOutput) = 0;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/DiagCommonKinds.inc b/include/mcld/LD/DiagCommonKinds.inc
index 08850e7..ae54fe4 100644
--- a/include/mcld/LD/DiagCommonKinds.inc
+++ b/include/mcld/LD/DiagCommonKinds.inc
@@ -24,9 +24,8 @@
 DIAG(err_enable_as_needed_on_static_system, DiagnosticEngine::Warning, "can not enable --as-needed on the target which does not support shared objects", "can not enable --as-needed on the target which does not support shared objects")
 DIAG(err_mix_static_as_needed, DiagnosticEngine::Warning, "cannot mix --static with --as-needed", "cannot mix --static with --as-needed")
 DIAG(err_cannot_change_file_size, DiagnosticEngine::Error, "cannot truncate file `%0' to size %1", "cannot truncate ffile `%0' to size %1")
-DIAG(err_cannot_open_file, DiagnosticEngine::Error, "cannot open file %0.\nError Code: %1", "cannot open file %0.\nError Code: %1")
-DIAG(err_cannot_close_file, DiagnosticEngine::Error, "cannot close file %0.\nError Code: %1", "cannot close file %0.\nError Code: %1")
-DIAG(err_cannot_get_file_status, DiagnosticEngine::Error, "cannot get file status.\nError Code: %0", "cannot get file status.\nError Code: %0")
+DIAG(err_cannot_open_file, DiagnosticEngine::Error, "cannot open file `%0': %1.", "cannot open file `%0': %1.")
+DIAG(err_cannot_close_file, DiagnosticEngine::Error, "cannot close file `%0': %1.", "cannot close file `%0': %1.")
 DIAG(err_cannot_read_file, DiagnosticEngine::Error, "cannot read file %0 from offset %1 to length %2.", "cannot read file %0 from offset %1 to length %2.")
 DIAG(err_cannot_read_small_file, DiagnosticEngine::Fatal, "file %0 is too small to read.\n  file size is %1.\n  read from %2.", "file %0 is too small to read.\n  file size is %1.\n  read from %2.")
 DIAG(err_cannot_mmap_file, DiagnosticEngine::Error, "cannot open memory mapped file %0 from offset %1 to length %2.", "cannot open memoory mpped file %0 from offset %1 to length %2.")
@@ -46,3 +45,5 @@
 DIAG(warn_unsupported_option, DiagnosticEngine::Warning, "Option `%0' is not implemented yet!", "Option `%0' is not implemented yet!")
 DIAG(warn_shared_textrel, DiagnosticEngine::Warning, "Add DT_TEXTREL in a shared object!", "Add DT_TEXTREL in a shared object.")
 DIAG(fatal_illegal_codegen_type, DiagnosticEngine::Fatal, "illegal output format of output %0", "illegal output format of output %0")
+DIAG(err_nmagic_not_static, DiagnosticEngine::Error, "cannot mix -nmagic option with -shared", "cannot mix -nmagic option with -shared")
+DIAG(err_omagic_not_static, DiagnosticEngine::Error, "cannot mix -omagic option with -shared", "cannot mix -omagic option with -shared")
diff --git a/include/mcld/LD/DynObjWriter.h b/include/mcld/LD/DynObjWriter.h
deleted file mode 100644
index 89d9765..0000000
--- a/include/mcld/LD/DynObjWriter.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//===- DynObjWriter.h -----------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_DYNAMIC_SHARED_OBJECT_WRITER_H
-#define MCLD_DYNAMIC_SHARED_OBJECT_WRITER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/LD/LDWriter.h>
-#include <llvm/Support/system_error.h>
-
-namespace mcld {
-
-class Module;
-class MemoryArea;
-class TargetLDBackend;
-
-/** \class DynObjWriter
- *  \brief DynObjWriter provides an common interface for different object
- *  formats.
- */
-class DynObjWriter : public LDWriter
-{
-protected:
-  // force to have a TargetLDBackend
-  DynObjWriter(TargetLDBackend& pLDBackend)
-  { }
-
-public:
-  virtual ~DynObjWriter() { }
-
-  virtual llvm::error_code writeDynObj(Module& pModule,
-                                       MemoryArea& pOutput) = 0;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/ELFBinaryWriter.h b/include/mcld/LD/ELFBinaryWriter.h
deleted file mode 100644
index 593b54b..0000000
--- a/include/mcld/LD/ELFBinaryWriter.h
+++ /dev/null
@@ -1,46 +0,0 @@
-//===- ELFBinaryWriter.h --------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_BINARY_WRITER_H
-#define MCLD_ELF_BINARY_WRITER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <llvm/Support/system_error.h>
-#include <mcld/LD/BinaryWriter.h>
-#include <mcld/LD/ELFWriter.h>
-
-namespace mcld {
-
-class Module;
-class LinkerConfig;
-class MemoryArea;
-class GNULDBackend;
-
-/** \class ELFBinaryWriter
- *  \brief ELFBinaryWriter writes the target-independent parts of Binary files.
- *  ELFBinaryWriter reads a MCLDFile and writes into raw_ostream
- *
- */
-class ELFBinaryWriter : public BinaryWriter, protected ELFWriter
-{
-public:
-  ELFBinaryWriter(GNULDBackend& pBackend, const LinkerConfig& pConfig);
-
-  ~ELFBinaryWriter();
-
-  llvm::error_code writeBinary(Module& pModule, MemoryArea& pOutput);
-
-private:
-  const LinkerConfig& m_Config;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/ELFDynObjWriter.h b/include/mcld/LD/ELFDynObjWriter.h
deleted file mode 100644
index 774943e..0000000
--- a/include/mcld/LD/ELFDynObjWriter.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//===- ELFDynObjWriter.h --------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_DYNAMIC_SHARED_OBJECT_WRITER_H
-#define MCLD_ELF_DYNAMIC_SHARED_OBJECT_WRITER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/LD/DynObjWriter.h>
-#include <mcld/LD/ELFWriter.h>
-
-namespace mcld {
-
-class Module;
-class LinkerConfig;
-class MemoryArea;
-class GNULDBackend;
-
-/** \class ELFDynObjWriter
- *  \brief ELFDynObjWriter writes the dynamic sections.
- */
-class ELFDynObjWriter : public DynObjWriter, private ELFWriter
-{
-public:
-  typedef ELFWriter::FileOffset FileOffset;
-
-public:
-  ELFDynObjWriter(GNULDBackend& pBackend,
-                  const LinkerConfig& pConfig);
-
-  ~ELFDynObjWriter();
-
-  llvm::error_code writeDynObj(Module& pModule, MemoryArea& pOutput);
-
-private:
-  const LinkerConfig& m_Config;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/ELFExecWriter.h b/include/mcld/LD/ELFExecWriter.h
deleted file mode 100644
index ca69235..0000000
--- a/include/mcld/LD/ELFExecWriter.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//===- ELFDynObjWriter.h --------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_EXECUTABLE_OBJECT_WRITER_H
-#define MCLD_ELF_EXECUTABLE_OBJECT_WRITER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/LD/ExecWriter.h>
-#include <mcld/LD/ELFWriter.h>
-
-namespace mcld {
-
-class Module;
-class LinkerConfig;
-class MemoryArea;
-class GNULDBackend;
-
-/** \class ELFDynObjWriter
- *  \brief ELFDynObjWriter writes the dynamic sections.
- */
-class ELFExecWriter : public ExecWriter, private ELFWriter
-{
-public:
-  typedef ELFWriter::FileOffset FileOffset;
-
-public:
-  ELFExecWriter(GNULDBackend& pBackend,
-                const LinkerConfig& pConfig);
-
-  ~ELFExecWriter();
-
-  llvm::error_code writeExecutable(Module& pModule, MemoryArea& pOutput);
-
-private:
-  const LinkerConfig& m_Config;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/ELFFileFormat.h b/include/mcld/LD/ELFFileFormat.h
index e52a813..5ed8997 100644
--- a/include/mcld/LD/ELFFileFormat.h
+++ b/include/mcld/LD/ELFFileFormat.h
@@ -180,6 +180,9 @@
   bool hasDataRelRoLocal() const
   { return (NULL != f_pDataRelRoLocal) && (0 != f_pDataRelRoLocal->size()); }
 
+  bool hasGNUHashTab() const
+  { return (NULL != f_pGNUHashTab) && (0 != f_pGNUHashTab->size()); }
+
   // -----  access functions  ----- //
   /// @ref Special Sections, Ch. 4.17, System V ABI, 4th edition.
   LDSection& getNULLSection() {
@@ -634,6 +637,16 @@
     return *f_pDataRelRoLocal;
   }
 
+  LDSection& getGNUHashTab() {
+    assert(NULL != f_pGNUHashTab);
+    return *f_pGNUHashTab;
+  }
+
+  const LDSection& getGNUHashTab() const {
+    assert(NULL != f_pGNUHashTab);
+    return *f_pGNUHashTab;
+  }
+
 protected:
   //         variable name         :  ELF
   /// @ref Special Sections, Ch. 4.17, System V ABI, 4th edition.
@@ -688,6 +701,7 @@
   LDSection* f_pStack;             // .stack
   LDSection* f_pStackNote;         // .note.GNU-stack
   LDSection* f_pDataRelRoLocal;    // .data.rel.ro.local
+  LDSection* f_pGNUHashTab;        // .gnu.hash
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/ELFObjectWriter.h b/include/mcld/LD/ELFObjectWriter.h
index 28bbba8..ec4311e 100644
--- a/include/mcld/LD/ELFObjectWriter.h
+++ b/include/mcld/LD/ELFObjectWriter.h
@@ -12,7 +12,7 @@
 #include <gtest.h>
 #endif
 #include <mcld/LD/ObjectWriter.h>
-#include <mcld/LD/ELFWriter.h>
+#include <cassert>
 
 #include <llvm/Support/system_error.h>
 
@@ -20,17 +20,27 @@
 
 class Module;
 class LinkerConfig;
-class MemoryArea;
 class GNULDBackend;
+class FragmentLinker;
+class Relocation;
+class LDSection;
+class SectionData;
+class RelocData;
+class Output;
+class MemoryRegion;
+class MemoryArea;
 
 /** \class ELFObjectWriter
  *  \brief ELFObjectWriter writes the target-independent parts of object files.
  *  ELFObjectWriter reads a MCLDFile and writes into raw_ostream
  *
  */
-class ELFObjectWriter : public ObjectWriter, protected ELFWriter
+class ELFObjectWriter : public ObjectWriter
 {
 public:
+  typedef uint64_t FileOffset;
+
+public:
   ELFObjectWriter(GNULDBackend& pBackend,
                   const LinkerConfig& pConfig);
 
@@ -39,9 +49,87 @@
   llvm::error_code writeObject(Module& pModule, MemoryArea& pOutput);
 
 private:
+  void writeSection(MemoryArea& pOutput, LDSection *section);
+
+  GNULDBackend&       target()        { return m_Backend; }
+
+  const GNULDBackend& target() const  { return m_Backend; }
+
+  // writeELFHeader - emit ElfXX_Ehdr
+  template<size_t SIZE>
+  void writeELFHeader(const LinkerConfig& pConfig,
+                      const Module& pModule,
+                      MemoryArea& pOutput) const;
+
+  uint64_t getEntryPoint(const LinkerConfig& pConfig,
+                         const Module& pModule) const;
+
+  // emitSectionHeader - emit ElfXX_Shdr
+  template<size_t SIZE>
+  void emitSectionHeader(const Module& pModule,
+                         const LinkerConfig& pConfig,
+                         MemoryArea& pOutput) const;
+
+  // emitProgramHeader - emit ElfXX_Phdr
+  template<size_t SIZE>
+  void emitProgramHeader(MemoryArea& pOutput) const;
+
+  // emitShStrTab - emit .shstrtab
+  void emitShStrTab(const LDSection& pShStrTab,
+                    const Module& pModule,
+                    MemoryArea& pOutput);
+
+  void emitSectionData(const LDSection& pSection,
+                       MemoryRegion& pRegion) const;
+
+  void emitRelocation(const LinkerConfig& pConfig,
+                      const LDSection& pSection,
+                      MemoryRegion& pRegion) const;
+
+  // emitRel - emit ElfXX_Rel
+  template<size_t SIZE>
+  void emitRel(const LinkerConfig& pConfig,
+               const RelocData& pRelocData,
+               MemoryRegion& pRegion) const;
+
+  // emitRela - emit ElfXX_Rela
+  template<size_t SIZE>
+  void emitRela(const LinkerConfig& pConfig,
+                const RelocData& pRelocData,
+                MemoryRegion& pRegion) const;
+
+  // getSectEntrySize - compute ElfXX_Shdr::sh_entsize
+  template<size_t SIZE>
+  uint64_t getSectEntrySize(const LDSection& pSection) const;
+
+  // getSectLink - compute ElfXX_Shdr::sh_link
+  uint64_t getSectLink(const LDSection& pSection,
+                       const LinkerConfig& pConfig) const;
+
+  // getSectInfo - compute ElfXX_Shdr::sh_info
+  uint64_t getSectInfo(const LDSection& pSection) const;
+
+  template<size_t SIZE>
+  uint64_t getLastStartOffset(const Module& pModule) const
+  {
+    assert(0 && "Call invalid ELFObjectWriter::getLastStartOffset");
+    return 0;
+  }
+
+  void emitSectionData(const SectionData& pSD, MemoryRegion& pRegion) const;
+
+private:
+  GNULDBackend& m_Backend;
+
   const LinkerConfig& m_Config;
 };
 
+template<>
+uint64_t ELFObjectWriter::getLastStartOffset<32>(const Module& pModule) const;
+
+template<>
+uint64_t ELFObjectWriter::getLastStartOffset<64>(const Module& pModule) const;
+
 } // namespace of mcld
 
 #endif
diff --git a/include/mcld/LD/ELFReader.h b/include/mcld/LD/ELFReader.h
index 146a00a..b42b272 100644
--- a/include/mcld/LD/ELFReader.h
+++ b/include/mcld/LD/ELFReader.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_READER_INTERFACE_H
-#define MCLD_ELF_READER_INTERFACE_H
+#ifndef MCLD_ELF_READER_H
+#define MCLD_ELF_READER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -16,120 +16,19 @@
 #include <llvm/Support/ELF.h>
 #include <llvm/Support/Host.h>
 
-#include <mcld/Module.h>
-#include <mcld/LinkerConfig.h>
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/LD/ELFReaderIf.h>
 #include <mcld/LD/ResolveInfo.h>
-#include <mcld/LD/LDContext.h>
 #include <mcld/Target/GNULDBackend.h>
 #include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/MsgHandling.h>
 
 namespace mcld {
 
-class Module;
+//class Module;
 class IRBuilder;
-class FragmentRef;
 class SectionData;
 class LDSection;
 
-/** \class ELFReaderIF
- *  \brief ELFReaderIF provides common interface for all kind of ELF readers.
- */
-class ELFReaderIF
-{
-public:
-  ELFReaderIF(GNULDBackend& pBackend)
-    : m_Backend(pBackend)
-  { }
-
-  virtual ~ELFReaderIF() { }
-
-  /// ELFHeaderSize - return the size of the ELFHeader
-  virtual size_t getELFHeaderSize() const = 0;
-
-  /// isELF - is this a ELF file
-  virtual bool isELF(void* pELFHeader) const = 0;
-
-  /// isMyEndian - is this ELF file in the same endian to me?
-  virtual bool isMyEndian(void* pELFHeader) const = 0;
-
-  /// isMyMachine - is this ELF file generated for the same machine.
-  virtual bool isMyMachine(void* pELFHeader) const = 0;
-
-  /// fileType - the file type of this file
-  virtual Input::Type fileType(void* pELFHeader) const = 0;
-
-  /// target - the target backend
-  const GNULDBackend& target() const { return m_Backend; }
-  GNULDBackend&       target()       { return m_Backend; }
-
-
-  /// readSectionHeaders - read ELF section header table and create LDSections
-  virtual bool readSectionHeaders(Input& pInput, void* pELFHeader) const = 0;
-
-  /// readRegularSection - read a regular section and create fragments.
-  virtual bool readRegularSection(Input& pInput, SectionData& pSD) const = 0;
-
-  /// readSymbols - read ELF symbols and create LDSymbol
-  virtual bool readSymbols(Input& pInput,
-                           IRBuilder& pBuilder,
-                           const MemoryRegion& pRegion,
-                           const char* StrTab) const = 0;
-
-  /// readSignature - read a symbol from the given Input and index in symtab
-  /// This is used to get the signature of a group section.
-  virtual ResolveInfo* readSignature(Input& pInput,
-                                     LDSection& pSymTab,
-                                     uint32_t pSymIdx) const = 0;
-
-  /// readRela - read ELF rela and create Relocation
-  virtual bool readRela(Input& pInput,
-                        LDSection& pSection,
-                        const MemoryRegion& pRegion) const = 0;
-
-  /// readRel - read ELF rel and create Relocation
-  virtual bool readRel(Input& pInput,
-                       LDSection& pSection,
-                       const MemoryRegion& pRegion) const = 0;
-
-  /// readDynamic - read ELF .dynamic in input dynobj
-  virtual bool readDynamic(Input& pInput) const = 0;
-
-protected:
-  /// LinkInfo - some section needs sh_link and sh_info, remember them.
-  struct LinkInfo {
-    LDSection* section;
-    uint32_t sh_link;
-    uint32_t sh_info;
-  };
-
-  typedef std::vector<LinkInfo> LinkInfoList;
-
-protected:
-  ResolveInfo::Type getSymType(uint8_t pInfo, uint16_t pShndx) const;
-
-  ResolveInfo::Desc getSymDesc(uint16_t pShndx, const Input& pInput) const;
-
-  ResolveInfo::Binding getSymBinding(uint8_t pBinding,
-                                     uint16_t pShndx,
-                                     uint8_t pVisibility) const;
-
-  uint64_t getSymValue(uint64_t pValue,
-                       uint16_t pShndx,
-                       const Input& pInput) const;
-
-  FragmentRef* getSymFragmentRef(Input& pInput,
-                                 uint16_t pShndx,
-                                 uint32_t pOffset) const;
-
-  ResolveInfo::Visibility getSymVisibility(uint8_t pVis) const;
-
-protected:
-  GNULDBackend& m_Backend;
-};
-
 /** \class ELFReader
  *  \brief ELFReader is a template scaffolding for partial specification.
  */
@@ -203,6 +102,73 @@
   bool readDynamic(Input& pInput) const;
 };
 
+
+/** \class ELFReader<64, true>
+ *  \brief ELFReader<64, true> is a 64-bit, little endian ELFReader.
+ */
+template<>
+class ELFReader<64, true> : public ELFReaderIF
+{
+public:
+  typedef llvm::ELF::Elf64_Ehdr ELFHeader;
+  typedef llvm::ELF::Elf64_Shdr SectionHeader;
+  typedef llvm::ELF::Elf64_Sym  Symbol;
+  typedef llvm::ELF::Elf64_Rel  Rel;
+  typedef llvm::ELF::Elf64_Rela Rela;
+
+public:
+  ELFReader(GNULDBackend& pBackend);
+
+  ~ELFReader();
+
+  /// ELFHeaderSize - return the size of the ELFHeader
+  size_t getELFHeaderSize() const
+  { return sizeof(ELFHeader); }
+
+  /// isELF - is this a ELF file
+  bool isELF(void* pELFHeader) const;
+
+  /// isMyEndian - is this ELF file in the same endian to me?
+  bool isMyEndian(void* pELFHeader) const;
+
+  /// isMyMachine - is this ELF file generated for the same machine.
+  bool isMyMachine(void* pELFHeader) const;
+
+  /// fileType - the file type of this file
+  Input::Type fileType(void* pELFHeader) const;
+
+  /// readSectionHeaders - read ELF section header table and create LDSections
+  bool readSectionHeaders(Input& pInput, void* pELFHeader) const;
+
+  /// readRegularSection - read a regular section and create fragments.
+  bool readRegularSection(Input& pInput, SectionData& pSD) const;
+
+  /// readSymbols - read ELF symbols and create LDSymbol
+  bool readSymbols(Input& pInput,
+                   IRBuilder& pBuilder,
+                   const MemoryRegion& pRegion,
+                   const char* StrTab) const;
+
+  /// readSignature - read a symbol from the given Input and index in symtab
+  /// This is used to get the signature of a group section.
+  ResolveInfo* readSignature(Input& pInput,
+                                    LDSection& pSymTab,
+                                    uint32_t pSymIdx) const;
+
+  /// readRela - read ELF rela and create Relocation
+  bool readRela(Input& pInput,
+                LDSection& pSection,
+                const MemoryRegion& pRegion) const;
+
+  /// readRel - read ELF rel and create Relocation
+  bool readRel(Input& pInput,
+               LDSection& pSection,
+               const MemoryRegion& pRegion) const;
+
+  /// readDynamic - read ELF .dynamic in input dynobj
+  bool readDynamic(Input& pInput) const;
+};
+
 } // namespace of mcld
 
 #endif
diff --git a/include/mcld/LD/ELFReaderIf.h b/include/mcld/LD/ELFReaderIf.h
new file mode 100644
index 0000000..245b542
--- /dev/null
+++ b/include/mcld/LD/ELFReaderIf.h
@@ -0,0 +1,132 @@
+//===- ELFReader.h --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ELF_READER_INTERFACE_H
+#define MCLD_ELF_READER_INTERFACE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Support/ELF.h>
+#include <llvm/Support/Host.h>
+
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/LD/LDContext.h>
+#include <mcld/Target/GNULDBackend.h>
+#include <mcld/Support/MsgHandling.h>
+
+namespace mcld {
+
+class Module;
+class IRBuilder;
+class FragmentRef;
+class SectionData;
+class LDSection;
+
+/** \class ELFReaderIF
+ *  \brief ELFReaderIF provides common interface for all kind of ELF readers.
+ */
+class ELFReaderIF
+{
+public:
+  ELFReaderIF(GNULDBackend& pBackend)
+    : m_Backend(pBackend)
+  { }
+
+  virtual ~ELFReaderIF() { }
+
+  /// ELFHeaderSize - return the size of the ELFHeader
+  virtual size_t getELFHeaderSize() const = 0;
+
+  /// isELF - is this a ELF file
+  virtual bool isELF(void* pELFHeader) const = 0;
+
+  /// isMyEndian - is this ELF file in the same endian to me?
+  virtual bool isMyEndian(void* pELFHeader) const = 0;
+
+  /// isMyMachine - is this ELF file generated for the same machine.
+  virtual bool isMyMachine(void* pELFHeader) const = 0;
+
+  /// fileType - the file type of this file
+  virtual Input::Type fileType(void* pELFHeader) const = 0;
+
+  /// target - the target backend
+  const GNULDBackend& target() const { return m_Backend; }
+  GNULDBackend&       target()       { return m_Backend; }
+
+
+  /// readSectionHeaders - read ELF section header table and create LDSections
+  virtual bool readSectionHeaders(Input& pInput, void* pELFHeader) const = 0;
+
+  /// readRegularSection - read a regular section and create fragments.
+  virtual bool readRegularSection(Input& pInput, SectionData& pSD) const = 0;
+
+  /// readSymbols - read ELF symbols and create LDSymbol
+  virtual bool readSymbols(Input& pInput,
+                           IRBuilder& pBuilder,
+                           const MemoryRegion& pRegion,
+                           const char* StrTab) const = 0;
+
+  /// readSignature - read a symbol from the given Input and index in symtab
+  /// This is used to get the signature of a group section.
+  virtual ResolveInfo* readSignature(Input& pInput,
+                                     LDSection& pSymTab,
+                                     uint32_t pSymIdx) const = 0;
+
+  /// readRela - read ELF rela and create Relocation
+  virtual bool readRela(Input& pInput,
+                        LDSection& pSection,
+                        const MemoryRegion& pRegion) const = 0;
+
+  /// readRel - read ELF rel and create Relocation
+  virtual bool readRel(Input& pInput,
+                       LDSection& pSection,
+                       const MemoryRegion& pRegion) const = 0;
+
+  /// readDynamic - read ELF .dynamic in input dynobj
+  virtual bool readDynamic(Input& pInput) const = 0;
+
+protected:
+  /// LinkInfo - some section needs sh_link and sh_info, remember them.
+  struct LinkInfo {
+    LDSection* section;
+    uint32_t sh_link;
+    uint32_t sh_info;
+  };
+
+  typedef std::vector<LinkInfo> LinkInfoList;
+
+protected:
+  ResolveInfo::Type getSymType(uint8_t pInfo, uint16_t pShndx) const;
+
+  ResolveInfo::Desc getSymDesc(uint16_t pShndx, const Input& pInput) const;
+
+  ResolveInfo::Binding getSymBinding(uint8_t pBinding,
+                                     uint16_t pShndx,
+                                     uint8_t pVisibility) const;
+
+  uint64_t getSymValue(uint64_t pValue,
+                       uint16_t pShndx,
+                       const Input& pInput) const;
+
+  FragmentRef* getSymFragmentRef(Input& pInput,
+                                 uint16_t pShndx,
+                                 uint32_t pOffset) const;
+
+  ResolveInfo::Visibility getSymVisibility(uint8_t pVis) const;
+
+protected:
+  GNULDBackend& m_Backend;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/ELFWriter.h b/include/mcld/LD/ELFWriter.h
deleted file mode 100644
index b0c4d81..0000000
--- a/include/mcld/LD/ELFWriter.h
+++ /dev/null
@@ -1,124 +0,0 @@
-//===- ELFWriter.h --------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_WRITER_H
-#define MCLD_ELF_WRITER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <llvm/Support/ELF.h>
-
-namespace mcld {
-
-class Module;
-class FragmentLinker;
-class LinkerConfig;
-class GNULDBackend;
-class Relocation;
-class LDSection;
-class SectionData;
-class RelocData;
-class Output;
-class MemoryRegion;
-class MemoryArea;
-
-/** \class ELFWriter
- *  \brief ELFWriter provides basic functions to write ELF sections, symbols,
- *  and so on.
- */
-class ELFWriter
-{
-public:
-  typedef uint64_t FileOffset;
-
-protected:
-  ELFWriter(GNULDBackend& pBackend)
-  : f_Backend(pBackend) {
-  }
-
-public:
-  virtual ~ELFWriter() { }
-
-  GNULDBackend& target()
-  { return f_Backend; }
-
-  const GNULDBackend& target() const
-  { return f_Backend; }
-
-  virtual void writeELF32Header(const LinkerConfig& pConfig,
-                                const Module& pModule,
-                                MemoryArea& pOutput) const;
-
-  virtual void writeELF64Header(const LinkerConfig& pConfig,
-                                const Module& pModule,
-                                MemoryArea& pOutput) const;
-
-  virtual uint64_t getEntryPoint(const LinkerConfig& pConfig,
-                                 const Module& pModule) const;
-
-protected:
-  void emitELF32SectionHeader(const Module& pModule,
-                              const LinkerConfig& pConfig,
-                              MemoryArea& pOutput) const;
-
-  void emitELF64SectionHeader(const Module& pModule,
-                              const LinkerConfig& pConfig,
-                              MemoryArea& pOutput) const;
-
-  void emitELF32ProgramHeader(MemoryArea& pOutput) const;
-
-  void emitELF64ProgramHeader(MemoryArea& pOutput) const;
-
-  // emitShStrTab - emit .shstrtab
-  void emitELFShStrTab(const LDSection& pShStrTab, const Module& pModule,
-                       MemoryArea& pOutput);
-
-  void emitSectionData(const LDSection& pSection,
-                       MemoryRegion& pRegion) const;
-
-  void emitRelocation(const LinkerConfig& pConfig,
-                      const LDSection& pSection,
-                      MemoryRegion& pRegion) const;
-
-  void emitRel(const LinkerConfig& pConfig,
-               const RelocData& pRelocData,
-               MemoryRegion& pRegion) const;
-
-  void emitRela(const LinkerConfig& pConfig,
-                const RelocData& pRelocData,
-                MemoryRegion& pRegion) const;
-
-private:
-  // getSectEntrySize - compute ElfXX_Shdr::sh_entsize
-  uint64_t getELF32SectEntrySize(const LDSection& pSection) const;
-
-  // getSectEntrySize - compute ElfXX_Shdr::sh_entsize
-  uint64_t getELF64SectEntrySize(const LDSection& pSection) const;
-
-  // getSectEntrySize - compute ElfXX_Shdr::sh_link
-  uint64_t getSectLink(const LDSection& pSection,
-                       const LinkerConfig& pConfig) const;
-
-  // getSectEntrySize - compute ElfXX_Shdr::sh_info
-  uint64_t getSectInfo(const LDSection& pSection) const;
-
-  uint64_t getELF32LastStartOffset(const Module& pModule) const;
-
-  uint64_t getELF64LastStartOffset(const Module& pModule) const;
-
-  void emitSectionData(const SectionData& pSD, MemoryRegion& pRegion) const;
-
-protected:
-  GNULDBackend& f_Backend;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/EhFrame.h b/include/mcld/LD/EhFrame.h
index dc360a2..695f72b 100644
--- a/include/mcld/LD/EhFrame.h
+++ b/include/mcld/LD/EhFrame.h
@@ -12,8 +12,11 @@
 #include <gtest.h>
 #endif
 
-#include <vector>
+#include <mcld/Config/Config.h>
 #include <mcld/Fragment/RegionFragment.h>
+#include <mcld/Support/Allocators.h>
+
+#include <vector>
 
 namespace mcld {
 
@@ -25,6 +28,17 @@
  */
 class EhFrame
 {
+private:
+  friend class Chunk<EhFrame, MCLD_SECTIONS_PER_INPUT>;
+
+  EhFrame();
+  explicit EhFrame(LDSection& pSection);
+
+  ~EhFrame();
+
+  EhFrame(const EhFrame&);            // DO NOT IMPLEMENT
+  EhFrame& operator=(const EhFrame&); // DO NOT IMPLEMENT
+
 public:
   /** \class CIE
    *  \brief Common Information Entry.
@@ -56,6 +70,7 @@
     const CIE& getCIE() const { return m_CIE; }
 
     uint32_t getDataStart() const { return m_DataStart; }
+
   private:
     const CIE& m_CIE;
     uint32_t m_DataStart;
@@ -74,15 +89,17 @@
   typedef FDEList::const_iterator const_fde_iterator;
 
 public:
-  EhFrame(LDSection& pSection);
+  static EhFrame* Create(LDSection& pSection);
 
-  ~EhFrame();
+  static void Destroy(EhFrame*& pSection);
+
+  static void Clear();
 
   /// merge - move all data from pOther to this object.
   EhFrame& merge(EhFrame& pOther);
 
-  const LDSection& getSection() const { return m_Section; }
-  LDSection&       getSection()       { return m_Section; }
+  const LDSection& getSection() const;
+  LDSection&       getSection();
 
   const SectionData& getSectionData() const { return *m_pSectionData; }
   SectionData&       getSectionData()       { return *m_pSectionData; }
@@ -125,7 +142,7 @@
   size_t numOfFDEs() const { return m_FDEs.size(); }
 
 private:
-  LDSection& m_Section;
+  LDSection* m_pSection;
   SectionData* m_pSectionData;
 
   CIEList m_CIEs;
diff --git a/include/mcld/LD/EhFrameHdr.h b/include/mcld/LD/EhFrameHdr.h
index 3a5971d..e9d8702 100644
--- a/include/mcld/LD/EhFrameHdr.h
+++ b/include/mcld/LD/EhFrameHdr.h
@@ -70,6 +70,9 @@
 template<>
 void EhFrameHdr::emitOutput<32>(MemoryArea& pOutput);
 
+template<>
+void EhFrameHdr::emitOutput<64>(MemoryArea& pOutput);
+
 } // namespace of mcld
 
 #endif
diff --git a/include/mcld/LD/ExecWriter.h b/include/mcld/LD/ExecWriter.h
deleted file mode 100644
index e0ea325..0000000
--- a/include/mcld/LD/ExecWriter.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//===- ExecWriter.h -------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_EXECUTABLE_OBJECT_WRITER_H
-#define MCLD_EXECUTABLE_OBJECT_WRITER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/LD/LDWriter.h>
-#include <llvm/Support/system_error.h>
-
-namespace mcld {
-
-class Module;
-class MemoryArea;
-class TargetLDBackend;
-
-/** \class ExecWriter
- *  \brief ExecWriter provides an common interface for different object
- *  formats.
- */
-class ExecWriter : public LDWriter
-{
-protected:
-  // force to have a TargetLDBackend
-  ExecWriter(TargetLDBackend& pLDBackend)
-  { }
-
-public:
-  virtual ~ExecWriter() { }
-
-  virtual llvm::error_code writeExecutable(Module& pModule,
-                                           MemoryArea& pOutput) = 0;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/LDSymbol.h b/include/mcld/LD/LDSymbol.h
index 326c82f..b40213c 100644
--- a/include/mcld/LD/LDSymbol.h
+++ b/include/mcld/LD/LDSymbol.h
@@ -19,6 +19,8 @@
 #include <mcld/LD/ResolveInfo.h>
 #include <mcld/Support/Allocators.h>
 
+#include <llvm/Support/ManagedStatic.h>
+
 namespace mcld {
 
 class FragmentRef;
@@ -127,6 +129,7 @@
 
 private:
   friend class Chunk<LDSymbol, MCLD_SYMBOLS_PER_INPUT>;
+  template<class T> friend void* llvm::object_creator();
 
   LDSymbol();
   LDSymbol(const LDSymbol& pCopy);
diff --git a/include/mcld/LD/LDWriter.h b/include/mcld/LD/LDWriter.h
deleted file mode 100644
index b7dd14c..0000000
--- a/include/mcld/LD/LDWriter.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//===- LDWriter.h ---------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//  LDWriter provides an interface used by MCLinker,
-//  which writes the result of linking into a .so file or a executable.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_WRITER_INTERFACE_H
-#define MCLD_WRITER_INTERFACE_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-namespace mcld {
-
-/** \class LDWriter
- *  \brief LDWriter provides the basic interfaces for all writers.
- *  (ObjectWriter, DynObjWriter, and EXEObjWriter)
- */
-class LDWriter
-{
-protected:
-  LDWriter() { }
-
-public:
-  virtual ~LDWriter() { }
-
-};
-
-} //end namespace
-
-#endif
-
diff --git a/include/mcld/LD/NamePool.h b/include/mcld/LD/NamePool.h
index 12b4b91..fa0bb10 100644
--- a/include/mcld/LD/NamePool.h
+++ b/include/mcld/LD/NamePool.h
@@ -12,15 +12,17 @@
 #include <gtest.h>
 #endif
 
-#include <utility>
-
-#include <llvm/ADT/StringRef.h>
-
+#include <mcld/Config/Config.h>
 #include <mcld/ADT/HashTable.h>
 #include <mcld/ADT/StringHash.h>
 #include <mcld/ADT/Uncopyable.h>
 #include <mcld/LD/Resolver.h>
 #include <mcld/LD/ResolveInfo.h>
+#include <mcld/Support/GCFactory.h>
+
+#include <utility>
+
+#include <llvm/ADT/StringRef.h>
 
 namespace mcld {
 
@@ -97,9 +99,12 @@
   size_type capacity() const;
 
 private:
+  typedef GCFactory<ResolveInfo*, 128> FreeInfoSet;
+
+private:
   Resolver* m_pResolver;
   Table m_Table;
-
+  FreeInfoSet m_FreeInfoSet;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/ObjectWriter.h b/include/mcld/LD/ObjectWriter.h
index a84e0d3..c1dcac6 100644
--- a/include/mcld/LD/ObjectWriter.h
+++ b/include/mcld/LD/ObjectWriter.h
@@ -17,7 +17,6 @@
 
 class Module;
 class MemoryArea;
-class GNULDBackend;
 
 /** \class ObjectWriter
  *  \brief ObjectWriter provides a common interface for object file writers.
@@ -25,7 +24,7 @@
 class ObjectWriter
 {
 protected:
-  ObjectWriter(GNULDBackend& pBackend);
+  ObjectWriter();
 
 public:
   virtual ~ObjectWriter();
diff --git a/include/mcld/LD/Relocator.h b/include/mcld/LD/Relocator.h
index 6fd431e..8589894 100644
--- a/include/mcld/LD/Relocator.h
+++ b/include/mcld/LD/Relocator.h
@@ -26,10 +26,11 @@
 class Relocator
 {
 public:
-  typedef Relocation::Type Type;
+  typedef Relocation::Type    Type;
   typedef Relocation::Address Address;
-  typedef Relocation::DWord DWord;
-  typedef Relocation::SWord SWord;
+  typedef Relocation::DWord   DWord;
+  typedef Relocation::SWord   SWord;
+  typedef Relocation::Size    Size;
 
 public:
   enum Result {
@@ -41,33 +42,21 @@
   };
 
 public:
-  virtual ~Relocator() {}
+  virtual ~Relocator() = 0;
 
   /// apply - general apply function
   virtual Result applyRelocation(Relocation& pRelocation) = 0;
 
-  void setFragmentLinker(const FragmentLinker& pLinker)
-  { m_pLinker = &pLinker; }
-
   // ------ observers -----//
-  const FragmentLinker& getFragmentLinker() const
-  {
-    assert(NULL != m_pLinker);
-    return *m_pLinker;
-  }
-
-  bool hasFragmentLinker() const
-  { return (NULL != m_pLinker); }
-
   virtual TargetLDBackend& getTarget() = 0;
 
   virtual const TargetLDBackend& getTarget() const = 0;
 
+  /// getName - get the name of a relocation
   virtual const char* getName(Type pType) const = 0;
 
-private:
-  const FragmentLinker* m_pLinker;
-
+  /// getSize - get the size of a relocation in bit
+  virtual Size getSize(Type pType) const = 0;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/StubFactory.h b/include/mcld/LD/StubFactory.h
index b38a96f..8548e5a 100644
--- a/include/mcld/LD/StubFactory.h
+++ b/include/mcld/LD/StubFactory.h
@@ -20,7 +20,7 @@
 class Stub;
 class Relocation;
 class BranchIslandFactory;
-class FragmentLinker;
+class IRBuilder;
 
 /** \class StubFactory
  *  \brief the clone factory of Stub
@@ -37,7 +37,7 @@
   /// create - create a stub if needed, otherwise return NULL
   Stub* create(Relocation& pReloc,
                uint64_t pTargetSymValue,
-               FragmentLinker& pLinker,
+               IRBuilder& pBuilder,
                BranchIslandFactory& pBRIslandFactory);
 
 private:
diff --git a/include/mcld/Linker.h b/include/mcld/Linker.h
index 891372c..d5fc438 100644
--- a/include/mcld/Linker.h
+++ b/include/mcld/Linker.h
@@ -38,14 +38,26 @@
 
   ~Linker();
 
+  /// config - To set up target-dependent options in pConfig.
   bool config(LinkerConfig& pConfig);
 
+  /// resolve - To read participatory input files and build up mcld::Module
+  bool resolve(Module& pModule, IRBuilder& pBuilder);
+
+  /// layout - To serialize the final result of the output mcld::Module
+  bool layout();
+
+  /// link - A convenient way to resolve and to layout the output mcld::Module.
   bool link(Module& pModule, IRBuilder& pBuilder);
 
+  /// emit - To emit output mcld::Module to a output MemoryArea
   bool emit(MemoryArea& pOutput);
 
+  /// emit - To open a file for output in pPath and to emit output mcld::Module
+  /// to the file.
   bool emit(const std::string& pPath);
 
+  /// emit - To emit output mcld::Module in the pFileDescriptor.
   bool emit(int pFileDescriptor);
 
   bool reset();
@@ -61,7 +73,6 @@
 
 private:
   LinkerConfig* m_pConfig;
-  Module* m_pModule;
   IRBuilder* m_pIRBuilder;
 
   const Target* m_pTarget;
diff --git a/include/mcld/LinkerConfig.h b/include/mcld/LinkerConfig.h
index 9e70ecf..f0c2c87 100644
--- a/include/mcld/LinkerConfig.h
+++ b/include/mcld/LinkerConfig.h
@@ -44,6 +44,28 @@
     Binary
   };
 
+  /** \enum CodePosition
+   *  CodePosition indicates the ability of the generated output to be
+   *  loaded at different addresses. If the output can be loaded at different
+   *  addresses, we say the output is position independent. Shared libraries
+   *  and position-independent executable programs (PIE) are in this category.
+   *  ::Independent indicates the output is position independent.
+   *  If a executable program can not be loaded at arbitrary addresses, but it
+   *  can call outside functions, we say the program is dynamic dependent on
+   *  the address to be loaded. ::DynamicDependent indicates the output is not
+   *  only a executable program, but also dynamic dependent. In general,
+   *  executable programs are dynamic dependent.
+   *  If a executable program can not be loaded at different addresses, and
+   *  only call inner functions, then we say the program is static dependent on
+   *  its loaded address. ::StaticDependent is used to indicate this kind of
+   *  output.
+   */
+  enum CodePosition {
+    Independent,      ///< Position Independent
+    DynamicDependent, ///< Can call outside libraries
+    StaticDependent   ///< Can not call outside libraries
+  };
+
 public:
   LinkerConfig();
 
@@ -70,6 +92,13 @@
 
   void setCodeGenType(CodeGenType pType) { m_CodeGenType = pType; }
 
+  CodePosition codePosition() const { return m_CodePosition; }
+  void setCodePosition(CodePosition pPosition) { m_CodePosition = pPosition; }
+
+  bool isCodeIndep()   const { return (Independent == m_CodePosition); }
+  bool isCodeDynamic() const { return (DynamicDependent == m_CodePosition); }
+  bool isCodeStatic()  const { return (StaticDependent == m_CodePosition); }
+
   static const char* version();
 
 private:
@@ -81,6 +110,7 @@
   AttributeOption m_Attribute;
 
   CodeGenType m_CodeGenType;
+  CodePosition m_CodePosition;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/MC/SearchDirs.h b/include/mcld/MC/SearchDirs.h
index 13cc12f..0c0c657 100644
--- a/include/mcld/MC/SearchDirs.h
+++ b/include/mcld/MC/SearchDirs.h
@@ -65,6 +65,8 @@
   iterator       end  ()       { return m_DirList.end();   }
 
   // -----  modifiers  ----- //
+  bool insert(const char* pDirectory);
+
   bool insert(const std::string& pDirectory);
 
   bool insert(const sys::fs::Path& pDirectory);
diff --git a/include/mcld/MC/SymbolCategory.h b/include/mcld/MC/SymbolCategory.h
index 3aa16c5..700fba2 100644
--- a/include/mcld/MC/SymbolCategory.h
+++ b/include/mcld/MC/SymbolCategory.h
@@ -11,7 +11,7 @@
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include <mcld/ADT/TypeTraits.h>
+#include <cstddef>
 #include <vector>
 
 namespace mcld
@@ -45,7 +45,7 @@
 
   SymbolCategory& changeCommonsToGlobal();
 
-  SymbolCategory& changeLocalToTLS(const LDSymbol& pSymbol);
+  SymbolCategory& changeLocalToDynamic(const LDSymbol& pSymbol);
 
   // -----  access  ----- //
   LDSymbol& at(size_t pPosition)
@@ -63,18 +63,30 @@
   // -----  observers  ----- //
   size_t numOfSymbols() const;
 
+  size_t numOfFiles() const;
+
   size_t numOfLocals() const;
 
+  size_t numOfLocalDyns() const;
+
   size_t numOfCommons() const;
 
+  size_t numOfDynamics() const;
+
   size_t numOfRegulars() const;
 
   bool empty() const;
 
+  bool emptyFiles() const;
+
   bool emptyLocals() const;
 
+  bool emptyLocalDyns() const;
+
   bool emptyCommons() const;
 
+  bool emptyDynamics() const;
+
   bool emptyRegulars() const;
 
   // -----  iterators  ----- //
@@ -83,21 +95,31 @@
   const_iterator begin() const;
   const_iterator end() const;
 
+  iterator fileBegin();
+  iterator fileEnd();
+  const_iterator fileBegin() const;
+  const_iterator fileEnd() const;
+
   iterator localBegin();
   iterator localEnd();
   const_iterator localBegin() const;
   const_iterator localEnd() const;
 
-  iterator tlsBegin();
-  iterator tlsEnd();
-  const_iterator tlsBegin() const;
-  const_iterator tlsEnd() const;
+  iterator localDynBegin();
+  iterator localDynEnd();
+  const_iterator localDynBegin() const;
+  const_iterator localDynEnd() const;
 
   iterator commonBegin();
   iterator commonEnd();
   const_iterator commonBegin() const;
   const_iterator commonEnd() const;
 
+  iterator dynamicBegin();
+  iterator dynamicEnd();
+  const_iterator dynamicBegin() const;
+  const_iterator dynamicEnd() const;
+
   iterator regularBegin();
   iterator regularEnd();
   const_iterator regularBegin() const;
@@ -110,10 +132,10 @@
     enum Type {
       File,
       Local,
-      TLS,
+      LocalDyn,
       Common,
-      Weak,
-      Global
+      Dynamic,
+      Regular
     };
 
   public:
@@ -147,18 +169,20 @@
     { return (NULL == next); }
 
     static Type categorize(const ResolveInfo& pInfo);
-
   };
 
 private:
+  SymbolCategory& add(LDSymbol& pSymbol, Category::Type pTarget);
+
+private:
   OutputSymbols m_OutputSymbols;
 
   Category* m_pFile;
   Category* m_pLocal;
-  Category* m_pTLS;
+  Category* m_pLocalDyn;
   Category* m_pCommon;
-  Category* m_pWeak;
-  Category* m_pGlobal;
+  Category* m_pDynamic;
+  Category* m_pRegular;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/Object/ObjectBuilder.h b/include/mcld/Object/ObjectBuilder.h
index bfa4c6b..79f81a5 100644
--- a/include/mcld/Object/ObjectBuilder.h
+++ b/include/mcld/Object/ObjectBuilder.h
@@ -65,12 +65,16 @@
   ///
   /// @see SectionMap
   /// @param [in] pInputSection The merged input section.
-  /// @return If the corresponding output sections is not defined, return false.
-  bool MergeSection(LDSection& pInputSection);
+  /// @return The merged output section. If the corresponding output sections
+  /// is not defined, return NULL.
+  LDSection* MergeSection(LDSection& pInputSection);
 
   /// MoveSectionData - move the fragment of pFrom to pTo section data.
   static bool MoveSectionData(SectionData& pFrom, SectionData& pTo);
 
+  /// UpdateSectionAlign - update alignment for input section
+  static void UpdateSectionAlign(LDSection& pTo, const LDSection& pFrom);
+
 /// @}
 /// @name Fragment Methods
 /// @{
diff --git a/include/mcld/Object/ObjectLinker.h b/include/mcld/Object/ObjectLinker.h
index 515bc58..999764f 100644
--- a/include/mcld/Object/ObjectLinker.h
+++ b/include/mcld/Object/ObjectLinker.h
@@ -44,12 +44,12 @@
 {
 public:
   ObjectLinker(const LinkerConfig& pConfig,
-               Module& pModule,
-               IRBuilder& pBuilder,
                TargetLDBackend& pLDBackend);
 
   ~ObjectLinker();
 
+  void setup(Module& pModule, IRBuilder& pBuilder);
+
   /// initFragmentLinker - initialize FragmentLinker
   ///  Connect all components in FragmentLinker
   bool initFragmentLinker();
@@ -72,6 +72,10 @@
   /// mergeSections - put allinput sections into output sections
   bool mergeSections();
 
+  /// allocateCommonSymobols - allocate fragments for common symbols to the
+  /// corresponding sections
+  bool allocateCommonSymbols();
+
   /// addStandardSymbols - shared object and executable files need some
   /// standard symbols
   ///   @return if there are some input symbols with the same name to the
@@ -84,9 +88,18 @@
   ///   target symbols, return false
   bool addTargetSymbols();
 
+  /// addScriptSymbols - define symbols from the command line option or linker
+  /// scripts.
+  ///   @return if there are some existing symbols with identical name to the
+  ///   script symbols, return false.
+  bool addScriptSymbols();
+
   /// scanRelocations - scan all relocation entries by output symbols.
   bool scanRelocations();
 
+  /// initStubs - initialize stub-related stuff.
+  bool initStubs();
+
   /// prelayout - help backend to do some modification before layout
   bool prelayout();
 
@@ -140,25 +153,15 @@
   const BinaryReader*  getBinaryReader () const { return m_pBinaryReader;  }
   BinaryReader*        getBinaryReader ()       { return m_pBinaryReader;  }
 
-  const ObjectWriter*  getObjectWriter () const { return m_pObjectWriter;  }
-  ObjectWriter*        getObjectWriter ()       { return m_pObjectWriter;  }
-
-  const DynObjWriter*  getDynObjWriter () const { return m_pDynObjWriter;  }
-  DynObjWriter*        getDynObjWriter ()       { return m_pDynObjWriter;  }
-
-  const ExecWriter*    getExecWriter   () const { return m_pExecWriter;    }
-  ExecWriter*          getExecWriter   ()       { return m_pExecWriter;    }
-
-  const BinaryWriter*  getBinaryWriter () const { return m_pBinaryWriter;  }
-  BinaryWriter*        getBinaryWriter ()       { return m_pBinaryWriter;  }
+  const ObjectWriter*  getWriter () const { return m_pWriter;  }
+  ObjectWriter*        getWriter ()       { return m_pWriter;  }
 
 private:
   const LinkerConfig& m_Config;
-  Module& m_Module;
-
-  IRBuilder& m_Builder; 
-
   FragmentLinker* m_pLinker;
+  Module* m_pModule;
+  IRBuilder* m_pBuilder;
+
   TargetLDBackend &m_LDBackend;
 
   // -----  readers and writers  ----- //
@@ -167,10 +170,7 @@
   ArchiveReader* m_pArchiveReader;
   GroupReader*   m_pGroupReader;
   BinaryReader*  m_pBinaryReader;
-  ObjectWriter*  m_pObjectWriter;
-  DynObjWriter*  m_pDynObjWriter;
-  ExecWriter*    m_pExecWriter;
-  BinaryWriter*  m_pBinaryWriter;
+  ObjectWriter*  m_pWriter;
 };
 
 } // end namespace mcld
diff --git a/include/mcld/Support/FileHandle.h b/include/mcld/Support/FileHandle.h
index 3b4fe81..ce43e0f 100644
--- a/include/mcld/Support/FileHandle.h
+++ b/include/mcld/Support/FileHandle.h
@@ -35,6 +35,7 @@
     BadBit     = 1L << 0, // error due to the inappropriate operation
     EOFBit     = 1L << 1, // reached End-Of-File
     FailBit    = 1L << 2, // internal logic fail
+    DeputedBit = 1L << 3, // the file descriptor is delegated
     IOStateEnd = 1L << 16
   };
 
@@ -120,14 +121,15 @@
 
   bool isFailed() const;
 
+  bool isOwned() const;
+
   bool isReadable() const;
 
   bool isWritable() const;
 
   bool isReadWrite() const;
 
-  int error() const
-  { return errno; }
+  int error() const { return errno; }
 
 private:
   sys::fs::Path m_Path;
diff --git a/include/mcld/Support/MemoryArea.h b/include/mcld/Support/MemoryArea.h
index a735f62..74297f3 100644
--- a/include/mcld/Support/MemoryArea.h
+++ b/include/mcld/Support/MemoryArea.h
@@ -110,7 +110,7 @@
     size_t m_Length;
   };
 
-  typedef std::map<Key, Space*, Key::Compare> SpaceMapType;
+  typedef std::multimap<Key, Space*, Key::Compare> SpaceMapType;
 
 private:
   SpaceMapType m_SpaceMap;
diff --git a/include/mcld/Support/PathCache.h b/include/mcld/Support/PathCache.h
index 89ec513..8da59e5 100644
--- a/include/mcld/Support/PathCache.h
+++ b/include/mcld/Support/PathCache.h
@@ -24,7 +24,7 @@
 
 namespace {
   typedef HashEntry<llvm::StringRef,
-                    mcld::sys::fs::Path*,
+                    mcld::sys::fs::Path,
                     StringCompare<llvm::StringRef> > HashEntryType;
 } // anonymous namespace
 
diff --git a/include/mcld/Target/ELFDynamic.h b/include/mcld/Target/ELFDynamic.h
index 7102226..62f534d 100644
--- a/include/mcld/Target/ELFDynamic.h
+++ b/include/mcld/Target/ELFDynamic.h
@@ -88,6 +88,43 @@
   Pair m_Pair;
 };
 
+template<>
+class Entry<64, true> : public EntryIF
+{
+public:
+  typedef llvm::ELF::Elf64_Dyn  Pair;
+  typedef llvm::ELF::Elf64_Sym  Symbol;
+  typedef llvm::ELF::Elf64_Rel  Rel;
+  typedef llvm::ELF::Elf64_Rela Rela;
+
+public:
+  inline Entry();
+
+  inline ~Entry();
+
+  Entry* clone() const
+  { return new Entry(); }
+
+  size_t size() const
+  { return sizeof(Pair); }
+
+  size_t symbolSize() const
+  { return sizeof(Symbol); }
+
+  size_t relSize() const
+  { return sizeof(Rel); }
+
+  size_t relaSize() const
+  { return sizeof(Rela); }
+
+  inline void setValue(uint64_t pTag, uint64_t pValue);
+
+  inline size_t emit(uint8_t* pAddress) const;
+
+private:
+  Pair m_Pair;
+};
+
 #include "ELFDynamic.tcc"
 
 } // namespace of elf_dynamic
diff --git a/include/mcld/Target/ELFDynamic.tcc b/include/mcld/Target/ELFDynamic.tcc
index 8b04651..5d67be4 100644
--- a/include/mcld/Target/ELFDynamic.tcc
+++ b/include/mcld/Target/ELFDynamic.tcc
@@ -7,6 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+//===----------------------------------------------------------------------===//
+/// 32-bit dynamic entry
 Entry<32, true>::Entry()
 {
   m_Pair.d_tag = 0;
@@ -31,3 +33,29 @@
   return sizeof(Pair);
 }
 
+//===----------------------------------------------------------------------===//
+/// 64-bit dynamic entry
+Entry<64, true>::Entry()
+{
+  m_Pair.d_tag = 0;
+  m_Pair.d_un.d_val = 0;
+}
+
+Entry<64, true>::~Entry()
+{
+}
+
+void Entry<64, true>::setValue(uint64_t pTag, uint64_t pValue)
+{
+  m_Pair.d_tag = pTag;
+  m_Pair.d_un.d_val = pValue;
+}
+
+size_t Entry<64, true>::emit(uint8_t* pAddress) const
+{
+  memcpy(reinterpret_cast<void*>(pAddress),
+         reinterpret_cast<const void*>(&m_Pair),
+         sizeof(Pair));
+  return sizeof(Pair);
+}
+
diff --git a/include/mcld/Target/GNUInfo.h b/include/mcld/Target/GNUInfo.h
index f918431..86a29ba 100644
--- a/include/mcld/Target/GNUInfo.h
+++ b/include/mcld/Target/GNUInfo.h
@@ -38,6 +38,33 @@
   /// ABIVersion - the value of e_ident[EI_ABIVRESION]
   uint8_t ABIVersion() const { return 0x0; }
 
+  /// defaultTextSegmentAddr - target should specify its own default start address
+  /// of the text segment. esp. for exec.
+  virtual uint64_t defaultTextSegmentAddr() const { return 0x0; }
+
+  /// flags - the value of ElfXX_Ehdr::e_flags
+  virtual uint64_t flags() const = 0;
+
+  /// entry - the symbol name of the entry point
+  virtual const char* entry() const { return "_start"; }
+
+  /// dyld - the name of the default dynamic linker
+  /// target may override this function if needed.
+  /// @ref gnu ld, bfd/elf32-i386.c:521
+  virtual const char* dyld() const { return "/usr/lib/libc.so.1"; }
+
+  /// isDefaultExecStack - target should specify whether the stack is default
+  /// executable. If target favors another choice, please override this function
+  virtual bool isDefaultExecStack() const { return true; }
+
+  /// commonPageSize - the common page size of the target machine, and we set it
+  /// to 4K here. If target favors the different size, please override this
+  virtual uint64_t commonPageSize() const { return 0x1000; }
+
+  /// abiPageSize - the abi page size of the target machine, and we set it to 4K
+  /// here. If target favors the different size, please override this function
+  virtual uint64_t abiPageSize() const { return 0x1000; }
+
 private:
   const llvm::Triple& m_Triple;
 };
diff --git a/include/mcld/Target/GNULDBackend.h b/include/mcld/Target/GNULDBackend.h
index d20b8ac..dfcbd85 100644
--- a/include/mcld/Target/GNULDBackend.h
+++ b/include/mcld/Target/GNULDBackend.h
@@ -23,10 +23,7 @@
 #include <mcld/LD/ELFObjectReader.h>
 #include <mcld/LD/ELFDynObjReader.h>
 #include <mcld/LD/ELFBinaryReader.h>
-#include <mcld/LD/ELFDynObjWriter.h>
-#include <mcld/LD/ELFExecWriter.h>
 #include <mcld/LD/ELFObjectWriter.h>
-#include <mcld/LD/ELFBinaryWriter.h>
 #include <mcld/LD/ELFSegment.h>
 #include <mcld/LD/ELFSegmentFactory.h>
 #include <mcld/Target/ELFDynamic.h>
@@ -41,7 +38,6 @@
 class LinkerConfig;
 class IRBuilder;
 class Layout;
-class EhFrame;
 class EhFrameHdr;
 class BranchIslandFactory;
 class StubFactory;
@@ -64,10 +60,7 @@
   ELFObjectReader* createObjectReader(IRBuilder& pBuilder);
   ELFDynObjReader* createDynObjReader(IRBuilder& pBuilder);
   ELFBinaryReader* createBinaryReader(IRBuilder& pBuilder);
-  ELFObjectWriter* createObjectWriter();
-  ELFDynObjWriter* createDynObjWriter();
-  ELFExecWriter*   createExecWriter();
-  ELFBinaryWriter* createBinaryWriter();
+  ELFObjectWriter* createWriter();
 
   // -----  output sections  ----- //
   /// initStdSections - initialize standard sections of the output file.
@@ -81,26 +74,26 @@
   /// initStandardSymbols - initialize standard symbols.
   /// Some section symbols is undefined in input object, and linkers must set
   /// up its value. Take __init_array_begin for example. This symbol is an
-  /// undefined symbol in input objects. FragmentLinker must finalize its value
+  /// undefined symbol in input objects. ObjectLinker must finalize its value
   /// to the begin of the .init_array section, then relocation enties to
   /// __init_array_begin can be applied without emission of "undefined
   /// reference to `__init_array_begin'".
-  bool initStandardSymbols(FragmentLinker& pLinker, Module& pModule);
+  bool initStandardSymbols(IRBuilder& pBuilder, Module& pModule);
 
   /// finalizeSymbol - Linker checks pSymbol.reserved() if it's not zero,
   /// then it will ask backend to finalize the symbol value.
   /// @return ture - if backend set the symbol value sucessfully
   /// @return false - if backend do not recognize the symbol
-  bool finalizeSymbols(FragmentLinker& pLinker) {
-    return (finalizeStandardSymbols(pLinker) &&
-            finalizeTargetSymbols(pLinker));
+  bool finalizeSymbols() {
+    return (finalizeStandardSymbols() &&
+            finalizeTargetSymbols());
   }
 
   /// finalizeStandardSymbols - set the value of standard symbols
-  virtual bool finalizeStandardSymbols(FragmentLinker& pLinker);
+  virtual bool finalizeStandardSymbols();
 
   /// finalizeTargetSymbols - set the value of target symbols
-  virtual bool finalizeTargetSymbols(FragmentLinker& pLinker) = 0;
+  virtual bool finalizeTargetSymbols() = 0;
 
   /// finalizeTLSSymbol - set the value of a TLS symbol
   virtual bool finalizeTLSSymbol(LDSymbol& pSymbol);
@@ -110,56 +103,41 @@
   const GNUInfo& getInfo() const { return *m_pInfo; }
   GNUInfo&       getInfo()       { return *m_pInfo; }
 
-  /// flags - the value of ElfXX_Ehdr::e_flags
-  virtual uint64_t flags() const = 0;
+  bool hasTextRel() const { return m_bHasTextRel; }
 
-  /// entry - the symbol name of the entry point
-  virtual const char* entry() const
-  { return "_start"; }
-
-  /// dyld - the name of the default dynamic linker
-  /// target may override this function if needed.
-  /// @ref gnu ld, bfd/elf32-i386.c:521
-  virtual const char* dyld() const
-  { return "/usr/lib/libc.so.1"; }
-
-  /// defaultTextSegmentAddr - target should specify its own default start address
-  /// of the text segment. esp. for exec.
-  virtual uint64_t defaultTextSegmentAddr() const
-  { return 0x0; }
-
-  bool hasTextRel() const
-  { return m_bHasTextRel; }
-
-  bool hasStaticTLS() const
-  { return m_bHasStaticTLS; }
+  bool hasStaticTLS() const { return m_bHasStaticTLS; }
 
   /// segmentStartAddr - this function returns the start address of the segment
-  uint64_t segmentStartAddr(const FragmentLinker& pLinker) const;
+  uint64_t segmentStartAddr() const;
 
   /// partialScanRelocation - When doing partial linking, fix the relocation
   /// offset after section merge
   void partialScanRelocation(Relocation& pReloc,
-                             FragmentLinker& pLinker,
                              Module& pModule,
                              const LDSection& pSection);
 
   /// sizeNamePools - compute the size of regular name pools
   /// In ELF executable files, regular name pools are .symtab, .strtab.,
   /// .dynsym, .dynstr, and .hash
-  virtual void sizeNamePools(const Module& pModule, bool pIsStaticLink);
+  virtual void sizeNamePools(Module& pModule, bool pIsStaticLink);
 
   /// emitSectionData - emit target-dependent section data
   virtual uint64_t emitSectionData(const LDSection& pSection,
                                    MemoryRegion& pRegion) const = 0;
 
   /// emitRegNamePools - emit regular name pools - .symtab, .strtab
-  virtual void emitRegNamePools(const Module& pModule,
-                                MemoryArea& pOutput);
+  virtual void emitRegNamePools(const Module& pModule, MemoryArea& pOutput);
 
   /// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
-  virtual void emitDynNamePools(const Module& pModule,
-                                MemoryArea& pOutput);
+  virtual void emitDynNamePools(Module& pModule, MemoryArea& pOutput);
+
+  /// emitELFHashTab - emit .hash
+  virtual void emitELFHashTab(const Module::SymbolTable& pSymtab,
+                              MemoryArea& pOutput);
+
+  /// emitGNUHashTab - emit .gnu.hash
+  virtual void emitGNUHashTab(Module::SymbolTable& pSymtab,
+                              MemoryArea& pOutput);
 
   /// sizeInterp - compute the size of program interpreter's name
   /// In ELF executables, this is the length of dynamic linker's path name
@@ -191,48 +169,44 @@
   /// numOfSegments - return the number of segments
   /// if the target favors other ways to emit program header, please override
   /// this function
-  virtual unsigned int numOfSegments() const
-  { return m_ELFSegmentTable.size(); }
+  size_t numOfSegments() const { return m_ELFSegmentTable.size(); }
 
   /// elfSegmentTable - return the reference of the elf segment table
-  ELFSegmentFactory& elfSegmentTable()
-  { return m_ELFSegmentTable; }
+  ELFSegmentFactory&       elfSegmentTable()       { return m_ELFSegmentTable; }
 
   /// elfSegmentTable - return the reference of the elf segment table
-  const ELFSegmentFactory& elfSegmentTable() const
-  { return m_ELFSegmentTable; }
+  const ELFSegmentFactory& elfSegmentTable() const { return m_ELFSegmentTable; }
 
-  /// commonPageSize - the common page size of the target machine, and we set it
-  /// to 4K here. If target favors the different size, please override this
-  /// function
-  virtual uint64_t commonPageSize() const;
+  /// commonPageSize - the common page size of the target machine
+  uint64_t commonPageSize() const;
 
-  /// abiPageSize - the abi page size of the target machine, and we set it to 4K
-  /// here. If target favors the different size, please override this function
-  virtual uint64_t abiPageSize() const;
+  /// abiPageSize - the abi page size of the target machine
+  uint64_t abiPageSize() const;
 
   /// getSymbolIdx - get the symbol index of ouput symbol table
-  size_t getSymbolIdx(LDSymbol* pSymbol) const;
-
-  /// isDefaultExecStack - target should specify whether the stack is default
-  /// executable. If target favors another choice, please override this function
-  virtual bool isDefaultExecStack() const
-  { return true; }
+  size_t getSymbolIdx(const LDSymbol* pSymbol) const;
 
   /// allocateCommonSymbols - allocate common symbols in the corresponding
   /// sections.
   /// Different concrete target backend may overlap this function.
   virtual bool allocateCommonSymbols(Module& pModule);
 
+  /// updateSectionFlags - update pTo's flags when merging pFrom
+  /// update the output section flags based on input section flags.
+  virtual bool updateSectionFlags(LDSection& pTo, const LDSection& pFrom);
+
   /// isSymbolPreemtible - whether the symbol can be preemted by other
   /// link unit
   /// @ref Google gold linker, symtab.h:551
   bool isSymbolPreemptible(const ResolveInfo& pSym) const;
 
+  virtual ResolveInfo::Desc getSymDesc(uint16_t pShndx) const {
+    return ResolveInfo::Define;
+  }
+
   /// symbolNeedsDynRel - return whether the symbol needs a dynamic relocation
   /// @ref Google gold linker, symtab.h:645
-  bool symbolNeedsDynRel(const FragmentLinker& pLinker,
-                         const ResolveInfo& pSym,
+  bool symbolNeedsDynRel(const ResolveInfo& pSym,
                          bool pSymHasPLT,
                          bool isAbsReloc) const;
 
@@ -270,10 +244,17 @@
 
   uint64_t getSymbolShndx(const LDSymbol& pSymbol) const;
 
+  /// isTemporary - Whether pSymbol is a local label.
+  virtual bool isTemporary(const LDSymbol& pSymbol) const;
+
   /// getHashBucketCount - calculate hash bucket count.
   /// @ref Google gold linker, dynobj.cc:791
   static unsigned getHashBucketCount(unsigned pNumOfSymbols, bool pIsGNUStyle);
 
+  /// getGNUHashMaskbitslog2 - calculate the number of mask bits in log2
+  /// @ref binutils gold, dynobj.cc:1165
+  unsigned getGNUHashMaskbitslog2(unsigned pNumOfSymbols) const;
+
   /// isDynamicSymbol
   /// @ref Google gold linker: symtab.cc:311
   bool isDynamicSymbol(const LDSymbol& pSymbol);
@@ -284,18 +265,15 @@
 
   /// symbolNeedsPLT - return whether the symbol needs a PLT entry
   /// @ref Google gold linker, symtab.h:596
-  bool symbolNeedsPLT(const FragmentLinker& pLinker,
-                      const ResolveInfo& pSym) const;
+  bool symbolNeedsPLT(const ResolveInfo& pSym) const;
 
   /// symbolNeedsCopyReloc - return whether the symbol needs a copy relocation
-  bool symbolNeedsCopyReloc(const FragmentLinker& pLinker,
-                            const Relocation& pReloc,
+  bool symbolNeedsCopyReloc(const Relocation& pReloc,
                             const ResolveInfo& pSym) const;
 
   /// symbolHasFinalValue - return true if the symbol's value can be decided at
   /// link time
-  bool symbolFinalValueIsKnown(const FragmentLinker& pLinker,
-                               const ResolveInfo& pSym) const;
+  bool symbolFinalValueIsKnown(const ResolveInfo& pSym) const;
 
   /// emitSymbol32 - emit an ELF32 symbol
   void emitSymbol32(llvm::ELF::Elf32_Sym& pSym32,
@@ -314,21 +292,19 @@
   /// checkAndSetHasTextRel - check pSection flag to set HasTextRel
   void checkAndSetHasTextRel(const LDSection& pSection);
 
-  void setHasStaticTLS(bool pVal = true)
-  { m_bHasStaticTLS = pVal; }
+  void setHasStaticTLS(bool pVal = true) { m_bHasStaticTLS = pVal; }
 
 private:
   /// createProgramHdrs - base on output sections to create the program headers
-  void createProgramHdrs(Module& pModule, const FragmentLinker& pLinker);
+  void createProgramHdrs(Module& pModule);
 
   /// doCreateProgramHdrs - backend can implement this function to create the
   /// target-dependent segments
-  virtual void doCreateProgramHdrs(Module& pModule,
-                                   const FragmentLinker& pLinker) = 0;
+  virtual void doCreateProgramHdrs(Module& pModule) = 0;
 
   /// setupProgramHdrs - set up the attributes of segments
   ///  (i.e., offset, addresses, file/mem size, flag,  and alignment)
-  void setupProgramHdrs(const FragmentLinker& pLinker);
+  void setupProgramHdrs();
 
   /// getSegmentFlag - give a section flag and return the corresponding segment
   /// flag
@@ -343,7 +319,7 @@
   }
 
   /// setupGNUStackInfo - setup the section flag of .note.GNU-stack in output
-  void setupGNUStackInfo(Module& pModule, FragmentLinker& pLinker);
+  void setupGNUStackInfo(Module& pModule);
 
   /// setupRelro - setup the offset constraint of PT_RELRO
   void setupRelro(Module& pModule);
@@ -356,28 +332,27 @@
                               uint64_t pStartOffset = -1U);
 
   /// setOutputSectionOffset - helper function to set output sections' address.
-  void setOutputSectionAddress(FragmentLinker& pLinker,
-                               Module& pModule,
+  void setOutputSectionAddress(Module& pModule,
                                Module::iterator pSectBegin,
                                Module::iterator pSectEnd);
 
   /// layout - layout method
-  void layout(Module& pModule, FragmentLinker& pLinker);
+  void layout(Module& pModule);
 
   /// preLayout - Backend can do any needed modification before layout
-  void preLayout(Module& pModule, FragmentLinker& pLinker);
+  void preLayout(Module& pModule, IRBuilder& pBuilder);
 
   /// postLayout -Backend can do any needed modification after layout
-  void postLayout(Module& pModule, FragmentLinker& pLinker);
+  void postLayout(Module& pModule, IRBuilder& pBuilder);
 
   /// preLayout - Backend can do any needed modification before layout
-  virtual void doPreLayout(FragmentLinker& pLinker) = 0;
+  virtual void doPreLayout(IRBuilder& pBuilder) = 0;
 
   /// postLayout -Backend can do any needed modification after layout
-  virtual void doPostLayout(Module& pModule, FragmentLinker& pLinker) = 0;
+  virtual void doPostLayout(Module& pModule, IRBuilder& pLinker) = 0;
 
   /// postProcessing - Backend can do any needed modification in the final stage
-  void postProcessing(FragmentLinker& pLinker, MemoryArea& pOutput);
+  void postProcessing(MemoryArea& pOutput);
 
   /// dynamic - the dynamic section of the target machine.
   virtual ELFDynamic& dynamic() = 0;
@@ -386,7 +361,7 @@
   virtual const ELFDynamic& dynamic() const = 0;
 
   /// relax - the relaxation pass
-  bool relax(Module& pModule, FragmentLinker& pLinker);
+  bool relax(Module& pModule, IRBuilder& pBuilder);
 
   /// mayRelax - Backends should override this function if they need relaxation
   virtual bool mayRelax() { return false; }
@@ -395,7 +370,7 @@
   /// implementation. Return true if the output (e.g., .text) is "relaxed"
   /// (i.e. layout is changed), and set pFinished to true if everything is fit,
   /// otherwise set it to false.
-  virtual bool doRelax(Module& pModule, FragmentLinker& pLinker, bool& pFinished)
+  virtual bool doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished)
   { return false; }
 
   /// getRelEntrySize - the size in BYTE of rel type relocation
@@ -450,6 +425,14 @@
     { return (X==Y); }
   };
 
+  // for gnu style hash table
+  struct DynsymCompare
+  {
+    bool needGNUHash(const LDSymbol& X) const;
+
+    bool operator()(const LDSymbol* X, const LDSymbol* Y) const;
+  };
+
   struct SymPtrHash
   {
     size_t operator()(const LDSymbol* pKey) const
@@ -488,9 +471,6 @@
   // map the LDSymbol to its index in the output symbol table
   HashTableType* m_pSymIndexMap;
 
-  /// m_pEhFrame - section .eh_frame
-  EhFrame* m_pEhFrame;
-
   // section .eh_frame_hdr
   EhFrameHdr* m_pEhFrameHdr;
 
diff --git a/include/mcld/Target/TargetLDBackend.h b/include/mcld/Target/TargetLDBackend.h
index 10cf280..1690004 100644
--- a/include/mcld/Target/TargetLDBackend.h
+++ b/include/mcld/Target/TargetLDBackend.h
@@ -16,7 +16,6 @@
 class Module;
 class LinkerConfig;
 class IRBuilder;
-class FragmentLinker;
 class Relocation;
 class RelocationFactory;
 class Relocator;
@@ -56,13 +55,13 @@
   virtual ~TargetLDBackend();
 
   // -----  target dependent  ----- //
-  virtual void initTargetSegments(FragmentLinker& pLinker) { }
+  virtual void initTargetSegments(IRBuilder& pBuilder) { }
   virtual void initTargetSections(Module& pModule, ObjectBuilder& pBuilder) { }
-  virtual void initTargetSymbols(FragmentLinker& pLinker) { }
-  virtual void initTargetRelocation(FragmentLinker& pLinker) { }
-  virtual bool initStandardSymbols(FragmentLinker& pLinker, Module& pModule) = 0;
+  virtual void initTargetSymbols(IRBuilder& pBuilder, Module& pModule) { }
+  virtual void initTargetRelocation(IRBuilder& pBuilder) { }
+  virtual bool initStandardSymbols(IRBuilder& pBuilder, Module& pModule) = 0;
 
-  virtual bool initRelocator(const FragmentLinker& pLinker) = 0;
+  virtual bool initRelocator() = 0;
 
   virtual Relocator* getRelocator() = 0;
 
@@ -74,9 +73,9 @@
   /// @param pInputSym - the input LDSymbol of relocation target symbol
   /// @param pSection - the section of relocation applying target
   virtual void scanRelocation(Relocation& pReloc,
-                              FragmentLinker& pLinker,
+                              IRBuilder& pBuilder,
                               Module& pModule,
-                              const LDSection& pSection) = 0;
+                              LDSection& pSection) = 0;
 
   /// partialScanRelocation - When doing partial linking, backend can do any
   /// modification to relocation to fix the relocation offset after section
@@ -85,7 +84,6 @@
   /// @param pInputSym - the input LDSymbol of relocation target symbol
   /// @param pSection - the section of relocation applying target
   virtual void partialScanRelocation(Relocation& pReloc,
-                                     FragmentLinker& pLinker,
                                      Module& pModule,
                                      const LDSection& pSection) = 0;
 
@@ -94,31 +92,21 @@
   virtual ObjectReader*  createObjectReader(IRBuilder&) = 0;
   virtual DynObjReader*  createDynObjReader(IRBuilder&) = 0;
   virtual BinaryReader*  createBinaryReader(IRBuilder&) = 0;
-  virtual ObjectWriter*  createObjectWriter() = 0;
-  virtual DynObjWriter*  createDynObjWriter() = 0;
-  virtual ExecWriter*    createExecWriter() = 0;
-  virtual BinaryWriter*  createBinaryWriter() = 0;
+  virtual ObjectWriter*  createWriter() = 0;
 
   virtual bool initStdSections(ObjectBuilder& pBuilder) = 0;
 
   /// layout - layout method
-  virtual void layout(Module& pModule, FragmentLinker& pLinker) = 0;
+  virtual void layout(Module& pModule) = 0;
 
   /// preLayout - Backend can do any needed modification before layout
-  virtual void preLayout(Module& pModule, FragmentLinker& pLinker) = 0;
+  virtual void preLayout(Module& pModule, IRBuilder& pBuilder) = 0;
 
-  /// postLayout -Backend can do any needed modification after layout
-  virtual void postLayout(Module& pModule, FragmentLinker& pLinker) = 0;
+  /// postLayout - Backend can do any needed modification after layout
+  virtual void postLayout(Module& pModule, IRBuilder& pBuilder) = 0;
 
   /// postProcessing - Backend can do any needed modification in the final stage
-  virtual void postProcessing(FragmentLinker& pLinker,
-                              MemoryArea& pOutput) = 0;
-
-  /// the common page size of the target machine
-  virtual uint64_t commonPageSize() const = 0;
-
-  /// the abi page size of the target machine
-  virtual uint64_t abiPageSize() const = 0;
+  virtual void postProcessing(MemoryArea& pOutput) = 0;
 
   /// section start offset in the output file
   virtual size_t sectionStartOffset() const = 0;
@@ -129,14 +117,13 @@
   /// sizeNamePools - compute the size of regular name pools
   /// In ELF executable files, regular name pools are .symtab, .strtab.,
   /// .dynsym, .dynstr, and .hash
-  virtual void
-  sizeNamePools(const Module& pModule, bool pIsStaticLink) = 0;
+  virtual void sizeNamePools(Module& pModule, bool pIsStaticLink) = 0;
 
   /// finalizeSymbol - Linker checks pSymbol.reserved() if it's not zero,
   /// then it will ask backend to finalize the symbol value.
   /// @return ture - if backend set the symbol value sucessfully
   /// @return false - if backend do not recognize the symbol
-  virtual bool finalizeSymbols(FragmentLinker& pLinker) = 0;
+  virtual bool finalizeSymbols() = 0;
 
   /// finalizeTLSSymbol - Linker asks backend to set the symbol value when it
   /// meets a TLS symbol
@@ -150,13 +137,17 @@
   virtual bool mergeSection(Module& pModule, LDSection& pInputSection)
   { return true; }
 
+  /// updateSectionFlags - update pTo's flags when merging pFrom
+  /// update the output section flags based on input section flags.
+  /// FIXME: (Luba) I know ELF need to merge flags, but I'm not sure if
+  /// MachO and COFF also need this.
+  virtual bool updateSectionFlags(LDSection& pTo, const LDSection& pFrom)
+  { return true; }
+
   /// readSection - read a target dependent section
   virtual bool readSection(Input& pInput, SectionData& pSD)
   { return true; }
 
-  /// dyld - the name of the default dynamic linker
-  virtual const char* dyld() const = 0;
-
   /// sizeInterp - compute the size of program interpreter's name
   /// In ELF executables, this is the length of dynamic linker's path name
   virtual void sizeInterp() = 0;
@@ -164,13 +155,13 @@
   // -----  relaxation  ----- //
   virtual bool initBRIslandFactory() = 0;
   virtual bool initStubFactory() = 0;
-  virtual bool initTargetStubs(FragmentLinker& pLinker) { return true; }
+  virtual bool initTargetStubs() { return true; }
 
   virtual BranchIslandFactory* getBRIslandFactory() = 0;
   virtual StubFactory*         getStubFactory() = 0;
 
   /// relax - the relaxation pass
-  virtual bool relax(Module& pModule, FragmentLinker& pLinker) = 0;
+  virtual bool relax(Module& pModule, IRBuilder& pBuilder) = 0;
 
   /// mayRelax - return true if the backend needs to do relaxation
   virtual bool mayRelax() = 0;
diff --git a/lib/CodeGen/MCLDTargetMachine.cpp b/lib/CodeGen/MCLDTargetMachine.cpp
index 785ef1f..57da5b5 100644
--- a/lib/CodeGen/MCLDTargetMachine.cpp
+++ b/lib/CodeGen/MCLDTargetMachine.cpp
@@ -214,8 +214,6 @@
                           pOutput.formatted_os(),
                           Context))
       return true;
-
-    pPM.add(createGCInfoDeleter()); // not in addPassesToMC
     break;
   }
   case CGFT_OBJFile: {
@@ -227,8 +225,6 @@
                            pOutput.mem_os(),
                            Context))
       return true;
-
-    pPM.add(createGCInfoDeleter()); // not in addPassesToMC
     break;
   }
   case CGFT_EXEFile: {
diff --git a/lib/CodeGen/MCLinker.cpp b/lib/CodeGen/MCLinker.cpp
index 6b7196b..3613a03 100644
--- a/lib/CodeGen/MCLinker.cpp
+++ b/lib/CodeGen/MCLinker.cpp
@@ -382,6 +382,7 @@
   std::vector<InputAction*>::iterator action, actionEnd = actions.end();
   for (action = actions.begin(); action != actionEnd; ++action) {
     (*action)->activate(pBuilder.getInputBuilder());
+    delete *action;
   }
 
   if (pBuilder.getInputBuilder().isInGroup())
diff --git a/lib/Core/GeneralOptions.cpp b/lib/Core/GeneralOptions.cpp
index d762237..f29ab1d 100644
--- a/lib/Core/GeneralOptions.cpp
+++ b/lib/Core/GeneralOptions.cpp
@@ -41,7 +41,6 @@
     m_Bgroup(false),
     m_bPIE(false),
     m_bColor(true),
-    m_bAllowShlibUndefined(true),
     m_bCreateEhFrameHdr(false),
     m_bNMagic(false),
     m_bOMagic(false),
@@ -50,8 +49,11 @@
     m_bWarnSharedTextrel(false),
     m_bBinaryInput(false),
     m_bDefineCommon(false),
-    m_bFatalWarnings(false)
-{
+    m_bFatalWarnings(false),
+    m_bNewDTags(false),
+    m_bNoStdlib(false),
+    m_StripSymbols(KeepAllSymbols),
+    m_HashStyle(SystemV) {
 }
 
 GeneralOptions::~GeneralOptions()
@@ -82,6 +84,11 @@
   m_SearchDirs.setSysRoot(pSysroot);
 }
 
+bool GeneralOptions::hasSysroot() const
+{
+  return !sysroot().empty();
+}
+
 void GeneralOptions::setSOName(const std::string& pName)
 {
   size_t pos = pName.find_last_of(sys::fs::separator);
diff --git a/lib/Core/IRBuilder.cpp b/lib/Core/IRBuilder.cpp
index 5472db0..549aa8d 100644
--- a/lib/Core/IRBuilder.cpp
+++ b/lib/Core/IRBuilder.cpp
@@ -83,7 +83,7 @@
   return LDFileFormat::MetaData;
 }
 
-bool shouldForceLocal(const ResolveInfo& pInfo, const LinkerConfig& pConfig)
+bool ShouldForceLocal(const ResolveInfo& pInfo, const LinkerConfig& pConfig)
 {
   // forced local symbol matches all rules:
   // 1. We are not doing incremental linking.
@@ -333,7 +333,7 @@
 {
   assert(!pSection.hasEhFrame() && "pSection already has eh_frame.");
 
-  EhFrame* eh_frame = new EhFrame(pSection);
+  EhFrame* eh_frame = EhFrame::Create(pSection);
   pSection.setEhFrame(eh_frame);
   return eh_frame;
 }
@@ -471,13 +471,14 @@
       return input_sym;
     }
     case Input::DynObj: {
-      return addSymbolFromDynObj(name, pType, pDesc, pBind, pSize, pValue, pVis);
+      return addSymbolFromDynObj(pInput, name, pType, pDesc, pBind, pSize, pValue, pVis);
     }
     default: {
       return NULL;
       break;
     }
   }
+  return NULL;
 }
 
 LDSymbol* IRBuilder::addSymbolFromObject(const std::string& pName,
@@ -564,7 +565,7 @@
 
       // No matter the symbol is already in the output or not, add it if it
       // should be forcefully set local.
-      if (shouldForceLocal(*resolved_result.info, m_Config))
+      if (ShouldForceLocal(*resolved_result.info, m_Config))
         m_Module.getSymbolTable().forceLocal(*output_sym);
       else {
         // the symbol should not be forcefully local.
@@ -572,8 +573,8 @@
       }
     }
     else if (resolved_result.overriden) {
-      if (!shouldForceLocal(old_info, m_Config) ||
-          !shouldForceLocal(*resolved_result.info, m_Config)) {
+      if (!ShouldForceLocal(old_info, m_Config) ||
+          !ShouldForceLocal(*resolved_result.info, m_Config)) {
         // If the old info and the new info are both forcefully local, then
         // we should keep the output_sym in forcefully local category. Else,
         // we should re-sort the output_sym
@@ -585,7 +586,8 @@
   return input_sym;
 }
 
-LDSymbol* IRBuilder::addSymbolFromDynObj(const std::string& pName,
+LDSymbol* IRBuilder::addSymbolFromDynObj(Input& pInput,
+                                         const std::string& pName,
                                          ResolveInfo::Type pType,
                                          ResolveInfo::Desc pDesc,
                                          ResolveInfo::Binding pBinding,
@@ -619,6 +621,9 @@
   // the return ResolveInfo should not NULL
   assert(NULL != resolved_result.info);
 
+  if (resolved_result.overriden || !resolved_result.existent)
+    pInput.setNeeded();
+
   // create a LDSymbol for the input file.
   LDSymbol* input_sym = LDSymbol::Create(*resolved_result.info);
   input_sym->setFragmentRef(FragmentRef::Null());
@@ -638,7 +643,7 @@
     // After symbol resolution, visibility is changed to the most restrict one.
     // If we are not doing incremental linking, then any symbol with hidden
     // or internal visibility is forcefully set as a local symbol.
-    if (shouldForceLocal(*resolved_result.info, m_Config)) {
+    if (ShouldForceLocal(*resolved_result.info, m_Config)) {
       m_Module.getSymbolTable().forceLocal(*output_sym);
     }
   }
@@ -674,3 +679,190 @@
   return relocation;
 }
 
+/// AddSymbol - define an output symbol and override it immediately
+template<> LDSymbol*
+IRBuilder::AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
+                                           const llvm::StringRef& pName,
+                                           ResolveInfo::Type pType,
+                                           ResolveInfo::Desc pDesc,
+                                           ResolveInfo::Binding pBinding,
+                                           ResolveInfo::SizeType pSize,
+                                           LDSymbol::ValueType pValue,
+                                           FragmentRef* pFragmentRef,
+                                           ResolveInfo::Visibility pVisibility)
+{
+  ResolveInfo* info = m_Module.getNamePool().findInfo(pName);
+  LDSymbol* output_sym = NULL;
+  if (NULL == info) {
+    // the symbol is not in the pool, create a new one.
+    // create a ResolveInfo
+    Resolver::Result result;
+    m_Module.getNamePool().insertSymbol(pName, false, pType, pDesc,
+                                        pBinding, pSize, pVisibility,
+                                        NULL, result);
+    assert(!result.existent);
+
+    // create a output LDSymbol
+    output_sym = LDSymbol::Create(*result.info);
+    result.info->setSymPtr(output_sym);
+
+    if (ShouldForceLocal(*result.info, m_Config))
+      m_Module.getSymbolTable().forceLocal(*output_sym);
+    else
+      m_Module.getSymbolTable().add(*output_sym);
+  }
+  else {
+    // the symbol is already in the pool, override it
+    ResolveInfo old_info;
+    old_info.override(*info);
+
+    info->setRegular();
+    info->setType(pType);
+    info->setDesc(pDesc);
+    info->setBinding(pBinding);
+    info->setVisibility(pVisibility);
+    info->setIsSymbol(true);
+    info->setSize(pSize);
+
+    output_sym = info->outSymbol();
+    if (NULL != output_sym)
+      m_Module.getSymbolTable().arrange(*output_sym, old_info);
+    else {
+      // create a output LDSymbol
+      output_sym = LDSymbol::Create(*info);
+      info->setSymPtr(output_sym);
+
+      m_Module.getSymbolTable().add(*output_sym);
+    }
+  }
+
+  if (NULL != output_sym) {
+    output_sym->setFragmentRef(pFragmentRef);
+    output_sym->setValue(pValue);
+  }
+
+  return output_sym;
+}
+
+/// AddSymbol - define an output symbol and override it immediately
+template<> LDSymbol*
+IRBuilder::AddSymbol<IRBuilder::AsReferred, IRBuilder::Unresolve>(
+                                           const llvm::StringRef& pName,
+                                           ResolveInfo::Type pType,
+                                           ResolveInfo::Desc pDesc,
+                                           ResolveInfo::Binding pBinding,
+                                           ResolveInfo::SizeType pSize,
+                                           LDSymbol::ValueType pValue,
+                                           FragmentRef* pFragmentRef,
+                                           ResolveInfo::Visibility pVisibility)
+{
+  ResolveInfo* info = m_Module.getNamePool().findInfo(pName);
+
+  if (NULL == info || !(info->isUndef() || info->isDyn())) {
+    // only undefined symbol and dynamic symbol can make a reference.
+    return NULL;
+  }
+
+  // the symbol is already in the pool, override it
+  ResolveInfo old_info;
+  old_info.override(*info);
+
+  info->setRegular();
+  info->setType(pType);
+  info->setDesc(pDesc);
+  info->setBinding(pBinding);
+  info->setVisibility(pVisibility);
+  info->setIsSymbol(true);
+  info->setSize(pSize);
+
+  LDSymbol* output_sym = info->outSymbol();
+  if (NULL != output_sym) {
+    output_sym->setFragmentRef(pFragmentRef);
+    output_sym->setValue(pValue);
+    m_Module.getSymbolTable().arrange(*output_sym, old_info);
+  }
+  else {
+    // create a output LDSymbol
+    output_sym = LDSymbol::Create(*info);
+    info->setSymPtr(output_sym);
+
+    m_Module.getSymbolTable().add(*output_sym);
+  }
+
+  return output_sym;
+}
+
+/// AddSymbol - define an output symbol and resolve it
+/// immediately
+template<> LDSymbol*
+IRBuilder::AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
+                                             const llvm::StringRef& pName,
+                                             ResolveInfo::Type pType,
+                                             ResolveInfo::Desc pDesc,
+                                             ResolveInfo::Binding pBinding,
+                                             ResolveInfo::SizeType pSize,
+                                             LDSymbol::ValueType pValue,
+                                             FragmentRef* pFragmentRef,
+                                             ResolveInfo::Visibility pVisibility)
+{
+  // Result is <info, existent, override>
+  Resolver::Result result;
+  ResolveInfo old_info;
+  m_Module.getNamePool().insertSymbol(pName, false, pType, pDesc, pBinding,
+                                      pSize, pVisibility,
+                                      &old_info, result);
+
+  LDSymbol* output_sym = result.info->outSymbol();
+  bool has_output_sym = (NULL != output_sym);
+
+  if (!result.existent || !has_output_sym) {
+    output_sym = LDSymbol::Create(*result.info);
+    result.info->setSymPtr(output_sym);
+  }
+
+  if (result.overriden || !has_output_sym) {
+    output_sym->setFragmentRef(pFragmentRef);
+    output_sym->setValue(pValue);
+  }
+
+  // After symbol resolution, the visibility is changed to the most restrict.
+  // arrange the output position
+  if (ShouldForceLocal(*result.info, m_Config))
+    m_Module.getSymbolTable().forceLocal(*output_sym);
+  else if (has_output_sym)
+    m_Module.getSymbolTable().arrange(*output_sym, old_info);
+  else
+    m_Module.getSymbolTable().add(*output_sym);
+
+  return output_sym;
+}
+
+/// defineSymbol - define an output symbol and resolve it immediately.
+template<> LDSymbol*
+IRBuilder::AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                            const llvm::StringRef& pName,
+                                            ResolveInfo::Type pType,
+                                            ResolveInfo::Desc pDesc,
+                                            ResolveInfo::Binding pBinding,
+                                            ResolveInfo::SizeType pSize,
+                                            LDSymbol::ValueType pValue,
+                                            FragmentRef* pFragmentRef,
+                                            ResolveInfo::Visibility pVisibility)
+{
+  ResolveInfo* info = m_Module.getNamePool().findInfo(pName);
+
+  if (NULL == info || !(info->isUndef() || info->isDyn())) {
+    // only undefined symbol and dynamic symbol can make a reference.
+    return NULL;
+  }
+
+  return AddSymbol<Force, Resolve>(pName,
+                                   pType,
+                                   pDesc,
+                                   pBinding,
+                                   pSize,
+                                   pValue,
+                                   pFragmentRef,
+                                   pVisibility);
+}
+
diff --git a/lib/Core/Linker.cpp b/lib/Core/Linker.cpp
index 9f6449e..d0c9b2e 100644
--- a/lib/Core/Linker.cpp
+++ b/lib/Core/Linker.cpp
@@ -32,7 +32,7 @@
 using namespace mcld;
 
 Linker::Linker()
-  : m_pConfig(NULL), m_pModule(NULL), m_pIRBuilder(NULL),
+  : m_pConfig(NULL), m_pIRBuilder(NULL),
     m_pTarget(NULL), m_pBackend(NULL), m_pObjLinker(NULL) {
 }
 
@@ -51,6 +51,9 @@
   if (!initBackend())
     return false;
 
+  m_pObjLinker = new ObjectLinker(*m_pConfig,
+                                  *m_pBackend);
+
   if (!initEmulator())
     return false;
 
@@ -62,13 +65,19 @@
 
 bool Linker::link(Module& pModule, IRBuilder& pBuilder)
 {
+  if (!resolve(pModule, pBuilder))
+    return false;
+
+  return layout();
+}
+
+bool Linker::resolve(Module& pModule, IRBuilder& pBuilder)
+{
   assert(NULL != m_pConfig);
 
   m_pIRBuilder = &pBuilder;
-  m_pObjLinker = new ObjectLinker(*m_pConfig,
-                                  pModule,
-                                  *m_pIRBuilder,
-                                  *m_pBackend);
+  assert(m_pObjLinker!=NULL);
+  m_pObjLinker->setup(pModule, pBuilder);
 
   // 2. - initialize FragmentLinker
   if (!m_pObjLinker->initFragmentLinker())
@@ -78,7 +87,13 @@
   if (!m_pObjLinker->initStdSections())
     return false;
 
+  if (!Diagnose())
+    return false;
+
   // 4. - normalize the input tree
+  //   read out sections and symbol/string tables (from the files) and
+  //   set them in Module. When reading out the symbol, resolve their symbols
+  //   immediately and set their ResolveInfo (i.e., Symbol Resolution).
   m_pObjLinker->normalize();
 
   if (m_pConfig->options().trace()) {
@@ -112,39 +127,80 @@
     }
   }
 
-  // 5. - check if we can do static linking and if we use split-stack.
+  // 5. - set up code position
+  if (LinkerConfig::DynObj == m_pConfig->codeGenType() ||
+      m_pConfig->options().isPIE()) {
+    m_pConfig->setCodePosition(LinkerConfig::Independent);
+  }
+  else if (pModule.getLibraryList().empty()) {
+    // If the output is dependent on its loaded address, and it does not need
+    // to call outside functions, then we can treat the output static dependent
+    // and perform better optimizations.
+    m_pConfig->setCodePosition(LinkerConfig::StaticDependent);
+  }
+  else {
+    m_pConfig->setCodePosition(LinkerConfig::DynamicDependent);
+  }
+
   if (!m_pObjLinker->linkable())
     return Diagnose();
 
   // 6. - read all relocation entries from input files
+  //   For all relocation sections of each input file (in the tree),
+  //   read out reloc entry info from the object file and accordingly
+  //   initiate their reloc entries in SectOrRelocData of LDSection.
   m_pObjLinker->readRelocations();
 
   // 7. - merge all sections
+  //   Push sections into Module's SectionTable.
+  //   Merge sections that have the same name.
+  //   Maintain them as fragments in the section.
   if (!m_pObjLinker->mergeSections())
     return false;
 
-  // 8. - add standard symbols and target-dependent symbols
+  // 8. - allocateCommonSymbols
+  //   Allocate fragments for common symbols to the corresponding sections.
+  if (!m_pObjLinker->allocateCommonSymbols())
+    return false;
+  return true;
+}
+
+bool Linker::layout()
+{
+  assert(NULL != m_pConfig && NULL != m_pObjLinker);
+
+  // 9. - add standard symbols, target-dependent symbols and script symbols
   // m_pObjLinker->addUndefSymbols();
   if (!m_pObjLinker->addStandardSymbols() ||
-      !m_pObjLinker->addTargetSymbols())
+      !m_pObjLinker->addTargetSymbols() ||
+      !m_pObjLinker->addScriptSymbols())
     return false;
 
-  // 9. - scan all relocation entries by output symbols.
+  // 10. - scan all relocation entries by output symbols.
+  //   reserve GOT space for layout.
+  //   the space info is needed by pre-layout to compute the section size
   m_pObjLinker->scanRelocations();
 
-  // 10.a - pre-layout
+  // 11.a - init relaxation stuff.
+  m_pObjLinker->initStubs();
+
+  // 11.b - pre-layout
   m_pObjLinker->prelayout();
 
-  // 10.b - linear layout
+  // 11.c - linear layout
+  //   Decide which sections will be left in. Sort the sections according to
+  //   a given order. Then, create program header accordingly.
+  //   Finally, set the offset for sections (@ref LDSection)
+  //   according to the new order.
   m_pObjLinker->layout();
 
-  // 10.c - post-layout (create segment, instruction relaxing)
+  // 11.d - post-layout (create segment, instruction relaxing)
   m_pObjLinker->postlayout();
 
-  // 11. - finalize symbol value
+  // 12. - finalize symbol value
   m_pObjLinker->finalizeSymbolValue();
 
-  // 12. - apply relocations
+  // 13. - apply relocations
   m_pObjLinker->relocation();
 
   if (!Diagnose())
@@ -202,7 +258,6 @@
 bool Linker::reset()
 {
   m_pConfig = NULL;
-  m_pModule = NULL;
   m_pIRBuilder = NULL;
   m_pTarget = NULL;
 
@@ -210,6 +265,7 @@
   // RelocData before deleting target backend.
   RelocData::Clear();
   SectionData::Clear();
+  EhFrame::Clear();
 
   delete m_pBackend;
   m_pBackend = NULL;
diff --git a/lib/Core/LinkerConfig.cpp b/lib/Core/LinkerConfig.cpp
index cbdb7a7..63609fa 100644
--- a/lib/Core/LinkerConfig.cpp
+++ b/lib/Core/LinkerConfig.cpp
@@ -22,7 +22,8 @@
     m_Targets(),
     m_Bitcode(),
     m_Attribute(),
-    m_CodeGenType(Unknown)
+    m_CodeGenType(Unknown),
+    m_CodePosition(DynamicDependent)
 {
   // FIXME: is here the right place to hold this?
   InitializeDiagnosticEngine(*this);
@@ -34,7 +35,8 @@
     m_Targets(pTripleString),
     m_Bitcode(),
     m_Attribute(),
-    m_CodeGenType(Unknown)
+    m_CodeGenType(Unknown),
+    m_CodePosition(DynamicDependent)
 {
   // FIXME: is here the right place to hold this?
   InitializeDiagnosticEngine(*this);
diff --git a/lib/Fragment/Android.mk b/lib/Fragment/Android.mk
index 0da2051..6e875a8 100644
--- a/lib/Fragment/Android.mk
+++ b/lib/Fragment/Android.mk
@@ -2,6 +2,7 @@
 
 mcld_fragment_SRC_FILES := \
   AlignFragment.cpp \
+  FGNode.cpp \
   FillFragment.cpp \
   Fragment.cpp \
   FragmentLinker.cpp \
diff --git a/lib/Fragment/FGNode.cpp b/lib/Fragment/FGNode.cpp
new file mode 100644
index 0000000..92706ba
--- /dev/null
+++ b/lib/Fragment/FGNode.cpp
@@ -0,0 +1,40 @@
+//===- FGNode.cpp ---------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Fragment/FGNode.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// FGNode
+//===----------------------------------------------------------------------===//
+FGNode::FGNode()
+  : m_Index(0x0)
+{
+}
+
+FGNode::FGNode(uint32_t pIndex)
+  : m_Index(pIndex)
+{
+}
+
+void FGNode::addFragment(Fragment* pFrag)
+{
+  m_Fragments.push_back(pFrag);
+}
+
+void FGNode::addSignal(Signal pSignal)
+{
+  m_Signals.push_back(pSignal);
+}
+
+void FGNode::addSlot(Slot pSlot)
+{
+  m_Slots.push_back(pSlot);
+}
+
diff --git a/lib/Fragment/FragmentGraph.cpp b/lib/Fragment/FragmentGraph.cpp
new file mode 100644
index 0000000..3140447
--- /dev/null
+++ b/lib/Fragment/FragmentGraph.cpp
@@ -0,0 +1,412 @@
+//===- FragmentGraph.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Fragment/FragmentGraph.h>
+#include <mcld/Fragment/Fragment.h>
+#include <mcld/Fragment/Relocation.h>
+#include <mcld/LD/LDContext.h>
+#include <mcld/LD/LDFileFormat.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/LD/RelocData.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/Module.h>
+#include <mcld/Support/MsgHandling.h>
+
+#include <llvm/Support/Casting.h>
+#include <llvm/Support/ELF.h>
+
+#include <iostream>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// non-member functions
+//===----------------------------------------------------------------------===//
+static int get_state(Fragment::Type pKind)
+{
+  switch(pKind) {
+    case Fragment::Alignment:
+      return 0;
+    case Fragment::Fillment:
+    case Fragment::Region:
+      return 1;
+    case Fragment::Null:
+      return 2;
+    default:
+      unreachable(diag::unexpected_frag_type) << pKind;
+  }
+  return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// ReachMatrix
+//===----------------------------------------------------------------------===//
+FragmentGraph::ReachMatrix::ReachMatrix(size_t pSize)
+{
+  assert(pSize != 0);
+  m_Data.assign(pSize * pSize, 0x0);
+  m_N = pSize;
+}
+
+uint32_t& FragmentGraph::ReachMatrix::at(uint32_t pX, uint32_t pY)
+{
+  return m_Data[pX * m_N + pY];
+}
+
+uint32_t FragmentGraph::ReachMatrix::at(uint32_t pX, uint32_t pY) const
+{
+  return m_Data[pX * m_N + pY];
+}
+
+//===----------------------------------------------------------------------===//
+// FragmentGraph
+//===----------------------------------------------------------------------===//
+FragmentGraph::FragmentGraph()
+ : m_pMatrix(NULL), m_NumOfPNodes(0x0), m_NumOfRNodes(0x0), m_NumOfEdges(0x0)
+{
+  m_pPseudoNodeFactory = new NodeFactoryType();
+  m_pRegularNodeFactory = new NodeFactoryType();
+  m_pFragNodeMap = new FragHashTableType(256);
+  m_pSymNodeMap = new SymHashTableType(256);
+}
+
+FragmentGraph::~FragmentGraph()
+{
+  delete m_pPseudoNodeFactory;
+  delete m_pRegularNodeFactory;
+  delete m_pFragNodeMap;
+}
+
+FGNode* FragmentGraph::getNode(const Fragment& pFrag)
+{
+  FragHashTableType::iterator entry = m_pFragNodeMap->find(&pFrag);
+  if (entry == m_pFragNodeMap->end())
+    return NULL;
+  return entry.getEntry()->value();
+}
+
+const FGNode* FragmentGraph::getNode(const Fragment& pFrag) const
+{
+  FragHashTableType::iterator entry = m_pFragNodeMap->find(&pFrag);
+  if (entry == m_pFragNodeMap->end())
+    return NULL;
+  return entry.getEntry()->value();
+}
+
+FGNode* FragmentGraph::getNode(const ResolveInfo& pSym)
+{
+  SymHashTableType::iterator entry = m_pSymNodeMap->find(&pSym);
+  if (entry == m_pSymNodeMap->end())
+    return NULL;
+  return entry.getEntry()->value();
+}
+
+const FGNode* FragmentGraph::getNode(const ResolveInfo& pSym) const
+{
+  SymHashTableType::iterator entry = m_pSymNodeMap->find(&pSym);
+  if (entry == m_pSymNodeMap->end())
+    return NULL;
+  return entry.getEntry()->value();
+}
+
+FGNode* FragmentGraph::producePseudoNode()
+{
+  FGNode* result = m_pPseudoNodeFactory->allocate();
+  new (result) FGNode(m_NumOfPNodes + m_NumOfRNodes);
+  ++m_NumOfPNodes;
+  return result;
+}
+
+FGNode* FragmentGraph::produceRegularNode()
+{
+  FGNode* result = m_pRegularNodeFactory->allocate();
+  new (result) FGNode(m_NumOfPNodes + m_NumOfRNodes);
+  ++m_NumOfRNodes;
+  return result;
+}
+
+bool FragmentGraph::setNodeSlots(Module& pModule)
+{
+  // symbols are the slots of nodes, push the symbols into the corresponding
+  // nodes.
+
+  // Traverse all defined symbols, including global and local symbols, to add
+  // symbols into the corresponding nodes
+  Module::SymbolTable& sym_tab = pModule.getSymbolTable();
+  SymbolCategory::iterator sym_it, sym_end = sym_tab.end();
+  for (sym_it = sym_tab.begin(); sym_it != sym_end; ++sym_it) {
+    // only the defined symbols with FragmnentRef can form a slot. The defined
+    // symbol with no FragmentRef such as ABS symbol should be skipped
+    LDSymbol* sym = *sym_it;
+    if (!sym->resolveInfo()->isDefine() ||
+        !sym->hasFragRef())
+      continue;
+
+    // FIXME: judge by getNode() is NULL or not
+    LDFileFormat::Kind sect_kind =
+                       sym->fragRef()->frag()->getParent()->getSection().kind();
+    if (sect_kind != LDFileFormat::Regular &&
+        sect_kind != LDFileFormat::BSS)
+      continue;
+
+    FGNode* node = getNode(*sym->fragRef()->frag());
+    assert(NULL != node);
+    node->addSlot(sym->resolveInfo());
+  }
+
+  return true;
+}
+
+bool FragmentGraph::createRegularEdges(Module& pModule)
+{
+  // The reference between nodes are presented by the relocations. Set the
+  // reachability matrix to present the connection
+
+  // Traverse all input relocations to set connection
+  Module::obj_iterator input, inEnd = pModule.obj_end();
+  for (input = pModule.obj_begin(); input != inEnd; ++input) {
+    LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
+    for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
+      // bypass the discarded relocations
+      // 1. its section kind is changed to Ignore. (The target section is a
+      // discarded group section.)
+      // 2. it has no reloc data. (All symbols in the input relocs are in the
+      // discarded group sections)
+      if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
+        continue;
+      RelocData::iterator reloc_it, rEnd = (*rs)->getRelocData()->end();
+      for (reloc_it = (*rs)->getRelocData()->begin(); reloc_it != rEnd;
+                                                                   ++reloc_it) {
+        Relocation* reloc = llvm::cast<Relocation>(reloc_it);
+        ResolveInfo* sym = reloc->symInfo();
+        // only the target symbols defined in the input fragments can make the
+        // connection
+        if (NULL == sym)
+          continue;
+        if (!sym->isDefine() || !sym->outSymbol()->hasFragRef())
+          continue;
+
+        // only the relocation target places which defined in the concerned
+        // sections can make the connection
+        // FIXME: judge by getNode() is NULL or not
+        LDFileFormat::Kind sect_kind =
+                   reloc->targetRef().frag()->getParent()->getSection().kind();
+        if (sect_kind != LDFileFormat::Regular &&
+            sect_kind != LDFileFormat::BSS)
+          continue;
+
+        // only the target symbols defined in the concerned sections can make
+        // the connection
+        // FIXME: judge by getNode() is NULL or not
+        sect_kind =
+          sym->outSymbol()->fragRef()->frag()->getParent()->getSection().kind();
+        if (sect_kind != LDFileFormat::Regular &&
+            sect_kind != LDFileFormat::BSS)
+          continue;
+
+        connect(reloc, sym);
+      }
+    }
+  }
+  return true;
+}
+
+bool FragmentGraph::createPseudoEdges(Module& pModule)
+{
+  // the pseudo edges are the edges from pseudo nodes to regular nodes, which
+  // present the reference from out-side world when building shared library
+
+  // Traverse all pseudo relocations in the pseudo nodes to set the connection
+  node_iterator node_it, node_end = m_pPseudoNodeFactory->end();
+  for (node_it = m_pPseudoNodeFactory->begin(); node_it != node_end; ++node_it) {
+    FGNode& node = *node_it;
+    FGNode::signal_iterator sig_it, sig_end = node.signal_end();
+    for (sig_it = node.signal_begin(); sig_it != sig_end; ++sig_it) {
+      connect(node, (*sig_it)->symInfo());
+    }
+  }
+  return true;
+}
+
+bool FragmentGraph::connect(Signal pSignal, Slot pSlot)
+{
+  FGNode* from = getNode(*pSignal->targetRef().frag());
+  assert(NULL != from);
+
+  FGNode* to = getNode(*pSlot->outSymbol()->fragRef()->frag());
+  assert(NULL != to);
+
+  // maintain edge counter
+  if (0 == m_pMatrix->at(from->getIndex(), to->getIndex()))
+    ++m_NumOfEdges;
+  ++m_pMatrix->at(from->getIndex(), to->getIndex());
+  return true;
+}
+
+bool FragmentGraph::connect(FGNode& pFrom, Slot pSlot)
+{
+  FGNode* to = getNode(*pSlot->outSymbol()->fragRef()->frag());
+  assert(NULL != to);
+
+  // maintain edge counter
+  if (0 == m_pMatrix->at(pFrom.getIndex(), to->getIndex()))
+    ++m_NumOfEdges;
+  ++m_pMatrix->at(pFrom.getIndex(), to->getIndex());
+  return true;
+}
+
+bool FragmentGraph::createPseudoNodes(Module& pModule)
+{
+  // when generating shared library, we need to create pseudo node for every
+  // global defined symbols to present the fan-in of a regular node.
+
+  // Traverse all global defined symbols to build the pseudo nodes.
+  Module::SymbolTable& sym_tab = pModule.getSymbolTable();
+  SymbolCategory::iterator sym_it, sym_end = sym_tab.dynamicEnd();
+  for (sym_it = sym_tab.dynamicBegin(); sym_it != sym_end; ++sym_it) {
+    ResolveInfo* sym = (*sym_it)->resolveInfo();
+    if (!sym->isDefine() || !sym->outSymbol()->hasFragRef())
+      continue;
+    FGNode* node = producePseudoNode();
+    // create the pseudo relocation to present the fan-out of the pseudo node
+    Relocation* reloc = Relocation::Create();
+    reloc->setSymInfo(sym);
+
+    // set the signal of the pseudo node
+    node->addSignal(reloc);
+
+    // maintain the map for symbol to pseudo node
+    SymHashTableType::entry_type* entry = 0;
+    bool exist = false;
+    entry = m_pSymNodeMap->insert(sym, exist);
+    entry->setValue(node);
+
+  }
+  return true;
+}
+
+bool FragmentGraph::createRegularNodes(Module& pModule)
+{
+  // Traverse all sections to build the Nodes. We build nodes only for Regular,
+  // and BSS
+  Module::iterator sect_it, sect_end = pModule.end();
+  for (sect_it = pModule.begin(); sect_it != sect_end; ++sect_it) {
+    LDSection* section = *sect_it;
+    SectionData* sect_data = NULL;
+
+    if (LDFileFormat::Regular != section->kind() &&
+        LDFileFormat::BSS != section->kind())
+      continue;
+
+    sect_data = section->getSectionData();
+    if (NULL == sect_data)
+      continue;
+
+    // Traverse all fragments in the sections, create Nodes and push the
+    // fragments into Nodes. Each Region or Fillment fragment belongs to a
+    // unique Node. The corresponding Align fragments and Null fragments belong
+    // to the same Node as the Region or Fillment fragment.
+    SectionData::iterator frag_it  = sect_data->begin();
+    SectionData::iterator frag_end = sect_data->end();
+    if (frag_it == frag_end)
+      continue;
+
+    int cur_stat = 0;
+    int last_stat = 0;
+    // FIXME:
+    // To prevent some cases that we add the redundant NULL or Align fragments
+    // and lead a Region/Fillment fragment has more than one NULL or Align
+    // fragment. We should put all of them into the same Node.
+    static int stat_matrix[3][3] = {{0, 1, 1},
+                                    {0, 1, 1},
+                                    {0, 0, 0}};
+
+    FragHashTableType::entry_type* entry = 0;
+    bool exist = false;
+
+    FGNode* node = produceRegularNode();
+    Fragment* frag = NULL;
+
+    frag = &(*frag_it);
+    cur_stat = get_state(frag->getKind());
+
+    node->addFragment(frag);
+    // maintain the fragment to Node map
+    entry = m_pFragNodeMap->insert(frag, exist);
+    entry->setValue(node);
+    ++frag_it;
+
+    while (frag_it != frag_end) {
+      last_stat = cur_stat;
+      frag = &(*frag_it);
+
+      cur_stat = get_state(frag->getKind());
+
+      if (stat_matrix[cur_stat][last_stat]) {
+        node = produceRegularNode();
+      }
+      node->addFragment(frag);
+      // maintain the fragment to Node map
+      entry = m_pFragNodeMap->insert(frag, exist);
+      entry->setValue(node);
+
+      ++frag_it;
+    }
+  }
+  return true;
+}
+
+void FragmentGraph::initMatrix()
+{
+  m_pMatrix = new ReachMatrix(m_NumOfPNodes + m_NumOfRNodes);
+}
+
+bool FragmentGraph::getEdges(FGNode& pNode, EdgeListType& pEdges)
+{
+  // Traverse all regular nodes to find the connection to pNode
+  node_iterator it, itEnd = m_pRegularNodeFactory->end();
+  for (it = m_pRegularNodeFactory->begin(); it != itEnd; ++it) {
+    FGNode& node_to = *it;
+    uint32_t weight = m_pMatrix->at(pNode.getIndex(), node_to.getIndex());
+    if (weight > 0) {
+      // build an Edge
+      pEdges.push_back(FGEdge(pNode, node_to, weight));
+    }
+  }
+
+  return true;
+}
+
+bool FragmentGraph::construct(const LinkerConfig& pConfig, Module& pModule)
+{
+  // create nodes - traverse all fragments to create the regular nodes, and
+  // then traverse all global defined symbols to create pseudo nodes
+  if (!createRegularNodes(pModule))
+    return false;
+  if (!createPseudoNodes(pModule))
+    return false;
+
+  // after all nodes created, we know the number of the nodes and then can
+  // create the reachability matrix
+  initMatrix();
+
+  // set slots - traverse all symbols to set the slots of regular nodes
+  if(!setNodeSlots(pModule))
+    return false;
+
+  // connect edges - traverse all relocations to set the edges
+  if(!createRegularEdges(pModule))
+    return false;
+  if(!createPseudoEdges(pModule))
+    return false;
+
+  return true;
+}
+
diff --git a/lib/Fragment/FragmentLinker.cpp b/lib/Fragment/FragmentLinker.cpp
index 0398834..dae7b00 100644
--- a/lib/Fragment/FragmentLinker.cpp
+++ b/lib/Fragment/FragmentLinker.cpp
@@ -52,194 +52,6 @@
 {
 }
 
-//===----------------------------------------------------------------------===//
-// Symbol Operations
-//===----------------------------------------------------------------------===//
-/// defineSymbolForcefully - define an output symbol and override it immediately
-LDSymbol* FragmentLinker::defineSymbolForcefully(const llvm::StringRef& pName,
-                                           bool pIsDyn,
-                                           ResolveInfo::Type pType,
-                                           ResolveInfo::Desc pDesc,
-                                           ResolveInfo::Binding pBinding,
-                                           ResolveInfo::SizeType pSize,
-                                           LDSymbol::ValueType pValue,
-                                           FragmentRef* pFragmentRef,
-                                           ResolveInfo::Visibility pVisibility)
-{
-  ResolveInfo* info = m_Module.getNamePool().findInfo(pName);
-  LDSymbol* output_sym = NULL;
-  if (NULL == info) {
-    // the symbol is not in the pool, create a new one.
-    // create a ResolveInfo
-    Resolver::Result result;
-    m_Module.getNamePool().insertSymbol(pName, pIsDyn, pType, pDesc,
-                                        pBinding, pSize, pVisibility,
-                                        NULL, result);
-    assert(!result.existent);
-
-    // create a output LDSymbol
-    output_sym = LDSymbol::Create(*result.info);
-    result.info->setSymPtr(output_sym);
-
-    if (shouldForceLocal(*result.info))
-      m_Module.getSymbolTable().forceLocal(*output_sym);
-    else
-      m_Module.getSymbolTable().add(*output_sym);
-  }
-  else {
-    // the symbol is already in the pool, override it
-    ResolveInfo old_info;
-    old_info.override(*info);
-
-    info->setSource(pIsDyn);
-    info->setType(pType);
-    info->setDesc(pDesc);
-    info->setBinding(pBinding);
-    info->setVisibility(pVisibility);
-    info->setIsSymbol(true);
-    info->setSize(pSize);
-
-    output_sym = info->outSymbol();
-    if (NULL != output_sym)
-      m_Module.getSymbolTable().arrange(*output_sym, old_info);
-    else {
-      // create a output LDSymbol
-      output_sym = LDSymbol::Create(*info);
-      info->setSymPtr(output_sym);
-
-      m_Module.getSymbolTable().add(*output_sym);
-    }
-  }
-
-  if (NULL != output_sym) {
-    output_sym->setFragmentRef(pFragmentRef);
-    output_sym->setValue(pValue);
-  }
-
-  return output_sym;
-}
-
-/// defineSymbolAsRefered - define an output symbol and override it immediately
-LDSymbol* FragmentLinker::defineSymbolAsRefered(const llvm::StringRef& pName,
-                                           bool pIsDyn,
-                                           ResolveInfo::Type pType,
-                                           ResolveInfo::Desc pDesc,
-                                           ResolveInfo::Binding pBinding,
-                                           ResolveInfo::SizeType pSize,
-                                           LDSymbol::ValueType pValue,
-                                           FragmentRef* pFragmentRef,
-                                           ResolveInfo::Visibility pVisibility)
-{
-  ResolveInfo* info = m_Module.getNamePool().findInfo(pName);
-
-  if (NULL == info || !(info->isUndef() || info->isDyn())) {
-    // only undefined symbol and dynamic symbol can make a reference.
-    return NULL;
-  }
-
-  // the symbol is already in the pool, override it
-  ResolveInfo old_info;
-  old_info.override(*info);
-
-  info->setSource(pIsDyn);
-  info->setType(pType);
-  info->setDesc(pDesc);
-  info->setBinding(pBinding);
-  info->setVisibility(pVisibility);
-  info->setIsSymbol(true);
-  info->setSize(pSize);
-
-  LDSymbol* output_sym = info->outSymbol();
-  if (NULL != output_sym) {
-    output_sym->setFragmentRef(pFragmentRef);
-    output_sym->setValue(pValue);
-    m_Module.getSymbolTable().arrange(*output_sym, old_info);
-  }
-  else {
-    // create a output LDSymbol
-    output_sym = LDSymbol::Create(*info);
-    info->setSymPtr(output_sym);
-
-    m_Module.getSymbolTable().add(*output_sym);
-  }
-
-  return output_sym;
-}
-
-/// defineAndResolveSymbolForcefully - define an output symbol and resolve it
-/// immediately
-LDSymbol* FragmentLinker::defineAndResolveSymbolForcefully(const llvm::StringRef& pName,
-                                                     bool pIsDyn,
-                                                     ResolveInfo::Type pType,
-                                                     ResolveInfo::Desc pDesc,
-                                                     ResolveInfo::Binding pBinding,
-                                                     ResolveInfo::SizeType pSize,
-                                                     LDSymbol::ValueType pValue,
-                                                     FragmentRef* pFragmentRef,
-                                                     ResolveInfo::Visibility pVisibility)
-{
-  // Result is <info, existent, override>
-  Resolver::Result result;
-  ResolveInfo old_info;
-  m_Module.getNamePool().insertSymbol(pName, pIsDyn, pType, pDesc, pBinding,
-                                      pSize, pVisibility,
-                                      &old_info, result);
-
-  LDSymbol* output_sym = result.info->outSymbol();
-  bool has_output_sym = (NULL != output_sym);
-
-  if (!result.existent || !has_output_sym) {
-    output_sym = LDSymbol::Create(*result.info);
-    result.info->setSymPtr(output_sym);
-  }
-
-  if (result.overriden || !has_output_sym) {
-    output_sym->setFragmentRef(pFragmentRef);
-    output_sym->setValue(pValue);
-  }
-
-  // After symbol resolution, the visibility is changed to the most restrict.
-  // arrange the output position
-  if (shouldForceLocal(*result.info))
-    m_Module.getSymbolTable().forceLocal(*output_sym);
-  else if (has_output_sym)
-    m_Module.getSymbolTable().arrange(*output_sym, old_info);
-  else
-    m_Module.getSymbolTable().add(*output_sym);
-
-  return output_sym;
-}
-
-/// defineAndResolveSymbolAsRefered - define an output symbol and resolve it
-/// immediately.
-LDSymbol* FragmentLinker::defineAndResolveSymbolAsRefered(const llvm::StringRef& pName,
-                                                    bool pIsDyn,
-                                                    ResolveInfo::Type pType,
-                                                    ResolveInfo::Desc pDesc,
-                                                    ResolveInfo::Binding pBinding,
-                                                    ResolveInfo::SizeType pSize,
-                                                    LDSymbol::ValueType pValue,
-                                                    FragmentRef* pFragmentRef,
-                                                    ResolveInfo::Visibility pVisibility)
-{
-  ResolveInfo* info = m_Module.getNamePool().findInfo(pName);
-
-  if (NULL == info || !(info->isUndef() || info->isDyn())) {
-    // only undefined symbol and dynamic symbol can make a reference.
-    return NULL;
-  }
-
-  return defineAndResolveSymbolForcefully(pName,
-                                          pIsDyn,
-                                          pType,
-                                          pDesc,
-                                          pBinding,
-                                          pSize,
-                                          pValue,
-                                          pFragmentRef,
-                                          pVisibility);
-}
-
 bool FragmentLinker::finalizeSymbols()
 {
   Module::sym_iterator symbol, symEnd = m_Module.sym_end();
@@ -270,24 +82,7 @@
     }
   }
 
-  // finialize target-dependent symbols
-  return m_Backend.finalizeSymbols(*this);
-}
-
-bool FragmentLinker::shouldForceLocal(const ResolveInfo& pInfo) const
-{
-  // forced local symbol matches all rules:
-  // 1. We are not doing incremental linking.
-  // 2. The symbol is with Hidden or Internal visibility.
-  // 3. The symbol should be global or weak. Otherwise, local symbol is local.
-  // 4. The symbol is defined or common
-  if (LinkerConfig::Object != m_Config.codeGenType() &&
-      (pInfo.visibility() == ResolveInfo::Hidden ||
-         pInfo.visibility() == ResolveInfo::Internal) &&
-      (pInfo.isGlobal() || pInfo.isWeak()) &&
-      (pInfo.isDefine() || pInfo.isCommon()))
-    return true;
-  return false;
+  return true;
 }
 
 //===----------------------------------------------------------------------===//
@@ -426,15 +221,25 @@
 void FragmentLinker::writeRelocationResult(Relocation& pReloc, uint8_t* pOutput)
 {
   // get output file offset
-  size_t out_offset = pReloc.targetRef().frag()->getParent()->getSection().offset() +
-                      pReloc.targetRef().getOutputOffset();
+  size_t out_offset =
+                 pReloc.targetRef().frag()->getParent()->getSection().offset() +
+                 pReloc.targetRef().getOutputOffset();
 
   uint8_t* target_addr = pOutput + out_offset;
   // byte swapping if target and host has different endian, and then write back
   if(llvm::sys::isLittleEndianHost() != m_Config.targets().isLittleEndian()) {
      uint64_t tmp_data = 0;
 
-     switch(m_Config.targets().bitclass()) {
+     switch(pReloc.size(*m_Backend.getRelocator())) {
+       case 8u:
+         std::memcpy(target_addr, &pReloc.target(), 1);
+         break;
+
+       case 16u:
+         tmp_data = mcld::bswap16(pReloc.target());
+         std::memcpy(target_addr, &tmp_data, 2);
+         break;
+
        case 32u:
          tmp_data = mcld::bswap32(pReloc.target());
          std::memcpy(target_addr, &tmp_data, 4);
@@ -450,33 +255,7 @@
     }
   }
   else
-    std::memcpy(target_addr, &pReloc.target(), m_Config.targets().bitclass()/8);
-}
-
-/// isOutputPIC - return whether the output is position-independent
-bool FragmentLinker::isOutputPIC() const
-{
-  return checkIsOutputPIC();
-}
-
-/// isStaticLink - return whether we're doing static link
-bool FragmentLinker::isStaticLink() const
-{
-  return checkIsStaticLink();
-}
-
-bool FragmentLinker::checkIsOutputPIC() const
-{
-  if (LinkerConfig::DynObj == m_Config.codeGenType() ||
-      m_Config.options().isPIE())
-    return true;
-  return false;
-}
-
-bool FragmentLinker::checkIsStaticLink() const
-{
-  if (m_Module.getLibraryList().empty() && !isOutputPIC())
-    return true;
-  return false;
+    std::memcpy(target_addr, &pReloc.target(),
+                                      pReloc.size(*m_Backend.getRelocator())/8);
 }
 
diff --git a/lib/Fragment/Relocation.cpp b/lib/Fragment/Relocation.cpp
index 293b1c9..fd042ea 100644
--- a/lib/Fragment/Relocation.cpp
+++ b/lib/Fragment/Relocation.cpp
@@ -143,10 +143,9 @@
   m_pSymInfo = pSym;
 }
 
-size_t Relocation::size() const
+Relocation::Size Relocation::size(Relocator& pRelocator) const
 {
-  // TODO: the size of Relocation fragment is handled by backend
-  return 0;
+  return pRelocator.getSize(m_Type);
 }
 
 void Relocation::updateAddend()
diff --git a/lib/LD/Android.mk b/lib/LD/Android.mk
index 53c1f10..edba1b0 100644
--- a/lib/LD/Android.mk
+++ b/lib/LD/Android.mk
@@ -7,7 +7,6 @@
 mcld_ld_SRC_FILES := \
   Archive.cpp \
   ArchiveReader.cpp \
-  BinaryWriter.cpp \
   BranchIsland.cpp  \
   BranchIslandFactory.cpp  \
   DWARFLineInfo.cpp \
@@ -17,27 +16,24 @@
   DiagnosticLineInfo.cpp  \
   DiagnosticPrinter.cpp \
   DynObjReader.cpp  \
-  DynObjWriter.cpp  \
   ELFBinaryReader.cpp  \
-  ELFBinaryWriter.cpp  \
   ELFSegment.cpp  \
   ELFSegmentFactory.cpp \
   EhFrame.cpp \
   EhFrameHdr.cpp  \
   EhFrameReader.cpp  \
-  ExecWriter.cpp  \
   GroupReader.cpp \
   LDContext.cpp \
   LDFileFormat.cpp  \
   LDReader.cpp  \
   LDSection.cpp \
   LDSymbol.cpp  \
-  LDWriter.cpp  \
   MsgHandler.cpp  \
   NamePool.cpp  \
   ObjectWriter.cpp  \
   RelocData.cpp  \
   RelocationFactory.cpp \
+  Relocator.cpp \
   ResolveInfo.cpp \
   Resolver.cpp  \
   SectionData.cpp \
@@ -80,14 +76,12 @@
   GNUArchiveReader.cpp  \
   ELFDynObjFileFormat.cpp \
   ELFDynObjReader.cpp \
-  ELFDynObjWriter.cpp \
   ELFExecFileFormat.cpp \
-  ELFExecWriter.cpp \
   ELFFileFormat.cpp \
   ELFObjectReader.cpp \
   ELFObjectWriter.cpp \
   ELFReader.cpp \
-  ELFWriter.cpp
+  ELFReaderIf.cpp
 
 # For the host
 # =====================================================
diff --git a/lib/LD/Archive.cpp b/lib/LD/Archive.cpp
index be82922..ee2edea 100644
--- a/lib/LD/Archive.cpp
+++ b/lib/LD/Archive.cpp
@@ -129,7 +129,10 @@
   ArchiveMemberEntryType* entry = m_ArchiveMemberMap.insert(pName, exist);
   if (!exist) {
     ArchiveMember& ar = entry->value();
-    ar.file = *pLastPos;
+    if (pLastPos == m_pInputTree->root())
+      ar.file = &m_ArchiveFile;
+    else
+      ar.file = *pLastPos;
     ar.lastPos = pLastPos;
     ar.move = pMove;
   }
diff --git a/lib/LD/BinaryWriter.cpp b/lib/LD/BinaryWriter.cpp
deleted file mode 100644
index 00dd169..0000000
--- a/lib/LD/BinaryWriter.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-//===- BinaryWriter.cpp ---------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/LD/BinaryWriter.h>
-#include <mcld/MC/MCLDInput.h>
-#include <mcld/Target/GNULDBackend.h>
-
-using namespace mcld;
-
-//==========================
-// BinaryWriter
-BinaryWriter::BinaryWriter(GNULDBackend& pBackend)
-{
-}
-
-BinaryWriter::~BinaryWriter()
-{
-}
-
diff --git a/lib/LD/DiagnosticEngine.cpp b/lib/LD/DiagnosticEngine.cpp
index c2e52d7..ac51080 100644
--- a/lib/LD/DiagnosticEngine.cpp
+++ b/lib/LD/DiagnosticEngine.cpp
@@ -30,6 +30,9 @@
     delete m_pPrinter;
 
   delete m_pInfoMap;
+
+  // FIXME: design the destructive relation of LineInfo.
+  delete m_pLineInfo;
 }
 
 void DiagnosticEngine::reset(const LinkerConfig& pConfig)
diff --git a/lib/LD/DiagnosticInfos.cpp b/lib/LD/DiagnosticInfos.cpp
index 130fd9a..280e178 100644
--- a/lib/LD/DiagnosticInfos.cpp
+++ b/lib/LD/DiagnosticInfos.cpp
@@ -130,12 +130,17 @@
             severity = DiagnosticEngine::Ignore;
           break;
         case LinkerConfig::DynObj:
-          if (m_Config.options().isNoUndefined() || !m_Config.options().isAllowShlibUndefined())
+          if (m_Config.options().isNoUndefined())
             severity = DiagnosticEngine::Error;
           else
             severity = DiagnosticEngine::Ignore;
           break;
         case LinkerConfig::Exec:
+          if (m_Config.options().isNoUndefined() || m_Config.isCodeStatic())
+            severity = DiagnosticEngine::Error;
+          else
+            severity = DiagnosticEngine::Ignore;
+          break;
         default:
           severity = DiagnosticEngine::Error;
           break;
diff --git a/lib/LD/DynObjWriter.cpp b/lib/LD/DynObjWriter.cpp
deleted file mode 100644
index 6f031ff..0000000
--- a/lib/LD/DynObjWriter.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-//===- DynObjWriter.cpp ---------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/LD/DynObjWriter.h"
-#include "mcld/Target/TargetLDBackend.h"
-#include "mcld/MC/MCLDInput.h"
-
-using namespace mcld;
-
-//==========================
-// DynObjWriter
diff --git a/lib/LD/ELFBinaryReader.cpp b/lib/LD/ELFBinaryReader.cpp
index c291544..f818286 100644
--- a/lib/LD/ELFBinaryReader.cpp
+++ b/lib/LD/ELFBinaryReader.cpp
@@ -16,6 +16,8 @@
 
 #include <llvm/Support/ELF.h>
 
+#include <cctype>
+
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
@@ -83,9 +85,16 @@
                       0x0,
                       data_sect);
 
+  std::string mangled_name = pInput.path().filename().string();
+  for (std::string::iterator it = mangled_name.begin(),
+    ie = mangled_name.end(); it != ie; ++it) {
+    if (isalnum(*it) == 0)
+      *it = '_';
+  }
+
   // symbol: _start
   m_Builder.AddSymbol(pInput,
-                      "_binary_" + pInput.path().filename().string() + "_start",
+                      "_binary_" + mangled_name + "_start",
                       ResolveInfo::NoType,
                       ResolveInfo::Define,
                       ResolveInfo::Global,
@@ -95,7 +104,7 @@
 
   // symbol: _end
   m_Builder.AddSymbol(pInput,
-                      "_binary_" + pInput.path().filename().string() + "_end",
+                      "_binary_" + mangled_name + "_end",
                       ResolveInfo::NoType,
                       ResolveInfo::Define,
                       ResolveInfo::Global,
@@ -105,7 +114,7 @@
 
   // symbol: _size
   m_Builder.AddSymbol(pInput,
-                      "_binary_" + pInput.path().filename().string() + "_size",
+                      "_binary_" + mangled_name + "_size",
                       ResolveInfo::NoType,
                       ResolveInfo::Define,
                       ResolveInfo::Global,
diff --git a/lib/LD/ELFBinaryWriter.cpp b/lib/LD/ELFBinaryWriter.cpp
deleted file mode 100644
index 28ef553..0000000
--- a/lib/LD/ELFBinaryWriter.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-//===- ELFBinaryWriter.cpp ------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/LD/ELFBinaryWriter.h>
-
-#include <mcld/Module.h>
-#include <mcld/Target/GNULDBackend.h>
-#include <mcld/Fragment/FragmentLinker.h>
-#include <mcld/Support/MemoryArea.h>
-#include <mcld/LD/ELFSegmentFactory.h>
-#include <mcld/LD/ELFSegment.h>
-
-#include <llvm/Support/system_error.h>
-using namespace llvm;
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// ELFBinaryWriter
-//===----------------------------------------------------------------------===//
-ELFBinaryWriter::ELFBinaryWriter(GNULDBackend& pBackend,
-                                 const LinkerConfig& pConfig)
-  : BinaryWriter(pBackend), ELFWriter(pBackend), m_Config(pConfig) {
-}
-
-ELFBinaryWriter::~ELFBinaryWriter()
-{
-}
-
-llvm::error_code ELFBinaryWriter::writeBinary(Module& pModule,
-                                              MemoryArea& pOutput)
-{
-  // Write out regular ELF sections
-  for (ELFSegmentFactory::iterator seg = target().elfSegmentTable().begin(),
-         segEnd = target().elfSegmentTable().end(); seg != segEnd; ++seg) {
-    if (llvm::ELF::PT_LOAD != (*seg).type())
-      continue;
-
-    for (ELFSegment::sect_iterator sect = (*seg).begin(),
-           sectEnd = (*seg).end(); sect != sectEnd; ++sect) {
-      MemoryRegion* region = NULL;
-      // request output region
-      switch((*sect)->kind()) {
-        case LDFileFormat::Note:
-          if ((*sect)->getSectionData() == NULL)
-            continue;
-          // Fall through
-        case LDFileFormat::Regular:
-        case LDFileFormat::Relocation:
-        case LDFileFormat::Target:
-        case LDFileFormat::Debug:
-        case LDFileFormat::GCCExceptTable:
-        case LDFileFormat::EhFrame: {
-          region = pOutput.request((*sect)->offset(), (*sect)->size());
-          if (NULL == region) {
-            llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section `") +
-                                     llvm::Twine((*sect)->name()) +
-                                     llvm::Twine("'.\n"));
-          }
-          break;
-        }
-        case LDFileFormat::Null:
-        case LDFileFormat::NamePool:
-        case LDFileFormat::BSS:
-        case LDFileFormat::MetaData:
-        case LDFileFormat::Version:
-        case LDFileFormat::EhFrameHdr:
-        case LDFileFormat::StackNote:
-          // ignore these sections
-          continue;
-        default: {
-          llvm::errs() << "WARNING: unsupported section kind: "
-                       << (*sect)->kind()
-                       << " of section "
-                       << (*sect)->name()
-                       << ".\n";
-          continue;
-        }
-      }
-
-      // write out sections with data
-      switch((*sect)->kind()) {
-        case LDFileFormat::Regular:
-        case LDFileFormat::Debug:
-        case LDFileFormat::GCCExceptTable:
-        case LDFileFormat::Note:
-        case LDFileFormat::EhFrame: {
-          // FIXME: if optimization of exception handling sections is enabled,
-          // then we should emit these sections by the other way.
-          emitSectionData(**sect, *region);
-          break;
-        }
-        case LDFileFormat::Relocation:
-          emitRelocation(m_Config, **sect, *region);
-          break;
-        case LDFileFormat::Target:
-          target().emitSectionData(**sect, *region);
-          break;
-        default:
-          continue;
-      }
-    } // end of section for loop
-  } // end of segment for loop
-  return llvm::make_error_code(llvm::errc::success);
-}
-
diff --git a/lib/LD/ELFDynObjFileFormat.cpp b/lib/LD/ELFDynObjFileFormat.cpp
index 9ccf967..e89f48b 100644
--- a/lib/LD/ELFDynObjFileFormat.cpp
+++ b/lib/LD/ELFDynObjFileFormat.cpp
@@ -52,12 +52,12 @@
                                            llvm::ELF::SHT_RELA,
                                            llvm::ELF::SHF_ALLOC,
                                            pBitClass / 8);
-  f_pRelDyn      = pBuilder.CreateSection(".rel.dyn",
+  f_pRelDyn       = pBuilder.CreateSection(".rel.dyn",
                                            LDFileFormat::Relocation,
                                            llvm::ELF::SHT_REL,
                                            llvm::ELF::SHF_ALLOC,
                                            pBitClass / 8);
-  f_pRelPlt      = pBuilder.CreateSection(".rel.plt",
+  f_pRelPlt       = pBuilder.CreateSection(".rel.plt",
                                            LDFileFormat::Relocation,
                                            llvm::ELF::SHT_REL,
                                            llvm::ELF::SHF_ALLOC,
@@ -77,10 +77,15 @@
                                            llvm::ELF::SHT_PROGBITS,
                                            llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                            pBitClass / 8);
-  f_pEhFrameHdr     = pBuilder.CreateSection(".eh_frame_hdr",
-                                              LDFileFormat::EhFrameHdr,
-                                              llvm::ELF::SHT_PROGBITS,
-                                              llvm::ELF::SHF_ALLOC,
-                                              0x4);
+  f_pEhFrameHdr   = pBuilder.CreateSection(".eh_frame_hdr",
+                                           LDFileFormat::EhFrameHdr,
+                                           llvm::ELF::SHT_PROGBITS,
+                                           llvm::ELF::SHF_ALLOC,
+                                           0x4);
+  f_pGNUHashTab   = pBuilder.CreateSection(".gnu.hash",
+                                           LDFileFormat::NamePool,
+                                           llvm::ELF::SHT_GNU_HASH,
+                                           llvm::ELF::SHF_ALLOC,
+                                           pBitClass / 8);
 }
 
diff --git a/lib/LD/ELFDynObjReader.cpp b/lib/LD/ELFDynObjReader.cpp
index e52e863..4f8c7ba 100644
--- a/lib/LD/ELFDynObjReader.cpp
+++ b/lib/LD/ELFDynObjReader.cpp
@@ -34,6 +34,8 @@
     m_Builder(pBuilder) {
   if (pConfig.targets().is32Bits() && pConfig.targets().isLittleEndian())
     m_pELFReader = new ELFReader<32, true>(pBackend);
+  else if (pConfig.targets().is64Bits() && pConfig.targets().isLittleEndian())
+    m_pELFReader = new ELFReader<64, true>(pBackend);
 }
 
 ELFDynObjReader::~ELFDynObjReader()
diff --git a/lib/LD/ELFDynObjWriter.cpp b/lib/LD/ELFDynObjWriter.cpp
deleted file mode 100644
index 2e903ce..0000000
--- a/lib/LD/ELFDynObjWriter.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-//===- ELFDynObjWriter.cpp ------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/LD/ELFDynObjWriter.h>
-
-#include <mcld/Module.h>
-#include <mcld/LinkerConfig.h>
-#include <mcld/LD/LDSymbol.h>
-#include <mcld/Target/GNULDBackend.h>
-#include <mcld/MC/MCLDInput.h>
-#include <mcld/Support/MemoryArea.h>
-
-#include <llvm/Support/ELF.h>
-
-#include <vector>
-
-using namespace llvm;
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// ELFDynObjWriter
-//===----------------------------------------------------------------------===//
-ELFDynObjWriter::ELFDynObjWriter(GNULDBackend& pBackend,
-                                 const LinkerConfig& pConfig)
-  : DynObjWriter(pBackend), ELFWriter(pBackend),
-    m_Config(pConfig) {
-
-}
-
-ELFDynObjWriter::~ELFDynObjWriter()
-{
-}
-
-llvm::error_code ELFDynObjWriter::writeDynObj(Module& pModule,
-                                              MemoryArea& pOutput)
-{
-  target().emitInterp(pOutput);
-
-  // Write out name pool sections: .dynsym, .dynstr, .hash
-  target().emitDynNamePools(pModule, pOutput);
-
-  // Write out name pool sections: .symtab, .strtab
-  target().emitRegNamePools(pModule, pOutput);
-
-  // Write out regular ELF sections
-  Module::iterator sect, sectEnd = pModule.end();
-  for (sect = pModule.begin(); sect != sectEnd; ++sect) {
-    MemoryRegion* region = NULL;
-    // request output region
-    switch((*sect)->kind()) {
-      case LDFileFormat::Note:
-        if ((*sect)->getSectionData() == NULL)
-          continue;
-        // Fall through
-      case LDFileFormat::Regular:
-      case LDFileFormat::Relocation:
-      case LDFileFormat::Target:
-      case LDFileFormat::Debug:
-      case LDFileFormat::GCCExceptTable:
-      case LDFileFormat::EhFrame: {
-        region = pOutput.request((*sect)->offset(), (*sect)->size());
-        if (NULL == region) {
-          llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section ") +
-                                   llvm::Twine((*sect)->name()) +
-                                   llvm::Twine(".\n"));
-        }
-        break;
-      }
-      case LDFileFormat::Null:
-      case LDFileFormat::NamePool:
-      case LDFileFormat::BSS:
-      case LDFileFormat::MetaData:
-      case LDFileFormat::Version:
-      case LDFileFormat::EhFrameHdr:
-      case LDFileFormat::StackNote:
-        // ignore these sections
-        continue;
-      default: {
-        llvm::errs() << "WARNING: unsupported section kind: "
-                     << (*sect)->kind()
-                     << " of section "
-                     << (*sect)->name()
-                     << ".\n";
-        continue;
-      }
-    }
-
-    // write out sections with data
-    switch((*sect)->kind()) {
-      case LDFileFormat::Regular:
-      case LDFileFormat::Debug:
-      case LDFileFormat::GCCExceptTable:
-      case LDFileFormat::Note:
-      case LDFileFormat::EhFrame: {
-        // FIXME: if optimization of exception handling sections is enabled,
-        // then we should emit these sections by the other way.
-        emitSectionData(**sect, *region);
-        break;
-      }
-      case LDFileFormat::Relocation:
-        emitRelocation(m_Config, **sect, *region);
-        break;
-      case LDFileFormat::Target:
-        target().emitSectionData(**sect, *region);
-        break;
-      default:
-        continue;
-    }
-
-  } // end of for loop
-
-  emitELFShStrTab(target().getOutputFormat()->getShStrTab(),
-                  pModule,
-                  pOutput);
-
-  if (m_Config.targets().is32Bits()) {
-    // Write out ELF header
-    // Write out section header table
-    writeELF32Header(m_Config, pModule, pOutput);
-
-    emitELF32ProgramHeader(pOutput);
-
-    emitELF32SectionHeader(pModule, m_Config, pOutput);
-  }
-  else if (m_Config.targets().is64Bits()) {
-    // Write out ELF header
-    // Write out section header table
-    writeELF64Header(m_Config, pModule, pOutput);
-
-    emitELF64ProgramHeader(pOutput);
-
-    emitELF64SectionHeader(pModule, m_Config, pOutput);
-  }
-  else
-    return make_error_code(errc::not_supported);
-  pOutput.clear();
-  return llvm::make_error_code(llvm::errc::success);
-}
-
diff --git a/lib/LD/ELFExecFileFormat.cpp b/lib/LD/ELFExecFileFormat.cpp
index a05c058..6a81f72 100644
--- a/lib/LD/ELFExecFileFormat.cpp
+++ b/lib/LD/ELFExecFileFormat.cpp
@@ -53,12 +53,12 @@
                                            llvm::ELF::SHT_RELA,
                                            llvm::ELF::SHF_ALLOC,
                                            pBitClass / 8);
-  f_pRelDyn      = pBuilder.CreateSection(".rel.dyn",
+  f_pRelDyn       = pBuilder.CreateSection(".rel.dyn",
                                            LDFileFormat::Relocation,
                                            llvm::ELF::SHT_REL,
                                            llvm::ELF::SHF_ALLOC,
                                            pBitClass / 8);
-  f_pRelPlt      = pBuilder.CreateSection(".rel.plt",
+  f_pRelPlt       = pBuilder.CreateSection(".rel.plt",
                                            LDFileFormat::Relocation,
                                            llvm::ELF::SHT_REL,
                                            llvm::ELF::SHF_ALLOC,
@@ -83,4 +83,9 @@
                                            llvm::ELF::SHT_PROGBITS,
                                            llvm::ELF::SHF_ALLOC,
                                            0x4);
+  f_pGNUHashTab   = pBuilder.CreateSection(".gnu.hash",
+                                           LDFileFormat::NamePool,
+                                           llvm::ELF::SHT_GNU_HASH,
+                                           llvm::ELF::SHF_ALLOC,
+                                           pBitClass / 8);
 }
diff --git a/lib/LD/ELFExecWriter.cpp b/lib/LD/ELFExecWriter.cpp
deleted file mode 100644
index a9af584..0000000
--- a/lib/LD/ELFExecWriter.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-//===- ELFExecWriter.cpp --------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/LD/ELFExecWriter.h>
-
-#include <mcld/Module.h>
-#include <mcld/LinkerConfig.h>
-#include <mcld/LD/LDSymbol.h>
-#include <mcld/Target/GNULDBackend.h>
-#include <mcld/Support/MemoryArea.h>
-
-#include <llvm/Support/ELF.h>
-#include <vector>
-
-using namespace llvm;
-using namespace mcld;
-
-
-//===----------------------------------------------------------------------===//
-// ELFExecWriter
-//===----------------------------------------------------------------------===//
-ELFExecWriter::ELFExecWriter(GNULDBackend& pBackend,
-                             const LinkerConfig& pConfig)
-  : ExecWriter(pBackend), ELFWriter(pBackend),
-    m_Config(pConfig) {
-
-}
-
-ELFExecWriter::~ELFExecWriter()
-{
-}
-
-llvm::error_code ELFExecWriter::writeExecutable(Module& pModule,
-                                                MemoryArea& pOutput)
-{
-  // write out the interpreter section: .interp
-  target().emitInterp(pOutput);
-
-  // Write out name pool sections: .dynsym, .dynstr, .hash
-  target().emitDynNamePools(pModule, pOutput);
-
-  // Write out name pool sections: .symtab, .strtab
-  target().emitRegNamePools(pModule, pOutput);
-
-  // Write out regular ELF sections
-  Module::iterator sect, sectEnd = pModule.end();
-  for (sect = pModule.begin(); sect != sectEnd; ++sect) {
-    MemoryRegion* region = NULL;
-    // request output region
-    switch((*sect)->kind()) {
-      case LDFileFormat::Note:
-        if ((*sect)->getSectionData() == NULL)
-          continue;
-        // Fall through
-      case LDFileFormat::Regular:
-      case LDFileFormat::Relocation:
-      case LDFileFormat::Target:
-      case LDFileFormat::Debug:
-      case LDFileFormat::GCCExceptTable:
-      case LDFileFormat::EhFrame: {
-        region = pOutput.request((*sect)->offset(), (*sect)->size());
-        if (NULL == region) {
-          llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section `") +
-                                   llvm::Twine((*sect)->name()) +
-                                   llvm::Twine("'.\n"));
-        }
-        break;
-      }
-      case LDFileFormat::Null:
-      case LDFileFormat::NamePool:
-      case LDFileFormat::BSS:
-      case LDFileFormat::MetaData:
-      case LDFileFormat::Version:
-      case LDFileFormat::EhFrameHdr:
-      case LDFileFormat::StackNote:
-        // ignore these sections
-        continue;
-      default: {
-        llvm::errs() << "WARNING: unsupported section kind: "
-                     << (*sect)->kind()
-                     << " of section "
-                     << (*sect)->name()
-                     << ".\n";
-        continue;
-      }
-    }
-
-    // write out sections with data
-    switch((*sect)->kind()) {
-      case LDFileFormat::Regular:
-      case LDFileFormat::Debug:
-      case LDFileFormat::GCCExceptTable:
-      case LDFileFormat::Note:
-      case LDFileFormat::EhFrame: {
-        // FIXME: if optimization of exception handling sections is enabled,
-        // then we should emit these sections by the other way.
-        emitSectionData(**sect, *region);
-        break;
-      }
-      case LDFileFormat::Relocation:
-        emitRelocation(m_Config, **sect, *region);
-        break;
-      case LDFileFormat::Target:
-        target().emitSectionData(**sect, *region);
-        break;
-      default:
-        continue;
-    }
-  } // end of for loop
-
-  emitELFShStrTab(target().getOutputFormat()->getShStrTab(),
-                  pModule,
-                  pOutput);
-
-  if (m_Config.targets().is32Bits()) {
-    // Write out ELF header
-    // Write out section header table
-    writeELF32Header(m_Config, pModule, pOutput);
-
-    emitELF32ProgramHeader(pOutput);
-
-    emitELF32SectionHeader(pModule, m_Config, pOutput);
-  }
-  else if (m_Config.targets().is64Bits()) {
-    // Write out ELF header
-    // Write out section header table
-    writeELF64Header(m_Config, pModule, pOutput);
-
-    emitELF64ProgramHeader(pOutput);
-
-    emitELF64SectionHeader(pModule, m_Config, pOutput);
-  }
-  else
-    return make_error_code(errc::not_supported);
-
-  pOutput.clear();
-  return llvm::make_error_code(llvm::errc::success);
-}
-
diff --git a/lib/LD/ELFFileFormat.cpp b/lib/LD/ELFFileFormat.cpp
index b4792b5..067f48c 100644
--- a/lib/LD/ELFFileFormat.cpp
+++ b/lib/LD/ELFFileFormat.cpp
@@ -59,7 +59,8 @@
     f_pStabStr(NULL),
     f_pStack(NULL),
     f_pStackNote(NULL),
-    f_pDataRelRoLocal(NULL) {
+    f_pDataRelRoLocal(NULL),
+    f_pGNUHashTab(NULL) {
 
 }
 
diff --git a/lib/LD/ELFObjectReader.cpp b/lib/LD/ELFObjectReader.cpp
index a87b5b8..b26bb1f 100644
--- a/lib/LD/ELFObjectReader.cpp
+++ b/lib/LD/ELFObjectReader.cpp
@@ -42,6 +42,9 @@
   if (pConfig.targets().is32Bits() && pConfig.targets().isLittleEndian()) {
     m_pELFReader = new ELFReader<32, true>(pBackend);
   }
+  else if (pConfig.targets().is64Bits() && pConfig.targets().isLittleEndian()) {
+    m_pELFReader = new ELFReader<64, true>(pBackend);
+  }
 
   m_pEhFrameReader = new EhFrameReader();
 }
diff --git a/lib/LD/ELFObjectWriter.cpp b/lib/LD/ELFObjectWriter.cpp
index e9b7b99..f31b9fb 100644
--- a/lib/LD/ELFObjectWriter.cpp
+++ b/lib/LD/ELFObjectWriter.cpp
@@ -12,10 +12,29 @@
 #include <mcld/LinkerConfig.h>
 #include <mcld/Target/GNULDBackend.h>
 #include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/ADT/SizeTraits.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/Fragment/AlignFragment.h>
+#include <mcld/Fragment/FillFragment.h>
+#include <mcld/Fragment/RegionFragment.h>
+#include <mcld/Fragment/Stub.h>
+#include <mcld/Fragment/NullFragment.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/LD/ELFSegment.h>
+#include <mcld/LD/ELFSegmentFactory.h>
+#include <mcld/LD/RelocData.h>
+#include <mcld/LD/EhFrame.h>
 
+#include <llvm/Support/ErrorHandling.h>
 #include <llvm/Support/system_error.h>
+#include <llvm/Support/ELF.h>
+#include <llvm/Support/Casting.h>
 
 using namespace llvm;
+using namespace llvm::ELF;
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
@@ -23,112 +42,622 @@
 //===----------------------------------------------------------------------===//
 ELFObjectWriter::ELFObjectWriter(GNULDBackend& pBackend,
                                  const LinkerConfig& pConfig)
-  : ObjectWriter(pBackend), ELFWriter(pBackend),
-    m_Config(pConfig) {
+  : ObjectWriter(), m_Backend(pBackend), m_Config(pConfig)
+{
 }
 
 ELFObjectWriter::~ELFObjectWriter()
 {
 }
 
+void ELFObjectWriter::writeSection(MemoryArea& pOutput, LDSection *section)
+{
+  MemoryRegion* region;
+  // Request output region
+  switch (section->kind()) {
+  case LDFileFormat::Note:
+    if (section->getSectionData() == NULL)
+      return;
+    // Fall through
+  case LDFileFormat::Regular:
+  case LDFileFormat::Relocation:
+  case LDFileFormat::Target:
+  case LDFileFormat::Debug:
+  case LDFileFormat::GCCExceptTable:
+  case LDFileFormat::EhFrame: {
+    region = pOutput.request(section->offset(), section->size());
+    if (NULL == region) {
+      llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section `") +
+                               llvm::Twine(section->name()) +
+                               llvm::Twine("'.\n"));
+    }
+    break;
+  }
+  case LDFileFormat::Null:
+  case LDFileFormat::NamePool:
+  case LDFileFormat::BSS:
+  case LDFileFormat::MetaData:
+  case LDFileFormat::Version:
+  case LDFileFormat::EhFrameHdr:
+  case LDFileFormat::StackNote:
+    // Ignore these sections
+    return;
+  default:
+    llvm::errs() << "WARNING: unsupported section kind: "
+                 << section->kind()
+                 << " of section "
+                 << section->name()
+                 << ".\n";
+    return;
+  }
+
+  // Write out sections with data
+  switch(section->kind()) {
+  case LDFileFormat::GCCExceptTable:
+  case LDFileFormat::EhFrame:
+  case LDFileFormat::Regular:
+  case LDFileFormat::Debug:
+  case LDFileFormat::Note:
+    // FIXME: if optimization of exception handling sections is enabled,
+    // then we should emit these sections by the other way.
+    emitSectionData(*section, *region);
+    break;
+  case LDFileFormat::Relocation:
+    emitRelocation(m_Config, *section, *region);
+    break;
+  case LDFileFormat::Target:
+    target().emitSectionData(*section, *region);
+    break;
+  default:
+    llvm_unreachable("invalid section kind");
+  }
+}
+
 llvm::error_code ELFObjectWriter::writeObject(Module& pModule,
                                               MemoryArea& pOutput)
 {
-  // Write out name pool sections: .symtab, .strtab
-  target().emitRegNamePools(pModule, pOutput);
+  bool is_dynobj = m_Config.codeGenType() == LinkerConfig::DynObj;
+  bool is_exec = m_Config.codeGenType() == LinkerConfig::Exec;
+  bool is_binary = m_Config.codeGenType() == LinkerConfig::Binary;
+  bool is_object = m_Config.codeGenType() == LinkerConfig::Object;
 
-  // Write out regular ELF sections
-  Module::iterator sect, sectEnd = pModule.end();
-  for (sect = pModule.begin(); sect != sectEnd; ++sect) {
-    MemoryRegion* region = NULL;
-    // request output region
-    switch((*sect)->kind()) {
-      case LDFileFormat::Note:
-        if ((*sect)->getSectionData() == NULL)
-          continue;
-        // Fall through
-      case LDFileFormat::Regular:
-      case LDFileFormat::Relocation:
-      case LDFileFormat::Target:
-      case LDFileFormat::Debug:
-      case LDFileFormat::GCCExceptTable:
-      case LDFileFormat::EhFrame: {
-        region = pOutput.request((*sect)->offset(), (*sect)->size());
-        if (NULL == region) {
-          llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section `") +
-                                   llvm::Twine((*sect)->name()) +
-                                   llvm::Twine("'.\n"));
-        }
-        break;
-      }
-      case LDFileFormat::Null:
-      case LDFileFormat::NamePool:
-      case LDFileFormat::BSS:
-      case LDFileFormat::MetaData:
-      case LDFileFormat::Version:
-      case LDFileFormat::EhFrameHdr:
-      case LDFileFormat::StackNote:
-        // ignore these sections
-        continue;
-      default: {
-        llvm::errs() << "WARNING: unsupported section kind: "
-                     << (*sect)->kind()
-                     << " of section "
-                     << (*sect)->name()
-                     << ".\n";
-        continue;
+  assert(is_dynobj || is_exec || is_binary || is_object);
+
+  if (is_dynobj || is_exec) {
+    // Write out the interpreter section: .interp
+    target().emitInterp(pOutput);
+
+    // Write out name pool sections: .dynsym, .dynstr, .hash
+    target().emitDynNamePools(pModule, pOutput);
+  }
+
+  if (is_object || is_dynobj || is_exec) {
+    // Write out name pool sections: .symtab, .strtab
+    target().emitRegNamePools(pModule, pOutput);
+  }
+
+  if (is_binary) {
+    // Iterate over the loadable segments and write the corresponding sections
+    ELFSegmentFactory::iterator seg, segEnd = target().elfSegmentTable().end();
+
+    for (seg = target().elfSegmentTable().begin(); seg != segEnd; ++seg) {
+      if (llvm::ELF::PT_LOAD == (*seg).type()) {
+        ELFSegment::sect_iterator sect, sectEnd = (*seg).end();
+        for (sect = (*seg).begin(); sect != sectEnd; ++sect)
+          writeSection(pOutput, *sect);
       }
     }
+  } else {
+    // Write out regular ELF sections
+    Module::iterator sect, sectEnd = pModule.end();
+    for (sect = pModule.begin(); sect != sectEnd; ++sect)
+      writeSection(pOutput, *sect);
 
-    // write out sections with data
-    switch((*sect)->kind()) {
-      case LDFileFormat::Regular:
-      case LDFileFormat::Debug:
-      case LDFileFormat::GCCExceptTable:
-      case LDFileFormat::Note:
-      case LDFileFormat::EhFrame: {
-        // FIXME: if optimization of exception handling sections is enabled,
-        // then we should emit these sections by the other way.
-        emitSectionData(**sect, *region);
-        break;
-      }
-      case LDFileFormat::Relocation:
-        emitRelocation(m_Config, **sect, *region);
-        break;
-      case LDFileFormat::Target:
-        target().emitSectionData(**sect, *region);
-        break;
-      default:
-        continue;
+    emitShStrTab(target().getOutputFormat()->getShStrTab(), pModule, pOutput);
+
+    if (m_Config.targets().is32Bits()) {
+      // Write out ELF header
+      // Write out section header table
+      writeELFHeader<32>(m_Config, pModule, pOutput);
+      if (is_dynobj || is_exec)
+        emitProgramHeader<32>(pOutput);
+
+      emitSectionHeader<32>(pModule, m_Config, pOutput);
     }
-  } // end of for loop
+    else if (m_Config.targets().is64Bits()) {
+      // Write out ELF header
+      // Write out section header table
+      writeELFHeader<64>(m_Config, pModule, pOutput);
+      if (is_dynobj || is_exec)
+        emitProgramHeader<64>(pOutput);
 
-  emitELFShStrTab(target().getOutputFormat()->getShStrTab(),
-                  pModule,
-                  pOutput);
-
-  if (m_Config.targets().is32Bits()) {
-    // Write out ELF header
-    // Write out section header table
-    writeELF32Header(m_Config,
-                     pModule,
-                     pOutput);
-
-    emitELF32SectionHeader(pModule, m_Config, pOutput);
+      emitSectionHeader<64>(pModule, m_Config, pOutput);
+    }
+    else
+      return make_error_code(errc::not_supported);
   }
-  else if (m_Config.targets().is64Bits()) {
-    // Write out ELF header
-    // Write out section header table
-    writeELF64Header(m_Config,
-                     pModule,
-                     pOutput);
-
-    emitELF64SectionHeader(pModule, m_Config, pOutput);
-  }
-  else
-    return make_error_code(errc::not_supported);
 
   pOutput.clear();
   return llvm::make_error_code(llvm::errc::success);
 }
 
+// writeELFHeader - emit ElfXX_Ehdr
+template<size_t SIZE>
+void ELFObjectWriter::writeELFHeader(const LinkerConfig& pConfig,
+                                     const Module& pModule,
+                                     MemoryArea& pOutput) const
+{
+  typedef typename ELFSizeTraits<SIZE>::Ehdr ElfXX_Ehdr;
+  typedef typename ELFSizeTraits<SIZE>::Shdr ElfXX_Shdr;
+  typedef typename ELFSizeTraits<SIZE>::Phdr ElfXX_Phdr;
+
+  // ELF header must start from 0x0
+  MemoryRegion *region = pOutput.request(0, sizeof(ElfXX_Ehdr));
+  ElfXX_Ehdr* header = (ElfXX_Ehdr*)region->start();
+
+  memcpy(header->e_ident, ElfMagic, EI_MAG3+1);
+
+  header->e_ident[EI_CLASS]      = (SIZE == 32) ? ELFCLASS32 : ELFCLASS64;
+  header->e_ident[EI_DATA]       = pConfig.targets().isLittleEndian()?
+                                       ELFDATA2LSB : ELFDATA2MSB;
+  header->e_ident[EI_VERSION]    = target().getInfo().ELFVersion();
+  header->e_ident[EI_OSABI]      = target().getInfo().OSABI();
+  header->e_ident[EI_ABIVERSION] = target().getInfo().ABIVersion();
+
+  // FIXME: add processor-specific and core file types.
+  switch(pConfig.codeGenType()) {
+    case LinkerConfig::Object:
+      header->e_type = ET_REL;
+      break;
+    case LinkerConfig::DynObj:
+      header->e_type = ET_DYN;
+      break;
+    case LinkerConfig::Exec:
+      header->e_type = ET_EXEC;
+      break;
+    default:
+      llvm::errs() << "unspported output file type: " << pConfig.codeGenType() << ".\n";
+      header->e_type = ET_NONE;
+  }
+  header->e_machine   = target().getInfo().machine();
+  header->e_version   = header->e_ident[EI_VERSION];
+  header->e_entry     = getEntryPoint(pConfig, pModule);
+
+  if (LinkerConfig::Object != pConfig.codeGenType())
+    header->e_phoff   = sizeof(ElfXX_Ehdr);
+  else
+    header->e_phoff   = 0x0;
+
+  header->e_shoff     = getLastStartOffset<SIZE>(pModule);
+  header->e_flags     = target().getInfo().flags();
+  header->e_ehsize    = sizeof(ElfXX_Ehdr);
+  header->e_phentsize = sizeof(ElfXX_Phdr);
+  header->e_phnum     = target().numOfSegments();
+  header->e_shentsize = sizeof(ElfXX_Shdr);
+  header->e_shnum     = pModule.size();
+  header->e_shstrndx  = pModule.getSection(".shstrtab")->index();
+}
+
+/// getEntryPoint
+uint64_t ELFObjectWriter::getEntryPoint(const LinkerConfig& pConfig,
+                                        const Module& pModule) const
+{
+  llvm::StringRef entry_name;
+  if (pConfig.options().hasEntry())
+    entry_name = pConfig.options().entry();
+  else
+    entry_name = target().getInfo().entry();
+
+  uint64_t result = 0x0;
+
+  bool issue_warning = (pConfig.options().hasEntry() &&
+                        LinkerConfig::Object != pConfig.codeGenType() &&
+                        LinkerConfig::DynObj != pConfig.codeGenType());
+
+  const LDSymbol* entry_symbol = pModule.getNamePool().findSymbol(entry_name);
+
+  // found the symbol
+  if (NULL != entry_symbol) {
+    if (entry_symbol->desc() != ResolveInfo::Define && issue_warning) {
+      llvm::errs() << "WARNING: entry symbol '"
+                   << entry_symbol->name()
+                   << "' exists but is not defined.\n";
+    }
+    result = entry_symbol->value();
+  }
+  // not in the symbol pool
+  else {
+    // We should parse entry as a number.
+    // @ref GNU ld manual, Options -e. e.g., -e 0x1000.
+    char* endptr;
+    result = strtoull(entry_name.data(), &endptr, 0);
+    if (*endptr != '\0') {
+      if (issue_warning) {
+        llvm::errs() << "cannot find entry symbol '"
+                     << entry_name.data()
+                     << "'.\n";
+      }
+      result = 0x0;
+    }
+  }
+  return result;
+}
+
+// emitSectionHeader - emit ElfXX_Shdr
+template<size_t SIZE>
+void ELFObjectWriter::emitSectionHeader(const Module& pModule,
+                                        const LinkerConfig& pConfig,
+                                        MemoryArea& pOutput) const
+{
+  typedef typename ELFSizeTraits<SIZE>::Shdr ElfXX_Shdr;
+
+  // emit section header
+  unsigned int sectNum = pModule.size();
+  unsigned int header_size = sizeof(ElfXX_Shdr) * sectNum;
+  MemoryRegion* region = pOutput.request(getLastStartOffset<SIZE>(pModule),
+                                         header_size);
+  ElfXX_Shdr* shdr = (ElfXX_Shdr*)region->start();
+
+  // Iterate the SectionTable in LDContext
+  unsigned int sectIdx = 0;
+  unsigned int shstridx = 0; // NULL section has empty name
+  for (; sectIdx < sectNum; ++sectIdx) {
+    const LDSection *ld_sect   = pModule.getSectionTable().at(sectIdx);
+    shdr[sectIdx].sh_name      = shstridx;
+    shdr[sectIdx].sh_type      = ld_sect->type();
+    shdr[sectIdx].sh_flags     = ld_sect->flag();
+    shdr[sectIdx].sh_addr      = ld_sect->addr();
+    shdr[sectIdx].sh_offset    = ld_sect->offset();
+    shdr[sectIdx].sh_size      = ld_sect->size();
+    shdr[sectIdx].sh_addralign = ld_sect->align();
+    shdr[sectIdx].sh_entsize   = getSectEntrySize<SIZE>(*ld_sect);
+    shdr[sectIdx].sh_link      = getSectLink(*ld_sect, pConfig);
+    shdr[sectIdx].sh_info      = getSectInfo(*ld_sect);
+
+    // adjust strshidx
+    shstridx += ld_sect->name().size() + 1;
+  }
+}
+
+// emitProgramHeader - emit ElfXX_Phdr
+template<size_t SIZE>
+void ELFObjectWriter::emitProgramHeader(MemoryArea& pOutput) const
+{
+  typedef typename ELFSizeTraits<SIZE>::Ehdr ElfXX_Ehdr;
+  typedef typename ELFSizeTraits<SIZE>::Phdr ElfXX_Phdr;
+
+  uint64_t start_offset, phdr_size;
+
+  start_offset = sizeof(ElfXX_Ehdr);
+  phdr_size = sizeof(ElfXX_Phdr);
+  // Program header must start directly after ELF header
+  MemoryRegion *region = pOutput.request(start_offset,
+                                         target().numOfSegments() * phdr_size);
+
+  ElfXX_Phdr* phdr = (ElfXX_Phdr*)region->start();
+
+  // Iterate the elf segment table in GNULDBackend
+  size_t index = 0;
+  ELFSegmentFactory::const_iterator seg = target().elfSegmentTable().begin(),
+                                 segEnd = target().elfSegmentTable().end();
+  for (; seg != segEnd; ++seg, ++index) {
+    phdr[index].p_type   = (*seg).type();
+    phdr[index].p_flags  = (*seg).flag();
+    phdr[index].p_offset = (*seg).offset();
+    phdr[index].p_vaddr  = (*seg).vaddr();
+    phdr[index].p_paddr  = (*seg).paddr();
+    phdr[index].p_filesz = (*seg).filesz();
+    phdr[index].p_memsz  = (*seg).memsz();
+    phdr[index].p_align  = (*seg).align();
+  }
+}
+
+/// emitShStrTab - emit section string table
+void
+ELFObjectWriter::emitShStrTab(const LDSection& pShStrTab,
+                              const Module& pModule,
+                              MemoryArea& pOutput)
+{
+  // write out data
+  MemoryRegion* region = pOutput.request(pShStrTab.offset(), pShStrTab.size());
+  unsigned char* data = region->start();
+  size_t shstrsize = 0;
+  Module::const_iterator section, sectEnd = pModule.end();
+  for (section = pModule.begin(); section != sectEnd; ++section) {
+    strcpy((char*)(data + shstrsize), (*section)->name().data());
+    shstrsize += (*section)->name().size() + 1;
+  }
+}
+
+/// emitSectionData
+void
+ELFObjectWriter::emitSectionData(const LDSection& pSection,
+                                 MemoryRegion& pRegion) const
+{
+  const SectionData* sd = NULL;
+  switch (pSection.kind()) {
+    case LDFileFormat::Relocation:
+      assert(pSection.hasRelocData());
+      return;
+    case LDFileFormat::EhFrame:
+      assert(pSection.hasEhFrame());
+      sd = &pSection.getEhFrame()->getSectionData();
+      break;
+    default:
+      assert(pSection.hasSectionData());
+      sd = pSection.getSectionData();
+      break;
+  }
+  emitSectionData(*sd, pRegion);
+}
+
+/// emitRelocation
+void ELFObjectWriter::emitRelocation(const LinkerConfig& pConfig,
+                                     const LDSection& pSection,
+                                     MemoryRegion& pRegion) const
+{
+  const RelocData* sect_data = pSection.getRelocData();
+  assert(NULL != sect_data && "SectionData is NULL in emitRelocation!");
+
+  if (pSection.type() == SHT_REL) {
+    if (pConfig.targets().is32Bits())
+      emitRel<32>(pConfig, *sect_data, pRegion);
+    else if (pConfig.targets().is64Bits())
+      emitRel<64>(pConfig, *sect_data, pRegion);
+    else {
+      fatal(diag::unsupported_bitclass) << pConfig.targets().triple().str()
+                                        << pConfig.targets().bitclass();
+    }
+  } else if (pSection.type() == SHT_RELA) {
+    if (pConfig.targets().is32Bits())
+      emitRela<32>(pConfig, *sect_data, pRegion);
+    else if (pConfig.targets().is64Bits())
+      emitRela<64>(pConfig, *sect_data, pRegion);
+    else {
+      fatal(diag::unsupported_bitclass) << pConfig.targets().triple().str()
+                                        << pConfig.targets().bitclass();
+    }
+  } else
+    llvm::report_fatal_error("unsupported relocation section type!");
+}
+
+
+// emitRel - emit ElfXX_Rel
+template<size_t SIZE>
+void ELFObjectWriter::emitRel(const LinkerConfig& pConfig,
+                              const RelocData& pRelocData,
+                              MemoryRegion& pRegion) const
+{
+  typedef typename ELFSizeTraits<SIZE>::Rel  ElfXX_Rel;
+  typedef typename ELFSizeTraits<SIZE>::Addr ElfXX_Addr;
+  typedef typename ELFSizeTraits<SIZE>::Word ElfXX_Word;
+
+  ElfXX_Rel* rel = reinterpret_cast<ElfXX_Rel*>(pRegion.start());
+
+  const Relocation* relocation = 0;
+  const FragmentRef* frag_ref = 0;
+
+  for (RelocData::const_iterator it = pRelocData.begin(),
+       ie = pRelocData.end(); it != ie; ++it, ++rel) {
+
+    relocation = &(llvm::cast<Relocation>(*it));
+    frag_ref = &(relocation->targetRef());
+
+    if(LinkerConfig::DynObj == pConfig.codeGenType() ||
+       LinkerConfig::Exec == pConfig.codeGenType()) {
+      rel->r_offset = static_cast<ElfXX_Addr>(
+                      frag_ref->frag()->getParent()->getSection().addr() +
+                      frag_ref->getOutputOffset());
+    }
+    else {
+      rel->r_offset = static_cast<ElfXX_Addr>(frag_ref->getOutputOffset());
+    }
+    ElfXX_Word Index;
+    if( relocation->symInfo() == NULL )
+      Index = 0;
+    else
+      Index = static_cast<ElfXX_Word>(
+              target().getSymbolIdx(relocation->symInfo()->outSymbol()));
+
+    rel->setSymbolAndType(Index, relocation->type());
+  }
+}
+
+// emitRela - emit ElfXX_Rela
+template<size_t SIZE>
+void ELFObjectWriter::emitRela(const LinkerConfig& pConfig,
+                               const RelocData& pRelocData,
+                               MemoryRegion& pRegion) const
+{
+  typedef typename ELFSizeTraits<SIZE>::Rela ElfXX_Rela;
+  typedef typename ELFSizeTraits<SIZE>::Addr ElfXX_Addr;
+  typedef typename ELFSizeTraits<SIZE>::Word ElfXX_Word;
+
+  ElfXX_Rela* rel = reinterpret_cast<ElfXX_Rela*>(pRegion.start());
+
+  const Relocation* relocation = 0;
+  const FragmentRef* frag_ref = 0;
+
+  for (RelocData::const_iterator it = pRelocData.begin(),
+       ie = pRelocData.end(); it != ie; ++it, ++rel) {
+
+    relocation = &(llvm::cast<Relocation>(*it));
+    frag_ref = &(relocation->targetRef());
+
+    if(LinkerConfig::DynObj == pConfig.codeGenType() ||
+       LinkerConfig::Exec == pConfig.codeGenType()) {
+      rel->r_offset = static_cast<ElfXX_Addr>(
+                      frag_ref->frag()->getParent()->getSection().addr() +
+                      frag_ref->getOutputOffset());
+    }
+    else {
+      rel->r_offset = static_cast<ElfXX_Addr>(frag_ref->getOutputOffset());
+    }
+
+    ElfXX_Word Index;
+    if( relocation->symInfo() == NULL )
+      Index = 0;
+    else
+      Index = static_cast<ElfXX_Word>(
+              target().getSymbolIdx(relocation->symInfo()->outSymbol()));
+
+    rel->setSymbolAndType(Index, relocation->type());
+    rel->r_addend = relocation->addend();
+  }
+}
+
+
+/// getSectEntrySize - compute ElfXX_Shdr::sh_entsize
+template<size_t SIZE>
+uint64_t ELFObjectWriter::getSectEntrySize(const LDSection& pSection) const
+{
+  typedef typename ELFSizeTraits<SIZE>::Word ElfXX_Word;
+  typedef typename ELFSizeTraits<SIZE>::Sym  ElfXX_Sym;
+  typedef typename ELFSizeTraits<SIZE>::Rel  ElfXX_Rel;
+  typedef typename ELFSizeTraits<SIZE>::Rela ElfXX_Rela;
+  typedef typename ELFSizeTraits<SIZE>::Dyn  ElfXX_Dyn;
+
+  if (llvm::ELF::SHT_DYNSYM == pSection.type() ||
+      llvm::ELF::SHT_SYMTAB == pSection.type())
+    return sizeof(ElfXX_Sym);
+  if (llvm::ELF::SHT_REL == pSection.type())
+    return sizeof(ElfXX_Rel);
+  if (llvm::ELF::SHT_RELA == pSection.type())
+    return sizeof(ElfXX_Rela);
+  if (llvm::ELF::SHT_HASH     == pSection.type() ||
+      llvm::ELF::SHT_GNU_HASH == pSection.type())
+    return sizeof(ElfXX_Word);
+  if (llvm::ELF::SHT_DYNAMIC == pSection.type())
+    return sizeof(ElfXX_Dyn);
+  return 0x0;
+}
+
+/// getSectLink - compute ElfXX_Shdr::sh_link
+uint64_t ELFObjectWriter::getSectLink(const LDSection& pSection,
+                                      const LinkerConfig& pConfig) const
+{
+  if (llvm::ELF::SHT_SYMTAB == pSection.type())
+    return target().getOutputFormat()->getStrTab().index();
+  if (llvm::ELF::SHT_DYNSYM == pSection.type())
+    return target().getOutputFormat()->getDynStrTab().index();
+  if (llvm::ELF::SHT_DYNAMIC == pSection.type())
+    return target().getOutputFormat()->getDynStrTab().index();
+  if (llvm::ELF::SHT_HASH     == pSection.type() ||
+      llvm::ELF::SHT_GNU_HASH == pSection.type())
+    return target().getOutputFormat()->getDynSymTab().index();
+  if (llvm::ELF::SHT_REL == pSection.type() ||
+      llvm::ELF::SHT_RELA == pSection.type()) {
+    if (LinkerConfig::Object == pConfig.codeGenType())
+      return target().getOutputFormat()->getSymTab().index();
+    else
+      return target().getOutputFormat()->getDynSymTab().index();
+  }
+  // FIXME: currently we link ARM_EXIDX section to output text section here
+  if (llvm::ELF::SHT_ARM_EXIDX == pSection.type())
+    return target().getOutputFormat()->getText().index();
+  return llvm::ELF::SHN_UNDEF;
+}
+
+/// getSectInfo - compute ElfXX_Shdr::sh_info
+uint64_t ELFObjectWriter::getSectInfo(const LDSection& pSection) const
+{
+  if (llvm::ELF::SHT_SYMTAB == pSection.type() ||
+      llvm::ELF::SHT_DYNSYM == pSection.type())
+    return pSection.getInfo();
+
+  if (llvm::ELF::SHT_REL == pSection.type() ||
+      llvm::ELF::SHT_RELA == pSection.type()) {
+    const LDSection* info_link = pSection.getLink();
+    if (NULL != info_link)
+      return info_link->index();
+  }
+
+  return 0x0;
+}
+
+/// getLastStartOffset
+template<>
+uint64_t ELFObjectWriter::getLastStartOffset<32>(const Module& pModule) const
+{
+  const LDSection* lastSect = pModule.back();
+  assert(lastSect != NULL);
+  return Align<32>(lastSect->offset() + lastSect->size());
+}
+
+/// getLastStartOffset
+template<>
+uint64_t ELFObjectWriter::getLastStartOffset<64>(const Module& pModule) const
+{
+  const LDSection* lastSect = pModule.back();
+  assert(lastSect != NULL);
+  return Align<64>(lastSect->offset() + lastSect->size());
+}
+
+/// emitSectionData
+void ELFObjectWriter::emitSectionData(const SectionData& pSD,
+                                      MemoryRegion& pRegion) const
+{
+  SectionData::const_iterator fragIter, fragEnd = pSD.end();
+  size_t cur_offset = 0;
+  for (fragIter = pSD.begin(); fragIter != fragEnd; ++fragIter) {
+    size_t size = fragIter->size();
+    switch(fragIter->getKind()) {
+      case Fragment::Region: {
+        const RegionFragment& region_frag = llvm::cast<RegionFragment>(*fragIter);
+        const uint8_t* from = region_frag.getRegion().start();
+        memcpy(pRegion.getBuffer(cur_offset), from, size);
+        break;
+      }
+      case Fragment::Alignment: {
+        // TODO: emit values with different sizes (> 1 byte), and emit nops
+        const AlignFragment& align_frag = llvm::cast<AlignFragment>(*fragIter);
+        uint64_t count = size / align_frag.getValueSize();
+        switch (align_frag.getValueSize()) {
+          case 1u:
+            std::memset(pRegion.getBuffer(cur_offset),
+                        align_frag.getValue(),
+                        count);
+            break;
+          default:
+            llvm::report_fatal_error("unsupported value size for align fragment emission yet.\n");
+            break;
+        }
+        break;
+      }
+      case Fragment::Fillment: {
+        const FillFragment& fill_frag = llvm::cast<FillFragment>(*fragIter);
+        if (0 == size ||
+            0 == fill_frag.getValueSize() ||
+            0 == fill_frag.size()) {
+          // ignore virtual fillment
+          break;
+        }
+
+        uint64_t num_tiles = fill_frag.size() / fill_frag.getValueSize();
+        for (uint64_t i = 0; i != num_tiles; ++i) {
+          std::memset(pRegion.getBuffer(cur_offset),
+                      fill_frag.getValue(),
+                      fill_frag.getValueSize());
+        }
+        break;
+      }
+      case Fragment::Stub: {
+        const Stub& stub_frag = llvm::cast<Stub>(*fragIter);
+        memcpy(pRegion.getBuffer(cur_offset), stub_frag.getContent(), size);
+        break;
+      }
+      case Fragment::Null: {
+        assert(0x0 == size);
+        break;
+      }
+      case Fragment::Target:
+        llvm::report_fatal_error("Target fragment should not be in a regular section.\n");
+        break;
+      default:
+        llvm::report_fatal_error("invalid fragment should not be in a regular section.\n");
+        break;
+    }
+    cur_offset += size;
+  }
+}
+
diff --git a/lib/LD/ELFReader.cpp b/lib/LD/ELFReader.cpp
index 84ad17b..4057ac8 100644
--- a/lib/LD/ELFReader.cpp
+++ b/lib/LD/ELFReader.cpp
@@ -13,7 +13,6 @@
 #include <mcld/LD/EhFrame.h>
 #include <mcld/LD/SectionData.h>
 #include <mcld/Target/GNULDBackend.h>
-#include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/MsgHandling.h>
 #include <mcld/Object/ObjectBuilder.h>
@@ -25,140 +24,11 @@
 #include <llvm/Support/ELF.h>
 #include <llvm/Support/Host.h>
 
+#include <iostream>
+
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
-// ELFReaderIF
-//===----------------------------------------------------------------------===//
-/// getSymType
-ResolveInfo::Type ELFReaderIF::getSymType(uint8_t pInfo, uint16_t pShndx) const
-{
-  ResolveInfo::Type result = static_cast<ResolveInfo::Type>(pInfo & 0xF);
-  if (llvm::ELF::SHN_ABS == pShndx && ResolveInfo::Section == result) {
-    // In Mips, __gp_disp is a special section symbol. Its name comes from
-    // .strtab, not .shstrtab. However, it is unique. Only it is also a ABS
-    // symbol. So here is a tricky to identify __gp_disp and convert it to
-    // Object symbol.
-    return ResolveInfo::Object;
-  }
-
-  return result;
-}
-
-/// getSymDesc
-ResolveInfo::Desc ELFReaderIF::getSymDesc(uint16_t pShndx, const Input& pInput) const
-{
-  if (pShndx == llvm::ELF::SHN_UNDEF)
-    return ResolveInfo::Undefined;
-
-  if (pShndx < llvm::ELF::SHN_LORESERVE) {
-    // an ELF symbol defined in a section which we are not including
-    // must be treated as an Undefined.
-    // @ref Google gold linker: symtab.cc: 1086
-    if (NULL == pInput.context()->getSection(pShndx) ||
-        LDFileFormat::Ignore == pInput.context()->getSection(pShndx)->kind())
-      return ResolveInfo::Undefined;
-    return ResolveInfo::Define;
-  }
-
-  if (pShndx == llvm::ELF::SHN_ABS)
-    return ResolveInfo::Define;
-
-  if (pShndx == llvm::ELF::SHN_COMMON)
-    return ResolveInfo::Common;
-
-  // FIXME: ELF weak alias should be ResolveInfo::Indirect
-  return ResolveInfo::NoneDesc;
-}
-
-/// getSymBinding
-ResolveInfo::Binding
-ELFReaderIF::getSymBinding(uint8_t pBinding, uint16_t pShndx, uint8_t pVis) const
-{
-
-  // TODO:
-  // if --just-symbols option is enabled, the symbol must covert to Absolute
-
-  switch(pBinding) {
-  case llvm::ELF::STB_LOCAL:
-    return ResolveInfo::Local;
-  case llvm::ELF::STB_GLOBAL:
-    return ResolveInfo::Global;
-  case llvm::ELF::STB_WEAK:
-    return ResolveInfo::Weak;
-  }
-
-  if (pShndx == llvm::ELF::SHN_ABS)
-    return ResolveInfo::Absolute;
-
-  return ResolveInfo::NoneBinding;
-}
-
-/// getSymFragmentRef
-FragmentRef*
-ELFReaderIF::getSymFragmentRef(Input& pInput,
-                               uint16_t pShndx,
-                               uint32_t pOffset) const
-{
-
-  if (Input::DynObj == pInput.type())
-    return FragmentRef::Null();
-
-  if (pShndx == llvm::ELF::SHN_UNDEF)
-    return FragmentRef::Null();
-
-  if (pShndx >= llvm::ELF::SHN_LORESERVE) // including ABS and COMMON
-    return FragmentRef::Null();
-
-  LDSection* sect_hdr = pInput.context()->getSection(pShndx);
-
-  if (NULL == sect_hdr)
-    unreachable(diag::unreachable_invalid_section_idx) << pShndx
-                                                       << pInput.path().native();
-
-  if (LDFileFormat::Ignore == sect_hdr->kind())
-    return FragmentRef::Null();
-
-  if (LDFileFormat::Group == sect_hdr->kind())
-    return FragmentRef::Null();
-
-  return FragmentRef::Create(*sect_hdr, pOffset);
-}
-
-/// getSymVisibility
-ResolveInfo::Visibility
-ELFReaderIF::getSymVisibility(uint8_t pVis) const
-{
-  return static_cast<ResolveInfo::Visibility>(pVis);
-}
-
-/// getSymValue - get the section offset of the symbol.
-uint64_t ELFReaderIF::getSymValue(uint64_t pValue,
-                                  uint16_t pShndx,
-                                  const Input& pInput) const
-{
-  if (Input::Object == pInput.type()) {
-    // In relocatable files, st_value holds alignment constraints for a symbol
-    // whose section index is SHN_COMMON
-    if (pShndx == llvm::ELF::SHN_COMMON || pShndx == llvm::ELF::SHN_ABS) {
-      return pValue;
-    }
-
-    // In relocatable files, st_value holds a section offset for a defined symbol.
-    // TODO:
-    // if --just-symbols option are enabled, convert the value from section offset
-    // to virtual address by adding input section's virtual address.
-    // The section's virtual address in relocatable files is normally zero, but
-    // people can use link script to change it.
-    return pValue;
-  }
-
-  // In executable and shared object files, st_value holds a virtual address.
-  // the virtual address is useless during linking.
-  return 0x0;
-}
-
-//===----------------------------------------------------------------------===//
 // ELFReader<32, true>
 //===----------------------------------------------------------------------===//
 /// constructor
@@ -413,8 +283,8 @@
 
   uint32_t shoff     = 0x0;
   uint16_t shentsize = 0x0;
-  uint16_t shnum     = 0x0;
-  uint16_t shstrtab  = 0x0;
+  uint32_t shnum     = 0x0;
+  uint32_t shstrtab  = 0x0;
 
   if (llvm::sys::isLittleEndianHost()) {
     shoff     = ehdr->e_shoff;
@@ -433,11 +303,8 @@
   if (0x0 == shoff)
     return true;
 
-  MemoryRegion* shdr_region = pInput.memArea()->request(
-                                 pInput.fileOffset() + shoff, shnum*shentsize);
-  llvm::ELF::Elf32_Shdr* shdrTab =
-                reinterpret_cast<llvm::ELF::Elf32_Shdr*>(shdr_region->start());
-
+  llvm::ELF::Elf32_Shdr *shdr = NULL;
+  MemoryRegion* shdr_region = NULL;
   uint32_t sh_name      = 0x0;
   uint32_t sh_type      = 0x0;
   uint32_t sh_flags     = 0x0;
@@ -447,8 +314,37 @@
   uint32_t sh_info      = 0x0;
   uint32_t sh_addralign = 0x0;
 
+  // if shnum and shstrtab overflow, the actual values are in the 1st shdr
+  if (shnum == llvm::ELF::SHN_UNDEF || shstrtab == llvm::ELF::SHN_XINDEX) {
+    shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
+                                            shentsize);
+    shdr = reinterpret_cast<llvm::ELF::Elf32_Shdr*>(shdr_region->start());
+
+    if (llvm::sys::isLittleEndianHost()) {
+      sh_size = shdr->sh_size;
+      sh_link = shdr->sh_link;
+    }
+    else {
+      sh_size = mcld::bswap32(shdr->sh_size);
+      sh_link = mcld::bswap32(shdr->sh_link);
+    }
+    pInput.memArea()->release(shdr_region);
+
+    if (shnum == llvm::ELF::SHN_UNDEF)
+      shnum = sh_size;
+    if (shstrtab == llvm::ELF::SHN_XINDEX)
+      shstrtab = sh_link;
+
+    shoff += shentsize;
+  }
+
+  shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
+                                          shnum * shentsize);
+  llvm::ELF::Elf32_Shdr * shdrTab =
+    reinterpret_cast<llvm::ELF::Elf32_Shdr*>(shdr_region->start());
+
   // get .shstrtab first
-  llvm::ELF::Elf32_Shdr* shdr = &shdrTab[shstrtab];
+  shdr = &shdrTab[shstrtab];
   if (llvm::sys::isLittleEndianHost()) {
     sh_offset = shdr->sh_offset;
     sh_size   = shdr->sh_size;
@@ -641,3 +537,512 @@
   return true;
 }
 
+//===----------------------------------------------------------------------===//
+// ELFReader<64, true>
+//===----------------------------------------------------------------------===//
+/// constructor
+ELFReader<64, true>::ELFReader(GNULDBackend& pBackend)
+  : ELFReaderIF(pBackend) {
+}
+
+/// destructor
+ELFReader<64, true>::~ELFReader()
+{
+}
+
+/// isELF - is this a ELF file
+bool ELFReader<64, true>::isELF(void* pELFHeader) const
+{
+  llvm::ELF::Elf64_Ehdr* hdr =
+                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
+  if (0 == memcmp(llvm::ELF::ElfMagic, hdr, 4))
+    return true;
+  return false;
+}
+
+/// readRegularSection - read a regular section and create fragments.
+bool
+ELFReader<64, true>::readRegularSection(Input& pInput, SectionData& pSD) const
+{
+  uint64_t offset = pInput.fileOffset() + pSD.getSection().offset();
+  uint64_t size = pSD.getSection().size();
+
+  Fragment* frag = IRBuilder::CreateRegion(pInput, offset, size);
+  ObjectBuilder::AppendFragment(*frag, pSD);
+  return true;
+}
+
+/// readSymbols - read ELF symbols and create LDSymbol
+bool ELFReader<64, true>::readSymbols(Input& pInput,
+                                      IRBuilder& pBuilder,
+                                      const MemoryRegion& pRegion,
+                                      const char* pStrTab) const
+{
+  // get number of symbols
+  size_t entsize = pRegion.size()/sizeof(llvm::ELF::Elf64_Sym);
+  const llvm::ELF::Elf64_Sym* symtab =
+                 reinterpret_cast<const llvm::ELF::Elf64_Sym*>(pRegion.start());
+
+  uint32_t st_name  = 0x0;
+  uint64_t st_value = 0x0;
+  uint64_t st_size  = 0x0;
+  uint8_t  st_info  = 0x0;
+  uint8_t  st_other = 0x0;
+  uint16_t st_shndx = 0x0;
+
+  // skip the first NULL symbol
+  pInput.context()->addSymbol(LDSymbol::Null());
+
+  for (size_t idx = 1; idx < entsize; ++idx) {
+    st_info  = symtab[idx].st_info;
+    st_other = symtab[idx].st_other;
+
+    if (llvm::sys::isLittleEndianHost()) {
+      st_name  = symtab[idx].st_name;
+      st_value = symtab[idx].st_value;
+      st_size  = symtab[idx].st_size;
+      st_shndx = symtab[idx].st_shndx;
+    }
+    else {
+      st_name  = mcld::bswap32(symtab[idx].st_name);
+      st_value = mcld::bswap64(symtab[idx].st_value);
+      st_size  = mcld::bswap64(symtab[idx].st_size);
+      st_shndx = mcld::bswap16(symtab[idx].st_shndx);
+    }
+
+    // If the section should not be included, set the st_shndx SHN_UNDEF
+    // - A section in interrelated groups are not included.
+    if (pInput.type() == Input::Object &&
+        st_shndx < llvm::ELF::SHN_LORESERVE &&
+        st_shndx != llvm::ELF::SHN_UNDEF) {
+      if (NULL == pInput.context()->getSection(st_shndx))
+        st_shndx = llvm::ELF::SHN_UNDEF;
+    }
+
+    // get ld_type
+    ResolveInfo::Type ld_type = getSymType(st_info, st_shndx);
+
+    // get ld_desc
+    ResolveInfo::Desc ld_desc = getSymDesc(st_shndx, pInput);
+
+    // get ld_binding
+    ResolveInfo::Binding ld_binding = getSymBinding((st_info >> 4), st_shndx, st_other);
+
+    // get ld_value - ld_value must be section relative.
+    uint64_t ld_value = getSymValue(st_value, st_shndx, pInput);
+
+    // get ld_vis
+    ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
+
+    // get section
+    LDSection* section = NULL;
+    if (st_shndx < llvm::ELF::SHN_LORESERVE) // including ABS and COMMON
+      section = pInput.context()->getSection(st_shndx);
+
+    // get ld_name
+    std::string ld_name;
+    if (ResolveInfo::Section == ld_type) {
+      // Section symbol's st_name is the section index.
+      assert(NULL != section && "get a invalid section");
+      ld_name = section->name();
+    }
+    else {
+      ld_name = std::string(pStrTab + st_name);
+    }
+
+    pBuilder.AddSymbol(pInput,
+                       ld_name,
+                       ld_type,
+                       ld_desc,
+                       ld_binding,
+                       st_size,
+                       ld_value,
+                       section, ld_vis);
+  } // end of for loop
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// ELFReader::read relocations - read ELF rela and rel, and create Relocation
+//===----------------------------------------------------------------------===//
+/// ELFReader::readRela - read ELF rela and create Relocation
+bool ELFReader<64, true>::readRela(Input& pInput,
+                                   LDSection& pSection,
+                                   const MemoryRegion& pRegion) const
+{
+  // get the number of rela
+  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf64_Rela);
+  const llvm::ELF::Elf64_Rela* relaTab =
+                reinterpret_cast<const llvm::ELF::Elf64_Rela*>(pRegion.start());
+
+  for (size_t idx=0; idx < entsize; ++idx) {
+    uint64_t r_offset = 0x0;
+    uint64_t r_info   = 0x0;
+    int64_t  r_addend = 0;
+    if (llvm::sys::isLittleEndianHost()) {
+      r_offset = relaTab[idx].r_offset;
+      r_info   = relaTab[idx].r_info;
+      r_addend = relaTab[idx].r_addend;
+    }
+    else {
+      r_offset = mcld::bswap64(relaTab[idx].r_offset);
+      r_info   = mcld::bswap64(relaTab[idx].r_info);
+      r_addend = mcld::bswap64(relaTab[idx].r_addend);
+    }
+
+    uint32_t  r_type = static_cast<uint32_t>(r_info);
+    uint32_t r_sym  = (r_info >> 32);
+    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
+    if (NULL == symbol) {
+      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
+    }
+
+    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset, r_addend);
+  } // end of for
+  return true;
+}
+
+/// readRel - read ELF rel and create Relocation
+bool ELFReader<64, true>::readRel(Input& pInput,
+                                  LDSection& pSection,
+                                  const MemoryRegion& pRegion) const
+{
+  // get the number of rel
+  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf64_Rel);
+  const llvm::ELF::Elf64_Rel* relTab =
+                 reinterpret_cast<const llvm::ELF::Elf64_Rel*>(pRegion.start());
+
+  for (size_t idx=0; idx < entsize; ++idx) {
+    uint64_t r_offset = 0x0;
+    uint64_t r_info   = 0x0;
+    if (llvm::sys::isLittleEndianHost()) {
+      r_offset = relTab[idx].r_offset;
+      r_info   = relTab[idx].r_info;
+    }
+    else {
+      r_offset = mcld::bswap64(relTab[idx].r_offset);
+      r_info   = mcld::bswap64(relTab[idx].r_info);
+    }
+
+    uint32_t  r_type = static_cast<uint32_t>(r_info);
+    uint32_t r_sym  = (r_info >> 32);
+
+    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
+    if (NULL == symbol) {
+      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
+    }
+
+    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset);
+  } // end of for
+  return true;
+}
+
+/// isMyEndian - is this ELF file in the same endian to me?
+bool ELFReader<64, true>::isMyEndian(void* pELFHeader) const
+{
+  llvm::ELF::Elf64_Ehdr* hdr =
+                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
+
+  return (hdr->e_ident[llvm::ELF::EI_DATA] == llvm::ELF::ELFDATA2LSB);
+}
+
+/// isMyMachine - is this ELF file generated for the same machine.
+bool ELFReader<64, true>::isMyMachine(void* pELFHeader) const
+{
+  llvm::ELF::Elf64_Ehdr* hdr =
+                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
+
+  if (llvm::sys::isLittleEndianHost())
+    return (hdr->e_machine == target().getInfo().machine());
+  return (mcld::bswap16(hdr->e_machine) == target().getInfo().machine());
+}
+
+/// fileType - return the file type
+Input::Type ELFReader<64, true>::fileType(void* pELFHeader) const
+{
+  llvm::ELF::Elf64_Ehdr* hdr =
+                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
+  uint32_t type = 0x0;
+  if (llvm::sys::isLittleEndianHost())
+    type = hdr->e_type;
+  else
+    type = mcld::bswap16(hdr->e_type);
+
+  switch(type) {
+  case llvm::ELF::ET_REL:
+    return Input::Object;
+  case llvm::ELF::ET_EXEC:
+    return Input::Exec;
+  case llvm::ELF::ET_DYN:
+    return Input::DynObj;
+  case llvm::ELF::ET_CORE:
+    return Input::CoreFile;
+  case llvm::ELF::ET_NONE:
+  default:
+    return Input::Unknown;
+  }
+}
+
+/// readSectionHeaders - read ELF section header table and create LDSections
+bool
+ELFReader<64, true>::readSectionHeaders(Input& pInput, void* pELFHeader) const
+{
+  llvm::ELF::Elf64_Ehdr* ehdr =
+                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
+
+  uint64_t shoff     = 0x0;
+  uint16_t shentsize = 0x0;
+  uint32_t shnum     = 0x0;
+  uint32_t shstrtab  = 0x0;
+
+  if (llvm::sys::isLittleEndianHost()) {
+    shoff     = ehdr->e_shoff;
+    shentsize = ehdr->e_shentsize;
+    shnum     = ehdr->e_shnum;
+    shstrtab  = ehdr->e_shstrndx;
+  }
+  else {
+    shoff     = mcld::bswap64(ehdr->e_shoff);
+    shentsize = mcld::bswap16(ehdr->e_shentsize);
+    shnum     = mcld::bswap16(ehdr->e_shnum);
+    shstrtab  = mcld::bswap16(ehdr->e_shstrndx);
+  }
+
+  // If the file has no section header table, e_shoff holds zero.
+  if (0x0 == shoff)
+    return true;
+
+  llvm::ELF::Elf64_Shdr *shdr = NULL;
+  MemoryRegion* shdr_region = NULL;
+  uint32_t sh_name      = 0x0;
+  uint32_t sh_type      = 0x0;
+  uint64_t sh_flags     = 0x0;
+  uint64_t sh_offset    = 0x0;
+  uint64_t sh_size      = 0x0;
+  uint32_t sh_link      = 0x0;
+  uint32_t sh_info      = 0x0;
+  uint64_t sh_addralign = 0x0;
+
+  // if shnum and shstrtab overflow, the actual values are in the 1st shdr
+  if (shnum == llvm::ELF::SHN_UNDEF || shstrtab == llvm::ELF::SHN_XINDEX) {
+    shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
+                                            shentsize);
+    shdr = reinterpret_cast<llvm::ELF::Elf64_Shdr*>(shdr_region->start());
+
+    if (llvm::sys::isLittleEndianHost()) {
+      sh_size = shdr->sh_size;
+      sh_link = shdr->sh_link;
+    }
+    else {
+      sh_size = mcld::bswap64(shdr->sh_size);
+      sh_link = mcld::bswap32(shdr->sh_link);
+    }
+    pInput.memArea()->release(shdr_region);
+
+    if (shnum == llvm::ELF::SHN_UNDEF)
+      shnum = sh_size;
+    if (shstrtab == llvm::ELF::SHN_XINDEX)
+      shstrtab = sh_link;
+
+    shoff += shentsize;
+  }
+
+  shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
+                                          shnum * shentsize);
+  llvm::ELF::Elf64_Shdr * shdrTab =
+    reinterpret_cast<llvm::ELF::Elf64_Shdr*>(shdr_region->start());
+
+  // get .shstrtab first
+  shdr = &shdrTab[shstrtab];
+  if (llvm::sys::isLittleEndianHost()) {
+    sh_offset = shdr->sh_offset;
+    sh_size   = shdr->sh_size;
+  }
+  else {
+    sh_offset = mcld::bswap64(shdr->sh_offset);
+    sh_size   = mcld::bswap64(shdr->sh_size);
+  }
+
+  MemoryRegion* sect_name_region = pInput.memArea()->request(
+                                      pInput.fileOffset() + sh_offset, sh_size);
+  const char* sect_name =
+                       reinterpret_cast<const char*>(sect_name_region->start());
+
+  LinkInfoList link_info_list;
+
+  // create all LDSections, including first NULL section.
+  for (size_t idx = 0; idx < shnum; ++idx) {
+    if (llvm::sys::isLittleEndianHost()) {
+      sh_name      = shdrTab[idx].sh_name;
+      sh_type      = shdrTab[idx].sh_type;
+      sh_flags     = shdrTab[idx].sh_flags;
+      sh_offset    = shdrTab[idx].sh_offset;
+      sh_size      = shdrTab[idx].sh_size;
+      sh_link      = shdrTab[idx].sh_link;
+      sh_info      = shdrTab[idx].sh_info;
+      sh_addralign = shdrTab[idx].sh_addralign;
+    }
+    else {
+      sh_name      = mcld::bswap32(shdrTab[idx].sh_name);
+      sh_type      = mcld::bswap32(shdrTab[idx].sh_type);
+      sh_flags     = mcld::bswap64(shdrTab[idx].sh_flags);
+      sh_offset    = mcld::bswap64(shdrTab[idx].sh_offset);
+      sh_size      = mcld::bswap64(shdrTab[idx].sh_size);
+      sh_link      = mcld::bswap32(shdrTab[idx].sh_link);
+      sh_info      = mcld::bswap32(shdrTab[idx].sh_info);
+      sh_addralign = mcld::bswap64(shdrTab[idx].sh_addralign);
+    }
+
+    LDSection* section = IRBuilder::CreateELFHeader(pInput,
+                                                    sect_name+sh_name,
+                                                    sh_type,
+                                                    sh_flags,
+                                                    sh_addralign);
+    section->setSize(sh_size);
+    section->setOffset(sh_offset);
+    section->setInfo(sh_info);
+
+    if (sh_link != 0x0 || sh_info != 0x0) {
+      LinkInfo link_info = { section, sh_link, sh_info };
+      link_info_list.push_back(link_info);
+    }
+  } // end of for
+
+  // set up InfoLink
+  LinkInfoList::iterator info, infoEnd = link_info_list.end();
+  for (info = link_info_list.begin(); info != infoEnd; ++info) {
+    if (LDFileFormat::NamePool == info->section->kind() ||
+        LDFileFormat::Group == info->section->kind() ||
+        LDFileFormat::Note == info->section->kind()) {
+      info->section->setLink(pInput.context()->getSection(info->sh_link));
+      continue;
+    }
+    if (LDFileFormat::Relocation == info->section->kind()) {
+      info->section->setLink(pInput.context()->getSection(info->sh_info));
+      continue;
+    }
+  }
+
+  pInput.memArea()->release(shdr_region);
+  pInput.memArea()->release(sect_name_region);
+
+  return true;
+}
+
+/// readSignature - read a symbol from the given Input and index in symtab
+/// This is used to get the signature of a group section.
+ResolveInfo* ELFReader<64, true>::readSignature(Input& pInput,
+                                                LDSection& pSymTab,
+                                                uint32_t pSymIdx) const
+{
+  LDSection* symtab = &pSymTab;
+  LDSection* strtab = symtab->getLink();
+  assert(NULL != symtab && NULL != strtab);
+
+  uint64_t offset = pInput.fileOffset() + symtab->offset() +
+                      sizeof(llvm::ELF::Elf64_Sym) * pSymIdx;
+  MemoryRegion* symbol_region =
+                pInput.memArea()->request(offset, sizeof(llvm::ELF::Elf64_Sym));
+  llvm::ELF::Elf64_Sym* entry =
+                reinterpret_cast<llvm::ELF::Elf64_Sym*>(symbol_region->start());
+
+  uint32_t st_name  = 0x0;
+  uint8_t  st_info  = 0x0;
+  uint8_t  st_other = 0x0;
+  uint16_t st_shndx = 0x0;
+  st_info  = entry->st_info;
+  st_other = entry->st_other;
+  if (llvm::sys::isLittleEndianHost()) {
+    st_name  = entry->st_name;
+    st_shndx = entry->st_shndx;
+  }
+  else {
+    st_name  = mcld::bswap32(entry->st_name);
+    st_shndx = mcld::bswap16(entry->st_shndx);
+  }
+
+  MemoryRegion* strtab_region = pInput.memArea()->request(
+                       pInput.fileOffset() + strtab->offset(), strtab->size());
+
+  // get ld_name
+  llvm::StringRef ld_name(
+                    reinterpret_cast<char*>(strtab_region->start() + st_name));
+
+  ResolveInfo* result = ResolveInfo::Create(ld_name);
+  result->setSource(pInput.type() == Input::DynObj);
+  result->setType(static_cast<ResolveInfo::Type>(st_info & 0xF));
+  result->setDesc(getSymDesc(st_shndx, pInput));
+  result->setBinding(getSymBinding((st_info >> 4), st_shndx, st_other));
+  result->setVisibility(getSymVisibility(st_other));
+
+  // release regions
+  pInput.memArea()->release(symbol_region);
+  pInput.memArea()->release(strtab_region);
+
+  return result;
+}
+
+/// readDynamic - read ELF .dynamic in input dynobj
+bool ELFReader<64, true>::readDynamic(Input& pInput) const
+{
+  assert(pInput.type() == Input::DynObj);
+  const LDSection* dynamic_sect = pInput.context()->getSection(".dynamic");
+  if (NULL == dynamic_sect) {
+    fatal(diag::err_cannot_read_section) << ".dynamic";
+  }
+  const LDSection* dynstr_sect = dynamic_sect->getLink();
+  if (NULL == dynstr_sect) {
+    fatal(diag::err_cannot_read_section) << ".dynstr";
+  }
+
+  MemoryRegion* dynamic_region = pInput.memArea()->request(
+           pInput.fileOffset() + dynamic_sect->offset(), dynamic_sect->size());
+
+  MemoryRegion* dynstr_region = pInput.memArea()->request(
+             pInput.fileOffset() + dynstr_sect->offset(), dynstr_sect->size());
+
+  assert(NULL != dynamic_region && NULL != dynstr_region);
+
+  const llvm::ELF::Elf64_Dyn* dynamic =
+    (llvm::ELF::Elf64_Dyn*) dynamic_region->start();
+  const char* dynstr = (const char*) dynstr_region->start();
+  bool hasSOName = false;
+  size_t numOfEntries = dynamic_sect->size() / sizeof(llvm::ELF::Elf64_Dyn);
+
+  for (size_t idx = 0; idx < numOfEntries; ++idx) {
+
+    llvm::ELF::Elf64_Sxword d_tag = 0x0;
+    llvm::ELF::Elf64_Xword d_val = 0x0;
+
+    if (llvm::sys::isLittleEndianHost()) {
+      d_tag = dynamic[idx].d_tag;
+      d_val = dynamic[idx].d_un.d_val;
+    } else {
+      d_tag = mcld::bswap64(dynamic[idx].d_tag);
+      d_val = mcld::bswap64(dynamic[idx].d_un.d_val);
+    }
+
+    switch (d_tag) {
+      case llvm::ELF::DT_SONAME:
+        assert(d_val < dynstr_sect->size());
+        pInput.setName(sys::fs::Path(dynstr + d_val).filename().native());
+        hasSOName = true;
+        break;
+      case llvm::ELF::DT_NEEDED:
+        // TODO:
+        break;
+      case llvm::ELF::DT_NULL:
+      default:
+        break;
+    }
+  }
+
+  // if there is no SONAME in .dynamic, then set it from input path
+  if (!hasSOName)
+    pInput.setName(pInput.path().filename().native());
+
+  pInput.memArea()->release(dynamic_region);
+  pInput.memArea()->release(dynstr_region);
+  return true;
+}
+
diff --git a/lib/LD/ELFReaderIf.cpp b/lib/LD/ELFReaderIf.cpp
new file mode 100644
index 0000000..9625d85
--- /dev/null
+++ b/lib/LD/ELFReaderIf.cpp
@@ -0,0 +1,164 @@
+//===- ELFReader.cpp ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/ELFReaderIf.h>
+
+#include <mcld/IRBuilder.h>
+#include <mcld/Fragment/FillFragment.h>
+#include <mcld/LD/EhFrame.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/Target/GNULDBackend.h>
+//#include <mcld/Support/MemoryArea.h>
+//#include <mcld/Support/MemoryRegion.h>
+//#include <mcld/Support/MsgHandling.h>
+//#include <mcld/Object/ObjectBuilder.h>
+
+#include <cstring>
+
+#include <llvm/ADT/StringRef.h>
+#include <llvm/ADT/Twine.h>
+#include <llvm/Support/ELF.h>
+#include <llvm/Support/Host.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ELFReaderIF
+//===----------------------------------------------------------------------===//
+/// getSymType
+ResolveInfo::Type ELFReaderIF::getSymType(uint8_t pInfo, uint16_t pShndx) const
+{
+  ResolveInfo::Type result = static_cast<ResolveInfo::Type>(pInfo & 0xF);
+  if (llvm::ELF::SHN_ABS == pShndx && ResolveInfo::Section == result) {
+    // In Mips, __gp_disp is a special section symbol. Its name comes from
+    // .strtab, not .shstrtab. However, it is unique. Only it is also a ABS
+    // symbol. So here is a tricky to identify __gp_disp and convert it to
+    // Object symbol.
+    return ResolveInfo::Object;
+  }
+
+  return result;
+}
+
+/// getSymDesc
+ResolveInfo::Desc ELFReaderIF::getSymDesc(uint16_t pShndx, const Input& pInput) const
+{
+  if (pShndx == llvm::ELF::SHN_UNDEF)
+    return ResolveInfo::Undefined;
+
+  if (pShndx < llvm::ELF::SHN_LORESERVE) {
+    // an ELF symbol defined in a section which we are not including
+    // must be treated as an Undefined.
+    // @ref Google gold linker: symtab.cc: 1086
+    if (NULL == pInput.context()->getSection(pShndx) ||
+        LDFileFormat::Ignore == pInput.context()->getSection(pShndx)->kind())
+      return ResolveInfo::Undefined;
+    return ResolveInfo::Define;
+  }
+
+  if (pShndx == llvm::ELF::SHN_ABS)
+    return ResolveInfo::Define;
+
+  if (pShndx == llvm::ELF::SHN_COMMON)
+    return ResolveInfo::Common;
+
+  if (pShndx >= llvm::ELF::SHN_LOPROC &&
+      pShndx <= llvm::ELF::SHN_HIPROC)
+    return target().getSymDesc(pShndx);
+
+  // FIXME: ELF weak alias should be ResolveInfo::Indirect
+  return ResolveInfo::NoneDesc;
+}
+
+/// getSymBinding
+ResolveInfo::Binding
+ELFReaderIF::getSymBinding(uint8_t pBinding, uint16_t pShndx, uint8_t pVis) const
+{
+
+  // TODO:
+  // if --just-symbols option is enabled, the symbol must covert to Absolute
+
+  switch(pBinding) {
+  case llvm::ELF::STB_LOCAL:
+    return ResolveInfo::Local;
+  case llvm::ELF::STB_GLOBAL:
+    return ResolveInfo::Global;
+  case llvm::ELF::STB_WEAK:
+    return ResolveInfo::Weak;
+  }
+
+  if (pShndx == llvm::ELF::SHN_ABS)
+    return ResolveInfo::Absolute;
+
+  return ResolveInfo::NoneBinding;
+}
+
+/// getSymFragmentRef
+FragmentRef*
+ELFReaderIF::getSymFragmentRef(Input& pInput,
+                               uint16_t pShndx,
+                               uint32_t pOffset) const
+{
+
+  if (Input::DynObj == pInput.type())
+    return FragmentRef::Null();
+
+  if (pShndx == llvm::ELF::SHN_UNDEF)
+    return FragmentRef::Null();
+
+  if (pShndx >= llvm::ELF::SHN_LORESERVE) // including ABS and COMMON
+    return FragmentRef::Null();
+
+  LDSection* sect_hdr = pInput.context()->getSection(pShndx);
+
+  if (NULL == sect_hdr)
+    unreachable(diag::unreachable_invalid_section_idx) << pShndx
+                                                       << pInput.path().native();
+
+  if (LDFileFormat::Ignore == sect_hdr->kind())
+    return FragmentRef::Null();
+
+  if (LDFileFormat::Group == sect_hdr->kind())
+    return FragmentRef::Null();
+
+  return FragmentRef::Create(*sect_hdr, pOffset);
+}
+
+/// getSymVisibility
+ResolveInfo::Visibility
+ELFReaderIF::getSymVisibility(uint8_t pVis) const
+{
+  return static_cast<ResolveInfo::Visibility>(pVis);
+}
+
+/// getSymValue - get the section offset of the symbol.
+uint64_t ELFReaderIF::getSymValue(uint64_t pValue,
+                                  uint16_t pShndx,
+                                  const Input& pInput) const
+{
+  if (Input::Object == pInput.type()) {
+    // In relocatable files, st_value holds alignment constraints for a symbol
+    // whose section index is SHN_COMMON
+    if (pShndx == llvm::ELF::SHN_COMMON || pShndx == llvm::ELF::SHN_ABS) {
+      return pValue;
+    }
+
+    // In relocatable files, st_value holds a section offset for a defined symbol.
+    // TODO:
+    // if --just-symbols option are enabled, convert the value from section offset
+    // to virtual address by adding input section's virtual address.
+    // The section's virtual address in relocatable files is normally zero, but
+    // people can use link script to change it.
+    return pValue;
+  }
+
+  // In executable and shared object files, st_value holds a virtual address.
+  // the virtual address is useless during linking.
+  return 0x0;
+}
+
diff --git a/lib/LD/ELFWriter.cpp b/lib/LD/ELFWriter.cpp
deleted file mode 100644
index a37e654..0000000
--- a/lib/LD/ELFWriter.cpp
+++ /dev/null
@@ -1,600 +0,0 @@
-//===- ELFWriter.cpp ------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <cstdlib>
-#include <cstring>
-
-#include <llvm/Support/ELF.h>
-#include <llvm/Support/Casting.h>
-
-#include <mcld/LinkerConfig.h>
-#include <mcld/Module.h>
-#include <mcld/ADT/SizeTraits.h>
-#include <mcld/Fragment/FragmentLinker.h>
-#include <mcld/Fragment/AlignFragment.h>
-#include <mcld/Fragment/FillFragment.h>
-#include <mcld/Fragment/RegionFragment.h>
-#include <mcld/Fragment/Stub.h>
-#include <mcld/Fragment/NullFragment.h>
-#include <mcld/LD/ELFWriter.h>
-#include <mcld/LD/LDSymbol.h>
-#include <mcld/LD/LDSection.h>
-#include <mcld/LD/SectionData.h>
-#include <mcld/LD/ELFSegment.h>
-#include <mcld/LD/ELFSegmentFactory.h>
-#include <mcld/LD/RelocData.h>
-#include <mcld/LD/EhFrame.h>
-#include <mcld/Target/GNULDBackend.h>
-#include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/MemoryRegion.h>
-
-using namespace llvm::ELF;
-using namespace mcld;
-
-/// writeELF32Header - write ELF header
-void ELFWriter::writeELF32Header(const LinkerConfig& pConfig,
-                                 const Module& pModule,
-                                 MemoryArea& pOutput) const
-{
-  // ELF header must start from 0x0
-  MemoryRegion *region = pOutput.request(0, sizeof(Elf32_Ehdr));
-  Elf32_Ehdr* header = (Elf32_Ehdr*)region->start();
-
-  memcpy(header->e_ident, ElfMagic, EI_MAG3+1);
-
-  header->e_ident[EI_CLASS]      = ELFCLASS32;
-  header->e_ident[EI_DATA]       = pConfig.targets().isLittleEndian()?
-                                       ELFDATA2LSB : ELFDATA2MSB;
-  header->e_ident[EI_VERSION]    = target().getInfo().ELFVersion();
-  header->e_ident[EI_OSABI]      = target().getInfo().OSABI();
-  header->e_ident[EI_ABIVERSION] = target().getInfo().ABIVersion();
-
-  // FIXME: add processor-specific and core file types.
-  switch(pConfig.codeGenType()) {
-    case LinkerConfig::Object:
-      header->e_type = ET_REL;
-      break;
-    case LinkerConfig::DynObj:
-      header->e_type = ET_DYN;
-      break;
-    case LinkerConfig::Exec:
-      header->e_type = ET_EXEC;
-      break;
-    default:
-      llvm::errs() << "unspported output file type: " << pConfig.codeGenType() << ".\n";
-      header->e_type = ET_NONE;
-  }
-  header->e_machine   = target().getInfo().machine();
-  header->e_version   = header->e_ident[EI_VERSION];
-  header->e_entry     = getEntryPoint(pConfig, pModule);
-
-  if (LinkerConfig::Object != pConfig.codeGenType())
-    header->e_phoff   = sizeof(Elf32_Ehdr);
-  else
-    header->e_phoff   = 0x0;
-
-  header->e_shoff     = getELF32LastStartOffset(pModule);
-  header->e_flags     = target().flags();
-  header->e_ehsize    = sizeof(Elf32_Ehdr);
-  header->e_phentsize = sizeof(Elf32_Phdr);
-  header->e_phnum     = target().numOfSegments();
-  header->e_shentsize = sizeof(Elf32_Shdr);
-  header->e_shnum     = pModule.size();
-  header->e_shstrndx  = pModule.getSection(".shstrtab")->index();
-}
-
-/// writeELF64Header - write ELF header
-void ELFWriter::writeELF64Header(const LinkerConfig& pConfig,
-                                 const Module& pModule,
-                                 MemoryArea& pOutput) const
-{
-  // ELF header must start from 0x0
-  MemoryRegion *region = pOutput.request(0, sizeof(Elf64_Ehdr));
-  Elf64_Ehdr* header = (Elf64_Ehdr*)region->start();
-
-  memcpy(header->e_ident, ElfMagic, EI_MAG3+1);
-
-  header->e_ident[EI_CLASS]      = ELFCLASS64;
-  header->e_ident[EI_DATA]       = pConfig.targets().isLittleEndian()?
-                                       ELFDATA2LSB : ELFDATA2MSB;
-  header->e_ident[EI_VERSION]    = target().getInfo().ELFVersion();
-  header->e_ident[EI_OSABI]      = target().getInfo().OSABI();
-  header->e_ident[EI_ABIVERSION] = target().getInfo().ABIVersion();
-
-  // FIXME: add processor-specific and core file types.
-  switch(pConfig.codeGenType()) {
-    case LinkerConfig::Object:
-      header->e_type = ET_REL;
-      break;
-    case LinkerConfig::DynObj:
-      header->e_type = ET_DYN;
-      break;
-    case LinkerConfig::Exec:
-      header->e_type = ET_EXEC;
-      break;
-    default:
-      llvm::errs() << "unspported output file type: " << pConfig.codeGenType() << ".\n";
-      header->e_type = ET_NONE;
-  }
-  header->e_machine   = target().getInfo().machine();
-  header->e_version   = header->e_ident[EI_VERSION];
-  header->e_entry     = getEntryPoint(pConfig, pModule);
-
-  if (LinkerConfig::Object != pConfig.codeGenType())
-    header->e_phoff   = sizeof(Elf64_Ehdr);
-  else
-    header->e_phoff   = 0x0;
-
-  header->e_shoff     = getELF64LastStartOffset(pModule);
-  header->e_flags     = target().flags();
-  header->e_ehsize    = sizeof(Elf64_Ehdr);
-  header->e_phentsize = sizeof(Elf64_Phdr);
-  header->e_phnum     = target().numOfSegments();
-  header->e_shentsize = sizeof(Elf64_Shdr);
-  header->e_shnum     = pModule.size();
-  header->e_shstrndx  = pModule.getSection(".shstrtab")->index();
-}
-
-/// getEntryPoint
-uint64_t ELFWriter::getEntryPoint(const LinkerConfig& pConfig,
-                                  const Module& pModule) const
-{
-
-  llvm::StringRef entry_name;
-  if (pConfig.options().hasEntry())
-    entry_name = pConfig.options().entry();
-  else
-    entry_name = target().entry();
-
-  uint64_t result = 0x0;
-
-  bool issue_warning = (pConfig.options().hasEntry() &&
-                        LinkerConfig::Object != pConfig.codeGenType() &&
-                        LinkerConfig::DynObj != pConfig.codeGenType());
-
-  const LDSymbol* entry_symbol = pModule.getNamePool().findSymbol(entry_name);
-
-  // found the symbol
-  if (NULL != entry_symbol) {
-    if (entry_symbol->desc() != ResolveInfo::Define && issue_warning) {
-      llvm::errs() << "WARNING: entry symbol '"
-                   << entry_symbol->name()
-                   << "' exists but is not defined.\n";
-    }
-    result = entry_symbol->value();
-  }
-  // not in the symbol pool
-  else {
-    // We should parse entry as a number.
-    // @ref GNU ld manual, Options -e. e.g., -e 0x1000.
-    char* endptr;
-    result = strtoull(entry_name.data(), &endptr, 0);
-    if (*endptr != '\0') {
-      if (issue_warning) {
-        llvm::errs() << "cannot find entry symbol '"
-                     << entry_name.data()
-                     << "'.\n";
-      }
-      result = 0x0;
-    }
-  }
-  return result;
-}
-
-/// emitELF32SectionHeader - emit Elf32_Shdr
-void
-ELFWriter::emitELF32SectionHeader(const Module& pModule,
-                                  const LinkerConfig& pConfig,
-                                  MemoryArea& pOutput) const
-{
-  // emit section header
-  unsigned int sectNum = pModule.size();
-  unsigned int header_size = sizeof(Elf32_Shdr) * sectNum;
-  MemoryRegion* region = pOutput.request(getELF32LastStartOffset(pModule), header_size);
-  Elf32_Shdr* shdr = (Elf32_Shdr*)region->start();
-
-  // Iterate the SectionTable in LDContext
-  unsigned int sectIdx = 0;
-  unsigned int shstridx = 0; // NULL section has empty name
-  for (; sectIdx < sectNum; ++sectIdx) {
-    const LDSection *ld_sect   = pModule.getSectionTable().at(sectIdx);
-    shdr[sectIdx].sh_name      = shstridx;
-    shdr[sectIdx].sh_type      = ld_sect->type();
-    shdr[sectIdx].sh_flags     = ld_sect->flag();
-    shdr[sectIdx].sh_addr      = ld_sect->addr();
-    shdr[sectIdx].sh_offset    = ld_sect->offset();
-    shdr[sectIdx].sh_size      = ld_sect->size();
-    shdr[sectIdx].sh_addralign = ld_sect->align();
-    shdr[sectIdx].sh_entsize   = getELF32SectEntrySize(*ld_sect);
-    shdr[sectIdx].sh_link      = getSectLink(*ld_sect, pConfig);
-    shdr[sectIdx].sh_info      = getSectInfo(*ld_sect);
-
-    // adjust strshidx
-    shstridx += ld_sect->name().size() + 1;
-  }
-}
-
-/// emitELF64SectionHeader - emit Elf64_Shdr
-void
-ELFWriter::emitELF64SectionHeader(const Module& pModule,
-                                  const LinkerConfig& pConfig,
-                                  MemoryArea& pOutput) const
-{
-  // emit section header
-  unsigned int sectNum = pModule.size();
-  unsigned int header_size = sizeof(Elf64_Shdr) * sectNum;
-  MemoryRegion* region = pOutput.request(getELF64LastStartOffset(pModule),
-                                         header_size);
-  Elf64_Shdr* shdr = (Elf64_Shdr*)region->start();
-
-  // Iterate the SectionTable in LDContext
-  unsigned int sectIdx = 0;
-  unsigned int shstridx = 0; // NULL section has empty name
-  for (; sectIdx < sectNum; ++sectIdx) {
-    const LDSection *ld_sect   = pModule.getSectionTable().at(sectIdx);
-    shdr[sectIdx].sh_name      = shstridx;
-    shdr[sectIdx].sh_type      = ld_sect->type();
-    shdr[sectIdx].sh_flags     = ld_sect->flag();
-    shdr[sectIdx].sh_addr      = ld_sect->addr();
-    shdr[sectIdx].sh_offset    = ld_sect->offset();
-    shdr[sectIdx].sh_size      = ld_sect->size();
-    shdr[sectIdx].sh_addralign = ld_sect->align();
-    shdr[sectIdx].sh_entsize   = getELF64SectEntrySize(*ld_sect);
-    shdr[sectIdx].sh_link      = getSectLink(*ld_sect, pConfig);
-    shdr[sectIdx].sh_info      = getSectInfo(*ld_sect);
-
-    // adjust strshidx
-    shstridx += ld_sect->name().size() + 1;
-  }
-}
-
-
-/// emitELF32ProgramHeader - emit Elf32_Phdr
-void ELFWriter::emitELF32ProgramHeader(MemoryArea& pOutput) const
-{
-  uint64_t start_offset, phdr_size;
-
-  start_offset = sizeof(Elf32_Ehdr);
-  phdr_size = sizeof(Elf32_Phdr);
-  // Program header must start directly after ELF header
-  MemoryRegion *region = pOutput.request(start_offset,
-                                         target().numOfSegments() * phdr_size);
-
-  Elf32_Phdr* phdr = (Elf32_Phdr*)region->start();
-
-  // Iterate the elf segment table in GNULDBackend
-  size_t index = 0;
-  ELFSegmentFactory::const_iterator seg = target().elfSegmentTable().begin(),
-                                 segEnd = target().elfSegmentTable().end();
-  for (; seg != segEnd; ++seg, ++index) {
-    phdr[index].p_type   = (*seg).type();
-    phdr[index].p_flags  = (*seg).flag();
-    phdr[index].p_offset = (*seg).offset();
-    phdr[index].p_vaddr  = (*seg).vaddr();
-    phdr[index].p_paddr  = (*seg).paddr();
-    phdr[index].p_filesz = (*seg).filesz();
-    phdr[index].p_memsz  = (*seg).memsz();
-    phdr[index].p_align  = (*seg).align();
-  }
-}
-
-/// emitELF64ProgramHeader - emit ElfR64Phdr
-void ELFWriter::emitELF64ProgramHeader(MemoryArea& pOutput) const
-{
-  uint64_t start_offset, phdr_size;
-
-  start_offset = sizeof(Elf64_Ehdr);
-  phdr_size = sizeof(Elf64_Phdr);
-  // Program header must start directly after ELF header
-  MemoryRegion *region = pOutput.request(start_offset,
-                                         target().numOfSegments() * phdr_size);
-  Elf64_Phdr* phdr = (Elf64_Phdr*)region->start();
-
-  // Iterate the elf segment table in GNULDBackend
-  size_t index = 0;
-  ELFSegmentFactory::const_iterator seg = target().elfSegmentTable().begin(),
-                                 segEnd = target().elfSegmentTable().end();
-  for (; seg != segEnd; ++seg, ++index) {
-    phdr[index].p_type   = (*seg).type();
-    phdr[index].p_flags  = (*seg).flag();
-    phdr[index].p_offset = (*seg).offset();
-    phdr[index].p_vaddr  = (*seg).vaddr();
-    phdr[index].p_paddr  = (*seg).paddr();
-    phdr[index].p_filesz = (*seg).filesz();
-    phdr[index].p_memsz  = (*seg).memsz();
-    phdr[index].p_align  = (*seg).align();
-  }
-}
-
-/// emitELFShStrTab - emit section string table
-void
-ELFWriter::emitELFShStrTab(const LDSection& pShStrTab, const Module& pModule,
-                           MemoryArea& pOutput)
-{
-  // write out data
-  MemoryRegion* region = pOutput.request(pShStrTab.offset(), pShStrTab.size());
-  unsigned char* data = region->start();
-  size_t shstrsize = 0;
-  Module::const_iterator section, sectEnd = pModule.end();
-  for (section = pModule.begin(); section != sectEnd; ++section) {
-    strcpy((char*)(data + shstrsize), (*section)->name().data());
-    shstrsize += (*section)->name().size() + 1;
-  }
-}
-
-/// emitSectionData
-void
-ELFWriter::emitSectionData(const LDSection& pSection,
-                           MemoryRegion& pRegion) const
-{
-  const SectionData* sd = NULL;
-  switch (pSection.kind()) {
-    case LDFileFormat::Relocation:
-      return;
-    case LDFileFormat::EhFrame:
-      sd = &pSection.getEhFrame()->getSectionData();
-      break;
-    default:
-      sd = pSection.getSectionData();
-      break;
-  }
-  emitSectionData(*sd, pRegion);
-}
-
-/// emitRelocation
-void ELFWriter::emitRelocation(const LinkerConfig& pConfig,
-                               const LDSection& pSection,
-                               MemoryRegion& pRegion) const
-{
-  const RelocData* sect_data = pSection.getRelocData();
-  assert(NULL != sect_data && "SectionData is NULL in emitRelocation!");
-
-  if (pSection.type() == SHT_REL)
-    emitRel(pConfig, *sect_data, pRegion);
-  else if (pSection.type() == SHT_RELA)
-    emitRela(pConfig, *sect_data, pRegion);
-  else
-    llvm::report_fatal_error("unsupported relocation section type!");
-}
-
-
-/// emitRel
-void ELFWriter::emitRel(const LinkerConfig& pConfig,
-                        const RelocData& pRelocData,
-                        MemoryRegion& pRegion) const
-{
-  Elf32_Rel* rel = reinterpret_cast<Elf32_Rel*>(pRegion.start());
-
-  Relocation* relocation = 0;
-  FragmentRef* frag_ref = 0;
-
-  for (RelocData::const_iterator it = pRelocData.begin(),
-       ie = pRelocData.end(); it != ie; ++it, ++rel) {
-
-    relocation = &(llvm::cast<Relocation>(*it));
-    frag_ref = &(relocation->targetRef());
-
-    if(LinkerConfig::DynObj == pConfig.codeGenType() ||
-       LinkerConfig::Exec == pConfig.codeGenType()) {
-      rel->r_offset = static_cast<Elf32_Addr>(
-                      frag_ref->frag()->getParent()->getSection().addr() +
-                      frag_ref->getOutputOffset());
-    }
-    else {
-      rel->r_offset = static_cast<Elf32_Addr>(frag_ref->getOutputOffset());
-    }
-    Elf32_Word Index;
-    if( relocation->symInfo() == NULL )
-      Index = 0;
-    else
-      Index = static_cast<Elf32_Word>(
-              f_Backend.getSymbolIdx(relocation->symInfo()->outSymbol()));
-
-    rel->setSymbolAndType(Index, relocation->type());
-  }
-}
-
-/// emitRela
-void ELFWriter::emitRela(const LinkerConfig& pConfig,
-                         const RelocData& pRelocData,
-                         MemoryRegion& pRegion) const
-{
-  Elf32_Rela* rel = reinterpret_cast<Elf32_Rela*>(pRegion.start());
-
-  Relocation* relocation = 0;
-  FragmentRef* frag_ref = 0;
-
-  for (RelocData::const_iterator it = pRelocData.begin(),
-       ie = pRelocData.end(); it != ie; ++it, ++rel) {
-
-    relocation = &(llvm::cast<Relocation>(*it));
-    frag_ref = &(relocation->targetRef());
-
-    if(LinkerConfig::DynObj == pConfig.codeGenType() ||
-       LinkerConfig::Exec == pConfig.codeGenType()) {
-      rel->r_offset = static_cast<Elf32_Addr>(
-                      frag_ref->frag()->getParent()->getSection().addr() +
-                      frag_ref->getOutputOffset());
-    }
-    else {
-      rel->r_offset = static_cast<Elf32_Addr>(frag_ref->getOutputOffset());
-    }
-
-    Elf32_Word Index;
-    if( relocation->symInfo() == NULL )
-      Index = 0;
-    else
-      Index = static_cast<Elf32_Word>(
-              f_Backend.getSymbolIdx(relocation->symInfo()->outSymbol()));
-
-    rel->setSymbolAndType(Index, relocation->type());
-    rel->r_addend = relocation->addend();
-  }
-}
-
-/// getELF32SectEntrySize - compute Elf32_Shdr::sh_entsize
-uint64_t ELFWriter::getELF32SectEntrySize(const LDSection& pSection) const
-{
-  if (llvm::ELF::SHT_DYNSYM == pSection.type() ||
-      llvm::ELF::SHT_SYMTAB == pSection.type())
-    return sizeof(llvm::ELF::Elf32_Sym);
-  if (llvm::ELF::SHT_REL == pSection.type())
-    return sizeof(llvm::ELF::Elf32_Rel);
-  if (llvm::ELF::SHT_RELA == pSection.type())
-    return sizeof(llvm::ELF::Elf32_Rela);
-  if (llvm::ELF::SHT_HASH == pSection.type())
-    return sizeof(llvm::ELF::Elf32_Word);
-  if (llvm::ELF::SHT_DYNAMIC == pSection.type())
-    return sizeof(llvm::ELF::Elf32_Dyn);
-  return 0x0;
-}
-
-/// getELF64SectEntrySize - compute Elf64_Shdr::sh_entsize
-uint64_t ELFWriter::getELF64SectEntrySize(const LDSection& pSection) const
-{
-  if (llvm::ELF::SHT_DYNSYM == pSection.type() ||
-      llvm::ELF::SHT_SYMTAB == pSection.type())
-    return sizeof(llvm::ELF::Elf64_Sym);
-  if (llvm::ELF::SHT_REL == pSection.type())
-    return sizeof(llvm::ELF::Elf64_Rel);
-  if (llvm::ELF::SHT_RELA == pSection.type())
-    return sizeof(llvm::ELF::Elf64_Rela);
-  if (llvm::ELF::SHT_HASH == pSection.type())
-    return sizeof(llvm::ELF::Elf64_Word);
-  if (llvm::ELF::SHT_DYNAMIC == pSection.type())
-    return sizeof(llvm::ELF::Elf64_Dyn);
-  return 0x0;
-}
-
-/// getSectLink - compute ElfXX_Shdr::sh_link
-uint64_t ELFWriter::getSectLink(const LDSection& pSection,
-                                const LinkerConfig& pConfig) const
-{
-  if (llvm::ELF::SHT_SYMTAB == pSection.type())
-    return target().getOutputFormat()->getStrTab().index();
-  if (llvm::ELF::SHT_DYNSYM == pSection.type())
-    return target().getOutputFormat()->getDynStrTab().index();
-  if (llvm::ELF::SHT_DYNAMIC == pSection.type())
-    return target().getOutputFormat()->getDynStrTab().index();
-  if (llvm::ELF::SHT_HASH == pSection.type())
-    return target().getOutputFormat()->getDynSymTab().index();
-  if (llvm::ELF::SHT_REL == pSection.type() ||
-      llvm::ELF::SHT_RELA == pSection.type()) {
-    if (LinkerConfig::Object == pConfig.codeGenType())
-      return target().getOutputFormat()->getSymTab().index();
-    else
-      return target().getOutputFormat()->getDynSymTab().index();
-  }
-  // FIXME: currently we link ARM_EXIDX section to output text section here
-  if (llvm::ELF::SHT_ARM_EXIDX == pSection.type())
-    return target().getOutputFormat()->getText().index();
-  return llvm::ELF::SHN_UNDEF;
-}
-
-/// getSectInfo - compute ElfXX_Shdr::sh_info
-uint64_t ELFWriter::getSectInfo(const LDSection& pSection) const
-{
-  if (llvm::ELF::SHT_SYMTAB == pSection.type() ||
-      llvm::ELF::SHT_DYNSYM == pSection.type())
-    return pSection.getInfo();
-
-  if (llvm::ELF::SHT_REL == pSection.type() ||
-      llvm::ELF::SHT_RELA == pSection.type()) {
-    const LDSection* info_link = pSection.getLink();
-    if (NULL != info_link)
-      return info_link->index();
-  }
-
-  return 0x0;
-}
-
-/// getELF32LastStartOffset
-uint64_t ELFWriter::getELF32LastStartOffset(const Module& pModule) const
-{
-  const LDSection* lastSect = pModule.back();
-  assert(lastSect != NULL);
-  return Align<32>(lastSect->offset() + lastSect->size());
-}
-
-/// getELF64LastStartOffset
-uint64_t ELFWriter::getELF64LastStartOffset(const Module& pModule) const
-{
-  const LDSection* lastSect = pModule.back();
-  assert(lastSect != NULL);
-  return Align<64>(lastSect->offset() + lastSect->size());
-}
-
-/// emitSectionData
-void
-ELFWriter::emitSectionData(const SectionData& pSD, MemoryRegion& pRegion) const
-{
-  SectionData::const_iterator fragIter, fragEnd = pSD.end();
-  size_t cur_offset = 0;
-  for (fragIter = pSD.begin(); fragIter != fragEnd; ++fragIter) {
-    size_t size = fragIter->size();
-    switch(fragIter->getKind()) {
-      case Fragment::Region: {
-        const RegionFragment& region_frag = llvm::cast<RegionFragment>(*fragIter);
-        const uint8_t* from = region_frag.getRegion().start();
-        memcpy(pRegion.getBuffer(cur_offset), from, size);
-        break;
-      }
-      case Fragment::Alignment: {
-        // TODO: emit values with different sizes (> 1 byte), and emit nops
-        AlignFragment& align_frag = llvm::cast<AlignFragment>(*fragIter);
-        uint64_t count = size / align_frag.getValueSize();
-        switch (align_frag.getValueSize()) {
-          case 1u:
-            std::memset(pRegion.getBuffer(cur_offset),
-                        align_frag.getValue(),
-                        count);
-            break;
-          default:
-            llvm::report_fatal_error("unsupported value size for align fragment emission yet.\n");
-            break;
-        }
-        break;
-      }
-      case Fragment::Fillment: {
-        FillFragment& fill_frag = llvm::cast<FillFragment>(*fragIter);
-        if (0 == size ||
-            0 == fill_frag.getValueSize() ||
-            0 == fill_frag.size()) {
-          // ignore virtual fillment
-          break;
-        }
-
-        uint64_t num_tiles = fill_frag.size() / fill_frag.getValueSize();
-        for (uint64_t i = 0; i != num_tiles; ++i) {
-          std::memset(pRegion.getBuffer(cur_offset),
-                      fill_frag.getValue(),
-                      fill_frag.getValueSize());
-        }
-        break;
-      }
-      case Fragment::Stub: {
-        Stub& stub_frag = llvm::cast<Stub>(*fragIter);
-        memcpy(pRegion.getBuffer(cur_offset), stub_frag.getContent(), size);
-        break;
-      }
-      case Fragment::Null: {
-        assert(0x0 == size);
-        break;
-      }
-      case Fragment::Target:
-        llvm::report_fatal_error("Target fragment should not be in a regular section.\n");
-        break;
-      default:
-        llvm::report_fatal_error("invalid fragment should not be in a regular section.\n");
-        break;
-    }
-    cur_offset += size;
-  }
-}
-
diff --git a/lib/LD/EhFrame.cpp b/lib/LD/EhFrame.cpp
index df61c24..9d49630 100644
--- a/lib/LD/EhFrame.cpp
+++ b/lib/LD/EhFrame.cpp
@@ -9,11 +9,18 @@
 #include <mcld/LD/EhFrame.h>
 #include <mcld/LD/LDSection.h>
 #include <mcld/LD/SectionData.h>
-#include <mcld/Support/MemoryRegion.h>
 #include <mcld/Object/ObjectBuilder.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/GCFactory.h>
+
+#include <llvm/Support/ManagedStatic.h>
 
 using namespace mcld;
 
+typedef GCFactory<EhFrame, MCLD_SECTIONS_PER_INPUT> EhFrameFactory;
+
+static llvm::ManagedStatic<EhFrameFactory> g_EhFrameFactory;
+
 //===----------------------------------------------------------------------===//
 // EhFrame::CIE
 //===----------------------------------------------------------------------===//
@@ -35,8 +42,12 @@
 //===----------------------------------------------------------------------===//
 // EhFrame
 //===----------------------------------------------------------------------===//
+EhFrame::EhFrame()
+  : m_pSection(NULL), m_pSectionData(NULL) {
+}
+
 EhFrame::EhFrame(LDSection& pSection)
-  : m_Section(pSection),
+  : m_pSection(&pSection),
     m_pSectionData(NULL) {
   m_pSectionData = SectionData::Create(pSection);
 }
@@ -47,6 +58,37 @@
   // will delete the fragments and we do not need to handle with it.
 }
 
+EhFrame* EhFrame::Create(LDSection& pSection)
+{
+  EhFrame* result = g_EhFrameFactory->allocate();
+  new (result) EhFrame(pSection);
+  return result;
+}
+
+void EhFrame::Destroy(EhFrame*& pSection)
+{
+  pSection->~EhFrame();
+  g_EhFrameFactory->deallocate(pSection);
+  pSection = NULL;
+}
+
+void EhFrame::Clear()
+{
+  g_EhFrameFactory->clear();
+}
+
+const LDSection& EhFrame::getSection() const
+{
+  assert(NULL != m_pSection);
+  return *m_pSection;
+}
+
+LDSection& EhFrame::getSection()
+{
+  assert(NULL != m_pSection);
+  return *m_pSection;
+}
+
 void EhFrame::addFragment(RegionFragment& pFrag)
 {
   uint32_t offset = 0;
diff --git a/lib/LD/EhFrameHdr.cpp b/lib/LD/EhFrameHdr.cpp
index 4c0d59c..a00d785 100644
--- a/lib/LD/EhFrameHdr.cpp
+++ b/lib/LD/EhFrameHdr.cpp
@@ -114,6 +114,12 @@
   pOutput.release(ehframe_region);
 }
 
+/// emitOutput<64> - write out eh_frame_hdr
+template<>
+void EhFrameHdr::emitOutput<64>(MemoryArea& pOutput)
+{
+}
+
 //===----------------------------------------------------------------------===//
 // EhFrameHdr
 //===----------------------------------------------------------------------===//
diff --git a/lib/LD/ExecWriter.cpp b/lib/LD/ExecWriter.cpp
deleted file mode 100644
index d66cd17..0000000
--- a/lib/LD/ExecWriter.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-//===- ExecWriter.cpp ---------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/LD/ExecWriter.h"
-#include "mcld/Target/TargetLDBackend.h"
-#include "mcld/MC/MCLDInput.h"
-
-using namespace mcld;
-
-//==========================
-// ExecWriter
diff --git a/lib/LD/GNUArchiveReader.cpp b/lib/LD/GNUArchiveReader.cpp
index 82e4fec..6324824 100644
--- a/lib/LD/GNUArchiveReader.cpp
+++ b/lib/LD/GNUArchiveReader.cpp
@@ -89,6 +89,10 @@
 
 bool GNUArchiveReader::readArchive(Archive& pArchive)
 {
+  // bypass the empty archive
+  if (Archive::MAGIC_LEN == pArchive.getARFile().memArea()->handler()->size())
+    return true;
+
   if (pArchive.getARFile().attribute()->isWholeArchive())
     return includeAllMembers(pArchive);
 
diff --git a/lib/LD/LDObjectWriter.cpp b/lib/LD/LDObjectWriter.cpp
deleted file mode 100644
index d08c6a7..0000000
--- a/lib/LD/LDObjectWriter.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-//===- LDObjectWriter.cpp -------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/MC/MCObjectWriter.h"
-
-using namespace mcld;
-
-//==========================
-// MCObjectWriter
-
-
-MCObjectWriter::MCObjectWriter() 
-{
-}
-
-MCObjectWriter::~MCObjectWriter() 
-{
-}
diff --git a/lib/LD/LDSymbol.cpp b/lib/LD/LDSymbol.cpp
index c6fab43..9002235 100644
--- a/lib/LD/LDSymbol.cpp
+++ b/lib/LD/LDSymbol.cpp
@@ -19,10 +19,10 @@
 
 using namespace mcld;
 
-static LDSymbol* g_NullSymbol = NULL;
-
 typedef GCFactory<LDSymbol, MCLD_SYMBOLS_PER_INPUT> LDSymbolFactory;
 
+static llvm::ManagedStatic<LDSymbol> g_NullSymbol;
+static llvm::ManagedStatic<NullFragment> g_NullSymbolFragment;
 static llvm::ManagedStatic<LDSymbolFactory> g_LDSymbolFactory;
 
 //===----------------------------------------------------------------------===//
@@ -72,14 +72,13 @@
 
 LDSymbol* LDSymbol::Null()
 {
-  if (NULL == g_NullSymbol) {
-    g_NullSymbol = new LDSymbol();
+  // lazy initialization
+  if (NULL == g_NullSymbol->resolveInfo()) {
     g_NullSymbol->setResolveInfo(*ResolveInfo::Null());
-    NullFragment* null_frag = new NullFragment();
-    g_NullSymbol->setFragmentRef(FragmentRef::Create(*null_frag, 0));
-    ResolveInfo::Null()->setSymPtr(g_NullSymbol);
+    g_NullSymbol->setFragmentRef(FragmentRef::Create(*g_NullSymbolFragment, 0));
+    ResolveInfo::Null()->setSymPtr(&*g_NullSymbol);
   }
-  return g_NullSymbol;
+  return &*g_NullSymbol;
 }
 
 void LDSymbol::setFragmentRef(FragmentRef* pFragmentRef)
diff --git a/lib/LD/LDWriter.cpp b/lib/LD/LDWriter.cpp
deleted file mode 100644
index e78f087..0000000
--- a/lib/LD/LDWriter.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-//===- LDWriter.cpp -------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/LD/LDWriter.h"
-
-using namespace mcld;
-
-//==========================
-// LDReader
-
diff --git a/lib/LD/NamePool.cpp b/lib/LD/NamePool.cpp
index 6af1f7d..7fb8688 100644
--- a/lib/LD/NamePool.cpp
+++ b/lib/LD/NamePool.cpp
@@ -22,6 +22,11 @@
 NamePool::~NamePool()
 {
   delete m_pResolver;
+
+  FreeInfoSet::iterator info, iEnd = m_FreeInfoSet.end();
+  for (info = m_FreeInfoSet.begin(); info != iEnd; ++info) {
+    ResolveInfo::Destroy(*info);
+  }
 }
 
 /// createSymbol - create a symbol
@@ -33,15 +38,16 @@
                                     ResolveInfo::SizeType pSize,
                                     ResolveInfo::Visibility pVisibility)
 {
-  ResolveInfo* result = ResolveInfo::Create(pName);
-  result->setIsSymbol(true);
-  result->setSource(pIsDyn);
-  result->setType(pType);
-  result->setDesc(pDesc);
-  result->setBinding(pBinding);
-  result->setVisibility(pVisibility);
-  result->setSize(pSize);
-  return result;
+  ResolveInfo** result = m_FreeInfoSet.allocate();
+  (*result) = ResolveInfo::Create(pName);
+  (*result)->setIsSymbol(true);
+  (*result)->setSource(pIsDyn);
+  (*result)->setType(pType);
+  (*result)->setDesc(pDesc);
+  (*result)->setBinding(pBinding);
+  (*result)->setVisibility(pVisibility);
+  (*result)->setSize(pSize);
+  return *result;
 }
 
 /// insertSymbol - insert a symbol and resolve it immediately
@@ -65,7 +71,6 @@
   ResolveInfo* old_symbol = m_Table.insert(pName, exist);
   ResolveInfo* new_symbol = NULL;
   if (exist && old_symbol->isSymbol()) {
-    exist = true;
     new_symbol = m_Table.getEntryFactory().produce(pName);
   }
   else {
@@ -82,7 +87,7 @@
   new_symbol->setSize(pSize);
 
   if (!exist) {
-    // not exit or not a symbol
+    // old_symbol is neither existed nor a symbol.
     pResult.info      = new_symbol;
     pResult.existent  = false;
     pResult.overriden = true;
@@ -102,8 +107,11 @@
     pResult.existent  = true;
     pResult.overriden = override;
   }
-  else
+  else {
       m_pResolver->resolveAgain(*this, action, *old_symbol, *new_symbol, pResult);
+  }
+
+  m_Table.getEntryFactory().destroy(new_symbol);
   return;
 }
 
diff --git a/lib/LD/ObjectWriter.cpp b/lib/LD/ObjectWriter.cpp
index 15691f2..17d04eb 100644
--- a/lib/LD/ObjectWriter.cpp
+++ b/lib/LD/ObjectWriter.cpp
@@ -7,14 +7,12 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/ObjectWriter.h>
-#include <mcld/MC/MCLDInput.h>
-#include <mcld/Target/GNULDBackend.h>
 
 using namespace mcld;
 
 //==========================
 // ObjectWriter
-ObjectWriter::ObjectWriter(GNULDBackend& pBackend)
+ObjectWriter::ObjectWriter()
 {
 }
 
diff --git a/lib/LD/RelocationFactory.cpp b/lib/LD/RelocationFactory.cpp
index 52bf45c..8a065a8 100644
--- a/lib/LD/RelocationFactory.cpp
+++ b/lib/LD/RelocationFactory.cpp
@@ -71,18 +71,16 @@
     pFragRef.memcpy(&target_data, (m_pConfig->targets().bitclass()/8));
   }
 
-  Relocation *result = allocate();
+  Relocation* result = allocate();
   new (result) Relocation(pType, &pFragRef, pAddend, target_data);
   return result;
 }
 
 Relocation* RelocationFactory::produceEmptyEntry()
 {
-  // FIXME: To prevent relocations from double free by both iplist and
-  // GCFactory, currently we new relocations directly and let iplist
-  // delete them.
-
-  return new Relocation(0, 0, 0, 0);
+  Relocation* result = allocate();
+  new (result) Relocation(0, 0, 0, 0);
+  return result;
 }
 
 void RelocationFactory::destroy(Relocation* pRelocation)
diff --git a/lib/LD/Relocator.cpp b/lib/LD/Relocator.cpp
new file mode 100644
index 0000000..d9dfb61
--- /dev/null
+++ b/lib/LD/Relocator.cpp
@@ -0,0 +1,19 @@
+//===- Relocator.cpp ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/Relocator.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// Relocator
+//===----------------------------------------------------------------------===//
+Relocator::~Relocator()
+{
+}
+
diff --git a/lib/LD/ResolveInfo.cpp b/lib/LD/ResolveInfo.cpp
index 00df6ae..42ee83c 100644
--- a/lib/LD/ResolveInfo.cpp
+++ b/lib/LD/ResolveInfo.cpp
@@ -275,6 +275,7 @@
     new (g_NullResolveInfo) ResolveInfo();
     g_NullResolveInfo->m_Name[0] = '\0';
     g_NullResolveInfo->m_BitField = 0x0;
+    g_NullResolveInfo->setBinding(Local);
   }
   return g_NullResolveInfo;
 }
diff --git a/lib/LD/StubFactory.cpp b/lib/LD/StubFactory.cpp
index cbe14b2..0124ec0 100644
--- a/lib/LD/StubFactory.cpp
+++ b/lib/LD/StubFactory.cpp
@@ -7,13 +7,13 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/StubFactory.h>
+#include <mcld/IRBuilder.h>
 #include <mcld/LD/BranchIslandFactory.h>
 #include <mcld/LD/BranchIsland.h>
 #include <mcld/LD/LDSymbol.h>
 #include <mcld/LD/ResolveInfo.h>
 #include <mcld/Fragment/Stub.h>
 #include <mcld/Fragment/Relocation.h>
-#include <mcld/Fragment/FragmentLinker.h>
 #include <mcld/Fragment/FragmentRef.h>
 
 #include <string>
@@ -39,7 +39,7 @@
 /// create - create a stub if needed, otherwise return NULL
 Stub* StubFactory::create(Relocation& pReloc,
                           uint64_t pTargetSymValue,
-                          FragmentLinker& pLinker,
+                          IRBuilder& pBuilder,
                           BranchIslandFactory& pBRIslandFactory)
 {
   // find if there is a prototype stub for the input relocation
@@ -74,9 +74,8 @@
 
       // create LDSymbol for the stub
       LDSymbol* symbol =
-        pLinker.defineSymbol<FragmentLinker::Force,
-                             FragmentLinker::Resolve>(name,
-                               false, // isDyn
+        pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
+                               name,
                                ResolveInfo::Function,
                                ResolveInfo::Define,
                                ResolveInfo::Local,
diff --git a/lib/MC/MCLDInput.cpp b/lib/MC/MCLDInput.cpp
index 1fc6cb5..a10466b 100644
--- a/lib/MC/MCLDInput.cpp
+++ b/lib/MC/MCLDInput.cpp
@@ -9,6 +9,7 @@
 #include <mcld/MC/MCLDInput.h>
 #include <mcld/MC/Attribute.h>
 #include <mcld/LD/LDContext.h>
+#include <mcld/Support/MemoryArea.h>
 
 using namespace mcld;
 
@@ -70,5 +71,7 @@
 {
   // Attribute is deleted by AttributeFactory
   // MemoryArea is deleted by MemoryAreaFactory
+  if (NULL != m_pMemArea)
+    m_pMemArea->clear();
 }
 
diff --git a/lib/MC/SearchDirs.cpp b/lib/MC/SearchDirs.cpp
index 12d08e2..940553e 100644
--- a/lib/MC/SearchDirs.cpp
+++ b/lib/MC/SearchDirs.cpp
@@ -56,7 +56,16 @@
     m_DirList.push_back(dir);
     return true;
   }
-  return false;
+  else {
+    delete dir;
+    return false;
+  }
+  return true;
+}
+
+bool SearchDirs::insert(const char* pPath)
+{
+  return insert(std::string(pPath));
 }
 
 bool SearchDirs::insert(const sys::fs::Path& pPath)
diff --git a/lib/MC/SymbolCategory.cpp b/lib/MC/SymbolCategory.cpp
index f01083f..3c3881a 100644
--- a/lib/MC/SymbolCategory.cpp
+++ b/lib/MC/SymbolCategory.cpp
@@ -10,6 +10,7 @@
 #include <mcld/LD/LDSymbol.h>
 #include <mcld/LD/ResolveInfo.h>
 #include <algorithm>
+#include <cassert>
 
 using namespace mcld;
 
@@ -24,33 +25,34 @@
     return Category::Local;
   if (ResolveInfo::Common == pInfo.desc())
     return Category::Common;
-  if (ResolveInfo::Weak == pInfo.binding())
-    return Category::Weak;
-  return Category::Global;
+  if (ResolveInfo::Default   == pInfo.visibility() ||
+      ResolveInfo::Protected == pInfo.visibility())
+    return Category::Dynamic;
+  return Category::Regular;
 }
 
 //===----------------------------------------------------------------------===//
 // SymbolCategory
 SymbolCategory::SymbolCategory()
 {
-  m_pFile   = new Category(Category::File);
-  m_pLocal  = new Category(Category::Local);
-  m_pTLS    = new Category(Category::TLS);
-  m_pCommon = new Category(Category::Common);
-  m_pWeak   = new Category(Category::Weak);
-  m_pGlobal = new Category(Category::Global);
+  m_pFile     = new Category(Category::File);
+  m_pLocal    = new Category(Category::Local);
+  m_pLocalDyn = new Category(Category::LocalDyn);
+  m_pCommon   = new Category(Category::Common);
+  m_pDynamic  = new Category(Category::Dynamic);
+  m_pRegular  = new Category(Category::Regular);
 
-  m_pFile->next   = m_pLocal;
-  m_pLocal->next  = m_pTLS;
-  m_pTLS->next    = m_pCommon;
-  m_pCommon->next = m_pWeak;
-  m_pWeak->next   = m_pGlobal;
+  m_pFile->next     = m_pLocal;
+  m_pLocal->next    = m_pLocalDyn;
+  m_pLocalDyn->next = m_pCommon;
+  m_pCommon->next   = m_pDynamic;
+  m_pDynamic->next  = m_pRegular;
 
-  m_pGlobal->prev = m_pWeak;
-  m_pWeak->prev   = m_pCommon;
-  m_pCommon->prev = m_pTLS;
-  m_pTLS->prev    = m_pLocal;
-  m_pLocal->prev  = m_pFile;
+  m_pRegular->prev  = m_pDynamic;
+  m_pDynamic->prev  = m_pCommon;
+  m_pCommon->prev   = m_pLocalDyn;
+  m_pLocalDyn->prev = m_pLocal;
+  m_pLocal->prev    = m_pFile;
 }
 
 SymbolCategory::~SymbolCategory()
@@ -63,18 +65,14 @@
   }
 }
 
-SymbolCategory& SymbolCategory::add(LDSymbol& pSymbol)
+SymbolCategory& SymbolCategory::add(LDSymbol& pSymbol, Category::Type pTarget)
 {
+  Category* current = m_pRegular;
   m_OutputSymbols.push_back(&pSymbol);
 
-  assert(NULL != pSymbol.resolveInfo());
-  Category::Type target = Category::categorize(*pSymbol.resolveInfo());
-
-  Category* current = m_pGlobal;
-
   // use non-stable bubble sort to arrange the order of symbols.
   while (NULL != current) {
-    if (current->type == target) {
+    if (current->type == pTarget) {
       current->end++;
       break;
     }
@@ -91,23 +89,19 @@
   return *this;
 }
 
-SymbolCategory& SymbolCategory::forceLocal(LDSymbol& pSymbol)
+SymbolCategory& SymbolCategory::add(LDSymbol& pSymbol)
 {
-  m_OutputSymbols.insert(localEnd(), &pSymbol);
-  m_pLocal->end++;
-  m_pTLS->begin++;
-  m_pTLS->end++;
-  m_pCommon->begin++;
-  m_pCommon->end++;
-  m_pWeak->begin++;
-  m_pWeak->end++;
-  m_pGlobal->begin++;
-  m_pGlobal->end++;
-
-  return *this;
+  assert(NULL != pSymbol.resolveInfo());
+  return add(pSymbol, Category::categorize(*pSymbol.resolveInfo()));
 }
 
-SymbolCategory& SymbolCategory::arrange(LDSymbol& pSymbol, const ResolveInfo& pSourceInfo)
+SymbolCategory& SymbolCategory::forceLocal(LDSymbol& pSymbol)
+{
+  return add(pSymbol, Category::Local);
+}
+
+SymbolCategory& SymbolCategory::arrange(LDSymbol& pSymbol,
+                                        const ResolveInfo& pSourceInfo)
 {
   assert(NULL != pSymbol.resolveInfo());
   Category::Type source = Category::categorize(pSourceInfo);
@@ -188,27 +182,30 @@
 
 SymbolCategory& SymbolCategory::changeCommonsToGlobal()
 {
-  if (emptyCommons())
-    return *this;
-
-  size_t com_rear = m_pCommon->end - 1;
-  size_t com_front = m_pCommon->begin;
-  size_t weak_rear = m_pWeak->end - 1;
-  size_t weak_size = m_pWeak->end - m_pWeak->begin;
-  for (size_t sym = com_rear; sym >= com_front; --sym) {
-    std::swap(m_OutputSymbols[weak_rear], m_OutputSymbols[sym]);
-    --weak_rear;
+  // Change Common to Dynamic/Regular
+  while (!emptyCommons()) {
+    size_t pos = m_pCommon->end - 1;
+    switch (Category::categorize(*(m_OutputSymbols[pos]->resolveInfo()))) {
+    case Category::Dynamic:
+      m_pCommon->end--;
+      m_pDynamic->begin--;
+      break;
+    case Category::Regular:
+      std::swap(m_OutputSymbols[pos], m_OutputSymbols[m_pDynamic->end - 1]);
+      m_pCommon->end--;
+      m_pDynamic->begin--;
+      m_pDynamic->end--;
+      m_pRegular->begin--;
+      break;
+    default:
+      assert(0);
+      break;
+    }
   }
-
-  m_pWeak->begin = m_pCommon->begin;
-  m_pWeak->end = m_pCommon->begin + weak_size;
-  m_pGlobal->begin = m_pWeak->end;
-  m_pCommon->begin = m_pCommon->end = m_pWeak->begin;
-
   return *this;
 }
 
-SymbolCategory& SymbolCategory::changeLocalToTLS(const LDSymbol& pSymbol)
+SymbolCategory& SymbolCategory::changeLocalToDynamic(const LDSymbol& pSymbol)
 {
   // find the position of pSymbol from local category
   size_t pos = m_pLocal->begin;
@@ -222,10 +219,10 @@
   if (m_pLocal->end == pos)
     return *this;
 
-  // bubble sort downward to TLS
+  // bubble sort downward to LocalDyn
   std::swap(m_OutputSymbols[pos], m_OutputSymbols[m_pLocal->end - 1]);
   m_pLocal->end--;
-  m_pTLS->begin--;
+  m_pLocalDyn->begin--;
   return *this;
 }
 
@@ -234,9 +231,19 @@
   return m_OutputSymbols.size();
 }
 
+size_t SymbolCategory::numOfFiles() const
+{
+  return m_pFile->size();
+}
+
 size_t SymbolCategory::numOfLocals() const
 {
-  return (m_pFile->size() + m_pLocal->size() + m_pTLS->size());
+  return m_pLocal->size();
+}
+
+size_t SymbolCategory::numOfLocalDyns() const
+{
+  return m_pLocalDyn->size();
 }
 
 size_t SymbolCategory::numOfCommons() const
@@ -244,21 +251,34 @@
   return m_pCommon->size();
 }
 
+size_t SymbolCategory::numOfDynamics() const
+{
+  return m_pDynamic->size();
+}
+
 size_t SymbolCategory::numOfRegulars() const
 {
-  return (m_pWeak->size() + m_pGlobal->size());
+  return m_pRegular->size();
 }
 
 bool SymbolCategory::empty() const
 {
-  return (emptyLocals() &&
-          emptyCommons() &&
-          emptyRegulars());
+  return m_OutputSymbols.empty();
+}
+
+bool SymbolCategory::emptyFiles() const
+{
+  return m_pFile->empty();
 }
 
 bool SymbolCategory::emptyLocals() const
 {
-  return (m_pFile->empty() && m_pLocal->empty() && m_pTLS->empty());
+  return m_pLocal->empty();
+}
+
+bool SymbolCategory::emptyLocalDyns() const
+{
+  return m_pLocalDyn->empty();
 }
 
 bool SymbolCategory::emptyCommons() const
@@ -266,9 +286,14 @@
   return m_pCommon->empty();
 }
 
+bool SymbolCategory::emptyDynamics() const
+{
+  return m_pDynamic->empty();
+}
+
 bool SymbolCategory::emptyRegulars() const
 {
-  return (m_pWeak->empty() && m_pGlobal->empty());
+  return m_pRegular->empty();
 }
 
 SymbolCategory::iterator SymbolCategory::begin()
@@ -291,80 +316,126 @@
   return m_OutputSymbols.end();
 }
 
-SymbolCategory::iterator SymbolCategory::localBegin()
+SymbolCategory::iterator SymbolCategory::fileBegin()
 {
   return m_OutputSymbols.begin();
 }
 
+SymbolCategory::iterator SymbolCategory::fileEnd()
+{
+  iterator iter = fileBegin();
+  iter += m_pFile->size();
+  return iter;
+}
+
+SymbolCategory::const_iterator SymbolCategory::fileBegin() const
+{
+  return m_OutputSymbols.begin();
+}
+
+SymbolCategory::const_iterator SymbolCategory::fileEnd() const
+{
+  const_iterator iter = fileBegin();
+  iter += m_pFile->size();
+  return iter;
+}
+
+SymbolCategory::iterator SymbolCategory::localBegin()
+{
+  return fileEnd();
+}
+
 SymbolCategory::iterator SymbolCategory::localEnd()
 {
-  iterator iter = m_OutputSymbols.begin();
-  iter += m_pFile->size();
+  iterator iter = localBegin();
   iter += m_pLocal->size();
   return iter;
 }
 
 SymbolCategory::const_iterator SymbolCategory::localBegin() const
 {
-  return m_OutputSymbols.begin();
+  return fileEnd();
 }
 
 SymbolCategory::const_iterator SymbolCategory::localEnd() const
 {
-  const_iterator iter = m_OutputSymbols.begin();
-  iter += m_pFile->size();
+  const_iterator iter = localBegin();
   iter += m_pLocal->size();
   return iter;
 }
 
-SymbolCategory::iterator SymbolCategory::tlsBegin()
+SymbolCategory::iterator SymbolCategory::localDynBegin()
 {
   return localEnd();
 }
 
-SymbolCategory::iterator SymbolCategory::tlsEnd()
+SymbolCategory::iterator SymbolCategory::localDynEnd()
 {
-  iterator iter = localEnd();
-  iter += m_pTLS->size();
+  iterator iter = localDynBegin();
+  iter += m_pLocalDyn->size();
   return iter;
 }
 
-SymbolCategory::const_iterator SymbolCategory::tlsBegin() const
+SymbolCategory::const_iterator SymbolCategory::localDynBegin() const
 {
   return localEnd();
 }
 
-SymbolCategory::const_iterator SymbolCategory::tlsEnd() const
+SymbolCategory::const_iterator SymbolCategory::localDynEnd() const
 {
-  const_iterator iter = localEnd();
-  iter += m_pTLS->size();
+  const_iterator iter = localDynBegin();
+  iter += m_pLocalDyn->size();
   return iter;
 }
 
 SymbolCategory::iterator SymbolCategory::commonBegin()
 {
-  return tlsEnd();
+  return localDynEnd();
 }
 
 SymbolCategory::iterator SymbolCategory::commonEnd()
 {
-  iterator iter = tlsEnd();
+  iterator iter = commonBegin();
   iter += m_pCommon->size();
   return iter;
 }
 
 SymbolCategory::const_iterator SymbolCategory::commonBegin() const
 {
-  return tlsEnd();
+  return localDynEnd();
 }
 
 SymbolCategory::const_iterator SymbolCategory::commonEnd() const
 {
-  const_iterator iter = tlsEnd();
+  const_iterator iter = commonBegin();
   iter += m_pCommon->size();
   return iter;
 }
 
+SymbolCategory::iterator SymbolCategory::dynamicBegin()
+{
+  return commonEnd();
+}
+
+SymbolCategory::iterator SymbolCategory::dynamicEnd()
+{
+  iterator iter = dynamicBegin();
+  iter += m_pDynamic->size();
+  return iter;
+}
+
+SymbolCategory::const_iterator SymbolCategory::dynamicBegin() const
+{
+  return commonEnd();
+}
+
+SymbolCategory::const_iterator SymbolCategory::dynamicEnd() const
+{
+  const_iterator iter = dynamicBegin();
+  iter += m_pDynamic->size();
+  return iter;
+}
+
 SymbolCategory::iterator SymbolCategory::regularBegin()
 {
   return commonEnd();
diff --git a/lib/Object/ObjectBuilder.cpp b/lib/Object/ObjectBuilder.cpp
index ec09901..d222110 100644
--- a/lib/Object/ObjectBuilder.cpp
+++ b/lib/Object/ObjectBuilder.cpp
@@ -49,7 +49,7 @@
 }
 
 /// MergeSection - merge the pInput section to the pOutput section
-bool ObjectBuilder::MergeSection(LDSection& pInputSection)
+LDSection* ObjectBuilder::MergeSection(LDSection& pInputSection)
 {
   const SectionMap::NamePair& pair =
               m_Config.scripts().sectionMap().find(pInputSection.name());
@@ -70,7 +70,7 @@
     case LDFileFormat::Relocation:
     case LDFileFormat::NamePool:
       /** do nothing **/
-      return true;
+      return target;
     case LDFileFormat::EhFrame: {
       EhFrame* eh_frame = NULL;
       if (target->hasEhFrame())
@@ -79,7 +79,8 @@
         eh_frame = IRBuilder::CreateEhFrame(*target);
 
       eh_frame->merge(*pInputSection.getEhFrame());
-      return true;
+			UpdateSectionAlign(*target, pInputSection);
+      return target;
     }
     default: {
       SectionData* data = NULL;
@@ -88,10 +89,14 @@
       else
         data = IRBuilder::CreateSectionData(*target);
 
-      return MoveSectionData(*pInputSection.getSectionData(), *data);
+      if (MoveSectionData(*pInputSection.getSectionData(), *data)) {
+        UpdateSectionAlign(*target, pInputSection);
+        return target;
+      }
+      return NULL;
     }
   }
-  return true;
+  return target;
 }
 
 /// MoveSectionData - move the fragments of pTO section data to pTo
@@ -125,20 +130,19 @@
   }
   to_list.splice(to_list.end(), from_list);
 
-  // append the null fragment
-  NullFragment* null = new NullFragment();
-  null->setParent(&pTo);
-  null->setOffset(offset);
-  pTo.getFragmentList().push_back(null);
-
   // set up pTo's header
   pTo.getSection().setSize(offset);
-  if (pFrom.getSection().align() > pTo.getSection().align())
-    pTo.getSection().setAlign(pFrom.getSection().align());
 
   return true;
 }
 
+/// UpdateSectionFlags - update alignment for input section
+void ObjectBuilder::UpdateSectionAlign(LDSection& pTo, const LDSection& pFrom)
+{
+  if (pFrom.align() > pTo.align())
+    pTo.setAlign(pFrom.align());
+}
+
 /// AppendFragment - To append pFrag to the given SectionData pSD.
 uint64_t ObjectBuilder::AppendFragment(Fragment& pFrag,
                                        SectionData& pSD,
diff --git a/lib/Object/ObjectLinker.cpp b/lib/Object/ObjectLinker.cpp
index 1e2ccb4..bbca437 100644
--- a/lib/Object/ObjectLinker.cpp
+++ b/lib/Object/ObjectLinker.cpp
@@ -21,9 +21,6 @@
 #include <mcld/LD/GroupReader.h>
 #include <mcld/LD/BinaryReader.h>
 #include <mcld/LD/ObjectWriter.h>
-#include <mcld/LD/DynObjWriter.h>
-#include <mcld/LD/ExecWriter.h>
-#include <mcld/LD/BinaryWriter.h>
 #include <mcld/LD/ResolveInfo.h>
 #include <mcld/LD/RelocData.h>
 #include <mcld/Support/RealPath.h>
@@ -35,32 +32,23 @@
 
 #include <llvm/Support/Casting.h>
 
+
 using namespace llvm;
 using namespace mcld;
 
 ObjectLinker::ObjectLinker(const LinkerConfig& pConfig,
-                           Module& pModule,
-                           IRBuilder& pBuilder,
                            TargetLDBackend& pLDBackend)
   : m_Config(pConfig),
-    m_Module(pModule),
-    m_Builder(pBuilder),
     m_pLinker(NULL),
+    m_pModule(NULL),
+    m_pBuilder(NULL),
     m_LDBackend(pLDBackend),
     m_pObjectReader(NULL),
     m_pDynObjReader(NULL),
     m_pArchiveReader(NULL),
     m_pGroupReader(NULL),
     m_pBinaryReader(NULL),
-    m_pObjectWriter(NULL),
-    m_pDynObjWriter(NULL),
-    m_pExecWriter(NULL),
-    m_pBinaryWriter(NULL)
-{
-  // set up soname
-  if (!m_Config.options().soname().empty()) {
-    m_Module.setName(m_Config.options().soname());
-  }
+    m_pWriter(NULL) {
 }
 
 ObjectLinker::~ObjectLinker()
@@ -71,10 +59,17 @@
   delete m_pArchiveReader;
   delete m_pGroupReader;
   delete m_pBinaryReader;
-  delete m_pObjectWriter;
-  delete m_pDynObjWriter;
-  delete m_pExecWriter;
-  delete m_pBinaryWriter;
+  delete m_pWriter;
+}
+
+void ObjectLinker::setup(Module& pModule, IRBuilder& pBuilder)
+{
+  m_pModule = &pModule;
+  m_pBuilder = &pBuilder;
+  // set up soname
+  if (!m_Config.options().soname().empty()) {
+    m_pModule->setName(m_Config.options().soname());
+  }
 }
 
 /// initFragmentLinker - initialize FragmentLinker
@@ -83,49 +78,37 @@
 {
   if (NULL == m_pLinker) {
     m_pLinker = new FragmentLinker(m_Config,
-                                   m_Module,
+                                   *m_pModule,
                                    m_LDBackend);
   }
 
   // initialize the readers and writers
   // Because constructor can not be failed, we initalize all readers and
   // writers outside the FragmentLinker constructors.
-  m_pObjectReader  = m_LDBackend.createObjectReader(m_Builder);
-  m_pArchiveReader = m_LDBackend.createArchiveReader(m_Module);
-  m_pDynObjReader  = m_LDBackend.createDynObjReader(m_Builder);
-  m_pGroupReader   = new GroupReader(m_Module, *m_pObjectReader,
+  m_pObjectReader  = m_LDBackend.createObjectReader(*m_pBuilder);
+  m_pArchiveReader = m_LDBackend.createArchiveReader(*m_pModule);
+  m_pDynObjReader  = m_LDBackend.createDynObjReader(*m_pBuilder);
+  m_pGroupReader   = new GroupReader(*m_pModule, *m_pObjectReader,
                                      *m_pDynObjReader, *m_pArchiveReader);
-  m_pBinaryReader  = m_LDBackend.createBinaryReader(m_Builder);
-  m_pObjectWriter  = m_LDBackend.createObjectWriter();
-  m_pDynObjWriter  = m_LDBackend.createDynObjWriter();
-  m_pExecWriter    = m_LDBackend.createExecWriter();
-  m_pBinaryWriter  = m_LDBackend.createBinaryWriter();
+  m_pBinaryReader  = m_LDBackend.createBinaryReader(*m_pBuilder);
+  m_pWriter        = m_LDBackend.createWriter();
 
   // initialize Relocator
-  m_LDBackend.initRelocator(*m_pLinker);
-
-  // initialize BranchIslandFactory
-  m_LDBackend.initBRIslandFactory();
-
-  // initialize StubFactory
-  m_LDBackend.initStubFactory();
-
-  // initialize target stubs
-  m_LDBackend.initTargetStubs(*m_pLinker);
+  m_LDBackend.initRelocator();
   return true;
 }
 
 /// initStdSections - initialize standard sections
 bool ObjectLinker::initStdSections()
 {
-  ObjectBuilder builder(m_Config, m_Module);
+  ObjectBuilder builder(m_Config, *m_pModule);
 
   // initialize standard sections
   if (!m_LDBackend.initStdSections(builder))
     return false;
 
   // initialize target-dependent sections
-  m_LDBackend.initTargetSections(m_Module, builder);
+  m_LDBackend.initTargetSections(*m_pModule, builder);
 
   return true;
 }
@@ -133,11 +116,11 @@
 void ObjectLinker::normalize()
 {
   // -----  set up inputs  ----- //
-  Module::input_iterator input, inEnd = m_Module.input_end();
-  for (input = m_Module.input_begin(); input!=inEnd; ++input) {
+  Module::input_iterator input, inEnd = m_pModule->input_end();
+  for (input = m_pModule->input_begin(); input!=inEnd; ++input) {
     // is a group node
     if (isGroup(input)) {
-      getGroupReader()->readGroup(input, m_Builder.getInputBuilder(), m_Config);
+      getGroupReader()->readGroup(input, m_pBuilder->getInputBuilder(), m_Config);
       continue;
     }
 
@@ -149,12 +132,12 @@
       continue;
 
     if (Input::Object == (*input)->type()) {
-      m_Module.getObjectList().push_back(*input);
+      m_pModule->getObjectList().push_back(*input);
       continue;
     }
 
     if (Input::DynObj == (*input)->type()) {
-      m_Module.getLibraryList().push_back(*input);
+      m_pModule->getLibraryList().push_back(*input);
       continue;
     }
 
@@ -162,7 +145,7 @@
     if (m_Config.options().isBinaryInput()) {
       (*input)->setType(Input::Object);
       getBinaryReader()->readBinary(**input);
-      m_Module.getObjectList().push_back(*input);
+      m_pModule->getObjectList().push_back(*input);
     }
     // is a relocatable object file
     else if (getObjectReader()->isMyFormat(**input)) {
@@ -170,22 +153,22 @@
       getObjectReader()->readHeader(**input);
       getObjectReader()->readSections(**input);
       getObjectReader()->readSymbols(**input);
-      m_Module.getObjectList().push_back(*input);
+      m_pModule->getObjectList().push_back(*input);
     }
     // is a shared object file
     else if (getDynObjReader()->isMyFormat(**input)) {
       (*input)->setType(Input::DynObj);
       getDynObjReader()->readHeader(**input);
       getDynObjReader()->readSymbols(**input);
-      m_Module.getLibraryList().push_back(*input);
+      m_pModule->getLibraryList().push_back(*input);
     }
     // is an archive
     else if (getArchiveReader()->isMyFormat(**input)) {
       (*input)->setType(Input::Archive);
-      Archive archive(**input, m_Builder.getInputBuilder());
+      Archive archive(**input, m_pBuilder->getInputBuilder());
       getArchiveReader()->readArchive(archive);
       if(archive.numOfObjectMember() > 0) {
-        m_Module.getInputTree().merge<InputTree::Inclusive>(input,
+        m_pModule->getInputTree().merge<InputTree::Inclusive>(input,
                                                             archive.inputs());
       }
     }
@@ -199,14 +182,14 @@
 bool ObjectLinker::linkable() const
 {
   // check we have input and output files
-  if (m_Module.getInputTree().empty()) {
+  if (m_pModule->getInputTree().empty()) {
     error(diag::err_no_inputs);
     return false;
   }
 
   // can not mix -static with shared objects
-  Module::const_lib_iterator lib, libEnd = m_Module.lib_end();
-  for (lib = m_Module.lib_begin(); lib != libEnd; ++lib) {
+  Module::const_lib_iterator lib, libEnd = m_pModule->lib_end();
+  for (lib = m_pModule->lib_begin(); lib != libEnd; ++lib) {
     if((*lib)->attribute()->isStatic()) {
       error(diag::err_mixed_shared_static_objects)
                                       << (*lib)->name() << (*lib)->path();
@@ -214,7 +197,21 @@
     }
   }
 
-  // can not mix -r with shared objects
+  // --nmagic and --omagic options lead to static executable program.
+  // These options turn off page alignment of sections. Because the
+  // sections are not aligned to pages, these sections can not contain any
+  // exported functions. Also, because the two options disable linking
+  // against shared libraries, the output absolutely does not call outside
+  // functions.
+  if (m_Config.options().nmagic() && !m_Config.isCodeStatic()) {
+    error(diag::err_nmagic_not_static);
+    return false;
+  }
+  if (m_Config.options().omagic() && !m_Config.isCodeStatic()) {
+    error(diag::err_omagic_not_static);
+    return false;
+  }
+
   return true;
 }
 
@@ -225,8 +222,8 @@
 {
   // Bitcode is read by the other path. This function reads relocation sections
   // in object files.
-  mcld::InputTree::bfs_iterator input, inEnd = m_Module.getInputTree().bfs_end();
-  for (input=m_Module.getInputTree().bfs_begin(); input!=inEnd; ++input) {
+  mcld::InputTree::bfs_iterator input, inEnd = m_pModule->getInputTree().bfs_end();
+  for (input=m_pModule->getInputTree().bfs_begin(); input!=inEnd; ++input) {
     if ((*input)->type() == Input::Object && (*input)->hasMemArea()) {
       if (!getObjectReader()->readRelocations(**input))
         return false;
@@ -239,9 +236,9 @@
 /// mergeSections - put allinput sections into output sections
 bool ObjectLinker::mergeSections()
 {
-  ObjectBuilder builder(m_Config, m_Module);
-  Module::obj_iterator obj, objEnd = m_Module.obj_end();
-  for (obj = m_Module.obj_begin(); obj != objEnd; ++obj) {
+  ObjectBuilder builder(m_Config, *m_pModule);
+  Module::obj_iterator obj, objEnd = m_pModule->obj_end();
+  for (obj = m_pModule->obj_begin(); obj != objEnd; ++obj) {
     LDContext::sect_iterator sect, sectEnd = (*obj)->context()->sectEnd();
     for (sect = (*obj)->context()->sectBegin(); sect != sectEnd; ++sect) {
       switch ((*sect)->kind()) {
@@ -255,7 +252,7 @@
           // skip
           continue;
         case LDFileFormat::Target:
-          if (!m_LDBackend.mergeSection(m_Module, **sect)) {
+          if (!m_LDBackend.mergeSection(*m_pModule, **sect)) {
             error(diag::err_cannot_merge_section) << (*sect)->name()
                                                   << (*obj)->name();
             return false;
@@ -265,7 +262,7 @@
           if (!(*sect)->hasEhFrame())
             continue; // skip
 
-          if (!builder.MergeSection(**sect)) {
+          if (NULL == builder.MergeSection(**sect)) {
             error(diag::err_cannot_merge_section) << (*sect)->name()
                                                   << (*obj)->name();
             return false;
@@ -276,7 +273,15 @@
           if (!(*sect)->hasSectionData())
             continue; // skip
 
-          if (!builder.MergeSection(**sect)) {
+          LDSection* out_sect = builder.MergeSection(**sect);
+          if (NULL != out_sect) {
+            if (!m_LDBackend.updateSectionFlags(*out_sect, **sect)) {
+              error(diag::err_cannot_merge_section) << (*sect)->name()
+                                                    << (*obj)->name();
+              return false;
+            }
+          }
+          else {
             error(diag::err_cannot_merge_section) << (*sect)->name()
                                                   << (*obj)->name();
             return false;
@@ -296,12 +301,12 @@
 bool ObjectLinker::addStandardSymbols()
 {
   // create and add section symbols for each output section
-  Module::iterator iter, iterEnd = m_Module.end();
-  for (iter = m_Module.begin(); iter != iterEnd; ++iter) {
-    m_Module.getSectionSymbolSet().add(**iter, m_Module.getNamePool());
+  Module::iterator iter, iterEnd = m_pModule->end();
+  for (iter = m_pModule->begin(); iter != iterEnd; ++iter) {
+    m_pModule->getSectionSymbolSet().add(**iter, m_pModule->getNamePool());
   }
 
-  return m_LDBackend.initStandardSymbols(*m_pLinker, m_Module);
+  return m_LDBackend.initStandardSymbols(*m_pBuilder, *m_pModule);
 }
 
 /// addTargetSymbols - some targets, such as MIPS and ARM, need some
@@ -310,15 +315,24 @@
 ///   target symbols, return false
 bool ObjectLinker::addTargetSymbols()
 {
-  m_LDBackend.initTargetSymbols(*m_pLinker);
+  m_LDBackend.initTargetSymbols(*m_pBuilder, *m_pModule);
+  return true;
+}
+
+/// addScriptSymbols - define symbols from the command line option or linker
+/// scripts.
+///   @return if there are some existing symbols with identical name to the
+///   script symbols, return false.
+bool ObjectLinker::addScriptSymbols()
+{
   return true;
 }
 
 bool ObjectLinker::scanRelocations()
 {
   // apply all relocations of all inputs
-  Module::obj_iterator input, inEnd = m_Module.obj_end();
-  for (input = m_Module.obj_begin(); input != inEnd; ++input) {
+  Module::obj_iterator input, inEnd = m_pModule->obj_end();
+  for (input = m_pModule->obj_begin(); input != inEnd; ++input) {
     LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
     for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
       // bypass the reloc section if
@@ -332,42 +346,54 @@
       for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
         Relocation* relocation = llvm::cast<Relocation>(reloc);
         // scan relocation
-        if (LinkerConfig::Object != m_Config.codeGenType()) {
-          m_LDBackend.scanRelocation(*relocation,
-                                     *m_pLinker,
-                                     m_Module,
-                                     *(*rs)->getLink());
-        }
-        else {
-          m_LDBackend.partialScanRelocation(*relocation,
-                                     *m_pLinker,
-                                     m_Module,
-                                     *(*rs)->getLink());
-        }
+        if (LinkerConfig::Object != m_Config.codeGenType())
+          m_LDBackend.scanRelocation(*relocation, *m_pBuilder, *m_pModule, **rs);
+        else
+          m_LDBackend.partialScanRelocation(*relocation, *m_pModule, **rs);
       } // for all relocations
     } // for all relocation section
   } // for all inputs
   return true;
 }
 
+/// initStubs - initialize stub-related stuff.
+bool ObjectLinker::initStubs()
+{
+  // initialize BranchIslandFactory
+  m_LDBackend.initBRIslandFactory();
+
+  // initialize StubFactory
+  m_LDBackend.initStubFactory();
+
+  // initialize target stubs
+  m_LDBackend.initTargetStubs();
+  return true;
+}
+
+/// allocateCommonSymobols - allocate fragments for common symbols to the
+/// corresponding sections
+bool ObjectLinker::allocateCommonSymbols()
+{
+  if (LinkerConfig::Object != m_Config.codeGenType() ||
+      m_Config.options().isDefineCommon())
+    return m_LDBackend.allocateCommonSymbols(*m_pModule);
+  return true;
+}
+
 /// prelayout - help backend to do some modification before layout
 bool ObjectLinker::prelayout()
 {
   // finalize the section symbols, set their fragment reference and push them
   // into output symbol table
-  Module::iterator sect, sEnd = m_Module.end();
-  for (sect = m_Module.begin(); sect != sEnd; ++sect) {
-    m_Module.getSectionSymbolSet().finalize(**sect, m_Module.getSymbolTable());
+  Module::iterator sect, sEnd = m_pModule->end();
+  for (sect = m_pModule->begin(); sect != sEnd; ++sect) {
+    m_pModule->getSectionSymbolSet().finalize(**sect, m_pModule->getSymbolTable());
   }
 
-  m_LDBackend.preLayout(m_Module, *m_pLinker);
-
-  if (LinkerConfig::Object != m_Config.codeGenType() ||
-      m_Config.options().isDefineCommon())
-    m_LDBackend.allocateCommonSymbols(m_Module);
+  m_LDBackend.preLayout(*m_pModule, *m_pBuilder);
 
   /// check program interpreter - computer the name size of the runtime dyld
-  if (!m_pLinker->isStaticLink() &&
+  if (!m_Config.isCodeStatic() &&
       (LinkerConfig::Exec == m_Config.codeGenType() ||
        m_Config.options().isPIE() ||
        m_Config.options().hasDyld()))
@@ -379,7 +405,7 @@
   ///
   /// dump all symbols and strings from FragmentLinker and build the format-dependent
   /// hash table.
-  m_LDBackend.sizeNamePools(m_Module, m_pLinker->isStaticLink());
+  m_LDBackend.sizeNamePools(*m_pModule, m_Config.isCodeStatic());
 
   return true;
 }
@@ -391,14 +417,14 @@
 ///   directly
 bool ObjectLinker::layout()
 {
-  m_LDBackend.layout(m_Module, *m_pLinker);
+  m_LDBackend.layout(*m_pModule);
   return true;
 }
 
 /// prelayout - help backend to do some modification after layout
 bool ObjectLinker::postlayout()
 {
-  m_LDBackend.postLayout(m_Module, *m_pLinker);
+  m_LDBackend.postLayout(*m_pModule, *m_pBuilder);
   return true;
 }
 
@@ -407,7 +433,7 @@
 ///   symbol.
 bool ObjectLinker::finalizeSymbolValue()
 {
-  return m_pLinker->finalizeSymbols();
+  return (m_pLinker->finalizeSymbols() && m_LDBackend.finalizeSymbols());
 }
 
 /// relocate - applying relocation entries and create relocation
@@ -423,23 +449,7 @@
 /// emitOutput - emit the output file.
 bool ObjectLinker::emitOutput(MemoryArea& pOutput)
 {
-  switch(m_Config.codeGenType()) {
-    case LinkerConfig::Object:
-      getObjectWriter()->writeObject(m_Module, pOutput);
-      return true;
-    case LinkerConfig::DynObj:
-      getDynObjWriter()->writeDynObj(m_Module, pOutput);
-      return true;
-    case LinkerConfig::Exec:
-      getExecWriter()->writeExecutable(m_Module, pOutput);
-      return true;
-    case LinkerConfig::Binary:
-      getBinaryWriter()->writeBinary(m_Module, pOutput);
-      return true;
-    default:
-      fatal(diag::unrecognized_output_file) << m_Config.codeGenType();
-  }
-  return false;
+  return llvm::errc::success == getWriter()->writeObject(*m_pModule, pOutput);
 }
 
 /// postProcessing - do modification after all processes
@@ -450,7 +460,7 @@
   // emit .eh_frame_hdr
   // eh_frame_hdr should be emitted after syncRelocation, because eh_frame_hdr
   // needs FDE PC value, which will be corrected at syncRelocation
-  m_LDBackend.postProcessing(*m_pLinker, pOutput);
+  m_LDBackend.postProcessing(pOutput);
   return true;
 }
 
diff --git a/lib/Support/Directory.cpp b/lib/Support/Directory.cpp
index 78bb761..a47b162 100644
--- a/lib/Support/Directory.cpp
+++ b/lib/Support/Directory.cpp
@@ -26,8 +26,9 @@
 
 } // namespace of anonymous
 
-//==========================
+//===----------------------------------------------------------------------===//
 // Directory
+//===----------------------------------------------------------------------===//
 Directory::Directory()
   : m_Path(),
     m_FileStatus(),
@@ -165,16 +166,16 @@
 
 Path* DirIterator::path()
 {
-  if (m_pParent == 0) // end
-    return 0;
-  return m_pEntry->value();
+  if (NULL == m_pParent)
+    return NULL;
+  return &m_pEntry->value();
 }
 
 const Path* DirIterator::path() const
 {
-  if (m_pParent == 0) // end
-    return 0;
-  return m_pEntry->value();
+  if (NULL == m_pParent)
+    return NULL;
+  return &m_pEntry->value();
 }
 
 DirIterator& DirIterator::operator=(const DirIterator& pCopy)
diff --git a/lib/Support/FileHandle.cpp b/lib/Support/FileHandle.cpp
index 4800bfa..7876ac6 100644
--- a/lib/Support/FileHandle.cpp
+++ b/lib/Support/FileHandle.cpp
@@ -6,6 +6,7 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include "mcld/Config/Config.h"
 #include <mcld/Support/FileHandle.h>
 #include <mcld/Support/FileSystem.h>
 #include <errno.h>
@@ -127,7 +128,7 @@
 
   m_Handler = pFD;
   m_OpenMode = pMode;
-  m_State = GoodBit;
+  m_State = (GoodBit | DeputedBit);
 
   if (!get_size(m_Handler, m_Size)) {
     setState(FailBit);
@@ -144,9 +145,11 @@
     return false;
   }
 
-  if (-1 == ::close(m_Handler)) {
-    setState(FailBit);
-    return false;
+  if (isOwned()) {
+    if (-1 == ::close(m_Handler)) {
+      setState(FailBit);
+      return false;
+    }
   }
 
   m_Path.native().clear();
@@ -327,3 +330,8 @@
   return (m_State & (BadBit | FailBit));
 }
 
+bool FileHandle::isOwned() const
+{
+  return !(m_State & DeputedBit);
+}
+
diff --git a/lib/Support/FileSystem.cpp b/lib/Support/FileSystem.cpp
index fb2633d..715960e 100644
--- a/lib/Support/FileSystem.cpp
+++ b/lib/Support/FileSystem.cpp
@@ -6,6 +6,7 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include "mcld/Config/Config.h"
 #include "mcld/Support/FileSystem.h"
 #include "mcld/Support/Path.h"
 
diff --git a/lib/Support/MemoryArea.cpp b/lib/Support/MemoryArea.cpp
index 3a3fa0c..b5873bf 100644
--- a/lib/Support/MemoryArea.cpp
+++ b/lib/Support/MemoryArea.cpp
@@ -32,11 +32,6 @@
 
 MemoryArea::~MemoryArea()
 {
-  SpaceMapType::iterator space, sEnd = m_SpaceMap.end();
-  for (space = m_SpaceMap.begin(); space != sEnd; ++space) {
-    if (space->second != NULL)
-      Space::Destroy(space->second);
-  }
 }
 
 // The layout of MemorySpace in the virtual memory space
@@ -68,7 +63,7 @@
     }
 
     space = Space::Create(*m_pFileHandle, pOffset, pLength);
-    m_SpaceMap.insert(std::make_pair(Key(pOffset, pLength), space));
+    m_SpaceMap.insert(std::make_pair(Key(space->start(), space->size()), space));
   }
 
   // adjust r_start
@@ -98,8 +93,19 @@
         // synchronize writable space before we release it.
         Space::Sync(space, *m_pFileHandle);
       }
-      m_SpaceMap.erase(Key(space->start(), space->size()));
+
+      std::pair<SpaceMapType::iterator, SpaceMapType::iterator> range =
+        m_SpaceMap.equal_range(Key(space->start(), space->size()));
+      SpaceMapType::iterator it;
+      for (it = range.first; it != range.second; ++it) {
+        if (space == it->second)
+          break;
+      }
+      m_SpaceMap.erase(it);
+
       Space::Release(space, *m_pFileHandle);
+      assert(NULL != space);
+      Space::Destroy(space);
     }
   }
 }
@@ -110,24 +116,23 @@
   if (NULL == m_pFileHandle)
     return;
 
+  SpaceMapType::iterator space, sEnd = m_SpaceMap.end();
   if (m_pFileHandle->isWritable()) {
-    SpaceMapType::iterator space, sEnd = m_SpaceMap.end();
     for (space = m_SpaceMap.begin(); space != sEnd; ++space) {
       Space::Sync(space->second, *m_pFileHandle);
       Space::Release(space->second, *m_pFileHandle);
+      assert(NULL != space->second);
+      Space::Destroy(space->second);
     }
   }
   else {
-    SpaceMapType::iterator space, sEnd = m_SpaceMap.end();
-    for (space = m_SpaceMap.begin(); space != sEnd; ++space)
+    for (space = m_SpaceMap.begin(); space != sEnd; ++space) {
       Space::Release(space->second, *m_pFileHandle);
+      assert(NULL != space->second);
+      Space::Destroy(space->second);
+    }
   }
 
-  for (SpaceMapType::iterator space = m_SpaceMap.begin(),
-         sEnd = m_SpaceMap.end(); space != sEnd; ++space) {
-    if (space->second != NULL)
-      Space::Destroy(space->second);
-  }
   m_SpaceMap.clear();
 }
 
diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp
index d359162..ee700c0 100644
--- a/lib/Support/Path.cpp
+++ b/lib/Support/Path.cpp
@@ -6,6 +6,7 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include "mcld/Config/Config.h"
 #include "mcld/Support/FileSystem.h"
 #include "mcld/Support/Path.h"
 #include <llvm/ADT/StringRef.h>
diff --git a/lib/Support/SystemUtils.cpp b/lib/Support/SystemUtils.cpp
index 5dfea36..19c5e90 100644
--- a/lib/Support/SystemUtils.cpp
+++ b/lib/Support/SystemUtils.cpp
@@ -6,6 +6,7 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include "mcld/Config/Config.h"
 #include <mcld/Support/SystemUtils.h>
 
 using namespace mcld::sys;
diff --git a/lib/Support/UniqueGCFactory.cpp b/lib/Support/UniqueGCFactory.cpp
deleted file mode 100644
index 2352181..0000000
--- a/lib/Support/UniqueGCFactory.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-//===- UniqueGCFactory.cpp ------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <UniqueGCFactory.h>
-
-using namespace mcld;
-
-//==========================
-// UniqueGCFactory
-
diff --git a/lib/Support/Unix/PathV3.inc b/lib/Support/Unix/PathV3.inc
index 68b0c36..1506e94 100644
--- a/lib/Support/Unix/PathV3.inc
+++ b/lib/Support/Unix/PathV3.inc
@@ -233,7 +233,7 @@
     bool exist = false;
     entry = pIter.m_pParent->m_Cache.insert(path, exist);
     if (!exist)
-      entry->setValue(new Path(path));
+      entry->setValue(path);
     break;
   }
   case 0:// meet real end
@@ -264,7 +264,7 @@
     bool exist = false;
     mcld::sys::fs::PathCache::entry_type* entry = pDir.m_Cache.insert(path, exist);
     if (!exist)
-      entry->setValue(new Path(path));
+      entry->setValue(path);
     return;
   }
   case 0:
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
index e294bc3..0b64646 100644
--- a/lib/Support/raw_ostream.cpp
+++ b/lib/Support/raw_ostream.cpp
@@ -6,6 +6,7 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include "mcld/Config/Config.h"
 #include <mcld/Support/raw_ostream.h>
 
 #if defined(HAVE_UNISTD_H)
diff --git a/lib/Target/ARM/ARMELFArchiveReader.cpp b/lib/Target/ARM/ARMELFArchiveReader.cpp
deleted file mode 100644
index 4c6d775..0000000
--- a/lib/Target/ARM/ARMELFArchiveReader.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-//===- ARMELFArchiveReader.cpp --------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "ARMELFArchiveReader.h"
-
-using namespace mcld;
-
-//==========================
-// ARMELFArchiveReader
diff --git a/lib/Target/ARM/ARMELFArchiveReader.h b/lib/Target/ARM/ARMELFArchiveReader.h
deleted file mode 100644
index 2fa9ce2..0000000
--- a/lib/Target/ARM/ARMELFArchiveReader.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//===- ARMELFArchiveReader.h ----------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_ARM_ELF_ARCHIVE_READER_H
-#define MCLD_ARM_ELF_ARCHIVE_READER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include "mcld/MC/MCELFArchiveTargetReader.h"
-
-namespace mcld
-{
-
-/// ARMELFArchiveReader - ARMELFArchiveReader is
-/// a target-dependent reader for ELF archive files.
-class ARMELFArchiveReader : public MCELFArchiveTargetReader
-{
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/lib/Target/ARM/ARMGNUInfo.h b/lib/Target/ARM/ARMGNUInfo.h
index 9091dce..0162f83 100644
--- a/lib/Target/ARM/ARMGNUInfo.h
+++ b/lib/Target/ARM/ARMGNUInfo.h
@@ -21,6 +21,11 @@
 
   uint32_t machine() const { return llvm::ELF::EM_ARM; }
 
+  uint64_t defaultTextSegmentAddr() const { return 0x8000; }
+
+  uint64_t flags() const
+  { return (llvm::ELF::EF_ARM_EABIMASK & 0x05000000); }
+
 };
 
 } // namespace of mcld
diff --git a/lib/Target/ARM/ARMLDBackend.cpp b/lib/Target/ARM/ARMLDBackend.cpp
index 844c8ba..8b96670 100644
--- a/lib/Target/ARM/ARMLDBackend.cpp
+++ b/lib/Target/ARM/ARMLDBackend.cpp
@@ -28,7 +28,6 @@
 #include <mcld/Fragment/FillFragment.h>
 #include <mcld/Fragment/AlignFragment.h>
 #include <mcld/Fragment/RegionFragment.h>
-#include <mcld/Fragment/FragmentLinker.h>
 #include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/MsgHandling.h>
@@ -115,63 +114,80 @@
   }
 }
 
-void ARMGNULDBackend::initTargetSymbols(FragmentLinker& pLinker)
+void ARMGNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule)
 {
   // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
   // same name in input
-  m_pGOTSymbol = pLinker.defineSymbol<FragmentLinker::AsRefered, FragmentLinker::Resolve>(
-                   "_GLOBAL_OFFSET_TABLE_",
-                   false,
-                   ResolveInfo::Object,
-                   ResolveInfo::Define,
-                   ResolveInfo::Local,
-                   0x0,  // size
-                   0x0,  // value
-                   FragmentRef::Null(), // FragRef
-                   ResolveInfo::Hidden);
-
-  FragmentRef* exidx_start = NULL;
-  FragmentRef* exidx_end = NULL;
-  ResolveInfo::Desc desc = ResolveInfo::Undefined;
+  m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                                  "_GLOBAL_OFFSET_TABLE_",
+                                                  ResolveInfo::Object,
+                                                  ResolveInfo::Define,
+                                                  ResolveInfo::Local,
+                                                  0x0,  // size
+                                                  0x0,  // value
+                                                  FragmentRef::Null(),
+                                                  ResolveInfo::Hidden);
   if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size()) {
-    exidx_start = FragmentRef::Create(m_pEXIDX->getSectionData()->front(), 0x0);
-    exidx_end = FragmentRef::Create(m_pEXIDX->getSectionData()->back(), 0x0);
-    desc = ResolveInfo::Define;
-  }
-  else {
-    exidx_start = FragmentRef::Null();
-    exidx_end = FragmentRef::Null();
-  }
-  m_pEXIDXStart =
-    pLinker.defineSymbol<FragmentLinker::Force,
-                         FragmentLinker::Resolve>("__exidx_start",
-                                                  false,
-                                                  ResolveInfo::NoType,
-                                                  desc, // ResolveInfo::Desc
-                                                  ResolveInfo::Global,
-                                                  0x0,  // size
-                                                  0x0,  // value
-                                                  exidx_start, // FragRef
-                                                  ResolveInfo::Hidden);
+    FragmentRef* exidx_start =
+      FragmentRef::Create(m_pEXIDX->getSectionData()->front(), 0x0);
+    FragmentRef* exidx_end =
+      FragmentRef::Create(m_pEXIDX->getSectionData()->front(),
+                          m_pEXIDX->size());
+    m_pEXIDXStart =
+      pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                                    "__exidx_start",
+                                                    ResolveInfo::Object,
+                                                    ResolveInfo::Define,
+                                                    ResolveInfo::Local,
+                                                    0x0, // size
+                                                    0x0, // value
+                                                    exidx_start, // FragRef
+                                                    ResolveInfo::Default);
 
-  m_pEXIDXEnd =
-    pLinker.defineSymbol<FragmentLinker::Force,
-                         FragmentLinker::Resolve>("__exidx_end",
-                                                  false,
-                                                  ResolveInfo::NoType,
-                                                  desc, //ResolveInfo::Desc
-                                                  ResolveInfo::Global,
-                                                  0x0,  // size
-                                                  0x0,  // value
-                                                  exidx_end, // FragRef
-                                                  ResolveInfo::Hidden);
+    m_pEXIDXEnd =
+      pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                                    "__exidx_end",
+                                                    ResolveInfo::Object,
+                                                    ResolveInfo::Define,
+                                                    ResolveInfo::Local,
+                                                    0x0, // size
+                                                    0x0, // value
+                                                    exidx_end, // FragRef
+                                                    ResolveInfo::Default);
+    // change __exidx_start/_end to local dynamic category
+    if (NULL != m_pEXIDXStart)
+      pModule.getSymbolTable().changeLocalToDynamic(*m_pEXIDXStart);
+    if (NULL != m_pEXIDXEnd)
+      pModule.getSymbolTable().changeLocalToDynamic(*m_pEXIDXEnd);
+  } else {
+    m_pEXIDXStart =
+      pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                                    "__exidx_start",
+                                                    ResolveInfo::NoType,
+                                                    ResolveInfo::Define,
+                                                    ResolveInfo::Absolute,
+                                                    0x0, // size
+                                                    0x0, // value
+                                                    FragmentRef::Null(),
+                                                    ResolveInfo::Default);
+
+    m_pEXIDXEnd =
+      pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                                    "__exidx_end",
+                                                    ResolveInfo::NoType,
+                                                    ResolveInfo::Define,
+                                                    ResolveInfo::Absolute,
+                                                    0x0, // size
+                                                    0x0, // value
+                                                    FragmentRef::Null(),
+                                                    ResolveInfo::Default);
+  }
 }
 
-bool ARMGNULDBackend::initRelocator(const FragmentLinker& pLinker)
+bool ARMGNULDBackend::initRelocator()
 {
   if (NULL == m_pRelocator) {
     m_pRelocator = new ARMRelocator(*this);
-    m_pRelocator->setFragmentLinker(pLinker);
   }
   return true;
 }
@@ -182,8 +198,12 @@
   return m_pRelocator;
 }
 
-void ARMGNULDBackend::doPreLayout(FragmentLinker& pLinker)
+void ARMGNULDBackend::doPreLayout(IRBuilder& pBuilder)
 {
+  // initialize .dynamic data
+  if (!config().isCodeStatic() && NULL == m_pDynamic)
+    m_pDynamic = new ARMELFDynamic(*this, config());
+
   // set .got size
   // when building shared object, the .got section is must
   if (LinkerConfig::Object != config().codeGenType()) {
@@ -191,7 +211,7 @@
         m_pGOT->hasGOT1() ||
         NULL != m_pGOTSymbol) {
       m_pGOT->finalizeSectionSize();
-      defineGOTSymbol(pLinker);
+      defineGOTSymbol(pBuilder);
     }
 
     // set .plt size
@@ -200,19 +220,24 @@
 
     ELFFileFormat* file_format = getOutputFormat();
     // set .rel.dyn size
-    if (!m_pRelDyn->empty())
+    if (!m_pRelDyn->empty()) {
+      assert(!config().isCodeStatic() &&
+            "static linkage should not result in a dynamic relocation section");
       file_format->getRelDyn().setSize(
                                   m_pRelDyn->numOfRelocs() * getRelEntrySize());
+    }
 
     // set .rel.plt size
-    if (!m_pRelPLT->empty())
+    if (!m_pRelPLT->empty()) {
+      assert(!config().isCodeStatic() &&
+            "static linkage should not result in a dynamic relocation section");
       file_format->getRelPlt().setSize(
                                   m_pRelPLT->numOfRelocs() * getRelEntrySize());
+    }
   }
 }
 
-void ARMGNULDBackend::doPostLayout(Module& pModule,
-                                   FragmentLinker& pLinker)
+void ARMGNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder)
 {
   const ELFFileFormat *file_format = getOutputFormat();
 
@@ -242,9 +267,7 @@
 /// Use co-variant return type to return its own dynamic section.
 ARMELFDynamic& ARMGNULDBackend::dynamic()
 {
-  if (NULL == m_pDynamic)
-    m_pDynamic = new ARMELFDynamic(*this, config());
-
+  assert(NULL != m_pDynamic);
   return *m_pDynamic;
 }
 
@@ -252,17 +275,16 @@
 /// Use co-variant return type to return its own dynamic section.
 const ARMELFDynamic& ARMGNULDBackend::dynamic() const
 {
-  assert( NULL != m_pDynamic);
+  assert(NULL != m_pDynamic);
   return *m_pDynamic;
 }
 
-void ARMGNULDBackend::defineGOTSymbol(FragmentLinker& pLinker)
+void ARMGNULDBackend::defineGOTSymbol(IRBuilder& pBuilder)
 {
   // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
   if (m_pGOTSymbol != NULL) {
-    pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Unresolve>(
+    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
                      "_GLOBAL_OFFSET_TABLE_",
-                     false,
                      ResolveInfo::Object,
                      ResolveInfo::Define,
                      ResolveInfo::Local,
@@ -272,9 +294,8 @@
                      ResolveInfo::Hidden);
   }
   else {
-    m_pGOTSymbol = pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Resolve>(
+    m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
                      "_GLOBAL_OFFSET_TABLE_",
-                     false,
                      ResolveInfo::Object,
                      ResolveInfo::Define,
                      ResolveInfo::Local,
@@ -301,7 +322,7 @@
 /// copy.
 /// This is executed at scan relocation stage.
 LDSymbol&
-ARMGNULDBackend::defineSymbolforCopyReloc(FragmentLinker& pLinker,
+ARMGNULDBackend::defineSymbolforCopyReloc(IRBuilder& pBuilder,
                                           const ResolveInfo& pSym)
 {
   // get or create corresponding BSS LDSection
@@ -336,9 +357,8 @@
     binding = ResolveInfo::Global;
 
   // Define the copy symbol in the bss section and resolve it
-  LDSymbol* cpy_sym = pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Resolve>(
+  LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
                       pSym.name(),
-                      false,
                       (ResolveInfo::Type)pSym.type(),
                       ResolveInfo::Define,
                       binding,
@@ -352,11 +372,10 @@
 
 /// checkValidReloc - When we attempt to generate a dynamic relocation for
 /// ouput file, check if the relocation is supported by dynamic linker.
-void ARMGNULDBackend::checkValidReloc(Relocation& pReloc,
-                                      const FragmentLinker& pLinker) const
+void ARMGNULDBackend::checkValidReloc(Relocation& pReloc) const
 {
   // If not PIC object, no relocation type is invalid
-  if (!pLinker.isOutputPIC())
+  if (!config().isCodeIndep())
     return;
 
   switch(pReloc.type()) {
@@ -379,8 +398,8 @@
   }
 }
 
-void ARMGNULDBackend::scanLocalReloc(Relocation& pReloc,
-                                     FragmentLinker& pLinker)
+void
+ARMGNULDBackend::scanLocalReloc(Relocation& pReloc, const LDSection& pSection)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
@@ -398,11 +417,12 @@
       // If buiding PIC object (shared library or PIC executable),
       // a dynamic relocations with RELATIVE type to this location is needed.
       // Reserve an entry in .rel.dyn
-      if (pLinker.isOutputPIC()) {
+      if (config().isCodeIndep()) {
         m_pRelDyn->reserveEntry();
         // set Rel bit
         rsym->setReserved(rsym->reserved() | ReserveRel);
-        }
+        checkAndSetHasTextRel(*pSection.getLink());
+      }
       return;
     }
 
@@ -416,7 +436,7 @@
     case llvm::ELF::R_ARM_THM_MOVW_ABS_NC:
     case llvm::ELF::R_ARM_THM_MOVT_ABS: {
       // PIC code should not contain these kinds of relocation
-      if (pLinker.isOutputPIC()) {
+      if (config().isCodeIndep()) {
         error(diag::non_pic_relocation) << (int)pReloc.type()
                                         << pReloc.symInfo()->name();
       }
@@ -443,7 +463,7 @@
       // If building PIC object, a dynamic relocation with
       // type RELATIVE is needed to relocate this GOT entry.
       // Reserve an entry in .rel.dyn
-      if (pLinker.isOutputPIC()) {
+      if (config().isCodeIndep()) {
         // create .rel.dyn section if not exist
         m_pRelDyn->reserveEntry();
         // set GOTRel bit
@@ -479,7 +499,8 @@
 }
 
 void ARMGNULDBackend::scanGlobalReloc(Relocation& pReloc,
-                                      FragmentLinker& pLinker)
+                                      IRBuilder& pBuilder,
+                                      const LDSection& pSection)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
@@ -505,7 +526,7 @@
     case llvm::ELF::R_ARM_ABS32_NOI: {
       // Absolute relocation type, symbol may needs PLT entry or
       // dynamic relocation entry
-      if (symbolNeedsPLT(pLinker, *rsym)) {
+      if (symbolNeedsPLT(*rsym)) {
         // create plt for this symbol if it does not have one
         if (!(rsym->reserved() & ReservePLT)){
           // Symbol needs PLT entry, we need to reserve a PLT entry
@@ -519,18 +540,18 @@
         }
       }
 
-      if (symbolNeedsDynRel(
-                      pLinker, *rsym, (rsym->reserved() & ReservePLT), true)) {
+      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), true)) {
         // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
         m_pRelDyn->reserveEntry();
-        if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
-          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
+        if (symbolNeedsCopyReloc(pReloc, *rsym)) {
+          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
           addCopyReloc(*cpy_sym.resolveInfo());
         }
         else {
-          checkValidReloc(pReloc, pLinker);
+          checkValidReloc(pReloc);
           // set Rel bit
           rsym->setReserved(rsym->reserved() | ReserveRel);
+          checkAndSetHasTextRel(*pSection.getLink());
         }
       }
       return;
@@ -594,18 +615,18 @@
     case llvm::ELF::R_ARM_MOVT_BREL:
     case llvm::ELF::R_ARM_MOVW_BREL: {
       // Relative addressing relocation, may needs dynamic relocation
-      if (symbolNeedsDynRel(
-                     pLinker, *rsym, (rsym->reserved() & ReservePLT), false)) {
+      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), false)) {
         // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
         m_pRelDyn->reserveEntry();
-        if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
-          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
+        if (symbolNeedsCopyReloc(pReloc, *rsym)) {
+          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
           addCopyReloc(*cpy_sym.resolveInfo());
         }
         else {
-          checkValidReloc(pReloc, pLinker);
+          checkValidReloc(pReloc);
           // set Rel bit
           rsym->setReserved(rsym->reserved() | ReserveRel);
+          checkAndSetHasTextRel(*pSection.getLink());
         }
       }
       return;
@@ -630,7 +651,7 @@
         return;
 
       // if the symbol's value can be decided at link time, then no need plt
-      if (symbolFinalValueIsKnown(pLinker, *rsym))
+      if (symbolFinalValueIsKnown(*rsym))
         return;
 
       // if symbol is defined in the ouput file and it's not
@@ -666,7 +687,7 @@
       m_pGOT->reserveGOT();
       // if the symbol cannot be fully resolved at link time, then we need a
       // dynamic relocation
-      if (!symbolFinalValueIsKnown(pLinker, *rsym)) {
+      if (!symbolFinalValueIsKnown(*rsym)) {
         m_pRelDyn->reserveEntry();
         // set GOTRel bit
         rsym->setReserved(rsym->reserved() | GOTRel);
@@ -693,16 +714,17 @@
 }
 
 void ARMGNULDBackend::scanRelocation(Relocation& pReloc,
-                                     FragmentLinker& pLinker,
+                                     IRBuilder& pBuilder,
                                      Module& pModule,
-                                     const LDSection& pSection)
+                                     LDSection& pSection)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
   assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
 
   pReloc.updateAddend();
-  if (0 == (pSection.flag() & llvm::ELF::SHF_ALLOC))
+  assert(NULL != pSection.getLink());
+  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC))
     return;
 
   // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation
@@ -711,21 +733,16 @@
 
   // rsym is local
   if (rsym->isLocal())
-    scanLocalReloc(pReloc, pLinker);
+    scanLocalReloc(pReloc, pSection);
 
   // rsym is external
   else
-    scanGlobalReloc(pReloc, pLinker);
+    scanGlobalReloc(pReloc, pBuilder, pSection);
 
   // check if we shoule issue undefined reference for the relocation target
   // symbol
   if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
     fatal(diag::undefined_reference) << rsym->name();
-
-  if ((rsym->reserved() & ReserveRel) != 0x0) {
-    // set hasTextRelSection if needed
-    checkAndSetHasTextRel(pSection);
-  }
 }
 
 uint64_t ARMGNULDBackend::emitSectionData(const LDSection& pSection,
@@ -765,7 +782,7 @@
           break;
         }
         case Fragment::Alignment: {
-          AlignFragment& align_frag = llvm::cast<AlignFragment>(*frag_iter);
+          const AlignFragment& align_frag = llvm::cast<AlignFragment>(*frag_iter);
           uint64_t count = size / align_frag.getValueSize();
           switch (align_frag.getValueSize()) {
             case 1u:
@@ -809,17 +826,8 @@
 }
 
 /// finalizeSymbol - finalize the symbol value
-bool ARMGNULDBackend::finalizeTargetSymbols(FragmentLinker& pLinker)
+bool ARMGNULDBackend::finalizeTargetSymbols()
 {
-  if (NULL != m_pEXIDXStart) {
-    if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size())
-      m_pEXIDXStart->setValue(m_pEXIDX->addr());
-  }
-
-  if (NULL != m_pEXIDXEnd) {
-    if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size())
-      m_pEXIDXEnd->setValue(m_pEXIDX->addr() + m_pEXIDX->size());
-  }
   return true;
 }
 
@@ -829,7 +837,7 @@
     case llvm::ELF::SHT_ARM_ATTRIBUTES: {
       // FIXME: (Luba)
       // Handle ARM attributes in the right way.
-      // In current milestone, FragmentLinker goes through the shortcut.
+      // In current milestone, we goes through the shortcut.
       // It reads input's ARM attributes and copies the first ARM attributes
       // into the output file. The correct way is merge these sections, not
       // just copy.
@@ -940,7 +948,8 @@
 }
 
 /// doRelax
-bool ARMGNULDBackend::doRelax(Module& pModule, FragmentLinker& pLinker, bool& pFinished)
+bool
+ARMGNULDBackend::doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished)
 {
   assert(NULL != getStubFactory() && NULL != getBRIslandFactory());
 
@@ -984,17 +993,20 @@
 
             Stub* stub = getStubFactory()->create(*relocation, // relocation
                                                   sym_value, // symbol value
-                                                  pLinker,
+                                                  pBuilder,
                                                   *getBRIslandFactory());
             if (NULL != stub) {
-              assert(NULL != stub->symInfo());
-              // increase the size of .symtab and .strtab
+              // a stub symbol should be local
+              assert(NULL != stub->symInfo() && stub->symInfo()->isLocal());
               LDSection& symtab = file_format->getSymTab();
               LDSection& strtab = file_format->getStrTab();
+
+              // increase the size of .symtab and .strtab if needed
               if (config().targets().is32Bits())
                 symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym));
               else
                 symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf64_Sym));
+              symtab.setInfo(symtab.getInfo() + 1);
               strtab.setSize(strtab.size() + stub->symInfo()->nameSize() + 1);
 
               isRelaxed = true;
@@ -1042,13 +1054,13 @@
 }
 
 /// initTargetStubs
-bool ARMGNULDBackend::initTargetStubs(FragmentLinker& pLinker)
+bool ARMGNULDBackend::initTargetStubs()
 {
   if (NULL != getStubFactory()) {
-    getStubFactory()->addPrototype(new ARMToARMStub(pLinker.isOutputPIC()));
-    getStubFactory()->addPrototype(new ARMToTHMStub(pLinker.isOutputPIC()));
-    getStubFactory()->addPrototype(new THMToTHMStub(pLinker.isOutputPIC()));
-    getStubFactory()->addPrototype(new THMToARMStub(pLinker.isOutputPIC()));
+    getStubFactory()->addPrototype(new ARMToARMStub(config().isCodeIndep()));
+    getStubFactory()->addPrototype(new ARMToTHMStub(config().isCodeIndep()));
+    getStubFactory()->addPrototype(new THMToTHMStub(config().isCodeIndep()));
+    getStubFactory()->addPrototype(new THMToARMStub(config().isCodeIndep()));
     return true;
   }
   return false;
@@ -1056,8 +1068,7 @@
 
 /// doCreateProgramHdrs - backend can implement this function to create the
 /// target-dependent segments
-void ARMGNULDBackend::doCreateProgramHdrs(Module& pModule,
-                                          const FragmentLinker& pLinker)
+void ARMGNULDBackend::doCreateProgramHdrs(Module& pModule)
 {
    if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size()) {
      // make PT_ARM_EXIDX
diff --git a/lib/Target/ARM/ARMLDBackend.h b/lib/Target/ARM/ARMLDBackend.h
index 6110b1c..170a7bf 100644
--- a/lib/Target/ARM/ARMLDBackend.h
+++ b/lib/Target/ARM/ARMLDBackend.h
@@ -20,7 +20,6 @@
 
 class LinkerConfig;
 class GNUInfo;
-class FragmentLinker;
 class SectionMap;
 
 //===----------------------------------------------------------------------===//
@@ -93,10 +92,10 @@
   void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
 
   /// initTargetSymbols - initialize target dependent symbols in output.
-  void initTargetSymbols(FragmentLinker& pLinker);
+  void initTargetSymbols(IRBuilder& pBuilder, Module& pModule);
 
   /// initRelocator - create and initialize Relocator.
-  bool initRelocator(const FragmentLinker& pLinker);
+  bool initRelocator();
 
   /// getRelocator - return relocator.
   Relocator* getRelocator();
@@ -108,22 +107,15 @@
   /// - PLT entry (for .plt section)
   /// - dynamin relocation entries (for .rel.plt and .rel.dyn sections)
   void scanRelocation(Relocation& pReloc,
-                      FragmentLinker& pLinker,
+                      IRBuilder& pBuilder,
                       Module& pModule,
-                      const LDSection& pSection);
-
-  /// flags - the value of ElfXX_Ehdr::e_flags
-  virtual uint64_t flags() const
-  { return (llvm::ELF::EF_ARM_EABIMASK & 0x05000000); }
-
-  uint64_t defaultTextSegmentAddr() const
-  { return 0x8000; }
+                      LDSection& pSection);
 
   /// doPreLayout - Backend can do any needed modification before layout
-  void doPreLayout(FragmentLinker& pLinker);
+  void doPreLayout(IRBuilder& pBuilder);
 
   /// doPostLayout -Backend can do any needed modification after layout
-  void doPostLayout(Module& pModule, FragmentLinker& pLinker);
+  void doPostLayout(Module& pModule, IRBuilder& pBuilder);
 
   /// dynamic - the dynamic section of the target machine.
   /// Use co-variant return type to return its own dynamic section.
@@ -172,7 +164,7 @@
   unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const;
 
   /// finalizeTargetSymbols - finalize the symbol value
-  bool finalizeTargetSymbols(FragmentLinker& pLinker);
+  bool finalizeTargetSymbols();
 
   /// mergeSection - merge target dependent sections
   bool mergeSection(Module& pModule, LDSection& pSection);
@@ -181,12 +173,13 @@
   bool readSection(Input& pInput, SectionData& pSD);
 
 private:
-  void scanLocalReloc(Relocation& pReloc, FragmentLinker& pLinker);
+  void scanLocalReloc(Relocation& pReloc, const LDSection& pSection);
 
-  void scanGlobalReloc(Relocation& pReloc, FragmentLinker& pLinker);
+  void scanGlobalReloc(Relocation& pReloc,
+                       IRBuilder& pBuilder,
+                       const LDSection& pSection);
 
-  void checkValidReloc(Relocation& pReloc,
-                       const FragmentLinker& pLinker) const;
+  void checkValidReloc(Relocation& pReloc) const;
 
   /// addCopyReloc - add a copy relocation into .rel.dyn for pSym
   /// @param pSym - A resolved copy symbol that defined in BSS section
@@ -195,10 +188,10 @@
   /// defineSymbolforCopyReloc - allocate a space in BSS section and
   /// and force define the copy of pSym to BSS section
   /// @return the output LDSymbol of the copy symbol
-  LDSymbol& defineSymbolforCopyReloc(FragmentLinker& pLinker,
+  LDSymbol& defineSymbolforCopyReloc(IRBuilder& pLinker,
                                      const ResolveInfo& pSym);
 
-  void defineGOTSymbol(FragmentLinker& pLinker);
+  void defineGOTSymbol(IRBuilder& pBuilder);
 
   /// maxBranchOffset
   /// FIXME: if we can handle arm attributes, we may refine this!
@@ -211,10 +204,10 @@
   /// implementation. Return true if the output (e.g., .text) is "relaxed"
   /// (i.e. layout is changed), and set pFinished to true if everything is fit,
   /// otherwise set it to false.
-  bool doRelax(Module& pModule, FragmentLinker& pLinker, bool& pFinished);
+  bool doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished);
 
   /// initTargetStubs
-  bool initTargetStubs(FragmentLinker& pLinker);
+  bool initTargetStubs();
 
   /// getRelEntrySize - the size in BYTE of rel type relocation
   size_t getRelEntrySize()
@@ -226,8 +219,7 @@
 
   /// doCreateProgramHdrs - backend can implement this function to create the
   /// target-dependent segments
-  virtual void doCreateProgramHdrs(Module& pModule,
-                                   const FragmentLinker& pLinker);
+  virtual void doCreateProgramHdrs(Module& pModule);
 
 private:
   Relocator* m_pRelocator;
@@ -252,24 +244,6 @@
 //  LDSection* m_pDebugOverlay;    // .ARM.debug_overlay
 //  LDSection* m_pOverlayTable;    // .ARM.overlay_table
 };
-
-//===----------------------------------------------------------------------===//
-/// ARMMachOLDBackend - linker backend of ARM target of MachO format
-///
-/**
-class ARMMachOLDBackend : public DarwinARMLDBackend
-{
-public:
-  ARMMachOLDBackend();
-  ~ARMMachOLDBackend();
-
-private:
-  MCMachOTargetArchiveReader *createTargetArchiveReader() const;
-  MCMachOTargetObjectReader *createTargetObjectReader() const;
-  MCMachOTargetObjectWriter *createTargetObjectWriter() const;
-
-};
-**/
 } // namespace of mcld
 
 #endif
diff --git a/lib/Target/ARM/ARMRelocator.cpp b/lib/Target/ARM/ARMRelocator.cpp
index d613d66..d400818 100644
--- a/lib/Target/ARM/ARMRelocator.cpp
+++ b/lib/Target/ARM/ARMRelocator.cpp
@@ -11,7 +11,6 @@
 #include <llvm/Support/DataTypes.h>
 #include <llvm/Support/ELF.h>
 #include <llvm/Support/Host.h>
-#include <mcld/Fragment/FragmentLinker.h>
 #include <mcld/Support/MsgHandling.h>
 #include "ARMRelocator.h"
 #include "ARMRelocationFunctions.h"
@@ -68,8 +67,14 @@
   return ApplyFunctions[pType].name;
 }
 
+Relocator::Size ARMRelocator::getSize(Relocation::Type pType) const
+{
+  return 32;
+}
+
 //===--------------------------------------------------------------------===//
 // non-member functions
+//===--------------------------------------------------------------------===//
 static Relocator::DWord getThumbBit(const Relocation& pReloc)
 {
   // Set thumb bit if
diff --git a/lib/Target/ARM/ARMRelocator.h b/lib/Target/ARM/ARMRelocator.h
index 0bf3653..4af48f9 100644
--- a/lib/Target/ARM/ARMRelocator.h
+++ b/lib/Target/ARM/ARMRelocator.h
@@ -43,6 +43,8 @@
 
   const char* getName(Relocation::Type pType) const;
 
+  Size getSize(Relocation::Type pType) const;
+
   const SymGOTMap& getSymGOTMap() const { return m_SymGOTMap; }
   SymGOTMap&       getSymGOTMap()       { return m_SymGOTMap; }
 
diff --git a/lib/Target/DarwinLDBackend.cpp b/lib/Target/DarwinLDBackend.cpp
deleted file mode 100644
index 5bd55c3..0000000
--- a/lib/Target/DarwinLDBackend.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-//===- DarwinLDBackend.cpp ------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <DarwinLDBackend.h>
-
-using namespace mcld;
-
-//==========================
-// DarwinLDBackend
-
diff --git a/lib/Target/ELFDynamic.cpp b/lib/Target/ELFDynamic.cpp
index 89917cc..aeccd92 100644
--- a/lib/Target/ELFDynamic.cpp
+++ b/lib/Target/ELFDynamic.cpp
@@ -35,10 +35,17 @@
 ELFDynamic::ELFDynamic(const GNULDBackend& pParent,
                        const LinkerConfig& pConfig)
   : m_pEntryFactory(NULL), m_Backend(pParent), m_Config(pConfig), m_Idx(0) {
-  if (m_Config.targets().is32Bits() && m_Config.targets().isLittleEndian()) {
-    m_pEntryFactory = new Entry<32, true>();
+  // FIXME: support big-endian machine.
+  if (m_Config.targets().is32Bits()) {
+    if (m_Config.targets().isLittleEndian())
+      m_pEntryFactory = new Entry<32, true>();
+  } else if (m_Config.targets().is64Bits()) {
+    if (m_Config.targets().isLittleEndian())
+      m_pEntryFactory = new Entry<64, true>();
+  } else {
+    fatal(diag::unsupported_bitclass) << m_Config.targets().triple().str()
+                                      << m_Config.targets().bitclass();
   }
-  // FIXME: support big-endian and 64-bit machine.
 }
 
 
@@ -78,7 +85,7 @@
 void ELFDynamic::reserveOne(uint64_t pTag)
 {
   assert(NULL != m_pEntryFactory);
-  m_EntryList.push_back(new elf_dynamic::Entry<32, true>());
+  m_EntryList.push_back(m_pEntryFactory->clone());
 }
 
 void ELFDynamic::applyOne(uint64_t pTag, uint64_t pValue)
@@ -117,6 +124,10 @@
   if (pFormat.hasHashTab())
     reserveOne(llvm::ELF::DT_HASH); // DT_HASH
 
+  // FIXME: use llvm enum constant
+  if (pFormat.hasGNUHashTab())
+    reserveOne(0x6ffffef5); // DT_GNU_HASH
+
   if (pFormat.hasDynSymTab()) {
     reserveOne(llvm::ELF::DT_SYMTAB); // DT_SYMTAB
     reserveOne(llvm::ELF::DT_SYMENT); // DT_SYMENT
@@ -149,14 +160,22 @@
     reserveOne(llvm::ELF::DT_RELAENT); // DT_RELAENT
   }
 
-  if (m_Config.options().hasOrigin() ||
-      m_Config.options().Bsymbolic() ||
-      m_Config.options().hasNow()    ||
-      m_Backend.hasTextRel()        ||
-      (m_Backend.hasStaticTLS() &&
-        (LinkerConfig::DynObj == m_Config.codeGenType()))) {
+  uint64_t dt_flags = 0x0;
+  if (m_Config.options().hasOrigin())
+    dt_flags |= llvm::ELF::DF_ORIGIN;
+  if (m_Config.options().Bsymbolic())
+    dt_flags |= llvm::ELF::DF_SYMBOLIC;
+  if (m_Config.options().hasNow())
+    dt_flags |= llvm::ELF::DF_BIND_NOW;
+  if (m_Backend.hasTextRel())
+    dt_flags |= llvm::ELF::DF_TEXTREL;
+  if (m_Backend.hasStaticTLS() &&
+      (LinkerConfig::DynObj == m_Config.codeGenType()))
+    dt_flags |= llvm::ELF::DF_STATIC_TLS;
+
+  if ((m_Config.options().hasNewDTags() && 0x0 != dt_flags) ||
+      0 != (dt_flags & llvm::ELF::DF_STATIC_TLS))
     reserveOne(llvm::ELF::DT_FLAGS); // DT_FLAGS
-  }
 
   if (m_Backend.hasTextRel())
     reserveOne(llvm::ELF::DT_TEXTREL); // DT_TEXTREL
@@ -211,6 +230,10 @@
   if (pFormat.hasHashTab())
     applyOne(llvm::ELF::DT_HASH, pFormat.getHashTab().addr()); // DT_HASH
 
+  // FIXME: use llvm enum constant
+  if (pFormat.hasGNUHashTab())
+    applyOne(0x6ffffef5, pFormat.getGNUHashTab().addr()); // DT_GNU_HASH
+
   if (pFormat.hasDynSymTab()) {
     applyOne(llvm::ELF::DT_SYMTAB, pFormat.getDynSymTab().addr()); // DT_SYMTAB
     applyOne(llvm::ELF::DT_SYMENT, symbolSize()); // DT_SYMENT
@@ -223,15 +246,16 @@
 
   applyTargetEntries(pFormat); // DT_PLTGOT
 
-  if (pFormat.hasRelPlt())
-    applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_REL); // DT_PLTREL
-  else if (pFormat.hasRelaPlt())
-    applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_RELA); // DT_PLTREL
-
   if (pFormat.hasRelPlt()) {
+    applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_REL); // DT_PLTREL
     applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelPlt().addr()); // DT_JMPREL
     applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelPlt().size()); // DT_PLTRELSZ
   }
+  else if (pFormat.hasRelaPlt()) {
+    applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_RELA); // DT_PLTREL
+    applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelaPlt().addr()); // DT_JMPREL
+    applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelaPlt().size()); // DT_PLTRELSZ
+  }
 
   if (pFormat.hasRelDyn()) {
     applyOne(llvm::ELF::DT_REL, pFormat.getRelDyn().addr()); // DT_REL
@@ -265,9 +289,10 @@
   if (m_Backend.hasStaticTLS() &&
       (LinkerConfig::DynObj == m_Config.codeGenType()))
     dt_flags |= llvm::ELF::DF_STATIC_TLS;
-  if (0x0 != dt_flags) {
+
+  if ((m_Config.options().hasNewDTags() && 0x0 != dt_flags) ||
+      0 != (dt_flags & llvm::ELF::DF_STATIC_TLS))
     applyOne(llvm::ELF::DT_FLAGS, dt_flags); // DT_FLAGS
-  }
 
   uint64_t dt_flags_1 = 0x0;
   if (m_Config.options().hasNow())
diff --git a/lib/Target/ELFEmulation.cpp b/lib/Target/ELFEmulation.cpp
index 3bd2094..bdd76aa 100644
--- a/lib/Target/ELFEmulation.cpp
+++ b/lib/Target/ELFEmulation.cpp
@@ -9,6 +9,8 @@
 #include <mcld/Target/ELFEmulation.h>
 #include <mcld/LinkerConfig.h>
 
+#include <llvm/Support/Host.h>
+
 using namespace mcld;
 
 struct NameMap {
@@ -61,6 +63,7 @@
 
 bool mcld::MCLDEmulateELF(LinkerConfig& pConfig)
 {
+  // set up section map
   if (pConfig.codeGenType() != LinkerConfig::Object) {
     const unsigned int map_size =  (sizeof(map) / sizeof(map[0]) );
     for (unsigned int i = 0; i < map_size; ++i) {
@@ -70,6 +73,18 @@
         return false;
     }
   }
+
+  if (!pConfig.options().nostdlib()) {
+    // TODO: check if user sets the default search path instead via -Y option
+    // set up default search path
+    if (llvm::Triple::NetBSD == pConfig.targets().triple().getOS()) {
+      pConfig.options().directories().insert("=/usr/lib");
+    }
+    else {
+      pConfig.options().directories().insert("=/lib");
+      pConfig.options().directories().insert("=/usr/lib");
+    }
+  }
   return true;
 }
 
diff --git a/lib/Target/GNULDBackend.cpp b/lib/Target/GNULDBackend.cpp
index 590c14f..ef4f1fb 100644
--- a/lib/Target/GNULDBackend.cpp
+++ b/lib/Target/GNULDBackend.cpp
@@ -13,6 +13,7 @@
 #include <cassert>
 #include <vector>
 #include <algorithm>
+#include <map>
 
 #include <mcld/Module.h>
 #include <mcld/LinkerConfig.h>
@@ -28,7 +29,6 @@
 #include <mcld/LD/RelocData.h>
 #include <mcld/LD/RelocationFactory.h>
 #include <mcld/MC/Attribute.h>
-#include <mcld/Fragment/FragmentLinker.h>
 #include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/MsgHandling.h>
@@ -66,7 +66,6 @@
     m_ELFSegmentTable(9), // magic number
     m_pBRIslandFactory(NULL),
     m_pStubFactory(NULL),
-    m_pEhFrame(NULL),
     m_pEhFrameHdr(NULL),
     m_bHasTextRel(false),
     m_bHasStaticTLS(false),
@@ -97,14 +96,11 @@
   delete m_pInfo;
   delete m_pDynObjFileFormat;
   delete m_pExecFileFormat;
+  delete m_pObjectFileFormat;
   delete m_pSymIndexMap;
-  delete m_pEhFrame;
   delete m_pEhFrameHdr;
-
-  if (NULL != m_pBRIslandFactory)
-    delete m_pBRIslandFactory;
-  if (NULL != m_pStubFactory)
-    delete m_pStubFactory;
+  delete m_pBRIslandFactory;
+  delete m_pStubFactory;
 }
 
 size_t GNULDBackend::sectionStartOffset() const
@@ -126,16 +122,16 @@
   }
 }
 
-uint64_t GNULDBackend::segmentStartAddr(const FragmentLinker& pLinker) const
+uint64_t GNULDBackend::segmentStartAddr() const
 {
   ScriptOptions::AddressMap::const_iterator mapping =
     config().scripts().addressMap().find(".text");
   if (mapping != config().scripts().addressMap().end())
     return mapping.getEntry()->value();
-  else if (pLinker.isOutputPIC())
+  else if (config().isCodeIndep())
     return 0x0;
   else
-    return defaultTextSegmentAddr();
+    return m_pInfo->defaultTextSegmentAddr();
 }
 
 GNUArchiveReader*
@@ -161,26 +157,11 @@
   return new ELFBinaryReader(*this, pBuilder, config());
 }
 
-ELFObjectWriter* GNULDBackend::createObjectWriter()
+ELFObjectWriter* GNULDBackend::createWriter()
 {
   return new ELFObjectWriter(*this, config());
 }
 
-ELFDynObjWriter* GNULDBackend::createDynObjWriter()
-{
-  return new ELFDynObjWriter(*this, config());
-}
-
-ELFExecWriter* GNULDBackend::createExecWriter()
-{
-  return new ELFExecWriter(*this, config());
-}
-
-ELFBinaryWriter* GNULDBackend::createBinaryWriter()
-{
-  return new ELFBinaryWriter(*this, config());
-}
-
 bool GNULDBackend::initStdSections(ObjectBuilder& pBuilder)
 {
   switch (config().codeGenType()) {
@@ -214,7 +195,7 @@
 
 /// initStandardSymbols - define and initialize standard symbols.
 /// This function is called after section merging but before read relocations.
-bool GNULDBackend::initStandardSymbols(FragmentLinker& pLinker,
+bool GNULDBackend::initStandardSymbols(IRBuilder& pBuilder,
                                        Module& pModule)
 {
   if (LinkerConfig::Object == config().codeGenType())
@@ -244,9 +225,8 @@
       llvm::StringRef start_name = llvm::StringRef("__start_" + section->name());
       FragmentRef* start_fragref = FragmentRef::Create(
                                        section->getSectionData()->front(), 0x0);
-      pLinker.defineSymbol<FragmentLinker::AsRefered,
-                           FragmentLinker::Resolve>(start_name,
-                                                    false, // isDyn
+      pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                                    start_name,
                                                     ResolveInfo::NoType,
                                                     ResolveInfo::Define,
                                                     ResolveInfo::Global,
@@ -258,9 +238,8 @@
       llvm::StringRef stop_name = llvm::StringRef("__stop_" + section->name());
       FragmentRef* stop_fragref = FragmentRef::Create(
                            section->getSectionData()->front(), section->size());
-      pLinker.defineSymbol<FragmentLinker::AsRefered,
-                           FragmentLinker::Resolve>(stop_name,
-                                                    false, // isDyn
+      pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                                    stop_name,
                                                     ResolveInfo::NoType,
                                                     ResolveInfo::Define,
                                                     ResolveInfo::Global,
@@ -285,9 +264,8 @@
     preinit_array = FragmentRef::Null();
   }
   f_pPreInitArrayStart =
-     pLinker.defineSymbol<FragmentLinker::AsRefered,
-                          FragmentLinker::Resolve>("__preinit_array_start",
-                                             false, // isDyn
+     pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                             "__preinit_array_start",
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Global,
@@ -296,9 +274,8 @@
                                              preinit_array, // FragRef
                                              ResolveInfo::Hidden);
   f_pPreInitArrayEnd =
-     pLinker.defineSymbol<FragmentLinker::AsRefered,
-                          FragmentLinker::Resolve>("__preinit_array_end",
-                                             false, // isDyn
+     pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                             "__preinit_array_end",
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Global,
@@ -319,9 +296,8 @@
   }
 
   f_pInitArrayStart =
-     pLinker.defineSymbol<FragmentLinker::AsRefered,
-                          FragmentLinker::Resolve>("__init_array_start",
-                                             false, // isDyn
+     pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                             "__init_array_start",
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Global,
@@ -330,9 +306,8 @@
                                              init_array, // FragRef
                                              ResolveInfo::Hidden);
   f_pInitArrayEnd =
-     pLinker.defineSymbol<FragmentLinker::AsRefered,
-                          FragmentLinker::Resolve>("__init_array_end",
-                                             false, // isDyn
+     pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                             "__init_array_end",
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Global,
@@ -353,9 +328,8 @@
   }
 
   f_pFiniArrayStart =
-     pLinker.defineSymbol<FragmentLinker::AsRefered,
-                          FragmentLinker::Resolve>("__fini_array_start",
-                                             false, // isDyn
+     pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                             "__fini_array_start",
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Global,
@@ -364,9 +338,8 @@
                                              fini_array, // FragRef
                                              ResolveInfo::Hidden);
   f_pFiniArrayEnd =
-     pLinker.defineSymbol<FragmentLinker::AsRefered,
-                          FragmentLinker::Resolve>("__fini_array_end",
-                                             false, // isDyn
+     pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                             "__fini_array_end",
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Global,
@@ -387,9 +360,8 @@
   }
 
   f_pStack =
-     pLinker.defineSymbol<FragmentLinker::AsRefered,
-                          FragmentLinker::Resolve>("__stack",
-                                             false, // isDyn
+     pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                             "__stack",
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Global,
@@ -402,9 +374,8 @@
   // TODO: add SectionData for .dynamic section, and then we can get the correct
   // symbol section index for _DYNAMIC. Now it will be ABS.
   f_pDynamic =
-     pLinker.defineSymbol<FragmentLinker::AsRefered,
-                          FragmentLinker::Resolve>("_DYNAMIC",
-                                                   false, // isDyn
+     pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                                   "_DYNAMIC",
                                                    ResolveInfo::Object,
                                                    ResolveInfo::Define,
                                                    ResolveInfo::Local,
@@ -415,9 +386,8 @@
 
   // -----  segment symbols  ----- //
   f_pExecutableStart =
-     pLinker.defineSymbol<FragmentLinker::AsRefered,
-                          FragmentLinker::Resolve>("__executable_start",
-                                             false, // isDyn
+     pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                             "__executable_start",
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
@@ -426,9 +396,8 @@
                                              FragmentRef::Null(), // FragRef
                                              ResolveInfo::Default);
   f_pEText =
-     pLinker.defineSymbol<FragmentLinker::AsRefered,
-                          FragmentLinker::Resolve>("etext",
-                                             false, // isDyn
+     pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                             "etext",
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
@@ -437,9 +406,8 @@
                                              FragmentRef::Null(), // FragRef
                                              ResolveInfo::Default);
   f_p_EText =
-     pLinker.defineSymbol<FragmentLinker::AsRefered,
-                          FragmentLinker::Resolve>("_etext",
-                                             false, // isDyn
+     pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                             "_etext",
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
@@ -448,9 +416,8 @@
                                              FragmentRef::Null(), // FragRef
                                              ResolveInfo::Default);
   f_p__EText =
-     pLinker.defineSymbol<FragmentLinker::AsRefered,
-                          FragmentLinker::Resolve>("__etext",
-                                             false, // isDyn
+     pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                             "__etext",
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
@@ -459,9 +426,8 @@
                                              FragmentRef::Null(), // FragRef
                                              ResolveInfo::Default);
   f_pEData =
-     pLinker.defineSymbol<FragmentLinker::AsRefered,
-                          FragmentLinker::Resolve>("edata",
-                                             false, // isDyn
+     pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                             "edata",
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
@@ -471,9 +437,8 @@
                                              ResolveInfo::Default);
 
   f_pEnd =
-     pLinker.defineSymbol<FragmentLinker::AsRefered,
-                          FragmentLinker::Resolve>("end",
-                                             false, // isDyn
+     pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                             "end",
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
@@ -485,9 +450,8 @@
   // _edata is defined forcefully.
   // @ref Google gold linker: defstd.cc: 186
   f_p_EData =
-     pLinker.defineSymbol<FragmentLinker::Force,
-                          FragmentLinker::Resolve>("_edata",
-                                             false, // isDyn
+     pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
+                                             "_edata",
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
@@ -499,9 +463,8 @@
   // __bss_start is defined forcefully.
   // @ref Google gold linker: defstd.cc: 214
   f_pBSSStart =
-     pLinker.defineSymbol<FragmentLinker::Force,
-                          FragmentLinker::Resolve>("__bss_start",
-                                             false, // isDyn
+     pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
+                                             "__bss_start",
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
@@ -513,9 +476,8 @@
   // _end is defined forcefully.
   // @ref Google gold linker: defstd.cc: 228
   f_p_End =
-     pLinker.defineSymbol<FragmentLinker::Force,
-                          FragmentLinker::Resolve>("_end",
-                                             false, // isDyn
+     pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
+                                             "_end",
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
@@ -527,8 +489,7 @@
   return true;
 }
 
-bool
-GNULDBackend::finalizeStandardSymbols(FragmentLinker& pLinker)
+bool GNULDBackend::finalizeStandardSymbols()
 {
   if (LinkerConfig::Object == config().codeGenType())
     return true;
@@ -752,7 +713,6 @@
 }
 
 void GNULDBackend::partialScanRelocation(Relocation& pReloc,
-                                         FragmentLinker& pLinker,
                                          Module& pModule,
                                          const LDSection& pSection)
 {
@@ -778,8 +738,7 @@
 /// sizeNamePools - compute the size of regular name pools
 /// In ELF executable files, regular name pools are .symtab, .strtab,
 /// .dynsym, .dynstr, .hash and .shstrtab.
-void
-GNULDBackend::sizeNamePools(const Module& pModule, bool pIsStaticLink)
+void GNULDBackend::sizeNamePools(Module& pModule, bool pIsStaticLink)
 {
   // number of entries in symbol tables starts from 1 to hold the special entry
   // at index 0 (STN_UNDEF). See ELF Spec Book I, p1-21.
@@ -788,112 +747,118 @@
 
   // size of string tables starts from 1 to hold the null character in their
   // first byte
-  size_t strtab = 1;
-  size_t dynstr = pIsStaticLink ? 0 : 1;
+  size_t strtab   = 1;
+  size_t dynstr   = pIsStaticLink ? 0 : 1;
   size_t shstrtab = 1;
-  size_t hash   = 0;
+  size_t hash     = 0;
+  size_t gnuhash  = 0;
 
-  // number of local symbol in the .dynsym
+  // number of local symbol in the .symtab and .dynsym
+  size_t symtab_local_cnt = 0;
   size_t dynsym_local_cnt = 0;
 
-  /// compute the size of .symtab, .dynsym and .strtab
+  Module::SymbolTable& symbols = pModule.getSymbolTable();
+  Module::const_sym_iterator symbol, symEnd;
+  /// Compute the size of .symtab, .strtab, and symtab_local_cnt
   /// @{
-  Module::const_sym_iterator symbol;
-  const Module::SymbolTable& symbols = pModule.getSymbolTable();
-  size_t str_size = 0;
-  // compute the size of symbols in Local and File category
-  Module::const_sym_iterator symEnd = symbols.localEnd();
-  for (symbol = symbols.localBegin(); symbol != symEnd; ++symbol) {
-    str_size = (*symbol)->nameSize() + 1;
-    if (!pIsStaticLink && isDynamicSymbol(**symbol)) {
-      ++dynsym;
-      if (ResolveInfo::Section != (*symbol)->type())
-        dynstr += str_size;
-    }
+  symEnd = symbols.end();
+  for (symbol = symbols.begin(); symbol != symEnd; ++symbol) {
     ++symtab;
     if (ResolveInfo::Section != (*symbol)->type())
-      strtab += str_size;
+      strtab += (*symbol)->nameSize() + 1;
   }
-  // compute the size of symbols in TLS category
-  symEnd = symbols.tlsEnd();
-  for (symbol = symbols.tlsBegin(); symbol != symEnd; ++symbol) {
-    str_size = (*symbol)->nameSize() + 1;
-    if (!pIsStaticLink) {
-      ++dynsym;
-      if (ResolveInfo::Section != (*symbol)->type())
-        dynstr += str_size;
-    }
-    ++symtab;
-    if (ResolveInfo::Section != (*symbol)->type())
-      strtab += str_size;
-  }
-  dynsym_local_cnt = dynsym;
-  // compute the size of the reset of symbols
-  symEnd = pModule.sym_end();
-  for (symbol = symbols.tlsEnd(); symbol != symEnd; ++symbol) {
-    str_size = (*symbol)->nameSize() + 1;
-    if (!pIsStaticLink && isDynamicSymbol(**symbol)) {
-      ++dynsym;
-      if (ResolveInfo::Section != (*symbol)->type())
-        dynstr += str_size;
-    }
-    ++symtab;
-    if (ResolveInfo::Section != (*symbol)->type())
-      strtab += str_size;
-  }
+  symtab_local_cnt = 1 + symbols.numOfFiles() + symbols.numOfLocals() +
+                     symbols.numOfLocalDyns();
 
   ELFFileFormat* file_format = getOutputFormat();
 
   switch(config().codeGenType()) {
-    // compute size of .dynstr and .hash
     case LinkerConfig::DynObj: {
       // soname
-      if (!pIsStaticLink)
-        dynstr += pModule.name().size() + 1;
+      dynstr += pModule.name().size() + 1;
     }
     /** fall through **/
     case LinkerConfig::Exec:
     case LinkerConfig::Binary: {
-      // add DT_NEED strings into .dynstr and .dynamic
-      // Rules:
-      //   1. ignore --no-add-needed
-      //   2. force count in --no-as-needed
-      //   3. judge --as-needed
       if (!pIsStaticLink) {
-        Module::const_lib_iterator lib, libEnd = pModule.lib_end();
-        for (lib = pModule.lib_begin(); lib != libEnd; ++lib) {
-          // --add-needed
-          if ((*lib)->attribute()->isAddNeeded()) {
-            // --no-as-needed
-            if (!(*lib)->attribute()->isAsNeeded()) {
-              dynstr += (*lib)->name().size() + 1;
-              dynamic().reserveNeedEntry();
-            }
-            // --as-needed
-            else if ((*lib)->isNeeded()) {
-              dynstr += (*lib)->name().size() + 1;
-              dynamic().reserveNeedEntry();
-            }
+        /// Compute the size of .dynsym, .dynstr, and dynsym_local_cnt
+        symEnd = symbols.dynamicEnd();
+        for (symbol = symbols.localDynBegin(); symbol != symEnd; ++symbol) {
+          ++dynsym;
+          if (ResolveInfo::Section != (*symbol)->type())
+            dynstr += (*symbol)->nameSize() + 1;
+        }
+        dynsym_local_cnt = 1 + symbols.numOfLocalDyns();
+
+        // compute .gnu.hash
+        if (GeneralOptions::GNU  == config().options().getHashStyle() ||
+            GeneralOptions::Both == config().options().getHashStyle()) {
+          // count the number of dynsym to hash
+          size_t hashed_sym_cnt = 0;
+          symEnd = symbols.dynamicEnd();
+          for (symbol = symbols.dynamicBegin(); symbol != symEnd; ++symbol) {
+            if (DynsymCompare().needGNUHash(**symbol))
+              ++hashed_sym_cnt;
+          }
+          // Special case for empty .dynsym
+          if (hashed_sym_cnt == 0)
+            gnuhash = 5 * 4 + config().targets().bitclass() / 8;
+          else {
+            size_t nbucket = getHashBucketCount(hashed_sym_cnt, true);
+            gnuhash = (4 + nbucket + hashed_sym_cnt) * 4;
+            gnuhash += (1U << getGNUHashMaskbitslog2(hashed_sym_cnt)) / 8;
           }
         }
 
         // compute .hash
-        // Both Elf32_Word and Elf64_Word are 4 bytes
-        hash = (2 + getHashBucketCount(dynsym, false) + dynsym) *
-               sizeof(llvm::ELF::Elf32_Word);
+        if (GeneralOptions::SystemV == config().options().getHashStyle() ||
+            GeneralOptions::Both == config().options().getHashStyle()) {
+          // Both Elf32_Word and Elf64_Word are 4 bytes
+          hash = (2 + getHashBucketCount(dynsym, false) + dynsym) *
+                 sizeof(llvm::ELF::Elf32_Word);
+        }
+
+        // add DT_NEEDED
+        Module::const_lib_iterator lib, libEnd = pModule.lib_end();
+        for (lib = pModule.lib_begin(); lib != libEnd; ++lib) {
+          if (!(*lib)->attribute()->isAsNeeded() || (*lib)->isNeeded()) {
+            dynstr += (*lib)->name().size() + 1;
+            dynamic().reserveNeedEntry();
+          }
+        }
+
+        // add DT_RPATH
+        if (!config().options().getRpathList().empty()) {
+          dynamic().reserveNeedEntry();
+          GeneralOptions::const_rpath_iterator rpath,
+            rpathEnd = config().options().rpath_end();
+          for (rpath = config().options().rpath_begin();
+               rpath != rpathEnd; ++rpath)
+            dynstr += (*rpath).size() + 1;
+        }
+
+        // set size
+        if (config().targets().is32Bits()) {
+          file_format->getDynSymTab().setSize(dynsym *
+                                              sizeof(llvm::ELF::Elf32_Sym));
+        } else {
+          file_format->getDynSymTab().setSize(dynsym *
+                                              sizeof(llvm::ELF::Elf64_Sym));
+        }
+        file_format->getDynStrTab().setSize(dynstr);
+        file_format->getHashTab().setSize(hash);
+        file_format->getGNUHashTab().setSize(gnuhash);
+
+        // set .dynsym sh_info to one greater than the symbol table
+        // index of the last local symbol
+        file_format->getDynSymTab().setInfo(dynsym_local_cnt);
+
+        // Because some entries in .dynamic section need information of .dynsym,
+        // .dynstr, .symtab, .strtab and .hash, we can not reserve non-DT_NEEDED
+        // entries until we get the size of the sections mentioned above
+        dynamic().reserveEntries(*file_format);
+        file_format->getDynamic().setSize(dynamic().numOfBytes());
       }
-
-      // set size
-      if (config().targets().is32Bits())
-        file_format->getDynSymTab().setSize(dynsym*sizeof(llvm::ELF::Elf32_Sym));
-      else
-        file_format->getDynSymTab().setSize(dynsym*sizeof(llvm::ELF::Elf64_Sym));
-      file_format->getDynStrTab().setSize(dynstr);
-      file_format->getHashTab().setSize(hash);
-
-      // set .dynsym sh_info to one greater than the symbol table
-      // index of the last local symbol
-      file_format->getDynSymTab().setInfo(dynsym_local_cnt);
     }
     /* fall through */
     case LinkerConfig::Object: {
@@ -905,41 +870,46 @@
 
       // set .symtab sh_info to one greater than the symbol table
       // index of the last local symbol
-      file_format->getSymTab().setInfo(symbols.numOfLocals() + 1);
+      file_format->getSymTab().setInfo(symtab_local_cnt);
+
+      // compute the size of .shstrtab section.
+      Module::const_iterator sect, sectEnd = pModule.end();
+      for (sect = pModule.begin(); sect != sectEnd; ++sect) {
+        switch ((*sect)->kind()) {
+        case LDFileFormat::Null:
+          break;
+        // take StackNote directly
+        case LDFileFormat::StackNote:
+          shstrtab += ((*sect)->name().size() + 1);
+          break;
+        case LDFileFormat::EhFrame:
+          if (((*sect)->size() != 0) ||
+              ((*sect)->hasEhFrame() &&
+               config().codeGenType() == LinkerConfig::Object))
+            shstrtab += ((*sect)->name().size() + 1);
+          break;
+        case LDFileFormat::Relocation:
+          if (((*sect)->size() != 0) ||
+              ((*sect)->hasRelocData() &&
+               config().codeGenType() == LinkerConfig::Object))
+            shstrtab += ((*sect)->name().size() + 1);
+          break;
+        default:
+          if (((*sect)->size() != 0) ||
+              ((*sect)->hasSectionData() &&
+               config().codeGenType() == LinkerConfig::Object))
+            shstrtab += ((*sect)->name().size() + 1);
+          break;
+        } // end of switch
+      } // end of for
+      shstrtab += (strlen(".shstrtab") + 1);
+      file_format->getShStrTab().setSize(shstrtab);
       break;
     }
     default:
       fatal(diag::fatal_illegal_codegen_type) << pModule.name();
       break;
   } // end of switch
-  /// @}
-
-  /// reserve fixed entries in the .dynamic section.
-  /// @{
-  if (LinkerConfig::DynObj == config().codeGenType() ||
-      LinkerConfig::Exec   == config().codeGenType() ||
-      LinkerConfig::Binary == config().codeGenType()) {
-    // Because some entries in .dynamic section need information of .dynsym,
-    // .dynstr, .symtab, .strtab and .hash, we can not reserve non-DT_NEEDED
-    // entries until we get the size of the sections mentioned above
-    if (!pIsStaticLink)
-      dynamic().reserveEntries(*file_format);
-    file_format->getDynamic().setSize(dynamic().numOfBytes());
-  }
-  /// @}
-
-  /// compute the size of .shstrtab section.
-  /// @{
-  Module::const_iterator sect, sectEnd = pModule.end();
-  for (sect = pModule.begin(); sect != sectEnd; ++sect) {
-    // StackNote sections will always be in output!
-    if (0 != (*sect)->size() || LDFileFormat::StackNote == (*sect)->kind()) {
-      shstrtab += ((*sect)->name().size() + 1);
-    }
-  }
-  shstrtab += (strlen(".shstrtab") + 1);
-  file_format->getShStrTab().setSize(shstrtab);
-  /// @}
 }
 
 /// emitSymbol32 - emit an ELF32 symbol
@@ -974,14 +944,19 @@
 {
    // FIXME: check the endian between host and target
    // write out symbol
+   if (ResolveInfo::Section != pSymbol.type()) {
+     pSym.st_name  = pStrtabsize;
+     strcpy((pStrtab + pStrtabsize), pSymbol.name());
+   }
+   else {
+     pSym.st_name  = 0;
+   }
    pSym.st_name  = pStrtabsize;
    pSym.st_value = pSymbol.value();
    pSym.st_size  = getSymbolSize(pSymbol);
    pSym.st_info  = getSymbolInfo(pSymbol);
    pSym.st_other = pSymbol.visibility();
    pSym.st_shndx = getSymbolShndx(pSymbol);
-   // write out string
-   strcpy((pStrtab + pStrtabsize), pSymbol.name());
 }
 
 /// emitRegNamePools - emit regular name pools - .symtab, .strtab
@@ -1015,54 +990,37 @@
 
   // set up strtab_region
   char* strtab = (char*)strtab_region->start();
-  strtab[0] = '\0';
 
-  // initialize the first ELF symbol
-  if (config().targets().is32Bits()) {
-    symtab32[0].st_name  = 0;
-    symtab32[0].st_value = 0;
-    symtab32[0].st_size  = 0;
-    symtab32[0].st_info  = 0;
-    symtab32[0].st_other = 0;
-    symtab32[0].st_shndx = 0;
-  }
-  else { // must 64
-    symtab64[0].st_name  = 0;
-    symtab64[0].st_value = 0;
-    symtab64[0].st_size  = 0;
-    symtab64[0].st_info  = 0;
-    symtab64[0].st_other = 0;
-    symtab64[0].st_shndx = 0;
-  }
+  // emit the first ELF symbol
+  if (config().targets().is32Bits())
+    emitSymbol32(symtab32[0], *LDSymbol::Null(), strtab, 0, 0);
+  else
+    emitSymbol64(symtab64[0], *LDSymbol::Null(), strtab, 0, 0);
 
   bool sym_exist = false;
   HashTableType::entry_type* entry = NULL;
   if (LinkerConfig::Object == config().codeGenType()) {
-    entry = m_pSymIndexMap->insert(NULL, sym_exist);
+    entry = m_pSymIndexMap->insert(LDSymbol::Null(), sym_exist);
     entry->setValue(0);
   }
 
-  size_t symtabIdx = 1;
+  size_t symIdx = 1;
   size_t strtabsize = 1;
-  // compute size of .symtab, .dynsym and .strtab
-  Module::const_sym_iterator symbol;
-  Module::const_sym_iterator symEnd = pModule.sym_end();
-  for (symbol = pModule.sym_begin(); symbol != symEnd; ++symbol) {
-    // maintain output's symbol and index map if building .o file
+
+  const Module::SymbolTable& symbols = pModule.getSymbolTable();
+  Module::const_sym_iterator symbol, symEnd;
+
+  symEnd = symbols.end();
+  for (symbol = symbols.begin(); symbol != symEnd; ++symbol) {
     if (LinkerConfig::Object == config().codeGenType()) {
       entry = m_pSymIndexMap->insert(*symbol, sym_exist);
-      entry->setValue(symtabIdx);
+      entry->setValue(symIdx);
     }
-
     if (config().targets().is32Bits())
-      emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
-                   symtabIdx);
+      emitSymbol32(symtab32[symIdx], **symbol, strtab, strtabsize, symIdx);
     else
-      emitSymbol64(symtab64[symtabIdx], **symbol, strtab, strtabsize,
-                   symtabIdx);
-
-    // sum up counters
-    ++symtabIdx;
+      emitSymbol64(symtab64[symIdx], **symbol, strtab, strtabsize, symIdx);
+    ++symIdx;
     if (ResolveInfo::Section != (*symbol)->type())
       strtabsize += (*symbol)->nameSize() + 1;
   }
@@ -1072,13 +1030,11 @@
 ///
 /// the size of these tables should be computed before layout
 /// layout should computes the start offset of these tables
-void GNULDBackend::emitDynNamePools(const Module& pModule,
-                                    MemoryArea& pOutput)
+void GNULDBackend::emitDynNamePools(Module& pModule, MemoryArea& pOutput)
 {
   ELFFileFormat* file_format = getOutputFormat();
   if (!file_format->hasDynSymTab() ||
       !file_format->hasDynStrTab() ||
-      !file_format->hasHashTab()   ||
       !file_format->hasDynamic())
     return;
 
@@ -1087,15 +1043,12 @@
 
   LDSection& symtab_sect = file_format->getDynSymTab();
   LDSection& strtab_sect = file_format->getDynStrTab();
-  LDSection& hash_sect   = file_format->getHashTab();
   LDSection& dyn_sect    = file_format->getDynamic();
 
   MemoryRegion* symtab_region = pOutput.request(symtab_sect.offset(),
                                                 symtab_sect.size());
   MemoryRegion* strtab_region = pOutput.request(strtab_sect.offset(),
                                                 strtab_sect.size());
-  MemoryRegion* hash_region   = pOutput.request(hash_sect.offset(),
-                                                hash_sect.size());
   MemoryRegion* dyn_region    = pOutput.request(dyn_sect.offset(),
                                                 dyn_sect.size());
   // set up symtab_region
@@ -1110,125 +1063,76 @@
                                       << config().targets().bitclass();
   }
 
-  // initialize the first ELF symbol
-  if (config().targets().is32Bits()) {
-    symtab32[0].st_name  = 0;
-    symtab32[0].st_value = 0;
-    symtab32[0].st_size  = 0;
-    symtab32[0].st_info  = 0;
-    symtab32[0].st_other = 0;
-    symtab32[0].st_shndx = 0;
-  }
-  else { // must 64
-    symtab64[0].st_name  = 0;
-    symtab64[0].st_value = 0;
-    symtab64[0].st_size  = 0;
-    symtab64[0].st_info  = 0;
-    symtab64[0].st_other = 0;
-    symtab64[0].st_shndx = 0;
-  }
   // set up strtab_region
   char* strtab = (char*)strtab_region->start();
-  strtab[0] = '\0';
 
-  // add the first symbol into m_pSymIndexMap
-  entry = m_pSymIndexMap->insert(NULL, sym_exist);
-  entry->setValue(0);
+  // emit the first ELF symbol
+  if (config().targets().is32Bits())
+    emitSymbol32(symtab32[0], *LDSymbol::Null(), strtab, 0, 0);
+  else
+    emitSymbol64(symtab64[0], *LDSymbol::Null(), strtab, 0, 0);
 
-  size_t symtabIdx = 1;
+  size_t symIdx = 1;
   size_t strtabsize = 1;
 
-  // emit of .dynsym, and .dynstr
-  Module::const_sym_iterator symbol;
-  const Module::SymbolTable& symbols = pModule.getSymbolTable();
-  // emit symbol in File and Local category if it's dynamic symbol
-  Module::const_sym_iterator symEnd = symbols.localEnd();
-  for (symbol = symbols.localBegin(); symbol != symEnd; ++symbol) {
-    if (!isDynamicSymbol(**symbol))
-      continue;
-
-    if (config().targets().is32Bits())
-      emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
-                   symtabIdx);
-    else
-      emitSymbol64(symtab64[symtabIdx], **symbol, strtab, strtabsize,
-                   symtabIdx);
-
-    // maintain output's symbol and index map
-    entry = m_pSymIndexMap->insert(*symbol, sym_exist);
-    entry->setValue(symtabIdx);
-    // sum up counters
-    ++symtabIdx;
-    if (ResolveInfo::Section != (*symbol)->type())
-      strtabsize += (*symbol)->nameSize() + 1;
+  Module::SymbolTable& symbols = pModule.getSymbolTable();
+  // emit .gnu.hash
+  if (GeneralOptions::GNU  == config().options().getHashStyle() ||
+      GeneralOptions::Both == config().options().getHashStyle()) {
+    // Currently we may add output symbols after sizeNamePools(), and a
+    // non-stable sort is used in SymbolCategory::arrange(), so we just
+    // sort .dynsym right before emitting .gnu.hash
+    std::stable_sort(symbols.dynamicBegin(), symbols.dynamicEnd(),
+                     DynsymCompare());
+    emitGNUHashTab(symbols, pOutput);
   }
+  // emit .hash
+  if (GeneralOptions::SystemV == config().options().getHashStyle() ||
+      GeneralOptions::Both == config().options().getHashStyle())
+    emitELFHashTab(symbols, pOutput);
 
-  // emit symbols in TLS category, all symbols in TLS category shold be emitited
-  symEnd = symbols.tlsEnd();
-  for (symbol = symbols.tlsBegin(); symbol != symEnd; ++symbol) {
+  // emit .dynsym, and .dynstr (emit LocalDyn and Dynamic category)
+  Module::const_sym_iterator symbol, symEnd = symbols.dynamicEnd();
+  for (symbol = symbols.localDynBegin(); symbol != symEnd; ++symbol) {
     if (config().targets().is32Bits())
-      emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
-                   symtabIdx);
+      emitSymbol32(symtab32[symIdx], **symbol, strtab, strtabsize, symIdx);
     else
-      emitSymbol64(symtab64[symtabIdx], **symbol, strtab, strtabsize,
-                   symtabIdx);
-
+      emitSymbol64(symtab64[symIdx], **symbol, strtab, strtabsize, symIdx);
     // maintain output's symbol and index map
     entry = m_pSymIndexMap->insert(*symbol, sym_exist);
-    entry->setValue(symtabIdx);
+    entry->setValue(symIdx);
     // sum up counters
-    ++symtabIdx;
-    if (ResolveInfo::Section != (*symbol)->type())
-      strtabsize += (*symbol)->nameSize() + 1;
-  }
-
-  // emit the reset of the symbols if the symbol is dynamic symbol
-  symEnd = pModule.sym_end();
-  for (symbol = symbols.tlsEnd(); symbol != symEnd; ++symbol) {
-    if (!isDynamicSymbol(**symbol))
-      continue;
-
-    if (config().targets().is32Bits())
-      emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
-                   symtabIdx);
-    else
-      emitSymbol64(symtab64[symtabIdx], **symbol, strtab, strtabsize,
-                   symtabIdx);
-
-    // maintain output's symbol and index map
-    entry = m_pSymIndexMap->insert(*symbol, sym_exist);
-    entry->setValue(symtabIdx);
-    // sum up counters
-    ++symtabIdx;
+    ++symIdx;
     if (ResolveInfo::Section != (*symbol)->type())
       strtabsize += (*symbol)->nameSize() + 1;
   }
 
   // emit DT_NEED
   // add DT_NEED strings into .dynstr
-  // Rules:
-  //   1. ignore --no-add-needed
-  //   2. force count in --no-as-needed
-  //   3. judge --as-needed
   ELFDynamic::iterator dt_need = dynamic().needBegin();
   Module::const_lib_iterator lib, libEnd = pModule.lib_end();
   for (lib = pModule.lib_begin(); lib != libEnd; ++lib) {
-    // --add-needed
-    if ((*lib)->attribute()->isAddNeeded()) {
-      // --no-as-needed
-      if (!(*lib)->attribute()->isAsNeeded()) {
-        strcpy((strtab + strtabsize), (*lib)->name().c_str());
-        (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
-        strtabsize += (*lib)->name().size() + 1;
-        ++dt_need;
-      }
-      // --as-needed
-      else if ((*lib)->isNeeded()) {
-        strcpy((strtab + strtabsize), (*lib)->name().c_str());
-        (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
-        strtabsize += (*lib)->name().size() + 1;
-        ++dt_need;
-      }
+    if (!(*lib)->attribute()->isAsNeeded() || (*lib)->isNeeded()) {
+      strcpy((strtab + strtabsize), (*lib)->name().c_str());
+      (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
+      strtabsize += (*lib)->name().size() + 1;
+      ++dt_need;
+    }
+  }
+
+  if (!config().options().getRpathList().empty()) {
+    if (!config().options().hasNewDTags())
+      (*dt_need)->setValue(llvm::ELF::DT_RPATH, strtabsize);
+    else
+      (*dt_need)->setValue(llvm::ELF::DT_RUNPATH, strtabsize);
+    ++dt_need;
+
+    GeneralOptions::const_rpath_iterator rpath,
+      rpathEnd = config().options().rpath_end();
+    for (rpath = config().options().rpath_begin(); rpath != rpathEnd; ++rpath) {
+      memcpy((strtab + strtabsize), (*rpath).data(), (*rpath).size());
+      strtabsize += (*rpath).size();
+      strtab[strtabsize++] = (rpath + 1 == rpathEnd ? '\0' : ':');
     }
   }
 
@@ -1245,18 +1149,27 @@
     strcpy((strtab + strtabsize), pModule.name().c_str());
     strtabsize += pModule.name().size() + 1;
   }
-  // emit hash table
-  // FIXME: this verion only emit SVR4 hash section.
-  //        Please add GNU new hash section
+}
 
+/// emitELFHashTab - emit .hash
+void GNULDBackend::emitELFHashTab(const Module::SymbolTable& pSymtab,
+                                  MemoryArea& pOutput)
+{
+  ELFFileFormat* file_format = getOutputFormat();
+  if (!file_format->hasHashTab())
+    return;
+  LDSection& hash_sect = file_format->getHashTab();
+  MemoryRegion* hash_region = pOutput.request(hash_sect.offset(),
+                                              hash_sect.size());
   // both 32 and 64 bits hash table use 32-bit entry
   // set up hash_region
   uint32_t* word_array = (uint32_t*)hash_region->start();
   uint32_t& nbucket = word_array[0];
   uint32_t& nchain  = word_array[1];
 
-  nbucket = getHashBucketCount(symtabIdx, false);
-  nchain  = symtabIdx;
+  size_t dynsymSize = 1 + pSymtab.numOfLocalDyns() + pSymtab.numOfDynamics();
+  nbucket = getHashBucketCount(dynsymSize, false);
+  nchain  = dynsymSize;
 
   uint32_t* bucket = (word_array + 2);
   uint32_t* chain  = (bucket + nbucket);
@@ -1266,21 +1179,140 @@
 
   StringHash<ELF> hash_func;
 
-  if (config().targets().is32Bits()) {
-    for (size_t sym_idx=0; sym_idx < symtabIdx; ++sym_idx) {
-      llvm::StringRef name(strtab + symtab32[sym_idx].st_name);
-      size_t bucket_pos = hash_func(name) % nbucket;
-      chain[sym_idx] = bucket[bucket_pos];
-      bucket[bucket_pos] = sym_idx;
-    }
+  size_t idx = 1;
+  Module::const_sym_iterator symbol, symEnd = pSymtab.dynamicEnd();
+  for (symbol = pSymtab.localDynBegin(); symbol != symEnd; ++symbol) {
+    llvm::StringRef name((*symbol)->name());
+    size_t bucket_pos = hash_func(name) % nbucket;
+    chain[idx] = bucket[bucket_pos];
+    bucket[bucket_pos] = idx;
+    ++idx;
   }
-  else if (config().targets().is64Bits()) {
-    for (size_t sym_idx=0; sym_idx < symtabIdx; ++sym_idx) {
-      llvm::StringRef name(strtab + symtab64[sym_idx].st_name);
-      size_t bucket_pos = hash_func(name) % nbucket;
-      chain[sym_idx] = bucket[bucket_pos];
-      bucket[bucket_pos] = sym_idx;
+}
+
+/// emitGNUHashTab - emit .gnu.hash
+void GNULDBackend::emitGNUHashTab(Module::SymbolTable& pSymtab,
+                                  MemoryArea& pOutput)
+{
+  ELFFileFormat* file_format = getOutputFormat();
+  if (!file_format->hasGNUHashTab())
+    return;
+
+  MemoryRegion* gnuhash_region =
+    pOutput.request(file_format->getGNUHashTab().offset(),
+                    file_format->getGNUHashTab().size());
+
+  uint32_t* word_array = (uint32_t*)gnuhash_region->start();
+  // fixed-length fields
+  uint32_t& nbucket   = word_array[0];
+  uint32_t& symidx    = word_array[1];
+  uint32_t& maskwords = word_array[2];
+  uint32_t& shift2    = word_array[3];
+  // variable-length fields
+  uint8_t*  bitmask = (uint8_t*)(word_array + 4);
+  uint32_t* bucket  = NULL;
+  uint32_t* chain   = NULL;
+
+  // count the number of dynsym to hash
+  size_t unhashed_sym_cnt = pSymtab.numOfLocalDyns();
+  size_t hashed_sym_cnt   = pSymtab.numOfDynamics();
+  Module::const_sym_iterator symbol, symEnd = pSymtab.dynamicEnd();
+  for (symbol = pSymtab.dynamicBegin(); symbol != symEnd; ++symbol) {
+    if (DynsymCompare().needGNUHash(**symbol))
+      break;
+      ++unhashed_sym_cnt;
+      --hashed_sym_cnt;
+  }
+
+  // special case for the empty hash table
+  if (hashed_sym_cnt == 0) {
+    nbucket   = 1; // one empty bucket
+    symidx    = 1 + unhashed_sym_cnt; // symidx above unhashed symbols
+    maskwords = 1; // bitmask length
+    shift2    = 0; // bloom filter
+
+    if (config().targets().is32Bits()) {
+      uint32_t* maskval = (uint32_t*)bitmask;
+      *maskval = 0; // no valid hashes
+    } else {
+      // must be 64
+      uint64_t* maskval = (uint64_t*)bitmask;
+      *maskval = 0; // no valid hashes
     }
+    bucket  = (uint32_t*)(bitmask + config().targets().bitclass() / 8);
+    *bucket = 0; // no hash in the only bucket
+    return;
+  }
+
+  uint32_t maskbitslog2 = getGNUHashMaskbitslog2(hashed_sym_cnt);
+  uint32_t maskbits = 1u << maskbitslog2;
+  uint32_t shift1 = config().targets().is32Bits() ? 5 : 6;
+  uint32_t mask = (1u << shift1) - 1;
+
+  nbucket   = getHashBucketCount(hashed_sym_cnt, true);
+  symidx    = 1 + unhashed_sym_cnt;
+  maskwords = 1 << (maskbitslog2 - shift1);
+  shift2    = maskbitslog2;
+
+  // setup bucket and chain
+  bucket = (uint32_t*)(bitmask + maskbits / 8);
+  chain  = (bucket + nbucket);
+
+  // build the gnu style hash table
+  typedef std::multimap<uint32_t,
+                        std::pair<LDSymbol*, uint32_t> > SymMapType;
+  SymMapType symmap;
+  symEnd = pSymtab.dynamicEnd();
+  for (symbol = pSymtab.localDynBegin() + symidx - 1; symbol != symEnd;
+    ++symbol) {
+    StringHash<DJB> hasher;
+    uint32_t djbhash = hasher((*symbol)->name());
+    uint32_t hash = djbhash % nbucket;
+    symmap.insert(std::make_pair(hash, std::make_pair(*symbol, djbhash)));
+  }
+
+  // compute bucket, chain, and bitmask
+  std::vector<uint64_t> bitmasks(maskwords);
+  size_t hashedidx = symidx;
+  for (size_t idx = 0; idx < nbucket; ++idx) {
+    size_t count = 0;
+    std::pair<SymMapType::iterator, SymMapType::iterator> ret;
+    ret = symmap.equal_range(idx);
+    for (SymMapType::iterator it = ret.first; it != ret.second; ) {
+      // rearrange the hashed symbol ordering
+      *(pSymtab.localDynBegin() + hashedidx - 1) = it->second.first;
+      uint32_t djbhash = it->second.second;
+      uint32_t val = ((djbhash >> shift1) & ((maskbits >> shift1) - 1));
+      bitmasks[val] |= 1u << (djbhash & mask);
+      bitmasks[val] |= 1u << ((djbhash >> shift2) & mask);
+      val = djbhash & ~1u;
+      // advance the iterator and check if we're dealing w/ the last elment
+      if (++it == ret.second) {
+        // last element terminates the chain
+        val |= 1;
+      }
+      chain[hashedidx - symidx] = val;
+
+      ++hashedidx;
+      ++count;
+    }
+
+    if (count == 0)
+      bucket[idx] = 0;
+    else
+      bucket[idx] = hashedidx - count;
+  }
+
+  // write the bitmasks
+  if (config().targets().is32Bits()) {
+    uint32_t* maskval = (uint32_t*)bitmask;
+    for (size_t i = 0; i < maskwords; ++i)
+      std::memcpy(maskval + i, &bitmasks[i], 4);
+  } else {
+    // must be 64
+    uint64_t* maskval = (uint64_t*)bitmask;
+    for (size_t i = 0; i < maskwords; ++i)
+      std::memcpy(maskval + i, &bitmasks[i], 8);
   }
 }
 
@@ -1291,7 +1323,7 @@
   if (config().options().hasDyld())
     dyld_name = config().options().dyld().c_str();
   else
-    dyld_name = dyld();
+    dyld_name = m_pInfo->dyld();
 
   LDSection& interp = getOutputFormat()->getInterp();
   interp.setSize(std::strlen(dyld_name) + 1);
@@ -1307,7 +1339,7 @@
     if (config().options().hasDyld())
       dyld_name = config().options().dyld().c_str();
     else
-      dyld_name = dyld();
+      dyld_name = m_pInfo->dyld();
 
     std::memcpy(region->start(), dyld_name, interp.size());
   }
@@ -1381,9 +1413,14 @@
     case LDFileFormat::Target:
       return getTargetSectionOrder(pSectHdr);
 
-    // handle .interp
+    // handle .interp and .note.* sections
     case LDFileFormat::Note:
-      return SHO_INTERP;
+      if (file_format->hasInterp() && (&pSectHdr == &file_format->getInterp()))
+        return SHO_INTERP;
+      else if (is_write)
+        return SHO_RW_NOTE;
+      else
+        return SHO_RO_NOTE;
 
     case LDFileFormat::EhFrame:
     case LDFileFormat::EhFrameHdr:
@@ -1456,7 +1493,8 @@
   if (pSymbol.resolveInfo()->isUndef() || pSymbol.isDyn())
     return llvm::ELF::SHN_UNDEF;
 
-  if (pSymbol.resolveInfo()->isLocal()) {
+  if (pSymbol.resolveInfo()->isLocal() &&
+      LinkerConfig::Object != config().codeGenType()) {
     switch (pSymbol.type()) {
       case ResolveInfo::NoType:
       case ResolveInfo::File:
@@ -1472,12 +1510,43 @@
 }
 
 /// getSymbolIdx - called by emitRelocation to get the ouput symbol table index
-size_t GNULDBackend::getSymbolIdx(LDSymbol* pSymbol) const
+size_t GNULDBackend::getSymbolIdx(const LDSymbol* pSymbol) const
 {
-   HashTableType::iterator entry = m_pSymIndexMap->find(pSymbol);
+   HashTableType::iterator entry = m_pSymIndexMap->find(const_cast<LDSymbol *>(pSymbol));
+   assert(entry != m_pSymIndexMap->end() && "symbol not found in the symbol table");
    return entry.getEntry()->value();
 }
 
+/// isTemporary - Whether pSymbol is a local label.
+bool GNULDBackend::isTemporary(const LDSymbol& pSymbol) const
+{
+  if (ResolveInfo::Local != pSymbol.binding())
+    return false;
+
+  if (pSymbol.nameSize() < 2)
+    return false;
+
+  const char* name = pSymbol.name();
+  if ('.' == name[0] && 'L' == name[1])
+    return true;
+
+  // UnixWare 2.1 cc generate DWARF debugging symbols with `..' prefix.
+  // @ref Google gold linker, target.cc:39 @@ Target::do_is_local_label_name()
+  if (name[0] == '.' && name[1] == '.')
+    return true;
+
+  // Work arround for gcc's bug
+  // gcc sometimes generate symbols with '_.L_' prefix.
+  // @ref Google gold linker, target.cc:39 @@ Target::do_is_local_label_name()
+  if (pSymbol.nameSize() < 4)
+    return false;
+
+  if (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_')
+    return true;
+
+  return false;
+}
+
 /// allocateCommonSymbols - allocate common symbols in the corresponding
 /// sections. This is executed at pre-layout stage.
 /// @refer Google gold linker: common.cc: 214
@@ -1486,7 +1555,8 @@
 {
   SymbolCategory& symbol_list = pModule.getSymbolTable();
 
-  if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
+  if (symbol_list.emptyCommons() && symbol_list.emptyFiles() &&
+      symbol_list.emptyLocals() && symbol_list.emptyLocalDyns())
     return true;
 
   SymbolCategory::iterator com_sym, com_end;
@@ -1575,10 +1645,33 @@
   return true;
 }
 
+/// updateSectionFlags - update pTo's flags when merging pFrom
+/// update the output section flags based on input section flags.
+/// @ref The Google gold linker:
+///      output.cc: 2809: Output_section::update_flags_for_input_section
+bool GNULDBackend::updateSectionFlags(LDSection& pTo, const LDSection& pFrom)
+{
+  // union the flags from input
+  uint32_t flags = pTo.flag();
+  flags |= (pFrom.flag() &
+              (llvm::ELF::SHF_WRITE |
+               llvm::ELF::SHF_ALLOC |
+               llvm::ELF::SHF_EXECINSTR));
+
+  // if there is an input section is not SHF_MERGE, clean this flag
+  if (0 == (pFrom.flag() & llvm::ELF::SHF_MERGE))
+    flags &= ~llvm::ELF::SHF_MERGE;
+
+  // if there is an input section is not SHF_STRINGS, clean this flag
+  if (0 == (pFrom.flag() & llvm::ELF::SHF_STRINGS))
+    flags &= ~llvm::ELF::SHF_STRINGS;
+
+  pTo.setFlag(flags);
+  return true;
+}
 
 /// createProgramHdrs - base on output sections to create the program headers
-void GNULDBackend::createProgramHdrs(Module& pModule,
-                                     const FragmentLinker& pLinker)
+void GNULDBackend::createProgramHdrs(Module& pModule)
 {
   ELFFileFormat *file_format = getOutputFormat();
 
@@ -1633,7 +1726,8 @@
     if (createPT_LOAD) {
       // create new PT_LOAD segment
       load_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_LOAD, cur_flag);
-      load_seg->setAlign(abiPageSize());
+      if (!config().options().nmagic() && !config().options().omagic())
+        load_seg->setAlign(abiPageSize());
     }
 
     assert(NULL != load_seg);
@@ -1695,12 +1789,31 @@
                               getSegmentFlag(file_format->getStackNote().flag()));
   }
 
+  // make PT_NOTE
+  ELFSegment *note_seg = NULL;
+  prev_flag = getSegmentFlag(0);
+  for (sect = pModule.begin(); sect != sect_end; ++sect) {
+    if ((*sect)->kind() != LDFileFormat::Note ||
+        ((*sect)->flag() & llvm::ELF::SHF_ALLOC) == 0)
+      continue;
+
+    cur_flag = getSegmentFlag((*sect)->flag());
+    // we have different section orders for read-only and writable notes, so
+    // create 2 segments if needed.
+    if (note_seg == NULL ||
+        (cur_flag & llvm::ELF::PF_W) != (prev_flag & llvm::ELF::PF_W))
+      note_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_NOTE, cur_flag);
+
+    note_seg->addSection(*sect);
+    prev_flag = cur_flag;
+  }
+
   // create target dependent segments
-  doCreateProgramHdrs(pModule, pLinker);
+  doCreateProgramHdrs(pModule);
 }
 
 /// setupProgramHdrs - set up the attributes of segments
-void GNULDBackend::setupProgramHdrs(const FragmentLinker& pLinker)
+void GNULDBackend::setupProgramHdrs()
 {
   // update segment info
   ELFSegmentFactory::iterator seg, seg_end = m_ELFSegmentTable.end();
@@ -1719,7 +1832,7 @@
         phdr_size = sizeof(llvm::ELF::Elf64_Phdr);
       }
       segment.setOffset(offset);
-      segment.setVaddr(segmentStartAddr(pLinker) + offset);
+      segment.setVaddr(segmentStartAddr() + offset);
       segment.setPaddr(segment.vaddr());
       segment.setFilesz(numOfSegments() * phdr_size);
       segment.setMemsz(numOfSegments() * phdr_size);
@@ -1734,7 +1847,7 @@
     segment.setOffset(segment.front()->offset());
     if (llvm::ELF::PT_LOAD == segment.type() &&
         LDFileFormat::Null == segment.front()->kind())
-      segment.setVaddr(segmentStartAddr(pLinker));
+      segment.setVaddr(segmentStartAddr());
     else
       segment.setVaddr(segment.front()->addr());
     segment.setPaddr(segment.vaddr());
@@ -1752,7 +1865,7 @@
 
 /// setupGNUStackInfo - setup the section flag of .note.GNU-stack in output
 /// @ref gold linker: layout.cc:2608
-void GNULDBackend::setupGNUStackInfo(Module& pModule, FragmentLinker& pLinker)
+void GNULDBackend::setupGNUStackInfo(Module& pModule)
 {
   uint32_t flag = 0x0;
   if (config().options().hasStackSet()) {
@@ -1787,7 +1900,7 @@
     // 2.3 a special case. Use the target default to decide if the stack should
     //     be executable
     if (llvm::ELF::SHF_EXECINSTR != flag && object_count != stack_note_count)
-      if (isDefaultExecStack())
+      if (m_pInfo->isDefaultExecStack())
         flag = llvm::ELF::SHF_EXECINSTR;
   }
 
@@ -1877,8 +1990,7 @@
 }
 
 /// setOutputSectionOffset - helper function to set output sections' address
-void GNULDBackend::setOutputSectionAddress(FragmentLinker& pLinker,
-                                           Module& pModule,
+void GNULDBackend::setOutputSectionAddress(Module& pModule,
                                            Module::iterator pSectBegin,
                                            Module::iterator pSectEnd)
 {
@@ -1907,39 +2019,43 @@
       mapping = config().scripts().addressMap().find((*seg).front()->name());
 
     if (mapping != config().scripts().addressMap().end()) {
-      // check address mapping
+      // use address mapping in script options
       start_addr = mapping.getEntry()->value();
-      if ((*seg).front()->kind() != LDFileFormat::Null) {
-        const uint64_t remainder = start_addr % abiPageSize();
-        if (remainder != (*seg).front()->offset() % abiPageSize()) {
-          uint64_t padding = abiPageSize() + remainder -
-                             (*seg).front()->offset() % abiPageSize();
-          setOutputSectionOffset(pModule,
-                                 pModule.begin() + (*seg).front()->index(),
-                                 pModule.end(),
-                                 (*seg).front()->offset() + padding);
-          if (config().options().hasRelro())
-            setupRelro(pModule);
-        }
-      }
     }
     else {
       if ((*seg).front()->kind() == LDFileFormat::Null) {
         // 1st PT_LOAD
-        start_addr = segmentStartAddr(pLinker);
+        start_addr = segmentStartAddr();
       }
       else if ((*prev).front()->kind() == LDFileFormat::Null) {
         // prev segment is 1st PT_LOAD
-        start_addr = segmentStartAddr(pLinker) + (*seg).front()->offset();
+        start_addr = segmentStartAddr() + (*seg).front()->offset();
       }
       else {
         // Others
         start_addr = (*prev).front()->addr() + (*seg).front()->offset();
       }
+      // Try to align p_vaddr at page boundary if not in script options.
+      // To do so will add more padding in file, but can save one page
+      // at runtime.
+      alignAddress(start_addr, (*seg).align());
+    }
 
-      // padding
-      if (((*seg).front()->offset() & (abiPageSize() - 1)) != 0)
-        start_addr += abiPageSize();
+    // in p75, http://www.sco.com/developers/devspecs/gabi41.pdf
+    // p_align: As "Program Loading" describes in this chapter of the
+    // processor supplement, loadable process segments must have congruent
+    // values for p_vaddr and p_offset, modulo the page size.
+    if ((start_addr & ((*seg).align() - 1)) !=
+        ((*seg).front()->offset() & ((*seg).align() - 1))) {
+      uint64_t padding = (*seg).align() +
+                         (start_addr & ((*seg).align() - 1)) -
+                         ((*seg).front()->offset() & ((*seg).align() - 1));
+      setOutputSectionOffset(pModule,
+                             pModule.begin() + (*seg).front()->index(),
+                             pModule.end(),
+                             (*seg).front()->offset() + padding);
+      if (config().options().hasRelro())
+        setupRelro(pModule);
     }
 
     for (ELFSegment::sect_iterator sect = (*seg).begin(),
@@ -1963,7 +2079,7 @@
 }
 
 /// layout - layout method
-void GNULDBackend::layout(Module& pModule, FragmentLinker& pLinker)
+void GNULDBackend::layout(Module& pModule)
 {
   std::vector<SHOEntry> output_list;
   // 1. determine what sections will go into final output, and push the needed
@@ -1971,44 +2087,55 @@
   for (Module::iterator it = pModule.begin(), ie = pModule.end(); it != ie;
        ++it) {
     switch ((*it)->kind()) {
-      // take NULL and StackNote directly
-      case LDFileFormat::Null:
-      case LDFileFormat::StackNote:
+    // take NULL and StackNote directly
+    case LDFileFormat::Null:
+    case LDFileFormat::StackNote:
+      output_list.push_back(std::make_pair(*it, getSectionOrder(**it)));
+      break;
+    // ignore if section size is 0
+    case LDFileFormat::EhFrame:
+      if (((*it)->size() != 0) ||
+          ((*it)->hasEhFrame() &&
+           config().codeGenType() == LinkerConfig::Object))
         output_list.push_back(std::make_pair(*it, getSectionOrder(**it)));
-        break;
-      // ignore if section size is 0
-      case LDFileFormat::Regular:
-      case LDFileFormat::Target:
-      case LDFileFormat::MetaData:
-      case LDFileFormat::BSS:
-      case LDFileFormat::Debug:
-      case LDFileFormat::EhFrame:
-      case LDFileFormat::GCCExceptTable:
-      case LDFileFormat::NamePool:
-      case LDFileFormat::Relocation:
-      case LDFileFormat::Note:
-      case LDFileFormat::EhFrameHdr:
-        if (0 != (*it)->size()) {
-          output_list.push_back(std::make_pair(*it, getSectionOrder(**it)));
-        }
-        break;
-      case LDFileFormat::Group:
-        if (LinkerConfig::Object == config().codeGenType()) {
-          //TODO: support incremental linking
-          ;
-        }
-        break;
-      case LDFileFormat::Version:
-        if (0 != (*it)->size()) {
-          output_list.push_back(std::make_pair(*it, getSectionOrder(**it)));
-          warning(diag::warn_unsupported_symbolic_versioning) << (*it)->name();
-        }
-        break;
-      default:
-        if (0 != (*it)->size()) {
-          error(diag::err_unsupported_section) << (*it)->name() << (*it)->kind();
-        }
-        break;
+      break;
+    case LDFileFormat::Relocation:
+      if (((*it)->size() != 0) ||
+          ((*it)->hasRelocData() &&
+           config().codeGenType() == LinkerConfig::Object))
+        output_list.push_back(std::make_pair(*it, getSectionOrder(**it)));
+      break;
+    case LDFileFormat::Regular:
+    case LDFileFormat::Target:
+    case LDFileFormat::MetaData:
+    case LDFileFormat::BSS:
+    case LDFileFormat::Debug:
+    case LDFileFormat::GCCExceptTable:
+    case LDFileFormat::Note:
+    case LDFileFormat::NamePool:
+    case LDFileFormat::EhFrameHdr:
+      if (((*it)->size() != 0) ||
+          ((*it)->hasSectionData() &&
+           config().codeGenType() == LinkerConfig::Object))
+        output_list.push_back(std::make_pair(*it, getSectionOrder(**it)));
+      break;
+    case LDFileFormat::Group:
+      if (LinkerConfig::Object == config().codeGenType()) {
+        //TODO: support incremental linking
+        ;
+      }
+      break;
+    case LDFileFormat::Version:
+      if (0 != (*it)->size()) {
+        output_list.push_back(std::make_pair(*it, getSectionOrder(**it)));
+        warning(diag::warn_unsupported_symbolic_versioning) << (*it)->name();
+      }
+      break;
+    default:
+      if (0 != (*it)->size()) {
+        error(diag::err_unsupported_section) << (*it)->name() << (*it)->kind();
+      }
+      break;
     }
   } // end of for
 
@@ -2024,7 +2151,7 @@
 
   // 4. create program headers
   if (LinkerConfig::Object != config().codeGenType()) {
-    createProgramHdrs(pModule, pLinker);
+    createProgramHdrs(pModule);
   }
 
   // 5. set output section offset
@@ -2032,12 +2159,13 @@
 }
 
 /// preLayout - Backend can do any needed modification before layout
-void GNULDBackend::preLayout(Module& pModule, FragmentLinker& pLinker)
+void GNULDBackend::preLayout(Module& pModule, IRBuilder& pBuilder)
 {
   // prelayout target first
-  doPreLayout(pLinker);
+  doPreLayout(pBuilder);
 
-  if (config().options().hasEhFrameHdr() && getOutputFormat()->hasEhFrame()) {
+  if (LinkerConfig::Object != config().codeGenType() &&
+      config().options().hasEhFrameHdr() && getOutputFormat()->hasEhFrame()) {
     // init EhFrameHdr and size the output section
     ELFFileFormat* format = getOutputFormat();
     m_pEhFrameHdr = new EhFrameHdr(format->getEhFrameHdr(),
@@ -2045,12 +2173,12 @@
     m_pEhFrameHdr->sizeOutput();
   }
 
-  // change .tbss and .tdata section symbol from Local to TLS category
+  // change .tbss and .tdata section symbol from Local to LocalDyn category
   if (NULL != f_pTDATA)
-    pModule.getSymbolTable().changeLocalToTLS(*f_pTDATA);
+    pModule.getSymbolTable().changeLocalToDynamic(*f_pTDATA);
 
   if (NULL != f_pTBSS)
-    pModule.getSymbolTable().changeLocalToTLS(*f_pTBSS);
+    pModule.getSymbolTable().changeLocalToDynamic(*f_pTBSS);
 
   // To merge input's relocation sections into output's relocation sections.
   //
@@ -2111,12 +2239,11 @@
   } // end of if
 
   // set up the section flag of .note.GNU-stack section
-  setupGNUStackInfo(pModule, pLinker);
+  setupGNUStackInfo(pModule);
 }
 
 /// postLayout - Backend can do any needed modification after layout
-void GNULDBackend::postLayout(Module& pModule,
-                              FragmentLinker& pLinker)
+void GNULDBackend::postLayout(Module& pModule, IRBuilder& pBuilder)
 {
   // 1. set up section address and segment attributes
   if (LinkerConfig::Object != config().codeGenType()) {
@@ -2126,25 +2253,28 @@
     }
 
     // 1.2 set up the output sections' address
-    setOutputSectionAddress(pLinker, pModule, pModule.begin(), pModule.end());
+    setOutputSectionAddress(pModule, pModule.begin(), pModule.end());
 
     // 1.3 do relaxation
-    relax(pModule, pLinker);
+    relax(pModule, pBuilder);
 
     // 1.4 set up the attributes of program headers
-    setupProgramHdrs(pLinker);
+    setupProgramHdrs();
   }
 
   // 2. target specific post layout
-  doPostLayout(pModule, pLinker);
+  doPostLayout(pModule, pBuilder);
 }
 
-void GNULDBackend::postProcessing(FragmentLinker& pLinker, MemoryArea& pOutput)
+void GNULDBackend::postProcessing(MemoryArea& pOutput)
 {
-  if (config().options().hasEhFrameHdr() && getOutputFormat()->hasEhFrame()) {
+  if (LinkerConfig::Object != config().codeGenType() &&
+      config().options().hasEhFrameHdr() && getOutputFormat()->hasEhFrame()) {
     // emit eh_frame_hdr
     if (config().targets().is32Bits())
       m_pEhFrameHdr->emitOutput<32>(pOutput);
+    else
+      m_pEhFrameHdr->emitOutput<64>(pOutput);
   }
 }
 
@@ -2174,6 +2304,27 @@
   return result;
 }
 
+/// getGNUHashMaskbitslog2 - calculate the number of mask bits in log2
+/// @ref binutils gold, dynobj.cc:1165
+unsigned GNULDBackend::getGNUHashMaskbitslog2(unsigned pNumOfSymbols) const
+{
+  uint32_t maskbitslog2 = 1;
+  for (uint32_t x = pNumOfSymbols >> 1; x != 0; x >>=1)
+    ++maskbitslog2;
+
+  if (maskbitslog2 < 3)
+    maskbitslog2 = 5;
+  else if (((1U << (maskbitslog2 - 2)) & pNumOfSymbols) != 0)
+    maskbitslog2 += 3;
+  else
+    maskbitslog2 += 2;
+
+  if (config().targets().bitclass() == 64 && maskbitslog2 == 5)
+    maskbitslog2 = 6;
+
+  return maskbitslog2;
+}
+
 /// isDynamicSymbol
 /// @ref Google gold linker: symtab.cc:311
 bool GNULDBackend::isDynamicSymbol(const LDSymbol& pSymbol)
@@ -2189,10 +2340,8 @@
       LinkerConfig::Exec   == config().codeGenType() ||
       LinkerConfig::Binary == config().codeGenType()) {
     if (pSymbol.resolveInfo()->visibility() == ResolveInfo::Default ||
-        pSymbol.resolveInfo()->visibility() == ResolveInfo::Protected ||
-        pSymbol.resolveInfo()->type() == ResolveInfo::ThreadLocal) {
+        pSymbol.resolveInfo()->visibility() == ResolveInfo::Protected)
       return true;
-    }
   }
   return false;
 }
@@ -2212,10 +2361,8 @@
       LinkerConfig::Exec   == config().codeGenType() ||
       LinkerConfig::Binary == config().codeGenType()) {
     if (pResolveInfo.visibility() == ResolveInfo::Default ||
-        pResolveInfo.visibility() == ResolveInfo::Protected ||
-        pResolveInfo.type() == ResolveInfo::ThreadLocal) {
+        pResolveInfo.visibility() == ResolveInfo::Protected)
       return true;
-    }
   }
   return false;
 }
@@ -2227,7 +2374,7 @@
   if (config().options().commPageSize() > 0)
     return std::min(config().options().commPageSize(), abiPageSize());
   else
-    return std::min(static_cast<uint64_t>(0x1000), abiPageSize());
+    return std::min(m_pInfo->commonPageSize(), abiPageSize());
 }
 
 /// abiPageSize - the abi page size of the target machine.
@@ -2237,7 +2384,7 @@
   if (config().options().maxPageSize() > 0)
     return config().options().maxPageSize();
   else
-    return static_cast<uint64_t>(0x1000);
+    return m_pInfo->abiPageSize();
 }
 
 /// isSymbolPreemtible - whether the symbol can be preemted by other
@@ -2271,8 +2418,7 @@
 
 /// symbolNeedsDynRel - return whether the symbol needs a dynamic relocation
 /// @ref Google gold linker, symtab.h:645
-bool GNULDBackend::symbolNeedsDynRel(const FragmentLinker& pLinker,
-                                     const ResolveInfo& pSym,
+bool GNULDBackend::symbolNeedsDynRel(const ResolveInfo& pSym,
                                      bool pSymHasPLT,
                                      bool isAbsReloc) const
 {
@@ -2284,13 +2430,17 @@
        LinkerConfig::Binary == config().codeGenType()))
     return false;
 
-  if (pSym.isAbsolute())
+  // An absolute symbol can be resolved directly if it is either local
+  // or we are linking statically. Otherwise it can still be overridden
+  // at runtime.
+  if (pSym.isAbsolute() &&
+      (pSym.binding() == ResolveInfo::Local || config().isCodeStatic()))
     return false;
-  if (pLinker.isOutputPIC() && isAbsReloc)
+  if (config().isCodeIndep() && isAbsReloc)
     return true;
   if (pSymHasPLT && ResolveInfo::Function == pSym.type())
     return false;
-  if (!pLinker.isOutputPIC() && pSymHasPLT)
+  if (!config().isCodeIndep() && pSymHasPLT)
     return false;
   if (pSym.isDyn() || pSym.isUndef() ||
       isSymbolPreemptible(pSym))
@@ -2301,8 +2451,7 @@
 
 /// symbolNeedsPLT - return whether the symbol needs a PLT entry
 /// @ref Google gold linker, symtab.h:596
-bool GNULDBackend::symbolNeedsPLT(const FragmentLinker& pLinker,
-                                  const ResolveInfo& pSym) const
+bool GNULDBackend::symbolNeedsPLT(const ResolveInfo& pSym) const
 {
   if (pSym.isUndef() &&
       !pSym.isDyn() &&
@@ -2316,7 +2465,7 @@
   if (pSym.type() != ResolveInfo::Function)
     return false;
 
-  if (pLinker.isStaticLink() && !pLinker.isOutputPIC())
+  if (config().isCodeStatic())
     return false;
 
   if (config().options().isPIE())
@@ -2330,12 +2479,12 @@
 /// symbolHasFinalValue - return true if the symbol's value can be decided at
 /// link time
 /// @ref Google gold linker, Symbol::final_value_is_known
-bool GNULDBackend::symbolFinalValueIsKnown(const FragmentLinker& pLinker,
-                                           const ResolveInfo& pSym) const
+bool GNULDBackend::symbolFinalValueIsKnown(const ResolveInfo& pSym) const
 {
   // if the output is pic code or if not executables, symbols' value may change
   // at runtime
-  if (pLinker.isOutputPIC() ||
+  // FIXME: CodeIndep() || LinkerConfig::Relocatable == CodeGenType
+  if (config().isCodeIndep() ||
       (LinkerConfig::Exec != config().codeGenType() &&
        LinkerConfig::Binary != config().codeGenType()))
     return false;
@@ -2352,17 +2501,16 @@
   // if the symbol is undefined and not in dynamic objects, for example, a weak
   // undefined symbol, then whether the symbol's final value can be known
   // depends on whrther we're doing static link
-  return pLinker.isStaticLink();
+  return config().isCodeStatic();
 }
 
 /// symbolNeedsCopyReloc - return whether the symbol needs a copy relocation
-bool GNULDBackend::symbolNeedsCopyReloc(const FragmentLinker& pLinker,
-                                        const Relocation& pReloc,
+bool GNULDBackend::symbolNeedsCopyReloc(const Relocation& pReloc,
                                         const ResolveInfo& pSym) const
 {
   // only the reference from dynamic executable to non-function symbol in
   // the dynamic objects may need copy relocation
-  if (pLinker.isOutputPIC() ||
+  if (config().isCodeIndep() ||
       !pSym.isDyn() ||
       pSym.type() == ResolveInfo::Function ||
       pSym.size() == 0)
@@ -2437,14 +2585,14 @@
   return true;
 }
 
-bool GNULDBackend::relax(Module& pModule, FragmentLinker& pLinker)
+bool GNULDBackend::relax(Module& pModule, IRBuilder& pBuilder)
 {
   if (!mayRelax())
     return true;
 
   bool finished = true;
   do {
-    if (doRelax(pModule, pLinker, finished)) {
+    if (doRelax(pModule, pBuilder, finished)) {
       // If the sections (e.g., .text) are relaxed, the layout is also changed
       // We need to do the following:
 
@@ -2456,10 +2604,24 @@
         setupRelro(pModule);
 
       // 3. set up the output sections' address
-      setOutputSectionAddress(pLinker, pModule, pModule.begin(), pModule.end());
+      setOutputSectionAddress(pModule, pModule.begin(), pModule.end());
     }
   } while (!finished);
 
   return true;
 }
 
+bool GNULDBackend::DynsymCompare::needGNUHash(const LDSymbol& X) const
+{
+  // FIXME: in bfd and gold linker, an undefined symbol might be hashed
+  // when the ouput is not PIC, if the symbol is referred by a non pc-relative
+  // reloc, and its value is set to the addr of the plt entry.
+  return !X.resolveInfo()->isUndef() && !X.isDyn();
+}
+
+bool GNULDBackend::DynsymCompare::operator()(const LDSymbol* X,
+                                             const LDSymbol* Y) const
+{
+  return !needGNUHash(*X) && needGNUHash(*Y);
+}
+
diff --git a/lib/Target/Hexagon/Hexagon.h b/lib/Target/Hexagon/Hexagon.h
new file mode 100644
index 0000000..5a286ef
--- /dev/null
+++ b/lib/Target/Hexagon/Hexagon.h
@@ -0,0 +1,32 @@
+//===- Hexagon.h ----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_HEXAGON_H
+#define MCLD_HEXAGON_H
+#include <string>
+#include <mcld/Target/TargetMachine.h>
+
+namespace llvm {
+
+class Target;
+
+} // namespace of llvm
+
+namespace mcld {
+
+class TargetLDBackend;
+
+extern mcld::Target TheHexagonTarget;
+
+TargetLDBackend*
+createHexagonLDBackend(const llvm::Target&, const std::string&);
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/Hexagon/HexagonDiagnostic.cpp b/lib/Target/Hexagon/HexagonDiagnostic.cpp
new file mode 100644
index 0000000..01b8f9b
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonDiagnostic.cpp
@@ -0,0 +1,37 @@
+//===- HexagonDiagnostic.cpp ----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <llvm/ADT/Triple.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/LD/DWARFLineInfo.h>
+#include "Hexagon.h"
+
+using namespace mcld;
+
+namespace mcld {
+
+// createHexagonDiagnostic - the help function to create corresponding
+// HexagonDiagnostic
+//
+DiagnosticLineInfo*
+createHexagonDiagLineInfo(const Target& pTarget, const std::string &pTriple)
+{
+  return new DWARFLineInfo();
+}
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+// InitializeHexagonDiagnostic
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeHexagonDiagnosticLineInfo() {
+  // Register the linker frontend
+  mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheHexagonTarget,
+                                                   createHexagonDiagLineInfo);
+}
+
diff --git a/lib/Target/Hexagon/HexagonELFDynamic.cpp b/lib/Target/Hexagon/HexagonELFDynamic.cpp
new file mode 100644
index 0000000..96d0946
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonELFDynamic.cpp
@@ -0,0 +1,37 @@
+//===- HexagonELFDynamic.cpp ----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "HexagonELFDynamic.h"
+
+#include <mcld/LD/ELFFileFormat.h>
+
+using namespace mcld;
+
+HexagonELFDynamic::HexagonELFDynamic(const GNULDBackend& pParent,
+                                     const LinkerConfig& pConfig)
+  : ELFDynamic(pParent, pConfig) {
+}
+
+HexagonELFDynamic::~HexagonELFDynamic()
+{
+}
+
+void HexagonELFDynamic::reserveTargetEntries(const ELFFileFormat& pFormat)
+{
+  // reservePLTGOT
+  if (pFormat.hasGOTPLT())
+    reserveOne(llvm::ELF::DT_PLTGOT);
+}
+
+void HexagonELFDynamic::applyTargetEntries(const ELFFileFormat& pFormat)
+{
+  // applyPLTGOT
+  if (pFormat.hasGOTPLT())
+	  applyOne(llvm::ELF::DT_PLTGOT, pFormat.getGOTPLT().addr());
+}
+
diff --git a/lib/Target/Hexagon/HexagonELFDynamic.h b/lib/Target/Hexagon/HexagonELFDynamic.h
new file mode 100644
index 0000000..423d918
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonELFDynamic.h
@@ -0,0 +1,32 @@
+//===- HexagonELFDynamic.h ------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_HEXAGON_ELFDYNAMIC_SECTION_H
+#define MCLD_HEXAGON_ELFDYNAMIC_SECTION_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Target/ELFDynamic.h>
+
+namespace mcld {
+
+class HexagonELFDynamic : public ELFDynamic
+{
+public:
+  HexagonELFDynamic(const GNULDBackend& pParent, const LinkerConfig& pConfig);
+  ~HexagonELFDynamic();
+
+private:
+  void reserveTargetEntries(const ELFFileFormat& pFormat);
+  void applyTargetEntries(const ELFFileFormat& pFormat);
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/Hexagon/HexagonELFMCLinker.cpp b/lib/Target/Hexagon/HexagonELFMCLinker.cpp
new file mode 100644
index 0000000..6cc4a01
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonELFMCLinker.cpp
@@ -0,0 +1,23 @@
+//===- HexagonELFMCLinker.cpp ---------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "HexagonELFMCLinker.h"
+#include <mcld/LinkerConfig.h>
+
+using namespace mcld;
+
+HexagonELFMCLinker::HexagonELFMCLinker(LinkerConfig& pConfig,
+                                       mcld::Module& pModule,
+                                       MemoryArea& pOutput)
+  : ELFMCLinker(pConfig, pModule, pOutput) {
+}
+
+HexagonELFMCLinker::~HexagonELFMCLinker()
+{
+}
+
diff --git a/lib/Target/Hexagon/HexagonELFMCLinker.h b/lib/Target/Hexagon/HexagonELFMCLinker.h
new file mode 100644
index 0000000..c588ddf
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonELFMCLinker.h
@@ -0,0 +1,38 @@
+//===- HexagonELFMCLinker.h -----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef HEXAGON_ELFSECTLINKER_H
+#define HEXAGON_ELFSECTLINKER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/Target/ELFMCLinker.h>
+
+namespace mcld {
+
+class Module;
+class MemoryArea;
+
+/** \class HexagonELFMCLinker
+ *  \brief HexagonELFMCLinker sets up the environment for linking.
+ *
+ *  \see
+ */
+class HexagonELFMCLinker : public ELFMCLinker
+{
+public:
+  HexagonELFMCLinker(LinkerConfig& pConfig,
+                     mcld::Module& pModule,
+                     MemoryArea& pOutput);
+
+  ~HexagonELFMCLinker();
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/Hexagon/HexagonEmulation.cpp b/lib/Target/Hexagon/HexagonEmulation.cpp
new file mode 100644
index 0000000..3b8ee0d
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonEmulation.cpp
@@ -0,0 +1,65 @@
+//===- HexagonEmulation.cpp -----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "Hexagon.h"
+#include <mcld/LinkerConfig.h>
+#include <mcld/Target/ELFEmulation.h>
+#include <mcld/Support/TargetRegistry.h>
+
+namespace mcld {
+
+static bool MCLDEmulateHexagonELF(LinkerConfig& pConfig)
+{
+  if (!MCLDEmulateELF(pConfig))
+    return false;
+
+  // set up bitclass and endian
+  pConfig.targets().setEndian(TargetOptions::Little);
+  pConfig.targets().setBitClass(32);
+
+  // set up target-dependent constraints of attributes
+  pConfig.attribute().constraint().enableWholeArchive();
+  pConfig.attribute().constraint().enableAsNeeded();
+  pConfig.attribute().constraint().setSharedSystem();
+
+  // set up the predefined attributes
+  pConfig.attribute().predefined().unsetWholeArchive();
+  pConfig.attribute().predefined().unsetAsNeeded();
+  pConfig.attribute().predefined().setDynamic();
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// emulateHexagonLD - the help function to emulate Hexagon ld
+//===----------------------------------------------------------------------===//
+bool emulateHexagonLD(const std::string& pTriple, LinkerConfig& pConfig)
+{
+  llvm::Triple theTriple(pTriple);
+  if (theTriple.isOSDarwin()) {
+    assert(0 && "MachO linker has not supported yet");
+    return false;
+  }
+  if (theTriple.isOSWindows()) {
+    assert(0 && "COFF linker has not supported yet");
+    return false;
+  }
+
+  return MCLDEmulateHexagonELF(pConfig);
+}
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+// HexagonEmulation
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeHexagonEmulation() {
+  // Register the emulation
+  mcld::TargetRegistry::RegisterEmulation(mcld::TheHexagonTarget,
+                                          mcld::emulateHexagonLD);
+}
+
diff --git a/lib/Target/Hexagon/HexagonGNUInfo.h b/lib/Target/Hexagon/HexagonGNUInfo.h
new file mode 100644
index 0000000..082e2e5
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonGNUInfo.h
@@ -0,0 +1,33 @@
+//===- HexagonGNUInfo.h ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TARGET_HEXAGON_GNU_INFO_H
+#define MCLD_TARGET_HEXAGON_GNU_INFO_H
+#include <mcld/Target/GNUInfo.h>
+
+#include <llvm/Support/ELF.h>
+
+namespace mcld {
+
+class HexagonGNUInfo : public GNUInfo
+{
+public:
+  HexagonGNUInfo(const llvm::Triple& pTriple) : GNUInfo(pTriple) { }
+
+  uint32_t machine() const { return llvm::ELF::EM_HEXAGON; }
+
+  uint64_t defaultTextSegmentAddr() const { return 0x0; }
+
+  /// flags - the value of ElfXX_Ehdr::e_flags
+  uint64_t flags() const { return 0x2; }
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/Hexagon/HexagonGOT.cpp b/lib/Target/Hexagon/HexagonGOT.cpp
new file mode 100644
index 0000000..551b40f
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonGOT.cpp
@@ -0,0 +1,48 @@
+//===- HexagonGOT.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "HexagonGOT.h"
+
+#include <mcld/LD/LDFileFormat.h>
+#include <mcld/LD/SectionData.h>
+
+#include <llvm/Support/Casting.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// HexagonGOT
+//===----------------------------------------------------------------------===//
+HexagonGOT::HexagonGOT(LDSection& pSection)
+  : GOT(pSection), m_pLast(NULL)
+{
+}
+
+HexagonGOT::~HexagonGOT()
+{
+}
+
+void HexagonGOT::reserve(size_t pNum)
+{
+  for (size_t i = 0; i < pNum; i++) {
+    new HexagonGOTEntry(0, m_SectionData);
+  }
+}
+
+HexagonGOTEntry* HexagonGOT::consume()
+{
+  if (NULL == m_pLast) {
+    assert(!empty() && "Consume empty GOT entry!");
+    m_pLast = llvm::cast<HexagonGOTEntry>(&m_SectionData->front());
+    return m_pLast;
+  }
+
+  m_pLast = llvm::cast<HexagonGOTEntry>(m_pLast->getNextNode());
+  return m_pLast;
+}
+
diff --git a/lib/Target/Hexagon/HexagonGOT.h b/lib/Target/Hexagon/HexagonGOT.h
new file mode 100644
index 0000000..4f9120c
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonGOT.h
@@ -0,0 +1,55 @@
+//===- HexagonGOT.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TARGET_HEXAGON_GOT_H
+#define MCLD_TARGET_HEXAGON_GOT_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Target/GOT.h>
+
+namespace mcld {
+
+class LDSection;
+class SectionData;
+
+/** \class HexagonGOTEntry
+ *  \brief GOT Entry with size of 4 bytes
+ */
+class HexagonGOTEntry : public GOT::Entry<4>
+{
+public:
+  HexagonGOTEntry(uint64_t pContent, SectionData* pParent)
+   : GOT::Entry<4>(pContent, pParent)
+  {}
+};
+
+/** \class HexagonGOT
+ *  \brief Hexagon Global Offset Table.
+ */
+
+class HexagonGOT : public GOT
+{
+public:
+  HexagonGOT(LDSection& pSection);
+
+  ~HexagonGOT();
+
+  void reserve(size_t pNum = 1);
+
+  HexagonGOTEntry* consume();
+
+private:
+  HexagonGOTEntry* m_pLast; ///< the last consumed entry
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/Hexagon/HexagonLDBackend.cpp b/lib/Target/Hexagon/HexagonLDBackend.cpp
new file mode 100644
index 0000000..0d7ba26
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonLDBackend.cpp
@@ -0,0 +1,270 @@
+//===- HexagonLDBackend.cpp -----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "Hexagon.h"
+#include "HexagonELFDynamic.h"
+#include "HexagonLDBackend.h"
+#include "HexagonRelocator.h"
+#include "HexagonGNUInfo.h"
+
+#include <llvm/ADT/Triple.h>
+#include <llvm/Support/Casting.h>
+
+#include <mcld/LinkerConfig.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/Fragment/FillFragment.h>
+#include <mcld/Fragment/RegionFragment.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/Object/ObjectBuilder.h>
+
+#include <cstring>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// HexagonLDBackend
+//===----------------------------------------------------------------------===//
+HexagonLDBackend::HexagonLDBackend(const LinkerConfig& pConfig, 
+                                   HexagonGNUInfo* pInfo)
+  : GNULDBackend(pConfig, pInfo),
+    m_pRelocator(NULL),
+    m_pGOT(NULL),
+    m_pPLT(NULL),
+    m_pRelDyn(NULL),
+    m_pRelPLT(NULL),
+    m_pDynamic(NULL),
+    m_pGOTSymbol(NULL) {
+}
+
+HexagonLDBackend::~HexagonLDBackend()
+{
+  delete m_pRelocator;
+  delete m_pGOT;
+  delete m_pPLT;
+  delete m_pRelDyn;
+  delete m_pRelPLT;
+  delete m_pDynamic;
+}
+
+bool HexagonLDBackend::initRelocator()
+{
+  if (NULL == m_pRelocator) {
+    m_pRelocator = new HexagonRelocator(*this);
+  }
+  return true;
+}
+
+Relocator* HexagonLDBackend::getRelocator()
+{
+  assert(NULL != m_pRelocator);
+  return m_pRelocator;
+}
+
+void HexagonLDBackend::doPreLayout(IRBuilder& pBuilder)
+{
+  // initialize .dynamic data
+  if (!config().isCodeStatic() && NULL == m_pDynamic)
+    m_pDynamic = new HexagonELFDynamic(*this, config());
+}
+
+void HexagonLDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder)
+{
+}
+
+/// dynamic - the dynamic section of the target machine.
+/// Use co-variant return type to return its own dynamic section.
+HexagonELFDynamic& HexagonLDBackend::dynamic()
+{
+  assert(NULL != m_pDynamic);
+  return *m_pDynamic;
+}
+
+/// dynamic - the dynamic section of the target machine.
+/// Use co-variant return type to return its own dynamic section.
+const HexagonELFDynamic& HexagonLDBackend::dynamic() const
+{
+  assert(NULL != m_pDynamic);
+  return *m_pDynamic;
+}
+
+void HexagonLDBackend::scanRelocation(Relocation& pReloc,
+                                      IRBuilder& pBuilder,
+                                      Module& pModule,
+                                      LDSection& pSection)
+{
+  pReloc.updateAddend();
+}
+
+uint64_t HexagonLDBackend::emitSectionData(const LDSection& pSection,
+                                          MemoryRegion& pRegion) const
+{
+  return 0;
+}
+
+HexagonGOT& HexagonLDBackend::getGOT()
+{
+  assert(NULL != m_pGOT);
+  return *m_pGOT;
+}
+
+const HexagonGOT& HexagonLDBackend::getGOT() const
+{
+  assert(NULL != m_pGOT);
+  return *m_pGOT;
+}
+
+HexagonPLT& HexagonLDBackend::getPLT()
+{
+  assert(NULL != m_pPLT && "PLT section not exist");
+  return *m_pPLT;
+}
+
+const HexagonPLT& HexagonLDBackend::getPLT() const
+{
+  assert(NULL != m_pPLT && "PLT section not exist");
+  return *m_pPLT;
+}
+
+OutputRelocSection& HexagonLDBackend::getRelDyn()
+{
+  assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
+  return *m_pRelDyn;
+}
+
+const OutputRelocSection& HexagonLDBackend::getRelDyn() const
+{
+  assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
+  return *m_pRelDyn;
+}
+
+OutputRelocSection& HexagonLDBackend::getRelPLT()
+{
+  assert(NULL != m_pRelPLT && ".rel.plt section not exist");
+  return *m_pRelPLT;
+}
+
+const OutputRelocSection& HexagonLDBackend::getRelPLT() const
+{
+  assert(NULL != m_pRelPLT && ".rel.plt section not exist");
+  return *m_pRelPLT;
+}
+
+unsigned int
+HexagonLDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
+{
+  const ELFFileFormat* file_format = getOutputFormat();
+
+  if (&pSectHdr == &file_format->getGOT()) {
+    if (config().options().hasNow())
+      return SHO_RELRO;
+    return SHO_RELRO_LAST;
+  }
+
+  if (&pSectHdr == &file_format->getPLT())
+    return SHO_PLT;
+
+  return SHO_UNDEFINED;
+}
+
+void HexagonLDBackend::initTargetSections(Module& pModule, 
+                                          ObjectBuilder& pBuilder)
+{
+  if (LinkerConfig::Object != config().codeGenType()) {
+    ELFFileFormat* file_format = getOutputFormat();
+    // initialize .got
+    LDSection& got = file_format->getGOT();
+    m_pGOT = new HexagonGOT(got);
+
+    // initialize .plt
+    LDSection& plt = file_format->getPLT();
+    m_pPLT = new HexagonPLT(plt,
+                        *m_pGOT,
+                        config());
+
+    // initialize .rel.plt
+    LDSection& relplt = file_format->getRelPlt();
+    relplt.setLink(&plt);
+    m_pRelPLT = new OutputRelocSection(pModule, relplt);
+
+    // initialize .rel.dyn
+    LDSection& reldyn = file_format->getRelDyn();
+    m_pRelDyn = new OutputRelocSection(pModule, reldyn);
+
+  }
+}
+
+void HexagonLDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule)
+{
+  if (LinkerConfig::Object != config().codeGenType()) {
+    // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
+    // same name in input
+    m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                                    "_GLOBAL_OFFSET_TABLE_",
+                                                    ResolveInfo::Object,
+                                                    ResolveInfo::Define,
+                                                    ResolveInfo::Local,
+                                                    0x0,  // size
+                                                    0x0,  // value
+                                                    FragmentRef::Null(),
+                                                    ResolveInfo::Hidden);
+  }
+}
+
+/// finalizeSymbol - finalize the symbol value
+bool HexagonLDBackend::finalizeTargetSymbols()
+{
+  return true;
+}
+
+/// doCreateProgramHdrs - backend can implement this function to create the
+/// target-dependent segments
+void HexagonLDBackend::doCreateProgramHdrs(Module& pModule)
+{
+  // TODO
+}
+
+namespace mcld {
+
+//===----------------------------------------------------------------------===//
+/// createHexagonLDBackend - the help funtion to create corresponding 
+/// HexagonLDBackend
+TargetLDBackend* createHexagonLDBackend(const llvm::Target& pTarget,
+                                    const LinkerConfig& pConfig)
+{
+  if (pConfig.targets().triple().isOSDarwin()) {
+    assert(0 && "MachO linker is not supported yet");
+    /**
+    return new HexagonMachOLDBackend(createHexagonMachOArchiveReader,
+                               createHexagonMachOObjectReader,
+                               createHexagonMachOObjectWriter);
+    **/
+  }
+  if (pConfig.targets().triple().isOSWindows()) {
+    assert(0 && "COFF linker is not supported yet");
+    /**
+    return new HexagonCOFFLDBackend(createHexagonCOFFArchiveReader,
+                               createHexagonCOFFObjectReader,
+                               createHexagonCOFFObjectWriter);
+    **/
+  }
+  return new HexagonLDBackend(pConfig, 
+                              new HexagonGNUInfo(pConfig.targets().triple()));
+}
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+// Force static initialization.
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeHexagonLDBackend() {
+  // Register the linker backend
+  mcld::TargetRegistry::RegisterTargetLDBackend(TheHexagonTarget, 
+                                                createHexagonLDBackend);
+}
diff --git a/lib/Target/Hexagon/HexagonLDBackend.h b/lib/Target/Hexagon/HexagonLDBackend.h
new file mode 100644
index 0000000..46da924
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonLDBackend.h
@@ -0,0 +1,149 @@
+//===- HexagonLDBackend.h -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef HEXAGON_LDBACKEND_H
+#define HEXAGON_LDBACKEND_H
+
+#include "HexagonELFDynamic.h"
+#include "HexagonGOT.h"
+#include "HexagonPLT.h"
+#include <mcld/LD/LDSection.h>
+#include <mcld/Target/GNULDBackend.h>
+#include <mcld/Target/OutputRelocSection.h>
+
+namespace mcld {
+
+class LinkerConfig;
+class HexagonGNUInfo;
+
+//===----------------------------------------------------------------------===//
+/// HexagonLDBackend - linker backend of Hexagon target of GNU ELF format
+///
+class HexagonLDBackend : public GNULDBackend
+{
+public:
+  HexagonLDBackend(const LinkerConfig& pConfig, HexagonGNUInfo* pInfo);
+
+  ~HexagonLDBackend();
+
+  uint32_t machine() const;
+
+  HexagonGOT& getGOT();
+
+  const HexagonGOT& getGOT() const;
+
+  HexagonPLT& getPLT();
+
+  const HexagonPLT& getPLT() const;
+
+  /// preLayout - Backend can do any needed modification before layout
+  void doPreLayout(IRBuilder& pBuilder);
+
+  /// postLayout - Backend can do any needed modification after layout
+  void doPostLayout(Module& pModule, IRBuilder& pBuilder);
+
+  /// dynamic - the dynamic section of the target machine.
+  /// Use co-variant return type to return its own dynamic section.
+  HexagonELFDynamic& dynamic();
+
+  /// dynamic - the dynamic section of the target machine.
+  /// Use co-variant return type to return its own dynamic section.
+  const HexagonELFDynamic& dynamic() const;
+
+  /// emitSectionData - write out the section data into the memory region.
+  /// When writers get a LDSection whose kind is LDFileFormat::Target, writers
+  /// call back target backend to emit the data.
+  ///
+  /// Backends handle the target-special tables (plt, gp,...) by themselves.
+  /// Backend can put the data of the tables in MCSectionData directly
+  ///  - LDSection.getSectionData can get the section data.
+  /// Or, backend can put the data into special data structure
+  ///  - backend can maintain its own map<LDSection, table> to get the table
+  /// from given LDSection.
+  ///
+  /// @param pSection - the given LDSection
+  /// @param pLayout - for comouting the size of fragment
+  /// @param pRegion - the region to write out data
+  /// @return the size of the table in the file.
+  uint64_t emitSectionData(const LDSection& pSection,
+                           MemoryRegion& pRegion) const;
+
+  /// initRelocator - create and initialize Relocator.
+  bool initRelocator();
+
+  /// getRelocator - return relocator.
+  Relocator* getRelocator();
+
+  ResolveInfo::Desc getSymDesc(uint16_t shndx) const
+  {
+    if (shndx >= llvm::ELF::SHN_HEXAGON_SCOMMON &&
+        shndx <= llvm::ELF::SHN_HEXAGON_SCOMMON_8)
+      return ResolveInfo::Common;
+    return ResolveInfo::NoneDesc;
+  }
+
+  void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
+
+  void initTargetSymbols(IRBuilder& pBuilder, Module& pModule);
+
+  /// scanRelocation - determine the empty entries are needed or not and create
+  /// the empty entries if needed.
+  /// For Hexagon, following entries are check to create:
+  /// - GOT entry (for .got and .got.plt sections)
+  /// - PLT entry (for .plt section)
+  /// - dynamin relocation entries (for .rel.plt and .rel.dyn sections)
+  void scanRelocation(Relocation& pReloc,
+                      IRBuilder& pBuilder,
+                      Module& pModule,
+                      LDSection& pSection);
+
+  OutputRelocSection& getRelDyn();
+
+  const OutputRelocSection& getRelDyn() const;
+
+  OutputRelocSection& getRelPLT();
+
+  const OutputRelocSection& getRelPLT() const;
+
+  /// getTargetSectionOrder - compute the layout order of Hexagon target section
+  unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const;
+
+  /// finalizeTargetSymbols - finalize the symbol value
+  bool finalizeTargetSymbols();
+
+private:
+
+  /// getRelEntrySize - the size in BYTE of rel type relocation
+  size_t getRelEntrySize()
+  { return 8; }
+
+  /// getRelEntrySize - the size in BYTE of rela type relocation
+  size_t getRelaEntrySize()
+  { return 12; }
+
+  /// doCreateProgramHdrs - backend can implement this function to create the
+  /// target-dependent segments
+  void doCreateProgramHdrs(Module& pModule);
+
+private:
+  Relocator* m_pRelocator;
+  HexagonGOT* m_pGOT;
+  HexagonPLT* m_pPLT;
+  /// m_RelDyn - dynamic relocation table of .rel.dyn
+  OutputRelocSection* m_pRelDyn;
+  /// m_RelPLT - dynamic relocation table of .rel.plt
+  OutputRelocSection* m_pRelPLT;
+
+  HexagonELFDynamic* m_pDynamic;
+  LDSymbol* m_pGOTSymbol;
+  LDSymbol* m_pBSSEnd;
+};
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/Hexagon/HexagonMCLinker.cpp b/lib/Target/Hexagon/HexagonMCLinker.cpp
new file mode 100644
index 0000000..4f4f839
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonMCLinker.cpp
@@ -0,0 +1,53 @@
+//===- HexagonMCLinker.cpp ------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "Hexagon.h"
+#include "HexagonELFMCLinker.h"
+#include <mcld/Module.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <llvm/ADT/Triple.h>
+
+using namespace mcld;
+
+namespace mcld {
+
+/// createHexagonMCLinker - the help funtion to create corresponding
+/// HexagonMCLinker
+MCLinker* createHexagonMCLinker(const std::string &pTriple,
+                                LinkerConfig& pConfig,
+                                mcld::Module& pModule,
+                                MemoryArea& pOutput)
+{
+  Triple theTriple(pTriple);
+  if (theTriple.isOSDarwin()) {
+    assert(0 && "MachO linker has not supported yet");
+    return NULL;
+  }
+  if (theTriple.isOSWindows()) {
+    assert(0 && "COFF linker has not supported yet");
+    return NULL;
+  }
+
+  if (theTriple.isArch32Bit())
+    return new HexagonELFMCLinker(pConfig, pModule, pOutput);
+
+  assert(0 && "Hexagon_64 has not supported yet");
+  return NULL;
+}
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+// HexagonMCLinker
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeHexagonMCLinker() {
+  // Register the linker frontend
+  mcld::TargetRegistry::RegisterMCLinker(TheHexagonTarget,
+                                         createHexagonMCLinker);
+}
+
diff --git a/lib/Target/Hexagon/HexagonPLT.cpp b/lib/Target/Hexagon/HexagonPLT.cpp
new file mode 100644
index 0000000..ae39af2
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonPLT.cpp
@@ -0,0 +1,97 @@
+//===- HexagonPLT.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "HexagonPLT.h"
+
+#include <llvm/Support/ELF.h>
+#include <llvm/Support/Casting.h>
+
+#include <mcld/LD/LDSection.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/Support/MsgHandling.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// PLT entry data
+//===----------------------------------------------------------------------===//
+HexagonDynPLT0::HexagonDynPLT0(SectionData& pParent)
+  : PLT::Entry<sizeof(hexagon_dyn_plt0)>(pParent)
+{
+}
+
+HexagonExecPLT0::HexagonExecPLT0(SectionData& pParent)
+  : PLT::Entry<sizeof(hexagon_exec_plt0)>(pParent)
+{
+}
+
+//===----------------------------------------------------------------------===//
+// HexagonPLT
+//===----------------------------------------------------------------------===//
+HexagonPLT::HexagonPLT(LDSection& pSection,
+               HexagonGOT &pGOTPLT,
+               const LinkerConfig& pConfig)
+  : PLT(pSection),
+    m_GOT(pGOTPLT),
+    m_Config(pConfig)
+{
+  assert(LinkerConfig::DynObj == m_Config.codeGenType() ||
+         LinkerConfig::Exec   == m_Config.codeGenType() ||
+         LinkerConfig::Binary == m_Config.codeGenType());
+
+  if (LinkerConfig::DynObj == m_Config.codeGenType()) {
+    m_PLT0 = hexagon_dyn_plt0;
+    m_PLT0Size = sizeof (hexagon_dyn_plt0);
+    // create PLT0
+    new HexagonDynPLT0(*m_SectionData);
+  }
+  else {
+    m_PLT0 = hexagon_exec_plt0;
+    m_PLT0Size = sizeof (hexagon_exec_plt0);
+    // create PLT0
+    new HexagonExecPLT0(*m_SectionData);
+  }
+  m_Last = m_SectionData->begin();
+}
+
+HexagonPLT::~HexagonPLT()
+{
+}
+
+PLTEntryBase* HexagonPLT::getPLT0() const
+{
+  iterator first = m_SectionData->getFragmentList().begin();
+
+  assert(first != m_SectionData->getFragmentList().end() &&
+         "FragmentList is empty, getPLT0 failed!");
+
+  PLTEntryBase* plt0 = &(llvm::cast<PLTEntryBase>(*first));
+
+  return plt0;
+}
+
+void HexagonPLT::finalizeSectionSize()
+{
+  uint64_t size = 0;
+  // plt0 size
+  size = getPLT0()->size();
+
+  m_Section.setSize(size);
+
+  uint32_t offset = 0;
+  SectionData::iterator frag, fragEnd = m_SectionData->end();
+  for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) {
+    frag->setOffset(offset);
+    offset += frag->size();
+  }
+}
+
+void HexagonPLT::reserveEntry(size_t pNum)
+{
+}
+
diff --git a/lib/Target/Hexagon/HexagonPLT.h b/lib/Target/Hexagon/HexagonPLT.h
new file mode 100644
index 0000000..a5743d4
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonPLT.h
@@ -0,0 +1,84 @@
+//===- HexagonPLT.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TARGET_HEXAGON_PLT_H
+#define MCLD_TARGET_HEXAGON_PLT_H
+
+#include "HexagonGOT.h"
+#include <mcld/Target/PLT.h>
+
+namespace {
+
+const uint8_t hexagon_dyn_plt0[] = {
+  0
+};
+
+const uint8_t hexagon_exec_plt0[] = {
+  0
+};
+
+} // anonymous namespace
+
+namespace mcld {
+
+class GOTEntry;
+class LinkerConfig;
+
+//===----------------------------------------------------------------------===//
+// HexagonPLT Entry
+//===----------------------------------------------------------------------===//
+class HexagonDynPLT0 : public PLT::Entry<sizeof(hexagon_dyn_plt0)>
+{
+public:
+  HexagonDynPLT0(SectionData& pParent);
+};
+
+class HexagonExecPLT0 : public PLT::Entry<sizeof(hexagon_exec_plt0)>
+{
+public:
+  HexagonExecPLT0(SectionData& pParent);
+};
+
+//===----------------------------------------------------------------------===//
+// HexagonPLT
+//===----------------------------------------------------------------------===//
+/** \class HexagonPLT
+ *  \brief Hexagon Procedure Linkage Table
+ */
+class HexagonPLT : public PLT
+{
+public:
+  HexagonPLT(LDSection& pSection,
+             HexagonGOT& pGOTPLT,
+             const LinkerConfig& pConfig);
+  ~HexagonPLT();
+
+  // finalizeSectionSize - set LDSection size
+  void finalizeSectionSize();
+
+  void reserveEntry(size_t pNum = 1) ;
+
+private:
+  PLTEntryBase* getPLT0() const;
+
+private:
+  HexagonGOT& m_GOT;
+
+  // the last consumed entry.
+  SectionData::iterator m_Last;
+
+  const uint8_t *m_PLT0;
+  unsigned int m_PLT0Size;
+
+  const LinkerConfig& m_Config;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/Hexagon/HexagonRelocationFunctions.h b/lib/Target/Hexagon/HexagonRelocationFunctions.h
new file mode 100644
index 0000000..c854dcb
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonRelocationFunctions.h
@@ -0,0 +1,113 @@
+//===- HexagonRelocationFunction.h ----------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#define DECL_HEXAGON_APPLY_RELOC_FUNC(Name) \
+static HexagonRelocator::Result Name    (Relocation& pEntry, \
+                                     HexagonRelocator& pParent);
+
+#define DECL_HEXAGON_APPLY_RELOC_FUNCS \
+DECL_HEXAGON_APPLY_RELOC_FUNC(none)              \
+DECL_HEXAGON_APPLY_RELOC_FUNC(relocB22PCREL)     \
+DECL_HEXAGON_APPLY_RELOC_FUNC(relocB15PCREL)     \
+DECL_HEXAGON_APPLY_RELOC_FUNC(relocLO16)         \
+DECL_HEXAGON_APPLY_RELOC_FUNC(relocHI16)         \
+DECL_HEXAGON_APPLY_RELOC_FUNC(reloc32)           \
+DECL_HEXAGON_APPLY_RELOC_FUNC(reloc16)           \
+DECL_HEXAGON_APPLY_RELOC_FUNC(reloc8)            \
+DECL_HEXAGON_APPLY_RELOC_FUNC(relocB13PCREL)     \
+DECL_HEXAGON_APPLY_RELOC_FUNC(reloc32PCREL)      \
+DECL_HEXAGON_APPLY_RELOC_FUNC(unsupport)
+
+
+#define DECL_HEXAGON_APPLY_RELOC_FUNC_PTRS \
+  { &none,                0, "R_HEX_NONE"                        }, \
+  { &relocB22PCREL,       1, "R_HEX_B22_PCREL"                   }, \
+  { &relocB15PCREL,       2, "R_HEX_B15_PCREL"                   }, \
+  { &unsupport,           3, "R_HEX_B7_PCREL"                    }, \
+  { &relocLO16,           4, "R_HEX_LO16"                        }, \
+  { &relocHI16,           5, "R_HEX_HI16"                        }, \
+  { &reloc32,             6, "R_HEX_32"                          }, \
+  { &reloc16,             7, "R_HEX_16"                          }, \
+  { &reloc8,              8, "R_HEX_8"                           }, \
+  { &unsupport,           9, "R_HEX_GPREL16_0"                   }, \
+  { &unsupport,           10, "R_HEX_GPREL16_1"                  }, \
+  { &unsupport,           11, "R_HEX_GPREL16_2"                  }, \
+  { &unsupport,           12, "R_HEX_GPREL16_3"                  }, \
+  { &unsupport,           13, "R_HEX_HL16"                       }, \
+  { &relocB13PCREL,       14, "R_HEX_B13_PCREL"                  }, \
+  { &unsupport,           15, "R_HEX_B9_PCREL"                   }, \
+  { &unsupport,           16, "R_HEX_B32_PCREL_X"                }, \
+  { &unsupport,           17, "R_HEX_32_6_X"                     }, \
+  { &unsupport,           18, "R_HEX_B22_PCREL_X"                }, \
+  { &unsupport,           19, "R_HEX_B15_PCREL_X"                }, \
+  { &unsupport,           20, "R_HEX_B13_PCREL_X"                }, \
+  { &unsupport,           21, "R_HEX_B9_PCREL_X"                 }, \
+  { &unsupport,           22, "R_HEX_B7_PCREL_X"                 }, \
+  { &unsupport,           23, "R_HEX_16_X"                       }, \
+  { &unsupport,           24, "R_HEX_12_X"                       }, \
+  { &unsupport,           25, "R_HEX_11_X"                       }, \
+  { &unsupport,           26, "R_HEX_10_X"                       }, \
+  { &unsupport,           27, "R_HEX_9_X"                        }, \
+  { &unsupport,           28, "R_HEX_8_X"                        }, \
+  { &unsupport,           29, "R_HEX_7_X"                        }, \
+  { &unsupport,           30, "R_HEX_6_X"                        }, \
+  { &reloc32PCREL,        31, "R_HEX_32_PCREL"                   }, \
+  { &unsupport,           32, "R_HEX_COPY"                       }, \
+  { &unsupport,           33, "R_HEX_GLOB_DAT"                   }, \
+  { &unsupport,           34, "R_HEX_JMP_SLOT"                   }, \
+  { &unsupport,           35, "R_HEX_RELATIVE"                   }, \
+  { &unsupport,           36, "R_HEX_PLT_B22_PCREL"              }, \
+  { &unsupport,           37, "R_HEX_GOTREL_LO16"                }, \
+  { &unsupport,           38, "R_HEX_GOTREL_HI16"                }, \
+  { &unsupport,           39, "R_HEX_GOTREL_32"                  }, \
+  { &unsupport,           40, "R_HEX_GOT_LO16"                   }, \
+  { &unsupport,           41, "R_HEX_GOT_HI16"                   }, \
+  { &unsupport,           42, "R_HEX_GOT_32"                     }, \
+  { &unsupport,           43, "R_HEX_GOT_16"                     }, \
+  { &unsupport,           44, "R_HEX_DTPMOD_32"                  }, \
+  { &unsupport,           45, "R_HEX_DTPREL_LO16"                }, \
+  { &unsupport,           46, "R_HEX_DTPREL_HI16"                }, \
+  { &unsupport,           47, "R_HEX_DTPREL_32"                  }, \
+  { &unsupport,           48, "R_HEX_DTPREL_16"                  }, \
+  { &unsupport,           49, "R_HEX_GD_PLT_B22_PCREL"           }, \
+  { &unsupport,           50, "R_HEX_GD_GOT_LO16"                }, \
+  { &unsupport,           51, "R_HEX_GD_GOT_HI16"                }, \
+  { &unsupport,           52, "R_HEX_GD_GOT_32"                  }, \
+  { &unsupport,           53, "R_HEX_GD_GOT_16"                  }, \
+  { &unsupport,           54, "R_HEX_IE_LO16"                    }, \
+  { &unsupport,           55, "R_HEX_IE_HI16"                    }, \
+  { &unsupport,           56, "R_HEX_IE_32"                      }, \
+  { &unsupport,           57, "R_HEX_IE_GOT_LO16"                }, \
+  { &unsupport,           58, "R_HEX_IE_GOT_HI16"                }, \
+  { &unsupport,           59, "R_HEX_IE_GOT_32"                  }, \
+  { &unsupport,           60, "R_HEX_IE_GOT_16"                  }, \
+  { &unsupport,           61, "R_HEX_TPREL_LO16"                 }, \
+  { &unsupport,           62, "R_HEX_TPREL_HI16"                 }, \
+  { &unsupport,           63, "R_HEX_TPREL_32"                   }, \
+  { &unsupport,           64, "R_HEX_TPREL_16"                   }, \
+  { &unsupport,           65, "R_HEX_6_PCREL_X"                  }, \
+  { &unsupport,           66, "R_HEX_GOTREL_32_6_X"              }, \
+  { &unsupport,           67, "R_HEX_GOTREL_16_X"                }, \
+  { &unsupport,           68, "R_HEX_GOTREL_11_X"                }, \
+  { &unsupport,           69, "R_HEX_GOT_32_6_X"                 }, \
+  { &unsupport,           70, "R_HEX_GOT_16_X"                   }, \
+  { &unsupport,           71, "R_HEX_GOT_11_X"                   }, \
+  { &unsupport,           72, "R_HEX_DTPREL_32_6_X"              }, \
+  { &unsupport,           73, "R_HEX_DTPREL_16_X"                }, \
+  { &unsupport,           74, "R_HEX_DTPREL_11_X"                }, \
+  { &unsupport,           75, "R_HEX_GD_GOT_32_6_X"              }, \
+  { &unsupport,           76, "R_HEX_GD_GOT_16_X"                }, \
+  { &unsupport,           77, "R_HEX_GD_GOT_11_X"                }, \
+  { &unsupport,           78, "R_HEX_IE_32_6_X"                  }, \
+  { &unsupport,           79, "R_HEX_IE_16_X"                    }, \
+  { &unsupport,           80, "R_HEX_IE_GOT_32_6_X"              }, \
+  { &unsupport,           81, "R_HEX_IE_GOT_16_X"                }, \
+  { &unsupport,           82, "R_HEX_IE_GOT_11_X"                }, \
+  { &unsupport,           83, "R_HEX_TPREL_32_6_X"               }, \
+  { &unsupport,           84, "R_HEX_TPREL_16_X"                 }, \
+  { &unsupport,           85, "R_HEX_TPREL_11_X"                 }
diff --git a/lib/Target/Hexagon/HexagonRelocator.cpp b/lib/Target/Hexagon/HexagonRelocator.cpp
new file mode 100644
index 0000000..1bfa2b0
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonRelocator.cpp
@@ -0,0 +1,259 @@
+//===- HexagonRelocator.cpp -----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <llvm/ADT/Twine.h>
+#include <llvm/Support/DataTypes.h>
+#include <llvm/Support/ELF.h>
+#include <mcld/Support/MsgHandling.h>
+
+#include "HexagonRelocator.h"
+#include "HexagonRelocationFunctions.h"
+
+using namespace mcld;
+
+//===--------------------------------------------------------------------===//
+// Relocation Functions and Tables
+//===--------------------------------------------------------------------===//
+DECL_HEXAGON_APPLY_RELOC_FUNCS
+
+/// the prototype of applying function
+typedef Relocator::Result (*ApplyFunctionType)(Relocation& pReloc,
+                                               HexagonRelocator& pParent);
+
+// the table entry of applying functions
+struct ApplyFunctionTriple
+{
+  ApplyFunctionType func;
+  unsigned int type;
+  const char* name;
+};
+
+// declare the table of applying functions
+static const ApplyFunctionTriple ApplyFunctions[] = {
+  DECL_HEXAGON_APPLY_RELOC_FUNC_PTRS
+};
+
+//===--------------------------------------------------------------------===//
+// HexagonRelocator
+//===--------------------------------------------------------------------===//
+HexagonRelocator::HexagonRelocator(HexagonLDBackend& pParent)
+  : Relocator(),
+    m_Target(pParent) {
+}
+
+HexagonRelocator::~HexagonRelocator()
+{
+}
+
+Relocator::Result
+HexagonRelocator::applyRelocation(Relocation& pRelocation)
+{
+  Relocation::Type type = pRelocation.type();
+
+  if (type > 85) { // 86-255 relocs do not exists for Hexagon
+    return Relocator::Unknown;
+  }
+
+  // apply the relocation
+  return ApplyFunctions[type].func(pRelocation, *this);
+}
+
+const char* HexagonRelocator::getName(Relocation::Type pType) const
+{
+  return ApplyFunctions[pType].name;
+}
+
+Relocator::Size HexagonRelocator::getSize(Relocation::Type pType) const
+{
+  return 32;
+}
+//===--------------------------------------------------------------------===//
+// Relocation helper function
+//===--------------------------------------------------------------------===//
+template<typename T1, typename T2>
+T1 ApplyMask(T2 pMask, T1 pData) {
+  T1 result = 0;
+  size_t off = 0;
+
+  for (size_t bit = 0; bit != sizeof (T1) * 8; ++bit) {
+    const bool valBit = (pData >> off) & 1;
+    const bool maskBit = (pMask >> bit) & 1;
+    if (maskBit) {
+      result |= static_cast<T1>(valBit) << bit;
+      ++off;
+    }
+  }
+  return result;
+}
+
+//=========================================//
+// Each relocation function implementation //
+//=========================================//
+
+// R_HEX_NONE
+HexagonRelocator::Result none(Relocation& pReloc, HexagonRelocator& pParent)
+{
+  return HexagonRelocator::OK;
+}
+
+// R_HEX_B22_PCREL: Word32_B22 : 0x01ff3ffe  (S + A - P) >> 2 : Signed Verify
+HexagonRelocator::Result relocB22PCREL(Relocation& pReloc,
+                                       HexagonRelocator& pParent)
+{
+  HexagonRelocator::Address S = pReloc.symValue();
+  HexagonRelocator::DWord   A = pReloc.addend();
+  HexagonRelocator::DWord   P = pReloc.place();
+
+  int32_t result = (int32_t) ((S + A - P) >> 2);
+  int32_t range = 1 << 21;
+
+  if ( (result < range) && (result > -range)) {
+    pReloc.target() = pReloc.target() | ApplyMask(0x01ff3ffe, result);
+    return HexagonRelocator::OK;
+  }
+  return HexagonRelocator::Overflow;
+}
+
+// R_HEX_B15_PCREL: Word32_B15 : 0x00df20fe  (S + A - P) >> 2 : Signed Verify
+HexagonRelocator::Result relocB15PCREL(Relocation& pReloc,
+                                       HexagonRelocator& pParent)
+{
+  HexagonRelocator::Address S = pReloc.symValue();
+  HexagonRelocator::DWord   A = pReloc.addend();
+  HexagonRelocator::DWord   P = pReloc.place();
+
+  int32_t result = (int32_t) ((S + A - P) >> 2);
+  int32_t range = 1 << 14;
+  if ( (result < range) && (result > -range)) {
+    pReloc.target() = pReloc.target() | ApplyMask(0x00df20fe,result);
+    return HexagonRelocator::OK;
+  }
+  return HexagonRelocator::Overflow;
+}
+
+// R_HEX_B7_PCREL: Word32_B7 : 0x0001f18  (S + A - P) >> 2 : Signed Verify
+HexagonRelocator::Result relocB7PCREL(Relocation& pReloc,
+                                      HexagonRelocator& pParent)
+{
+  HexagonRelocator::Address S = pReloc.symValue();
+  HexagonRelocator::DWord   A = pReloc.addend();
+  HexagonRelocator::DWord   P = pReloc.place();
+
+  int32_t result = (int32_t) ((S + A - P) >> 2);
+  int32_t range = 1 << 6;
+  if ( (result < range) && (result > -range)) {
+    pReloc.target() = pReloc.target() | ApplyMask(0x00001f18, result);
+    return HexagonRelocator::OK;
+  }
+  return HexagonRelocator::Overflow;
+}
+
+// R_HEX_LO16: Word32_LO : 0x00c03fff  (S + A) : Unsigned Truncate
+HexagonRelocator::Result relocLO16(Relocation& pReloc,
+                                   HexagonRelocator& pParent)
+{
+  HexagonRelocator::Address S = pReloc.symValue();
+  HexagonRelocator::DWord   A = pReloc.addend();
+
+  uint32_t result = (uint32_t) (S + A);
+  pReloc.target() = pReloc.target() | ApplyMask(0x00c03fff, result);
+  return HexagonRelocator::OK;
+}
+
+// R_HEX_HI16: Word32_LO : 0x00c03fff  (S + A) >> 16 : Unsigned Truncate
+HexagonRelocator::Result relocHI16(Relocation& pReloc,
+                                   HexagonRelocator& pParent)
+{
+  HexagonRelocator::Address S = pReloc.symValue();
+  HexagonRelocator::DWord   A = pReloc.addend();
+
+  uint32_t result = (uint32_t) ((S + A) >> 16);
+  pReloc.target() = pReloc.target() | ApplyMask(0x00c03fff, result);
+  return HexagonRelocator::OK;
+}
+
+// R_HEX_32: Word32 : 0xffffffff : (S + A) : Unsigned Truncate
+HexagonRelocator::Result reloc32(Relocation& pReloc, HexagonRelocator& pParent)
+{
+  HexagonRelocator::DWord A = pReloc.addend();
+  HexagonRelocator::DWord S = pReloc.symValue();
+
+  uint32_t result = (uint32_t) (S + A);
+
+  pReloc.target() = result | pReloc.target();
+  return HexagonRelocator::OK;
+}
+
+// R_HEX_16: Word32 : 0xffff : (S + A) : Unsigned Truncate
+HexagonRelocator::Result reloc16(Relocation& pReloc, HexagonRelocator& pParent)
+{
+  HexagonRelocator::DWord A = pReloc.addend();
+  HexagonRelocator::DWord S = pReloc.symValue();
+
+  uint32_t result = (uint32_t) (S + A);
+  pReloc.target() = pReloc.target() | ApplyMask(0x0000ffff, result);
+
+  return HexagonRelocator::OK;
+}
+
+// R_HEX_8: Word32 : 0xff : (S + A) : Unsigned Truncate
+HexagonRelocator::Result reloc8(Relocation& pReloc, HexagonRelocator& pParent)
+{
+  HexagonRelocator::DWord A = pReloc.addend();
+  HexagonRelocator::DWord S = pReloc.symValue();
+
+  uint32_t result = (uint32_t) (S + A);
+  pReloc.target() = pReloc.target() | ApplyMask(0x000000ff, result);
+
+  return HexagonRelocator::OK;
+}
+
+// R_HEX_B13_PCREL : Word32_B13 : 0x00202ffe  (S + A - P)>>2 : Signed Verify
+HexagonRelocator::Result relocB13PCREL(Relocation& pReloc,
+                                       HexagonRelocator& pParent)
+{
+  HexagonRelocator::Address S = pReloc.symValue();
+  HexagonRelocator::DWord   A = pReloc.addend();
+  HexagonRelocator::DWord   P = pReloc.place();
+
+  int32_t result = ((S + A - P) >> 2);
+  int32_t range = 1L << 12;
+  if (result < range && result > -range) {
+    pReloc.target() = pReloc.target() | ApplyMask(0x00202ffe, result);
+    return HexagonRelocator::OK;
+  }
+  return HexagonRelocator::Overflow;
+}
+
+HexagonRelocator::Result unsupport(Relocation& pReloc,
+                                   HexagonRelocator& pParent)
+{
+  return HexagonRelocator::Unsupport;
+}
+
+
+
+// R_HEX_32_PCREL : Word32 : 0xffffffff  (S + A - P) : Signed Verify
+HexagonRelocator::Result reloc32PCREL(Relocation& pReloc,
+                                      HexagonRelocator& pParent)
+{
+  HexagonRelocator::Address S = pReloc.symValue();
+  HexagonRelocator::DWord   A = pReloc.addend();
+  HexagonRelocator::DWord   P = pReloc.place();
+
+  int64_t result = S + A - P;
+  int32_t range = 1 << 31;
+
+  if (result < range && result > -range)  {
+    pReloc.target() = pReloc.target() | ApplyMask(0xffffffff, result);
+    return HexagonRelocator::OK;
+  }
+
+  return HexagonRelocator::Overflow;
+}
diff --git a/lib/Target/Hexagon/HexagonRelocator.h b/lib/Target/Hexagon/HexagonRelocator.h
new file mode 100644
index 0000000..b7347ee
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonRelocator.h
@@ -0,0 +1,66 @@
+//===-  HexagonRelocator.h ------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef HEXAGON_RELOCATION_FACTORY_H
+#define HEXAGON_RELOCATION_FACTORY_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/LD/Relocator.h>
+#include <mcld/Target/GOT.h>
+#include <mcld/Target/PLT.h>
+#include <mcld/Target/SymbolEntryMap.h>
+#include "HexagonLDBackend.h"
+
+namespace mcld {
+
+class ResolveInfo;
+
+/** \class HexagonRelocator
+ *  \brief HexagonRelocator creates and destroys the Hexagon relocations.
+ *
+ */
+class HexagonRelocator : public Relocator
+{
+public:
+  typedef SymbolEntryMap<PLTEntryBase> SymPLTMap;
+  typedef SymbolEntryMap<HexagonGOTEntry> SymGOTMap;
+
+public:
+  HexagonRelocator(HexagonLDBackend& pParent);
+  ~HexagonRelocator();
+
+  Result applyRelocation(Relocation& pRelocation);
+
+  HexagonLDBackend& getTarget()
+  { return m_Target; }
+
+  const HexagonLDBackend& getTarget() const
+  { return m_Target; }
+
+  const char* getName(Relocation::Type pType) const;
+
+  Size getSize(Relocation::Type pType) const;
+
+  const SymPLTMap& getSymPLTMap() const { return m_SymPLTMap; }
+  SymPLTMap&       getSymPLTMap()       { return m_SymPLTMap; }
+
+  const SymGOTMap& getSymGOTMap() const { return m_SymGOTMap; }
+  SymGOTMap&       getSymGOTMap()       { return m_SymGOTMap; }
+
+private:
+  HexagonLDBackend& m_Target;
+  SymPLTMap m_SymPLTMap;
+  SymGOTMap m_SymGOTMap;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/Hexagon/HexagonTargetMachine.cpp b/lib/Target/Hexagon/HexagonTargetMachine.cpp
new file mode 100644
index 0000000..4e4f1c2
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonTargetMachine.cpp
@@ -0,0 +1,29 @@
+//===- HexagonTargetMachine.cpp -------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "HexagonTargetMachine.h"
+#include "Hexagon.h"
+#include <mcld/Target/TargetMachine.h>
+#include <mcld/Support/TargetRegistry.h>
+
+extern "C" void MCLDInitializeHexagonLDTarget() {
+  // Register createTargetMachine function pointer to mcld::Target
+  mcld::RegisterTargetMachine<mcld::HexagonTargetMachine>
+     X(mcld::TheHexagonTarget);
+}
+
+mcld::HexagonTargetMachine::HexagonTargetMachine(llvm::TargetMachine& pPM,
+                                                 const mcld::Target &pTarget,
+                                                 const std::string& pTriple)
+  : mcld::MCLDTargetMachine(pPM, pTarget, pTriple) {
+}
+
+mcld::HexagonTargetMachine::~HexagonTargetMachine()
+{
+}
+
diff --git a/lib/Target/Hexagon/HexagonTargetMachine.h b/lib/Target/Hexagon/HexagonTargetMachine.h
new file mode 100644
index 0000000..a374475
--- /dev/null
+++ b/lib/Target/Hexagon/HexagonTargetMachine.h
@@ -0,0 +1,28 @@
+//===- HexagonTargetMachine.h ---------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_HEXAGON_TARGET_MACHINE_H
+#define MCLD_HEXAGON_TARGET_MACHINE_H
+#include "Hexagon.h"
+#include <mcld/Target/TargetMachine.h>
+
+namespace mcld {
+
+class HexagonTargetMachine : public MCLDTargetMachine
+{
+public:
+  HexagonTargetMachine(llvm::TargetMachine &pTM,
+                       const mcld::Target &pTarget,
+                       const std::string &pTriple);
+
+  virtual ~HexagonTargetMachine();
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp b/lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp
new file mode 100644
index 0000000..0b113aa
--- /dev/null
+++ b/lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp
@@ -0,0 +1,22 @@
+//===- HexagonTargetInfo.cpp -----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Target/TargetMachine.h>
+#include <mcld/Support/TargetRegistry.h>
+
+namespace mcld {
+
+mcld::Target TheHexagonTarget;
+
+extern "C" void MCLDInitializeHexagonLDTargetInfo() {
+  // register into mcld::TargetRegistry
+  mcld::RegisterTarget X(TheHexagonTarget, "hexagon");
+}
+
+} // namespace of mcld
+
diff --git a/lib/Target/Mips/MipsGNUInfo.h b/lib/Target/Mips/MipsGNUInfo.h
index 9bbc548..a1d8cd2 100644
--- a/lib/Target/Mips/MipsGNUInfo.h
+++ b/lib/Target/Mips/MipsGNUInfo.h
@@ -17,10 +17,36 @@
 class MipsGNUInfo : public GNUInfo
 {
 public:
+  enum {
+    // The original o32 abi.
+    E_MIPS_ABI_O32    = 0x00001000,
+    // O32 extended to work on 64 bit architectures.
+    E_MIPS_ABI_O64    = 0x00002000,
+    // EABI in 32 bit mode.
+    E_MIPS_ABI_EABI32 = 0x00003000,
+    // EABI in 64 bit mode.
+    E_MIPS_ABI_EABI64 = 0x00004000
+  };
+
+public:
   MipsGNUInfo(const llvm::Triple& pTriple) : GNUInfo(pTriple) { }
 
   uint32_t machine() const { return llvm::ELF::EM_MIPS; }
 
+  uint64_t defaultTextSegmentAddr() const { return 0x80000; }
+
+  uint64_t flags() const
+  {
+    // TODO: (simon) The correct flag's set depend on command line
+    // arguments and flags from input .o files.
+    return llvm::ELF::EF_MIPS_ARCH_32R2 |
+           llvm::ELF::EF_MIPS_NOREORDER |
+           llvm::ELF::EF_MIPS_PIC |
+           llvm::ELF::EF_MIPS_CPIC |
+           E_MIPS_ABI_O32;
+  }
+
+  uint64_t abiPageSize() const { return 0x10000; }
 };
 
 } // namespace of mcld
diff --git a/lib/Target/Mips/MipsLDBackend.cpp b/lib/Target/Mips/MipsLDBackend.cpp
index 59b8d18..0806a2a 100644
--- a/lib/Target/Mips/MipsLDBackend.cpp
+++ b/lib/Target/Mips/MipsLDBackend.cpp
@@ -20,7 +20,6 @@
 #include <mcld/IRBuilder.h>
 #include <mcld/MC/Attribute.h>
 #include <mcld/Fragment/FillFragment.h>
-#include <mcld/Fragment/FragmentLinker.h>
 #include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/MsgHandling.h>
@@ -28,17 +27,6 @@
 #include <mcld/Target/OutputRelocSection.h>
 #include <mcld/Object/ObjectBuilder.h>
 
-enum {
-  // The original o32 abi.
-  E_MIPS_ABI_O32    = 0x00001000,
-  // O32 extended to work on 64 bit architectures.
-  E_MIPS_ABI_O64    = 0x00002000,
-  // EABI in 32 bit mode.
-  E_MIPS_ABI_EABI32 = 0x00003000,
-  // EABI in 64 bit mode.
-  E_MIPS_ABI_EABI64 = 0x00004000
-};
-
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
@@ -79,13 +67,12 @@
   }
 }
 
-void MipsGNULDBackend::initTargetSymbols(FragmentLinker& pLinker)
+void MipsGNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule)
 {
   // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
   // same name in input
-  m_pGOTSymbol = pLinker.defineSymbol<FragmentLinker::AsRefered, FragmentLinker::Resolve>(
+  m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
                    "_GLOBAL_OFFSET_TABLE_",
-                   false,
                    ResolveInfo::Object,
                    ResolveInfo::Define,
                    ResolveInfo::Local,
@@ -94,9 +81,8 @@
                    FragmentRef::Null(), // FragRef
                    ResolveInfo::Hidden);
 
-  m_pGpDispSymbol = pLinker.defineSymbol<FragmentLinker::AsRefered, FragmentLinker::Resolve>(
+  m_pGpDispSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
                    "_gp_disp",
-                   false,
                    ResolveInfo::Section,
                    ResolveInfo::Define,
                    ResolveInfo::Absolute,
@@ -110,11 +96,10 @@
   }
 }
 
-bool MipsGNULDBackend::initRelocator(const FragmentLinker& pLinker)
+bool MipsGNULDBackend::initRelocator()
 {
   if (NULL == m_pRelocator) {
     m_pRelocator = new MipsRelocator(*this);
-    m_pRelocator->setFragmentLinker(pLinker);
   }
   return true;
 }
@@ -126,9 +111,9 @@
 }
 
 void MipsGNULDBackend::scanRelocation(Relocation& pReloc,
-                                      FragmentLinker& pLinker,
+                                      IRBuilder& pBuilder,
                                       Module& pModule,
-                                      const LDSection& pSection)
+                                      LDSection& pSection)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
@@ -142,7 +127,8 @@
 
   pReloc.updateAddend();
 
-  if (0 == (pSection.flag() & llvm::ELF::SHF_ALLOC))
+  assert(NULL != pSection.getLink());
+  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC))
     return;
 
   // We test isLocal or if pInputSym is not a dynamic symbol
@@ -150,47 +136,22 @@
   // Don't put undef symbols into local entries.
   if ((rsym->isLocal() || !isDynamicSymbol(*rsym) ||
       !rsym->isDyn()) && !rsym->isUndef())
-    scanLocalReloc(pReloc, pLinker);
+    scanLocalReloc(pReloc, pBuilder, pSection);
   else
-    scanGlobalReloc(pReloc, pLinker);
+    scanGlobalReloc(pReloc, pBuilder, pSection);
 
   // check if we shoule issue undefined reference for the relocation target
   // symbol
   if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
     fatal(diag::undefined_reference) << rsym->name();
-
-  if ((rsym->reserved() & ReserveRel) != 0x0) {
-    // set hasTextRelSection if needed
-    checkAndSetHasTextRel(pSection);
-  }
 }
 
-uint64_t MipsGNULDBackend::flags() const
+void MipsGNULDBackend::doPreLayout(IRBuilder& pBuilder)
 {
-  // TODO: (simon) The correct flag's set depend on command line
-  // arguments and flags from input .o files.
-  return llvm::ELF::EF_MIPS_ARCH_32R2 |
-         llvm::ELF::EF_MIPS_NOREORDER |
-         llvm::ELF::EF_MIPS_PIC |
-         llvm::ELF::EF_MIPS_CPIC |
-         E_MIPS_ABI_O32;
-}
+  // initialize .dynamic data
+  if (!config().isCodeStatic() && NULL == m_pDynamic)
+    m_pDynamic = new MipsELFDynamic(*this, config());
 
-uint64_t MipsGNULDBackend::defaultTextSegmentAddr() const
-{
-  return 0x80000;
-}
-
-uint64_t MipsGNULDBackend::abiPageSize() const
-{
-  if (config().options().maxPageSize() > 0)
-    return config().options().maxPageSize();
-  else
-    return static_cast<uint64_t>(0x10000);
-}
-
-void MipsGNULDBackend::doPreLayout(FragmentLinker& pLinker)
-{
   // set .got size
   // when building shared object, the .got section is must.
   if (LinkerConfig::Object != config().codeGenType()) {
@@ -198,18 +159,21 @@
         m_pGOT->hasGOT1() ||
         NULL != m_pGOTSymbol) {
       m_pGOT->finalizeSectionSize();
-      defineGOTSymbol(pLinker);
+      defineGOTSymbol(pBuilder);
     }
 
     ELFFileFormat* file_format = getOutputFormat();
     // set .rel.dyn size
-    if (!m_pRelDyn->empty())
+    if (!m_pRelDyn->empty()) {
+      assert(!config().isCodeStatic() &&
+            "static linkage should not result in a dynamic relocation section");
       file_format->getRelDyn().setSize(
                                   m_pRelDyn->numOfRelocs() * getRelEntrySize());
+    }
   }
 }
-void MipsGNULDBackend::doPostLayout(Module& pModule,
-                                    FragmentLinker& pLinker)
+
+void MipsGNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder)
 {
 }
 
@@ -217,9 +181,7 @@
 /// Use co-variant return type to return its own dynamic section.
 MipsELFDynamic& MipsGNULDBackend::dynamic()
 {
-  if (NULL == m_pDynamic)
-    m_pDynamic = new MipsELFDynamic(*this, config());
-
+  assert(NULL != m_pDynamic);
   return *m_pDynamic;
 }
 
@@ -227,7 +189,7 @@
 /// Use co-variant return type to return its own dynamic section.
 const MipsELFDynamic& MipsGNULDBackend::dynamic() const
 {
-  assert( NULL != m_pDynamic);
+  assert(NULL != m_pDynamic);
   return *m_pDynamic;
 }
 
@@ -260,7 +222,7 @@
 /// In ELF executable files, regular name pools are .symtab, .strtab,
 /// .dynsym, .dynstr, .hash and .shstrtab.
 void
-MipsGNULDBackend::sizeNamePools(const Module& pModule, bool pIsStaticLink)
+MipsGNULDBackend::sizeNamePools(Module& pModule, bool pIsStaticLink)
 {
   // number of entries in symbol tables starts from 1 to hold the special entry
   // at index 0 (STN_UNDEF). See ELF Spec Book I, p1-21.
@@ -275,53 +237,37 @@
   size_t hash   = 0;
 
   // number of local symbol in the .dynsym
+  size_t symtab_local_cnt = 0;
   size_t dynsym_local_cnt = 0;
 
-  /// compute the size of .symtab, .dynsym and .strtab
-  /// @{
-  Module::const_sym_iterator symbol;
   const Module::SymbolTable& symbols = pModule.getSymbolTable();
-  size_t str_size = 0;
-  // compute the size of symbols in Local and File category
-  Module::const_sym_iterator symEnd = symbols.localEnd();
-  for (symbol = symbols.localBegin(); symbol != symEnd; ++symbol) {
-    str_size = (*symbol)->nameSize() + 1;
-    if (!pIsStaticLink && isDynamicSymbol(**symbol)) {
-      ++dynsym;
-    if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
-        dynstr += str_size;
-    }
+  Module::const_sym_iterator symbol, symEnd;
+  /// Compute the size of .symtab, .strtab, and symtab_local_cnt
+  /// @{
+  symEnd = symbols.end();
+  for (symbol = symbols.begin(); symbol != symEnd; ++symbol) {
     ++symtab;
-    if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
-      strtab += str_size;
+    if (ResolveInfo::Section != (*symbol)->type() ||
+        *symbol == m_pGpDispSymbol)
+      strtab += (*symbol)->nameSize() + 1;
   }
-  // compute the size of symbols in TLS category
-  symEnd = symbols.tlsEnd();
-  for (symbol = symbols.tlsBegin(); symbol != symEnd; ++symbol) {
-    str_size = (*symbol)->nameSize() + 1;
-    if (!pIsStaticLink) {
+  symtab_local_cnt = 1 + symbols.numOfFiles() + symbols.numOfLocals() +
+                     symbols.numOfLocalDyns();
+  /// @}
+
+  /// Compute the size of .dynsym, .dynstr, and dynsym_local_cnt
+  /// @{
+  if (!pIsStaticLink) {
+    symEnd = symbols.dynamicEnd();
+    for (symbol = symbols.localDynBegin(); symbol != symEnd; ++symbol) {
       ++dynsym;
-      if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
-        dynstr += str_size;
+      if (ResolveInfo::Section != (*symbol)->type() ||
+          *symbol == m_pGpDispSymbol)
+        dynstr += (*symbol)->nameSize() + 1;
     }
-    ++symtab;
-    if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
-      strtab += str_size;
+    dynsym_local_cnt = 1 + symbols.numOfLocalDyns();
   }
-  dynsym_local_cnt = dynsym;
-  // compute the size of the reset of symbols
-  symEnd = pModule.sym_end();
-  for (symbol = symbols.tlsEnd(); symbol != symEnd; ++symbol) {
-    str_size = (*symbol)->nameSize() + 1;
-    if (!pIsStaticLink && isDynamicSymbol(**symbol)) {
-      ++dynsym;
-    if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
-        dynstr += str_size;
-    }
-    ++symtab;
-    if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
-      strtab += str_size;
-  }
+  /// @}
 
   ELFFileFormat* file_format = getOutputFormat();
 
@@ -357,6 +303,15 @@
           }
         }
 
+        if (!config().options().getRpathList().empty()) {
+          dynamic().reserveNeedEntry();
+          GeneralOptions::const_rpath_iterator rpath,
+            rpathEnd = config().options().rpath_end();
+          for (rpath = config().options().rpath_begin();
+               rpath != rpathEnd; ++rpath)
+            dynstr += (*rpath).size() + 1;
+        }
+
         // compute .hash
         // Both Elf32_Word and Elf64_Word are 4 bytes
         hash = (2 + getHashBucketCount(dynsym, false) + dynsym) *
@@ -385,7 +340,7 @@
 
       // set .symtab sh_info to one greater than the symbol table
       // index of the last local symbol
-      file_format->getSymTab().setInfo(symbols.numOfLocals() + 1);
+      file_format->getSymTab().setInfo(symtab_local_cnt);
       break;
     }
     default: {
@@ -449,8 +404,7 @@
 ///
 /// the size of these tables should be computed before layout
 /// layout should computes the start offset of these tables
-void MipsGNULDBackend::emitDynNamePools(const Module& pModule,
-                                        MemoryArea& pOutput)
+void MipsGNULDBackend::emitDynNamePools(Module& pModule, MemoryArea& pOutput)
 {
   ELFFileFormat* file_format = getOutputFormat();
   if (!file_format->hasDynSymTab() ||
@@ -498,61 +452,14 @@
   size_t symtabIdx = 1;
   size_t strtabsize = 1;
 
-  // emit of .dynsym, and .dynstr except GOT entries
-  Module::const_sym_iterator symbol;
+  // emit .dynsym, and .dynstr (emit LocalDyn and Dynamic category) except GOT
+  // entries
   const Module::SymbolTable& symbols = pModule.getSymbolTable();
-  // emit symbol in File and Local category if it's dynamic symbol
-  Module::const_sym_iterator symEnd = symbols.localEnd();
-  for (symbol = symbols.localBegin(); symbol != symEnd; ++symbol) {
-    if (!isDynamicSymbol(**symbol))
-      continue;
-
+  Module::const_sym_iterator symbol, symEnd = symbols.dynamicEnd();
+  for (symbol = symbols.localDynBegin(); symbol != symEnd; ++symbol) {
     if (isGlobalGOTSymbol(**symbol))
       continue;
-
-    emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
-                   symtabIdx);
-
-    // maintain output's symbol and index map
-    entry = m_pSymIndexMap->insert(*symbol, sym_exist);
-    entry->setValue(symtabIdx);
-    // sum up counters
-    ++symtabIdx;
-    if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
-      strtabsize += (*symbol)->nameSize() + 1;
-  }
-
-  // emit symbols in TLS category, all symbols in TLS category shold be emitited
-  // directly, except GOT entries
-  symEnd = symbols.tlsEnd();
-  for (symbol = symbols.tlsBegin(); symbol != symEnd; ++symbol) {
-    if (isGlobalGOTSymbol(**symbol))
-      continue;
-
-    emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
-                   symtabIdx);
-
-    // maintain output's symbol and index map
-    entry = m_pSymIndexMap->insert(*symbol, sym_exist);
-    entry->setValue(symtabIdx);
-    // sum up counters
-    ++symtabIdx;
-    if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
-      strtabsize += (*symbol)->nameSize() + 1;
-  }
-
-  // emit the reset of the symbols if the symbol is dynamic symbol
-  symEnd = pModule.sym_end();
-  for (symbol = symbols.tlsEnd(); symbol != symEnd; ++symbol) {
-    if (!isDynamicSymbol(**symbol))
-      continue;
-
-    if (isGlobalGOTSymbol(**symbol))
-      continue;
-
-    emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
-                   symtabIdx);
-
+    emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize, symtabIdx);
     // maintain output's symbol and index map
     entry = m_pSymIndexMap->insert(*symbol, sym_exist);
     entry->setValue(symtabIdx);
@@ -566,22 +473,19 @@
   for (std::vector<LDSymbol*>::const_iterator symbol = m_GlobalGOTSyms.begin(),
        symbol_end = m_GlobalGOTSyms.end();
        symbol != symbol_end; ++symbol) {
-
     // Make sure this golbal GOT entry is a dynamic symbol.
     // If not, something is wrong earlier when putting this symbol into
     //  global GOT.
     if (!isDynamicSymbol(**symbol))
       fatal(diag::mips_got_symbol) << (*symbol)->name();
 
-    emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
-                   symtabIdx);
+    emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize, symtabIdx);
     // maintain output's symbol and index map
     entry = m_pSymIndexMap->insert(*symbol, sym_exist);
     entry->setValue(symtabIdx);
-
     // sum up counters
     ++symtabIdx;
-    if (ResolveInfo::Section != (*symbol)->type())
+    if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
       strtabsize += (*symbol)->nameSize() + 1;
   }
 
@@ -614,6 +518,19 @@
   } // for
 
   // emit soname
+
+  if (!config().options().getRpathList().empty()) {
+    (*dt_need)->setValue(llvm::ELF::DT_RPATH, strtabsize);
+    ++dt_need;
+    GeneralOptions::const_rpath_iterator rpath,
+      rpathEnd = config().options().rpath_end();
+    for (rpath = config().options().rpath_begin(); rpath != rpathEnd; ++rpath) {
+      memcpy((strtab + strtabsize), (*rpath).data(), (*rpath).size());
+      strtabsize += (*rpath).size();
+      strtab[strtabsize++] = (rpath + 1 == rpathEnd ? '\0' : ':');
+    }
+  }
+
   // initialize value of ELF .dynamic section
   if (LinkerConfig::DynObj == config().codeGenType())
     dynamic().applySoname(strtabsize);
@@ -689,7 +606,7 @@
 }
 
 /// finalizeSymbol - finalize the symbol value
-bool MipsGNULDBackend::finalizeTargetSymbols(FragmentLinker& pLinker)
+bool MipsGNULDBackend::finalizeTargetSymbols()
 {
   if (NULL != m_pGpDispSymbol)
     m_pGpDispSymbol->setValue(m_pGOT->addr() + 0x7FF0);
@@ -704,7 +621,8 @@
 {
   SymbolCategory& symbol_list = pModule.getSymbolTable();
 
-  if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
+  if (symbol_list.emptyCommons() && symbol_list.emptyFiles() &&
+      symbol_list.emptyLocals() && symbol_list.emptyLocalDyns())
     return true;
 
   SymbolCategory::iterator com_sym, com_end;
@@ -796,7 +714,8 @@
 }
 
 void MipsGNULDBackend::scanLocalReloc(Relocation& pReloc,
-                                      FragmentLinker& pLinker)
+                                      IRBuilder& pBuilder,
+                                      const LDSection& pSection)
 {
   ResolveInfo* rsym = pReloc.symInfo();
 
@@ -812,6 +731,7 @@
         // 2. Check this condition here.
         m_pRelDyn->reserveEntry();
         rsym->setReserved(rsym->reserved() | ReserveRel);
+        checkAndSetHasTextRel(*pSection.getLink());
 
         // Remeber this rsym is a local GOT entry (as if it needs an entry).
         // Actually we don't allocate an GOT entry.
@@ -846,6 +766,10 @@
       break;
     case llvm::ELF::R_MIPS_GOT16:
     case llvm::ELF::R_MIPS_CALL16:
+    case llvm::ELF::R_MIPS_GOT_HI16:
+    case llvm::ELF::R_MIPS_CALL_HI16:
+    case llvm::ELF::R_MIPS_GOT_LO16:
+    case llvm::ELF::R_MIPS_CALL_LO16:
       // For got16 section based relocations, we need to reserve got entries.
       if (rsym->type() == ResolveInfo::Section) {
         m_pGOT->reserveLocalEntry();
@@ -864,12 +788,7 @@
     case llvm::ELF::R_MIPS_GPREL32:
     case llvm::ELF::R_MIPS_GPREL16:
     case llvm::ELF::R_MIPS_LITERAL:
-      break;
     case llvm::ELF::R_MIPS_GOT_DISP:
-    case llvm::ELF::R_MIPS_GOT_HI16:
-    case llvm::ELF::R_MIPS_CALL_HI16:
-    case llvm::ELF::R_MIPS_GOT_LO16:
-    case llvm::ELF::R_MIPS_CALL_LO16:
       break;
     case llvm::ELF::R_MIPS_TLS_DTPMOD32:
     case llvm::ELF::R_MIPS_TLS_DTPREL32:
@@ -892,7 +811,8 @@
 }
 
 void MipsGNULDBackend::scanGlobalReloc(Relocation& pReloc,
-                                       FragmentLinker& pLinker)
+                                       IRBuilder& pBuilder,
+                                       const LDSection& pSection)
 {
   ResolveInfo* rsym = pReloc.symInfo();
 
@@ -913,9 +833,10 @@
     case llvm::ELF::R_MIPS_64:
     case llvm::ELF::R_MIPS_HI16:
     case llvm::ELF::R_MIPS_LO16:
-      if (symbolNeedsDynRel(pLinker, *rsym, false, true)) {
+      if (symbolNeedsDynRel(*rsym, false, true)) {
         m_pRelDyn->reserveEntry();
         rsym->setReserved(rsym->reserved() | ReserveRel);
+        checkAndSetHasTextRel(*pSection.getLink());
 
         // Remeber this rsym is a global GOT entry (as if it needs an entry).
         // Actually we don't allocate an GOT entry.
@@ -982,13 +903,12 @@
   }
 }
 
-void MipsGNULDBackend::defineGOTSymbol(FragmentLinker& pLinker)
+void MipsGNULDBackend::defineGOTSymbol(IRBuilder& pBuilder)
 {
   // define symbol _GLOBAL_OFFSET_TABLE_
   if ( m_pGOTSymbol != NULL ) {
-    pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Unresolve>(
+    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
                      "_GLOBAL_OFFSET_TABLE_",
-                     false,
                      ResolveInfo::Object,
                      ResolveInfo::Define,
                      ResolveInfo::Local,
@@ -998,9 +918,8 @@
                      ResolveInfo::Hidden);
   }
   else {
-    m_pGOTSymbol = pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Resolve>(
+    m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
                      "_GLOBAL_OFFSET_TABLE_",
-                     false,
                      ResolveInfo::Object,
                      ResolveInfo::Define,
                      ResolveInfo::Local,
@@ -1013,8 +932,7 @@
 
 /// doCreateProgramHdrs - backend can implement this function to create the
 /// target-dependent segments
-void MipsGNULDBackend::doCreateProgramHdrs(Module& pModule,
-                                           const FragmentLinker& pLinker)
+void MipsGNULDBackend::doCreateProgramHdrs(Module& pModule)
 {
   // TODO
 }
diff --git a/lib/Target/Mips/MipsLDBackend.h b/lib/Target/Mips/MipsLDBackend.h
index b9db410..1933751 100644
--- a/lib/Target/Mips/MipsLDBackend.h
+++ b/lib/Target/Mips/MipsLDBackend.h
@@ -15,7 +15,6 @@
 namespace mcld {
 
 class LinkerConfig;
-class FragmentLinker;
 class OutputRelocSection;
 class SectionMap;
 class MemoryArea;
@@ -43,10 +42,10 @@
   void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
 
   /// initTargetSymbols - initialize target dependent symbols in output.
-  void initTargetSymbols(FragmentLinker& pLinker);
+  void initTargetSymbols(IRBuilder& pBuilder, Module& pModule);
 
   /// initRelocator - create and initialize Relocator.
-  bool initRelocator(const FragmentLinker& pLinker);
+  bool initRelocator();
 
   /// getRelocator - return relocator.
   Relocator* getRelocator();
@@ -55,23 +54,15 @@
   /// create the empty entries if needed.
   /// For Mips, the GOT, GP, and dynamic relocation entries are check to create.
   void scanRelocation(Relocation& pReloc,
-                      FragmentLinker& pLinker,
+                      IRBuilder& pBuilder,
                       Module& pModule,
-                      const LDSection& pSection);
-
-  /// flags - the value of ElfXX_Ehdr::e_flags
-  uint64_t flags() const;
-
-  uint64_t defaultTextSegmentAddr() const;
-
-  /// abiPageSize - the abi page size of the target machine
-  uint64_t abiPageSize() const;
+                      LDSection& pSection);
 
   /// preLayout - Backend can do any needed modification before layout
-  void doPreLayout(FragmentLinker& pLinker);
+  void doPreLayout(IRBuilder& pBuilder);
 
-  /// postLayout -Backend can do any needed modification after layout
-  void doPostLayout(Module& pModule, FragmentLinker& pLinker);
+  /// postLayout - Backend can do any needed modification after layout
+  void doPostLayout(Module& pModule, IRBuilder& pBuilder);
 
   /// dynamic - the dynamic section of the target machine.
   /// Use co-variant return type to return its own dynamic section.
@@ -98,10 +89,10 @@
   uint64_t emitSectionData(const LDSection& pSection,
                            MemoryRegion& pRegion) const;
 
-  void sizeNamePools(const Module& pModule, bool pIsStaticLink);
+  void sizeNamePools(Module& pModule, bool pIsStaticLink);
 
   /// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
-  void emitDynNamePools(const Module& pModule, MemoryArea& pOut);
+  void emitDynNamePools(Module& pModule, MemoryArea& pOut);
 
 
   MipsGOT& getGOT();
@@ -114,18 +105,22 @@
   unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const;
 
   /// finalizeSymbol - finalize the symbol value
-  bool finalizeTargetSymbols(FragmentLinker& pLinker);
+  bool finalizeTargetSymbols();
 
   /// allocateCommonSymbols - allocate common symbols in the corresponding
   /// sections.
   bool allocateCommonSymbols(Module& pModule);
 
 private:
-  void scanLocalReloc(Relocation& pReloc, FragmentLinker& pLinker);
+  void scanLocalReloc(Relocation& pReloc,
+                      IRBuilder& pBuilder,
+                      const LDSection& pSection);
 
-  void scanGlobalReloc(Relocation& pReloc, FragmentLinker& pLinker);
+  void scanGlobalReloc(Relocation& pReloc,
+                       IRBuilder& pBuilder,
+                       const LDSection& pSection);
 
-  void defineGOTSymbol(FragmentLinker& pLinker);
+  void defineGOTSymbol(IRBuilder& pBuilder);
 
   /// emitSymbol32 - emit an ELF32 symbol, override parent's function
   void emitSymbol32(llvm::ELF::Elf32_Sym& pSym32,
@@ -144,8 +139,7 @@
 
   /// doCreateProgramHdrs - backend can implement this function to create the
   /// target-dependent segments
-  virtual void doCreateProgramHdrs(Module& pModule,
-                                   const FragmentLinker& pLinker);
+  void doCreateProgramHdrs(Module& pModule);
 
 private:
   Relocator* m_pRelocator;
diff --git a/lib/Target/Mips/MipsRelocationFunctions.h b/lib/Target/Mips/MipsRelocationFunctions.h
index aad708e..f1461a0 100644
--- a/lib/Target/Mips/MipsRelocationFunctions.h
+++ b/lib/Target/Mips/MipsRelocationFunctions.h
@@ -23,55 +23,55 @@
 DECL_MIPS_APPLY_RELOC_FUNC(gotlo16)
 
 #define DECL_MIPS_APPLY_RELOC_FUNC_PTRS \
-  { &none,     0, "R_MIPS_NONE"            }, \
-  { &none,     1, "R_MIPS_16"              }, \
-  { &abs32,    2, "R_MIPS_32"              }, \
-  { &none,     3, "R_MIPS_REL32"           }, \
-  { &none,     4, "R_MIPS_26"              }, \
-  { &hi16,     5, "R_MIPS_HI16"            }, \
-  { &lo16,     6, "R_MIPS_LO16"            }, \
-  { &none,     7, "R_MIPS_GPREL16"         }, \
-  { &none,     8, "R_MIPS_LITERAL"         }, \
-  { &got16,    9, "R_MIPS_GOT16"           }, \
-  { &none,    10, "R_MIPS_PC16"            }, \
-  { &call16,  11, "R_MIPS_CALL16"          }, \
-  { &gprel32, 12, "R_MIPS_GPREL32"         }, \
-  { &none,    13, "R_MIPS_UNUSED1"         }, \
-  { &none,    14, "R_MIPS_UNUSED2"         }, \
-  { &none,    15, "R_MIPS_UNUSED3"         }, \
-  { &none,    16, "R_MIPS_SHIFT5"          }, \
-  { &none,    17, "R_MIPS_SHIFT6"          }, \
-  { &none,    18, "R_MIPS_64"              }, \
-  { &none,    19, "R_MIPS_GOT_DISP"        }, \
-  { &none,    20, "R_MIPS_GOT_PAGE"        }, \
-  { &none,    21, "R_MIPS_GOT_OFST"        }, \
-  { &gothi16, 22, "R_MIPS_GOT_HI16"        }, \
-  { &gotlo16, 23, "R_MIPS_GOT_LO16"        }, \
-  { &none,    24, "R_MIPS_SUB"             }, \
-  { &none,    25, "R_MIPS_INSERT_A"        }, \
-  { &none,    26, "R_MIPS_INSERT_B"        }, \
-  { &none,    27, "R_MIPS_DELETE"          }, \
-  { &none,    28, "R_MIPS_HIGHER"          }, \
-  { &none,    29, "R_MIPS_HIGHEST"         }, \
-  { &gothi16, 30, "R_MIPS_CALL_HI16"       }, \
-  { &gotlo16, 31, "R_MIPS_CALL_LO16"       }, \
-  { &none,    32, "R_MIPS_SCN_DISP"        }, \
-  { &none,    33, "R_MIPS_REL16"           }, \
-  { &none,    34, "R_MIPS_ADD_IMMEDIATE"   }, \
-  { &none,    35, "R_MIPS_PJUMP"           }, \
-  { &none,    36, "R_MIPS_RELGOT"          }, \
-  { &none,    37, "R_MIPS_JALR"            }, \
-  { &none,    38, "R_MIPS_TLS_DTPMOD32"    }, \
-  { &none,    39, "R_MIPS_TLS_DTPREL32"    }, \
-  { &none,    40, "R_MIPS_TLS_DTPMOD64"    }, \
-  { &none,    41, "R_MIPS_TLS_DTPREL64"    }, \
-  { &none,    42, "R_MIPS_TLS_GD"          }, \
-  { &none,    43, "R_MIPS_TLS_LDM"         }, \
-  { &none,    44, "R_MIPS_TLS_DTPREL_HI16" }, \
-  { &none,    45, "R_MIPS_TLS_DTPREL_LO16" }, \
-  { &none,    46, "R_MIPS_TLS_GOTTPREL"    }, \
-  { &none,    47, "R_MIPS_TLS_TPREL32"     }, \
-  { &none,    48, "R_MIPS_TLS_TPREL64"     }, \
-  { &none,    49, "R_MIPS_TLS_TPREL_HI16"  }, \
-  { &none,    50, "R_MIPS_TLS_TPREL_LO16"  }, \
-  { &none,    51, "R_MIPS_GLOB_DAT"        }
+  { &none,     0, "R_MIPS_NONE",             0}, \
+  { &none,     1, "R_MIPS_16",              16}, \
+  { &abs32,    2, "R_MIPS_32",              32}, \
+  { &none,     3, "R_MIPS_REL32",           32}, \
+  { &none,     4, "R_MIPS_26",              64}, \
+  { &hi16,     5, "R_MIPS_HI16",            16}, \
+  { &lo16,     6, "R_MIPS_LO16",            16}, \
+  { &none,     7, "R_MIPS_GPREL16",         16}, \
+  { &none,     8, "R_MIPS_LITERAL",         16}, \
+  { &got16,    9, "R_MIPS_GOT16",           16}, \
+  { &none,    10, "R_MIPS_PC16",            16}, \
+  { &call16,  11, "R_MIPS_CALL16",          16}, \
+  { &gprel32, 12, "R_MIPS_GPREL32",         32}, \
+  { &none,    13, "R_MIPS_UNUSED1",          0}, \
+  { &none,    14, "R_MIPS_UNUSED2",          0}, \
+  { &none,    15, "R_MIPS_UNUSED3",          0}, \
+  { &none,    16, "R_MIPS_SHIFT5",          32}, \
+  { &none,    17, "R_MIPS_SHIFT6",          32}, \
+  { &none,    18, "R_MIPS_64",              64}, \
+  { &none,    19, "R_MIPS_GOT_DISP",        16}, \
+  { &none,    20, "R_MIPS_GOT_PAGE",        16}, \
+  { &none,    21, "R_MIPS_GOT_OFST",        16}, \
+  { &gothi16, 22, "R_MIPS_GOT_HI16",        16}, \
+  { &gotlo16, 23, "R_MIPS_GOT_LO16",        16}, \
+  { &none,    24, "R_MIPS_SUB",             64}, \
+  { &none,    25, "R_MIPS_INSERT_A",         0}, \
+  { &none,    26, "R_MIPS_INSERT_B",         0}, \
+  { &none,    27, "R_MIPS_DELETE",           0}, \
+  { &none,    28, "R_MIPS_HIGHER",          16}, \
+  { &none,    29, "R_MIPS_HIGHEST",         16}, \
+  { &gothi16, 30, "R_MIPS_CALL_HI16",       16}, \
+  { &gotlo16, 31, "R_MIPS_CALL_LO16",       16}, \
+  { &none,    32, "R_MIPS_SCN_DISP",        32}, \
+  { &none,    33, "R_MIPS_REL16",            0}, \
+  { &none,    34, "R_MIPS_ADD_IMMEDIATE",    0}, \
+  { &none,    35, "R_MIPS_PJUMP",            0}, \
+  { &none,    36, "R_MIPS_RELGOT",           0}, \
+  { &none,    37, "R_MIPS_JALR",            32}, \
+  { &none,    38, "R_MIPS_TLS_DTPMOD32",    32}, \
+  { &none,    39, "R_MIPS_TLS_DTPREL32",    32}, \
+  { &none,    40, "R_MIPS_TLS_DTPMOD64",     0}, \
+  { &none,    41, "R_MIPS_TLS_DTPREL64",     0}, \
+  { &none,    42, "R_MIPS_TLS_GD",          16}, \
+  { &none,    43, "R_MIPS_TLS_LDM",         16}, \
+  { &none,    44, "R_MIPS_TLS_DTPREL_HI16", 16}, \
+  { &none,    45, "R_MIPS_TLS_DTPREL_LO16", 16}, \
+  { &none,    46, "R_MIPS_TLS_GOTTPREL",    16}, \
+  { &none,    47, "R_MIPS_TLS_TPREL32",     32}, \
+  { &none,    48, "R_MIPS_TLS_TPREL64",      0}, \
+  { &none,    49, "R_MIPS_TLS_TPREL_HI16",  16}, \
+  { &none,    50, "R_MIPS_TLS_TPREL_LO16",  16}, \
+  { &none,    51, "R_MIPS_GLOB_DAT",         0}
diff --git a/lib/Target/Mips/MipsRelocator.cpp b/lib/Target/Mips/MipsRelocator.cpp
index ad5de22..ec551ae 100644
--- a/lib/Target/Mips/MipsRelocator.cpp
+++ b/lib/Target/Mips/MipsRelocator.cpp
@@ -9,7 +9,6 @@
 
 #include <llvm/ADT/Twine.h>
 #include <llvm/Support/ELF.h>
-#include <mcld/Fragment/FragmentLinker.h>
 #include <mcld/Support/MsgHandling.h>
 #include <mcld/Target/OutputRelocSection.h>
 
@@ -32,6 +31,7 @@
   ApplyFunctionType func;
   unsigned int type;
   const char* name;
+  unsigned int size;
 };
 
 // declare the table of applying functions
@@ -68,9 +68,13 @@
   return ApplyFunctions[pType].name;
 }
 
+Relocator::Size MipsRelocator::getSize(Relocation::Type pType) const
+{
+  return ApplyFunctions[pType].size;
+}
+
 //===----------------------------------------------------------------------===//
 // Relocation helper function
-
 //===----------------------------------------------------------------------===//
 static const char * const GP_DISP_NAME = "_gp_disp";
 
diff --git a/lib/Target/Mips/MipsRelocator.h b/lib/Target/Mips/MipsRelocator.h
index 836b7d2..fcb6af9 100644
--- a/lib/Target/Mips/MipsRelocator.h
+++ b/lib/Target/Mips/MipsRelocator.h
@@ -48,6 +48,8 @@
 
   const char* getName(Relocation::Type pType) const;
 
+  Size getSize(Relocation::Type pType) const;
+
   const SymGOTMap& getSymGOTMap() const { return m_SymGOTMap; }
   SymGOTMap&       getSymGOTMap()       { return m_SymGOTMap; }
 
diff --git a/lib/Target/OutputRelocSection.cpp b/lib/Target/OutputRelocSection.cpp
index 3c1a0ce..2584d13 100644
--- a/lib/Target/OutputRelocSection.cpp
+++ b/lib/Target/OutputRelocSection.cpp
@@ -71,7 +71,7 @@
 
 bool OutputRelocSection::addSymbolToDynSym(LDSymbol& pSymbol)
 {
-  m_Module.getSymbolTable().changeLocalToTLS(pSymbol);
+  m_Module.getSymbolTable().changeLocalToDynamic(pSymbol);
   return true;
 }
 
diff --git a/lib/Target/X86/TargetInfo/X86TargetInfo.cpp b/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
index 0985c02..3c02314 100644
--- a/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
+++ b/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
@@ -11,11 +11,13 @@
 
 namespace mcld {
 
-mcld::Target TheX86Target;
+mcld::Target TheX86_32Target;
+mcld::Target TheX86_64Target;
 
 extern "C" void MCLDInitializeX86LDTargetInfo() {
   // register into mcld::TargetRegistry
-  mcld::RegisterTarget X(TheX86Target, "x86");
+  mcld::RegisterTarget X(TheX86_32Target, "x86");
+  mcld::RegisterTarget Y(TheX86_64Target, "x86-64");
 }
 
 } // namespace of mcld
diff --git a/lib/Target/X86/X86.h b/lib/Target/X86/X86.h
index 2d07314..0f7d65d 100644
--- a/lib/Target/X86/X86.h
+++ b/lib/Target/X86/X86.h
@@ -14,7 +14,8 @@
 namespace mcld {
 class TargetLDBackend;
 
-extern mcld::Target TheX86Target;
+extern mcld::Target TheX86_32Target;
+extern mcld::Target TheX86_64Target;
 
 TargetLDBackend *createX86LDBackend(const llvm::Target&, const std::string&);
 
diff --git a/lib/Target/X86/X86Diagnostic.cpp b/lib/Target/X86/X86Diagnostic.cpp
index 7191596..9287ca7 100644
--- a/lib/Target/X86/X86Diagnostic.cpp
+++ b/lib/Target/X86/X86Diagnostic.cpp
@@ -33,6 +33,7 @@
 // InitializeX86Diagnostic
 extern "C" void MCLDInitializeX86DiagnosticLineInfo() {
   // Register the linker frontend
-  mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheX86Target, createX86DiagLineInfo);
+  mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheX86_32Target, createX86DiagLineInfo);
+  mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheX86_64Target, createX86DiagLineInfo);
 }
 
diff --git a/lib/Target/X86/X86Emulation.cpp b/lib/Target/X86/X86Emulation.cpp
index 9343583..753d7cc 100644
--- a/lib/Target/X86/X86Emulation.cpp
+++ b/lib/Target/X86/X86Emulation.cpp
@@ -20,7 +20,17 @@
 
   // set up bitclass and endian
   pConfig.targets().setEndian(TargetOptions::Little);
-  pConfig.targets().setBitClass(32);
+  unsigned int bitclass;
+  Triple::ArchType arch = pConfig.targets().triple().getArch();
+  assert (arch == Triple::x86 || arch == Triple::x86_64);
+  if (arch == Triple::x86 ||
+      pConfig.targets().triple().getEnvironment() == Triple::GNUX32) {
+    bitclass = 32;
+  }
+  else {
+    bitclass = 64;
+  }
+  pConfig.targets().setBitClass(bitclass);
 
   // set up target-dependent constraints of attributes
   pConfig.attribute().constraint().enableWholeArchive();
@@ -59,6 +69,7 @@
 //===----------------------------------------------------------------------===//
 extern "C" void MCLDInitializeX86Emulation() {
   // Register the emulation
-  mcld::TargetRegistry::RegisterEmulation(mcld::TheX86Target, mcld::emulateX86LD);
+  mcld::TargetRegistry::RegisterEmulation(mcld::TheX86_32Target, mcld::emulateX86LD);
+  mcld::TargetRegistry::RegisterEmulation(mcld::TheX86_64Target, mcld::emulateX86LD);
 }
 
diff --git a/lib/Target/X86/X86GNUInfo.h b/lib/Target/X86/X86GNUInfo.h
index af548f0..65b0451 100644
--- a/lib/Target/X86/X86GNUInfo.h
+++ b/lib/Target/X86/X86GNUInfo.h
@@ -14,13 +14,34 @@
 
 namespace mcld {
 
-class X86GNUInfo : public GNUInfo
+class X86_32GNUInfo : public GNUInfo
 {
 public:
-  X86GNUInfo(const llvm::Triple& pTriple) : GNUInfo(pTriple) { }
+  X86_32GNUInfo(const llvm::Triple& pTriple) : GNUInfo(pTriple) { }
 
   uint32_t machine() const { return llvm::ELF::EM_386; }
 
+  uint64_t defaultTextSegmentAddr() const { return 0x08048000; }
+
+  /// flags - the value of ElfXX_Ehdr::e_flags
+  /// FIXME
+  uint64_t flags() const { return 0x0; }
+
+};
+
+class X86_64GNUInfo : public GNUInfo
+{
+public:
+  X86_64GNUInfo(const llvm::Triple& pTriple) : GNUInfo(pTriple) { }
+
+  uint32_t machine() const { return llvm::ELF::EM_X86_64; }
+
+  uint64_t defaultTextSegmentAddr() const { return 0x400000; }
+
+  /// flags - the value of ElfXX_Ehdr::e_flags
+  /// FIXME
+  uint64_t flags() const { return 0x0; }
+
 };
 
 } // namespace of mcld
diff --git a/lib/Target/X86/X86GOT.cpp b/lib/Target/X86/X86GOT.cpp
index e734bb3..b77cfd3 100644
--- a/lib/Target/X86/X86GOT.cpp
+++ b/lib/Target/X86/X86GOT.cpp
@@ -16,33 +16,64 @@
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
-// X86GOT
+// X86_32GOT
 //===----------------------------------------------------------------------===//
-X86GOT::X86GOT(LDSection& pSection)
+X86_32GOT::X86_32GOT(LDSection& pSection)
   : GOT(pSection), m_pLast(NULL)
 {
 }
 
-X86GOT::~X86GOT()
+X86_32GOT::~X86_32GOT()
 {
 }
 
-void X86GOT::reserve(size_t pNum)
+void X86_32GOT::reserve(size_t pNum)
 {
   for (size_t i = 0; i < pNum; i++) {
-    new X86GOTEntry(0, m_SectionData);
+    new X86_32GOTEntry(0, m_SectionData);
   }
 }
 
-X86GOTEntry* X86GOT::consume()
+X86_32GOTEntry* X86_32GOT::consume()
 {
   if (NULL == m_pLast) {
     assert(!empty() && "Consume empty GOT entry!");
-    m_pLast = llvm::cast<X86GOTEntry>(&m_SectionData->front());
+    m_pLast = llvm::cast<X86_32GOTEntry>(&m_SectionData->front());
     return m_pLast;
   }
 
-  m_pLast = llvm::cast<X86GOTEntry>(m_pLast->getNextNode());
+  m_pLast = llvm::cast<X86_32GOTEntry>(m_pLast->getNextNode());
+  return m_pLast;
+}
+
+//===----------------------------------------------------------------------===//
+// X86_64GOT
+//===----------------------------------------------------------------------===//
+X86_64GOT::X86_64GOT(LDSection& pSection)
+  : GOT(pSection), m_pLast(NULL)
+{
+}
+
+X86_64GOT::~X86_64GOT()
+{
+}
+
+void X86_64GOT::reserve(size_t pNum)
+{
+  for (size_t i = 0; i < pNum; i++) {
+    new X86_64GOTEntry(0, m_SectionData);
+  }
+}
+
+X86_64GOTEntry* X86_64GOT::consume()
+{
+  if (NULL == m_pLast) {
+    assert(!empty() && "Consume empty GOT entry!");
+    m_pLast = llvm::cast<X86_64GOTEntry>(&m_SectionData->front());
+    return m_pLast;
+  }
+
+  m_pLast = llvm::cast<X86_64GOTEntry>(m_pLast->getNextNode());
   return m_pLast;
 }
 
diff --git a/lib/Target/X86/X86GOT.h b/lib/Target/X86/X86GOT.h
index 66967e1..df557f3 100644
--- a/lib/Target/X86/X86GOT.h
+++ b/lib/Target/X86/X86GOT.h
@@ -19,34 +19,64 @@
 class LDSection;
 class SectionData;
 
-/** \class X86GOTEntry
+/** \class X86_32GOTEntry
  *  \brief GOT Entry with size of 4 bytes
  */
-class X86GOTEntry : public GOT::Entry<4>
+class X86_32GOTEntry : public GOT::Entry<4>
 {
 public:
-  X86GOTEntry(uint64_t pContent, SectionData* pParent)
+  X86_32GOTEntry(uint64_t pContent, SectionData* pParent)
    : GOT::Entry<4>(pContent, pParent)
   {}
 };
 
-/** \class X86GOT
- *  \brief X86 Global Offset Table.
+/** \class X86_32GOT
+ *  \brief X86_32 Global Offset Table.
  */
 
-class X86GOT : public GOT
+class X86_32GOT : public GOT
 {
 public:
-  X86GOT(LDSection& pSection);
+  X86_32GOT(LDSection& pSection);
 
-  ~X86GOT();
+  ~X86_32GOT();
 
   void reserve(size_t pNum = 1);
 
-  X86GOTEntry* consume();
+  X86_32GOTEntry* consume();
 
 private:
-  X86GOTEntry* m_pLast; ///< the last consumed entry
+  X86_32GOTEntry* m_pLast; ///< the last consumed entry
+};
+
+/** \class X86_64GOTEntry
+ *  \brief GOT Entry with size of 8 bytes
+ */
+class X86_64GOTEntry : public GOT::Entry<8>
+{
+public:
+  X86_64GOTEntry(uint64_t pContent, SectionData* pParent)
+   : GOT::Entry<8>(pContent, pParent)
+  {}
+};
+
+/** \class X86_64GOT
+ *  \brief X86_64 Global Offset Table.
+ */
+
+class X86_64GOT : public GOT
+{
+public:
+  X86_64GOT(LDSection& pSection);
+
+  ~X86_64GOT();
+
+  void reserve(size_t pNum = 1);
+
+  X86_64GOTEntry* consume();
+
+private:
+  X86_64GOTEntry* m_pLast; ///< the last consumed entry
 };
 
 } // namespace of mcld
diff --git a/lib/Target/X86/X86GOTPLT.cpp b/lib/Target/X86/X86GOTPLT.cpp
index b72487e..961e0dc 100644
--- a/lib/Target/X86/X86GOTPLT.cpp
+++ b/lib/Target/X86/X86GOTPLT.cpp
@@ -18,10 +18,10 @@
 namespace mcld {
 
 //===----------------------------------------------------------------------===//
-// X86GOTPLT
+// X86_32GOTPLT
 //===----------------------------------------------------------------------===//
-X86GOTPLT::X86GOTPLT(LDSection& pSection)
-  : GOT(pSection), m_pLast(NULL)
+X86_32GOTPLT::X86_32GOTPLT(LDSection& pSection)
+  : X86_32GOT(pSection)
 {
   // Create GOT0 entries
   reserve(X86GOTPLT0Num);
@@ -32,41 +32,22 @@
   }
 }
 
-X86GOTPLT::~X86GOTPLT()
+X86_32GOTPLT::~X86_32GOTPLT()
 {
 }
 
-void X86GOTPLT::reserve(size_t pNum)
-{
-  for (size_t i = 0; i < pNum; i++) {
-    new X86GOTPLTEntry(0, m_SectionData);
-  }
-}
-
-X86GOTPLTEntry* X86GOTPLT::consume()
-{
-  if (NULL == m_pLast) {
-    assert(!empty() && "Consume empty GOT entry!");
-    m_pLast = llvm::cast<X86GOTPLTEntry>(&m_SectionData->front());
-    return m_pLast;
-  }
-
-  m_pLast = llvm::cast<X86GOTPLTEntry>(m_pLast->getNextNode());
-  return m_pLast;
-}
-
-bool X86GOTPLT::hasGOT1() const
+bool X86_32GOTPLT::hasGOT1() const
 {
   return (m_SectionData->size() > X86GOTPLT0Num);
 }
 
-void X86GOTPLT::applyGOT0(uint64_t pAddress)
+void X86_32GOTPLT::applyGOT0(uint64_t pAddress)
 {
-  llvm::cast<X86GOTPLTEntry>
+  llvm::cast<X86_32GOTEntry>
     (*(m_SectionData->getFragmentList().begin())).setValue(pAddress);
 }
 
-void X86GOTPLT::applyAllGOTPLT(const X86PLT& pPLT)
+void X86_32GOTPLT::applyAllGOTPLT(const X86PLT& pPLT)
 {
   iterator it = begin();
   // skip GOT0
@@ -75,7 +56,51 @@
   // address of corresponding plt entry
   uint64_t plt_addr = pPLT.addr() + pPLT.getPLT0Size();
   for (; it != end() ; ++it) {
-    llvm::cast<X86GOTPLTEntry>(*it).setValue(plt_addr + 6);
+    llvm::cast<X86_32GOTEntry>(*it).setValue(plt_addr + 6);
+    plt_addr += pPLT.getPLT1Size();
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// X86_64GOTPLT
+//===----------------------------------------------------------------------===//
+X86_64GOTPLT::X86_64GOTPLT(LDSection& pSection)
+  : X86_64GOT(pSection)
+{
+  // Create GOT0 entries
+  reserve(X86GOTPLT0Num);
+
+  // Skip GOT0 entries
+  for (size_t i = 0; i < X86GOTPLT0Num; ++i) {
+    consume();
+  }
+}
+
+X86_64GOTPLT::~X86_64GOTPLT()
+{
+}
+
+bool X86_64GOTPLT::hasGOT1() const
+{
+  return (m_SectionData->size() > X86GOTPLT0Num);
+}
+
+void X86_64GOTPLT::applyGOT0(uint64_t pAddress)
+{
+  llvm::cast<X86_64GOTEntry>
+    (*(m_SectionData->getFragmentList().begin())).setValue(pAddress);
+}
+
+void X86_64GOTPLT::applyAllGOTPLT(const X86PLT& pPLT)
+{
+  iterator it = begin();
+  // skip GOT0
+  for (size_t i = 0; i < X86GOTPLT0Num; ++i)
+    ++it;
+  // address of corresponding plt entry
+  uint64_t plt_addr = pPLT.addr() + pPLT.getPLT0Size();
+  for (; it != end() ; ++it) {
+    llvm::cast<X86_64GOTEntry>(*it).setValue(plt_addr + 6);
     plt_addr += pPLT.getPLT1Size();
   }
 }
diff --git a/lib/Target/X86/X86GOTPLT.h b/lib/Target/X86/X86GOTPLT.h
index f288fa4..8e13fac 100644
--- a/lib/Target/X86/X86GOTPLT.h
+++ b/lib/Target/X86/X86GOTPLT.h
@@ -14,7 +14,7 @@
 
 #include <llvm/ADT/DenseMap.h>
 
-#include <mcld/Target/GOT.h>
+#include "X86GOT.h"
 
 namespace mcld {
 
@@ -23,27 +23,15 @@
 
 const unsigned int X86GOTPLT0Num = 3;
 
-class X86GOTPLTEntry : public GOT::Entry<4>
-{
-public:
-  X86GOTPLTEntry(uint64_t pContent, SectionData* pParent)
-   : GOT::Entry<4>(pContent, pParent)
-  {}
-};
-
-/** \class X86GOTPLT
- *  \brief X86 .got.plt section.
+/** \class X86_32GOTPLT
+ *  \brief X86_32 .got.plt section.
  */
-class X86GOTPLT : public GOT
+class X86_32GOTPLT : public X86_32GOT
 {
 public:
-  X86GOTPLT(LDSection &pSection);
+  X86_32GOTPLT(LDSection &pSection);
 
-  ~X86GOTPLT();
-
-  void reserve(size_t pNum = 1);
-
-  X86GOTPLTEntry* consume();
+  ~X86_32GOTPLT();
 
   // hasGOT1 - return if this section has any GOT1 entry
   bool hasGOT1() const;
@@ -51,9 +39,24 @@
   void applyGOT0(uint64_t pAddress);
 
   void applyAllGOTPLT(const X86PLT& pPLT);
+};
 
-private:
-  X86GOTPLTEntry* m_pLast; ///< the last consumed entry
+/** \class X86_64GOTPLT
+ *  \brief X86_64 .got.plt section.
+ */
+class X86_64GOTPLT : public X86_64GOT
+{
+public:
+  X86_64GOTPLT(LDSection &pSection);
+
+  ~X86_64GOTPLT();
+
+  // hasGOT1 - return if this section has any GOT1 entry
+  bool hasGOT1() const;
+
+  void applyGOT0(uint64_t pAddress);
+
+  void applyAllGOTPLT(const X86PLT& pPLT);
 };
 
 } // namespace of mcld
diff --git a/lib/Target/X86/X86LDBackend.cpp b/lib/Target/X86/X86LDBackend.cpp
index a18fedb..e08120e 100644
--- a/lib/Target/X86/X86LDBackend.cpp
+++ b/lib/Target/X86/X86LDBackend.cpp
@@ -32,79 +32,83 @@
 //===----------------------------------------------------------------------===//
 // X86GNULDBackend
 //===----------------------------------------------------------------------===//
-X86GNULDBackend::X86GNULDBackend(const LinkerConfig& pConfig, X86GNUInfo* pInfo)
+X86GNULDBackend::X86GNULDBackend(const LinkerConfig& pConfig,
+				 GNUInfo* pInfo,
+				 Relocation::Type pCopyRel)
   : GNULDBackend(pConfig, pInfo),
     m_pRelocator(NULL),
-    m_pGOT(NULL),
     m_pPLT(NULL),
-    m_pGOTPLT(NULL),
     m_pRelDyn(NULL),
     m_pRelPLT(NULL),
     m_pDynamic(NULL),
-    m_pGOTSymbol(NULL) {
+    m_pGOTSymbol(NULL),
+    m_CopyRel(pCopyRel)
+{
+  Triple::ArchType arch = pConfig.targets().triple().getArch();
+  assert (arch == Triple::x86 || arch == Triple::x86_64);
+  if (arch == Triple::x86 ||
+      pConfig.targets().triple().getEnvironment() == Triple::GNUX32) {
+    m_RelEntrySize = 8;
+    m_RelaEntrySize = 12;
+    if (arch == Triple::x86)
+      m_PointerRel = llvm::ELF::R_386_32;
+    else
+      m_PointerRel = llvm::ELF::R_X86_64_32;
+  }
+  else {
+    m_RelEntrySize = 16;
+    m_RelaEntrySize = 24;
+    m_PointerRel = llvm::ELF::R_X86_64_64;
+  }
 }
 
 X86GNULDBackend::~X86GNULDBackend()
 {
   delete m_pRelocator;
-  delete m_pGOT;
   delete m_pPLT;
-  delete m_pGOTPLT;
   delete m_pRelDyn;
   delete m_pRelPLT;
   delete m_pDynamic;
 }
 
-bool X86GNULDBackend::initRelocator(const FragmentLinker& pLinker)
-{
-  if (NULL == m_pRelocator) {
-    m_pRelocator = new X86Relocator(*this);
-    m_pRelocator->setFragmentLinker(pLinker);
-  }
-  return true;
-}
-
 Relocator* X86GNULDBackend::getRelocator()
 {
   assert(NULL != m_pRelocator);
   return m_pRelocator;
 }
 
-void X86GNULDBackend::doPreLayout(FragmentLinker& pLinker)
+void X86GNULDBackend::doPreLayout(IRBuilder& pBuilder)
 {
-  // set .got.plt size
+  // initialize .dynamic data
+  if (!config().isCodeStatic() && NULL == m_pDynamic)
+    m_pDynamic = new X86ELFDynamic(*this, config());
+
+  // set .got.plt and .got sizes
   // when building shared object, the .got section is must
   if (LinkerConfig::Object != config().codeGenType()) {
-    if (LinkerConfig::DynObj == config().codeGenType() ||
-        m_pGOTPLT->hasGOT1() ||
-        NULL != m_pGOTSymbol) {
-      m_pGOTPLT->finalizeSectionSize();
-      defineGOTSymbol(pLinker);
-    }
-
-    // set .got size
-    if (!m_pGOT->empty())
-      m_pGOT->finalizeSectionSize();
+    setGOTSectionSize(pBuilder);
 
     // set .plt size
     if (m_pPLT->hasPLT1())
       m_pPLT->finalizeSectionSize();
 
-    ELFFileFormat* file_format = getOutputFormat();
-    // set .rel.dyn size
-    if (!m_pRelDyn->empty())
-      file_format->getRelDyn().setSize(
-                                  m_pRelDyn->numOfRelocs() * getRelEntrySize());
-
-    // set .rel.plt size
-    if (!m_pRelPLT->empty())
-      file_format->getRelPlt().setSize(
-                                  m_pRelPLT->numOfRelocs() * getRelEntrySize());
+    // set .rel.dyn/.rela.dyn size
+    if (!m_pRelDyn->empty()) {
+      assert(!config().isCodeStatic() &&
+            "static linkage should not result in a dynamic relocation section");
+      setRelDynSize();
+    }
+    // set .rel.plt/.rela.plt size
+    if (!m_pRelPLT->empty()) {
+      assert(!config().isCodeStatic() &&
+            "static linkage should not result in a dynamic relocation section");
+      setRelPLTSize();
+    }
   }
 }
 
 void X86GNULDBackend::doPostLayout(Module& pModule,
-                                   FragmentLinker& pLinker)
+                                   IRBuilder& pBuilder)
 {
 }
 
@@ -112,9 +116,7 @@
 /// Use co-variant return type to return its own dynamic section.
 X86ELFDynamic& X86GNULDBackend::dynamic()
 {
-  if (NULL == m_pDynamic)
-    m_pDynamic = new X86ELFDynamic(*this, config());
-
+  assert(NULL != m_pDynamic);
   return *m_pDynamic;
 }
 
@@ -122,35 +124,34 @@
 /// Use co-variant return type to return its own dynamic section.
 const X86ELFDynamic& X86GNULDBackend::dynamic() const
 {
-  assert( NULL != m_pDynamic);
+  assert(NULL != m_pDynamic);
   return *m_pDynamic;
 }
 
-void X86GNULDBackend::defineGOTSymbol(FragmentLinker& pLinker)
+void X86GNULDBackend::defineGOTSymbol(IRBuilder& pBuilder,
+				      Fragment& pFrag)
 {
   // define symbol _GLOBAL_OFFSET_TABLE_
   if (m_pGOTSymbol != NULL) {
-    pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Unresolve>(
+    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
                      "_GLOBAL_OFFSET_TABLE_",
-                     false,
                      ResolveInfo::Object,
                      ResolveInfo::Define,
                      ResolveInfo::Local,
                      0x0, // size
                      0x0, // value
-                     FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0),
+                     FragmentRef::Create(pFrag, 0x0),
                      ResolveInfo::Hidden);
   }
   else {
-    m_pGOTSymbol = pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Resolve>(
+    m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
                      "_GLOBAL_OFFSET_TABLE_",
-                     false,
                      ResolveInfo::Object,
                      ResolveInfo::Define,
                      ResolveInfo::Local,
                      0x0, // size
                      0x0, // value
-                     FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0),
+                     FragmentRef::Create(pFrag, 0x0),
                      ResolveInfo::Hidden);
   }
 }
@@ -158,7 +159,7 @@
 void X86GNULDBackend::addCopyReloc(ResolveInfo& pSym)
 {
   Relocation& rel_entry = *m_pRelDyn->consumeEntry();
-  rel_entry.setType(llvm::ELF::R_386_COPY);
+  rel_entry.setType(m_CopyRel);
   assert(pSym.outSymbol()->hasFragRef());
   rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
   rel_entry.setSymInfo(&pSym);
@@ -169,7 +170,7 @@
 /// section and all other reference to this symbol should refer to this
 /// copy.
 /// @note This is executed at `scan relocation' stage.
-LDSymbol& X86GNULDBackend::defineSymbolforCopyReloc(FragmentLinker& pLinker,
+LDSymbol& X86GNULDBackend::defineSymbolforCopyReloc(IRBuilder& pBuilder,
                                                     const ResolveInfo& pSym)
 {
   // get or create corresponding BSS LDSection
@@ -205,10 +206,8 @@
     binding = ResolveInfo::Global;
 
   // Define the copy symbol in the bss section and resolve it
-  LDSymbol* cpy_sym =
-           pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Resolve>(
+  LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
                       pSym.name(),
-                      false,
                       (ResolveInfo::Type)pSym.type(),
                       ResolveInfo::Define,
                       binding,
@@ -220,10 +219,204 @@
   return *cpy_sym;
 }
 
-void X86GNULDBackend::scanLocalReloc(Relocation& pReloc,
-                                     FragmentLinker& pLinker,
+void X86GNULDBackend::scanRelocation(Relocation& pReloc,
+                                     IRBuilder& pLinker,
                                      Module& pModule,
-                                     const LDSection& pSection)
+                                     LDSection& pSection)
+{
+  if (LinkerConfig::Object == config().codeGenType())
+    return;
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  assert(NULL != rsym &&
+         "ResolveInfo of relocation not set while scanRelocation");
+
+  pReloc.updateAddend();
+  assert(NULL != pSection.getLink());
+  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC))
+    return;
+
+  // Scan relocation type to determine if the GOT/PLT/Dynamic Relocation
+  // entries should be created.
+  if (rsym->isLocal()) // rsym is local
+    scanLocalReloc(pReloc, pLinker, pModule, pSection);
+  else // rsym is external
+    scanGlobalReloc(pReloc, pLinker, pModule, pSection);
+
+  // check if we should issue undefined reference for the relocation target
+  // symbol
+  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
+    fatal(diag::undefined_reference) << rsym->name();
+}
+
+uint64_t X86GNULDBackend::emitSectionData(const LDSection& pSection,
+                                          MemoryRegion& pRegion) const
+{
+  assert(pRegion.size() && "Size of MemoryRegion is zero!");
+
+  const ELFFileFormat* FileFormat = getOutputFormat();
+  assert(FileFormat &&
+         "ELFFileFormat is NULL in X86GNULDBackend::emitSectionData!");
+
+  unsigned int EntrySize = 0;
+  uint64_t RegionSize = 0;
+
+  if (&pSection == &(FileFormat->getPLT())) {
+    assert(m_pPLT && "emitSectionData failed, m_pPLT is NULL!");
+
+    unsigned char* buffer = pRegion.getBuffer();
+
+    m_pPLT->applyPLT0();
+    m_pPLT->applyPLT1();
+    X86PLT::iterator it = m_pPLT->begin();
+    unsigned int plt0_size = llvm::cast<PLTEntryBase>((*it)).size();
+
+    memcpy(buffer, llvm::cast<PLTEntryBase>((*it)).getValue(), plt0_size);
+    RegionSize += plt0_size;
+    ++it;
+
+    PLTEntryBase* plt1 = 0;
+    X86PLT::iterator ie = m_pPLT->end();
+    while (it != ie) {
+      plt1 = &(llvm::cast<PLTEntryBase>(*it));
+      EntrySize = plt1->size();
+      memcpy(buffer + RegionSize, plt1->getValue(), EntrySize);
+      RegionSize += EntrySize;
+      ++it;
+    }
+  }
+
+  else if (&pSection == &(FileFormat->getGOT())) {
+    RegionSize += emitGOTSectionData(pRegion);
+  }
+
+  else if (&pSection == &(FileFormat->getGOTPLT())) {
+    RegionSize += emitGOTPLTSectionData(pRegion, FileFormat);
+  }
+
+  else {
+    fatal(diag::unrecognized_output_sectoin)
+            << pSection.name()
+            << "mclinker@googlegroups.com";
+  }
+  return RegionSize;
+}
+
+X86PLT& X86GNULDBackend::getPLT()
+{
+  assert(NULL != m_pPLT && "PLT section not exist");
+  return *m_pPLT;
+}
+
+const X86PLT& X86GNULDBackend::getPLT() const
+{
+  assert(NULL != m_pPLT && "PLT section not exist");
+  return *m_pPLT;
+}
+
+OutputRelocSection& X86GNULDBackend::getRelDyn()
+{
+  assert(NULL != m_pRelDyn && ".rel.dyn/.rela.dyn section not exist");
+  return *m_pRelDyn;
+}
+
+const OutputRelocSection& X86GNULDBackend::getRelDyn() const
+{
+  assert(NULL != m_pRelDyn && ".rel.dyn/.rela.dyn section not exist");
+  return *m_pRelDyn;
+}
+
+OutputRelocSection& X86GNULDBackend::getRelPLT()
+{
+  assert(NULL != m_pRelPLT && ".rel.plt/.rela.plt section not exist");
+  return *m_pRelPLT;
+}
+
+const OutputRelocSection& X86GNULDBackend::getRelPLT() const
+{
+  assert(NULL != m_pRelPLT && ".rel.plt/.rela.plt section not exist");
+  return *m_pRelPLT;
+}
+
+unsigned int
+X86GNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
+{
+  const ELFFileFormat* file_format = getOutputFormat();
+
+  if (&pSectHdr == &file_format->getGOT()) {
+    if (config().options().hasNow())
+      return SHO_RELRO;
+    return SHO_RELRO_LAST;
+  }
+
+  if (&pSectHdr == &file_format->getGOTPLT()) {
+    if (config().options().hasNow())
+      return SHO_RELRO;
+    return SHO_NON_RELRO_FIRST;
+  }
+
+  if (&pSectHdr == &file_format->getPLT())
+    return SHO_PLT;
+
+  return SHO_UNDEFINED;
+}
+
+void X86GNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule)
+{
+  if (LinkerConfig::Object != config().codeGenType()) {
+    // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
+    // same name in input
+    m_pGOTSymbol =
+      pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                                                "_GLOBAL_OFFSET_TABLE_",
+                                                ResolveInfo::Object,
+                                                ResolveInfo::Define,
+                                                ResolveInfo::Local,
+                                                0x0,  // size
+                                                0x0,  // value
+                                                FragmentRef::Null(), // FragRef
+                                                ResolveInfo::Hidden);
+  }
+}
+
+/// finalizeSymbol - finalize the symbol value
+bool X86GNULDBackend::finalizeTargetSymbols()
+{
+  return true;
+}
+
+/// doCreateProgramHdrs - backend can implement this function to create the
+/// target-dependent segments
+void X86GNULDBackend::doCreateProgramHdrs(Module& pModule)
+{
+  // TODO
+}
+
+X86_32GNULDBackend::X86_32GNULDBackend(const LinkerConfig& pConfig,
+				       GNUInfo* pInfo)
+  : X86GNULDBackend(pConfig, pInfo, llvm::ELF::R_386_COPY),
+    m_pGOT (NULL),
+    m_pGOTPLT (NULL) {
+}
+
+X86_32GNULDBackend::~X86_32GNULDBackend()
+{
+  delete m_pGOT;
+  delete m_pGOTPLT;
+}
+
+bool X86_32GNULDBackend::initRelocator()
+{
+  if (NULL == m_pRelocator) {
+    m_pRelocator = new X86_32Relocator(*this);
+  }
+  return true;
+}
+
+void X86_32GNULDBackend::scanLocalReloc(Relocation& pReloc,
+					IRBuilder& pBuilder,
+					Module& pModule,
+					LDSection& pSection)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
@@ -236,10 +429,11 @@
       // If buiding PIC object (shared library or PIC executable),
       // a dynamic relocations with RELATIVE type to this location is needed.
       // Reserve an entry in .rel.dyn
-      if (pLinker.isOutputPIC()) {
+      if (config().isCodeIndep()) {
         m_pRelDyn->reserveEntry();
         // set Rel bit
         rsym->setReserved(rsym->reserved() | ReserveRel);
+        checkAndSetHasTextRel(*pSection.getLink());
       }
       return;
 
@@ -255,6 +449,13 @@
         return;
       // FIXME: check STT_GNU_IFUNC symbol
       m_pGOT->reserve();
+
+      // If the GOT is used in statically linked binaries,
+      // the GOT entry is enough and no relocation is needed.
+      if (config().isCodeStatic()) {
+        rsym->setReserved(rsym->reserved() | ReserveGOT);
+        return;
+      }
       // If building shared object or the symbol is undefined, a dynamic
       // relocation is needed to relocate this GOT entry. Reserve an
       // entry in .rel.dyn
@@ -316,6 +517,11 @@
       if (LinkerConfig::DynObj == config().codeGenType()) {
         m_pRelDyn->reserveEntry();
         rsym->setReserved(rsym->reserved() | ReserveRel);
+        checkAndSetHasTextRel(*pSection.getLink());
+      } else {
+        // for local sym, we can convert ie to le if not building shared object
+        convertTLSIEtoLE(pReloc, pSection);
+        return;
       }
       if (rsym->reserved() & GOTRel)
         return;
@@ -346,6 +552,7 @@
       if (LinkerConfig::DynObj == config().codeGenType()) {
         m_pRelDyn->reserveEntry();
         rsym->setReserved(rsym->reserved() | ReserveRel);
+        checkAndSetHasTextRel(*pSection.getLink());
         // the target symbol of the dynamic relocation is rsym, so we need to
         // emit it into .dynsym
         assert(NULL != rsym->outSymbol());
@@ -360,10 +567,10 @@
   } // end switch
 }
 
-void X86GNULDBackend::scanGlobalReloc(Relocation& pReloc,
-                                      FragmentLinker& pLinker,
-                                      Module& pModule,
-                                      const LDSection& pSection)
+void X86_32GNULDBackend::scanGlobalReloc(Relocation& pReloc,
+					 IRBuilder& pBuilder,
+					 Module& pModule,
+					 LDSection& pSection)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
@@ -374,7 +581,7 @@
     case llvm::ELF::R_386_8:
       // Absolute relocation type, symbol may needs PLT entry or
       // dynamic relocation entry
-      if (symbolNeedsPLT(pLinker, *rsym)) {
+      if (symbolNeedsPLT(*rsym)) {
         // create plt for this symbol if it does not have one
         if (!(rsym->reserved() & ReservePLT)){
           // Symbol needs PLT entry, we need to reserve a PLT entry
@@ -389,17 +596,17 @@
         }
       }
 
-      if (symbolNeedsDynRel(pLinker, *rsym, (rsym->reserved() & ReservePLT),
-                                                                       true)) {
+      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), true)) {
         // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
         m_pRelDyn->reserveEntry();
-        if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
-          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
+        if (symbolNeedsCopyReloc(pReloc, *rsym)) {
+          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
           addCopyReloc(*cpy_sym.resolveInfo());
         }
         else {
           // set Rel bit
           rsym->setReserved(rsym->reserved() | ReserveRel);
+          checkAndSetHasTextRel(pSection);
         }
       }
       return;
@@ -418,7 +625,7 @@
         return;
 
       // if the symbol's value can be decided at link time, then no need plt
-      if (symbolFinalValueIsKnown(pLinker, *rsym))
+      if (symbolFinalValueIsKnown(*rsym))
         return;
 
       // if symbol is defined in the ouput file and it's not
@@ -445,6 +652,13 @@
       if (rsym->reserved() & (ReserveGOT | GOTRel))
         return;
       m_pGOT->reserve();
+
+      // If the GOT is used in statically linked binaries,
+      // the GOT entry is enough and no relocation is needed.
+      if (config().isCodeStatic()) {
+        rsym->setReserved(rsym->reserved() | ReserveGOT);
+        return;
+      }
       // If building shared object or the symbol is undefined, a dynamic
       // relocation is needed to relocate this GOT entry. Reserve an
       // entry in .rel.dyn
@@ -463,8 +677,8 @@
     case llvm::ELF::R_386_PC16:
     case llvm::ELF::R_386_PC8:
 
-      if (symbolNeedsPLT(pLinker, *rsym) &&
-                               LinkerConfig::DynObj != config().codeGenType()) {
+      if (symbolNeedsPLT(*rsym) &&
+          LinkerConfig::DynObj != config().codeGenType()) {
         // create plt for this symbol if it does not have one
         if (!(rsym->reserved() & ReservePLT)){
           // Symbol needs PLT entry, we need to reserve a PLT entry
@@ -479,17 +693,17 @@
         }
       }
 
-      if (symbolNeedsDynRel(pLinker, *rsym, (rsym->reserved() & ReservePLT),
-                                                                      false)) {
+      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), false)) {
         // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
         m_pRelDyn->reserveEntry();
-        if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
-          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
+        if (symbolNeedsCopyReloc(pReloc, *rsym)) {
+          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
           addCopyReloc(*cpy_sym.resolveInfo());
         }
         else {
           // set Rel bit
           rsym->setReserved(rsym->reserved() | ReserveRel);
+          checkAndSetHasTextRel(pSection);
         }
       }
       return;
@@ -519,6 +733,13 @@
       if (LinkerConfig::DynObj == config().codeGenType()) {
         m_pRelDyn->reserveEntry();
         rsym->setReserved(rsym->reserved() | ReserveRel);
+        checkAndSetHasTextRel(*pSection.getLink());
+      } else {
+        // for global sym, we can convert ie to le if its final value is known
+        if (symbolFinalValueIsKnown(*rsym)) {
+          convertTLSIEtoLE(pReloc, pSection);
+          return;
+        }
       }
       if (rsym->reserved() & GOTRel)
         return;
@@ -547,6 +768,7 @@
       if (LinkerConfig::DynObj == config().codeGenType()) {
         m_pRelDyn->reserveEntry();
         rsym->setReserved(rsym->reserved() | ReserveRel);
+        checkAndSetHasTextRel(*pSection.getLink());
       }
       return;
 
@@ -558,171 +780,188 @@
   } // end switch
 }
 
-void X86GNULDBackend::scanRelocation(Relocation& pReloc,
-                                     FragmentLinker& pLinker,
-                                     Module& pModule,
-                                     const LDSection& pSection)
+void X86_32GNULDBackend::initTargetSections(Module& pModule,
+					    ObjectBuilder& pBuilder)
 {
-  if (LinkerConfig::Object == config().codeGenType())
-    return;
-  // rsym - The relocation target symbol
-  ResolveInfo* rsym = pReloc.symInfo();
-  assert(NULL != rsym &&
-         "ResolveInfo of relocation not set while scanRelocation");
+  if (LinkerConfig::Object != config().codeGenType()) {
+    ELFFileFormat* file_format = getOutputFormat();
+    // initialize .got
+    LDSection& got = file_format->getGOT();
+    m_pGOT = new X86_32GOT(got);
 
-  pReloc.updateAddend();
-  if (0 == (pSection.flag() & llvm::ELF::SHF_ALLOC))
-    return;
+    // initialize .got.plt
+    LDSection& gotplt = file_format->getGOTPLT();
+    m_pGOTPLT = new X86_32GOTPLT(gotplt);
 
-  // Scan relocation type to determine if the GOT/PLT/Dynamic Relocation
-  // entries should be created.
-  if (rsym->isLocal()) // rsym is local
-    scanLocalReloc(pReloc, pLinker, pModule, pSection);
-  else // rsym is external
-    scanGlobalReloc(pReloc, pLinker, pModule, pSection);
+    // initialize .plt
+    LDSection& plt = file_format->getPLT();
+    m_pPLT = new X86_32PLT(plt,
+			   *m_pGOTPLT,
+			   config());
 
-  // check if we shoule issue undefined reference for the relocation target
-  // symbol
-  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
-    fatal(diag::undefined_reference) << rsym->name();
+    // initialize .rel.plt
+    LDSection& relplt = file_format->getRelPlt();
+    relplt.setLink(&plt);
+    m_pRelPLT = new OutputRelocSection(pModule, relplt);
 
-  if ((rsym->reserved() & ReserveRel) != 0x0) {
-    // set hasTextRelSection if needed
-    checkAndSetHasTextRel(pSection);
+    // initialize .rel.dyn
+    LDSection& reldyn = file_format->getRelDyn();
+    m_pRelDyn = new OutputRelocSection(pModule, reldyn);
+
   }
 }
 
-uint64_t X86GNULDBackend::emitSectionData(const LDSection& pSection,
-                                          MemoryRegion& pRegion) const
+X86_32GOT& X86_32GNULDBackend::getGOT()
 {
-  assert(pRegion.size() && "Size of MemoryRegion is zero!");
+  assert(NULL != m_pGOT);
+  return *m_pGOT;
+}
 
-  const ELFFileFormat* FileFormat = getOutputFormat();
-  assert(FileFormat &&
-         "ELFFileFormat is NULL in X86GNULDBackend::emitSectionData!");
+const X86_32GOT& X86_32GNULDBackend::getGOT() const
+{
+  assert(NULL != m_pGOT);
+  return *m_pGOT;
+}
 
-  unsigned int EntrySize = 0;
+X86_32GOTPLT& X86_32GNULDBackend::getGOTPLT()
+{
+  assert(NULL != m_pGOTPLT);
+  return *m_pGOTPLT;
+}
+
+const X86_32GOTPLT& X86_32GNULDBackend::getGOTPLT() const
+{
+  assert(NULL != m_pGOTPLT);
+  return *m_pGOTPLT;
+}
+
+void X86_32GNULDBackend::setRelDynSize()
+{
+  ELFFileFormat* file_format = getOutputFormat();
+  file_format->getRelDyn().setSize
+    (m_pRelDyn->numOfRelocs() * getRelEntrySize());
+}
+
+void X86_32GNULDBackend::setRelPLTSize()
+{
+  ELFFileFormat* file_format = getOutputFormat();
+  file_format->getRelPlt().setSize
+    (m_pRelPLT->numOfRelocs() * getRelEntrySize());
+}
+
+void X86_32GNULDBackend::setGOTSectionSize(IRBuilder& pBuilder)
+{
+  // set .got.plt size
+  if (LinkerConfig::DynObj == config().codeGenType() ||
+      m_pGOTPLT->hasGOT1() ||
+      NULL != m_pGOTSymbol) {
+    m_pGOTPLT->finalizeSectionSize();
+    defineGOTSymbol(pBuilder, *(m_pGOTPLT->begin()));
+  }
+
+  // set .got size
+  if (!m_pGOT->empty())
+    m_pGOT->finalizeSectionSize();
+}
+
+uint64_t X86_32GNULDBackend::emitGOTSectionData(MemoryRegion& pRegion) const
+{
+  assert(m_pGOT && "emitGOTSectionData failed, m_pGOT is NULL!");
+
+  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
+
+  X86_32GOTEntry* got = 0;
+  unsigned int EntrySize = X86_32GOTEntry::EntrySize;
   uint64_t RegionSize = 0;
 
-  if (&pSection == &(FileFormat->getPLT())) {
-    assert(m_pPLT && "emitSectionData failed, m_pPLT is NULL!");
-
-    unsigned char* buffer = pRegion.getBuffer();
-
-    m_pPLT->applyPLT0();
-    m_pPLT->applyPLT1();
-    X86PLT::iterator it = m_pPLT->begin();
-    unsigned int plt0_size = llvm::cast<PLTEntryBase>((*it)).size();
-
-    memcpy(buffer, llvm::cast<PLTEntryBase>((*it)).getValue(), plt0_size);
-    RegionSize += plt0_size;
-    ++it;
-
-    PLTEntryBase* plt1 = 0;
-    X86PLT::iterator ie = m_pPLT->end();
-    while (it != ie) {
-      plt1 = &(llvm::cast<PLTEntryBase>(*it));
-      EntrySize = plt1->size();
-      memcpy(buffer + RegionSize, plt1->getValue(), EntrySize);
-      RegionSize += EntrySize;
-      ++it;
-    }
+  for (X86_32GOT::iterator it = m_pGOT->begin(),
+       ie = m_pGOT->end(); it != ie; ++it, ++buffer) {
+    got = &(llvm::cast<X86_32GOTEntry>((*it)));
+    *buffer = static_cast<uint32_t>(got->getValue());
+    RegionSize += EntrySize;
   }
 
-  else if (&pSection == &(FileFormat->getGOT())) {
-    assert(m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
-
-    uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
-
-    X86GOTEntry* got = 0;
-    EntrySize = X86GOTEntry::EntrySize;
-
-    for (X86GOT::iterator it = m_pGOT->begin(),
-         ie = m_pGOT->end(); it != ie; ++it, ++buffer) {
-      got = &(llvm::cast<X86GOTEntry>((*it)));
-      *buffer = static_cast<uint32_t>(got->getValue());
-      RegionSize += EntrySize;
-    }
-  }
-
-  else if (&pSection == &(FileFormat->getGOTPLT())) {
-    assert(m_pGOTPLT && "emitSectionData failed, m_pGOTPLT is NULL!");
-    m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr());
-    m_pGOTPLT->applyAllGOTPLT(*m_pPLT);
-
-    uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
-
-    X86GOTEntry* got = 0;
-    EntrySize = X86GOTPLTEntry::EntrySize;
-
-    for (X86GOTPLT::iterator it = m_pGOTPLT->begin(),
-         ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) {
-      got = &(llvm::cast<X86GOTEntry>((*it)));
-      *buffer = static_cast<uint32_t>(got->getValue());
-      RegionSize += EntrySize;
-    }
-  }
-
-  else {
-    fatal(diag::unrecognized_output_sectoin)
-            << pSection.name()
-            << "mclinker@googlegroups.com";
-  }
   return RegionSize;
 }
 
-X86GOT& X86GNULDBackend::getGOT()
+uint64_t X86_32GNULDBackend::emitGOTPLTSectionData(MemoryRegion& pRegion,
+						   const ELFFileFormat* FileFormat) const
 {
-  assert(NULL != m_pGOT);
-  return *m_pGOT;
+  assert(m_pGOTPLT && "emitGOTPLTSectionData failed, m_pGOTPLT is NULL!");
+  m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr());
+  m_pGOTPLT->applyAllGOTPLT(*m_pPLT);
+
+  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
+
+  X86_32GOTEntry* got = 0;
+  unsigned int EntrySize = X86_32GOTEntry::EntrySize;
+  uint64_t RegionSize = 0;
+
+  for (X86_32GOTPLT::iterator it = m_pGOTPLT->begin(),
+       ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) {
+    got = &(llvm::cast<X86_32GOTEntry>((*it)));
+    *buffer = static_cast<uint32_t>(got->getValue());
+    RegionSize += EntrySize;
+  }
+
+  return RegionSize;
 }
 
-const X86GOT& X86GNULDBackend::getGOT() const
+/// convert R_386_TLS_IE to R_386_TLS_LE
+void X86_32GNULDBackend::convertTLSIEtoLE(Relocation& pReloc,
+					  LDSection& pSection)
 {
-  assert(NULL != m_pGOT);
-  return *m_pGOT;
-}
+  assert(pReloc.type() == llvm::ELF::R_386_TLS_IE);
+  assert(NULL != pReloc.targetRef().frag());
 
-X86GOTPLT& X86GNULDBackend::getGOTPLT()
-{
-  assert(NULL != m_pGOTPLT);
-  return *m_pGOTPLT;
-}
+  // 1. create the fragment references and new relocs
+  uint64_t off = pReloc.targetRef().offset();
+  if (off >= 4)
+    off -= 4;
+  else
+    off = 0;
 
-const X86GOTPLT& X86GNULDBackend::getGOTPLT() const
-{
-  assert(NULL != m_pGOTPLT);
-  return *m_pGOTPLT;
-}
+  FragmentRef* fragref = FragmentRef::Create(*pReloc.targetRef().frag(), off);
+  // TODO: add symbols for R_386_TLS_OPT relocs
+  Relocation* reloc = Relocation::Create(X86_32Relocator::R_386_TLS_OPT,
+                                         *fragref,
+                                         0x0);
 
-X86PLT& X86GNULDBackend::getPLT()
-{
-  assert(NULL != m_pPLT && "PLT section not exist");
-  return *m_pPLT;
-}
+  // 2. modify the opcodes to the appropriate ones
+  uint8_t* op =  (reinterpret_cast<uint8_t*>(&reloc->target()));
+  off = pReloc.targetRef().offset() - reloc->targetRef().offset() - 1;
+  if (op[off] == 0xa1) {
+    op[off] = 0xb8;
+  } else {
+    switch (op[off - 1]) {
+      case 0x8b:
+        assert((op[off] & 0xc7) == 0x05);
+        op[off - 1] = 0xc7;
+        op[off]     = 0xc0 | ((op[off] >> 3) & 7);
+        break;
+      case 0x03:
+        assert((op[off] & 0xc7) == 0x05);
+        op[off - 1] = 0x81;
+        op[off]     = 0xc0 | ((op[off] >> 3) & 7);
+        break;
+      default:
+        assert(0);
+        break;
+    }
+  }
 
-const X86PLT& X86GNULDBackend::getPLT() const
-{
-  assert(NULL != m_pPLT && "PLT section not exist");
-  return *m_pPLT;
-}
+  // 3. insert the new relocs "BEFORE" the original reloc.
+  pSection.getRelocData()->getRelocationList().insert(
+    RelocData::iterator(pReloc), reloc);
 
-OutputRelocSection& X86GNULDBackend::getRelDyn()
-{
-  assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
-  return *m_pRelDyn;
-}
-
-const OutputRelocSection& X86GNULDBackend::getRelDyn() const
-{
-  assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
-  return *m_pRelDyn;
+  // 4. change the type of the original reloc
+  pReloc.setType(llvm::ELF::R_386_TLS_LE);
 }
 
 // Create a GOT entry for the TLS module index
-X86GOTEntry& X86GNULDBackend::getTLSModuleID()
+X86_32GOTEntry& X86_32GNULDBackend::getTLSModuleID()
 {
-  static X86GOTEntry* got_entry = NULL;
+  static X86_32GOTEntry* got_entry = NULL;
   if (NULL != got_entry)
     return *got_entry;
 
@@ -740,102 +979,358 @@
   return *got_entry;
 }
 
-OutputRelocSection& X86GNULDBackend::getRelPLT()
-{
-  assert(NULL != m_pRelPLT && ".rel.plt section not exist");
-  return *m_pRelPLT;
+X86_64GNULDBackend::X86_64GNULDBackend(const LinkerConfig& pConfig,
+				       GNUInfo* pInfo)
+  : X86GNULDBackend(pConfig, pInfo, llvm::ELF::R_X86_64_COPY),
+    m_pGOT (NULL),
+    m_pGOTPLT (NULL) {
 }
 
-const OutputRelocSection& X86GNULDBackend::getRelPLT() const
+X86_64GNULDBackend::~X86_64GNULDBackend()
 {
-  assert(NULL != m_pRelPLT && ".rel.plt section not exist");
-  return *m_pRelPLT;
+  delete m_pGOT;
+  delete m_pGOTPLT;
 }
 
-unsigned int
-X86GNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
+bool X86_64GNULDBackend::initRelocator()
 {
-  const ELFFileFormat* file_format = getOutputFormat();
-
-  if (&pSectHdr == &file_format->getGOT()) {
-    if (config().options().hasNow())
-      return SHO_RELRO;
-    return SHO_RELRO_LAST;
+  if (NULL == m_pRelocator) {
+    m_pRelocator = new X86_64Relocator(*this);
   }
-
-  if (&pSectHdr == &file_format->getGOTPLT()) {
-    if (config().options().hasNow())
-      return SHO_RELRO;
-    return SHO_NON_RELRO_FIRST;
-  }
-
-  if (&pSectHdr == &file_format->getPLT())
-    return SHO_PLT;
-
-  return SHO_UNDEFINED;
+  return true;
 }
 
-void X86GNULDBackend::initTargetSections(Module& pModule, ObjectBuilder& pBuilder)
+X86_64GOT& X86_64GNULDBackend::getGOT()
+{
+  assert(NULL != m_pGOT);
+  return *m_pGOT;
+}
+
+const X86_64GOT& X86_64GNULDBackend::getGOT() const
+{
+  assert(NULL != m_pGOT);
+  return *m_pGOT;
+}
+
+X86_64GOTPLT& X86_64GNULDBackend::getGOTPLT()
+{
+  assert(NULL != m_pGOTPLT);
+  return *m_pGOTPLT;
+}
+
+const X86_64GOTPLT& X86_64GNULDBackend::getGOTPLT() const
+{
+  assert(NULL != m_pGOTPLT);
+  return *m_pGOTPLT;
+}
+
+void X86_64GNULDBackend::setRelDynSize()
+{
+  ELFFileFormat* file_format = getOutputFormat();
+  file_format->getRelaDyn().setSize
+    (m_pRelDyn->numOfRelocs() * getRelaEntrySize());
+}
+
+void X86_64GNULDBackend::setRelPLTSize()
+{
+  ELFFileFormat* file_format = getOutputFormat();
+  file_format->getRelaPlt().setSize
+    (m_pRelPLT->numOfRelocs() * getRelaEntrySize());
+}
+
+void X86_64GNULDBackend::scanLocalReloc(Relocation& pReloc,
+					IRBuilder& pBuilder,
+					Module& pModule,
+					LDSection& pSection)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+
+  switch(pReloc.type()){
+    case llvm::ELF::R_X86_64_64:
+    case llvm::ELF::R_X86_64_32:
+    case llvm::ELF::R_X86_64_16:
+    case llvm::ELF::R_X86_64_8:
+    case llvm::ELF::R_X86_64_32S:
+      // If buiding PIC object (shared library or PIC executable),
+      // a dynamic relocations with RELATIVE type to this location is needed.
+      // Reserve an entry in .rela.dyn
+      if (config().isCodeIndep()) {
+        m_pRelDyn->reserveEntry();
+        // set Rel bit
+        rsym->setReserved(rsym->reserved() | ReserveRel);
+        checkAndSetHasTextRel(*pSection.getLink());
+      }
+      return;
+
+    case llvm::ELF::R_X86_64_PC32:
+    case llvm::ELF::R_X86_64_PC16:
+    case llvm::ELF::R_X86_64_PC8:
+      return;
+
+    case llvm::ELF::R_X86_64_GOTPCREL:
+      // Symbol needs GOT entry, reserve entry in .got
+      // return if we already create GOT for this symbol
+      if (rsym->reserved() & (ReserveGOT | GOTRel))
+        return;
+      m_pGOT->reserve();
+
+      // If the GOT is used in statically linked binaries,
+      // the GOT entry is enough and no relocation is needed.
+      if (config().isCodeStatic()) {
+        rsym->setReserved(rsym->reserved() | ReserveGOT);
+        return;
+      }
+      // If building shared object or the symbol is undefined, a dynamic
+      // relocation is needed to relocate this GOT entry. Reserve an
+      // entry in .rela.dyn
+      if (LinkerConfig::DynObj ==
+                   config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
+        m_pRelDyn->reserveEntry();
+        // set GOTRel bit
+        rsym->setReserved(rsym->reserved() | GOTRel);
+        return;
+      }
+      // set GOT bit
+      rsym->setReserved(rsym->reserved() | ReserveGOT);
+      return;
+
+    default:
+      fatal(diag::unsupported_relocation) << (int)pReloc.type()
+                                          << "mclinker@googlegroups.com";
+      break;
+  } // end switch
+}
+
+void X86_64GNULDBackend::scanGlobalReloc(Relocation& pReloc,
+					 IRBuilder& pBuilder,
+					 Module& pModule,
+					 LDSection& pSection)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+
+  switch(pReloc.type()) {
+    case llvm::ELF::R_X86_64_64:
+    case llvm::ELF::R_X86_64_32:
+    case llvm::ELF::R_X86_64_16:
+    case llvm::ELF::R_X86_64_8:
+    case llvm::ELF::R_X86_64_32S:
+      // Absolute relocation type, symbol may needs PLT entry or
+      // dynamic relocation entry
+      if (symbolNeedsPLT(*rsym)) {
+        // create plt for this symbol if it does not have one
+        if (!(rsym->reserved() & ReservePLT)){
+          // Symbol needs PLT entry, we need to reserve a PLT entry
+          // and the corresponding GOT and dynamic relocation entry
+          // in .got and .rela.plt. (GOT entry will be reserved simultaneously
+          // when calling X86PLT->reserveEntry())
+          m_pPLT->reserveEntry();
+          m_pGOTPLT->reserve();
+          m_pRelPLT->reserveEntry();
+          // set PLT bit
+          rsym->setReserved(rsym->reserved() | ReservePLT);
+        }
+      }
+
+      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), true)) {
+        // symbol needs dynamic relocation entry, reserve an entry in .rela.dyn
+        m_pRelDyn->reserveEntry();
+        if (symbolNeedsCopyReloc(pReloc, *rsym)) {
+          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
+          addCopyReloc(*cpy_sym.resolveInfo());
+        }
+        else {
+          // set Rel bit
+          rsym->setReserved(rsym->reserved() | ReserveRel);
+	  checkAndSetHasTextRel(*pSection.getLink());
+        }
+      }
+      return;
+
+    case llvm::ELF::R_X86_64_GOTPCREL:
+      // Symbol needs GOT entry, reserve entry in .got
+      // return if we already create GOT for this symbol
+      if (rsym->reserved() & (ReserveGOT | GOTRel))
+        return;
+      m_pGOT->reserve();
+
+      // If the GOT is used in statically linked binaries,
+      // the GOT entry is enough and no relocation is needed.
+      if (config().isCodeStatic()) {
+        rsym->setReserved(rsym->reserved() | ReserveGOT);
+        return;
+      }
+      // If building shared object or the symbol is undefined, a dynamic
+      // relocation is needed to relocate this GOT entry. Reserve an
+      // entry in .rela.dyn
+      if (LinkerConfig::DynObj ==
+                   config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
+        m_pRelDyn->reserveEntry();
+        // set GOTRel bit
+        rsym->setReserved(rsym->reserved() | GOTRel);
+        return;
+      }
+      // set GOT bit
+      rsym->setReserved(rsym->reserved() | ReserveGOT);
+      return;
+
+    case llvm::ELF::R_X86_64_PLT32:
+      // A PLT entry is needed when building shared library
+
+      // return if we already create plt for this symbol
+      if (rsym->reserved() & ReservePLT)
+        return;
+
+      // if the symbol's value can be decided at link time, then no need plt
+      if (symbolFinalValueIsKnown(*rsym))
+        return;
+
+      // if symbol is defined in the ouput file and it's not
+      // preemptible, no need plt
+      if (rsym->isDefine() && !rsym->isDyn() &&
+         !isSymbolPreemptible(*rsym)) {
+        return;
+      }
+
+      // Symbol needs PLT entry, we need to reserve a PLT entry
+      // and the corresponding GOT and dynamic relocation entry
+      // in .got and .rel.plt. (GOT entry will be reserved simultaneously
+      // when calling X86PLT->reserveEntry())
+      m_pPLT->reserveEntry();
+      m_pGOTPLT->reserve();
+      m_pRelPLT->reserveEntry();
+      // set PLT bit
+      rsym->setReserved(rsym->reserved() | ReservePLT);
+      return;
+
+    case llvm::ELF::R_X86_64_PC32:
+    case llvm::ELF::R_X86_64_PC16:
+    case llvm::ELF::R_X86_64_PC8:
+      if (symbolNeedsPLT(*rsym) &&
+          LinkerConfig::DynObj != config().codeGenType()) {
+        // create plt for this symbol if it does not have one
+        if (!(rsym->reserved() & ReservePLT)){
+          // Symbol needs PLT entry, we need to reserve a PLT entry
+          // and the corresponding GOT and dynamic relocation entry
+          // in .got and .rel.plt. (GOT entry will be reserved simultaneously
+          // when calling X86PLT->reserveEntry())
+          m_pPLT->reserveEntry();
+          m_pGOTPLT->reserve();
+          m_pRelPLT->reserveEntry();
+          // set PLT bit
+          rsym->setReserved(rsym->reserved() | ReservePLT);
+        }
+      }
+
+      // Only PC relative relocation against dynamic symbol needs a
+      // dynamic relocation.  Only dynamic copy relocation is allowed
+      // and PC relative relocation will be resolved to the local copy.
+      // All other dynamic relocations may lead to run-time relocation
+      // overflow.
+      if (isDynamicSymbol(*rsym) &&
+	  symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), false) &&
+	  symbolNeedsCopyReloc(pReloc, *rsym)) {
+        m_pRelDyn->reserveEntry();
+	LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
+	addCopyReloc(*cpy_sym.resolveInfo());
+      }
+      return;
+
+    default:
+      fatal(diag::unsupported_relocation) << (int)pReloc.type()
+                                          << "mclinker@googlegroups.com";
+      break;
+  } // end switch
+}
+
+void X86_64GNULDBackend::initTargetSections(Module& pModule,
+					    ObjectBuilder& pBuilder)
 {
   if (LinkerConfig::Object != config().codeGenType()) {
     ELFFileFormat* file_format = getOutputFormat();
     // initialize .got
     LDSection& got = file_format->getGOT();
-    m_pGOT = new X86GOT(got);
+    m_pGOT = new X86_64GOT(got);
 
     // initialize .got.plt
     LDSection& gotplt = file_format->getGOTPLT();
-    m_pGOTPLT = new X86GOTPLT(gotplt);
+    m_pGOTPLT = new X86_64GOTPLT(gotplt);
 
     // initialize .plt
     LDSection& plt = file_format->getPLT();
-    m_pPLT = new X86PLT(plt,
-                        *m_pGOTPLT,
-                        config());
+    m_pPLT = new X86_64PLT(plt,
+			   *m_pGOTPLT,
+			   config());
 
-    // initialize .rel.plt
-    LDSection& relplt = file_format->getRelPlt();
+    // initialize .rela.plt
+    LDSection& relplt = file_format->getRelaPlt();
     relplt.setLink(&plt);
     m_pRelPLT = new OutputRelocSection(pModule, relplt);
 
-    // initialize .rel.dyn
-    LDSection& reldyn = file_format->getRelDyn();
+    // initialize .rela.dyn
+    LDSection& reldyn = file_format->getRelaDyn();
     m_pRelDyn = new OutputRelocSection(pModule, reldyn);
 
   }
 }
 
-void X86GNULDBackend::initTargetSymbols(FragmentLinker& pLinker)
+void X86_64GNULDBackend::setGOTSectionSize(IRBuilder& pBuilder)
 {
-  if (LinkerConfig::Object != config().codeGenType()) {
-    // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
-    // same name in input
-    m_pGOTSymbol =
-      pLinker.defineSymbol<FragmentLinker::AsRefered,
-                           FragmentLinker::Resolve>("_GLOBAL_OFFSET_TABLE_",
-                                                    false,
-                                                    ResolveInfo::Object,
-                                                    ResolveInfo::Define,
-                                                    ResolveInfo::Local,
-                                                    0x0,  // size
-                                                    0x0,  // value
-                                                    FragmentRef::Null(), // FragRef
-                                                    ResolveInfo::Hidden);
+  // set .got.plt size
+  if (LinkerConfig::DynObj == config().codeGenType() ||
+      m_pGOTPLT->hasGOT1() ||
+      NULL != m_pGOTSymbol) {
+    m_pGOTPLT->finalizeSectionSize();
+    defineGOTSymbol(pBuilder, *(m_pGOTPLT->begin()));
   }
+
+  // set .got size
+  if (!m_pGOT->empty())
+    m_pGOT->finalizeSectionSize();
 }
 
-/// finalizeSymbol - finalize the symbol value
-bool X86GNULDBackend::finalizeTargetSymbols(FragmentLinker& pLinker)
+uint64_t X86_64GNULDBackend::emitGOTSectionData(MemoryRegion& pRegion) const
 {
-  return true;
+  assert(m_pGOT && "emitGOTSectionData failed, m_pGOT is NULL!");
+
+  uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.getBuffer());
+
+  X86_64GOTEntry* got = 0;
+  unsigned int EntrySize = X86_64GOTEntry::EntrySize;
+  uint64_t RegionSize = 0;
+
+  for (X86_64GOT::iterator it = m_pGOT->begin(),
+       ie = m_pGOT->end(); it != ie; ++it, ++buffer) {
+    got = &(llvm::cast<X86_64GOTEntry>((*it)));
+    *buffer = static_cast<uint64_t>(got->getValue());
+    RegionSize += EntrySize;
+  }
+
+  return RegionSize;
 }
 
-/// doCreateProgramHdrs - backend can implement this function to create the
-/// target-dependent segments
-void X86GNULDBackend::doCreateProgramHdrs(Module& pModule,
-                                          const FragmentLinker& pLinker)
+uint64_t X86_64GNULDBackend::emitGOTPLTSectionData(MemoryRegion& pRegion,
+						   const ELFFileFormat* FileFormat) const
 {
-  // TODO
+  assert(m_pGOTPLT && "emitGOTPLTSectionData failed, m_pGOTPLT is NULL!");
+  m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr());
+  m_pGOTPLT->applyAllGOTPLT(*m_pPLT);
+
+  uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.getBuffer());
+
+  X86_64GOTEntry* got = 0;
+  unsigned int EntrySize = X86_64GOTEntry::EntrySize;
+  uint64_t RegionSize = 0;
+
+  for (X86_64GOTPLT::iterator it = m_pGOTPLT->begin(),
+       ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) {
+    got = &(llvm::cast<X86_64GOTEntry>((*it)));
+    *buffer = static_cast<uint64_t>(got->getValue());
+    RegionSize += EntrySize;
+  }
+
+  return RegionSize;
 }
 
 namespace mcld {
@@ -862,7 +1357,13 @@
                                createX86COFFObjectWriter);
     **/
   }
-  return new X86GNULDBackend(pConfig, new X86GNUInfo(pConfig.targets().triple()));
+  Triple::ArchType arch = pConfig.targets().triple().getArch();
+  if (arch == Triple::x86)
+    return new X86_32GNULDBackend(pConfig,
+				  new X86_32GNUInfo(pConfig.targets().triple()));
+  assert (arch == Triple::x86_64);
+  return new X86_64GNULDBackend(pConfig,
+				new X86_64GNUInfo(pConfig.targets().triple()));
 }
 
 } // namespace of mcld
@@ -872,5 +1373,6 @@
 //===----------------------------------------------------------------------===//
 extern "C" void MCLDInitializeX86LDBackend() {
   // Register the linker backend
-  mcld::TargetRegistry::RegisterTargetLDBackend(TheX86Target, createX86LDBackend);
+  mcld::TargetRegistry::RegisterTargetLDBackend(TheX86_32Target, createX86LDBackend);
+  mcld::TargetRegistry::RegisterTargetLDBackend(TheX86_64Target, createX86LDBackend);
 }
diff --git a/lib/Target/X86/X86LDBackend.h b/lib/Target/X86/X86LDBackend.h
index 3f8a626..a008d00 100644
--- a/lib/Target/X86/X86LDBackend.h
+++ b/lib/Target/X86/X86LDBackend.h
@@ -20,7 +20,7 @@
 namespace mcld {
 
 class LinkerConfig;
-class X86GNUInfo;
+class GNUInfo;
 
 //===----------------------------------------------------------------------===//
 /// X86GNULDBackend - linker backend of X86 target of GNU ELF format
@@ -72,31 +72,23 @@
   };
 
 public:
-  X86GNULDBackend(const LinkerConfig& pConfig, X86GNUInfo* pInfo);
+  X86GNULDBackend(const LinkerConfig& pConfig,
+		  GNUInfo* pInfo,
+		  Relocation::Type pCopyRel);
 
   ~X86GNULDBackend();
 
   uint32_t machine() const;
 
-  X86GOT& getGOT();
-
-  const X86GOT& getGOT() const;
-
-  X86GOTPLT& getGOTPLT();
-
-  const X86GOTPLT& getGOTPLT() const;
-
   X86PLT& getPLT();
 
   const X86PLT& getPLT() const;
 
-  X86GOTEntry& getTLSModuleID();
-
   /// preLayout - Backend can do any needed modification before layout
-  void doPreLayout(FragmentLinker& pLinker);
+  void doPreLayout(IRBuilder& pBuilder);
 
   /// postLayout -Backend can do any needed modification after layout
-  void doPostLayout(Module& pModule, FragmentLinker& pLinker);
+  void doPostLayout(Module& pModule, IRBuilder& pBuilder);
 
   /// dynamic - the dynamic section of the target machine.
   /// Use co-variant return type to return its own dynamic section.
@@ -124,23 +116,15 @@
   uint64_t emitSectionData(const LDSection& pSection,
                            MemoryRegion& pRegion) const;
 
-  /// flags - the value of ElfXX_Ehdr::e_flags
-  /// FIXME
-  uint64_t flags() const
-  { return 0x0; }
-
-  uint64_t defaultTextSegmentAddr() const
-  { return 0x08048000; }
-
   /// initRelocator - create and initialize Relocator.
-  bool initRelocator(const FragmentLinker& pLinker);
+  virtual bool initRelocator() = 0;
 
   /// getRelocator - return relocator.
   Relocator* getRelocator();
 
-  void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
+  virtual void initTargetSections(Module& pModule, ObjectBuilder& pBuilder) = 0;
 
-  void initTargetSymbols(FragmentLinker& pLinker);
+  void initTargetSymbols(IRBuilder& pBuilder, Module& pModule);
 
   /// scanRelocation - determine the empty entries are needed or not and create
   /// the empty entries if needed.
@@ -149,9 +133,9 @@
   /// - PLT entry (for .plt section)
   /// - dynamin relocation entries (for .rel.plt and .rel.dyn sections)
   void scanRelocation(Relocation& pReloc,
-                      FragmentLinker& pLinker,
+                      IRBuilder& pBuilder,
                       Module& pModule,
-                      const LDSection& pSection);
+                      LDSection& pSection);
 
   OutputRelocSection& getRelDyn();
 
@@ -165,19 +149,24 @@
   unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const;
 
   /// finalizeTargetSymbols - finalize the symbol value
-  bool finalizeTargetSymbols(FragmentLinker& pLinker);
+  bool finalizeTargetSymbols();
+
+  /// getPointerRel - get pointer relocation type. 
+  Relocation::Type getPointerRel()
+  { return m_PointerRel; }
 
 private:
-  void scanLocalReloc(Relocation& pReloc,
-                      FragmentLinker& pLinker,
-                      Module& pModule,
-                      const LDSection& pSection);
+  virtual void scanLocalReloc(Relocation& pReloc,
+			      IRBuilder& pBuilder,
+			      Module& pModule,
+			      LDSection& pSection) = 0;
 
-  void scanGlobalReloc(Relocation& pReloc,
-                       FragmentLinker& pLinker,
-                       Module& pModule,
-                       const LDSection& pSection);
+  virtual void scanGlobalReloc(Relocation& pReloc,
+			       IRBuilder& pBuilder,
+			       Module& pModule,
+			       LDSection& pSection) = 0;
 
+protected:
   /// addCopyReloc - add a copy relocation into .rel.dyn for pSym
   /// @param pSym - A resolved copy symbol that defined in BSS section
   void addCopyReloc(ResolveInfo& pSym);
@@ -185,29 +174,38 @@
   /// defineSymbolforCopyReloc - allocate a space in BSS section and
   /// and force define the copy of pSym to BSS section
   /// @return the output LDSymbol of the copy symbol
-  LDSymbol& defineSymbolforCopyReloc(FragmentLinker& pLinker,
+  LDSymbol& defineSymbolforCopyReloc(IRBuilder& pLinker,
                                      const ResolveInfo& pSym);
 
-  void defineGOTSymbol(FragmentLinker& pLinker);
+  void defineGOTSymbol(IRBuilder& pBuilder, Fragment&);
 
+protected:
   /// getRelEntrySize - the size in BYTE of rel type relocation
   size_t getRelEntrySize()
-  { return 8; }
+  { return m_RelEntrySize; }
 
   /// getRelEntrySize - the size in BYTE of rela type relocation
   size_t getRelaEntrySize()
-  { return 12; }
-
-  /// doCreateProgramHdrs - backend can implement this function to create the
-  /// target-dependent segments
-  virtual void doCreateProgramHdrs(Module& pModule,
-                                   const FragmentLinker& pLinker);
+  { return m_RelaEntrySize; }
 
 private:
+  /// doCreateProgramHdrs - backend can implement this function to create the
+  /// target-dependent segments
+  void doCreateProgramHdrs(Module& pModule);
+
+  virtual void setGOTSectionSize(IRBuilder& pBuilder) = 0;
+
+  virtual uint64_t emitGOTSectionData(MemoryRegion& pRegion) const = 0;
+
+  virtual uint64_t emitGOTPLTSectionData(MemoryRegion& pRegion,
+					 const ELFFileFormat* FileFormat) const = 0;
+
+  virtual void setRelDynSize() = 0;
+  virtual void setRelPLTSize() = 0;
+
+protected:
   Relocator* m_pRelocator;
-  X86GOT* m_pGOT;
   X86PLT* m_pPLT;
-  X86GOTPLT* m_pGOTPLT;
   /// m_RelDyn - dynamic relocation table of .rel.dyn
   OutputRelocSection* m_pRelDyn;
   /// m_RelPLT - dynamic relocation table of .rel.plt
@@ -215,25 +213,119 @@
 
   X86ELFDynamic* m_pDynamic;
   LDSymbol* m_pGOTSymbol;
+
+  size_t m_RelEntrySize;
+  size_t m_RelaEntrySize;
+
+  Relocation::Type m_CopyRel;
+  Relocation::Type m_PointerRel;
 };
 
+//
 //===----------------------------------------------------------------------===//
-/// X86MachOLDBackend - linker backend of X86 target of MachO format
+/// X86_32GNULDBackend - linker backend of X86-32 target of GNU ELF format
 ///
-/**
-class X86MachOLDBackend : public DarwinX86LDBackend
+class X86_32GNULDBackend : public X86GNULDBackend
 {
 public:
-  X86MachOLDBackend();
-  ~X86MachOLDBackend();
+  X86_32GNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo);
+
+  ~X86_32GNULDBackend();
+
+  void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
+
+  X86_32GOT& getGOT();
+
+  const X86_32GOT& getGOT() const;
+
+  X86_32GOTPLT& getGOTPLT();
+
+  const X86_32GOTPLT& getGOTPLT() const;
+
+  X86_32GOTEntry& getTLSModuleID();
 
 private:
-  MCMachOTargetArchiveReader *createTargetArchiveReader() const;
-  MCMachOTargetObjectReader *createTargetObjectReader() const;
-  MCMachOTargetObjectWriter *createTargetObjectWriter() const;
+  void scanLocalReloc(Relocation& pReloc,
+                      IRBuilder& pBuilder,
+                      Module& pModule,
+                      LDSection& pSection);
 
+  void scanGlobalReloc(Relocation& pReloc,
+                       IRBuilder& pBuilder,
+                       Module& pModule,
+                       LDSection& pSection);
+
+  /// initRelocator - create and initialize Relocator.
+  bool initRelocator();
+
+  /// -----  tls optimization  ----- ///
+  /// convert R_386_TLS_IE to R_386_TLS_LE
+  void convertTLSIEtoLE(Relocation& pReloc, LDSection& pSection);
+
+  void setGOTSectionSize(IRBuilder& pBuilder);
+
+  uint64_t emitGOTSectionData(MemoryRegion& pRegion) const;
+
+  uint64_t emitGOTPLTSectionData(MemoryRegion& pRegion,
+				 const ELFFileFormat* FileFormat) const;
+
+  void setRelDynSize();
+  void setRelPLTSize();
+
+private:
+  X86_32GOT* m_pGOT;
+  X86_32GOTPLT* m_pGOTPLT;
 };
-**/
+
+//
+//===----------------------------------------------------------------------===//
+/// X86_64GNULDBackend - linker backend of X86-64 target of GNU ELF format
+///
+class X86_64GNULDBackend : public X86GNULDBackend
+{
+public:
+  X86_64GNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo);
+
+  ~X86_64GNULDBackend();
+
+  void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
+
+  X86_64GOT& getGOT();
+
+  const X86_64GOT& getGOT() const;
+
+  X86_64GOTPLT& getGOTPLT();
+
+  const X86_64GOTPLT& getGOTPLT() const;
+
+private:
+  void scanLocalReloc(Relocation& pReloc,
+                      IRBuilder& pBuilder,
+                      Module& pModule,
+                      LDSection& pSection);
+
+  void scanGlobalReloc(Relocation& pReloc,
+                       IRBuilder& pBuilder,
+                       Module& pModule,
+                       LDSection& pSection);
+
+  /// initRelocator - create and initialize Relocator.
+  bool initRelocator();
+
+  void setGOTSectionSize(IRBuilder& pBuilder);
+
+  uint64_t emitGOTSectionData(MemoryRegion& pRegion) const;
+
+  uint64_t emitGOTPLTSectionData(MemoryRegion& pRegion,
+				 const ELFFileFormat* FileFormat) const;
+
+  void setRelDynSize();
+  void setRelPLTSize();
+
+private:
+  X86_64GOT* m_pGOT;
+  X86_64GOTPLT* m_pGOTPLT;
+};
 } // namespace of mcld
 
 #endif
diff --git a/lib/Target/X86/X86MCLinker.cpp b/lib/Target/X86/X86MCLinker.cpp
index e55add3..bad20a9 100644
--- a/lib/Target/X86/X86MCLinker.cpp
+++ b/lib/Target/X86/X86MCLinker.cpp
@@ -34,11 +34,7 @@
     return NULL;
   }
 
-  if (theTriple.isArch32Bit())
-    return new X86ELFMCLinker(pConfig, pModule, pOutput);
-
-  assert(0 && "X86_64 has not supported yet");
-  return NULL;
+  return new X86ELFMCLinker(pConfig, pModule, pOutput);
 }
 
 } // namespace of mcld
@@ -48,6 +44,7 @@
 //===----------------------------------------------------------------------===//
 extern "C" void MCLDInitializeX86MCLinker() {
   // Register the linker frontend
-  mcld::TargetRegistry::RegisterMCLinker(TheX86Target, createX86MCLinker);
+  mcld::TargetRegistry::RegisterMCLinker(TheX86_32Target, createX86MCLinker);
+  mcld::TargetRegistry::RegisterMCLinker(TheX86_64Target, createX86MCLinker);
 }
 
diff --git a/lib/Target/X86/X86PLT.cpp b/lib/Target/X86/X86PLT.cpp
index 25eaab9..669a047 100644
--- a/lib/Target/X86/X86PLT.cpp
+++ b/lib/Target/X86/X86PLT.cpp
@@ -21,23 +21,33 @@
 //===----------------------------------------------------------------------===//
 // PLT entry data
 //===----------------------------------------------------------------------===//
-X86DynPLT0::X86DynPLT0(SectionData& pParent)
-  : PLT::Entry<sizeof(x86_dyn_plt0)>(pParent)
+X86_32DynPLT0::X86_32DynPLT0(SectionData& pParent)
+  : PLT::Entry<sizeof(x86_32_dyn_plt0)>(pParent)
 {
 }
 
-X86DynPLT1::X86DynPLT1(SectionData& pParent)
-  : PLT::Entry<sizeof(x86_dyn_plt1)>(pParent)
+X86_32DynPLT1::X86_32DynPLT1(SectionData& pParent)
+  : PLT::Entry<sizeof(x86_32_dyn_plt1)>(pParent)
 {
 }
 
-X86ExecPLT0::X86ExecPLT0(SectionData& pParent)
-  : PLT::Entry<sizeof(x86_exec_plt0)>(pParent)
+X86_32ExecPLT0::X86_32ExecPLT0(SectionData& pParent)
+  : PLT::Entry<sizeof(x86_32_exec_plt0)>(pParent)
 {
 }
 
-X86ExecPLT1::X86ExecPLT1(SectionData& pParent)
-  : PLT::Entry<sizeof(x86_exec_plt1)>(pParent)
+X86_32ExecPLT1::X86_32ExecPLT1(SectionData& pParent)
+  : PLT::Entry<sizeof(x86_32_exec_plt1)>(pParent)
+{
+}
+
+X86_64PLT0::X86_64PLT0(SectionData& pParent)
+  : PLT::Entry<sizeof(x86_64_plt0)>(pParent)
+{
+}
+
+X86_64PLT1::X86_64PLT1(SectionData& pParent)
+  : PLT::Entry<sizeof(x86_64_plt1)>(pParent)
 {
 }
 
@@ -45,31 +55,42 @@
 // X86PLT
 //===----------------------------------------------------------------------===//
 X86PLT::X86PLT(LDSection& pSection,
-               X86GOTPLT &pGOTPLT,
-               const LinkerConfig& pConfig)
+	       const LinkerConfig& pConfig,
+	       int got_size)
   : PLT(pSection),
-    m_GOTPLT(pGOTPLT),
     m_Config(pConfig)
 {
   assert(LinkerConfig::DynObj == m_Config.codeGenType() ||
          LinkerConfig::Exec   == m_Config.codeGenType() ||
          LinkerConfig::Binary == m_Config.codeGenType());
 
-  if (LinkerConfig::DynObj == m_Config.codeGenType()) {
-    m_PLT0 = x86_dyn_plt0;
-    m_PLT1 = x86_dyn_plt1;
-    m_PLT0Size = sizeof (x86_dyn_plt0);
-    m_PLT1Size = sizeof (x86_dyn_plt1);
-    // create PLT0
-    new X86DynPLT0(*m_SectionData);
+  if (got_size == 32) {
+    if (LinkerConfig::DynObj == m_Config.codeGenType()) {
+      m_PLT0 = x86_32_dyn_plt0;
+      m_PLT1 = x86_32_dyn_plt1;
+      m_PLT0Size = sizeof (x86_32_dyn_plt0);
+      m_PLT1Size = sizeof (x86_32_dyn_plt1);
+      // create PLT0
+      new X86_32DynPLT0(*m_SectionData);
+    }
+    else {
+      m_PLT0 = x86_32_exec_plt0;
+      m_PLT1 = x86_32_exec_plt1;
+      m_PLT0Size = sizeof (x86_32_exec_plt0);
+      m_PLT1Size = sizeof (x86_32_exec_plt1);
+      // create PLT0
+      new X86_32ExecPLT0(*m_SectionData);
+    }
   }
   else {
-    m_PLT0 = x86_exec_plt0;
-    m_PLT1 = x86_exec_plt1;
-    m_PLT0Size = sizeof (x86_exec_plt0);
-    m_PLT1Size = sizeof (x86_exec_plt1);
+    assert(got_size == 64);
+    m_PLT0 = x86_64_plt0;
+    m_PLT1 = x86_64_plt1;
+    m_PLT0Size = sizeof (x86_64_plt0);
+    m_PLT1Size = sizeof (x86_64_plt1);
     // create PLT0
-    new X86ExecPLT0(*m_SectionData);
+    new X86_64PLT0(*m_SectionData);
+    m_Last = m_SectionData->begin();
   }
   m_Last = m_SectionData->begin();
 }
@@ -114,9 +135,9 @@
   for (size_t i = 0; i < pNum; ++i) {
 
     if (LinkerConfig::DynObj == m_Config.codeGenType())
-      plt1_entry = new X86DynPLT1(*m_SectionData);
+      plt1_entry = new X86_32DynPLT1(*m_SectionData);
     else
-      plt1_entry = new X86ExecPLT1(*m_SectionData);
+      plt1_entry = new X86_32ExecPLT1(*m_SectionData);
 
     if (NULL == plt1_entry)
       fatal(diag::fail_allocate_memory_plt);
@@ -144,8 +165,18 @@
   return plt0;
 }
 
+//===----------------------------------------------------------------------===//
+// X86_32PLT
+//===----------------------------------------------------------------------===//
+X86_32PLT::X86_32PLT(LDSection& pSection,
+		     X86_32GOTPLT& pGOTPLT,
+		     const LinkerConfig& pConfig)
+  : X86PLT(pSection, pConfig, 32),
+    m_GOTPLT(pGOTPLT) {
+}
+
 // FIXME: It only works on little endian machine.
-void X86PLT::applyPLT0()
+void X86_32PLT::applyPLT0()
 {
   PLTEntryBase* plt0 = getPLT0();
 
@@ -157,7 +188,7 @@
 
   memcpy(data, m_PLT0, plt0->size());
 
-  if (m_PLT0 == x86_exec_plt0) {
+  if (m_PLT0 == x86_32_exec_plt0) {
     uint32_t *offset = reinterpret_cast<uint32_t*>(data + 2);
     *offset = m_GOTPLT.addr() + 4;
     offset = reinterpret_cast<uint32_t*>(data + 8);
@@ -168,7 +199,7 @@
 }
 
 // FIXME: It only works on little endian machine.
-void X86PLT::applyPLT1()
+void X86_32PLT::applyPLT1()
 {
   assert(m_Section.addr() && ".plt base address is NULL!");
 
@@ -176,7 +207,7 @@
   X86PLT::iterator ie = m_SectionData->end();
   assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
 
-  uint64_t GOTEntrySize = X86GOTPLTEntry::EntrySize;
+  uint64_t GOTEntrySize = X86_32GOTEntry::EntrySize;
 
   // Skip GOT0
   uint64_t GOTEntryOffset = GOTEntrySize * X86GOTPLT0Num;
@@ -220,3 +251,96 @@
   }
 }
 
+//===----------------------------------------------------------------------===//
+// X86_64PLT
+//===----------------------------------------------------------------------===//
+X86_64PLT::X86_64PLT(LDSection& pSection,
+		     X86_64GOTPLT& pGOTPLT,
+		     const LinkerConfig& pConfig)
+  : X86PLT(pSection, pConfig, 64),
+    m_GOTPLT(pGOTPLT) {
+}
+
+// FIXME: It only works on little endian machine.
+void X86_64PLT::applyPLT0()
+{
+  PLTEntryBase* plt0 = getPLT0();
+
+  unsigned char* data = 0;
+  data = static_cast<unsigned char*>(malloc(plt0->size()));
+
+  if (!data)
+    fatal(diag::fail_allocate_memory_plt);
+
+  memcpy(data, m_PLT0, plt0->size());
+
+  // pushq GOT + 8(%rip)
+  uint32_t *offset = reinterpret_cast<uint32_t*>(data + 2);
+  *offset = m_GOTPLT.addr() - addr() + 8 - 6;
+  // jmq *GOT + 16(%rip)
+  offset = reinterpret_cast<uint32_t*>(data + 8);
+  *offset = m_GOTPLT.addr() - addr() + 16 - 12;
+
+  plt0->setValue(data);
+}
+
+// FIXME: It only works on little endian machine.
+void X86_64PLT::applyPLT1()
+{
+  assert(m_Section.addr() && ".plt base address is NULL!");
+
+  X86PLT::iterator it = m_SectionData->begin();
+  X86PLT::iterator ie = m_SectionData->end();
+  assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
+
+  uint64_t GOTEntrySize = X86_64GOTEntry::EntrySize;
+
+  // compute sym@GOTPCREL of the PLT1 entry.
+  uint64_t SymGOTPCREL = m_GOTPLT.addr();
+
+  // Skip GOT0
+  SymGOTPCREL += GOTEntrySize * X86GOTPLT0Num;
+
+  // skip PLT0
+  uint64_t PLTEntryOffset = m_PLT0Size;
+  ++it;
+
+  // PC-relative to entry in PLT section.
+  SymGOTPCREL -= addr() + PLTEntryOffset + 6;
+
+  PLTEntryBase* plt1 = 0;
+
+  uint64_t PLTRelIndex = 0;
+
+  while (it != ie) {
+    plt1 = &(llvm::cast<PLTEntryBase>(*it));
+    unsigned char *data;
+    data = static_cast<unsigned char*>(malloc(plt1->size()));
+
+    if (!data)
+      fatal(diag::fail_allocate_memory_plt);
+
+    memcpy(data, m_PLT1, plt1->size());
+
+    uint32_t* offset;
+
+    // jmpq *sym@GOTPCREL(%rip)
+    offset = reinterpret_cast<uint32_t*>(data + 2);
+    *offset = SymGOTPCREL;
+    SymGOTPCREL += GOTEntrySize - m_PLT1Size;
+
+    // pushq $index
+    offset = reinterpret_cast<uint32_t*>(data + 7);
+    *offset = PLTRelIndex;
+    PLTRelIndex++;
+
+    // jmpq plt0
+    offset = reinterpret_cast<uint32_t*>(data + 12);
+    *offset = -(PLTEntryOffset + 12 + 4);
+    PLTEntryOffset += m_PLT1Size;
+
+    plt1->setValue(data);
+    ++it;
+  }
+}
+
diff --git a/lib/Target/X86/X86PLT.h b/lib/Target/X86/X86PLT.h
index 75a72e6..2f4176c 100644
--- a/lib/Target/X86/X86PLT.h
+++ b/lib/Target/X86/X86PLT.h
@@ -13,63 +13,90 @@
 
 namespace {
 
-const uint8_t x86_dyn_plt0[] = {
+const uint8_t x86_32_dyn_plt0[] = {
   0xff, 0xb3, 0x04, 0, 0, 0, // pushl  0x4(%ebx)
   0xff, 0xa3, 0x08, 0, 0, 0, // jmp    *0x8(%ebx)
   0x0f, 0x1f, 0x4,  0        // nopl   0(%eax)
 };
 
-const uint8_t x86_dyn_plt1[] = {
+const uint8_t x86_32_dyn_plt1[] = {
   0xff, 0xa3, 0, 0, 0, 0,    // jmp    *sym@GOT(%ebx)
   0x68, 0, 0, 0, 0,          // pushl  $offset
   0xe9, 0, 0, 0, 0           // jmp    plt0
 };
 
-const uint8_t x86_exec_plt0[] = {
+const uint8_t x86_32_exec_plt0[] = {
   0xff, 0x35, 0, 0, 0, 0,    // pushl  .got + 4
   0xff, 0x25, 0, 0, 0, 0,    // jmp    *(.got + 8)
   0x0f, 0x1f, 0x4, 0         // nopl   0(%eax)
 };
 
-const uint8_t x86_exec_plt1[] = {
+const uint8_t x86_32_exec_plt1[] = {
   0xff, 0x25, 0, 0, 0, 0,    // jmp    *(sym in .got)
   0x68, 0, 0, 0, 0,          // pushl  $offset
   0xe9, 0, 0, 0, 0           // jmp    plt0
 };
 
+const uint8_t x86_64_plt0[] = {
+  0xff, 0x35, 0x8, 0, 0, 0,  // pushq  GOT + 8(%rip)
+  0xff, 0x25, 0x16, 0, 0, 0, // jmq    *GOT + 16(%rip)
+  0x0f, 0x1f, 0x40, 0        // nopl   0(%rax)
+};
+
+const uint8_t x86_64_plt1[] = {
+  0xff, 0x25, 0, 0, 0, 0,    // jmpq   *sym@GOTPCREL(%rip)
+  0x68, 0, 0, 0, 0,          // pushq  $index
+  0xe9, 0, 0, 0, 0           // jmpq   plt0
+};
+
 } // anonymous namespace
 
 namespace mcld {
 
-class X86GOTPLT;
+class X86_32GOTPLT;
 class GOTEntry;
 class LinkerConfig;
 
 //===----------------------------------------------------------------------===//
-// X86PLT Entry
+// X86_32PLT Entry
 //===----------------------------------------------------------------------===//
-class X86DynPLT0 : public PLT::Entry<sizeof(x86_dyn_plt0)>
+class X86_32DynPLT0 : public PLT::Entry<sizeof(x86_32_dyn_plt0)>
 {
 public:
-  X86DynPLT0(SectionData& pParent);
+  X86_32DynPLT0(SectionData& pParent);
 };
 
-class X86DynPLT1 : public PLT::Entry<sizeof(x86_dyn_plt1)>
+class X86_32DynPLT1 : public PLT::Entry<sizeof(x86_32_dyn_plt1)>
 {
 public:
-  X86DynPLT1(SectionData& pParent);
+  X86_32DynPLT1(SectionData& pParent);
 };
 
-class X86ExecPLT0 : public PLT::Entry<sizeof(x86_exec_plt0)>
+class X86_32ExecPLT0 : public PLT::Entry<sizeof(x86_32_exec_plt0)>
 {
 public:
-  X86ExecPLT0(SectionData& pParent);
+  X86_32ExecPLT0(SectionData& pParent);
 };
 
-class X86ExecPLT1 : public PLT::Entry<sizeof(x86_exec_plt1)>
+class X86_32ExecPLT1 : public PLT::Entry<sizeof(x86_32_exec_plt1)>
 {
 public:
-  X86ExecPLT1(SectionData& pParent);
+  X86_32ExecPLT1(SectionData& pParent);
+};
+
+//===----------------------------------------------------------------------===//
+// X86_64PLT Entry
+//===----------------------------------------------------------------------===//
+class X86_64PLT0 : public PLT::Entry<sizeof(x86_64_plt0)>
+{
+public:
+  X86_64PLT0(SectionData& pParent);
+};
+
+class X86_64PLT1 : public PLT::Entry<sizeof(x86_64_plt1)>
+{
+public:
+  X86_64PLT1(SectionData& pParent);
 };
 
 //===----------------------------------------------------------------------===//
@@ -82,8 +109,8 @@
 {
 public:
   X86PLT(LDSection& pSection,
-         X86GOTPLT& pGOTPLT,
-         const LinkerConfig& pConfig);
+         const LinkerConfig& pConfig,
+	 int got_size);
   ~X86PLT();
 
   // finalizeSectionSize - set LDSection size
@@ -96,19 +123,17 @@
 
   PLTEntryBase* consume();
 
-  void applyPLT0();
+  virtual void applyPLT0() = 0;
 
-  void applyPLT1();
+  virtual void applyPLT1() = 0;
 
   unsigned int getPLT0Size() const { return m_PLT0Size; }
   unsigned int getPLT1Size() const { return m_PLT1Size; }
 
-private:
+protected:
   PLTEntryBase* getPLT0() const;
 
-private:
-  X86GOTPLT& m_GOTPLT;
-
+protected:
   // the last consumed entry.
   SectionData::iterator m_Last;
 
@@ -120,6 +145,48 @@
   const LinkerConfig& m_Config;
 };
 
+//===----------------------------------------------------------------------===//
+// X86_32PLT
+//===----------------------------------------------------------------------===//
+/** \class X86_32PLT
+ *  \brief X86_32 Procedure Linkage Table
+ */
+class X86_32PLT : public X86PLT
+{
+public:
+  X86_32PLT(LDSection& pSection,
+	    X86_32GOTPLT& pGOTPLT,
+	    const LinkerConfig& pConfig);
+
+  void applyPLT0();
+
+  void applyPLT1();
+
+private:
+  X86_32GOTPLT& m_GOTPLT;
+};
+
+//===----------------------------------------------------------------------===//
+// X86_64PLT
+//===----------------------------------------------------------------------===//
+/** \class X86_64PLT
+ *  \brief X86_64 Procedure Linkage Table
+ */
+class X86_64PLT : public X86PLT
+{
+public:
+  X86_64PLT(LDSection& pSection,
+	    X86_64GOTPLT& pGOTPLT,
+	    const LinkerConfig& pConfig);
+
+  void applyPLT0();
+
+  void applyPLT1();
+
+private:
+  X86_64GOTPLT& m_GOTPLT;
+};
+
 } // namespace of mcld
 
 #endif
diff --git a/lib/Target/X86/X86RelocationFunctions.h b/lib/Target/X86/X86RelocationFunctions.h
index df2e70c..9209242 100644
--- a/lib/Target/X86/X86RelocationFunctions.h
+++ b/lib/Target/X86/X86RelocationFunctions.h
@@ -7,69 +7,122 @@
 //
 //===----------------------------------------------------------------------===//
 
-#define DECL_X86_APPLY_RELOC_FUNC(Name) \
-static X86Relocator::Result Name    (Relocation& pEntry, \
-					                          X86Relocator& pParent);
+#define DECL_X86_32_APPLY_RELOC_FUNC(Name) \
+static X86Relocator::Result Name(Relocation& pEntry, X86_32Relocator& pParent);
 
-#define DECL_X86_APPLY_RELOC_FUNCS \
-DECL_X86_APPLY_RELOC_FUNC(none)             \
-DECL_X86_APPLY_RELOC_FUNC(abs)              \
-DECL_X86_APPLY_RELOC_FUNC(rel)              \
-DECL_X86_APPLY_RELOC_FUNC(plt32)            \
-DECL_X86_APPLY_RELOC_FUNC(got32)            \
-DECL_X86_APPLY_RELOC_FUNC(gotoff32)	        \
-DECL_X86_APPLY_RELOC_FUNC(gotpc32)          \
-DECL_X86_APPLY_RELOC_FUNC(tls_gd)           \
-DECL_X86_APPLY_RELOC_FUNC(tls_ie)           \
-DECL_X86_APPLY_RELOC_FUNC(tls_gotie)        \
-DECL_X86_APPLY_RELOC_FUNC(tls_le)           \
-DECL_X86_APPLY_RELOC_FUNC(tls_ldm)          \
-DECL_X86_APPLY_RELOC_FUNC(tls_ldo_32)       \
-DECL_X86_APPLY_RELOC_FUNC(unsupport)
+#define DECL_X86_32_APPLY_RELOC_FUNCS \
+DECL_X86_32_APPLY_RELOC_FUNC(none)             \
+DECL_X86_32_APPLY_RELOC_FUNC(abs)              \
+DECL_X86_32_APPLY_RELOC_FUNC(rel)              \
+DECL_X86_32_APPLY_RELOC_FUNC(plt32)            \
+DECL_X86_32_APPLY_RELOC_FUNC(got32)            \
+DECL_X86_32_APPLY_RELOC_FUNC(gotoff32)         \
+DECL_X86_32_APPLY_RELOC_FUNC(gotpc32)          \
+DECL_X86_32_APPLY_RELOC_FUNC(tls_gd)           \
+DECL_X86_32_APPLY_RELOC_FUNC(tls_ie)           \
+DECL_X86_32_APPLY_RELOC_FUNC(tls_gotie)        \
+DECL_X86_32_APPLY_RELOC_FUNC(tls_le)           \
+DECL_X86_32_APPLY_RELOC_FUNC(tls_ldm)          \
+DECL_X86_32_APPLY_RELOC_FUNC(tls_ldo_32)       \
+DECL_X86_32_APPLY_RELOC_FUNC(unsupport)
 
 
-#define DECL_X86_APPLY_RELOC_FUNC_PTRS \
-  { &none,               0, "R_386_NONE"              },  \
-  { &abs,                1, "R_386_32"                },  \
-  { &rel,                2, "R_386_PC32"              },  \
-  { &got32,              3, "R_386_GOT32"             },  \
-  { &plt32,              4, "R_386_PLT32"             },  \
-  { &none,               5, "R_386_COPY"              },  \
-  { &none,               6, "R_386_GLOB_DAT"          },  \
-  { &none,               7, "R_386_JMP_SLOT"          },  \
-  { &none,               8, "R_386_RELATIVE"          },  \
-  { &gotoff32,           9, "R_386_GOTOFF"            },  \
-  { &gotpc32,           10, "R_386_GOTPC"             },  \
-  { &unsupport,         11, "R_386_32PLT"             },  \
-  { &unsupport,         12, ""                        },  \
-  { &unsupport,         13, ""                        },  \
-  { &unsupport,         14, "R_386_TLS_TPOFF"         },  \
-  { &tls_ie,            15, "R_386_TLS_IE"            },  \
-  { &tls_gotie,         16, "R_386_TLS_GOTIE"         },  \
-  { &tls_le,            17, "R_386_TLS_LE"            },  \
-  { &tls_gd,            18, "R_386_TLS_GD"            },  \
-  { &tls_ldm,           19, "R_386_TLS_LDM"           },  \
-  { &abs,               20, "R_386_16"                },  \
-  { &rel,               21, "R_386_PC16"              },  \
-  { &abs,               22, "R_386_8"                 },  \
-  { &rel,               23, "R_386_PC8"               },  \
-  { &unsupport,         24, "R_386_TLS_GD_32"         },  \
-  { &unsupport,         25, "R_386_TLS_GD_PUSH"       },  \
-  { &unsupport,         26, "R_386_TLS_GD_CALL"       },  \
-  { &unsupport,         27, "R_386_TLS_GD_POP"        },  \
-  { &unsupport,         28, "R_386_TLS_LDM_32"        },  \
-  { &unsupport,         29, "R_386_TLS_LDM_PUSH"      },  \
-  { &unsupport,         30, "R_386_TLS_LDM_CALL"      },  \
-  { &unsupport,         31, "R_386_TLS_LDM_POP"       },  \
-  { &tls_ldo_32,        32, "R_386_TLS_LDO_32"        },  \
-  { &unsupport,         33, "R_386_TLS_IE_32"         },  \
-  { &unsupport,         34, "R_386_TLS_LE_32"         },  \
-  { &unsupport,         35, "R_386_TLS_DTPMOD32"      },  \
-  { &unsupport,         36, "R_386_TLS_DTPOFF32"      },  \
-  { &unsupport,         37, "R_386_TLS_TPOFF32"       },  \
-  { &unsupport,         38, ""                        },  \
-  { &unsupport,         39, "R_386_TLS_GOTDESC"       },  \
-  { &unsupport,         40, "R_386_TLS_DESC_CALL"     },  \
-  { &unsupport,         41, "R_386_TLS_DESC"          },  \
-  { &unsupport,         42, "R_386_IRELATIVE"         },  \
-  { &unsupport,         43,  "R_386_NUM"              }
+#define DECL_X86_32_APPLY_RELOC_FUNC_PTRS \
+  { &none,               0, "R_386_NONE",             0  },  \
+  { &abs,                1, "R_386_32",               32 },  \
+  { &rel,                2, "R_386_PC32",             32 },  \
+  { &got32,              3, "R_386_GOT32",            32 },  \
+  { &plt32,              4, "R_386_PLT32",            32 },  \
+  { &none,               5, "R_386_COPY",             0  },  \
+  { &none,               6, "R_386_GLOB_DAT",         0  },  \
+  { &none,               7, "R_386_JMP_SLOT",         0  },  \
+  { &none,               8, "R_386_RELATIVE",         0  },  \
+  { &gotoff32,           9, "R_386_GOTOFF",           32 },  \
+  { &gotpc32,           10, "R_386_GOTPC",            32 },  \
+  { &unsupport,         11, "R_386_32PLT",            0  },  \
+  { &unsupport,         12, "",                       0  },  \
+  { &unsupport,         13, "",                       0  },  \
+  { &unsupport,         14, "R_386_TLS_TPOFF",        0  },  \
+  { &tls_ie,            15, "R_386_TLS_IE",           0  },  \
+  { &tls_gotie,         16, "R_386_TLS_GOTIE",        0  },  \
+  { &tls_le,            17, "R_386_TLS_LE",           0  },  \
+  { &tls_gd,            18, "R_386_TLS_GD",           0  },  \
+  { &tls_ldm,           19, "R_386_TLS_LDM",          0  },  \
+  { &abs,               20, "R_386_16",               16 },  \
+  { &rel,               21, "R_386_PC16",             16 },  \
+  { &abs,               22, "R_386_8",                8  },  \
+  { &rel,               23, "R_386_PC8",              8  },  \
+  { &unsupport,         24, "R_386_TLS_GD_32",        0  },  \
+  { &unsupport,         25, "R_386_TLS_GD_PUSH",      0  },  \
+  { &unsupport,         26, "R_386_TLS_GD_CALL",      0  },  \
+  { &unsupport,         27, "R_386_TLS_GD_POP",       0  },  \
+  { &unsupport,         28, "R_386_TLS_LDM_32",       0  },  \
+  { &unsupport,         29, "R_386_TLS_LDM_PUSH",     0  },  \
+  { &unsupport,         30, "R_386_TLS_LDM_CALL",     0  },  \
+  { &unsupport,         31, "R_386_TLS_LDM_POP",      0  },  \
+  { &tls_ldo_32,        32, "R_386_TLS_LDO_32",       0  },  \
+  { &unsupport,         33, "R_386_TLS_IE_32",        0  },  \
+  { &unsupport,         34, "R_386_TLS_LE_32",        0  },  \
+  { &unsupport,         35, "R_386_TLS_DTPMOD32",     0  },  \
+  { &unsupport,         36, "R_386_TLS_DTPOFF32",     0  },  \
+  { &unsupport,         37, "R_386_TLS_TPOFF32",      0  },  \
+  { &unsupport,         38, "",                       0  },  \
+  { &unsupport,         39, "R_386_TLS_GOTDESC",      0  },  \
+  { &unsupport,         40, "R_386_TLS_DESC_CALL",    0  },  \
+  { &unsupport,         41, "R_386_TLS_DESC",         0  },  \
+  { &unsupport,         42, "R_386_IRELATIVE",        0  },  \
+  { &unsupport,         43, "R_386_NUM",              0  },  \
+  { &none,              44, "R_386_TLS_OPT",          0  }
+
+#define DECL_X86_64_APPLY_RELOC_FUNC(Name) \
+static X86Relocator::Result Name(Relocation& pEntry, X86_64Relocator& pParent);
+
+#define DECL_X86_64_APPLY_RELOC_FUNCS \
+DECL_X86_64_APPLY_RELOC_FUNC(none)             \
+DECL_X86_64_APPLY_RELOC_FUNC(abs)              \
+DECL_X86_64_APPLY_RELOC_FUNC(signed32)         \
+DECL_X86_64_APPLY_RELOC_FUNC(gotpcrel)         \
+DECL_X86_64_APPLY_RELOC_FUNC(plt32)            \
+DECL_X86_64_APPLY_RELOC_FUNC(rel)              \
+DECL_X86_64_APPLY_RELOC_FUNC(unsupport)
+
+#define DECL_X86_64_APPLY_RELOC_FUNC_PTRS \
+  { &none,               0, "R_X86_64_NONE",            0  },  \
+  { &abs,                1, "R_X86_64_64",              64 },  \
+  { &rel,                2, "R_X86_64_PC32",            32 },  \
+  { &unsupport,          3, "R_X86_64_GOT32",           32 },  \
+  { &plt32,              4, "R_X86_64_PLT32",           32 },  \
+  { &none,               5, "R_X86_64_COPY",            0  },  \
+  { &none,               6, "R_X86_64_GLOB_DAT",        0  },  \
+  { &none,               7, "R_X86_64_JMP_SLOT",        0  },  \
+  { &none,               8, "R_X86_64_RELATIVE",        0  },  \
+  { &gotpcrel,           9, "R_X86_64_GOTPCREL",        32 },  \
+  { &abs,               10, "R_X86_64_32",              32 },  \
+  { &signed32,          11, "R_X86_64_32S",             32 },  \
+  { &abs,               12, "R_X86_64_16",              16 },  \
+  { &rel,               13, "R_X86_64_PC16",            16 },  \
+  { &abs,               14, "R_X86_64_8",               8  },  \
+  { &rel,               15, "R_X86_64_PC8",             8  },  \
+  { &none,              16, "R_X86_64_DTPMOD64",        0  },  \
+  { &unsupport,         17, "R_X86_64_DTPOFF64",        0  },  \
+  { &none,              18, "R_X86_64_TPOFF64",         0  },  \
+  { &unsupport,         19, "R_X86_64_TLSGD",           0  },  \
+  { &unsupport,         20, "R_X86_64_TLSLD",           0  },  \
+  { &unsupport,         21, "R_X86_64_DTPOFF32",        0  },  \
+  { &unsupport,         22, "R_X86_64_GOTTPOFF",        0  },  \
+  { &unsupport,         23, "R_X86_64_TPOFF32",         0  },  \
+  { &unsupport,         24, "R_X86_64_PC64",            64 },  \
+  { &unsupport,         25, "R_X86_64_GOTOFF64",        64 },  \
+  { &unsupport,         26, "R_X86_64_GOTPC32",         32 },  \
+  { &unsupport,         27, "R_X86_64_GOT64",           64 },  \
+  { &unsupport,         28, "R_X86_64_GOTPCREL64",      64 },  \
+  { &unsupport,         29, "R_X86_64_GOTPC64",         64 },  \
+  { &unsupport,         30, "R_X86_64_GOTPLT64",        64 },  \
+  { &unsupport,         31, "R_X86_64_PLTOFF64",        64 },  \
+  { &unsupport,         32, "R_X86_64_SIZE32",          32 },  \
+  { &unsupport,         33, "R_X86_64_SIZE64",          64 },  \
+  { &unsupport,         34, "R_X86_64_GOTPC32_TLSDESC", 0  },  \
+  { &unsupport,         35, "R_X86_64_TLSDESC_CALL",    0  },  \
+  { &none,              36, "R_X86_64_TLSDESC",         0  },  \
+  { &none,              37, "R_X86_64_IRELATIVE",       0  },  \
+  { &none,              38, "R_X86_64_RELATIVE64",      0  }
diff --git a/lib/Target/X86/X86Relocator.cpp b/lib/Target/X86/X86Relocator.cpp
index 3b4d389..a4eac66 100644
--- a/lib/Target/X86/X86Relocator.cpp
+++ b/lib/Target/X86/X86Relocator.cpp
@@ -6,68 +6,80 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include "X86Relocator.h"
+#include "X86RelocationFunctions.h"
+
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/LD/LDSymbol.h>
 
 #include <llvm/ADT/Twine.h>
 #include <llvm/Support/DataTypes.h>
 #include <llvm/Support/ELF.h>
-#include <mcld/Fragment/FragmentLinker.h>
-#include <mcld/Support/MsgHandling.h>
-
-#include "X86Relocator.h"
-#include "X86RelocationFunctions.h"
 
 using namespace mcld;
 
 //===--------------------------------------------------------------------===//
 // Relocation Functions and Tables
 //===--------------------------------------------------------------------===//
-DECL_X86_APPLY_RELOC_FUNCS
+DECL_X86_32_APPLY_RELOC_FUNCS
 
 /// the prototype of applying function
-typedef Relocator::Result (*ApplyFunctionType)(Relocation& pReloc,
-                                               X86Relocator& pParent);
+typedef Relocator::Result (*X86_32ApplyFunctionType)(Relocation& pReloc,
+						     X86_32Relocator& pParent);
 
 // the table entry of applying functions
-struct ApplyFunctionTriple
+struct X86_32ApplyFunctionTriple
 {
-  ApplyFunctionType func;
+  X86_32ApplyFunctionType func;
   unsigned int type;
   const char* name;
+  unsigned int size;
 };
 
 // declare the table of applying functions
-static const ApplyFunctionTriple ApplyFunctions[] = {
-  DECL_X86_APPLY_RELOC_FUNC_PTRS
+static const X86_32ApplyFunctionTriple X86_32ApplyFunctions[] = {
+  DECL_X86_32_APPLY_RELOC_FUNC_PTRS
 };
 
 //===--------------------------------------------------------------------===//
 // X86Relocator
 //===--------------------------------------------------------------------===//
-X86Relocator::X86Relocator(X86GNULDBackend& pParent)
-  : Relocator(),
-    m_Target(pParent) {
+X86Relocator::X86Relocator()
+  : Relocator() {
 }
 
 X86Relocator::~X86Relocator()
 {
 }
 
+//===--------------------------------------------------------------------===//
+// X86_32Relocator
+//===--------------------------------------------------------------------===//
+X86_32Relocator::X86_32Relocator(X86_32GNULDBackend& pParent)
+  : X86Relocator(), m_Target(pParent) {
+}
+
 Relocator::Result
-X86Relocator::applyRelocation(Relocation& pRelocation)
+X86_32Relocator::applyRelocation(Relocation& pRelocation)
 {
   Relocation::Type type = pRelocation.type();
 
-  if (type >= sizeof (ApplyFunctions) / sizeof (ApplyFunctions[0]) ) {
+  if (type >= sizeof (X86_32ApplyFunctions) / sizeof (X86_32ApplyFunctions[0]) ) {
     return Unknown;
   }
 
   // apply the relocation
-  return ApplyFunctions[type].func(pRelocation, *this);
+  return X86_32ApplyFunctions[type].func(pRelocation, *this);
 }
 
-const char* X86Relocator::getName(Relocation::Type pType) const
+const char* X86_32Relocator::getName(Relocation::Type pType) const
 {
-  return ApplyFunctions[pType].name;
+  return X86_32ApplyFunctions[pType].name;
+}
+
+Relocator::Size X86_32Relocator::getSize(Relocation::Type pType) const
+{
+  return X86_32ApplyFunctions[pType].size;;
 }
 
 //===--------------------------------------------------------------------===//
@@ -80,9 +92,9 @@
                           Fragment& pFrag,
                           uint64_t pOffset,
                           X86Relocator::Type pType,
-                          X86Relocator& pParent)
+                          X86_32Relocator& pParent)
 {
-  X86GNULDBackend& ld_backend = pParent.getTarget();
+  X86_32GNULDBackend& ld_backend = pParent.getTarget();
   Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
   rel_entry.setType(pType);
   rel_entry.targetRef().assign(pFrag, pOffset);
@@ -99,7 +111,7 @@
 /// R_386_RELATIVE
 static bool
 helper_use_relative_reloc(const ResolveInfo& pSym,
-                          const X86Relocator& pFactory)
+                          const X86_32Relocator& pFactory)
 
 {
   // if symbol is dynamic or undefine or preemptible
@@ -111,14 +123,14 @@
 }
 
 static
-X86GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
-                                     X86Relocator& pParent)
+X86_32GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
+					X86_32Relocator& pParent)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
-  X86GNULDBackend& ld_backend = pParent.getTarget();
+  X86_32GNULDBackend& ld_backend = pParent.getTarget();
 
-  X86GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
+  X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
   if (NULL != got_entry)
     return *got_entry;
 
@@ -150,27 +162,28 @@
 
 
 static
-X86Relocator::Address helper_GOT_ORG(X86Relocator& pParent)
+X86Relocator::Address helper_GOT_ORG(X86_32Relocator& pParent)
 {
   return pParent.getTarget().getGOTPLT().addr();
 }
 
 
 static
-X86Relocator::Address helper_GOT(Relocation& pReloc, X86Relocator& pParent)
+X86Relocator::Address helper_GOT(Relocation& pReloc, X86_32Relocator& pParent)
 {
-  X86GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
+  X86_32GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
   X86Relocator::Address got_addr = pParent.getTarget().getGOT().addr();
   return got_addr + got_entry.getOffset();
 }
 
 
 static
-PLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc, X86Relocator& pParent)
+PLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc,
+				      X86_32Relocator& pParent)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
-  X86GNULDBackend& ld_backend = pParent.getTarget();
+  X86_32GNULDBackend& ld_backend = pParent.getTarget();
 
   PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
   if (NULL != plt_entry)
@@ -181,7 +194,7 @@
   pParent.getSymPLTMap().record(*rsym, *plt_entry);
   // If we first get this PLT entry, we should initialize it.
   if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
-    X86GOTPLTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
+    X86_32GOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
     assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!");
     gotplt_entry = ld_backend.getGOTPLT().consume();
     pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
@@ -200,14 +213,14 @@
 
 
 static
-X86Relocator::Address helper_PLT_ORG(X86Relocator& pParent)
+X86Relocator::Address helper_PLT_ORG(X86_32Relocator& pParent)
 {
   return pParent.getTarget().getPLT().addr();
 }
 
 
 static
-X86Relocator::Address helper_PLT(Relocation& pReloc, X86Relocator& pParent)
+X86Relocator::Address helper_PLT(Relocation& pReloc, X86_32Relocator& pParent)
 {
   PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
   return helper_PLT_ORG(pParent) + plt_entry.getOffset();
@@ -219,7 +232,7 @@
 //=========================================//
 
 // R_386_NONE
-X86Relocator::Result none(Relocation& pReloc, X86Relocator& pParent)
+X86Relocator::Result none(Relocation& pReloc, X86_32Relocator& pParent)
 {
   return X86Relocator::OK;
 }
@@ -227,13 +240,12 @@
 // R_386_32: S + A
 // R_386_16
 // R_386_8
-X86Relocator::Result abs(Relocation& pReloc, X86Relocator& pParent)
+X86Relocator::Result abs(Relocation& pReloc, X86_32Relocator& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
   Relocator::DWord A = pReloc.target() + pReloc.addend();
   Relocator::DWord S = pReloc.symValue();
   bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
-                              pParent.getFragmentLinker(),
                               *rsym,
                               (rsym->reserved() & X86GNULDBackend::ReservePLT),
                               true);
@@ -292,7 +304,7 @@
 // R_386_PC32: S + A - P
 // R_386_PC16
 // R_386_PC8
-X86Relocator::Result rel(Relocation& pReloc, X86Relocator& pParent)
+X86Relocator::Result rel(Relocation& pReloc, X86_32Relocator& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
   Relocator::DWord A = pReloc.target() + pReloc.addend();
@@ -314,7 +326,6 @@
        pReloc.target() = S + A - P;
     }
     if (pParent.getTarget().symbolNeedsDynRel(
-                              pParent.getFragmentLinker(),
                               *rsym,
                               (rsym->reserved() & X86GNULDBackend::ReservePLT),
                               false)) {
@@ -336,7 +347,7 @@
 }
 
 // R_386_GOTOFF: S + A - GOT_ORG
-X86Relocator::Result gotoff32(Relocation& pReloc, X86Relocator& pParent)
+X86Relocator::Result gotoff32(Relocation& pReloc, X86_32Relocator& pParent)
 {
   Relocator::DWord      A = pReloc.target() + pReloc.addend();
   X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
@@ -347,7 +358,7 @@
 }
 
 // R_386_GOTPC: GOT_ORG + A - P
-X86Relocator::Result gotpc32(Relocation& pReloc, X86Relocator& pParent)
+X86Relocator::Result gotpc32(Relocation& pReloc, X86_32Relocator& pParent)
 {
   Relocator::DWord      A       = pReloc.target() + pReloc.addend();
   X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
@@ -357,7 +368,7 @@
 }
 
 // R_386_GOT32: GOT(S) + A - GOT_ORG
-X86Relocator::Result got32(Relocation& pReloc, X86Relocator& pParent)
+X86Relocator::Result got32(Relocation& pReloc, X86_32Relocator& pParent)
 {
   if (!(pReloc.symInfo()->reserved()
        & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) {
@@ -372,7 +383,7 @@
 }
 
 // R_386_PLT32: PLT(S) + A - P
-X86Relocator::Result plt32(Relocation& pReloc, X86Relocator& pParent)
+X86Relocator::Result plt32(Relocation& pReloc, X86_32Relocator& pParent)
 {
   // PLT_S depends on if there is a PLT entry.
   X86Relocator::Address PLT_S;
@@ -387,7 +398,7 @@
 }
 
 // R_386_TLS_GD:
-X86Relocator::Result tls_gd(Relocation& pReloc, X86Relocator& pParent)
+X86Relocator::Result tls_gd(Relocation& pReloc, X86_32Relocator& pParent)
 {
   // global-dynamic
   ResolveInfo* rsym = pReloc.symInfo();
@@ -396,19 +407,19 @@
      return X86Relocator::BadReloc;
   }
 
-  X86GNULDBackend& ld_backend = pParent.getTarget();
+  X86_32GNULDBackend& ld_backend = pParent.getTarget();
   ELFFileFormat* file_format = pParent.getTarget().getOutputFormat();
   // setup corresponding got and dynamic relocatio entries:
   // get first got entry, if there is already a got entry for rsym, then apply
   // this relocation to the got entry directly. If not, setup the corresponding
   // got and dyn relocation entries
-  X86GOTEntry* got_entry1 = pParent.getSymGOTMap().lookUp(*rsym);
+  X86_32GOTEntry* got_entry1 = pParent.getSymGOTMap().lookUp(*rsym);
 
   if (NULL == got_entry1) {
     // get and init two got entries if not exist
     got_entry1 = ld_backend.getGOT().consume();
     pParent.getSymGOTMap().record(*rsym, *got_entry1);
-    X86GOTEntry* got_entry2 = ld_backend.getGOT().consume();
+    X86_32GOTEntry* got_entry2 = ld_backend.getGOT().consume();
     got_entry1->setValue(0x0);
     got_entry2->setValue(0x0);
     // setup dyn rel for get_entry1
@@ -450,10 +461,10 @@
 }
 
 // R_386_TLS_LDM
-X86Relocator::Result tls_ldm(Relocation& pReloc, X86Relocator& pParent)
+X86Relocator::Result tls_ldm(Relocation& pReloc, X86_32Relocator& pParent)
 {
   // FIXME: no linker optimization for TLS relocation
-  const X86GOTEntry& got_entry = pParent.getTarget().getTLSModuleID();
+  const X86_32GOTEntry& got_entry = pParent.getTarget().getTLSModuleID();
 
   // All GOT offsets are relative to the end of the GOT.
   X86Relocator::SWord GOT_S = got_entry.getOffset() -
@@ -466,7 +477,7 @@
 }
 
 // R_386_TLS_LDO_32
-X86Relocator::Result tls_ldo_32(Relocation& pReloc, X86Relocator& pParent)
+X86Relocator::Result tls_ldo_32(Relocation& pReloc, X86_32Relocator& pParent)
 {
   // FIXME: no linker optimization for TLS relocation
   Relocator::DWord A = pReloc.target() + pReloc.addend();
@@ -476,7 +487,7 @@
 }
 
 // R_X86_TLS_IE
-X86Relocator::Result tls_ie(Relocation& pReloc, X86Relocator& pParent)
+X86Relocator::Result tls_ie(Relocation& pReloc, X86_32Relocator& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
   if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) {
@@ -490,10 +501,10 @@
   }
 
   // set up the got and dynamic relocation entries if not exist
-  X86GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
+  X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
   if (NULL == got_entry) {
     // set got entry
-    X86GNULDBackend& ld_backend = pParent.getTarget();
+    X86_32GNULDBackend& ld_backend = pParent.getTarget();
     got_entry = ld_backend.getGOT().consume();
     pParent.getSymGOTMap().record(*rsym, *got_entry);
     got_entry->setValue(0x0);
@@ -515,7 +526,7 @@
 }
 
 // R_386_TLS_GOTIE
-X86Relocator::Result tls_gotie(Relocation& pReloc, X86Relocator& pParent)
+X86Relocator::Result tls_gotie(Relocation& pReloc, X86_32Relocator& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
   if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) {
@@ -523,10 +534,10 @@
   }
 
   // set up the got and dynamic relocation entries if not exist
-  X86GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
+  X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
   if (NULL == got_entry) {
     // set got entry
-    X86GNULDBackend& ld_backend = pParent.getTarget();
+    X86_32GNULDBackend& ld_backend = pParent.getTarget();
     got_entry = ld_backend.getGOT().consume();
     pParent.getSymGOTMap().record(*rsym, *got_entry);
     got_entry->setValue(0x0);
@@ -547,7 +558,7 @@
 }
 
 // R_X86_TLS_LE
-X86Relocator::Result tls_le(Relocation& pReloc, X86Relocator& pParent)
+X86Relocator::Result tls_le(Relocation& pReloc, X86_32Relocator& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
   if (pReloc.symInfo()->reserved() & X86GNULDBackend::ReserveRel) {
@@ -569,8 +580,375 @@
   return X86Relocator::OK;
 }
 
-X86Relocator::Result unsupport(Relocation& pReloc, X86Relocator& pParent)
+X86Relocator::Result unsupport(Relocation& pReloc, X86_32Relocator& pParent)
 {
   return X86Relocator::Unsupport;
 }
 
+//===--------------------------------------------------------------------===//
+// Relocation Functions and Tables
+//===--------------------------------------------------------------------===//
+DECL_X86_64_APPLY_RELOC_FUNCS
+
+/// the prototype of applying function
+typedef Relocator::Result (*X86_64ApplyFunctionType)(Relocation& pReloc,
+						     X86_64Relocator& pParent);
+
+// the table entry of applying functions
+struct X86_64ApplyFunctionTriple
+{
+  X86_64ApplyFunctionType func;
+  unsigned int type;
+  const char* name;
+  unsigned int size;
+};
+
+// declare the table of applying functions
+static const X86_64ApplyFunctionTriple X86_64ApplyFunctions[] = {
+  DECL_X86_64_APPLY_RELOC_FUNC_PTRS
+};
+
+//===--------------------------------------------------------------------===//
+// X86_64Relocator
+//===--------------------------------------------------------------------===//
+X86_64Relocator::X86_64Relocator(X86_64GNULDBackend& pParent)
+  : X86Relocator(), m_Target(pParent) {
+}
+
+Relocator::Result
+X86_64Relocator::applyRelocation(Relocation& pRelocation)
+{
+  Relocation::Type type = pRelocation.type();
+
+  if (type >= sizeof (X86_64ApplyFunctions) / sizeof (X86_64ApplyFunctions[0]) ) {
+    return Unknown;
+  }
+
+  // apply the relocation
+  return X86_64ApplyFunctions[type].func(pRelocation, *this);
+}
+
+const char* X86_64Relocator::getName(Relocation::Type pType) const
+{
+  return X86_64ApplyFunctions[pType].name;
+}
+
+Relocator::Size X86_64Relocator::getSize(Relocation::Type pType) const
+{
+  return X86_64ApplyFunctions[pType].size;
+}
+
+/// helper_DynRel - Get an relocation entry in .rela.dyn
+static
+Relocation& helper_DynRel(ResolveInfo* pSym,
+                          Fragment& pFrag,
+                          uint64_t pOffset,
+                          X86Relocator::Type pType,
+                          X86_64Relocator& pParent)
+{
+  X86_64GNULDBackend& ld_backend = pParent.getTarget();
+  Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
+  rel_entry.setType(pType);
+  rel_entry.targetRef().assign(pFrag, pOffset);
+  if (pType == llvm::ELF::R_X86_64_RELATIVE || NULL == pSym)
+    rel_entry.setSymInfo(0);
+  else
+    rel_entry.setSymInfo(pSym);
+
+  return rel_entry;
+}
+
+
+/// helper_use_relative_reloc - Check if symbol can use relocation
+/// R_X86_64_RELATIVE
+static bool
+helper_use_relative_reloc(const ResolveInfo& pSym,
+                          const X86_64Relocator& pFactory)
+
+{
+  // if symbol is dynamic or undefine or preemptible
+  if (pSym.isDyn() ||
+      pSym.isUndef() ||
+      pFactory.getTarget().isSymbolPreemptible(pSym))
+    return false;
+  return true;
+}
+
+static
+X86_64GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
+					X86_64Relocator& pParent)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  X86_64GNULDBackend& ld_backend = pParent.getTarget();
+
+  X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
+  if (NULL != got_entry)
+    return *got_entry;
+
+  // not found
+  got_entry = ld_backend.getGOT().consume();
+  pParent.getSymGOTMap().record(*rsym, *got_entry);
+
+  // If we first get this GOT entry, we should initialize it.
+  if (rsym->reserved() & X86GNULDBackend::ReserveGOT) {
+    // No corresponding dynamic relocation, initialize to the symbol value.
+    got_entry->setValue(pReloc.symValue());
+  }
+  else if (rsym->reserved() & X86GNULDBackend::GOTRel) {
+    // Initialize got_entry content and the corresponding dynamic relocation.
+    if (helper_use_relative_reloc(*rsym, pParent)) {
+      Relocation& rel_entry = helper_DynRel(rsym, *got_entry, 0x0,
+					    llvm::ELF::R_X86_64_RELATIVE,
+					    pParent);
+      rel_entry.setAddend(pReloc.symValue());
+    }
+    else {
+      helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_X86_64_GLOB_DAT,
+		    pParent);
+    }
+    got_entry->setValue(0);
+  }
+  else {
+    fatal(diag::reserve_entry_number_mismatch_got);
+  }
+  return *got_entry;
+}
+
+static
+X86Relocator::Address helper_GOT_ORG(X86_64Relocator& pParent)
+{
+  return pParent.getTarget().getGOT().addr();
+}
+
+static
+X86Relocator::Address helper_GOT(Relocation& pReloc, X86_64Relocator& pParent)
+{
+  X86_64GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
+  return got_entry.getOffset();
+}
+
+static
+PLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc,
+				      X86_64Relocator& pParent)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  X86_64GNULDBackend& ld_backend = pParent.getTarget();
+
+  PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
+  if (NULL != plt_entry)
+    return *plt_entry;
+
+  // not found
+  plt_entry = ld_backend.getPLT().consume();
+  pParent.getSymPLTMap().record(*rsym, *plt_entry);
+  // If we first get this PLT entry, we should initialize it.
+  if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
+    X86_64GOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
+    assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!");
+    gotplt_entry = ld_backend.getGOTPLT().consume();
+    pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
+    // init the corresponding rel entry in .rel.plt
+    Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry();
+    rel_entry.setType(llvm::ELF::R_X86_64_JUMP_SLOT);
+    rel_entry.targetRef().assign(*gotplt_entry);
+    rel_entry.setSymInfo(rsym);
+  }
+  else {
+    fatal(diag::reserve_entry_number_mismatch_plt);
+  }
+
+  return *plt_entry;
+}
+
+static
+X86Relocator::Address helper_PLT_ORG(X86_64Relocator& pParent)
+{
+  return pParent.getTarget().getPLT().addr();
+}
+
+static
+X86Relocator::Address helper_PLT(Relocation& pReloc, X86_64Relocator& pParent)
+{
+  PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
+  return helper_PLT_ORG(pParent) + plt_entry.getOffset();
+}
+
+//
+// R_X86_64_NONE
+X86Relocator::Result none(Relocation& pReloc, X86_64Relocator& pParent)
+{
+  return X86Relocator::OK;
+}
+
+// R_X86_64_64: S + A
+// R_X86_64_32:
+// R_X86_64_16:
+// R_X86_64_8
+X86Relocator::Result abs(Relocation& pReloc, X86_64Relocator& pParent)
+{
+  ResolveInfo* rsym = pReloc.symInfo();
+  Relocator::DWord A = pReloc.addend();
+  Relocator::DWord S = pReloc.symValue();
+  bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
+                              *rsym,
+                              (rsym->reserved() & X86GNULDBackend::ReservePLT),
+                              true);
+
+  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
+  // If the flag of target section is not ALLOC, we will not scan this relocation
+  // but perform static relocation. (e.g., applying .debug section)
+  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
+    pReloc.target() = S + A;
+    return X86Relocator::OK;
+  }
+
+  Relocation::Type pointerRel = pParent.getTarget().getPointerRel();
+
+  // A local symbol may need REL Type dynamic relocation
+  if (rsym->isLocal() && has_dyn_rel) {
+    if (pointerRel == pReloc.type()) {
+      Relocation& rel_entry = helper_DynRel(rsym, *pReloc.targetRef().frag(),
+					    pReloc.targetRef().offset(),
+					    llvm::ELF::R_X86_64_RELATIVE,
+					    pParent);
+      rel_entry.setAddend(S + A);
+    }
+    else {
+      // FIXME: check Section symbol
+      Relocation& rel_entry = helper_DynRel(rsym, *pReloc.targetRef().frag(),
+					    pReloc.targetRef().offset(),
+					    pReloc.type(), pParent);
+      rel_entry.setAddend(S + A);
+    }
+    return X86Relocator::OK;
+  }
+
+  // An external symbol may need PLT and dynamic relocation
+  if (!rsym->isLocal()) {
+    // If we generate a dynamic relocation for a place with explicit
+    // addend, there is no need to perform static relocation on it.
+    if (has_dyn_rel) {
+      Relocation& rel_entry = helper_DynRel(rsym, *pReloc.targetRef().frag(),
+					    pReloc.targetRef().offset(),
+					    llvm::ELF::R_X86_64_RELATIVE,
+					    pParent);
+      // Copy addend.
+      rel_entry.setAddend(A);
+      return X86Relocator::OK;
+    }
+    else if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
+      S = helper_PLT(pReloc, pParent);
+    }
+  }
+
+  // perform static relocation
+  pReloc.target() = S + A;
+  return X86Relocator::OK;
+}
+
+// R_X86_64_32S: S + A
+X86Relocator::Result signed32(Relocation& pReloc, X86_64Relocator& pParent)
+{
+  ResolveInfo* rsym = pReloc.symInfo();
+  Relocator::DWord A = pReloc.addend();
+  Relocator::DWord S = pReloc.symValue();
+  bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
+                              *rsym,
+                              (rsym->reserved() & X86GNULDBackend::ReservePLT),
+                              true);
+
+  // There should be no dynamic relocations for R_X86_64_32S.
+  if (has_dyn_rel)
+    return X86Relocator::BadReloc;
+ 
+  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
+  // If the flag of target section is not ALLOC, we will not scan this relocation
+  // but perform static relocation. (e.g., applying .debug section)
+  // An external symbol may need PLT and dynamic relocation
+  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag()) &&
+      !rsym->isLocal() && rsym->reserved() & X86GNULDBackend::ReservePLT)
+    S = helper_PLT(pReloc, pParent);
+
+  // Check 32-bit signed overflow.
+  Relocator::SWord V = S + A;
+  if (V > INT64_C(0x7fffffff) || V < INT64_C(-0x80000000))
+    return X86Relocator::Overflow;
+
+  // perform static relocation
+  pReloc.target() = S + A;
+  return X86Relocator::OK;
+}
+
+// R_X86_64_GOTPCREL: GOT(S) + GOT_ORG + A - P
+X86Relocator::Result gotpcrel(Relocation& pReloc, X86_64Relocator& pParent)
+{
+  if (!(pReloc.symInfo()->reserved()
+       & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) {
+    return X86Relocator::BadReloc;
+  }
+  X86Relocator::Address GOT_S   = helper_GOT(pReloc, pParent);
+  Relocator::DWord      A       = pReloc.addend();
+  X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
+  // Apply relocation.
+  pReloc.target() = GOT_S + GOT_ORG + A - pReloc.place();
+  return X86Relocator::OK;
+}
+
+// R_X86_64_PLT32: PLT(S) + A - P
+X86Relocator::Result plt32(Relocation& pReloc, X86_64Relocator& pParent)
+{
+  // PLT_S depends on if there is a PLT entry.
+  X86Relocator::Address PLT_S;
+  if ((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT))
+    PLT_S = helper_PLT(pReloc, pParent);
+  else
+    PLT_S = pReloc.symValue();
+  Relocator::DWord      A = pReloc.addend();
+  X86Relocator::Address P = pReloc.place();
+  pReloc.target() = PLT_S + A - P;
+  return X86Relocator::OK;
+}
+
+// R_X86_64_PC32: S + A - P
+// R_X86_64_PC16
+// R_X86_64_PC8
+X86Relocator::Result rel(Relocation& pReloc, X86_64Relocator& pParent)
+{
+  ResolveInfo* rsym = pReloc.symInfo();
+  Relocator::DWord A = pReloc.addend();
+  Relocator::DWord S = pReloc.symValue();
+  Relocator::DWord P = pReloc.place();
+
+  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
+  // If the flag of target section is not ALLOC, we will not scan this relocation
+  // but perform static relocation. (e.g., applying .debug section)
+  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
+    pReloc.target() = S + A - P;
+    return X86Relocator::OK;
+  }
+
+  // An external symbol may need PLT and dynamic relocation
+  if (!rsym->isLocal()) {
+    if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
+       S = helper_PLT(pReloc, pParent);
+       pReloc.target() = S + A - P;
+    }
+    if (pParent.getTarget().symbolNeedsDynRel(
+                              *rsym,
+                              (rsym->reserved() & X86GNULDBackend::ReservePLT),
+                              false)) {
+          return X86Relocator::Overflow;
+    }
+  }
+
+   // perform static relocation
+  pReloc.target() = S + A - P;
+  return X86Relocator::OK;
+}
+
+X86Relocator::Result unsupport(Relocation& pReloc, X86_64Relocator& pParent)
+{
+  return X86Relocator::Unsupport;
+}
diff --git a/lib/Target/X86/X86Relocator.h b/lib/Target/X86/X86Relocator.h
index 7d3c289..922f1f2 100644
--- a/lib/Target/X86/X86Relocator.h
+++ b/lib/Target/X86/X86Relocator.h
@@ -30,25 +30,50 @@
 {
 public:
   typedef SymbolEntryMap<PLTEntryBase> SymPLTMap;
-  typedef SymbolEntryMap<X86GOTEntry> SymGOTMap;
-  typedef SymbolEntryMap<X86GOTPLTEntry> SymGOTPLTMap;
 
 public:
-  X86Relocator(X86GNULDBackend& pParent);
+  X86Relocator();
   ~X86Relocator();
 
+  virtual Result applyRelocation(Relocation& pRelocation) = 0;
+
+  virtual const char* getName(Relocation::Type pType) const = 0;
+
+  const SymPLTMap& getSymPLTMap() const { return m_SymPLTMap; }
+  SymPLTMap&       getSymPLTMap()       { return m_SymPLTMap; }
+
+private:
+  SymPLTMap m_SymPLTMap;
+};
+
+/** \class X86_32Relocator
+ *  \brief X86_32Relocator creates and destroys the X86-32 relocations.
+ *
+ */
+class X86_32Relocator : public X86Relocator
+{
+public:
+  typedef SymbolEntryMap<X86_32GOTEntry> SymGOTMap;
+  typedef SymbolEntryMap<X86_32GOTEntry> SymGOTPLTMap;
+
+  enum {
+    R_386_TLS_OPT = 44 // mcld internal relocation type
+  };
+
+public:
+  X86_32Relocator(X86_32GNULDBackend& pParent);
+
   Result applyRelocation(Relocation& pRelocation);
 
-  X86GNULDBackend& getTarget()
+  X86_32GNULDBackend& getTarget()
   { return m_Target; }
 
-  const X86GNULDBackend& getTarget() const
+  const X86_32GNULDBackend& getTarget() const
   { return m_Target; }
 
   const char* getName(Relocation::Type pType) const;
 
-  const SymPLTMap& getSymPLTMap() const { return m_SymPLTMap; }
-  SymPLTMap&       getSymPLTMap()       { return m_SymPLTMap; }
+  Size getSize(Relocation::Type pType) const;
 
   const SymGOTMap& getSymGOTMap() const { return m_SymGOTMap; }
   SymGOTMap&       getSymGOTMap()       { return m_SymGOTMap; }
@@ -57,8 +82,44 @@
   SymGOTPLTMap&       getSymGOTPLTMap()       { return m_SymGOTPLTMap; }
 
 private:
-  X86GNULDBackend& m_Target;
-  SymPLTMap m_SymPLTMap;
+  X86_32GNULDBackend& m_Target;
+  SymGOTMap m_SymGOTMap;
+  SymGOTPLTMap m_SymGOTPLTMap;
+};
+
+/** \class X86_64Relocator
+ *  \brief X86_64Relocator creates and destroys the X86-64 relocations.
+ *
+ */
+class X86_64Relocator : public X86Relocator
+{
+public:
+  typedef SymbolEntryMap<X86_64GOTEntry> SymGOTMap;
+  typedef SymbolEntryMap<X86_64GOTEntry> SymGOTPLTMap;
+
+public:
+  X86_64Relocator(X86_64GNULDBackend& pParent);
+
+  Result applyRelocation(Relocation& pRelocation);
+
+  X86_64GNULDBackend& getTarget()
+  { return m_Target; }
+
+  const X86_64GNULDBackend& getTarget() const
+  { return m_Target; }
+
+  const char* getName(Relocation::Type pType) const;
+
+  Size getSize(Relocation::Type pType) const;
+
+  const SymGOTMap& getSymGOTMap() const { return m_SymGOTMap; }
+  SymGOTMap&       getSymGOTMap()       { return m_SymGOTMap; }
+
+  const SymGOTPLTMap& getSymGOTPLTMap() const { return m_SymGOTPLTMap; }
+  SymGOTPLTMap&       getSymGOTPLTMap()       { return m_SymGOTPLTMap; }
+
+private:
+  X86_64GNULDBackend& m_Target;
   SymGOTMap m_SymGOTMap;
   SymGOTPLTMap m_SymGOTPLTMap;
 };
diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp
index 9b5a24e..b419fd1 100644
--- a/lib/Target/X86/X86TargetMachine.cpp
+++ b/lib/Target/X86/X86TargetMachine.cpp
@@ -14,7 +14,8 @@
 
 extern "C" void MCLDInitializeX86LDTarget() {
   // Register createTargetMachine function pointer to mcld::Target
-  mcld::RegisterTargetMachine<mcld::X86TargetMachine> X(mcld::TheX86Target);
+  mcld::RegisterTargetMachine<mcld::X86TargetMachine> X(mcld::TheX86_32Target);
+  mcld::RegisterTargetMachine<mcld::X86TargetMachine> Y(mcld::TheX86_64Target);
 }
 
 mcld::X86TargetMachine::X86TargetMachine(llvm::TargetMachine& pPM,
diff --git a/tools/llvm-mcld/llvm-mcld.cpp b/tools/llvm-mcld/llvm-mcld.cpp
index fc0b99f..8daf65f 100644
--- a/tools/llvm-mcld/llvm-mcld.cpp
+++ b/tools/llvm-mcld/llvm-mcld.cpp
@@ -461,6 +461,66 @@
       "surround result strings only if the output is a tty"),
     clEnumValEnd));
 
+static cl::opt<bool>
+ArgDiscardLocals("discard-locals",
+                 cl::desc("Delete all temporary local symbols."),
+                 cl::init(false));
+
+static cl::alias
+ArgDiscardLocalsAlias("X",
+                      cl::desc("alias for --discard-locals"),
+                      cl::aliasopt(ArgDiscardLocals));
+
+static cl::opt<bool>
+ArgDiscardAll("discard-all",
+              cl::desc("Delete all local symbols."),
+              cl::init(false));
+
+static cl::alias
+ArgDiscardAllAlias("x",
+                   cl::desc("alias for --discard-all"),
+                   cl::aliasopt(ArgDiscardAll));
+
+static cl::opt<bool>
+ArgStripDebug("strip-debug",
+              cl::desc("Omit debugger symbol information from the output file."),
+              cl::init(false));
+
+static cl::alias
+ArgStripDebugAlias("S",
+                   cl::desc("alias for --strip-debug"),
+                   cl::aliasopt(ArgStripDebug));
+
+static cl::opt<bool>
+ArgStripAll("strip-all",
+            cl::desc("Omit all symbol information from the output file."),
+            cl::init(false));
+
+static cl::alias
+ArgStripAllAlias("s",
+                 cl::desc("alias for --strip-all"),
+                 cl::aliasopt(ArgStripAll));
+
+static cl::opt<bool>
+ArgNMagic("nmagic",
+          cl::desc("Do not page align data"),
+          cl::init(false));
+
+static cl::alias
+ArgNMagicAlias("n",
+               cl::desc("alias for --nmagic"),
+               cl::aliasopt(ArgNMagic));
+
+static cl::opt<bool>
+ArgOMagic("omagic",
+          cl::desc("Do not page align data, do not make text readonly"),
+          cl::init(false));
+
+static cl::alias
+ArgOMagicAlias("N",
+               cl::desc("alias for --omagic"),
+               cl::aliasopt(ArgOMagic));
+
 /// @{
 /// @name FIXME: begin of unsupported options
 /// @}
@@ -484,6 +544,7 @@
 
 static cl::opt<icf::Mode>
 ArgICF("icf",
+       cl::ZeroOrMore,
        cl::desc("Identical Code Folding"),
        cl::init(icf::None),
        cl::values(
@@ -502,56 +563,6 @@
           cl::init(false));
 
 static cl::opt<bool>
-ArgDiscardLocals("discard-locals",
-                 cl::desc("Delete all temporary local symbols."),
-                 cl::init(false));
-
-static cl::alias
-ArgDiscardLocalsAlias("X",
-                      cl::desc("alias for --discard-locals"),
-                      cl::aliasopt(ArgDiscardLocals));
-
-static cl::opt<bool>
-ArgDiscardAll("discard-all",
-              cl::desc("Delete all local symbols."),
-              cl::init(false));
-
-static cl::alias
-ArgDiscardAllAlias("x",
-                   cl::desc("alias for --discard-all"),
-                   cl::aliasopt(ArgDiscardAll));
-
-static cl::opt<bool>
-ArgNMagic("nmagic",
-          cl::desc("Do not page align data"),
-          cl::init(false));
-
-static cl::alias
-ArgNMagicAlias("n",
-               cl::desc("alias for --nmagic"),
-               cl::aliasopt(ArgNMagic));
-
-static cl::opt<bool>
-ArgOMagic("omagic",
-          cl::desc("Do not page align data, do not make text readonly"),
-          cl::init(false));
-
-static cl::alias
-ArgOMagicAlias("N",
-               cl::desc("alias for --omagic"),
-               cl::aliasopt(ArgOMagic));
-
-static cl::opt<bool>
-ArgStripDebug("strip-debug",
-              cl::desc("Omit debugger symbol information from the output file."),
-              cl::init(false));
-
-static cl::alias
-ArgStripDebugAlias("S",
-                   cl::desc("alias for --strip-debug"),
-                   cl::aliasopt(ArgStripDebug));
-
-static cl::opt<bool>
 ArgExportDynamic("export-dynamic",
                  cl::desc("Export all dynamic symbols"),
                  cl::init(false));
@@ -566,13 +577,9 @@
              cl::desc("Set GNU linker emulation"),
              cl::value_desc("emulation"));
 
-static cl::opt<std::string>
-ArgRuntimePath("rpath",
-               cl::desc("Add a directory to the runtime library search path"),
-               cl::value_desc("dir"));
-
-static cl::opt<std::string>
+static cl::list<std::string, bool, llvm::cl::SearchDirParser>
 ArgRuntimePathLink("rpath-link",
+                   cl::ZeroOrMore,
                    cl::desc("Add a directory to the link time library search path"),
                    cl::value_desc("dir"));
 
@@ -603,25 +610,108 @@
                  cl::value_desc("Version script"));
 
 static cl::opt<bool>
-ArgNoStdLib("nostdlib",
-            cl::desc("Only search lib dirs explicitly specified on cmdline"),
-            cl::init(false));
-
-static cl::opt<bool>
 ArgWarnCommon("warn-common",
               cl::desc("warn common symbol"),
               cl::init(false));
 
+static cl::opt<mcld::GeneralOptions::HashStyle>
+ArgHashStyle("hash-style", cl::init(mcld::GeneralOptions::SystemV),
+  cl::desc("Set the type of linker's hash table(s)."),
+  cl::values(
+       clEnumValN(mcld::GeneralOptions::SystemV, "sysv",
+                 "classic ELF .hash section"),
+       clEnumValN(mcld::GeneralOptions::GNU, "gnu",
+                 "new style GNU .gnu.hash section"),
+       clEnumValN(mcld::GeneralOptions::Both, "both",
+                 "both the classic ELF and new style GNU hash tables"),
+       clEnumValEnd));
+
+static cl::opt<std::string>
+ArgFilter("F",
+          cl::desc("Filter for shared object symbol table"),
+          cl::value_desc("name"));
+
+static cl::alias
+ArgFilterAlias("filter",
+               cl::desc("alias for -F"),
+               cl::aliasopt(ArgFilterAlias));
+
+static cl::list<std::string>
+ArgAuxiliary("f",
+             cl::ZeroOrMore,
+             cl::desc("Auxiliary filter for shared object symbol table"),
+             cl::value_desc("name"));
+
+static cl::alias
+ArgAuxiliaryAlias("auxiliary",
+                  cl::desc("alias for -f"),
+                  cl::aliasopt(ArgAuxiliary));
+
 static cl::opt<bool>
-ArgFatalWarnings("fatal-warnings",
-              cl::desc("turn all warnings into errors"),
-              cl::init(false));
+ArgEB("EB",
+      cl::desc("Link big-endian objects. This affects the default output format."),
+      cl::init(false));
+
+static cl::opt<bool>
+ArgEL("EL",
+      cl::desc("Link little-endian objects. This affects the default output format."),
+      cl::init(false));
 
 /// @{
 /// @name FIXME: end of unsupported options
 /// @}
 
 static cl::opt<bool>
+ArgNoStdlib("nostdlib",
+            cl::desc("Only search lib dirs explicitly specified on cmdline"),
+            cl::init(false));
+
+static cl::list<std::string, bool, llvm::cl::SearchDirParser>
+ArgRuntimePath("rpath",
+               cl::ZeroOrMore,
+               cl::desc("Add a directory to the runtime library search path"),
+               cl::value_desc("dir"));
+
+static cl::alias
+ArgRuntimePathAlias("R",
+                    cl::desc("alias for --rpath"),
+                    cl::aliasopt(ArgRuntimePath), cl::Prefix);
+
+static cl::opt<bool>
+ArgEnableNewDTags("enable-new-dtags",
+                  cl::desc("Enable use of DT_RUNPATH and DT_FLAGS"),
+                  cl::init(false));
+
+class FalseParser : public cl::parser<bool> {
+  const char *ArgStr;
+public:
+
+  // parse - Return true on error.
+  bool parse(cl::Option &O, StringRef ArgName, StringRef Arg, bool &Val) {
+    if (cl::parser<bool>::parse(O, ArgName, Arg, Val))
+      return false;
+    Val = false;
+    return false;
+  }
+};
+
+static bool ArgFatalWarnings;
+
+static cl::opt<bool, true, FalseParser>
+ArgNoFatalWarnings("no-fatal-warnings",
+              cl::location(ArgFatalWarnings),
+              cl::desc("do not turn warnings into errors"),
+              cl::init(false),
+              cl::ValueDisallowed);
+
+static cl::opt<bool, true>
+ArgFatalWarnings_("fatal-warnings",
+              cl::location(ArgFatalWarnings),
+              cl::desc("turn all warnings into errors"),
+              cl::init(false),
+              cl::ValueDisallowed);
+
+static cl::opt<bool>
 ArgWarnSharedTextrel("warn-shared-textrel",
                      cl::desc("Warn if adding DT_TEXTREL in a shared object."),
                      cl::init(false));
@@ -895,8 +985,15 @@
   // set up soname
   pConfig.options().setSOName(ArgSOName);
 
+  // add all rpath entries
+  cl::list<std::string>::iterator rp;
+  cl::list<std::string>::iterator rpEnd = ArgRuntimePath.end();
+  for (rp = ArgRuntimePath.begin(); rp != rpEnd; ++rp) {
+    pConfig.options().getRpathList().push_back(*rp);
+  }
+
   // --fatal-warnings
-  pConfig.options().setFatalWarnings(ArgFatalWarnings);
+  // pConfig.options().setFatalWarnings(ArgFatalWarnings);
 
   // -shared or -pie
   if (true == ArgShared || true == ArgPIE) {
@@ -952,10 +1049,22 @@
   pConfig.options().setEhFrameHdr(ArgEhFrameHdr);
   pConfig.options().setNMagic(ArgNMagic);
   pConfig.options().setOMagic(ArgOMagic);
-  pConfig.options().setStripDebug(ArgStripDebug);
+  pConfig.options().setStripDebug(ArgStripDebug || ArgStripAll);
   pConfig.options().setExportDynamic(ArgExportDynamic);
   pConfig.options().setWarnSharedTextrel(ArgWarnSharedTextrel);
   pConfig.options().setDefineCommon(ArgDefineCommon);
+  pConfig.options().setNewDTags(ArgEnableNewDTags);
+  pConfig.options().setHashStyle(ArgHashStyle);
+  pConfig.options().setNoStdlib(ArgNoStdlib);
+
+  if (ArgStripAll)
+    pConfig.options().setStripSymbols(mcld::GeneralOptions::StripAllSymbols);
+  else if (ArgDiscardAll)
+    pConfig.options().setStripSymbols(mcld::GeneralOptions::StripLocals);
+  else if (ArgDiscardLocals)
+    pConfig.options().setStripSymbols(mcld::GeneralOptions::StripTemporaries);
+  else
+    pConfig.options().setStripSymbols(mcld::GeneralOptions::KeepAllSymbols);
 
   // set up rename map, for --wrap
   cl::list<std::string>::iterator wname;
@@ -1034,14 +1143,6 @@
     mcld::warning(mcld::diag::warn_unsupported_option) << ArgFIXCA8.ArgStr;
   }
 
-  if (ArgDiscardLocals) {
-    mcld::warning(mcld::diag::warn_unsupported_option) << ArgDiscardLocals.ArgStr;
-  }
-
-  if (ArgDiscardAll) {
-    mcld::warning(mcld::diag::warn_unsupported_option) << ArgDiscardAll.ArgStr;
-  }
-
   // add address mappings
   // -Ttext
   if (-1U != ArgTextSegAddr) {
@@ -1079,6 +1180,14 @@
     addr_mapping->setValue(address);
   }
 
+  // set up filter/aux filter for shared object
+  pConfig.options().setFilter(ArgFilter);
+
+  cl::list<std::string>::iterator aux;
+  cl::list<std::string>::iterator auxEnd = ArgAuxiliary.end();
+  for (aux = ArgAuxiliary.begin(); aux != auxEnd; ++aux)
+    pConfig.options().getAuxiliaryList().push_back(*aux);
+
   return true;
 }
 
diff --git a/tools/mcld/main.cpp b/tools/mcld/main.cpp
index 58a9bb0..968c5e6 100644
--- a/tools/mcld/main.cpp
+++ b/tools/mcld/main.cpp
@@ -31,7 +31,7 @@
 // Compiler Options
 //===----------------------------------------------------------------------===//
 #ifdef TARGET_BUILD
-static const std::string OptTargetTripe(DEFAULT_TARGET_TRIPLE_STRING);
+static const std::string OptTargetTriple(DEFAULT_TARGET_TRIPLE_STRING);
 #else
 static llvm::cl::opt<std::string>
 OptTargetTriple("mtriple",
@@ -253,10 +253,6 @@
     config->addSearchDir(*sdir);
   }
 
-  // set up default search directories
-  config->addSearchDir("=/lib");
-  config->addSearchDir("=/usr/lib");
-
   // 7. Set up output's type.
   config->setShared(OptShared);
 
diff --git a/unittests/ELFReaderTest.cpp b/unittests/ELFReaderTest.cpp
new file mode 100644
index 0000000..fe7dd39
--- /dev/null
+++ b/unittests/ELFReaderTest.cpp
@@ -0,0 +1,162 @@
+//===- ELFReaderTest.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <cstdio>
+
+#include <llvm/Support/ELF.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/TargetOptions.h>
+#include <mcld/LD/ELFReader.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/Support/Path.h>
+#include <../lib/Target/X86/X86LDBackend.h>
+#include <../lib/Target/X86/X86GNUInfo.h>
+
+#include "ELFReaderTest.h"
+
+using namespace mcld;
+using namespace mcld::sys::fs;
+using namespace mcldtest;
+
+// Constructor can do set-up work for all test here.
+ELFReaderTest::ELFReaderTest()
+ : m_pInput(NULL)
+{
+  m_pConfig = new LinkerConfig("x86_64-linux-gnueabi");
+  m_pConfig->targets().setEndian( TargetOptions::Little );
+  m_pConfig->targets().setBitClass( 64 );
+  Relocation::SetUp( *m_pConfig );
+
+  m_pInfo = new X86_64GNUInfo( m_pConfig->targets().triple() );
+  m_pLDBackend = new X86_64GNULDBackend( *m_pConfig, m_pInfo );
+  m_pELFReader = new ELFReader<64, true>( *m_pLDBackend );
+  m_pModule = new Module();
+  m_pIRBuilder = new IRBuilder( *m_pModule, *m_pConfig);
+  m_pELFObjReader = new ELFObjectReader(*m_pLDBackend,
+                                        *m_pIRBuilder,
+                                        *m_pConfig);
+}
+
+// Destructor can do clean-up work that doesn't throw exceptions here.
+ELFReaderTest::~ELFReaderTest()
+{
+  delete m_pConfig;
+  delete m_pLDBackend;
+  delete m_pELFReader;
+  delete m_pModule;
+  delete m_pIRBuilder;
+  delete m_pELFObjReader;
+}
+
+// SetUp() will be called immediately before each test.
+void ELFReaderTest::SetUp()
+{
+  Path path(TOPDIR);
+  path.append("unittests/test_x86_64.o");
+
+  m_pInput = m_pIRBuilder->ReadInput("test_x86_64", path);
+  ASSERT_TRUE(NULL!=m_pInput);
+
+  ASSERT_TRUE(m_pInput->hasMemArea());
+  size_t hdr_size = m_pELFReader->getELFHeaderSize();
+  MemoryRegion* region = m_pInput->memArea()->request(m_pInput->fileOffset(),
+                                                    hdr_size);
+  uint8_t* ELF_hdr = region->start();
+  bool shdr_result = m_pELFReader->readSectionHeaders(*m_pInput, ELF_hdr);
+  m_pInput->memArea()->release(region);
+  ASSERT_TRUE(shdr_result);
+}
+
+// TearDown() will be called immediately after each test.
+void ELFReaderTest::TearDown()
+{
+}
+
+//===----------------------------------------------------------------------===//
+// Testcases
+//===----------------------------------------------------------------------===//
+TEST_F( ELFReaderTest,  read_section_headers ) {
+  ASSERT_EQ(m_pInput->context()->numOfSections(), 13);
+  LDContext::const_sect_iterator iter = m_pInput->context()->sectBegin();
+  ++iter; /// test section[1]
+  ASSERT_EQ(".text", (*iter)->name());
+  ASSERT_EQ(llvm::ELF::SHT_PROGBITS, (*iter)->type());
+  ASSERT_EQ(0x40, (*iter)->offset());
+  ASSERT_EQ(0x15, (*iter)->size());
+  ASSERT_TRUE(llvm::ELF::SHF_ALLOC & (*iter)->flag()); //AX
+  ASSERT_EQ(0x4, (*iter)->align());
+  ASSERT_EQ(NULL, (*iter)->getLink());
+  ASSERT_EQ(0, (*iter)->getInfo());
+}
+
+TEST_F( ELFReaderTest, read_symbol_and_rela )
+{
+  ASSERT_TRUE(m_pInput->hasMemArea());
+  ASSERT_TRUE(m_pInput->hasContext());
+  m_pInput->setType(Input::Object);
+
+  // -- read symbols
+  LDSection* symtab_shdr = m_pInput->context()->getSection(".symtab");
+  ASSERT_TRUE(NULL!=symtab_shdr);
+
+  LDSection* strtab_shdr = symtab_shdr->getLink();
+  ASSERT_TRUE(NULL!=strtab_shdr);
+
+  MemoryRegion* symtab_region = m_pInput->memArea()->request(
+                         m_pInput->fileOffset() + symtab_shdr->offset(),
+                         symtab_shdr->size());
+
+  MemoryRegion* strtab_region = m_pInput->memArea()->request(
+                         m_pInput->fileOffset() + strtab_shdr->offset(),
+                         strtab_shdr->size());
+  char* strtab = reinterpret_cast<char*>(strtab_region->start());
+  bool result = m_pELFReader->readSymbols(*m_pInput, *m_pIRBuilder,
+                                          *symtab_region, strtab);
+  ASSERT_TRUE(result);
+  ASSERT_EQ("hello.c", std::string(m_pInput->context()->getSymbol(1)->name()));
+  ASSERT_EQ("puts", std::string(m_pInput->context()->getSymbol(10)->name()));
+  ASSERT_TRUE(NULL==m_pInput->context()->getSymbol(11));
+  m_pInput->memArea()->release(symtab_region);
+  m_pInput->memArea()->release(strtab_region);
+
+  // -- read relocations
+  MemoryArea* mem = m_pInput->memArea();
+  LDContext::sect_iterator rs = m_pInput->context()->relocSectBegin();
+  ASSERT_TRUE(rs!=m_pInput->context()->relocSectEnd());
+  ASSERT_EQ(".rela.text", (*rs)->name());
+
+  uint64_t offset = m_pInput->fileOffset() + (*rs)->offset();
+  uint64_t size = (*rs)->size();
+  MemoryRegion* region = mem->request(offset, size);
+  IRBuilder::CreateRelocData(**rs); /// create relocation data for the header
+
+  ASSERT_EQ(llvm::ELF::SHT_RELA, (*rs)->type());
+  ASSERT_TRUE(m_pELFReader->readRela(*m_pInput, **rs, *region));
+  mem->release(region);
+
+  const RelocData::RelocationListType &rRelocs =
+                          (*rs)->getRelocData()->getRelocationList();
+  RelocData::const_iterator rReloc = rRelocs.begin();
+  ASSERT_EQ(2, rRelocs.size());
+  ASSERT_TRUE(rRelocs.end()!=rReloc);
+  ++rReloc; /// test rRelocs[1]
+  ASSERT_EQ("puts", std::string(rReloc->symInfo()->name()));
+  ASSERT_EQ(llvm::ELF::R_X86_64_PC32, rReloc->type());
+  ASSERT_EQ(0x0, rReloc->symValue());
+  ASSERT_EQ(-0x4, rReloc->addend());
+}
+
+TEST_F( ELFReaderTest, read_regular_sections ) {
+  ASSERT_TRUE( m_pELFObjReader->readSections(*m_pInput) );
+}
+
+TEST_F( ELFReaderTest, is_my_format ) {
+  ASSERT_TRUE( m_pELFObjReader->isMyFormat(*m_pInput) );
+}
+
+
diff --git a/unittests/ELFReaderTest.h b/unittests/ELFReaderTest.h
new file mode 100644
index 0000000..c977cfb
--- /dev/null
+++ b/unittests/ELFReaderTest.h
@@ -0,0 +1,56 @@
+//===- ELFReaderTest.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ELFREADER_TEST_H
+#define MCLD_ELFREADER_TEST_H
+
+#include <gtest.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/LD/ELFReaderIf.h>
+#include <mcld/LD/ELFReader.h>
+#include <mcld/LD/ELFObjectReader.h>
+#include <mcld/Target/GNULDBackend.h>
+#include <mcld/MC/InputBuilder.h>
+
+namespace mcld {
+  class ELFReader<64, true>;
+} // namespace for mcld
+
+namespace mcldtest
+{
+
+class ELFReaderTest : public ::testing::Test
+{
+public:
+  // Constructor can do set-up work for all test here.
+  ELFReaderTest();
+
+  // Destructor can do clean-up work that doesn't throw exceptions here.
+  virtual ~ELFReaderTest();
+
+  // SetUp() will be called immediately before each test.
+  virtual void SetUp();
+
+  // TearDown() will be called immediately after each test.
+  virtual void TearDown();
+
+protected:
+  mcld::Input *m_pInput;
+  mcld::LinkerConfig *m_pConfig;
+  mcld::GNUInfo *m_pInfo;
+  mcld::GNULDBackend *m_pLDBackend;
+  mcld::ELFReaderIF *m_pELFReader;
+  mcld::Module *m_pModule;
+  mcld::IRBuilder *m_pIRBuilder;
+  mcld::ELFObjectReader *m_pELFObjReader;
+};
+
+} // namespace of mcldtest
+
+#endif
+
diff --git a/unittests/FileHandleTest.cpp b/unittests/FileHandleTest.cpp
index db6f25f..dc9ecdd 100644
--- a/unittests/FileHandleTest.cpp
+++ b/unittests/FileHandleTest.cpp
@@ -48,6 +48,7 @@
   ASSERT_TRUE(m_pTestee->open(path, FileHandle::ReadOnly));
   ASSERT_TRUE(m_pTestee->isOpened());
   ASSERT_TRUE(m_pTestee->isGood());
+  ASSERT_TRUE(m_pTestee->isOwned());
 
   ASSERT_TRUE(27 == m_pTestee->size());
 
@@ -67,19 +68,19 @@
   ASSERT_TRUE(m_pTestee->delegate(fd, FileHandle::ReadOnly));
   ASSERT_TRUE(m_pTestee->isOpened());
   ASSERT_TRUE(m_pTestee->isGood());
+  ASSERT_FALSE(m_pTestee->isOwned());
 
   ASSERT_TRUE(27 == m_pTestee->size());
 
   ASSERT_TRUE(m_pTestee->close());
   ASSERT_FALSE(m_pTestee->isOpened());
   ASSERT_TRUE(m_pTestee->isGood());
+  ASSERT_TRUE(m_pTestee->isOwned());
 
   ASSERT_TRUE(0 == m_pTestee->size());
 
   int close_result = ::close(fd);
-  int close_err = errno;
-  ASSERT_EQ(-1, close_result);
-  ASSERT_EQ(EBADF, close_err);
+  ASSERT_EQ(0, close_result);
 }
 
 TEST_F(FileHandleTest, fail_close) {
diff --git a/unittests/LinkerTest.cpp b/unittests/LinkerTest.cpp
index 00ba23b..ab439cb 100644
--- a/unittests/LinkerTest.cpp
+++ b/unittests/LinkerTest.cpp
@@ -84,6 +84,11 @@
   ///< --mtriple="armv7-none-linux-gnueabi"
   LinkerConfig config("armv7-none-linux-gnueabi");
 
+  /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
+  Path search_dir(TOPDIR);
+  search_dir.append("test/libs/ARM/Android/android-14");
+  config.options().directories().insert(search_dir);
+
   /// To configure linker before setting options. Linker::config sets up
   /// default target-dependent configuration to LinkerConfig.
   linker.config(config);
@@ -92,11 +97,6 @@
   config.options().setSOName("libplasma.so");   ///< --soname=libplasma.so
   config.options().setBsymbolic();              ///< -Bsymbolic
 
-  /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
-  Path search_dir(TOPDIR);
-  search_dir.append("test/libs/ARM/Android/android-14");
-  config.options().directories().insert(search_dir);
-
   Module module("libplasma.so");
   IRBuilder builder(module, config);
 
@@ -141,6 +141,11 @@
   ///< --mtriple="armv7-none-linux-gnueabi"
   LinkerConfig config1("armv7-none-linux-gnueabi");
 
+  /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
+  Path search_dir(TOPDIR);
+  search_dir.append("test/libs/ARM/Android/android-14");
+  config1.options().directories().insert(search_dir);
+
   /// To configure linker before setting options. Linker::config sets up
   /// default target-dependent configuration to LinkerConfig.
   linker.config(config1);
@@ -149,11 +154,6 @@
   config1.options().setSOName("libplasma.once.so");   ///< --soname=libplasma.twice.so
   config1.options().setBsymbolic(false);              ///< -Bsymbolic
 
-  /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
-  Path search_dir(TOPDIR);
-  search_dir.append("test/libs/ARM/Android/android-14");
-  config1.options().directories().insert(search_dir);
-
   Module module1("libplasma.once.so");
   IRBuilder builder1(module1, config1);
 
@@ -191,6 +191,9 @@
   ///< --mtriple="armv7-none-linux-gnueabi"
   LinkerConfig config2("armv7-none-linux-gnueabi");
 
+  /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
+  config2.options().directories().insert(search_dir);
+
   /// To configure linker before setting options. Linker::config sets up
   /// default target-dependent configuration to LinkerConfig.
   linker.config(config2);
@@ -199,9 +202,6 @@
   config2.options().setSOName("libplasma.twice.so");   ///< --soname=libplasma.twice.exe
   config2.options().setBsymbolic();              ///< -Bsymbolic
 
-  /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
-  config2.options().directories().insert(search_dir);
-
   Module module2("libplasma.so");
   IRBuilder builder2(module2, config2);
 
@@ -236,6 +236,11 @@
   ///< --mtriple="armv7-none-linux-gnueabi"
   LinkerConfig config1("armv7-none-linux-gnueabi");
 
+  /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
+  Path search_dir(TOPDIR);
+  search_dir.append("test/libs/ARM/Android/android-14");
+  config1.options().directories().insert(search_dir);
+
   /// To configure linker before setting options. Linker::config sets up
   /// default target-dependent configuration to LinkerConfig.
   linker.config(config1);
@@ -244,11 +249,6 @@
   config1.options().setSOName("libplasma.once.so");   ///< --soname=libplasma.twice.so
   config1.options().setBsymbolic(false);              ///< -Bsymbolic
 
-  /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
-  Path search_dir(TOPDIR);
-  search_dir.append("test/libs/ARM/Android/android-14");
-  config1.options().directories().insert(search_dir);
-
   Module module1("libplasma.once.so");
   IRBuilder *builder1 = new IRBuilder(module1, config1);
 
@@ -291,6 +291,9 @@
   ///< --mtriple="armv7-none-linux-gnueabi"
   LinkerConfig config2("armv7-none-linux-gnueabi");
 
+  /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
+  config2.options().directories().insert(search_dir);
+
   /// To configure linker before setting options. Linker::config sets up
   /// default target-dependent configuration to LinkerConfig.
   linker.config(config2);
@@ -299,9 +302,6 @@
   config2.options().setSOName("libplasma.twice.so");   ///< --soname=libplasma.twice.exe
   config2.options().setBsymbolic();              ///< -Bsymbolic
 
-  /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
-  config2.options().directories().insert(search_dir);
-
   Module module2("libplasma.so");
   IRBuilder* builder2 = new IRBuilder(module2, config2);
 
diff --git a/unittests/SymbolCategoryTest.cpp b/unittests/SymbolCategoryTest.cpp
index 07f479b..fae146b 100644
--- a/unittests/SymbolCategoryTest.cpp
+++ b/unittests/SymbolCategoryTest.cpp
@@ -80,13 +80,13 @@
   ++sym;
   ASSERT_STREQ("e", (*sym)->name());
 
-  ASSERT_TRUE(2 == m_pTestee->numOfLocals());
+  ASSERT_TRUE(1 == m_pTestee->numOfLocals());
   ASSERT_TRUE(1 == m_pTestee->numOfCommons());
-  ASSERT_TRUE(2 == m_pTestee->numOfRegulars());
+  ASSERT_TRUE(2 == m_pTestee->numOfDynamics());
   ASSERT_TRUE(5 == m_pTestee->numOfSymbols());
 }
 
-TEST_F(SymbolCategoryTest, change_local_to_tls) {
+TEST_F(SymbolCategoryTest, change_local_to_dynamic) {
   ResolveInfo* a = ResolveInfo::Create("a");
   ResolveInfo* b = ResolveInfo::Create("b");
   ResolveInfo* c = ResolveInfo::Create("c");
@@ -129,7 +129,7 @@
   ++sym;
   ASSERT_STREQ("e", (*sym)->name());
 
-  m_pTestee->changeLocalToTLS(*bb);
+  m_pTestee->changeLocalToDynamic(*bb);
 
   sym = m_pTestee->begin();
   ASSERT_STREQ("c", (*sym)->name());
diff --git a/unittests/test b/unittests/test
new file mode 100644
index 0000000..d2a5b5d
--- /dev/null
+++ b/unittests/test
@@ -0,0 +1,8 @@
+0x41, 0x1f, 0x00, 0x00,
+0x00, 0x61, 0x65, 0x61,
+0x62, 0x69, 0x00, 0x01,
+0x15, 0x00, 0x00, 0x00,
+0x06, 0x02, 0x08, 0x01,
+0x09, 0x01, 0x14, 0x01,
+0x15, 0x01, 0x17, 0x03,
+0x18, 0x01, 0x19, 0x01,
diff --git a/unittests/test_x86_64.o b/unittests/test_x86_64.o
new file mode 100644
index 0000000..18389aa
--- /dev/null
+++ b/unittests/test_x86_64.o
Binary files differ